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
{
48 struct bin_ht_entry_t
{
52 struct bin_class_header_t
{
53 struct bin_ht_header_t child_ht
;
54 struct bin_ht_header_t rootset_ht
;
57 struct bin_set_header_t
{
58 struct bin_ht_header_t child_ht
;
59 long sdat_start
; //points to setdata_header
62 struct bin_setdata_header_t
{
63 struct bin_ht_header_t variant_ht
;
66 struct bin_model_header_t
{ //one for each framebox, currently
67 long facing_array_start
;
70 struct bin_frame_header_t
{
82 struct bin_pixel_node_t
{
83 struct bin_pixel_node_t
* next
;
84 struct bin_pixel_t data
;
86 struct bin_attachment_header_t
{
87 int num_attachment_lists
;
90 struct bin_attachment_t
{
94 /* Read out of the als, after first ir pass, resolves the
95 attach_pos of the src-set that created the attachment_list
96 to the header that describes the attachment_list */
97 struct bin_attachment_list_t
{
99 struct bin_attachment_t
** attachments
;
103 struct bin_attachment_list_t
**attachment_stack
, **asp
; //attachment_stack, attachment_stack_pointer
107 #define NAMEHASH(name, domain) (XXH32(name, u8_strlen(name), 0XCEED ) & domain)
115 for (iter
= ir_set_framebox(set
); iter
!= NULL
; iter
= ir_setdata_nextsib(iter
))
121 int bin_class_sibcount
126 for (iter
= class; iter
!= NULL
; iter
= ir_class_nextsib(iter
))
137 for (iter
= set
; iter
!= NULL
; iter
= ir_set_nextsib(iter
))
142 /* Given a position and a size, checks if the bytes are null and returns
143 the file position to where it started. 1 if not null, 0 if null*/
144 /* TODO: Determine why fseeking file past end sets bytes to -1, and not 0 */
146 int bytes_null( int len
, int pos
)
148 { if(fgetc(binaryout
) > 0)
149 { fseek(binaryout
, pos
, SEEK_SET
);
153 fseek(binaryout
, pos
, SEEK_SET
);
156 /* Checks if the key at entrypos is the same as the parameter key. Returns
157 1 if so, 0 if not. */
159 int bin_keys_identical
164 fseek(binaryout
, entry_pos
, SEEK_SET
);
165 fscanf(binaryout
, "%u", &curr_key
);
172 typedef RGBA_t
uint32_t;
174 long bin_traverse_class(ir_class
);
175 /* Takes root class and begins processing */
177 ir_binout_init(ir_class root_class
)
178 { binaryout
= fopen("binaryout", "w+");
179 asp
= attachment_stack
;
180 pagelist_init(datapages
, (size_t) SYS_PAGESIZE
);
181 pagelist_init(linkpages
, (size_t) SYS_PAGESIZE
);
182 bin_traverse_class(root_class
);
185 #define ENTRY_OCCUPIED() (bytes_null(sizeof(ht_entry->key), entry_pos))
186 #define WRITE_ENTRY() do { \
187 if(fseek(binaryout, entry_pos, SEEK_SET) == -1) wprintf("fseek failed with %s", strerror(errno)); \
188 fwrite(&ht_entry, sizeof ht_entry, 1, binaryout); \
190 #define LOOP_ENTRY(_HTSTART) (entry_pos = _HTSTART)
191 #define INC_ENTRY() do { \
192 entry_pos += sizeof(ht_entry); \
193 if(fseek(binaryout, entry_pos, SEEK_SET) == -1) eprintf("fseek failed with %s", strerror(errno)); \
195 #define HT_END(_HTEND) (entry_pos >= _HTEND) //just in case at last entry
197 /* TODO: Should overwrite be a default? */
201 struct bin_ht_entry_t
* ht_entry
,
204 { long entry_pos
, ht_end
;
206 ht_end
= ht_start
+ ht_size
;
207 entry_pos
= ht_start
+ sizeof(ht_entry
) * ht_entry
->key
;
208 fseek(binaryout
, entry_pos
, SEEK_SET
);
210 if (!ENTRY_OCCUPIED())
211 { uprintf("key not occupied\n");
214 while( ENTRY_OCCUPIED() )
216 { if(bin_keys_identical(entry_pos
, ht_entry
->key
))
219 { eprintf("error in hashtable insertion, keys are identical");
223 LOOP_ENTRY(ht_start
);
234 |--------------------|
236 |--------------------|
238 |--------------------|
240 |--------------------|
241 | classchild header |
245 long bin_traverse_set(ir_set
);
247 #define HT_INIT(_START, _SIZE, _INIT_ENTRIES) do { \
248 _SIZE = _INIT_ENTRIES ? (_INIT_ENTRIES * (sizeof(struct bin_ht_entry_t) << 1)): 0; \
249 _START = ftell(binaryout); \
250 fseek(binaryout, _SIZE, SEEK_CUR); \
256 struct bin_class_header_t class_header
;
257 struct bin_ht_entry_t ht_entry
;
258 long class_start
, classht_start
, classht_size
, rootsetht_start
, rootsetht_size
;
259 int num_csibs
, num_ssibs
;
262 class_start
= ftell(binaryout
);
263 class_name
= ir_class_name(class);
265 num_csibs
= bin_class_sibcount(class);
266 num_ssibs
= bin_set_sibcount(ir_class_rootset(class));
268 /* alloc space (before hash tables) for class header */
269 class_header
.namelen
= u8_strlen(class_name
);
270 fseek(binaryout
, class_start
+ sizeof(class_header
) + class_header
.namelen
,SEEK_SET
);
272 HT_INIT(classht_start
, classht_size
, num_csibs
);
273 HT_INIT(rootsetht_start
, rootsetht_size
, num_ssibs
);
275 /* TODO: Figure out generic way to output headers */
276 /* populate class header */
277 class_header
.child_ht
.entries
= num_csibs
;
278 class_header
.child_ht
.start
= classht_start
;
279 class_header
.rootset_ht
.entries
= num_ssibs
;
280 class_header
.rootset_ht
.start
= rootsetht_start
;
281 fseek(binaryout
, class_start
, SEEK_SET
); //seek back to where we allocated header
282 fwrite(&class_header
, sizeof(class_header
), 1, binaryout
);
283 fwrite(class_name
, class_header
.namelen
, 1, binaryout
);
285 /* Start populating root_set hash table */
286 for ( siter
= ir_class_rootset(class); siter
!= NULL
; siter
= ir_set_nextsib(siter
))
287 { fseek(binaryout
, 0, SEEK_END
);
288 ht_entry
.key
= NAMEHASH(ir_set_name(siter
), num_ssibs
<< 1);
289 ht_entry
.value
= bin_traverse_set(siter
);
290 bin_insert_ht_entry(rootsetht_start
, rootsetht_size
, &ht_entry
, 0);
293 /* Start populating class child hash table */
294 for ( citer
= ir_class_nextchild(class); citer
!= NULL
; citer
= ir_class_nextsib(citer
))
295 { if(chdir((char*) class_name
))
296 eprintf("CHDIR %U from %s\n",(char*) class_name
,getcwd(NULL
,255));
297 fseek(binaryout
, 0, SEEK_END
);
298 ht_entry
.key
= NAMEHASH(ir_class_name(citer
), num_csibs
<< 1);
299 ht_entry
.value
= bin_traverse_class(citer
);
300 bin_insert_ht_entry(classht_start
, classht_size
, &ht_entry
, 0);
302 eprintf("CHDIR ..\n");
308 long bin_process_sdat( ir_set
);
311 |-----------------| |
313 |-----------------| |
314 ---| setchild ht |<--
315 | |-----------------|
316 |->| setchild header |
324 struct bin_set_header_t header
;
325 struct bin_ht_entry_t ht_entry
;
326 int num_child
, setname_len
;
327 long childht_start
, childht_size
, set_start
;
330 set_start
= ftell(binaryout
);
331 set_name
= ir_set_name(set
);
333 /* alloc space for set header */
334 setname_len
= u8_strlen(set_name
);
335 fseek(binaryout
, sizeof(struct bin_set_header_t
) + setname_len
, SEEK_CUR
);
337 /* process the set data */
338 header
.sdat_start
= bin_process_sdat(set
);
340 /* Setup child hash table for current sets children */
341 num_child
= bin_set_sibcount(ir_set_nextchild(set
));
342 HT_INIT(childht_start
, childht_size
, num_child
);
344 /* populate header, write to file */
345 header
.child_ht
.entries
= num_child
;
346 header
.child_ht
.start
= childht_start
;
347 fseek(binaryout
, set_start
, SEEK_SET
);
348 fwrite(&header
, sizeof(struct bin_set_header_t
), 1, binaryout
);
349 fwrite(set_name
, setname_len
, 1, binaryout
);
351 for(iter
= ir_set_nextchild(set
); iter
!= NULL
; iter
= ir_set_nextsib(iter
))
352 { fseek(binaryout
, 0, SEEK_END
);
353 ht_entry
.key
= NAMEHASH(ir_set_name(iter
), num_child
<< 1);
354 ht_entry
.value
= bin_traverse_set(iter
);
355 bin_insert_ht_entry(childht_start
, childht_size
, &ht_entry
, 0);
359 ir_set_assign_fpos(set
, set_start
);
373 | 1st variant data | -- variant == framebox
381 void bin_insert_links(struct bin_processed_lists_t
*, struct bin_ht_header_t
*, long);
382 struct bin_pixel_node_t
* bin_find_default_pixel_list(ir_set
);
383 void bin_process_frameboxes(ir_set
, struct bin_ht_header_t
*, struct bin_pixel_node_t
*);
384 int bin_process_links(ir_set
, ir_setdata
);
385 int bin_process_dlinks(struct bin_processed_lists_t
*);
387 /* Init the variant hash table for the set, process the sets links and add them to link_stack
388 and variant hash table, and then output the actual framedata */
392 { struct bin_setdata_header_t header
;
393 struct bin_attachment_list_t attachment_list
;
394 struct bin_pixel_node_t
*default_pixel_list
;
395 struct bin_ht_header_t ht_header
;
396 struct bin_processed_links_t
* processed_links_root
;
397 long varht_start
, varht_size
, sdat_start
;
398 int num_entries
, num_links
;
400 sdat_start
= ftell(binaryout
);
402 /* Alloc position for sdat_header */
403 fseek(binaryout
, sizeof(struct bin_setdata_header_t
), SEEK_CUR
);
405 /* set up root for processed_links */
406 processed_links_root
= stack_alloc(&plinkpages
, bin_processed_links_t
);
407 processed_links_root_val
->mlink_len
= processed_links_root
->vlink_len
= 0;
408 processed_links_root
= bin_process_links(set
, processed_links_root
);
410 num_links
= processed_links_root
->mlink_len
+ processed_links_root
->vlink_len
;
412 num_entries
= bin_set_varcount(set
) + num_links
;
414 HT_INIT(varht_start
, varht_size
, num_entries
);
416 /* Populate the sdat_header */
417 fseek(binaryout
, 0, sdat_start
);
418 header
.variant_ht
.start
= ht_header
.start
= varht_start
;
419 header
.variant_ht
.entries
= ht_header
.entries
= num_entries
;
420 attachment_list
.filepos
= header
.attach_pos
= ftell(binaryout
) + sizeof(varht_start
) + sizeof(num_entries
);
421 fwrite(&header
, sizeof(header
), 1, binaryout
);
422 fseek(binaryout
, 0, SEEK_END
);
425 bin_process_dlinks(processed_links_root
);
428 /* Determine the default pixel list for all of the frameboxes */
429 default_pixel_list
= bin_find_default_pixel_list(set
);
430 /* Output each framebox, and insert it into the variant hash table */
431 bin_process_frameboxes(set
, &ht_header
, default_pixel_list
);
433 /* insert the links that were processed into the variant hash table */
434 bin_insert_links(processed_links_root
, &ht_header
, attachment_list
.filepos
);
436 /* TODO: Convert the default pixel list to an attachment_list and then push the */
437 /* sdats attachment_list onto the attachment_stack so it can be procesed */
439 /* free plinkpages and datapages */
445 void bin_process_dlinks
446 ( struct bin_processed_links_t
* processed_links
)
447 { struct bin_linklist_t
* olink_iter
;
449 for( dlink_iter
= processed_links
->dlink_list
; dlink_iter
!= NULL
; dlink_iter
= dlink_iter
->next
)
450 { /* Construct its fully qualified name based on ?*/
451 /* Output an int for its length, and then output the name */
458 struct bin_linklist_t
* bin_linklist_head
459 ( struct bin_linklist_t
* root
)
460 { struct bin_linklist_t
* head
;
467 /* We dont know src_pos at this point because this is still in the control flow
468 of bin_process_links, which determines the number of links, which determines
471 #define PUSH_LINK(_LINK) (*(linkdata*) stack_alloc(&linkpages, sizeof(linkdata)) = _LINK)
474 struct bin_processed_links_t
* processed_links
)
475 { struct bin_processed_links_t
* plp
;
476 struct bin_linklist_t
* vlink_list_head
;
482 vlink_list_head
= bin_linklist_head(processed_links
->vlink_list
);
483 link_name
= ir_setdata_name(vlink
);
485 { plp
= struct_alloc(bin_processed_links_t
);
486 plp
->linkdata
= vlink
;
487 vlink_list_head
->next
= plp
;
488 processed_links
->vlink_len
++;
491 else // linking a variant hash table
492 { trg_set
= ir_linkdata_set(vlink
);
493 for (fiter
= ir_set_framebox(trg_set
); fiter
!= NULL
; fiter
= ir_setdata_nextsib(fiter
))
494 { plp
= struct_alloc(bin_processed_links_t
);
495 new_vlink
= struct_alloc(linkdata
);
496 ir_linkdata_assign_name(new_vlink
,ir_setdata_name(fiter
));
497 ir_linkdata_assign_set(new_vlink
,trg_set
);
498 ir_linkdata_assign_type(new_vlink
,VLINK
);
499 plp
->linkdata
= vlink
;
500 vlink_list_head
->next
= plp
;
501 processed_links
->vlink_len
++;
506 return processed_links
;
510 /* Adds an mlink to the stack_alloc, to be processed later */
514 bin_processed_links_t
* processed_links
516 { uint8_t* mlink_name
;
517 struct bin_processed_links_t
* mlink_list_head
;
519 mlink_list_head
= bin_listlist_head(processed_links
->mlink_list
);
520 mlink_name
= ir_setdata_name(mlink
);
521 plp
= stack_alloc(&linkpages
, bin_linklist_t
);
522 plp
->header
.filepos
= 0; //TBD after resolving the childlist | TODO: attach_pos?
523 if(mlink_name
) plp
->name
= mlink_name
;// TODO: What does a mlink with a name mean? specifying the framebox mapsheet to use?
524 plp
->trg_set
= ir_linkdata_set(mlink
);
525 mlink_list_head
->next
= plp
;
526 processed_links
->mlink_len
++;
528 return processed_links
;
531 /* TODO: implement this */
532 /* Determine if olink is already part of the olink_list.
533 if it is, theres a cycle, return 1. Else return 0. */
537 struct bin_processed_links_t
* processed_links
539 { struct bin_linklist_t
* iter
;
541 olink_set
= ir_linkdata_set(olink
);
542 for( iter
= processed_links
->olink_list
; iter
!= NULL
; iter
= iter
->next
)
543 if(iter
== olink_set
)
548 /* if olink, process target sets frameboxes(turn into vlinks) and its attachment_list (turn into mlink),
549 else its a dlink so just add it to the processed_links list*/
551 void bin_process_olink
553 struct bin_processed_links_t
* processed_links_root
,
556 { struct bin_linklist_t
* link_list_head
;
557 if(trg_set
)) //add olink to list so we can check for cycles
558 { bin_set_frameboxes_vlinks(trg_set
, processed_links_root
); //TODO: implement
559 bin_set_attachmentlist_mlink(trg_set
, processed_links_root
); //TODO: implement
560 link_list_head
= bin_linklist_head(processed_links_root
->olink_list
);
561 link_list_head
->next
= struct_alloc(bin_linklist_t
);
562 link_list_head
->next
->linkdata
= olink
;
564 else // olink is actually a dynamic link
565 { link_list_head
= bin_linklist_head(processed_links_root
->dlink_list
);
566 link_list_head
->next
= struct_alloc(bin_linklist_t
);
567 link_list_head
->next
->linkdata
= olink
;
572 struct bin_linklist_t
;
573 struct bin_linklist_t
574 { struct bin_linklist_t
* next
;
578 struct bin_processed_links_t
579 { struct bin_linklist_t
* vlink_list
;
581 struct bin_linklist_t
* mlink_list
;
583 struct bin_linklist_t
* olink_list
; //keep track of olink cycles
585 struct bin_linklist_t
* dlink_list
;
589 /* Given a set, determine the number of links it has and process each link and
590 then add them to stack_alloc, where they will be popped off and further processed. */
591 struct bin_processed_links_t
* bin_process_links
593 struct bin_processed_links_t
* processed_links_root
;
595 { struct bin_processed_links_t
* returned_val
;
598 for(linkdata
= ir_set_link(src_set
); linkdata
!= NULL
; linkdata
= (linkdata
) ir_setdata_nextsib((ir_setdata
) linkdata
))
599 { switch (ir_linkdata_type(linkdata
)) {
601 if (olink_cycle(linkdata
, processed_links_root
))
602 return processed_links_root
; //TODO: what return value?
603 trg_set
= ir_linkdata_set(linkdata
);
604 bin_process_olink(trg_set
, linkdata
, processed_links_root
);
605 bin_process_links(trg_set
, processed_links_root
);
608 bin_process_vlink(linkdata
, processed_links_root
);
611 bin_process_mlink(linkdata
, processed_links_root
);
613 case ALINK
: //TODO: ?
617 return processed_links_root
;
620 /* Insert both mlinks and vlinks into the link stack, after determining their src_pos. Vlinks
621 have an additional requirement of being added into the variant hash table */
622 #define PUSH_PLINK(_LINK) (*(struct **) stack_alloc(&linkpages, sizeof (_LINK)) = _LINK )
625 ( struct bin_processed_links_t
* links
,
626 struct bin_ht_header_t
* ht
,
629 { struct bin_plink_t
* plp
;
630 struct bin_ht_entry_t ht_entry
;
631 struct link_list_t
* vlinkiter
, mlinkiter
;
635 /* Insert vlinks into hash table, put v/mlinks on link stack to be processed later */
636 for ( vlinkiter
= links
->vlink_root
; vlinkiter
!= NULL
; vlinkiter
= vlinkiter
->next
;)
637 { ht_entry
.key
= NAMEHASH(ir_setdata_name(vlinkiter
->linkdata
), ht
->entries
<< 1);
639 entry_pos
= bin_insert_ht_entry(ht
->start
, ht
->entries
* sizeof(ht_entry
), &ht_entry
, 0);
640 ir_setdata_assign_fpos(vlinkiter
->linkdata
, entry_pos
);
641 PUSH_PLINK(vlinkiter
->linkdata
);
643 for ( mlinkiter
= links
->mlink_root
; mlinkiter
!= NULL
; mlinkiter
= mlinkiter
->next
)
644 { >trg_set
= plp
->trg_set
;
645 plp
->src_pos
= attach_pos
;
648 /* Process dlinks here */
653 long bin_process_facing(ir_setdata
, apc_facing
, struct bin_pixel_node_t
*);
654 /* |-------------------|
656 |-------------------|
658 |-------------------|
659 | SWFACE framesheet |
660 |-------------------|
667 struct bin_pixel_node_t
* default_pixel_list
669 { struct bin_model_header_t header
;
670 long framebox_start
, index_pos
;
673 framebox_start
= ftell(binaryout
);
675 /* insert model header */
677 header
.facing_array_start
= framebox_start
+ sizeof(header
);
678 fwrite(&header
, sizeof(header
), 1, binaryout
);
680 /* Create the index array for framesheet of each direction */
681 for ( i
= SFACE
; i
< FACING_MAX
; i
++)
682 { fseek(binaryout
, 0, SEEK_END
);
683 index_pos
= bin_process_facing(framebox
, i
, default_pixel_list
); //TODO: finish process_direction
684 fseek(binaryout
, header
.facing_array_start
+ i
* sizeof(long), SEEK_SET
);
685 fwrite(&index_pos
, sizeof(long), 1, binaryout
);
688 return framebox_start
;
691 bin_process_frameboxes
693 struct bin_ht_header_t
* ht
,
694 struct bin_pixel_node_t
* default_pixel_list
696 { struct bin_ht_entry_t ht_entry
;
699 /* Insert variants into hash table to overwrite olink insertions*/
700 for ( fiter
= ir_set_framebox(set
); fiter
!= NULL
; fiter
= ir_setdata_nextsib(fiter
))
701 { fseek(binaryout
, 0, SEEK_END
);
702 ht_entry
.key
= NAMEHASH(ir_setdata_name(fiter
), ht
->entries
<< 1);
703 ht_entry
.value
= bin_process_framebox(set
, fiter
, default_pixel_list
);
704 bin_insert_ht_entry(ht
->start
, ht
->entries
* sizeof(ht_entry
), &ht_entry
, 1);
708 /* Determine clipping based on image height/width and frame height/width */
710 void bin_set_img_info
711 ( struct bin_img_info_t
* img_info
,
712 ir_setdata frame_data
714 { ir_frameinfo frameinfo
;
715 frameinfo
= ir_framedata_frameinfo(frame_data
);
716 img_info
->fwidth
= frameinfo
->w
;
717 img_info
->fheight
= frameinfo
->h
;
718 img_info
->unaligned_height
= img_info
->height
% img_info
->fheight
;
719 img_info
->unaligned_width
= img_info
->width
% img_info
->fwidth
;
722 /* |-----------------------------|
724 |-----------------------------|
725 | pixel data for frame1 - n |
726 |-----------------------------|
727 | op data for frame1 - n |
728 |-----------------------------| */
731 #define GENERATE_FILENAME(_N) ((char*) u8_strcat(_N, png_suffix))
733 ( ir_setdata framebox
,
735 struct bin_pixel_node_t
* default_pixel_list
737 { struct bin_img_info_t mapsheet_info
, framesheet_info
;
738 int num_mapchannels
, num_framechannels
, x
;
739 struct bin_frame_header_t header
;
741 RGBA_t
* mapdata
, * framedata
;
742 uint8_t* png_suffix
= ".png";
743 struct bin_pixel_node_t
* map_pixel_list
;
745 facing_start
= ftell(binaryout
);
748 /* Set up data pointers to mapsheet and framesheet, as well as their image infos */
749 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);
750 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);
751 bin_set_img_info(&framesheet_info
, ir_framebox_framesheet(framebox
, SFACE
));
752 bin_set_img_info(&mapsheet_info
, ir_framebox_mapsheet(framebox
, SFACE
));
754 /* Allocate space for header */
755 fseek(binaryout
, sizeof(header
), SEEK_CUR
);
758 /* Output framesheet */
759 if(!stbi_write_png(binaryout
, framesheet_info
.width
, framesheet_info
.height
, 4, mapdata
, framesheet_info
.fwidth
))
760 eprintf("error writing out framesheet\n");
762 /* Output framesheet header */
763 header
.width
= framesheet_info
.fwidth
;
764 header
.height
= framesheet_info
.fheight
;
765 header
.frames
= framesheet_info
.width
/ framesheet_info
.fwidth
; //TODO: division is bad
766 header
.op_start
= ftell(binaryout
);
767 fseek(binaryout
, facing_start
, SEEK_SET
);
768 fwrite(&header
, sizeof(header
), 1, binaryout
);
769 fseek(binaryout
, 0, SEEK_END
);
772 /* Assuming that fheight = image height */
773 /* For each mapframe in mapsheet */
774 for ( x
= 0; x
< header
.frames
; x
++)
775 { map_pixel_list
= bin_map_to_pixel_list(mapsheet_info
, 0, x
* mapsheet_info
.fwidth
, data
);
776 if(!bin_process_map_pixel_list(default_pixel_list
, map_pixel_list
))
777 eprintf("error processing map pixel list\n");
778 bin_output_pixel_list(map_pixel_list
);
779 data
+= mapsheet_info
.fwidth
;
782 /* Determine pixel_list */
784 /* Output pixel_list */
791 /* TODO: Please rename all the functions jhc*/
793 void bin_number_pixel_list
794 ( struct bin_pixel_node_t
* pixel_list
)
796 struct bin_pixel_node_t
* iter
;
798 { iter
.data
.attach_idx
= num
++;
803 /* Assuming at this point that map_pixel_list is valid */
805 int bin_set_map_pixel_list_attach_idxs
806 ( struct bin_pixel_node_t
* default_pixel_list
,
807 struct bin_pixel_node_t
* map_pixel_list
809 { struct bin_pixel_node_t
* mapiter
, defaultiter
;
810 mapiter
= map_pixel_list
;
811 defaultiter
= default_pixel_list
;
812 while (mapiter
&& defaultiter
)
813 { /* if mapiter.data.ref == defaultiter.data.ref, assign mapiter index_idx to defaultiter */
814 if (mapiter
.data
.ref
== defauliter
.data
.ref
)
815 { defaultiter
.data
.attach_idx
= mapiter
.data
.attach_idx
;
816 mapiter
= mapiter
->next
;
817 defaultiter
= defaultiter
->next
;
820 defaultiter
= defaultiter
->next
;
824 /* map_pixel_list cannot have more pixels. for all of its pixels,
825 the refs must be represented in default pixel list. 0 if invalid, 1 if valid */
827 int bin_valid_map_pixel_list
828 ( struct bin_pixel_node_t
* default_pixel_list
,
829 struct bin_pixel_node_t
* map_pixel_list
831 { struct bin_pixel_node_t
* mapiter
, defaultiter
;
832 defaultiter
= default_pixel_list
;
833 /* check length of each to make sure default < max */
834 /* for each pixel node in default and map */
836 { for( mapiter
= map_pixel_list
; mapiter
!= NULL
; mapiter
= mapiter
->next
)
842 if(!mapiter
&& defaultiter
) //defaultiter is longer so error!
851 int bin_process_map_pixel_list
852 ( struct bin_pixel_node_t
* default_pixel_list
,
853 struct bin_pixel_node_t
* map_pixel_list
855 { /* Determine if pixel_list is valid */
857 /* Determine attach_idx of each pixel, as compared to default pixel list */
862 bin_assign_pixel_idxs
863 ( struct bin_pixel_node_t
* pixel_list
)
867 /* Insert pixel(s) into the list, z sorted */
868 /* number the pixels as you insert them */
869 struct bin_pixel_node_t
*
870 bin_insert_node_into_list
871 ( struct bin_pixel_node_t
* pixel_list_root
,
872 struct bin_pixel_node_t
* pixel_node
874 { struct bin_pixel_node_t
* head_node
, * prev_node
;
877 if(pixel_list_root
== NULL
)
878 { pixel_list_root
= pixel_node
;
881 prev_node
= head_node
= pixel_list_root
;
882 while(head_node
!= NULL
)
883 { if(pixel_node
->data
.z
> head_node
->data
.z
)
884 { if(head_node
->next
)
885 { prev_node
= head_node
;
886 head_node
= head_node
->next
;
889 { head_node
->next
= pixel_node
;
893 else if (pixel_node
->data
.z
< head_node
->data
.z
|| pixel_node
->data
.z
== head_node
->data
.z
)
894 { prev_node
->next
= pixel_node
;
895 pixel_node
->next
= head_node
;
900 return pixel_list_root
;
905 /* Returns the non null pixels of a single map */
906 /* TODO: Finish this */
907 struct bin_pixel_node_t
*
908 bin_mapframe_to_pixel_list
909 ( struct bin_img_info_t
* img_info
,
914 { int x
, y
, fheight
, fwidth
;
915 struct bin_pixel_node_t
* pixel_list
,* pixel_node
;
919 /* if frame clips, process unclippign frames */
920 if( img_info
->unaligned_width
)
921 { if(img_info
->height
< img_info
->fheight
)
922 fheight
= img_info
->height
;
924 fheight
= img_info
->fheight
;
927 fheight
= img_info
->fheight
;
928 if (img_info
->unaligned_height
)
929 { if(img_info
->width
< img_info
->fwidth
)
930 fwidth
= img_info
->width
;
932 fwidth
= img_info
->fwidth
;
935 fwidth
= img_info
->fwidth
;
939 for (y
= 0; y
< fheight
; y
++)
940 { for ( x
= 0; x
< fwidth
; x
++ )
942 { pixel_node
= struct_alloc(bin_pixel_node_t
);
943 /* get ref from 4 bytes of data */
944 pixel_node
->data
.ref
= (*data
) >> 8;
945 /* bitshift by ? to get Z */
946 pixel_node
->data
.z
= (*data
& 0xFF);
948 pixel_node
->data
.x
= x
+ init_width
;
949 pixel_node
->data
.y
= y
+ init_width
;
950 pixel_list
= bin_insert_node_into_list(pixel_list
, pixel_node
);
954 data
+= img_info
->width
- img_info
->fwidth
; //stride
960 int bin_pixel_list_len
961 ( struct bin_pixel_node_t
* pl
)
962 { struct bin_pixel_node_t
* plp
;
973 struct bin_pixel_node_t
*
974 bin_cmp_default_pixel_lists
975 ( struct bin_pixel_node_t
* pl1
,
976 struct bin_pixel_node_t
* pl2
978 { struct bin_pixel_node_t
* pl1p
, * pl2p
;
979 int i
, pl1_len
, pl2_len
;
983 pl1_len
= bin_pixel_list_len(pl1
);
984 pl2_len
= bin_pixel_list_len(pl2
);
986 if (pl1_len
> pl2_len
)
988 else if (pl1_len
< pl2_len
)
990 /* pl1 == pl2, make sure that all refs are the same */
991 /* TODO: what type of warning/error handling should occur here? */
992 for (i
= 0; i
< pl1_len
; i
++)
993 { if (pl1p
->data
.ref
!= pl2p
->data
.ref
)
994 eprintf("Error in determining default pixel list\n");
998 return pl1
; //doesnt matter which one you return
1001 /* Find default framebox, based on the framebox with the most attachments*/
1002 /* Search through first frame of S of each framebox */
1003 struct bin_pixel_node_t
*
1004 bin_find_default_pixel_list
1007 struct bin_pixel_node_t
* default_pixel_list
, * curr_pixel_list
;
1010 struct bin_img_info_t img_info
;
1012 for (fiter
= ir_set_framebox(set
); fiter
!= NULL
; fiter
= ir_setdata_nextsib(fiter
))
1013 { /* TODO: Stringify the frame name with .png? */
1014 /* TODO: Add directory changing */
1015 data
= (RGBA_t
*) stbi_load(ir_setdata_name((ir_setdata
) ir_framebox_mapsheet(fiter
,SFACE
) ), &img_info
.width
, &img_info
.width
, &num_channels
, 0);
1016 bin_set_img_info(&img_info
, ir_framebox_mapsheet(fiter
, SFACE
));
1017 curr_pixel_list
= bin_mapframe_to_pixel_list(&img_info
, 0, 0, data
);
1018 default_pixel_list
= bin_cmp_default_pixel_lists(curr_pixel_list
, default_pixel_list
);
1023 return default_pixel_list
;