--- /dev/null
+/* Standard */
+#include <stdlib.h> //exit, malloc
+#include <stdio.h> //print
+#include <stdarg.h> //va_args
+#include <string.h> //memset, str*
+#include <errno.h>
+/* Unicode */
+#include <unistd.h> //u8_* functions
+#include <unitypes.h> //uint8_t as a char
+#include <unistr.h> //u32_cpy
+#include <unistdio.h> //ulc_fprintf
+/* Local */
+#include "print.h"
+#include "apc.h"
+#include "ir.h"
+#include "pagenode.h"
+#undef do_error
+#define do_error(...) exit(-1)
+#define XXH_PRIVATE_API
+#include "../xxHash/xxhash.h"
+#define STB_IMAGE_IMPLEMENTATION
+#include "stb_image.h"
+
+/* Public */
+void ir_binout_init(struct ir_class_t*);
+
+/* Memory Allocation */
+#define struct_alloc(_T) ((struct _T*) stack_alloc(&datapages, sizeof(struct _T)))
+static
+struct pagelist_t linkpages, datapages;
+
+enum model_type { SS };
+/* Binaryout out structure definitions */
+struct bin_img_info_t {
+ int height;
+ int width;
+ int fwidth; //map and frame width
+ int fheight; //map and frame height
+ int unaligned_width;
+ int unaligned_height;
+};
+struct bin_ht_header_t {
+ long start;
+ int entries;
+};
+struct bin_ht_entry_t {
+ uint32_t key;
+ long value;
+};
+struct bin_class_header_t {
+ struct bin_ht_header_t child_ht;
+ struct bin_ht_header_t rootset_ht;
+ int namelen;
+};
+struct bin_set_header_t {
+ struct bin_ht_header_t child_ht;
+ long sdat_start; //points to setdata_header
+ int namelen;
+};
+struct bin_setdata_header_t {
+ struct bin_ht_header_t variant_ht;
+ long attach_pos;
+};
+struct bin_model_header_t { //one for each framebox, currently
+ long facing_array_start;
+ enum model_type type;
+};
+struct bin_frame_header_t {
+ int width;
+ int height;
+ int frames;
+ long op_start;
+};
+struct bin_plink_t {
+ enum ltype type;
+ ir_set trg_set;
+ uint8_t* name;
+ long src_pos;
+};
+struct bin_pixel_t {
+ int x, y, z;
+ uint32_t ref;
+};
+struct bin_pixel_node_t {
+ struct bin_pixel_node_t* next;
+ struct bin_pixel_t data;
+};
+struct bin_op_t {
+ int x;
+ int y;
+ int attach_idx;
+};
+struct bin_attachment_header_t {
+ int num_attachment_lists;
+ int num_attachments;
+};
+struct bin_attachment_t {
+ int idx;
+ ir_set set;
+};
+/* Read out of the als, after first ir pass, resolves the
+ attach_pos of the src-set that created the attachment_list
+ to the header that describes the attachment_list */
+struct bin_attachment_list_t {
+ int num_attachments;
+ struct bin_attachment_t** attachments;
+ long filepos;
+};
+
+struct bin_attachment_list_t **attachment_stack, **asp; //attachment_stack, attachment_stack_pointer
+FILE* binaryout;
+
+
+
+#define NAMEHASH(name, domain) (XXH32(name, u8_strlen(name), 0XCEED ) & domain)
+
+/* Given a position and a size, checks if the bytes are null and returns
+ the file position to where it started. 1 if not null, 0 if null*/
+/* TODO: Determine why fseeking file past end sets bytes to -1, and not 0 */
+static inline
+int bytes_null( int len, int pos )
+{ while(len--)
+ { if(fgetc(binaryout) > 0)
+ { fseek(binaryout, pos, SEEK_SET);
+ return 1;
+ }
+ }
+ fseek(binaryout, pos, SEEK_SET);
+ return 0;
+}
+/* Checks if the key at entrypos is the same as the parameter key. Returns
+ 1 if so, 0 if not. */
+static inline
+int bin_keys_identical
+( long entry_pos,
+ uint32_t key
+)
+{ uint32_t curr_key;
+ fseek(binaryout, entry_pos, SEEK_SET);
+ fscanf(binaryout, "%u", &curr_key);
+ if( curr_key == key)
+ return 1;
+ return 0;
+}
+
+long bin_traverse_class(ir_class);
+/* Takes root class and begins processing */
+void
+ir_binout_init(ir_class root_class)
+{ binaryout = fopen("binaryout", "w+");
+ asp = attachment_stack;
+ pagelist_init(datapages, (size_t) SYS_PAGESIZE);
+ pagelist_init(linkpages, (size_t) SYS_PAGESIZE);
+ bin_traverse_class(root_class);
+}
+
+#define ENTRY_OCCUPIED() (bytes_null(sizeof(ht_entry->key), entry_pos))
+#define WRITE_ENTRY() do { \
+ if(fseek(binaryout, entry_pos, SEEK_SET) == -1) wprintf("fseek failed with %s", strerror(errno)); \
+ fwrite(&ht_entry, sizeof ht_entry, 1, binaryout); \
+ } while (0)
+#define LOOP_ENTRY(_HTSTART) (entry_pos = _HTSTART)
+#define INC_ENTRY() do { \
+ entry_pos += sizeof(ht_entry); \
+ if(fseek(binaryout, entry_pos, SEEK_SET) == -1) eprintf("fseek failed with %s", strerror(errno)); \
+ } while (0)
+#define HT_END(_HTEND) (entry_pos >= _HTEND) //just in case at last entry
+void
+/* TODO: Should overwrite be a default? */
+bin_insert_ht_entry
+( long ht_start,
+ long ht_size,
+ struct bin_ht_entry_t* ht_entry,
+ int overwrite
+)
+{ long entry_pos, ht_end;
+
+ ht_end = ht_start + ht_size;
+ entry_pos = ht_start + sizeof(ht_entry) * ht_entry->key;
+ fseek(binaryout, entry_pos, SEEK_SET);
+
+ if (!ENTRY_OCCUPIED())
+ { uprintf("key not occupied\n");
+ WRITE_ENTRY();
+ }
+ while( ENTRY_OCCUPIED() )
+ { if(overwrite)
+ { if(bin_keys_identical(entry_pos, ht_entry->key))
+ break;
+ else
+ { eprintf("error in hashtable insertion, keys are identical");
+ }
+ }
+ if (HT_END(ht_end))
+ LOOP_ENTRY(ht_start);
+ else
+ INC_ENTRY();
+ }
+ WRITE_ENTRY();
+
+}
+
+/* | class header |
+ |--------------------|
+ | rootset ht |
+ |--------------------|
+ | rootsets data |
+ |--------------------|
+ | classchild ht |
+ |--------------------|
+ | classchild header |
+ | ... |
+*/
+
+long bin_traverse_set(ir_set);
+long
+#define HT_INIT(_START, _SIZE, _INIT_ENTRIES) do { \
+ _SIZE = _INIT_ENTRIES ? (_INIT_ENTRIES * (sizeof(struct bin_ht_entry_t) << 1)): 0; \
+ _START = ftell(binaryout); \
+ fseek(binaryout, _SIZE, SEEK_CUR); \
+} while (0)
+bin_traverse_class
+( ir_class class)
+{ ir_class citer;
+ ir_set siter;
+ struct bin_class_header_t class_header;
+ struct bin_ht_entry_t ht_entry;
+ long class_start, classht_start, classht_size, rootsetht_start, rootsetht_size;
+ int num_csibs, num_ssibs;
+ uint8_t* class_name;
+
+ class_start = ftell(binaryout);
+ class_name = get_class_name(class);
+
+ num_csibs = get_class_sibcount(class);
+ num_ssibs = get_set_sibcount(get_class_root_set(class));
+
+ /* alloc space (before hash tables) for class header */
+ class_header.namelen = u8_strlen(class_name);
+ fseek(binaryout, class_start + sizeof(class_header) + class_header.namelen ,SEEK_SET);
+
+ HT_INIT(classht_start, classht_size, num_csibs);
+ HT_INIT(rootsetht_start, rootsetht_size, num_ssibs);
+
+ /* TODO: Figure out generic way to output headers */
+ /* populate class header */
+ class_header.child_ht.entries = num_csibs;
+ class_header.child_ht.start = classht_start;
+ class_header.rootset_ht.entries = num_ssibs;
+ class_header.rootset_ht.start = rootsetht_start;
+ fseek(binaryout, class_start, SEEK_SET); //seek back to where we allocated header
+ fwrite(&class_header, sizeof(class_header), 1, binaryout);
+ fwrite(class_name, class_header.namelen, 1, binaryout);
+
+ /* Start populating root_set hash table */
+ for ( siter = get_class_root_set(class); siter != NULL; siter = get_set_nextsib(siter))
+ { fseek(binaryout, 0, SEEK_END);
+ ht_entry.key = NAMEHASH(get_set_name(siter), num_ssibs << 1);
+ ht_entry.value = bin_traverse_set(siter);
+ bin_insert_ht_entry(rootsetht_start, rootsetht_size, &ht_entry, 0);
+ }
+
+ /* Start populating class child hash table */
+ for ( citer = get_class_nextchild(class); citer != NULL; citer = get_class_nextsib(citer))
+ { fseek(binaryout, 0, SEEK_END);
+ ht_entry.key = NAMEHASH(get_class_name(citer), num_csibs << 1);
+ ht_entry.value = bin_traverse_class(citer);
+ bin_insert_ht_entry(classht_start, classht_size, &ht_entry, 0);
+ }
+
+ return class_start;
+}
+
+long bin_process_sdat( ir_set);
+
+/* | set header |--|
+ |-----------------| |
+ | set data |<-|
+ |-----------------| |
+---| setchild ht |<--
+| |-----------------|
+|->| setchild header |
+|->| ... |
+*/
+
+long
+bin_traverse_set
+( ir_set set )
+{ ir_set iter;
+ struct bin_set_header_t header;
+ struct bin_ht_entry_t ht_entry;
+ int num_child, setname_len;
+ long childht_start, childht_size, set_start;
+ uint8_t* set_name;
+
+ set_start = ftell(binaryout);
+ set_name = get_set_name(set);
+
+ /* alloc space for set header */
+ setname_len = u8_strlen(set_name);
+ fseek(binaryout, sizeof(struct bin_set_header_t) + setname_len , SEEK_CUR);
+
+ /* process the set data */
+ header.sdat_start = bin_process_sdat(set);
+
+ /* Setup child hash table for current sets children */
+ num_child = get_set_sibcount(get_set_nextchild(set));
+ HT_INIT(childht_start, childht_size, num_child);
+
+ /* populate header, write to file */
+ header.child_ht.entries = num_child;
+ header.child_ht.start = childht_start;
+ fseek(binaryout, set_start, SEEK_SET);
+ fwrite(&header, sizeof(struct bin_set_header_t), 1, binaryout);
+ fwrite(set_name, setname_len, 1, binaryout);
+
+ for(iter = get_set_nextchild(set); iter != NULL; iter = get_set_nextsib(iter))
+ { fseek(binaryout, 0, SEEK_END);
+ ht_entry.key = NAMEHASH(get_set_name(iter), num_child << 1);
+ ht_entry.value = bin_traverse_set(iter);
+ bin_insert_ht_entry(childht_start, childht_size, &ht_entry, 0);
+ }
+
+
+ set_set_filepos(set, set_start);
+ return set_start;
+
+}
+/* | sdat header |
+ |------------------|
+ | variant ht |
+ |------------------|
+ | 1st variant data | -- variant == framebox
+ |------------------|
+ | 2nd variant data |
+ |------------------|
+ | etc. |
+
+*/
+
+void bin_insert_links(int, struct bin_ht_header_t*, long);
+struct bin_pixel_node_t* bin_find_default_pixel_list(ir_set);
+void bin_process_frameboxes(ir_set, struct bin_ht_header_t*, struct bin_pixel_node_t*);
+int bin_process_links(ir_set, ir_setdata);
+
+/* Init the variant hash table for the set, process the sets links and add them to link_stack
+ and variant hash table, and then output the actual framedata */
+long
+bin_process_sdat
+( ir_set set )
+{ struct bin_setdata_header_t header;
+ struct bin_attachment_list_t attachment_list;
+ struct bin_pixel_node_t *default_pixel_list;
+ struct bin_ht_header_t ht_header;
+ long varht_start, varht_size, sdat_start;
+ int num_entries, num_links;
+ ir_setdata olink_head;
+
+ sdat_start = ftell(binaryout);
+
+ /* Alloc position for sdat_header */
+ fseek(binaryout, sizeof(struct bin_setdata_header_t), SEEK_CUR);
+
+ num_links = bin_process_links(set, olink_head);
+ num_entries = get_set_variants(set) + num_links;
+
+ HT_INIT(varht_start, varht_size, num_entries);
+
+ /* Populate the sdat_header */
+ fseek(binaryout, 0, sdat_start);
+ header.variant_ht.start = ht_header.start = varht_start;
+ header.variant_ht.entries = ht_header.entries = num_entries;
+ attachment_list.filepos = header.attach_pos = ftell(binaryout) + sizeof(varht_start) + sizeof(num_entries);
+ fwrite(&header, sizeof(header), 1, binaryout);
+ fseek(binaryout, 0, SEEK_END);
+
+ /* insert the links that were processed into the variant hash table */
+ bin_insert_links(num_links, &ht_header, attachment_list.filepos);
+ /* Determine the default pixel list for all of the frameboxes */
+ default_pixel_list = bin_find_default_pixel_list(set);
+ /* Output each framebox, and insert it into the variant hash table */
+ bin_process_frameboxes(set, &ht_header, default_pixel_list);
+
+ /* TODO: Convert the default pixel list to an attachment_list and then push the */
+ /* sdats attachment_list onto the attachment_stack so it can be procesed */
+
+
+ return sdat_start;
+}
+
+
+/* Adds a vlink onto the stack_alloc to be popped during the processing of the
+ sets variant hash table. If the vlink has a name, its a vlink to a single
+ variant. if the vlink doesnt have a name, its the vlink to an entire variant
+ hash table, and each variant (framebox) needs to be added */
+int
+bin_process_vlink
+( ir_setdata vlink,
+ ir_set trg_set
+)
+{ struct bin_plink_t* plp;
+ ir_setdata fiter;
+ uint8_t* link_name;
+ int num_links;
+
+ num_links = 0;
+
+ /* TODO: Macroize? or not worth? */
+ link_name = get_link_name(vlink);
+
+ if (link_name)
+ { plp = struct_alloc(bin_plink_t);
+ plp->src_pos = 0; // TBD @ process_setdata
+ plp->name = link_name;
+ plp->trg_set = trg_set;
+ plp->type = VLINK;
+ num_links++;
+ }
+ else // linking a variant hash table
+ for (fiter = get_set_frameboxes(trg_set); fiter != NULL; fiter = get_framebox_nextsib(fiter))
+ { plp = struct_alloc(bin_plink_t);
+ plp->src_pos = 0; // TBD @ process_setdata
+ plp->name = get_framebox_name(fiter);
+ plp->trg_set = trg_set;
+ plp->type = VLINK;
+ num_links++;
+ }
+
+ return num_links;
+
+}
+
+/* Adds an mlink to the stack_alloc, to be processed later */
+int
+bin_process_mlink
+( ir_setdata mlink,
+ ir_set trg_set
+)
+{ struct bin_plink_t* plp;
+ uint8_t* mlink_name;
+ mlink_name = get_link_name(mlink);
+ plp = struct_alloc(bin_plink_t);
+ plp->src_pos = 0; //TBD after resolving the childlist | TODO: attach_pos?
+ if(mlink_name) plp->name = mlink_name;
+ plp->trg_set = trg_set;
+ plp->type = MLINK;
+
+ return 1;
+}
+
+/* TODO: implement this */
+/* Determine if olink is already part of the olink_list.
+ if it is, theres a cycle, return 1. Else return 0. */
+static inline
+int olink_cycle
+( ir_setdata olink,
+ ir_setdata olink_head )
+{ ir_setdata iter;
+
+
+
+ return 0;
+
+
+}
+
+/* Given a set, determine the number of links it has and process each link and
+ then add them to stack_alloc, where they will be popped off and further processed. */
+int
+bin_process_links
+( ir_set src_set,
+ ir_setdata olink_head
+)
+{ int num_links;
+ ir_setdata liter; //link iter
+ ir_set trg_set;
+
+ num_links = 0;
+
+ for(liter = get_set_links(src_set); liter != NULL; liter = get_link_nextsib(liter))
+ { trg_set = get_set_from_ref(get_link_ref(liter));
+ switch (get_link_type(liter)) {
+ case OLINK:
+ if (olink_cycle(liter, olink_head)) //TODO: stack of olinks to iterate and check for cycles?
+ return num_links;
+ num_links += bin_process_vlink(liter, trg_set);
+ num_links += bin_process_mlink(liter, trg_set);
+ num_links += bin_process_links(trg_set, liter);
+ break;
+ case VLINK:
+ num_links += bin_process_vlink(liter, trg_set);
+ break;
+ case MLINK:
+ num_links += bin_process_mlink(liter, trg_set);
+ break;
+ case ALINK: //TODO: ?
+ break;
+ }
+ }
+ return num_links;
+}
+
+/* Insert both mlinks and vlinks into the link stack, after determining their src_pos. Vlinks
+ have an additional requirement of being added into the variant hash table */
+#define pop_linkp() (*(struct bin_plink_t**) pagelist_pop(&datapages, sizeof(struct bin_plink_t*)))
+#define PUSH_PLINK(_LINK) (*(struct bin_plink_t**) stack_alloc(&linkpages, sizeof (_LINK)) = _LINK )
+void
+bin_insert_links
+( int num_links,
+ struct bin_ht_header_t* ht,
+ long attach_pos
+)
+{ struct bin_plink_t* plp;
+ struct bin_ht_entry_t ht_entry;
+ int i;
+
+ /* Insert vlinks into hash table, put v/mlinks on link stack to be processed later */
+ for ( i = 0; i < num_links; i++)
+ { plp = pop_linkp();
+ switch (plp->type) {
+ case MLINK:
+ plp->trg_set = plp->trg_set;
+ plp->src_pos = attach_pos;
+ PUSH_PLINK(plp);
+ break;
+ case VLINK:
+ ht_entry.key = NAMEHASH(plp->name, ht->entries << 1);
+ ht_entry.value = 0;
+ bin_insert_ht_entry(ht->start, ht->entries * sizeof(ht_entry), &ht_entry, 0);
+ plp->src_pos = ht_entry.key + sizeof(ht_entry.key);
+ PUSH_PLINK(plp);
+ break;
+ case OLINK:
+ break;
+ //shouldnt exist
+ case ALINK:
+ break;
+ //TBD
+ }
+ }
+}
+
+long bin_process_facing(ir_setdata, apc_facing, struct bin_pixel_node_t*);
+/* |-------------------|
+ | framebox header |
+ |-------------------|
+ | SFACE framesheet |
+ |-------------------|
+ | SWFACE framesheet |
+ |-------------------|
+ | etc. |
+*/
+long
+bin_process_framebox
+( ir_set set,
+ ir_setdata framebox,
+ struct bin_pixel_node_t* default_pixel_list
+)
+{ struct bin_model_header_t header;
+ long framebox_start, index_pos;
+ int i;
+
+ framebox_start = ftell(binaryout);
+
+ /* insert model header */
+ header.type = SS;
+ header.facing_array_start = framebox_start + sizeof(header);
+ fwrite(&header, sizeof(header), 1, binaryout);
+
+ /* Create the index array for framesheet of each direction */
+ for ( i = SFACE; i < FACING_MAX; i++)
+ { fseek(binaryout, 0, SEEK_END);
+ index_pos = bin_process_facing(framebox, i, default_pixel_list); //TODO: finish process_direction
+ fseek(binaryout, header.facing_array_start + i * sizeof(long), SEEK_SET);
+ fwrite(&index_pos, sizeof(long), 1, binaryout);
+ }
+
+ return framebox_start;
+}
+void
+bin_process_frameboxes
+( ir_set set,
+ struct bin_ht_header_t* ht,
+ struct bin_pixel_node_t* default_pixel_list
+)
+{ struct bin_ht_entry_t ht_entry;
+ ir_setdata fiter;
+
+ /* Insert variants into hash table to overwrite olink insertions*/
+ for ( fiter = get_set_frameboxes(set); fiter != NULL; fiter = get_framebox_nextsib(fiter))
+ { fseek(binaryout, 0, SEEK_END);
+ ht_entry.key = NAMEHASH(get_framebox_name(fiter), ht->entries << 1);
+ ht_entry.value = bin_process_framebox(set, fiter, default_pixel_list);
+ bin_insert_ht_entry(ht->start, ht->entries * sizeof(ht_entry), &ht_entry, 1);
+ }
+
+}
+/* Determine clipping based on image height/width and frame height/width */
+static inline
+void bin_set_img_info
+( struct bin_img_info_t* img_info,
+ ir_setdata framedata
+)
+{ img_info->fwidth = get_framedata_width(framedata);
+ img_info->fheight = get_framedata_height(framedata);
+ img_info->unaligned_height = img_info->height % img_info->fheight;
+ img_info->unaligned_width = img_info->width % img_info->fwidth;
+
+}
+
+/* TODO: Implement this */
+long
+bin_process_frame
+ ()
+{}
+
+
+
+/* Combine the framesheet and mapsheet to create
+ the output sheet */
+/* |-------------------------|
+ | outputsheet header |
+ |-------------------------|
+ | pixel data for frame1 |
+ |-------------------------|
+ | op data for frame1 |
+ |-------------------------|
+ | etc. | */
+//TODO: processing direction sounds dumb, but cant call it process_framesheet because
+// its actually the mapsheet and the framesheet. rename to output sheet?
+/* THIS FUNCTION IS NOT DONE */
+long
+bin_process_facing
+( ir_setdata framebox,
+ apc_facing facing,
+ struct bin_pixel_node_t* default_pixel_list
+)
+{ struct bin_img_info_t mapsheet_info, framesheet_info;
+ int num_mapchannels, num_framechannels;
+ long facing_start;
+ unsigned char* mapdata, * framedata;
+
+ facing_start = ftell(binaryout);
+
+
+ /* Set up data pointers to mapsheet and framesheet, as well as their image infos */
+ mapdata = stbi_load(get_framedata_name(get_framebox_facing_mapdata(framebox,SFACE)), &mapsheet_info.width, &mapsheet_info.width, &num_framechannels , 0);
+ framedata = stbi_load(get_framedata_name(get_framebox_facing_framedata(framebox,SFACE)), &framesheet_info.width, &framesheet_info.height, &num_mapchannels, 0);
+ bin_set_img_info(&framesheet_info, get_framebox_facing_framedata(framebox, SFACE));
+ bin_set_img_info(&mapsheet_info, get_framebox_facing_mapdata(framebox, SFACE));
+
+ /* TODO: output framesheet/direction header */
+
+
+ /* For each frame and map i in framesheet + mapsheet */
+ /* output frame data */
+ /* output op space for frames */
+ /* determine ops in map */
+ /* check if ops are acceptable */
+ /* output ops */
+
+
+ return facing_start;
+
+}
+
+
+
+
+
+/* Insert pixel(s) into the list, z sorted */
+void
+bin_insert_node_into_list
+( struct bin_pixel_node_t* pixel_list_root,
+ struct bin_pixel_node_t* pixel_node
+)
+{ struct bin_pixel_node_t* head_node, *prev_node;
+ int node_z;
+
+ head_node = pixel_list_root->next;
+ node_z = pixel_node->data.z;
+
+ if(head_node == NULL)
+ { head_node = pixel_node;
+ }
+ prev_node = pixel_list_root;
+ while(head_node != NULL)
+ { if(node_z > head_node->data.z)
+ { prev_node = head_node;
+ head_node = head_node->next;
+ }
+ else if (node_z < head_node->data.z || node_z == head_node->data.z)
+ { prev_node->next = pixel_node;
+ pixel_node->next = head_node;
+ break;
+ }
+ }
+
+
+}
+
+/* TODO: Finish this */
+struct bin_pixel_node_t*
+bin_process_pixel
+( unsigned char* data,
+ int x,
+ int y,
+ int init_height,
+ int init_width
+)
+{ struct bin_pixel_node_t* pixel_node;
+
+
+ pixel_node = struct_alloc(bin_pixel_node_t);
+
+ if(data)
+ { /* get ref from 4 bytes of data */
+ pixel_node->data.ref = (int) data;
+ /* bitshift by ? to get Z ordering */
+
+ /* set x and y */
+ pixel_node->data.x = x + init_width ;
+ pixel_node->data.y = y + init_width;
+ data += 4;
+ }
+ else
+ { data += 4; //TODO: does this correctly increment past 0x00000000?
+ return NULL;
+ }
+
+
+
+ return pixel_node;
+
+}
+
+/* Returns the non null pixels of a single frame */
+/* TODO: Finish this */
+struct bin_pixel_node_t*
+bin_map_to_pixel_list
+( struct bin_img_info_t* img_info,
+ int init_height,
+ int init_width,
+ unsigned char* data
+)
+{ int x, y;
+ struct bin_pixel_node_t* pixel_list, * pixel_node;
+
+ pixel_list = NULL;
+
+ /* Check if frame clips */
+ if( img_info->unaligned_width )
+ ;
+ if (img_info->unaligned_height )
+ ;
+
+ /* Process the map*/
+ for (y = 0; y < img_info->fheight; y++)
+ { for ( x = 0; x < img_info->fwidth; x++ )
+ { pixel_node = bin_process_pixel(data, x, y, init_height, init_width);
+ bin_insert_node_into_list(pixel_list, pixel_node);
+ }
+ }
+
+ return pixel_node;
+}
+
+static inline
+int bin_pixel_list_len
+( struct bin_pixel_node_t* pl )
+{ struct bin_pixel_node_t* plp;
+ int count;
+ count = 0;
+ plp = pl;
+ while(plp)
+ { count++;
+ plp = plp->next;
+ }
+ return count;
+}
+
+struct bin_pixel_node_t*
+bin_cmp_default_pixel_lists
+( struct bin_pixel_node_t* pl1,
+ struct bin_pixel_node_t* pl2
+)
+{ struct bin_pixel_node_t* pl1p, * pl2p;
+ int i, pl1_len, pl2_len;
+
+ pl1p = pl1;
+ pl2p = pl2;
+ pl1_len = bin_pixel_list_len(pl1);
+ pl2_len = bin_pixel_list_len(pl2);
+
+ if (pl1_len > pl2_len)
+ return pl1;
+ else if (pl1_len < pl2_len)
+ return pl2;
+ /* pl1 == pl2, make sure that all refs are the same */
+ /* TODO: what type of warning/error handling should occur here? */
+ for (i = 0; i < pl1_len; i++)
+ { if (pl1p->data.ref != pl2p->data.ref)
+ eprintf("Error in determining default pixel list\n");
+ pl1p = pl1p->next;
+ pl2p = pl2p->next;
+ }
+ return pl1; //doesnt matter which one you return
+}
+
+/* Find default framebox, based on the framebox with the most attachments*/
+/* Search through first frame of S of each framebox */
+struct bin_pixel_node_t*
+bin_find_default_pixel_list
+( ir_set set)
+{ ir_setdata fiter;
+ struct bin_pixel_node_t* default_pixel_list, * curr_pixel_list;
+ unsigned char* data;
+ int num_channels;
+ struct bin_img_info_t img_info;
+
+ for (fiter = get_set_frameboxes(set); fiter != NULL; fiter = get_framebox_nextsib(fiter))
+ { /* TODO: Stringify the frame name with .png? */
+ /* TODO: Add directory changing */
+ data = stbi_load(get_framedata_name(get_framebox_facing_mapdata(fiter, SFACE)), &img_info.width, &img_info.width, &num_channels, 0);
+ bin_set_img_info(&img_info, get_framebox_facing_mapdata(fiter, SFACE));
+ curr_pixel_list = bin_map_to_pixel_list(&img_info, 0, 0, data);
+ default_pixel_list = bin_cmp_default_pixel_lists(curr_pixel_list, default_pixel_list);
+
+ free(data);
+ }
+
+ return default_pixel_list;
+}
#include <stdarg.h> //va_args\r
#include <stdint.h> //uint64_t\r
#include <string.h> //memset, str*\r
+#include <errno.h>\r
/* Unicode */\r
#include <unistd.h> //u8_* functions\r
#include <unitypes.h> //uint8_t as a char\r
#include "print.h"\r
#include "apc.h"\r
#include "ir.h"\r
+#include "pagenode.h"\r
#undef do_error\r
#define do_error(...) exit(-1)\r
#define XXH_PRIVATE_API\r
void ir_test(void);\r
int ir_linker(void);\r
int ir_condenser(void);\r
-/* Memory allocation structures */\r
-struct pagenode_t;\r
-struct pagenode_header_t {\r
- struct pagenode_t* next;\r
- char* head;\r
-};\r
-struct pagenode_t {\r
- struct pagenode_header_t header;\r
- char root[];\r
-};\r
-struct pagelist_t {\r
- struct pagenode_t* root, * head;\r
- size_t pagesize;\r
-};\r
-#define SYS_PAGESIZE (sys_pagesize)\r
-#define NAME_PAGESIZE (APC_NAME_MAX * 1024)\r
-#define PL_HEADERSIZE (sizeof(struct pagenode_header_t))\r
-#define PL_HEADSIZE(_PL) (_PL.head->header.head - _PL.head->root)\r
-#define PL_HEADMEM(_PL) (_PL.pagesize - PL_HEADERSIZE - PL_HEADSIZE(_PL))\r
/* Set data mem */\r
enum dtype { FSDAT, MSDAT, ADAT, LDAT, FBDAT };\r
struct ir_namelist_t;\r
struct ir_framebox_t* frameboxes;\r
struct ir_simplex_t* audio;\r
struct ir_link_t* links;\r
+ long filepos;\r
};\r
/* Functions */\r
static inline\r
static inline\r
int classnames_identical(const uint8_t*,const uint8_t*);\r
static\r
-void* stack_alloc(size_t);\r
-#define struct_alloc(_T) ((struct _T*) stack_alloc(sizeof(struct _T)))\r
-#define struct_clear(_S) (memset((_S), 0, sizeof(*(_S))))\r
-static\r
uint8_t* name_alloc(const uint8_t*);\r
static\r
uint8_t* classname_alloc(const uint8_t*);\r
-static inline\r
-void* pagelist_pop(struct pagelist_t*,size_t);\r
-#define $($)#$\r
-#define pagelist_alloc(pagelist) do { \\r
- pagelist.head->header.next = (struct pagenode_t*) malloc(pagelist.pagesize); \\r
- if (pagelist.head->header.next == NULL) \\r
- eprintf("Memory allocation error\n"); \\r
- struct_clear(pagelist.head->header.next); \\r
- pagelist.head = pagelist.head->header.next; \\r
- pagelist.head->header.head = pagelist.head->root; \\r
- } while (0)\r
-#define pagelist_init(pagelist,size) do { \\r
- pagelist.pagesize = size; \\r
- pagelist.root = (struct pagenode_t*) malloc(size); \\r
- if (pagelist.root == NULL) \\r
- eprintf("Memory allocation error\n"); \\r
- struct_clear(pagelist.root); \\r
- pagelist.head = pagelist.root; \\r
- pagelist.head->header.head = pagelist.head->root; \\r
- } while (0)\r
-static\r
-void pagenode_free(struct pagenode_t*);\r
+#define struct_clear(_S) (memset((_S), 0, sizeof(*(_S))))\r
#define REFHASH(ref) (XXH32(&ref, sizeof(uint32_t), 0xCEED) & 0xCFF)\r
-\r
+#define struct_alloc(_T) ((struct _T*) stack_alloc(&datapages, sizeof(struct _T)))\r
extern //apc.c\r
long sys_pagesize;\r
static\r
{ pagelist_init(datapages, (size_t)SYS_PAGESIZE);\r
pagelist_init(namepages, (size_t)NAME_PAGESIZE);\r
pagelist_init(refhashpages, (size_t)SYS_PAGESIZE);\r
+\r
return 0;\r
}\r
\r
{ pagenode_free(datapages.root);\r
pagenode_free(namepages.root);\r
pagenode_free(refhashpages.root);\r
-}\r
\r
-/* Recursively clean pagenode linked list, freeing last first */\r
-static\r
-void pagenode_free\r
-( struct pagenode_t* pagenode )\r
-{ if (pagenode->header.next != NULL)\r
- pagenode_free(pagenode->header.next);\r
- free(pagenode);\r
}\r
\r
/* Link */\r
return (union ir_setdata_t*) link;\r
}\r
\r
-static inline\r
-void* pagelist_pop\r
-( struct pagelist_t* pagelist,\r
- size_t size\r
-)\r
-{ size_t headsize = PL_HEADSIZE((*pagelist));\r
- if (!headsize)\r
- { free(pagelist->head);\r
- pagelist->head = pagelist->root;\r
- while (pagelist->head->header.next != NULL)\r
- pagelist->head = pagelist->head->header.next;\r
- }\r
- if (headsize < size)\r
- eprintf("Attempted to pop unaligned value from pagelist\n");\r
- pagelist->head->header.head -= size;\r
- return pagelist->head->header.head;\r
-}\r
-\r
-static\r
-void* stack_alloc\r
-( size_t bytes )\r
-{ void* p;\r
- if (PL_HEADMEM(datapages) < bytes) \r
- pagelist_alloc(datapages);\r
- p = datapages.head->header.head;\r
- datapages.head->header.head += bytes;\r
- return p;\r
-}\r
\r
static\r
uint8_t* name_alloc\r
\r
static void crawl_class(struct ir_class_t*);\r
static void crawl_set(struct ir_set_t*,int);\r
+\r
void ir_test(void)\r
{ uprintf("IR From Directory: %s\n",getcwd(NULL,255));\r
crawl_class(&root_class);\r
if (root_class.root_set != NULL)\r
crawl_set(root_class.root_set, 0);\r
+ uprintf("starting binaryout \n");\r
+ ir_binout_init(&root_class);\r
}\r
\r
+\r
static\r
void crawl_class\r
( struct ir_class_t* class )\r
{ struct ir_class_t* iter;\r
for (iter = class->nextchild; iter != NULL; iter = iter->nextsib)\r
- { wprintf("%U/\n", iter->name);\r
+ { wprintf("Crawling class %U/\n", iter->name);\r
if(chdir((char*)iter->name))\r
eprintf("CHDIR %U from %s\n",iter->name,getcwd(NULL,255));\r
crawl_class(iter);\r
crawl_set(iter->root_set, 0);\r
uprintf("%U\\\n",iter->name);\r
if (chdir(".."))\r
- eprintf("CHDIR ..\n");\r
+ eprintf("CHDIR ..\n");\r
+ wprintf("Finished crawling class %U/\n", iter->name);\r
}\r
}\r
\r
-#define push_setp(setp) (*(struct ir_set_t**)stack_alloc(sizeof(struct ir_set_t*)) = setp)\r
+#define push_setp(setp) (*(struct ir_set_t**)stack_alloc(&datapages, sizeof(struct ir_set_t*)) = setp)\r
#define pop_setp() (*(struct ir_set_t**)pagelist_pop(&datapages, sizeof(struct ir_set_t*)))\r
static\r
void crawl_set\r
while (i--)\r
putchar('.');\r
i = depth;\r
+\r
for(iter = set; iter != NULL; iter = iter->nextchild)\r
{ uprintf("[%10U]", iter->name);\r
push_setp(iter);\r
i++;\r
}\r
+\r
putchar('\n');\r
while (--i >= depth)\r
if (((iter = pop_setp())->nextsib) != NULL)\r