added stb, more binaryout changes"
[henge/apc.git] / src / binaryout.c
index 94f8c29..f4eea8a 100644 (file)
@@ -29,7 +29,7 @@ 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;
+struct pagelist_t linkpages, datapages, plinkpages;
 
 enum model_type { SS };
 /* Binaryout out structure definitions */
@@ -73,12 +73,7 @@ struct bin_frame_header_t {
   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;
@@ -109,18 +104,15 @@ struct bin_attachment_list_t **attachment_stack, **asp; //attachment_stack, atta
 FILE* binaryout;
 
 
-
 #define  NAMEHASH(name, domain) (XXH32(name, u8_strlen(name), 0XCEED ) & domain) 
 
 static inline
 int bin_set_varcount
 ( ir_set set )
 { int count;
-  framebox set_fb;
   framebox iter;
-  set_fb = ir_set_framebox(set);
   count = 0;
-  for (iter = set_fb; iter != NULL; iter = ir_setdata_nextsib(iter))
+  for (iter = ir_set_framebox(set); iter != NULL; iter = ir_setdata_nextsib(iter))
     count++;
   return count;
 }
@@ -176,6 +168,9 @@ int bin_keys_identical
   return 0;    
 }
 
+
+typedef RGBA_t uint32_t;
+
 long bin_traverse_class(ir_class);
 /* Takes root class and begins processing */
 void
@@ -198,7 +193,7 @@ ir_binout_init(ir_class root_class)
       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
+long
 /* TODO: Should overwrite be a default? */
 bin_insert_ht_entry
 ( long ht_start,
@@ -230,6 +225,8 @@ bin_insert_ht_entry
        INC_ENTRY();
     }
   WRITE_ENTRY();
+
+  return entry_pos;
     
 }
 
@@ -364,6 +361,12 @@ bin_traverse_set
   
 }
 /* |   sdat header    |
+   |------------------|
+   |   num dlinks     |
+   |------------------|
+   |    dlink len     |
+   |------------------|
+   |   dlink string   |
    |------------------|
    |    variant ht    |
    |------------------|
@@ -375,10 +378,11 @@ bin_traverse_set
  
 */
 
-void bin_insert_links(int, struct bin_ht_header_t*, long);
+void bin_insert_links(struct bin_processed_lists_t*, 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);
+int bin_process_dlinks(struct bin_processed_lists_t*);
 
 /* 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 */
@@ -389,16 +393,22 @@ bin_process_sdat
   struct bin_attachment_list_t attachment_list;
   struct bin_pixel_node_t *default_pixel_list;
   struct bin_ht_header_t ht_header;
+  struct bin_processed_links_t* processed_links_root;
   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);
+  /* set up root for processed_links */
+  processed_links_root = stack_alloc(&plinkpages, bin_processed_links_t);
+  processed_links_root_val->mlink_len = processed_links_root->vlink_len = 0;
+  processed_links_root =  bin_process_links(set, processed_links_root);
+
+  num_links = processed_links_root->mlink_len + processed_links_root->vlink_len;
+  
   num_entries = bin_set_varcount(set) + num_links;
   
   HT_INIT(varht_start, varht_size, num_entries);
@@ -411,78 +421,111 @@ bin_process_sdat
   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);
+  /* Process dlinks */
+  bin_process_dlinks(processed_links_root);
+  
+  
   /* 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);
 
+  /* insert the links that were processed into the variant hash table */
+  bin_insert_links(processed_links_root, &ht_header, attachment_list.filepos);
+
   /* 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   */
 
+  /* free plinkpages and datapages */
+
 
   return sdat_start;
 }
+static inline
+void bin_process_dlinks
+( struct bin_processed_links_t* processed_links )
+{ struct bin_linklist_t* olink_iter;
+  ir_set trg_set;
+  for( dlink_iter = processed_links->dlink_list; dlink_iter != NULL; dlink_iter = dlink_iter->next)
+    { /* Construct its fully qualified name based on ?*/
+      /* Output an int for its length, and then output the name */
+          
+         
+    }
+}
 
+static inline
+struct bin_linklist_t* bin_linklist_head
+( struct bin_linklist_t* root )
+{ struct bin_linklist_t* head;
+  head = root;
+  while(head->next)
+    head = head->next;
+  return head;
+}
 
-/* 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
+/* We dont know src_pos at this point because this is still in the control flow
+   of bin_process_links, which determines the number of links, which determines
+   the hash table. */
+void
+#define PUSH_LINK(_LINK) (*(linkdata*) stack_alloc(&linkpages, sizeof(linkdata)) = _LINK)
 bin_process_vlink
-( ir_setdata vlink,
-  ir_set trg_set
-)
-{ struct bin_plink_t* plp;
+( linkdata vlink,
+  struct bin_processed_links_t* processed_links)
+{ struct bin_processed_links_t* plp;
+  struct bin_linklist_t* vlink_list_head;
+  linkdata new_vlink;
   ir_setdata fiter;
+  ir_set trg_set;
   uint8_t* link_name;
-  int num_links;
-
-  num_links = 0;
 
-  /* TODO: Macroize? or not worth? */
-  link_name = ir_setdata_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++;
+  vlink_list_head = bin_linklist_head(processed_links->vlink_list);
+  link_name = ir_setdata_name(vlink); 
+  if (link_name) 
+    { plp =  struct_alloc(bin_processed_links_t);
+      plp->linkdata = vlink;
+      vlink_list_head->next = plp;
+      processed_links->vlink_len++;
+      PUSH_LINK(vlink);
     }
   else // linking a variant hash table
-    for (fiter = ir_set_framebox(trg_set); fiter != NULL; fiter = ir_setdata_nextsib(fiter))
-      { plp = struct_alloc(bin_plink_t);
-       plp->src_pos = 0; // TBD @ process_setdata
-       plp->name = ir_setdata_name(fiter);
-       plp->trg_set = trg_set;
-       plp->type = VLINK;
-       num_links++;
+    { trg_set = ir_linkdata_set(vlink);
+      for (fiter = ir_set_framebox(trg_set); fiter != NULL; fiter = ir_setdata_nextsib(fiter))
+      { plp = struct_alloc(bin_processed_links_t);
+        new_vlink = struct_alloc(linkdata);
+       ir_linkdata_assign_name(new_vlink,ir_setdata_name(fiter));
+       ir_linkdata_assign_set(new_vlink,trg_set);
+       ir_linkdata_assign_type(new_vlink,VLINK);
+        plp->linkdata = vlink;
+        vlink_list_head->next = plp;
+        processed_links->vlink_len++;
+        PUSH_LINK(vlink);
       }
+    }
 
-  return num_links;
+  return processed_links;
 
 }
 
 /* Adds an mlink to the stack_alloc, to be processed later */
-int
+void
 bin_process_mlink
-( ir_setdata mlink,
-  ir_set trg_set
+( linkdata mlink,
+  bin_processed_links_t* processed_links
 )
-{ struct bin_plink_t* plp;
-  uint8_t* mlink_name;
-  mlink_name = ir_setdata_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;
+{ uint8_t* mlink_name;
+  struct bin_processed_links_t* mlink_list_head;
 
-  return 1;
+  mlink_list_head = bin_listlist_head(processed_links->mlink_list);
+  mlink_name = ir_setdata_name(mlink);
+  plp = stack_alloc(&linkpages, bin_linklist_t);
+  plp->header.filepos = 0; //TBD after resolving the childlist | TODO: attach_pos?
+  if(mlink_name) plp->name = mlink_name;// TODO: What does a mlink with a name mean? specifying the framebox mapsheet to use? 
+  plp->trg_set = ir_linkdata_set(mlink);
+  mlink_list_head->next = plp;
+  processed_links->mlink_len++;
+
+  return processed_links;
 }
 
 /* TODO: implement this */
@@ -490,91 +533,121 @@ bin_process_mlink
    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;
-
+( linkdata olink,
+  struct bin_processed_links_t* processed_links
+)
+{ struct bin_linklist_t* iter;
+  ir_set olink_set;
+  olink_set = ir_linkdata_set(olink);
+  for( iter = processed_links->olink_list; iter != NULL; iter = iter->next)
+    if(iter == olink_set)
+     return 1;  
   
-
   return 0;
-
 }
+/* if olink, process target sets frameboxes(turn into vlinks) and its attachment_list (turn into mlink),
+   else its a dlink so just add it to the processed_links list*/
+static inline
+void bin_process_olink
+( linkdata olink,
+  struct bin_processed_links_t* processed_links_root,
+  ir_set trg_set
+)
+{ struct bin_linklist_t* link_list_head;
+  if(trg_set)) //add olink to list so we can check for cycles
+    { bin_set_frameboxes_vlinks(trg_set, processed_links_root); //TODO: implement
+      bin_set_attachmentlist_mlink(trg_set, processed_links_root); //TODO: implement
+      link_list_head = bin_linklist_head(processed_links_root->olink_list);
+      link_list_head->next = struct_alloc(bin_linklist_t);
+      link_list_head->next->linkdata = olink;
+    }
+  else // olink is actually a dynamic link
+    { link_list_head = bin_linklist_head(processed_links_root->dlink_list);
+      link_list_head->next = struct_alloc(bin_linklist_t);
+      link_list_head->next->linkdata = olink;
+    }
+  
+}
+
+struct bin_linklist_t;
+struct bin_linklist_t 
+{ struct bin_linklist_t* next;
+  linkdata               linkdata;
+};
+
+struct bin_processed_links_t
+{ struct bin_linklist_t* vlink_list;
+  int                    vlink_len;
+  struct bin_linklist_t* mlink_list;
+  int                    mlink_len;
+  struct bin_linklist_t* olink_list; //keep track of olink cycles
+  int                    olink_len;
+  struct bin_linklist_t* dlink_list;
+  int                    dlink_len;
+};
 
 /* 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
+struct bin_processed_links_t* bin_process_links
 ( ir_set src_set,
-  ir_setdata olink_head
+  struct bin_processed_links_t* processed_links_root;
 )
-{ int num_links;
-  linkdata liter; //link iter
+{ struct bin_processed_links_t* returned_val;
+  linkdata linkdata;
   ir_set trg_set;
-
-  num_links = 0;
-  
-  for(liter = ir_set_link(src_set); liter != NULL; liter = ir_setdata_nextsib((ir_setdata) liter))
-    { trg_set = ir_set_from_ref(ir_linkdata_ref(liter));
-      switch (ir_linkdata_type(liter)) {
+  for(linkdata = ir_set_link(src_set); linkdata != NULL; linkdata = (linkdata) ir_setdata_nextsib((ir_setdata) linkdata))
+    { switch (ir_linkdata_type(linkdata)) {
       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);
+       if (olink_cycle(linkdata, processed_links_root)) 
+         return processed_links_root; //TODO: what return value? 
+       trg_set = ir_linkdata_set(linkdata);
+       bin_process_olink(trg_set, linkdata, processed_links_root);
+       bin_process_links(trg_set, processed_links_root);       
        break;
       case VLINK:
-       num_links += bin_process_vlink(liter, trg_set);
+       bin_process_vlink(linkdata, processed_links_root);
        break;
       case MLINK:
-        num_links += bin_process_mlink(liter, trg_set);
+        bin_process_mlink(linkdata, processed_links_root);  
        break;
       case ALINK: //TODO: ?
        break;
       }      
     }
-  return num_links;
+  return processed_links_root;
 }
 
 /* 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 )
+#define PUSH_PLINK(_LINK) (*(struct **) stack_alloc(&linkpages, sizeof (_LINK)) = _LINK )
 void
 bin_insert_links
-( int num_links,
+( struct bin_processed_links_t* links,
   struct bin_ht_header_t* ht,
   long attach_pos
 )
 { struct bin_plink_t* plp;
   struct bin_ht_entry_t ht_entry;
-  int i;
+  struct link_list_t* vlinkiter, mlinkiter;
+  long entry_pos;
+  
   
   /* 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
-      }
+  for ( vlinkiter = links->vlink_root; vlinkiter != NULL; vlinkiter = vlinkiter->next;)
+    { ht_entry.key = NAMEHASH(ir_setdata_name(vlinkiter->linkdata), ht->entries << 1);
+      ht_entry.value = 0;
+      entry_pos = bin_insert_ht_entry(ht->start, ht->entries * sizeof(ht_entry), &ht_entry, 0);     
+      ir_setdata_assign_fpos(vlinkiter->linkdata, entry_pos);
+      PUSH_PLINK(vlinkiter->linkdata);
     }
+  for ( mlinkiter = links->mlink_root; mlinkiter != NULL; mlinkiter = mlinkiter->next)
+    { >trg_set = plp->trg_set;
+      plp->src_pos = attach_pos;
+      PUSH_PLINK(plp);
+    }
+  /* Process dlinks here */
+
+     
 }
 
 long bin_process_facing(ir_setdata, apc_facing, struct bin_pixel_node_t*);
@@ -665,7 +738,7 @@ bin_process_facing
   int num_mapchannels, num_framechannels, x;
   struct bin_frame_header_t header;
   long facing_start;
-  unsigned char* mapdata, * framedata;
+  RGBA_t* mapdata, * framedata;
   uint8_t* png_suffix = ".png";
   struct bin_pixel_node_t* map_pixel_list;
 
@@ -673,8 +746,8 @@ bin_process_facing
 
   
   /* Set up data pointers to mapsheet and framesheet, as well as their image infos */
-  mapdata = stbi_load(GENERATE_FILENAME(ir_setdata_name((ir_setdata) ir_framebox_mapsheet(framebox,SFACE))), &mapsheet_info.width, &mapsheet_info.width, &num_framechannels , 0);
-  framedata = stbi_load(GENERATE_FILENAME(ir_setdata_name((ir_setdata) ir_framebox_framesheet(framebox,SFACE))), &framesheet_info.width, &framesheet_info.height, &num_mapchannels, 0);
+  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);
+  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);
   bin_set_img_info(&framesheet_info, ir_framebox_framesheet(framebox, SFACE));
   bin_set_img_info(&mapsheet_info, ir_framebox_mapsheet(framebox, SFACE));
 
@@ -829,31 +902,6 @@ bin_insert_node_into_list
 
 }
 
-/* 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 = NULL;
-  if(*data)
-    { pixel_node = struct_alloc(bin_pixel_node_t);
-      /* get ref from 4 bytes of data */  
-      pixel_node->data.ref = (int) data;
-      /* bitshift by ? to get Z */
-      pixel_node->data.z = ((int) data << 24);
-      /* set x and y */
-      pixel_node->data.x = x + init_width ;
-      pixel_node->data.y = y + init_width;
-    }
-  *data += 4;
-  return pixel_node;
-      
-}
-
 /* Returns the non null pixels of a single map */
 /* TODO: Finish this */
 struct bin_pixel_node_t* 
@@ -861,10 +909,10 @@ bin_mapframe_to_pixel_list
 ( struct bin_img_info_t* img_info,
   int init_height,
   int init_width,
-  unsigned char* data
+  RBGA_t* data
 )
 { int x, y, fheight, fwidth;
-  struct bin_pixel_node_t* pixel_list, * pixel_node;
+  struct bin_pixel_node_t* pixel_list,* pixel_node;
 
   pixel_list = NULL;
 
@@ -890,13 +938,22 @@ bin_mapframe_to_pixel_list
   /* Process the map*/
   for (y = 0; y < fheight; y++)
     { for ( x = 0; x < fwidth; x++ )
-        { pixel_node = bin_process_pixel(data, x, y, init_height, init_width);
-          pixel_list = bin_insert_node_into_list(pixel_list, pixel_node);
-         data += img_info->width - img_info->fwidth; //stride
-        }
+      { if (*data)
+         { pixel_node = struct_alloc(bin_pixel_node_t);
+           /* get ref from 4 bytes of data */  
+           pixel_node->data.ref =  (*data) >> 8;
+           /* bitshift by ? to get Z */
+           pixel_node->data.z = (*data & 0xFF);
+           /* set x and y */
+           pixel_node->data.x = x + init_width;
+           pixel_node->data.y = y + init_width;
+           pixel_list = bin_insert_node_into_list(pixel_list, pixel_node);
+         }
+       data++;
+      }
+      data += img_info->width - img_info->fwidth; //stride
     }
-
-  return pixel_list;   
+  return pixel_list;
 }
 
 static inline
@@ -948,14 +1005,14 @@ 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;
+  RGBA_t* data;
   int num_channels;
   struct bin_img_info_t img_info;
   
   for (fiter = ir_set_framebox(set); fiter != NULL; fiter = ir_setdata_nextsib(fiter))
     { /* TODO: Stringify the frame name with .png? */
       /* TODO: Add directory changing */
-      data = stbi_load(ir_setdata_name((ir_setdata) ir_framebox_mapsheet(fiter,SFACE) ), &img_info.width, &img_info.width, &num_channels, 0);
+      data = (RGBA_t*) stbi_load(ir_setdata_name((ir_setdata) ir_framebox_mapsheet(fiter,SFACE) ), &img_info.width, &img_info.width, &num_channels, 0);
       bin_set_img_info(&img_info, ir_framebox_mapsheet(fiter, SFACE));
       curr_pixel_list = bin_mapframe_to_pixel_list(&img_info, 0, 0, data);
       default_pixel_list = bin_cmp_default_pixel_lists(curr_pixel_list, default_pixel_list);