2 #include <stdlib.h> //exit, malloc
3 #include <stdio.h> //print
4 #include <stdarg.h> //va_args
5 #include <string.h> //memset, str*
8 #include <unistd.h> //u8_* functions
9 #include <unitypes.h> //uint8_t as a char
10 #include <unistr.h> //u32_cpy
11 #include <unistdio.h> //ulc_fprintf
18 #define do_error(...) exit(-1)
19 #define XXH_PRIVATE_API
20 #include "../xxHash/xxhash.h"
21 #define STB_IMAGE_IMPLEMENTATION
22 #include "../stb/stb_image.h"
23 #define STB_IMAGE_WRITE_IMPLEMENTATION
24 #include "../stb/stb_image_write.h"
27 void ir_binout_init(struct ir_class_t
*);
29 /* Memory Allocation */
30 #define struct_alloc(_T) ((struct _T*) stack_alloc(&datapages, sizeof(struct _T)))
32 struct pagelist_t linkpages
, datapages
, plinkpages
;
34 enum model_type
{ SS
};
35 /* Binaryout out structure definitions */
36 struct bin_img_info_t
{
39 int fwidth
; //map and frame width
40 int fheight
; //map and frame height
44 struct bin_ht_header_t
{
49 struct bin_default_ht_entry_t
{
53 struct bin_var_ht_entry_t
{
58 struct bin_class_header_t
{
59 struct bin_ht_header_t child_ht
;
60 struct bin_ht_header_t rootset_ht
;
63 struct bin_set_header_t
{
64 struct bin_ht_header_t child_ht
;
65 long sdat_start
; //points to setdata_header
68 struct bin_setdata_header_t
{
69 struct bin_ht_header_t variant_ht
;
72 struct bin_model_header_t
{ //one for each framebox, currently
73 long facing_array_start
;
76 struct bin_frame_header_t
{
84 int x
, y
, z
, num
; //the x matching pixel
88 struct bin_pixel_node_t
{
89 struct bin_pixel_node_t
* next
;
90 struct bin_pixel_t data
;
92 struct bin_attachment_header_t
{
93 int num_attachment_lists
;
96 struct bin_attachment_t
{
100 /* Read out of the als, after first ir pass, resolves the
101 attach_pos of the src-set that created the attachment_list
102 to the header that describes the attachment_list */
103 struct bin_attachment_list_t
{
105 struct bin_attachment_t
** attachments
;
108 struct bin_linklist_t
;
109 struct bin_linklist_t
110 { struct bin_linklist_t
* next
;
114 struct bin_processed_links_t
115 { struct bin_linklist_t
* vlink_list
;
117 struct bin_linklist_t
* mlink_list
;
119 struct bin_linklist_t
* olink_list
; //keep track of olink cycles
121 struct bin_linklist_t
* dlink_list
;
125 struct bin_attachment_list_t
**attachment_stack
, **asp
; //attachment_stack, attachment_stack_pointer
129 #define NAMEHASH(name, domain) (XXH32(name, u8_strlen(name), 0XCEED ) & domain)
137 for (iter
= ir_set_framebox(set
); iter
!= NULL
; iter
= ir_setdata_nextsib(iter
))
143 int bin_class_sibcount
148 for (iter
= class; iter
!= NULL
; iter
= ir_class_nextsib(iter
))
159 for (iter
= set
; iter
!= NULL
; iter
= ir_set_nextsib(iter
))
164 /* Given a position and a size, checks if the bytes are null and returns
165 the file position to where it started. 1 if not null, 0 if null*/
166 /* TODO: Determine why fseeking file past end sets bytes to -1, and not 0 */
168 int bytes_null( int len
, int pos
)
170 { if(fgetc(binaryout
) > 0)
171 { fseek(binaryout
, pos
, SEEK_SET
);
175 fseek(binaryout
, pos
, SEEK_SET
);
178 /* Checks if the key at entrypos is the same as the parameter key. Returns
179 1 if so, 0 if not. */
181 int bin_keys_identical
186 fseek(binaryout
, entry_pos
, SEEK_SET
);
187 fscanf(binaryout
, "%u", &curr_key
);
194 typedef uint32_t RGBA_t
;
196 long bin_traverse_class(ir_class
);
197 /* Takes root class and begins processing */
199 ir_binout_init(ir_class root_class
)
200 { binaryout
= fopen("binaryout", "w+");
201 asp
= attachment_stack
;
202 pagelist_init(datapages
, (size_t) SYS_PAGESIZE
);
203 pagelist_init(linkpages
, (size_t) SYS_PAGESIZE
);
204 pagelist_init(plinkpages
, (size_t) SYS_PAGESIZE
);
205 bin_traverse_class(root_class
);
209 /* Returns the key position where the hash table entry was inserted. */
210 #define ENTRY_OCCUPIED() (bytes_null(uint32_t), entry_pos))
211 #define LOOP_ENTRY(_HTSTART) (entry_pos = _HTSTART)
212 #define WRITE_DEF_ENTRY() do { \
213 if(fseek(binaryout, entry_pos, SEEK_SET) == -1) wprintf("fseek failed with %s", strerror(errno)); \
214 fwrite(&def_ht_entry, sizeof def_ht_entry, 1, binaryout); \
216 #define INC_DEF_ENTRY() do { \
217 entry_pos += sizeof(def_ht_entry); \
218 if(fseek(binaryout, entry_pos, SEEK_SET) == -1) eprintf("fseek failed with %s", strerror(errno)); \
220 #define HT_END(_HTEND) (entry_pos >= _HTEND) //just in case at last entry
222 bin_insert_default_ht_entry
225 struct bin_def_ht_entry_t
* def_ht_entry
,
228 { long entry_pos
, ht_end
;
230 ht_end
= ht_start
+ ht_size
;
231 entry_pos
= ht_start
+ sizeof(ht_entry
) * ht_entry
->key
;
232 fseek(binaryout
, entry_pos
, SEEK_SET
);
234 if (!ENTRY_OCCUPIED())
235 { uprintf("key not occupied\n");
238 while( ENTRY_OCCUPIED() )
240 { if(bin_keys_identical(entry_pos
, ht_entry
->key
))
243 { eprintf("error in hashtable insertion, keys are identical");
247 LOOP_ENTRY(ht_start
);
257 #define WRITE_VAR_ENTRY() do { \
258 if(fseek(binaryout, entry_pos, SEEK_SET) == -1) wprintf("fseek failed with %s", strerror(errno)); \
259 fwrite(&var_ht_entry, sizeof var_ht_entry, 1, binaryout); \
261 #define INC_VAR_ENTRY() do { \
262 entry_pos += sizeof(var_ht_entry); \
263 if(fseek(binaryout, entry_pos, SEEK_SET) == -1) eprintf("fseek failed with %s", strerror(errno)); \
265 bin_insert_var_ht_entry
268 struct bin_var_ht_entry_t
* var_ht_entry
,
271 { long entry_pos
, ht_end
;
273 ht_end
= ht_start
+ ht_size
;
274 entry_pos
= ht_start
+ sizeof(var_ht_entry
) * ht_entry
->key
;
275 fseek(binaryout
, entry_pos
, SEEK_SET
);
277 if (!ENTRY_OCCUPIED())
278 { uprintf("key not occupied\n");
281 while( ENTRY_OCCUPIED() )
283 { if(bin_keys_identical(entry_pos
, ht_entry
->key
))
286 { eprintf("error in hashtable insertion, keys are identical");
290 LOOP_ENTRY(ht_start
);
298 /** @see http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2 */
300 int bin_calculate_ht_entries
302 { entries
= (entries
<< 1) - 1;
303 entries
|= entries
>> 1;
304 entries
|= entries
>> 2;
305 entries
|= entries
>> 4;
306 entries
|= entries
>> 8;
307 entries
|= entries
>> 16;
312 |--------------------|
314 |--------------------|
316 |--------------------|
318 |--------------------|
319 | classchild header |
323 long bin_traverse_set(ir_set
);
325 #define DEF_HT_INIT(_START, _SIZE, _INIT_ENTRIES) do { \
326 _SIZE = _ENTRIES * sizeof(var_ht_entry); \
327 _START = ftell(binaryout); \
328 fseek(binaryout, _SIZE, SEEK_CUR); \
330 #define VAR_HT_INIT(_START, _SIZE, _ENTRIES) do { \
331 _SIZE = _ENTRIES * sizeof(var_ht_entry); \
332 _START = ftell(binaryout); \
333 fseek(binaryout, _SIZE, SEEK_CUR); \
339 struct bin_class_header_t class_header
;
340 struct bin_def_ht_entry_t ht_entry
;
341 long class_start
, classht_start
, classht_size
, rootsetht_start
, rootsetht_size
;
342 int num_class_entries
, num_rootset_entries
;
345 class_start
= ftell(binaryout
);
346 class_name
= ir_class_name(class);
348 num_class_entries
= bin_calculate_ht_entries(bin_class_sibcount(class));
349 num_rootset_entries
= bin_calculate_ht_entries(ir_class_rootset(class));
351 /* alloc space (before hash tables) for class header */
352 class_header
.namelen
= u8_strlen(class_name
);
353 fseek(binaryout
, class_start
+ sizeof(class_header
) + class_header
.namelen
,SEEK_SET
);
355 DEF_HT_INIT(classht_start
, classht_size
, num_class_entries
);
356 DEF_HT_INIT(rootsetht_start
, rootsetht_size
, num_rootset_entries
);
358 /* TODO: Figure out generic way to output headers */
359 /* populate class header */
360 class_header
.child_ht
.entries
= num_class_entries
;
361 class_header
.child_ht
.start
= classht_start
;
362 class_header
.child_ht
.size
= classht_size
;
363 class_header
.rootset_ht
.entries
= num_rootset_entries
;
364 class_header
.rootset_ht
.start
= rootsetht_start
;
365 class_header
.rootset_ht
.size
= rootsetht_size
;
366 fseek(binaryout
, class_start
, SEEK_SET
); //seek back to where we allocated header
367 fwrite(&class_header
, sizeof(class_header
), 1, binaryout
);
368 fwrite(class_name
, class_header
.namelen
, 1, binaryout
);
370 /* Start populating root_set hash table */
371 for ( siter
= ir_class_rootset(class); siter
!= NULL
; siter
= ir_set_nextsib(siter
))
372 { fseek(binaryout
, 0, SEEK_END
);
373 ht_entry
.key
= NAMEHASH(ir_set_name(siter
), num_rootset_entries
);
374 ht_entry
.value
= bin_traverse_set(siter
);
375 bin_insert_def_ht_entry(rootsetht_start
, rootsetht_size
, &ht_entry
, 0);
378 /* Start populating class child hash table */
379 for ( citer
= ir_class_nextchild(class); citer
!= NULL
; citer
= ir_class_nextsib(citer
))
380 { if(chdir((char*) class_name
))
381 eprintf("CHDIR %U from %s\n",(char*) class_name
,getcwd(NULL
,255));
382 fseek(binaryout
, 0, SEEK_END
);
383 ht_entry
.key
= NAMEHASH(ir_class_name(citer
), num_class_entries
);
384 ht_entry
.value
= bin_traverse_class(citer
);
385 bin_insert_def_ht_entry(classht_start
, classht_size
, &ht_entry
, 0);
387 eprintf("CHDIR ..\n");
393 long bin_process_sdat( ir_set
);
396 |-----------------| |
398 |-----------------| |
399 ---| setchild ht |<--
400 | |-----------------|
401 |->| setchild header |
409 struct bin_set_header_t header
;
410 struct bin_def_ht_entry_t ht_entry
;
411 int num_entries
, setname_len
;
412 long childht_start
, childht_size
, set_start
;
415 set_start
= ftell(binaryout
);
416 set_name
= ir_set_name(set
);
418 /* alloc space for set header */
419 setname_len
= u8_strlen(set_name
);
420 fseek(binaryout
, sizeof(struct bin_set_header_t
) + setname_len
, SEEK_CUR
);
422 /* process the set data */
423 header
.sdat_start
= bin_process_sdat(set
);
425 /* Setup child hash table for current sets children */
426 num_entries
= bin_calculate_ht_entries(bin_set_sibcount(ir_set_nextchild(set
)));
428 DEF_HT_INIT(childht_start
, childht_size
, num_child
);
430 /* populate header, write to file */
431 header
.child_ht
.entries
= num_entries
;
432 header
.child_ht
.start
= childht_start
;
433 header
.child_ht
.size
= childht_size
;
434 fseek(binaryout
, set_start
, SEEK_SET
);
435 fwrite(&header
, sizeof(struct bin_set_header_t
), 1, binaryout
);
436 fwrite(set_name
, setname_len
, 1, binaryout
);
438 for(iter
= ir_set_nextchild(set
); iter
!= NULL
; iter
= ir_set_nextsib(iter
))
439 { fseek(binaryout
, 0, SEEK_END
);
440 ht_entry
.key
= NAMEHASH(ir_set_name(iter
), num_entries
);
441 ht_entry
.value
= bin_traverse_set(iter
);
442 bin_insert_def_ht_entry(childht_start
, childht_size
, &ht_entry
, 0);
446 ir_set_assign_fpos(set
, set_start
);
460 | 1st variant data | -- variant == framebox
468 static inline void bin_insert_links(struct bin_processed_links_t
*, struct bin_ht_header_t
*, long);
469 static inline struct bin_pixel_node_t
* bin_find_default_pixel_list(ir_set
);
470 static inline void bin_process_frameboxes(ir_set
, struct bin_ht_header_t
*, struct bin_pixel_node_t
*);
471 static inline struct bin_processed_links_t
* bin_process_links(ir_set
, struct bin_processed_links_t
*);
472 static inline void bin_process_dlinks(struct bin_processed_links_t
*);
474 /* Init the variant hash table for the set, process the sets links and add them to link_stack
475 and variant hash table, and then output the actual framedata */
479 { struct bin_setdata_header_t header
;
480 struct bin_attachment_list_t attachment_list
;
481 struct bin_pixel_node_t
*default_pixel_list
;
482 struct bin_ht_header_t ht_header
;
483 struct bin_processed_links_t
* processed_links_root
;
484 long varht_start
, varht_size
, sdat_start
;
485 int num_entries
, num_links
;
487 sdat_start
= ftell(binaryout
);
489 /* Alloc position for sdat_header */
490 fseek(binaryout
, sizeof(struct bin_setdata_header_t
), SEEK_CUR
);
492 /* set up root for processed_links */
493 processed_links_root
= stack_alloc(&plinkpages
, sizeof(struct bin_processed_links_t
));
494 processed_links_root
->mlink_len
= processed_links_root
->vlink_len
= processed_links_root
->dlink_len
= processed_links_root
->olinks_len
= 0;
495 processed_links_root
= bin_process_links(set
, processed_links_root
);
497 num_links
= processed_links_root
->mlink_len
+ processed_links_root
->vlink_len
;
499 num_entries
= bin_calculate_ht_entries(bin_set_varcount(set
) + num_links
);
501 VAR_HT_INIT(varht_start
, varht_size
, num_entries
);
503 /* Populate the sdat_header */
504 fseek(binaryout
, 0, sdat_start
);
505 header
.variant_ht
.start
= varht_start
;
506 header
.variant_ht
.entries
= num_entries
;
507 header
.variant_ht
.size
= varht_size
;
508 attachment_list
.filepos
= header
.attach_pos
= ftell(binaryout
) + sizeof(varht_start
) + sizeof(num_entries
);
509 fwrite(&header
, sizeof(header
), 1, binaryout
);
510 fseek(binaryout
, 0, SEEK_ENDhttps
://en.wikipedia.org/wiki/Generic_programming);
513 bin_process_dlinks(processed_links_root
);
515 /* Determine the default pixel list for all of the frameboxes */
516 default_pixel_list
= bin_find_default_pixel_list(set
);
517 /* Output each framebox, and insert it into the variant hash table */
518 bin_process_frameboxes(set
, &ht_header
, default_pixel_list
);
520 /* insert the links that were processed into the variant hash table */
521 bin_insert_links(processed_links_root
, &ht_header
, attachment_list
.filepos
);
523 /* TODO: Convert the default pixel list to an attachment_list and then push the */
524 /* sdats attachment_list onto the attachment_stack so it can be procesed */
532 void bin_process_dlinks
533 ( struct bin_processed_links_t
* processed_links
)
534 { struct bin_linklist_t
* dlink_iter
;
535 for( dlink_iter
= processed_links
->dlink_list
; dlink_iter
!= NULL
; dlink_iter
= dlink_iter
->next
)
536 { /* TODO: Construct its fully qualified name based on its linkdata*/
538 /* Output an int for its length, and then output the name */
545 struct bin_linklist_t
* bin_linklist_head
546 ( struct bin_linklist_t
* root
)
547 { struct bin_linklist_t
* head
;
554 /* We dont know src_pos at this point because this is still in the control flow
555 of bin_process_links, which determines the number of links, which determines
558 #define PUSH_LINK(_LINK) (*(linkdata*) stack_alloc(&linkpages, sizeof(linkdata)) = _LINK)
561 struct bin_processed_links_t
* processed_links
)
562 { struct bin_linklist_t
* llp
;
563 struct bin_linklist_t
* vlink_list_head
;
569 vlink_list_head
= bin_linklist_head(processed_links
->vlink_list
);
570 link_name
= ir_setdata_name(vlink
);
572 { llp
= stack_alloc(&plinkpages
, sizeof(bin_linklist_t
));
573 llp
->linkdata
= vlink
;
574 vlink_list_head
->next
= llp
;
575 processed_links
->vlink_len
++;
577 else // linking a variant hash table
578 { trg_set
= ir_linkdata_set(vlink
);
579 for (fiter
= ir_set_framebox(trg_set
); fiter
!= NULL
; fiter
= ir_setdata_nextsib(fiter
))
580 { llp
= stack_alloc(&plinkpages
, sizeof(bin_linklist_t
));
581 new_vlink
= stack_alloc(&plinkpages
, sizeof(linkdata
));
582 ir_data_assign_path(new_vlink
,ir_setdata_name(fiter
));
583 ir_linkdata_assign_set(new_vlink
,trg_set
);
584 ir_linkdata_assign_type(new_vlink
,VLINK
);
585 llp
->linkdata
= vlink
;
586 vlink_list_head
->next
= llp
;
587 processed_links
->vlink_len
++;
594 /* Adds an mlink to the stack_alloc, to be processed later */
599 struct bin_processed_links_t
* processed_links
601 { uint8_t* mlink_name
;
602 struct bin_linklist_t
* llp
;
603 struct bin_linklist_t
* mlink_list_head
;
609 mlink_list_head
= bin_linklist_head(processed_links
->mlink_list
);
610 mlink_name
= ir_setdata_name(mlink
);
613 { llp
= stack_alloc(&plinkpages
, sizeof(bin_linklist_t
));
614 llp
->linkdata
= mlink
;
615 mlink_list_head
->next
= llp
;
616 processed_links
->mlink_len
++;
619 { trg_set
= ir_linkdata_set(mlink
);
620 for (fiter
= ir_set_framebox(trg_set
); fiter
!= NULL
; fiter
= ir_setdata_nextsib(fiter
))
621 { //TODO: check here if illegal mlink(linking to a opsheet of a vdat not in src_set domain)?
622 llp
= stack_alloc(&plinkpages
, sizeof(bin_linklist_t
));
623 new_mlink
= stack_alloc(&plinkpages
, sizeof(linkdata
));
624 ir_data_assign_path(new_mlink
,ir_setdata_name(fiter
));//TODO: assign name
625 ir_linkdata_assign_set(new_vlink
,trg_set
);
626 ir_linkdata_assign_type(new_vlink
,VLINK
);
627 llp
->linkdata
= vlink
;
628 vlink_list_head
->next
= llp
;
629 processed_links
->vlink_len
++;
635 return processed_links
;
638 /* Determine if olink is already part of the olink_list.
639 if it is, theres a cycle, return 1. Else return 0. */
643 struct bin_processed_links_t
* processed_links
645 { struct bin_linklist_t
* iter
;
647 olink_set
= ir_linkdata_set(olink
);
648 for( iter
= processed_links
->olink_list
; iter
!= NULL
; iter
= iter
->next
)
649 if(ir_linkdata_set(iter
->linkdata
) == olink_set
)
654 /* if olink, process target sets frameboxes(turn into vlinks) and its attachment_list (turn into mlink),
655 else its a dlink so just add it to the processed_links list*/
657 void bin_process_olink
660 struct bin_processed_links_t
* processed_links_root
662 { struct bin_linklist_t
* link_list_head
;
663 struct bin_linklist_t
* new_link
;
665 new_link
= stack_alloc(&plinkpages
, sizeof(bin_linklist_t
));
666 if(trg_set
) //add olink to list so we can check for cycles
667 { bin_set_frameboxes_vlinks(trg_set
, processed_links_root
); //TODO:
668 bin_set_attachmentlist_mlink(trg_set
, processed_links_root
); //TODO:
669 link_list_head
= bin_linklist_head(processed_links_root
->olink_list
);
670 new_link
->linkdata
= olink
;
671 link_list_head
->next
= new_link
;
673 else // olink is actually a dynamic link
674 { link_list_head
= bin_linklist_head(processed_links_root
->dlink_list
);
675 new_link
->linkdata
= olink
;
676 link_list_head
->next
= new_link
;
682 /* Given a set, determine the number of links it has and process each link and
683 then add them to stack_alloc, where they will be popped off and further processed. */
684 struct bin_processed_links_t
* bin_process_links
686 struct bin_processed_links_t
* processed_links_root
690 for(linkdata
= ir_set_link(src_set
); linkdata
!= NULL
; linkdata
= ir_setdata_nextsib((ir_setdata
) linkdata
))
691 { switch (ir_linkdata_type(linkdata
)) {
693 if (olink_cycle(linkdata
, processed_links_root
))
694 return processed_links_root
; //TODO: what return value?
695 trg_set
= ir_linkdata_set(linkdata
);
696 bin_process_olink(trg_set
, linkdata
, processed_links_root
);
697 bin_process_links(trg_set
, processed_links_root
);
700 bin_process_vlink(linkdata
, processed_links_root
);
703 bin_process_mlink(linkdata
, processed_links_root
);
705 case ALINK
: //TODO: ?
709 return processed_links_root
;
712 /* Insert both mlinks and vlinks into the link stack, after determining their src_pos. Vlinks
713 have an additional requirement of being added into the variant hash table */
714 #define FRAME_POS() (entry_pos + sizeof(long))
715 #define MAP_POS() (entry_pos + sizeof(long)*2)
716 #define PUSH_PLINK(_LINK) (*(linkdata*) stack_alloc(&linkpages, sizeof (_LINK)) = _LINK )
719 ( struct bin_processed_links_t
* links
,
720 struct bin_ht_header_t
* ht
,
723 { struct bin_plink_t
* plp
;
724 struct bin_var_ht_entry_t ht_entry
;
725 struct bin_linklist_t
* vlinkiter
, *mlinkiter
;
729 /* Insert vlinks and mlinks into hash table, put v/mlinks on link stack to be processed later */
730 for ( vlinkiter
= links
->vlink_list
; vlinkiter
!= NULL
; vlinkiter
= vlinkiter
->next
)
731 { ht_entry
.key
= NAMEHASH(ir_setdata_name(vlinkiter
->linkdata
), ht
->entries
);
733 entry_pos
= bin_insert_var_ht_entry(ht
->start
, ht
->size
, &ht_entry
, 0);
734 ir_setdata_assign_fpos(vlinkiter
->linkdata
, FRAME_POS());
735 PUSH_PLINK(vlinkiter
->linkdata
);
737 /* TODO: If name exists in src_set, overwrite. if it dont, print a warning */
738 for ( mlinkiter
= links
->mlink_list
; mlinkiter
!= NULL
; mlinkiter
= mlinkiter
->next
)
739 { ht_entry
.key
= NAMEHASH(ir_setdata_name(mlinkiter
->linkdata
), ht
->size
);
741 entrypos
= bin_insert_var_ht_entry(ht
->start
, ht
->size
, &ht_entry
, 0);
742 ir_setdata_assign_fpos(mlinkiter
->linkdata
, MAP_POS());
743 PUSH_PLINK(mlinkiter
->linkdata
);
745 /* free all the processed links */
746 pagelist_free(plinkpages
);
751 long bin_process_facing(ir_setdata
, apc_facing
, struct bin_pixel_node_t
*);
752 /* |-------------------|
754 |-------------------|
756 |-------------------|
757 | SWFACE framesheet |
758 |-------------------|
765 struct bin_pixel_node_t
* default_pixel_list
767 { struct bin_model_header_t header
;
768 long framebox_start
, index_pos
;
771 framebox_start
= ftell(binaryout
);
773 /* insert model header */
775 header
.facing_array_start
= framebox_start
+ sizeof(header
);
776 fwrite(&header
, sizeof(header
), 1, binaryout
);
778 /* Create the index array for framesheet of each direction */
779 for ( i
= SFACE
; i
< FACING_MAX
; i
++)
780 { fseek(binaryout
, 0, SEEK_END
);
781 index_pos
= bin_process_facing(framebox
, i
, default_pixel_list
); //TODO: finish process_direction
782 fseek(binaryout
, header
.facing_array_start
+ i
* sizeof(long), SEEK_SET
);
783 fwrite(&index_pos
, sizeof(long), 1, binaryout
);
786 return framebox_start
;
789 bin_process_frameboxes
791 struct bin_ht_header_t
* ht
,
792 struct bin_pixel_node_t
* default_pixel_list
794 { struct bin_ht_entry_t ht_entry
;
797 /* Insert variants into hash table to overwrite olink insertions*/
798 for ( fiter
= ir_set_framebox(set
); fiter
!= NULL
; fiter
= ir_setdata_nextsib(fiter
))
799 { fseek(binaryout
, 0, SEEK_END
);
800 ht_entry
.key
= NAMEHASH(ir_setdata_name(fiter
), ht
->entries
);
801 ht_entry
.value
= bin_process_framebox(set
, fiter
, default_pixel_list
);
802 bin_insert_var_ht_entry(ht
->start
, ht
->entries
* sizeof(ht_entry
), &ht_entry
, 1);
806 /* Determine clipping based on image height/width and frame height/width */
808 void bin_set_img_info
809 ( struct bin_img_info_t
* img_info
,
810 ir_setdata frame_data
812 { ir_frameinfo frameinfo
;
813 frameinfo
= ir_framedata_frameinfo(frame_data
);
814 img_info
->fwidth
= frameinfo
->w
;
815 img_info
->fheight
= frameinfo
->h
;
816 img_info
->unaligned_height
= img_info
->height
% img_info
->fheight
;
817 img_info
->unaligned_width
= img_info
->width
% img_info
->fwidth
;
820 /* |-----------------------------|
822 |-----------------------------|
823 | pixel data for frame1 - n |
824 |-----------------------------|
825 | op data for frame1 - n |
826 |-----------------------------| */
829 //TODO: THIS SHOULD THE SET SPEC, NOT THE FRAMEBOX NAME
830 #define GENERATE_FILENAME(_N) ((char*) u8_strcat(_N, png_suffix))
832 ( ir_setdata framebox
,
834 struct bin_pixel_node_t
* default_pixel_list
836 { struct bin_img_info_t mapsheet_info
, framesheet_info
;
837 int num_mapchannels
, num_framechannels
, x
;
838 struct bin_frame_header_t header
;
840 RGBA_t
* mapdata
, * framedata
;
841 uint8_t* png_suffix
= ".png";
842 struct bin_pixel_node_t
* map_pixel_list
;
844 facing_start
= ftell(binaryout
);
847 /* Set up data pointers to mapsheet and framesheet, as well as their image infos */
848 mapdata
= (RGBA_t
*) stbi_load(GENERATE_FILENAME(ir_setdata_name((ir_setdata
) ir_framebox_mapsheet(framebox
,SFACE
))), &mapsheet_info
.width
, &mapsheet_info
.width
, &num_framechannels
, 0);
849 framedata
= (RGBA_t
*) stbi_load(GENERATE_FILENAME(ir_setdata_name((ir_setdata
) ir_framebox_framesheet(framebox
,SFACE
))), &framesheet_info
.width
, &framesheet_info
.height
, &num_mapchannels
, 0);
850 bin_set_img_info(&framesheet_info
, ir_framebox_framesheet(framebox
, SFACE
));
851 bin_set_img_info(&mapsheet_info
, ir_framebox_mapsheet(framebox
, SFACE
));
853 /* Allocate space for header */
854 fseek(binaryout
, sizeof(header
), SEEK_CUR
);
857 /* Output framesheet */
858 if(!stbi_write_png(binaryout
, framesheet_info
.width
, framesheet_info
.height
, 4, mapdata
, framesheet_info
.fwidth
))
859 eprintf("error writing out framesheet\n");
861 /* Output framesheet header */
862 header
.width
= framesheet_info
.fwidth
;
863 header
.height
= framesheet_info
.fheight
;
864 header
.frames
= framesheet_info
.width
/ framesheet_info
.fwidth
; //TODO: division is bad
865 header
.op_start
= ftell(binaryout
);
866 fseek(binaryout
, facing_start
, SEEK_SET
);
867 fwrite(&header
, sizeof(header
), 1, binaryout
);
868 fseek(binaryout
, 0, SEEK_END
);
873 /* Assuming that fheight = image height */
874 /* For each mapframe in mapsheet */
875 for ( x
= 0; x
< header
.frames
; x
++)
876 { map_pixel_list
= bin_mapframe_to_pixel_list(mapsheet_info
, 0, x
* mapsheet_info
.fwidth
, mapdata
);
877 if(!bin_process_map_pixel_list(default_pixel_list
, map_pixel_list
))
878 eprintf("error processing map pixel list\n");
879 bin_output_pixel_list(map_pixel_list
);
880 mapdata
= mapsheet_info
.fwidth
* x
; //do we do this in mapframe to pixellist?
890 /* pixel_list == ops, output up to fwidth amount of them */
892 bin_output_pixel_list(struct bin_pixel_node_t
* map_pixel_list
)
894 /* TODO: Please rename all the functions jhc*/
896 void bin_number_pixel_list
897 ( struct bin_pixel_node_t
* pixel_list
)
899 struct bin_pixel_node_t
* iter
;
901 { iter
->data
.attach_idx
= num
++;
906 /* Assuming at this point that map_pixel_list is valid */
908 int bin_set_map_pixel_list_attach_idxs
909 ( struct bin_pixel_node_t
* default_pixel_list
,
910 struct bin_pixel_node_t
* map_pixel_list
912 { struct bin_pixel_node_t
* mapiter
, defaultiter
;
913 mapiter
= map_pixel_list
;
914 defaultiter
= default_pixel_list
;
915 while (mapiter
&& defaultiter
)
916 { /* if mapiter.data.ref == defaultiter.data.ref, assign mapiter index_idx to defaultiter */
917 if (mapiter
.data
.ref
== defauliter
.data
.ref
)
918 { defaultiter
.data
.attach_idx
= mapiter
.data
.attach_idx
;
919 mapiter
= mapiter
->next
;
920 defaultiter
= defaultiter
->next
;
923 defaultiter
= defaultiter
->next
;
927 /* map_pixel_list cannot have more pixels. for all of its pixels,
928 the refs must be represented in default pixel list. 0 if invalid, 1 if valid */
930 int bin_valid_map_pixel_list
931 ( struct bin_pixel_node_t
* default_pixel_list
,
932 struct bin_pixel_node_t
* map_pixel_list
934 { struct bin_pixel_node_t
* mapiter
, *defaultiter
;
935 defaultiter
= default_pixel_list
;
936 /* check length of each to make sure default < max */
937 /* for each pixel node in default and map */
938 /* TODO: Implement:: basically just checkking if map_pixel_list is subset of default_pixel_list
939 which means is the intersection of default_pl and map_pl == default_pl */
943 if(!mapiter
&& defaultiter
) //defaultiter is longer so error!
952 int bin_process_map_pixel_list
953 ( struct bin_pixel_node_t
* default_pixel_list
,
954 struct bin_pixel_node_t
* map_pixel_list
956 { /* Determine if pixel_list is valid */
957 if(!bin_valid_map_pixel_list(default_pixel_list
, map_pixel_list
))
960 /* Determine attach_idx of each pixel, as compared to default pixel list */
966 bin_assign_pixel_idxs
967 ( struct bin_pixel_node_t
* pixel_list
)
971 /* Insert pixel(s) into the list, z sorted */
972 /* number the pixels as you insert them */
973 struct bin_pixel_node_t
*
974 bin_insert_node_into_list
975 ( struct bin_pixel_node_t
* pixel_list_root
,
976 struct bin_pixel_node_t
* pixel_node
978 { struct bin_pixel_node_t
* head_node
, * prev_node
;
981 if(pixel_list_root
== NULL
)
982 { pixel_list_root
= pixel_node
;
985 prev_node
= head_node
= pixel_list_root
;
986 while(head_node
!= NULL
)
987 { if(pixel_node
->data
.z
> head_node
->data
.z
)
988 { if(head_node
->next
)
989 { prev_node
= head_node
;
990 head_node
= head_node
->next
;
993 { head_node
->next
= pixel_node
;
997 else if (pixel_node
->data
.z
< head_node
->data
.z
)
999 prev_node
->next
= pixel_node
;
1000 pixel_node
->next
= head_node
;
1003 else // pixel_node->data.z == head_node->data.z
1004 { pixel_node
->num
= head_node
->num
+ 1;
1005 prev_node
->next
= pixel_node
;
1006 pixel_node
->next
= head_node
;
1010 return pixel_list_root
;
1015 /* Returns the non null pixels of a single map */
1016 /* TODO: Finish this */
1017 struct bin_pixel_node_t
*
1018 bin_mapframe_to_pixel_list
1019 ( struct bin_img_info_t
* img_info
,
1024 { int x
, y
, fheight
, fwidth
;
1025 struct bin_pixel_node_t
* pixel_list
,* pixel_node
;
1029 /* if frame clips, process unclippign frames */
1030 if( img_info
->unaligned_width
)
1031 { if(img_info
->height
< img_info
->fheight
)
1032 fheight
= img_info
->height
;
1034 fheight
= img_info
->fheight
;
1037 fheight
= img_info
->fheight
;
1038 if (img_info
->unaligned_height
)
1039 { if(img_info
->width
< img_info
->fwidth
)
1040 fwidth
= img_info
->width
;
1042 fwidth
= img_info
->fwidth
;
1045 fwidth
= img_info
->fwidth
;
1048 /* Process the map*/
1049 for (y
= 0; y
< fheight
; y
++)
1050 { for ( x
= 0; x
< fwidth
; x
++ )
1052 { pixel_node
= struct_alloc(bin_pixel_node_t
);
1053 /* get ref from 4 bytes of data */
1054 pixel_node
->data
.ref
= (*data
) >> 8;
1055 /* bitshift by ? to get Z */
1056 pixel_node
->data
.z
= (*data
& 0xFF);
1058 pixel_node
->data
.x
= x
+ init_width
;
1059 pixel_node
->data
.y
= y
+ init_width
;
1060 pixel_list
= bin_insert_node_into_list(pixel_list
, pixel_node
);
1064 data
+= img_info
->width
- img_info
->fwidth
; //stride TODO: isnt this null at the last iteration?
1066 //TODO: fix these two for loops why dontcha
1067 for ( x
= 0; x
< fwidth
; x
++ )
1069 { pixel_node
= struct_alloc(bin_pixel_node_t
);
1070 /* get ref from 4 bytes of data */
1071 pixel_node
->data
.ref
= (*data
) >> 8;
1072 /* bitshift by ? to get Z */
1073 pixel_node
->data
.z
= (*data
& 0xFF);
1075 pixel_node
->data
.x
= x
+ init_width
;
1076 pixel_node
->data
.y
= y
+ init_width
;
1077 pixel_list
= bin_insert_node_into_list(pixel_list
, pixel_node
);
1086 int bin_pixel_list_len
1087 ( struct bin_pixel_node_t
* pl
)
1088 { struct bin_pixel_node_t
* plp
;
1099 struct bin_pixel_node_t
*
1100 bin_cmp_default_pixel_lists
1101 ( struct bin_pixel_node_t
* pl1
,
1102 struct bin_pixel_node_t
* pl2
1104 { struct bin_pixel_node_t
* pl1p
, * pl2p
;
1105 int i
, pl1_len
, pl2_len
;
1109 pl1_len
= bin_pixel_list_len(pl1
);
1110 pl2_len
= bin_pixel_list_len(pl2
);
1112 if (pl1_len
> pl2_len
)
1114 else if (pl1_len
< pl2_len
)
1116 /* pl1 == pl2, make sure that all refs are the same */
1117 /* TODO: what type of warning/error handling should occur here? */
1118 for (i
= 0; i
< pl1_len
; i
++)
1119 { if (pl1p
->data
.ref
!= pl2p
->data
.ref
)
1120 eprintf("Error in determining default pixel list\n");
1124 return pl1
; //doesnt matter which one you return
1127 /* Find default framebox, based on the framebox with the most attachments*/
1128 /* Search through first frame of S of each framebox */
1129 struct bin_pixel_node_t
*
1130 bin_find_default_pixel_list
1133 struct bin_pixel_node_t
* default_pixel_list
, * curr_pixel_list
;
1136 struct bin_img_info_t img_info
;
1138 for (fiter
= ir_set_framebox(set
); fiter
!= NULL
; fiter
= ir_setdata_nextsib(fiter
))
1139 { /* TODO: Stringify the frame name with .png? */
1140 /* TODO: Add directory changing */
1141 data
= (RGBA_t
*) stbi_load(ir_setdata_name((ir_setdata
) ir_framebox_mapsheet(fiter
,SFACE
) ), &img_info
.width
, &img_info
.width
, &num_channels
, 0);
1142 bin_set_img_info(&img_info
, ir_framebox_mapsheet(fiter
, SFACE
));
1143 curr_pixel_list
= bin_mapframe_to_pixel_list(&img_info
, 0, 0, data
);
1144 default_pixel_list
= bin_cmp_default_pixel_lists(curr_pixel_list
, default_pixel_list
);
1149 return default_pixel_list
;