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"
25 #include "../ston/ston.h"
28 void ir_binout_init(struct ir_class_t
*);
31 long file_ht_insert(long,int,int,int,uint32_t*,uint32_t,uint32_t);
32 /* Memory Allocation */
33 #define struct_alloc(_T) ((struct _T*) stack_alloc(&datapages, sizeof(struct _T)))
35 struct pagelist_t linkpages
, datapages
, plinkpages
;
37 enum model_type
{ SS
};
38 /* Binaryout out structure definitions */
39 struct bin_img_info_t
{
42 int fwidth
; //map and frame width
43 int fheight
; //map and frame height
47 struct bin_ht_header_t
{
52 struct bin_ht_entry_t
{
56 struct bin_variant_ht_entry_t
{
61 struct bin_class_header_t
{
62 struct bin_ht_header_t child_ht
;
63 struct bin_ht_header_t rootset_ht
;
66 struct bin_set_header_t
{
67 struct bin_ht_header_t child_ht
;
68 long sdat_start
; //points to setdata_header
71 struct bin_setdata_header_t
{
72 struct bin_ht_header_t variant_ht
;
75 struct bin_model_header_t
{ //one for each framebox, currently
76 long facing_array_start
;
79 struct bin_frame_header_t
{
91 struct bin_pixel_node_t
{
92 struct bin_pixel_node_t
* next
;
93 struct bin_pixel_t data
;
95 struct bin_attachment_header_t
{
96 int num_attachment_lists
;
99 struct bin_attachment_t
{
103 /* Read out of the als, after first ir pass, resolves the
104 attach_pos of the src-set that created the attachment_list
105 to the header that describes the attachment_list */
106 struct bin_attachment_list_t
{
108 struct bin_attachment_t
** attachments
;
111 struct bin_linklist_t
;
112 struct bin_linklist_t
113 { struct bin_linklist_t
* next
;
117 struct bin_processed_links_t
118 { struct bin_linklist_t
* vlink_list
;
120 struct bin_linklist_t
* mlink_list
;
122 struct bin_linklist_t
* olink_list
; //keep track of olink cycles
124 struct bin_linklist_t
* dlink_list
;
127 struct bin_pixel_ht_entry_t
132 struct bin_pixel_ht_t
133 { struct bin_pixel_ht_t
* next
;
134 struct bin_pixel_ht_entry_t
* hash_entries
;
138 struct bin_attachment_list_t
**attachment_stack
, **asp
; //attachment_stack, attachment_stack_pointer
142 #define NAMEHASH(name, domain) (XXH32(name, u8_strlen(name), 0XCEED ) & domain)
143 #define REFHASH(ref, domain) (XXH32(&ref, sizeof(uint32_t), 0xCEED) & domain)
150 for (iter
= ir_set_framebox(set
); iter
!= NULL
; iter
= ir_setdata_nextsib(iter
))
156 int bin_class_sibcount
161 for (iter
= class; iter
!= NULL
; iter
= ir_class_nextsib(iter
))
172 for (iter
= set
; iter
!= NULL
; iter
= ir_set_nextsib(iter
))
177 /* Checks if the key at entrypos is the same as the parameter key. Returns
178 1 if so, 0 if not. */
180 int bin_keys_identical
185 fseek(binaryout
, entry_pos
, SEEK_SET
);
186 fscanf(binaryout
, "%u", &curr_key
);
193 typedef uint32_t RGBA_t
;
195 long bin_traverse_class(ir_class
);
196 /* Takes root class and begins processing */
198 ir_binout_init(ir_class root_class
)
199 { binaryout
= fopen("binaryout", "w+");
200 asp
= attachment_stack
;
201 pagelist_init(datapages
, (size_t) SYS_PAGESIZE
);
202 pagelist_init(linkpages
, (size_t) SYS_PAGESIZE
);
203 pagelist_init(plinkpages
, (size_t) SYS_PAGESIZE
);
204 bin_traverse_class(root_class
);
207 /* INSERT INTO HASH TABLE */
208 /* Returns the key position where the hash table entry was inserted. */
209 #define SEEK_TO(_FPOS) do { \
211 if (fseek(binaryout, _FPOS, SEEK_SET)) \
212 eprintf("Failed to seek to position %l: %s\n", _FPOS, strerror(errno)); \
214 #define SEEK_REL(_FPOS) do { \
216 if (fseek(binaryout, _FPOS, SEEK_CUR)) \
217 eprintf("Failed to seek to position %l: %s\n", _FPOS, strerror(errno)); \
219 #define READ_DATA_AND_INCREMENT(_DATA,_SIZE) do { \
221 if (fread(_DATA, _SIZE, 1, binaryout) != 1) \
222 eprintf("Failed to read data at file position %l: %s\n", \
226 #define READ_DATA(_DATA,_SIZE) do { \
227 READ_DATA_AND_INCREMENT(_DATA,_SIZE); \
230 #define WRITE_DATA_AND_INCREMENT(_DATA,_SIZE) do { \
232 if (fwrite(_DATA, _SIZE, 1, binaryout) != 1) \
233 eprintf("Failed to write data to file at position %l: %s\n", \
237 #define WRITE_DATA(_DATA,_SIZE) do { \
238 WRITE_DATA_AND_INCREMENT(_DATA,_SIZE); \
242 /* Insert a value into an arbitrary hash table in-file */
253 { uint32_t entry
[ht_row_values
];
254 # define ENTRY_VAL(N) entry[N]
255 # define ENTRY_KEY ENTRY_VAL(0)
257 size_t entry_row
= key
& (ht_rows
- 1);
259 long writepos
, startpos
;
260 startpos
= ftell(binaryout
);
262 SEEK_TO(ht_start
+ (entry_row
* sizeof(entry
)));
263 READ_DATA(entry
, sizeof(uint32_t) * ht_row_values
);
264 for (i
= 0; i
< ht_row_values
; i
++)
268 SEEK_REL(sizeof(uint32_t) * ht_which_value
);
269 WRITE_DATA(entry
+ ht_which_value
, sizeof(*entry
));
270 writepos
= ftell(binaryout
);
274 if (ENTRY_KEY
== key
)
275 { if (overwrite
!= NULL
)
276 *overwrite
= ENTRY_VAL(ht_which_value
);
277 ENTRY_VAL(ht_which_value
) = value
;
280 if (entry_row
< ht_rows
)
283 eprintf("cannot insert into filled hashtable\n");
292 uint32_t* mem_ht_insert
303 size_t entry_row
= key
& (ht_rows
- 1);
306 entry
= (uint32_t*)ht_start
+ (ht_row_values
* entry_row
);
307 for (i
= 0; i
< ht_row_values
; i
++)
311 entry
[ht_which_value
] = value
;
312 return &entry
[ht_which_value
];
314 if (ENTRY_KEY
== key
)
315 { if (overwrite
!= NULL
)
316 *overwrite
= ENTRY_VAL(ht_which_value
);
319 if (entry_row
< ht_rows
)
322 eprintf("cannot insert into filled hashtable\n");
330 /** @see http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2 */
332 int bin_calculate_ht_entries
334 { entries
= (entries
<< 1) - 1;
335 entries
|= entries
>> 1;
336 entries
|= entries
>> 2;
337 entries
|= entries
>> 4;
338 entries
|= entries
>> 8;
339 entries
|= entries
>> 16;
344 |--------------------|
346 |--------------------|
348 |--------------------|
350 |--------------------|
351 | classchild header |
355 long bin_traverse_set(ir_set
);
357 #define DEF_HT_INIT(_START, _SIZE, _INIT_ENTRIES) do { \
358 _SIZE = _ENTRIES * sizeof(var_ht_entry); \
359 _START = ftell(binaryout); \
360 fseek(binaryout, _SIZE, SEEK_CUR); \
362 #define VAR_HT_INIT(_START, _SIZE, _ENTRIES) do { \
363 _SIZE = _ENTRIES * sizeof(var_ht_entry); \
364 _START = ftell(binaryout); \
365 fseek(binaryout, _SIZE, SEEK_CUR); \
371 struct bin_class_header_t class_header
;
372 long class_start
, classht_start
, classht_size
, rootsetht_start
, rootsetht_size
;
373 int num_class_entries
, num_rootset_entries
;
376 class_header
.namelen
= u8_strlen(class_name
);
379 class_start
= ftell(binaryout
);
380 class_name
= ir_class_name(class);
382 num_class_entries
= bin_calculate_ht_entries(bin_class_sibcount(class));
383 num_rootset_entries
= bin_calculate_ht_entries(bin_set_sibcount(ir_class_rootset(class)));
385 /* alloc space (before hash tables) for class header */
386 fseek(binaryout
, class_start
+ sizeof(class_header
) + class_header
.namelen
,SEEK_SET
);
388 DEF_HT_INIT(classht_start
, classht_size
, num_class_entries
);
389 DEF_HT_INIT(rootsetht_start
, rootsetht_size
, num_rootset_entries
);
391 /* TODO: Figure out generic way to output headers */
392 /* populate class header */
393 class_header
.child_ht
.entries
= num_class_entries
;
394 class_header
.child_ht
.start
= classht_start
;
395 class_header
.child_ht
.size
= classht_size
;
396 class_header
.rootset_ht
.entries
= num_rootset_entries
;
397 class_header
.rootset_ht
.start
= rootsetht_start
;
398 class_header
.rootset_ht
.size
= rootsetht_size
;
399 fseek(binaryout
, class_start
, SEEK_SET
); //seek back to where we allocated header
400 fwrite(&class_header
, sizeof(class_header
), 1, binaryout
);
401 fwrite(class_name
, class_header
.namelen
, 1, binaryout
);
403 /* Start populating root_set hash table */
404 for ( siter
= ir_class_rootset(class); siter
!= NULL
; siter
= ir_set_nextsib(siter
))
405 { fseek(binaryout
, 0, SEEK_END
);
406 file_ht_insert(rootsetht_start
, 2, 1,
409 NAMEHASH(ir_set_name(siter
), num_rootset_entries
),
410 bin_traverse_set(siter
));
413 /* Start populating class child hash table */
414 for ( citer
= ir_class_nextchild(class); citer
!= NULL
; citer
= ir_class_nextsib(citer
))
415 { if(chdir((char*) class_name
))
416 eprintf("CHDIR %U from %s\n",(char*) class_name
,getcwd(NULL
,255));
417 fseek(binaryout
, 0, SEEK_END
);
418 file_ht_insert(classht_start
, 2, 1,
421 NAMEHASH(ir_class_name(citer
), num_class_entries
),
422 bin_traverse_class(citer
));
424 eprintf("CHDIR ..\n");
430 long bin_process_sdat( ir_set
);
433 |-----------------| |
435 |-----------------| |
436 ---| setchild ht |<--
437 | |-----------------|
438 |->| setchild header |
446 struct bin_set_header_t header
;
447 struct bin_def_ht_entry_t ht_entry
;
448 int num_entries
, setname_len
;
449 long childht_start
, childht_size
, set_start
;
452 set_start
= ftell(binaryout
);
453 set_name
= ir_set_name(set
);
455 /* alloc space for set header */
456 setname_len
= u8_strlen(set_name
);
457 fseek(binaryout
, sizeof(struct bin_set_header_t
) + setname_len
, SEEK_CUR
);
459 /* process the set data */
460 header
.sdat_start
= bin_process_sdat(set
);
462 /* Setup child hash table for current sets children */
463 num_entries
= bin_calculate_ht_entries(bin_set_sibcount(ir_set_nextchild(set
)));
465 DEF_HT_INIT(childht_start
, childht_size
, num_child
);
467 /* populate header, write to file */
468 header
.child_ht
.entries
= num_entries
;
469 header
.child_ht
.start
= childht_start
;
470 header
.child_ht
.size
= childht_size
;
471 fseek(binaryout
, set_start
, SEEK_SET
);
472 fwrite(&header
, sizeof(struct bin_set_header_t
), 1, binaryout
);
473 fwrite(set_name
, setname_len
, 1, binaryout
);
475 for(iter
= ir_set_nextchild(set
); iter
!= NULL
; iter
= ir_set_nextsib(iter
))
476 { fseek(binaryout
, 0, SEEK_END
);
477 ht_entry
.key
= NAMEHASH(ir_set_name(iter
), num_entries
);
478 ht_entry
.value
= bin_traverse_set(iter
);
479 bin_insert_ht_entry(childht_start
, childht_size
, &ht_entry
, 0);
483 ir_set_assign_fpos(set
, set_start
);
497 | 1st variant data | -- variant == framebox
505 static inline void bin_insert_links(struct bin_processed_links_t
*, struct bin_ht_header_t
*, long);
506 static inline struct bin_pixel_node_t
* bin_find_default_pixel_list(ir_set
);
507 static inline void bin_process_frameboxes(ir_set
, struct bin_ht_header_t
*, struct bin_pixel_node_t
*);
508 static inline struct bin_processed_links_t
* bin_process_links(ir_set
, struct bin_processed_links_t
*);
509 static inline void bin_process_dlinks(struct bin_processed_links_t
*);
511 /* Init the variant hash table for the set, process the sets links and add them to link_stack
512 and variant hash table, and then output the actual framedata */
516 { struct bin_setdata_header_t header
;
517 struct bin_attachment_list_t attachment_list
;
518 struct bin_pixel_node_t
*default_pixel_list
;
519 struct bin_ht_header_t ht_header
;
520 struct bin_processed_links_t
* processed_links_root
;
521 long varht_start
, varht_size
, sdat_start
;
522 int num_entries
, num_links
;
524 sdat_start
= ftell(binaryout
);
526 /* Alloc position for sdat_header */
527 fseek(binaryout
, sizeof(struct bin_setdata_header_t
), SEEK_CUR
);
529 /* set up root for processed_links */
530 processed_links_root
= stack_alloc(&plinkpages
, sizeof(struct bin_processed_links_t
));
531 processed_links_root
->mlink_len
= processed_links_root
->vlink_len
= processed_links_root
->dlink_len
= processed_links_root
->olinks_len
= 0;
532 processed_links_root
= bin_process_links(set
, processed_links_root
);
534 num_links
= processed_links_root
->mlink_len
+ processed_links_root
->vlink_len
;
536 num_entries
= bin_calculate_ht_entries(bin_set_varcount(set
) + num_links
);
538 VAR_HT_INIT(varht_start
, varht_size
, num_entries
);
540 /* Populate the sdat_header */
541 fseek(binaryout
, 0, sdat_start
);
542 header
.variant_ht
.start
= varht_start
;
543 header
.variant_ht
.entries
= num_entries
;
544 header
.variant_ht
.size
= varht_size
;
545 attachment_list
.filepos
= header
.attach_pos
= ftell(binaryout
) + sizeof(varht_start
) + sizeof(num_entries
);
546 fwrite(&header
, sizeof(header
), 1, binaryout
);
547 fseek(binaryout
, 0, SEEK_ENDhttps
://en.wikipedia.org/wiki/Generic_programming);
550 bin_process_dlinks(processed_links_root
);
552 /* Determine the default pixel list for all of the frameboxes */
553 default_pixel_list
= bin_find_default_pixel_list(set
);
554 /* Output each framebox, and insert it into the variant hash table */
555 bin_process_frameboxes(set
, &ht_header
, default_pixel_list
);
557 /* insert the links that were processed into the variant hash table */
558 bin_insert_links(processed_links_root
, &ht_header
, attachment_list
.filepos
);
560 /* TODO: Convert the default pixel list to an attachment_list and then push the */
561 /* sdats attachment_list onto the attachment_stack so it can be procesed */
569 void bin_process_dlinks
570 ( struct bin_processed_links_t
* processed_links
)
571 { struct bin_linklist_t
* dlink_iter
;
572 for( dlink_iter
= processed_links
->dlink_list
; dlink_iter
!= NULL
; dlink_iter
= dlink_iter
->next
)
573 { /* TODO: Construct its fully qualified name based on its linkdata*/
575 /* Output an int for its length, and then output the name */
582 struct bin_linklist_t
* bin_linklist_head
583 ( struct bin_linklist_t
* root
)
584 { struct bin_linklist_t
* head
;
591 /* We dont know src_pos at this point because this is still in the control flow
592 of bin_process_links, which determines the number of links, which determines
595 #define PUSH_LINK(_LINK) (*(linkdata*) stack_alloc(&linkpages, sizeof(linkdata)) = _LINK)
598 struct bin_processed_links_t
* processed_links
)
599 { struct bin_linklist_t
* llp
;
600 struct bin_linklist_t
* vlink_list_head
;
606 vlink_list_head
= bin_linklist_head(processed_links
->vlink_list
);
607 link_name
= ir_setdata_name(vlink
);
609 { llp
= stack_alloc(&plinkpages
, sizeof(bin_linklist_t
));
610 llp
->linkdata
= vlink
;
611 vlink_list_head
->next
= llp
;
612 processed_links
->vlink_len
++;
614 else // linking a variant hash table
615 { trg_set
= ir_linkdata_set(vlink
);
616 for (fiter
= ir_set_framebox(trg_set
); fiter
!= NULL
; fiter
= ir_setdata_nextsib(fiter
))
617 { llp
= stack_alloc(&plinkpages
, sizeof(bin_linklist_t
));
618 new_vlink
= stack_alloc(&plinkpages
, sizeof(linkdata
));
619 ir_data_assign_path(new_vlink
,ir_setdata_name(fiter
));
620 ir_linkdata_assign_set(new_vlink
,trg_set
);
621 ir_linkdata_assign_type(new_vlink
,VLINK
);
622 llp
->linkdata
= vlink
;
623 vlink_list_head
->next
= llp
;
624 processed_links
->vlink_len
++;
631 /* Adds an mlink to the stack_alloc, to be processed later */
636 struct bin_processed_links_t
* processed_links
638 { uint8_t* mlink_name
;
639 struct bin_linklist_t
* llp
;
640 struct bin_linklist_t
* mlink_list_head
;
646 mlink_list_head
= bin_linklist_head(processed_links
->mlink_list
);
647 mlink_name
= ir_setdata_name(mlink
);
650 { llp
= stack_alloc(&plinkpages
, sizeof(bin_linklist_t
));
651 llp
->linkdata
= mlink
;
652 mlink_list_head
->next
= llp
;
653 processed_links
->mlink_len
++;
656 { trg_set
= ir_linkdata_set(mlink
);
657 for (fiter
= ir_set_framebox(trg_set
); fiter
!= NULL
; fiter
= ir_setdata_nextsib(fiter
))
658 { //TODO: check here if illegal mlink(linking to a opsheet of a vdat not in src_set domain)?
659 llp
= stack_alloc(&plinkpages
, sizeof(bin_linklist_t
));
660 new_mlink
= stack_alloc(&plinkpages
, sizeof(linkdata
));
661 ir_data_assign_path(new_mlink
,ir_setdata_name(fiter
));//TODO: assign name
662 ir_linkdata_assign_set(new_vlink
,trg_set
);
663 ir_linkdata_assign_type(new_vlink
,VLINK
);
664 llp
->linkdata
= vlink
;
665 vlink_list_head
->next
= llp
;
666 processed_links
->vlink_len
++;
672 return processed_links
;
675 /* Determine if olink is already part of the olink_list.
676 if it is, theres a cycle, return 1. Else return 0. */
680 struct bin_processed_links_t
* processed_links
682 { struct bin_linklist_t
* iter
;
684 olink_set
= ir_linkdata_set(olink
);
685 for( iter
= processed_links
->olink_list
; iter
!= NULL
; iter
= iter
->next
)
686 if(ir_linkdata_set(iter
->linkdata
) == olink_set
)
691 /* if olink, process target sets frameboxes(turn into vlinks) and its attachment_list (turn into mlink),
692 else its a dlink so just add it to the processed_links list*/
694 void bin_process_olink
697 struct bin_processed_links_t
* processed_links_root
699 { struct bin_linklist_t
* link_list_head
;
700 struct bin_linklist_t
* new_link
;
702 new_link
= stack_alloc(&plinkpages
, sizeof(bin_linklist_t
));
703 if(trg_set
) //add olink to list so we can check for cycles
704 { bin_set_frameboxes_vlinks(trg_set
, processed_links_root
); //TODO:
705 bin_set_attachmentlist_mlink(trg_set
, processed_links_root
); //TODO:
706 link_list_head
= bin_linklist_head(processed_links_root
->olink_list
);
707 new_link
->linkdata
= olink
;
708 link_list_head
->next
= new_link
;
710 else // olink is actually a dynamic link
711 { link_list_head
= bin_linklist_head(processed_links_root
->dlink_list
);
712 new_link
->linkdata
= olink
;
713 link_list_head
->next
= new_link
;
719 /* Given a set, determine the number of links it has and process each link and
720 then add them to stack_alloc, where they will be popped off and further processed. */
721 struct bin_processed_links_t
* bin_process_links
723 struct bin_processed_links_t
* processed_links_root
727 for(linkdata
= ir_set_link(src_set
); linkdata
!= NULL
; linkdata
= ir_setdata_nextsib((ir_setdata
) linkdata
))
728 { switch (ir_linkdata_type(linkdata
)) {
730 if (olink_cycle(linkdata
, processed_links_root
))
731 return processed_links_root
; //TODO: what return value?
732 trg_set
= ir_linkdata_set(linkdata
);
733 bin_process_olink(trg_set
, linkdata
, processed_links_root
);
734 bin_process_links(trg_set
, processed_links_root
);
737 bin_process_vlink(linkdata
, processed_links_root
);
740 bin_process_mlink(linkdata
, processed_links_root
);
742 case ALINK
: //TODO: ?
746 return processed_links_root
;
749 /* Insert both mlinks and vlinks into the link stack, after determining their src_pos. Vlinks
750 have an additional requirement of being added into the variant hash table */
751 #define FRAME_POS() (entry_pos + sizeof(long))
752 #define MAP_POS() (entry_pos + sizeof(long)*2)
753 #define PUSH_PLINK(_LINK) (*(linkdata*) stack_alloc(&linkpages, sizeof (_LINK)) = _LINK )
756 ( struct bin_processed_links_t
* links
,
757 struct bin_ht_header_t
* ht
,
760 { struct bin_plink_t
* plp
;
761 struct bin_var_ht_entry_t ht_entry
;
762 struct bin_linklist_t
* vlinkiter
, *mlinkiter
;
766 /* Insert vlinks and mlinks into hash table, put v/mlinks on link stack to be processed later */
767 for ( vlinkiter
= links
->vlink_list
; vlinkiter
!= NULL
; vlinkiter
= vlinkiter
->next
)
768 { ht_entry
.key
= NAMEHASH(ir_setdata_name(vlinkiter
->linkdata
), ht
->entries
);
770 entry_pos
= bin_insert_var_ht_entry(ht
->start
, ht
->size
, &ht_entry
, 0);
771 ir_setdata_assign_fpos(vlinkiter
->linkdata
, FRAME_POS());
772 PUSH_PLINK(vlinkiter
->linkdata
);
774 /* TODO: If name exists in src_set, overwrite. if it dont, print a warning */
775 for ( mlinkiter
= links
->mlink_list
; mlinkiter
!= NULL
; mlinkiter
= mlinkiter
->next
)
776 { ht_entry
.key
= NAMEHASH(ir_setdata_name(mlinkiter
->linkdata
), ht
->size
);
778 entrypos
= bin_insert_var_ht_entry(ht
->start
, ht
->size
, &ht_entry
, 0);
779 ir_setdata_assign_fpos(mlinkiter
->linkdata
, MAP_POS());
780 PUSH_PLINK(mlinkiter
->linkdata
);
782 /* free all the processed links */
783 pagelist_free(plinkpages
);
788 long bin_process_facing(ir_setdata
, apc_facing
, struct bin_pixel_node_t
*);
789 /* |-------------------|
791 |-------------------|
793 |-------------------|
794 | SWFACE framesheet |
795 |-------------------|
802 struct bin_pixel_node_t
* default_pixel_list
804 { struct bin_model_header_t header
;
805 long framebox_start
, index_pos
;
808 framebox_start
= ftell(binaryout
);
810 /* insert model header */
812 header
.facing_array_start
= framebox_start
+ sizeof(header
);
813 fwrite(&header
, sizeof(header
), 1, binaryout
);
815 /* Create the index array for framesheet of each direction */
816 for ( i
= SFACE
; i
< FACING_MAX
; i
++)
817 { fseek(binaryout
, 0, SEEK_END
);
818 index_pos
= bin_process_facing(framebox
, i
, default_pixel_list
); //TODO: finish process_direction
819 fseek(binaryout
, header
.facing_array_start
+ i
* sizeof(long), SEEK_SET
);
820 fwrite(&index_pos
, sizeof(long), 1, binaryout
);
823 return framebox_start
;
826 struct bin_pixel_ht_t
* bin_pixel_ht_alloc
828 { struct bin_pixel_ht_t
* htp
;
829 if(!(htp
= (struct bin_pixel_ht_t
*) malloc(sizeof(bin_pixel_ht_t
) + )))
830 eprintf("error mallocing pixel_ht\n");
834 int bin_insert_pixel_ht_entry
835 ( struct bin_pixel_ht_t
* ht
,
836 struct bin_pixel_ht_entry_t
* ht_entry
843 bin_process_frameboxes
845 struct bin_ht_header_t
* ht
,
846 struct bin_pixel_node_t
* default_pixel_list
848 { struct bin_ht_entry_t ht_entry
;
849 struct bin_pixel_ht_t
* ht
;
850 struct bin_pixel_node_t
* pixeliter
;
853 /* create the default ht */
855 for(pixeliter
= default_pixel_list
; pixeliter
!= NULL
; pixeliter
= pixeliter
->next
)
857 ht_entry
.key
= pixel_iter
->data
.ref
;
858 bin_insert_pixel_ht_entry(&ht
, ;
864 /* Insert variants into hash table to overwrite olink insertions*/
865 for ( fiter
= ir_set_framebox(set
); fiter
!= NULL
; fiter
= ir_setdata_nextsib(fiter
))
866 { fseek(binaryout
, 0, SEEK_END
);
867 ht_entry
.key
= NAMEHASH(ir_setdata_name(fiter
), ht
->entries
);
868 /* create the copy, pass the copy */
869 ht_entry
.value
= bin_process_framebox(set
, fiter
, default_pixel_list
);
870 bin_insert_var_ht_entry(ht
->start
, ht
->entries
* sizeof(ht_entry
), &ht_entry
, 1);
874 /* Determine clipping based on image height/width and frame height/width */
876 void bin_set_img_info
877 ( struct bin_img_info_t
* img_info
,
878 ir_setdata frame_data
880 { ir_frameinfo frameinfo
;
881 frameinfo
= ir_framedata_frameinfo(frame_data
);
882 img_info
->fwidth
= frameinfo
->w
;
883 img_info
->fheight
= frameinfo
->h
;
884 img_info
->unaligned_height
= img_info
->height
% img_info
->fheight
;
885 img_info
->unaligned_width
= img_info
->width
% img_info
->fwidth
;
888 /* |-----------------------------|
890 |-----------------------------|
891 | pixel data for frame1 - n |
892 |-----------------------------|
893 | op data for frame1 - n |
894 |-----------------------------| */
897 //TODO: THIS SHOULD THE SET SPEC, NOT THE FRAMEBOX NAME
898 #define GENERATE_FILENAME(_N) ((char*) u8_strcat(_N, png_suffix))
900 ( ir_setdata framebox
,
902 struct bin_pixel_node_t
* default_pixel_list
904 { struct bin_img_info_t mapsheet_info
, framesheet_info
;
905 int num_mapchannels
, num_framechannels
, x
;
906 struct bin_frame_header_t header
;
908 RGBA_t
* mapdata
, * framedata
;
909 uint8_t* png_suffix
= ".png";
910 struct bin_pixel_node_t
* map_pixel_list
;
912 facing_start
= ftell(binaryout
);
915 /* Set up data pointers to mapsheet and framesheet, as well as their image infos */
916 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);
917 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);
918 bin_set_img_info(&framesheet_info
, ir_framebox_framesheet(framebox
, SFACE
));
919 bin_set_img_info(&mapsheet_info
, ir_framebox_mapsheet(framebox
, SFACE
));
921 /* Allocate space for header */
922 fseek(binaryout
, sizeof(header
), SEEK_CUR
);
925 /* Output framesheet */
926 if(!stbi_write_png(binaryout
, framesheet_info
.width
, framesheet_info
.height
, 4, mapdata
, framesheet_info
.fwidth
))
927 eprintf("error writing out framesheet\n");
929 /* Output framesheet header */
930 header
.width
= framesheet_info
.fwidth
;
931 header
.height
= framesheet_info
.fheight
;
932 header
.frames
= framesheet_info
.width
/ framesheet_info
.fwidth
; //TODO: division is bad
933 header
.op_start
= ftell(binaryout
);
934 fseek(binaryout
, facing_start
, SEEK_SET
);
935 fwrite(&header
, sizeof(header
), 1, binaryout
);
936 fseek(binaryout
, 0, SEEK_END
);
941 /* Assuming that fheight = image height */
942 /* For each mapframe in mapsheet */
943 for ( x
= 0; x
< header
.frames
; x
++)
944 { map_pixel_list
= bin_mapframe_to_pixel_list(mapsheet_info
, 0, x
* mapsheet_info
.fwidth
, mapdata
);
945 if(!bin_process_map_pixel_list(default_pixel_list
, map_pixel_list
))
946 eprintf("error processing map pixel list\n");
947 bin_output_pixel_list(map_pixel_list
);
948 mapdata
= mapsheet_info
.fwidth
* x
; //do we do this in mapframe to pixellist?
958 /* pixel_list == ops, output up to fwidth amount of them */
960 bin_output_pixel_list(struct bin_pixel_node_t
* map_pixel_list
);
962 /* TODO: Please rename all the functions jhc*/
964 void bin_number_pixel_list
965 ( struct bin_pixel_node_t
* pixel_list
)
967 struct bin_pixel_node_t
* iter
;
969 { iter
->data
.attach_idx
= num
++;
974 /* Assuming at this point that map_pixel_list is valid */
976 int bin_set_map_pixel_list_attach_idxs
977 ( struct bin_pixel_node_t
* default_pixel_list
,
978 struct bin_pixel_node_t
* map_pixel_list
980 { struct bin_pixel_node_t
* mapiter
, defaultiter
;
981 mapiter
= map_pixel_list
;
982 defaultiter
= default_pixel_list
;
983 while (mapiter
&& defaultiter
)
984 { /* if mapiter.data.ref == defaultiter.data.ref, assign mapiter index_idx to defaultiter */
985 if (mapiter
.data
.ref
== defauliter
.data
.ref
)
986 { defaultiter
.data
.attach_idx
= mapiter
.data
.attach_idx
;
987 mapiter
= mapiter
->next
;
988 defaultiter
= defaultiter
->next
;
991 defaultiter
= defaultiter
->next
;
994 int bin_ref_in_pixel_list
995 ( struct bin_pixel_node_t
* pixel_list
,
998 { struct bin_pixel_node_t
* iter
;
999 for(iter
= pixel_list
; iter
!= NULL
; iter
= iter
->next
)
1000 { if(ref
== iter
.data
.ref
)
1006 struct bin_pixel_ht_t
*
1007 #define PIXEL_HT_SIZE() (sizeof(bin_pixel_ht_entry_t) * SYS_PAGESIZE + sizeof(bin_pixel_ht_t*))
1010 { struct bin_pixel_ht_t
* ht
;
1012 if(!(ht
= (struct bin_pixel_ht_t
*) malloc( PIXEL_HT_SIZE())))
1013 eprintf("Memory allocation error in bin_pixel_ht_alloc\n");
1014 memset(ht
, 0, PIXEL_HT_SIZE());
1020 bin_insert_pixel_ht_entry
1021 ( struct bin_pixel_ht_t
** ht
,
1022 struct bin_pixel_ht_entry_t
* ht_entry
1025 *ht
= bin_pixel_ht_alloc();
1029 /* Determines if the multiset map_pixel is a subset of the multiset default pixel list.
1030 0 if invalid, 1 if valid */
1032 int bin_valid_map_pixel_list
1033 ( struct bin_pixel_ht_t
* default_ht
,
1034 struct bin_pixel_node_t
* map_pixel_list
1036 { struct bin_pixel_node_t
* mapiter
, *defaultiter
, *tmpdefault
, tmpmap
;
1038 defaultiter
= default_pixel_list
;
1039 mapiter
= map_pixel_list
;
1041 while(mapiter
!= NULL
)
1043 /* compare against the default ht */
1044 /* decrement the value of the found ht_entry */
1045 /* if(value == 0) */
1056 int bin_process_map_pixel_list
1057 ( struct bin_pixel_node_t
* default_pixel_list
,
1058 struct bin_pixel_node_t
* map_pixel_list
1060 { /* Determine if pixel_list is valid */
1061 if(!bin_valid_map_pixel_list(default_pixel_list
, map_pixel_list
))
1064 /* Determine attach_idx of each pixel, as compared to default pixel list */
1070 bin_assign_pixel_idxs
1071 ( struct bin_pixel_node_t
* pixel_list
)
1075 /* Insert pixel(s) into the list, z sorted */
1076 /* number the pixels as you insert them */
1077 struct bin_pixel_node_t
*
1078 bin_insert_node_into_list
1079 ( struct bin_pixel_node_t
** pixel_list_root
,
1080 struct bin_pixel_node_t
* pixel_node
1082 { struct bin_pixel_node_t
** head_node
;
1084 head_node
= pixel_list_root
;
1086 while(*head_node
!= NULL
&& head_node
->data
.ref
< pixel_node
->data
.ref
)
1087 head_node
= &((*head_node
)->next
);
1089 pixel_node
->next
= *head_node
;
1090 *head_node
= pixel_node
;
1092 return pixel_list_root
;
1097 /* Returns the non null pixels of a single mapframe (unaligned or not)
1098 given any height and width */
1099 struct bin_pixel_node_t
*
1100 bin_mapframe_to_pixel_list
1101 ( struct bin_img_info_t
* img_info
,
1106 { int j
, i
, fheight
, fwidth
, fhsize
, fwsize
;
1108 struct bin_pixel_node_t
* pixel_list
,* pixel_node
;
1112 /* if frame clips, process unclippign frames */
1114 fwsize
= img_info
->unaligned_width
? img_info
->unaligned_width
: img_info
->fwidth
;
1115 fhsize
= img_info
->unaligned_height
? img_info
->unaligned_height
: img_info
->fwidth
;
1118 fwidth
= img_info
->fwidth
;
1119 fheight
= img_info
->fheight
;
1122 /* Process the map*/
1123 for (i
= init_height
; i
< fhsize
; i
++)
1124 { for ( j
= init_width
; j
< fwsize
; j
++ )
1125 { if (p
= data
[i
*img_info
->width
+j
])
1126 { pixel_node
= struct_alloc(bin_pixel_node_t
);
1127 /* get ref from 4 bytes of data */
1128 pixel_node
->data
.ref
= (*p
) >> 8;
1129 /* bitshift by ? to get Z */
1130 pixel_node
->data
.z
= (*p
& 0xFF);
1132 pixel_node
->data
.x
= j
;
1133 pixel_node
->data
.y
= i
;
1134 pixel_node
->data
.num
= 0;
1135 pixel_list
= bin_insert_node_into_list(&pixel_list
, pixel_node
);
1144 int bin_pixel_list_len
1145 ( struct bin_pixel_node_t
* pl
)
1146 { struct bin_pixel_node_t
* plp
;
1156 /* TODO: what are the qualifications for the default pixel list? len and __? */
1157 struct bin_pixel_node_t
*
1158 bin_cmp_default_pixel_lists
1159 ( struct bin_pixel_node_t
* pl1
,
1160 struct bin_pixel_node_t
* pl2
1162 { struct bin_pixel_node_t
* pl1p
, * pl2p
;
1163 int i
, pl1_len
, pl2_len
;
1167 pl1_len
= bin_pixel_list_len(pl1
);
1168 pl2_len
= bin_pixel_list_len(pl2
);
1170 if (pl1_len
> pl2_len
)
1172 else if (pl1_len
< pl2_len
)
1174 /* pl1 == pl2, make sure that all refs are the same */
1175 /* TODO: what type of warning/error handling should occur here? */
1176 for (i
= 0; i
< pl1_len
; i
++)
1177 { if (pl1p
->data
.ref
!= pl2p
->data
.ref
)
1178 eprintf("Error in determining default pixel list\n");
1182 return pl1
; //doesnt matter which one you return
1185 /* Find default framebox, based on the framebox with the most attachments*/
1186 /* Search through first frame of S of each framebox */
1187 struct bin_pixel_node_t
*
1188 bin_find_default_pixel_list
1191 struct bin_pixel_node_t
* default_pixel_list
, * curr_pixel_list
;
1194 struct bin_img_info_t img_info
;
1196 for (fiter
= ir_set_framebox(set
); fiter
!= NULL
; fiter
= ir_setdata_nextsib(fiter
))
1197 { /* TODO: Stringify the frame name with .png? */
1198 /* TODO: Add directory changing */
1199 data
= (RGBA_t
*) stbi_load(ir_setdata_name((ir_setdata
) ir_framebox_mapsheet(fiter
,SFACE
) ), &img_info
.width
, &img_info
.width
, &num_channels
, 0);
1200 bin_set_img_info(&img_info
, ir_framebox_mapsheet(fiter
, SFACE
));
1201 curr_pixel_list
= bin_mapframe_to_pixel_list(&img_info
, 0, 0, data
);
1202 default_pixel_list
= bin_cmp_default_pixel_lists(curr_pixel_list
, default_pixel_list
);
1207 return default_pixel_list
;