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
13 #define eprintf_callback(...) exit(EXIT_FAILURE)
18 #define XXH_PRIVATE_API
19 #include "../xxHash/xxhash.h"
20 #define STB_IMAGE_IMPLEMENTATION
21 #include "../stb/stb_image.h"
22 #define STB_IMAGE_WRITE_IMPLEMENTATION
23 #include "../stb/stb_image_write.h"
26 void ir_binout_init(struct ir_class_t
*);
28 /* Memory Allocation */
29 #define struct_alloc(_T) ((struct _T*) stack_alloc(&datapages, sizeof(struct _T)))
31 struct pagelist_t linkpages
, datapages
, plinkpages
;
33 enum model_type
{ SS
};
34 /* Binaryout out structure definitions */
35 struct bin_img_info_t
{
38 int fwidth
; //map and frame width
39 int fheight
; //map and frame height
43 struct bin_ht_header_t
{
47 struct bin_ht_entry_t
{
51 struct bin_class_header_t
{
52 struct bin_ht_header_t child_ht
;
53 struct bin_ht_header_t rootset_ht
;
56 struct bin_set_header_t
{
57 struct bin_ht_header_t child_ht
;
58 long sdat_start
; //points to setdata_header
61 struct bin_setdata_header_t
{
62 struct bin_ht_header_t variant_ht
;
65 struct bin_model_header_t
{ //one for each framebox, currently
66 long facing_array_start
;
69 struct bin_frame_header_t
{
81 struct bin_pixel_node_t
{
82 struct bin_pixel_node_t
* next
;
83 struct bin_pixel_t data
;
85 struct bin_attachment_header_t
{
86 int num_attachment_lists
;
89 struct bin_attachment_t
{
93 /* Read out of the als, after first ir pass, resolves the
94 attach_pos of the src-set that created the attachment_list
95 to the header that describes the attachment_list */
96 struct bin_attachment_list_t
{
98 struct bin_attachment_t
** attachments
;
102 struct bin_attachment_list_t
**attachment_stack
, **asp
; //attachment_stack, attachment_stack_pointer
106 #define NAMEHASH(name, domain) (XXH32(name, u8_strlen(name), 0XCEED ) & domain)
114 for (iter
= ir_set_framebox(set
); iter
!= NULL
; iter
= ir_setdata_nextsib(iter
))
120 int bin_class_sibcount
125 for (iter
= class; iter
!= NULL
; iter
= ir_class_nextsib(iter
))
136 for (iter
= set
; iter
!= NULL
; iter
= ir_set_nextsib(iter
))
141 /* Given a position and a size, checks if the bytes are null and returns
142 the file position to where it started. 1 if not null, 0 if null*/
143 /* TODO: Determine why fseeking file past end sets bytes to -1, and not 0 */
145 int bytes_null( int len
, int pos
)
147 { if(fgetc(binaryout
) > 0)
148 { fseek(binaryout
, pos
, SEEK_SET
);
152 fseek(binaryout
, pos
, SEEK_SET
);
155 /* Checks if the key at entrypos is the same as the parameter key. Returns
156 1 if so, 0 if not. */
158 int bin_keys_identical
163 fseek(binaryout
, entry_pos
, SEEK_SET
);
164 fscanf(binaryout
, "%u", &curr_key
);
171 typedef RGBA_t
uint32_t;
173 long bin_traverse_class(ir_class
);
174 /* Takes root class and begins processing */
176 ir_binout_init(ir_class root_class
)
177 { binaryout
= fopen("binaryout", "w+");
178 asp
= attachment_stack
;
179 pagelist_init(datapages
, (size_t) SYS_PAGESIZE
);
180 pagelist_init(linkpages
, (size_t) SYS_PAGESIZE
);
181 bin_traverse_class(root_class
);
184 #define ENTRY_OCCUPIED() (bytes_null(sizeof(ht_entry->key), entry_pos))
185 #define WRITE_ENTRY() do { \
186 if(fseek(binaryout, entry_pos, SEEK_SET) == -1) wprintf("fseek failed with %s", strerror(errno)); \
187 fwrite(&ht_entry, sizeof ht_entry, 1, binaryout); \
189 #define LOOP_ENTRY(_HTSTART) (entry_pos = _HTSTART)
190 #define INC_ENTRY() do { \
191 entry_pos += sizeof(ht_entry); \
192 if(fseek(binaryout, entry_pos, SEEK_SET) == -1) eprintf("fseek failed with %s", strerror(errno)); \
194 #define HT_END(_HTEND) (entry_pos >= _HTEND) //just in case at last entry
196 /* TODO: Should overwrite be a default? */
200 struct bin_ht_entry_t
* ht_entry
,
203 { long entry_pos
, ht_end
;
205 ht_end
= ht_start
+ ht_size
;
206 entry_pos
= ht_start
+ sizeof(ht_entry
) * ht_entry
->key
;
207 fseek(binaryout
, entry_pos
, SEEK_SET
);
209 if (!ENTRY_OCCUPIED())
210 { uprintf("key not occupied\n");
213 while( ENTRY_OCCUPIED() )
215 { if(bin_keys_identical(entry_pos
, ht_entry
->key
))
218 { eprintf("error in hashtable insertion, keys are identical");
222 LOOP_ENTRY(ht_start
);
233 |--------------------|
235 |--------------------|
237 |--------------------|
239 |--------------------|
240 | classchild header |
244 long bin_traverse_set(ir_set
);
246 #define HT_INIT(_START, _SIZE, _INIT_ENTRIES) do { \
247 _SIZE = _INIT_ENTRIES ? (_INIT_ENTRIES * (sizeof(struct bin_ht_entry_t) << 1)): 0; \
248 _START = ftell(binaryout); \
249 fseek(binaryout, _SIZE, SEEK_CUR); \
255 struct bin_class_header_t class_header
;
256 struct bin_ht_entry_t ht_entry
;
257 long class_start
, classht_start
, classht_size
, rootsetht_start
, rootsetht_size
;
258 int num_csibs
, num_ssibs
;
261 class_start
= ftell(binaryout
);
262 class_name
= ir_class_name(class);
264 num_csibs
= bin_class_sibcount(class);
265 num_ssibs
= bin_set_sibcount(ir_class_rootset(class));
267 /* alloc space (before hash tables) for class header */
268 class_header
.namelen
= u8_strlen(class_name
);
269 fseek(binaryout
, class_start
+ sizeof(class_header
) + class_header
.namelen
,SEEK_SET
);
271 HT_INIT(classht_start
, classht_size
, num_csibs
);
272 HT_INIT(rootsetht_start
, rootsetht_size
, num_ssibs
);
274 /* TODO: Figure out generic way to output headers */
275 /* populate class header */
276 class_header
.child_ht
.entries
= num_csibs
;
277 class_header
.child_ht
.start
= classht_start
;
278 class_header
.rootset_ht
.entries
= num_ssibs
;
279 class_header
.rootset_ht
.start
= rootsetht_start
;
280 fseek(binaryout
, class_start
, SEEK_SET
); //seek back to where we allocated header
281 fwrite(&class_header
, sizeof(class_header
), 1, binaryout
);
282 fwrite(class_name
, class_header
.namelen
, 1, binaryout
);
284 /* Start populating root_set hash table */
285 for ( siter
= ir_class_rootset(class); siter
!= NULL
; siter
= ir_set_nextsib(siter
))
286 { fseek(binaryout
, 0, SEEK_END
);
287 ht_entry
.key
= NAMEHASH(ir_set_name(siter
), num_ssibs
<< 1);
288 ht_entry
.value
= bin_traverse_set(siter
);
289 bin_insert_ht_entry(rootsetht_start
, rootsetht_size
, &ht_entry
, 0);
292 /* Start populating class child hash table */
293 for ( citer
= ir_class_nextchild(class); citer
!= NULL
; citer
= ir_class_nextsib(citer
))
294 { if(chdir((char*) class_name
))
295 eprintf("CHDIR %U from %s\n",(char*) class_name
,getcwd(NULL
,255));
296 fseek(binaryout
, 0, SEEK_END
);
297 ht_entry
.key
= NAMEHASH(ir_class_name(citer
), num_csibs
<< 1);
298 ht_entry
.value
= bin_traverse_class(citer
);
299 bin_insert_ht_entry(classht_start
, classht_size
, &ht_entry
, 0);
301 eprintf("CHDIR ..\n");
307 long bin_process_sdat( ir_set
);
310 |-----------------| |
312 |-----------------| |
313 ---| setchild ht |<--
314 | |-----------------|
315 |->| setchild header |
323 struct bin_set_header_t header
;
324 struct bin_ht_entry_t ht_entry
;
325 int num_child
, setname_len
;
326 long childht_start
, childht_size
, set_start
;
329 set_start
= ftell(binaryout
);
330 set_name
= ir_set_name(set
);
332 /* alloc space for set header */
333 setname_len
= u8_strlen(set_name
);
334 fseek(binaryout
, sizeof(struct bin_set_header_t
) + setname_len
, SEEK_CUR
);
336 /* process the set data */
337 header
.sdat_start
= bin_process_sdat(set
);
339 /* Setup child hash table for current sets children */
340 num_child
= bin_set_sibcount(ir_set_nextchild(set
));
341 HT_INIT(childht_start
, childht_size
, num_child
);
343 /* populate header, write to file */
344 header
.child_ht
.entries
= num_child
;
345 header
.child_ht
.start
= childht_start
;
346 fseek(binaryout
, set_start
, SEEK_SET
);
347 fwrite(&header
, sizeof(struct bin_set_header_t
), 1, binaryout
);
348 fwrite(set_name
, setname_len
, 1, binaryout
);
350 for(iter
= ir_set_nextchild(set
); iter
!= NULL
; iter
= ir_set_nextsib(iter
))
351 { fseek(binaryout
, 0, SEEK_END
);
352 ht_entry
.key
= NAMEHASH(ir_set_name(iter
), num_child
<< 1);
353 ht_entry
.value
= bin_traverse_set(iter
);
354 bin_insert_ht_entry(childht_start
, childht_size
, &ht_entry
, 0);
358 ir_set_assign_fpos(set
, set_start
);
372 | 1st variant data | -- variant == framebox
380 void bin_insert_links(struct bin_processed_lists_t
*, struct bin_ht_header_t
*, long);
381 struct bin_pixel_node_t
* bin_find_default_pixel_list(ir_set
);
382 void bin_process_frameboxes(ir_set
, struct bin_ht_header_t
*, struct bin_pixel_node_t
*);
383 int bin_process_links(ir_set
, ir_setdata
);
384 int bin_process_dlinks(struct bin_processed_lists_t
*);
386 /* Init the variant hash table for the set, process the sets links and add them to link_stack
387 and variant hash table, and then output the actual framedata */
391 { struct bin_setdata_header_t header
;
392 struct bin_attachment_list_t attachment_list
;
393 struct bin_pixel_node_t
*default_pixel_list
;
394 struct bin_ht_header_t ht_header
;
395 struct bin_processed_links_t
* processed_links_root
;
396 long varht_start
, varht_size
, sdat_start
;
397 int num_entries
, num_links
;
399 sdat_start
= ftell(binaryout
);
401 /* Alloc position for sdat_header */
402 fseek(binaryout
, sizeof(struct bin_setdata_header_t
), SEEK_CUR
);
404 /* set up root for processed_links */
405 processed_links_root
= stack_alloc(&plinkpages
, bin_processed_links_t
);
406 processed_links_root_val
->mlink_len
= processed_links_root
->vlink_len
= 0;
407 processed_links_root
= bin_process_links(set
, processed_links_root
);
409 num_links
= processed_links_root
->mlink_len
+ processed_links_root
->vlink_len
;
411 num_entries
= bin_set_varcount(set
) + num_links
;
413 HT_INIT(varht_start
, varht_size
, num_entries
);
415 /* Populate the sdat_header */
416 fseek(binaryout
, 0, sdat_start
);
417 header
.variant_ht
.start
= ht_header
.start
= varht_start
;
418 header
.variant_ht
.entries
= ht_header
.entries
= num_entries
;
419 attachment_list
.filepos
= header
.attach_pos
= ftell(binaryout
) + sizeof(varht_start
) + sizeof(num_entries
);
420 fwrite(&header
, sizeof(header
), 1, binaryout
);
421 fseek(binaryout
, 0, SEEK_END
);
424 bin_process_dlinks(processed_links_root
);
427 /* Determine the default pixel list for all of the frameboxes */
428 default_pixel_list
= bin_find_default_pixel_list(set
);
429 /* Output each framebox, and insert it into the variant hash table */
430 bin_process_frameboxes(set
, &ht_header
, default_pixel_list
);
432 /* insert the links that were processed into the variant hash table */
433 bin_insert_links(processed_links_root
, &ht_header
, attachment_list
.filepos
);
435 /* TODO: Convert the default pixel list to an attachment_list and then push the */
436 /* sdats attachment_list onto the attachment_stack so it can be procesed */
438 /* free plinkpages and datapages */
444 void bin_process_dlinks
445 ( struct bin_processed_links_t
* processed_links
)
446 { struct bin_linklist_t
* olink_iter
;
448 for( dlink_iter
= processed_links
->dlink_list
; dlink_iter
!= NULL
; dlink_iter
= dlink_iter
->next
)
449 { /* Construct its fully qualified name based on ?*/
450 /* Output an int for its length, and then output the name */
457 struct bin_linklist_t
* bin_linklist_head
458 ( struct bin_linklist_t
* root
)
459 { struct bin_linklist_t
* head
;
466 /* We dont know src_pos at this point because this is still in the control flow
467 of bin_process_links, which determines the number of links, which determines
470 #define PUSH_LINK(_LINK) (*(linkdata*) stack_alloc(&linkpages, sizeof(linkdata)) = _LINK)
473 struct bin_processed_links_t
* processed_links
)
474 { struct bin_processed_links_t
* plp
;
475 struct bin_linklist_t
* vlink_list_head
;
481 vlink_list_head
= bin_linklist_head(processed_links
->vlink_list
);
482 link_name
= ir_setdata_name(vlink
);
484 { plp
= struct_alloc(bin_processed_links_t
);
485 plp
->linkdata
= vlink
;
486 vlink_list_head
->next
= plp
;
487 processed_links
->vlink_len
++;
490 else // linking a variant hash table
491 { trg_set
= ir_linkdata_set(vlink
);
492 for (fiter
= ir_set_framebox(trg_set
); fiter
!= NULL
; fiter
= ir_setdata_nextsib(fiter
))
493 { plp
= struct_alloc(bin_processed_links_t
);
494 new_vlink
= struct_alloc(linkdata
);
495 ir_linkdata_assign_name(new_vlink
,ir_setdata_name(fiter
));
496 ir_linkdata_assign_set(new_vlink
,trg_set
);
497 ir_linkdata_assign_type(new_vlink
,VLINK
);
498 plp
->linkdata
= vlink
;
499 vlink_list_head
->next
= plp
;
500 processed_links
->vlink_len
++;
505 return processed_links
;
509 /* Adds an mlink to the stack_alloc, to be processed later */
513 bin_processed_links_t
* processed_links
515 { uint8_t* mlink_name
;
516 struct bin_processed_links_t
* mlink_list_head
;
518 mlink_list_head
= bin_listlist_head(processed_links
->mlink_list
);
519 mlink_name
= ir_setdata_name(mlink
);
520 plp
= stack_alloc(&linkpages
, bin_linklist_t
);
521 plp
->header
.filepos
= 0; //TBD after resolving the childlist | TODO: attach_pos?
522 if(mlink_name
) plp
->name
= mlink_name
;// TODO: What does a mlink with a name mean? specifying the framebox mapsheet to use?
523 plp
->trg_set
= ir_linkdata_set(mlink
);
524 mlink_list_head
->next
= plp
;
525 processed_links
->mlink_len
++;
527 return processed_links
;
530 /* TODO: implement this */
531 /* Determine if olink is already part of the olink_list.
532 if it is, theres a cycle, return 1. Else return 0. */
536 struct bin_processed_links_t
* processed_links
538 { struct bin_linklist_t
* iter
;
540 olink_set
= ir_linkdata_set(olink
);
541 for( iter
= processed_links
->olink_list
; iter
!= NULL
; iter
= iter
->next
)
542 if(iter
== olink_set
)
547 /* if olink, process target sets frameboxes(turn into vlinks) and its attachment_list (turn into mlink),
548 else its a dlink so just add it to the processed_links list*/
550 void bin_process_olink
552 struct bin_processed_links_t
* processed_links_root
,
555 { struct bin_linklist_t
* link_list_head
;
556 if(trg_set
)) //add olink to list so we can check for cycles
557 { bin_set_frameboxes_vlinks(trg_set
, processed_links_root
); //TODO: implement
558 bin_set_attachmentlist_mlink(trg_set
, processed_links_root
); //TODO: implement
559 link_list_head
= bin_linklist_head(processed_links_root
->olink_list
);
560 link_list_head
->next
= struct_alloc(bin_linklist_t
);
561 link_list_head
->next
->linkdata
= olink
;
563 else // olink is actually a dynamic link
564 { link_list_head
= bin_linklist_head(processed_links_root
->dlink_list
);
565 link_list_head
->next
= struct_alloc(bin_linklist_t
);
566 link_list_head
->next
->linkdata
= olink
;
571 struct bin_linklist_t
;
572 struct bin_linklist_t
573 { struct bin_linklist_t
* next
;
577 struct bin_processed_links_t
578 { struct bin_linklist_t
* vlink_list
;
580 struct bin_linklist_t
* mlink_list
;
582 struct bin_linklist_t
* olink_list
; //keep track of olink cycles
584 struct bin_linklist_t
* dlink_list
;
588 /* Given a set, determine the number of links it has and process each link and
589 then add them to stack_alloc, where they will be popped off and further processed. */
590 struct bin_processed_links_t
* bin_process_links
592 struct bin_processed_links_t
* processed_links_root
;
594 { struct bin_processed_links_t
* returned_val
;
597 for(linkdata
= ir_set_link(src_set
); linkdata
!= NULL
; linkdata
= (linkdata
) ir_setdata_nextsib((ir_setdata
) linkdata
))
598 { switch (ir_linkdata_type(linkdata
)) {
600 if (olink_cycle(linkdata
, processed_links_root
))
601 return processed_links_root
; //TODO: what return value?
602 trg_set
= ir_linkdata_set(linkdata
);
603 bin_process_olink(trg_set
, linkdata
, processed_links_root
);
604 bin_process_links(trg_set
, processed_links_root
);
607 bin_process_vlink(linkdata
, processed_links_root
);
610 bin_process_mlink(linkdata
, processed_links_root
);
612 case ALINK
: //TODO: ?
616 return processed_links_root
;
619 /* Insert both mlinks and vlinks into the link stack, after determining their src_pos. Vlinks
620 have an additional requirement of being added into the variant hash table */
621 #define PUSH_PLINK(_LINK) (*(struct **) stack_alloc(&linkpages, sizeof (_LINK)) = _LINK )
624 ( struct bin_processed_links_t
* links
,
625 struct bin_ht_header_t
* ht
,
628 { struct bin_plink_t
* plp
;
629 struct bin_ht_entry_t ht_entry
;
630 struct link_list_t
* vlinkiter
, mlinkiter
;
634 /* Insert vlinks into hash table, put v/mlinks on link stack to be processed later */
635 for ( vlinkiter
= links
->vlink_root
; vlinkiter
!= NULL
; vlinkiter
= vlinkiter
->next
;)
636 { ht_entry
.key
= NAMEHASH(ir_setdata_name(vlinkiter
->linkdata
), ht
->entries
<< 1);
638 entry_pos
= bin_insert_ht_entry(ht
->start
, ht
->entries
* sizeof(ht_entry
), &ht_entry
, 0);
639 ir_setdata_assign_fpos(vlinkiter
->linkdata
, entry_pos
);
640 PUSH_PLINK(vlinkiter
->linkdata
);
642 for ( mlinkiter
= links
->mlink_root
; mlinkiter
!= NULL
; mlinkiter
= mlinkiter
->next
)
643 { >trg_set
= plp
->trg_set
;
644 plp
->src_pos
= attach_pos
;
647 /* Process dlinks here */
652 long bin_process_facing(ir_setdata
, apc_facing
, struct bin_pixel_node_t
*);
653 /* |-------------------|
655 |-------------------|
657 |-------------------|
658 | SWFACE framesheet |
659 |-------------------|
666 struct bin_pixel_node_t
* default_pixel_list
668 { struct bin_model_header_t header
;
669 long framebox_start
, index_pos
;
672 framebox_start
= ftell(binaryout
);
674 /* insert model header */
676 header
.facing_array_start
= framebox_start
+ sizeof(header
);
677 fwrite(&header
, sizeof(header
), 1, binaryout
);
679 /* Create the index array for framesheet of each direction */
680 for ( i
= SFACE
; i
< FACING_MAX
; i
++)
681 { fseek(binaryout
, 0, SEEK_END
);
682 index_pos
= bin_process_facing(framebox
, i
, default_pixel_list
); //TODO: finish process_direction
683 fseek(binaryout
, header
.facing_array_start
+ i
* sizeof(long), SEEK_SET
);
684 fwrite(&index_pos
, sizeof(long), 1, binaryout
);
687 return framebox_start
;
690 bin_process_frameboxes
692 struct bin_ht_header_t
* ht
,
693 struct bin_pixel_node_t
* default_pixel_list
695 { struct bin_ht_entry_t ht_entry
;
698 /* Insert variants into hash table to overwrite olink insertions*/
699 for ( fiter
= ir_set_framebox(set
); fiter
!= NULL
; fiter
= ir_setdata_nextsib(fiter
))
700 { fseek(binaryout
, 0, SEEK_END
);
701 ht_entry
.key
= NAMEHASH(ir_setdata_name(fiter
), ht
->entries
<< 1);
702 ht_entry
.value
= bin_process_framebox(set
, fiter
, default_pixel_list
);
703 bin_insert_ht_entry(ht
->start
, ht
->entries
* sizeof(ht_entry
), &ht_entry
, 1);
707 /* Determine clipping based on image height/width and frame height/width */
709 void bin_set_img_info
710 ( struct bin_img_info_t
* img_info
,
711 ir_setdata frame_data
713 { ir_frameinfo frameinfo
;
714 frameinfo
= ir_framedata_frameinfo(frame_data
);
715 img_info
->fwidth
= frameinfo
->w
;
716 img_info
->fheight
= frameinfo
->h
;
717 img_info
->unaligned_height
= img_info
->height
% img_info
->fheight
;
718 img_info
->unaligned_width
= img_info
->width
% img_info
->fwidth
;
721 /* |-----------------------------|
723 |-----------------------------|
724 | pixel data for frame1 - n |
725 |-----------------------------|
726 | op data for frame1 - n |
727 |-----------------------------| */
730 #define GENERATE_FILENAME(_N) ((char*) u8_strcat(_N, png_suffix))
732 ( ir_setdata framebox
,
734 struct bin_pixel_node_t
* default_pixel_list
736 { struct bin_img_info_t mapsheet_info
, framesheet_info
;
737 int num_mapchannels
, num_framechannels
, x
;
738 struct bin_frame_header_t header
;
740 RGBA_t
* mapdata
, * framedata
;
741 uint8_t* png_suffix
= ".png";
742 struct bin_pixel_node_t
* map_pixel_list
;
744 facing_start
= ftell(binaryout
);
747 /* Set up data pointers to mapsheet and framesheet, as well as their image infos */
748 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);
749 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);
750 bin_set_img_info(&framesheet_info
, ir_framebox_framesheet(framebox
, SFACE
));
751 bin_set_img_info(&mapsheet_info
, ir_framebox_mapsheet(framebox
, SFACE
));
753 /* Allocate space for header */
754 fseek(binaryout
, sizeof(header
), SEEK_CUR
);
757 /* Output framesheet */
758 if(!stbi_write_png(binaryout
, framesheet_info
.width
, framesheet_info
.height
, 4, mapdata
, framesheet_info
.fwidth
))
759 eprintf("error writing out framesheet\n");
761 /* Output framesheet header */
762 header
.width
= framesheet_info
.fwidth
;
763 header
.height
= framesheet_info
.fheight
;
764 header
.frames
= framesheet_info
.width
/ framesheet_info
.fwidth
; //TODO: division is bad
765 header
.op_start
= ftell(binaryout
);
766 fseek(binaryout
, facing_start
, SEEK_SET
);
767 fwrite(&header
, sizeof(header
), 1, binaryout
);
768 fseek(binaryout
, 0, SEEK_END
);
771 /* Assuming that fheight = image height */
772 /* For each mapframe in mapsheet */
773 for ( x
= 0; x
< header
.frames
; x
++)
774 { map_pixel_list
= bin_map_to_pixel_list(mapsheet_info
, 0, x
* mapsheet_info
.fwidth
, data
);
775 if(!bin_process_map_pixel_list(default_pixel_list
, map_pixel_list
))
776 eprintf("error processing map pixel list\n");
777 bin_output_pixel_list(map_pixel_list
);
778 data
+= mapsheet_info
.fwidth
;
781 /* Determine pixel_list */
783 /* Output pixel_list */
790 /* TODO: Please rename all the functions jhc*/
792 void bin_number_pixel_list
793 ( struct bin_pixel_node_t
* pixel_list
)
795 struct bin_pixel_node_t
* iter
;
797 { iter
.data
.attach_idx
= num
++;
802 /* Assuming at this point that map_pixel_list is valid */
804 int bin_set_map_pixel_list_attach_idxs
805 ( struct bin_pixel_node_t
* default_pixel_list
,
806 struct bin_pixel_node_t
* map_pixel_list
808 { struct bin_pixel_node_t
* mapiter
, defaultiter
;
809 mapiter
= map_pixel_list
;
810 defaultiter
= default_pixel_list
;
811 while (mapiter
&& defaultiter
)
812 { /* if mapiter.data.ref == defaultiter.data.ref, assign mapiter index_idx to defaultiter */
813 if (mapiter
.data
.ref
== defauliter
.data
.ref
)
814 { defaultiter
.data
.attach_idx
= mapiter
.data
.attach_idx
;
815 mapiter
= mapiter
->next
;
816 defaultiter
= defaultiter
->next
;
819 defaultiter
= defaultiter
->next
;
823 /* map_pixel_list cannot have more pixels. for all of its pixels,
824 the refs must be represented in default pixel list. 0 if invalid, 1 if valid */
826 int bin_valid_map_pixel_list
827 ( struct bin_pixel_node_t
* default_pixel_list
,
828 struct bin_pixel_node_t
* map_pixel_list
830 { struct bin_pixel_node_t
* mapiter
, defaultiter
;
831 defaultiter
= default_pixel_list
;
832 /* check length of each to make sure default < max */
833 /* for each pixel node in default and map */
835 { for( mapiter
= map_pixel_list
; mapiter
!= NULL
; mapiter
= mapiter
->next
)
841 if(!mapiter
&& defaultiter
) //defaultiter is longer so error!
850 int bin_process_map_pixel_list
851 ( struct bin_pixel_node_t
* default_pixel_list
,
852 struct bin_pixel_node_t
* map_pixel_list
854 { /* Determine if pixel_list is valid */
856 /* Determine attach_idx of each pixel, as compared to default pixel list */
861 bin_assign_pixel_idxs
862 ( struct bin_pixel_node_t
* pixel_list
)
866 /* Insert pixel(s) into the list, z sorted */
867 /* number the pixels as you insert them */
868 struct bin_pixel_node_t
*
869 bin_insert_node_into_list
870 ( struct bin_pixel_node_t
* pixel_list_root
,
871 struct bin_pixel_node_t
* pixel_node
873 { struct bin_pixel_node_t
* head_node
, * prev_node
;
876 if(pixel_list_root
== NULL
)
877 { pixel_list_root
= pixel_node
;
880 prev_node
= head_node
= pixel_list_root
;
881 while(head_node
!= NULL
)
882 { if(pixel_node
->data
.z
> head_node
->data
.z
)
883 { if(head_node
->next
)
884 { prev_node
= head_node
;
885 head_node
= head_node
->next
;
888 { head_node
->next
= pixel_node
;
892 else if (pixel_node
->data
.z
< head_node
->data
.z
|| pixel_node
->data
.z
== head_node
->data
.z
)
893 { prev_node
->next
= pixel_node
;
894 pixel_node
->next
= head_node
;
899 return pixel_list_root
;
904 /* Returns the non null pixels of a single map */
905 /* TODO: Finish this */
906 struct bin_pixel_node_t
*
907 bin_mapframe_to_pixel_list
908 ( struct bin_img_info_t
* img_info
,
913 { int x
, y
, fheight
, fwidth
;
914 struct bin_pixel_node_t
* pixel_list
,* pixel_node
;
918 /* if frame clips, process unclippign frames */
919 if( img_info
->unaligned_width
)
920 { if(img_info
->height
< img_info
->fheight
)
921 fheight
= img_info
->height
;
923 fheight
= img_info
->fheight
;
926 fheight
= img_info
->fheight
;
927 if (img_info
->unaligned_height
)
928 { if(img_info
->width
< img_info
->fwidth
)
929 fwidth
= img_info
->width
;
931 fwidth
= img_info
->fwidth
;
934 fwidth
= img_info
->fwidth
;
938 for (y
= 0; y
< fheight
; y
++)
939 { for ( x
= 0; x
< fwidth
; x
++ )
941 { pixel_node
= struct_alloc(bin_pixel_node_t
);
942 /* get ref from 4 bytes of data */
943 pixel_node
->data
.ref
= (*data
) >> 8;
944 /* bitshift by ? to get Z */
945 pixel_node
->data
.z
= (*data
& 0xFF);
947 pixel_node
->data
.x
= x
+ init_width
;
948 pixel_node
->data
.y
= y
+ init_width
;
949 pixel_list
= bin_insert_node_into_list(pixel_list
, pixel_node
);
953 data
+= img_info
->width
- img_info
->fwidth
; //stride
959 int bin_pixel_list_len
960 ( struct bin_pixel_node_t
* pl
)
961 { struct bin_pixel_node_t
* plp
;
972 struct bin_pixel_node_t
*
973 bin_cmp_default_pixel_lists
974 ( struct bin_pixel_node_t
* pl1
,
975 struct bin_pixel_node_t
* pl2
977 { struct bin_pixel_node_t
* pl1p
, * pl2p
;
978 int i
, pl1_len
, pl2_len
;
982 pl1_len
= bin_pixel_list_len(pl1
);
983 pl2_len
= bin_pixel_list_len(pl2
);
985 if (pl1_len
> pl2_len
)
987 else if (pl1_len
< pl2_len
)
989 /* pl1 == pl2, make sure that all refs are the same */
990 /* TODO: what type of warning/error handling should occur here? */
991 for (i
= 0; i
< pl1_len
; i
++)
992 { if (pl1p
->data
.ref
!= pl2p
->data
.ref
)
993 eprintf("Error in determining default pixel list\n");
997 return pl1
; //doesnt matter which one you return
1000 /* Find default framebox, based on the framebox with the most attachments*/
1001 /* Search through first frame of S of each framebox */
1002 struct bin_pixel_node_t
*
1003 bin_find_default_pixel_list
1006 struct bin_pixel_node_t
* default_pixel_list
, * curr_pixel_list
;
1009 struct bin_img_info_t img_info
;
1011 for (fiter
= ir_set_framebox(set
); fiter
!= NULL
; fiter
= ir_setdata_nextsib(fiter
))
1012 { /* TODO: Stringify the frame name with .png? */
1013 /* TODO: Add directory changing */
1014 data
= (RGBA_t
*) stbi_load(ir_setdata_name((ir_setdata
) ir_framebox_mapsheet(fiter
,SFACE
) ), &img_info
.width
, &img_info
.width
, &num_channels
, 0);
1015 bin_set_img_info(&img_info
, ir_framebox_mapsheet(fiter
, SFACE
));
1016 curr_pixel_list
= bin_mapframe_to_pixel_list(&img_info
, 0, 0, data
);
1017 default_pixel_list
= bin_cmp_default_pixel_lists(curr_pixel_list
, default_pixel_list
);
1022 return default_pixel_list
;