/*!@file \brief IR Memory Implementation \details Intermediary memory management \author Jordan Lavatai \date Aug 2016 ----------------------------------------------------------------------------*/ #include #include #include //uint8_t as a char #include //u32_cpy #include //uint64_t #include //memset #include //u8_* functions #include "apc.h" extern int name_u8_cpy(struct name*, struct name*); extern int name_u8_cmp(struct name*, struct name*); extern int name_u8_set(struct name*, ucs4_t); int ir_init(void); struct cdat* alloc_cdat(void); struct odat* alloc_odat(void); void alloc_vdat(void); struct link* alloc_link(void); struct ref* alloc_ref(void); struct set* alloc_set(void); struct cdat* curr_cdat(void); struct odat* curr_odat(void); struct vdat* curr_vdat(void); struct map* curr_map(void); struct set* curr_cdat_set(void); struct set* curr_set(int); struct ref* curr_ref(void); struct model* curr_model(void); /* ir.c */ void inc_posts(void); void push_cdat(struct name*); void pop_cdat(void); void insert_link_name(struct name*); void insert_link_namelist(struct name*); void insert_ss_name(struct name*); void insert_ss_namelist(struct name*); void insert_mlink(struct name*, int); void insert_vlink(struct name*, int); void insert_ref(struct odat*, int); void alloc_vdat(void); void insert_vdat(void); void insert_map(struct name*, int, int, int, int, uint8_t*); void insert_framesheet(struct name*, int, int, int, int, uint8_t*); //type safety handled by macro expansion (do not call these directly from code, make dependent macros for access to these) #define CHUNKS_LEN(STACK) ((STACK).csp - (STACK).chunks) #define CURRENT_CHUNK(STACK) ((STACK).chunks[CHUNKS_LEN(STACK) - 1]) #define CHUNKS_FULL(STACK) ( (STACK).csp >= \ (STACK).chunks + MAX_CHUNKS * (STACK).chunk_size) #define CURRENT_DSP(STACK,TYPE) ((TYPE*) ((STACK).dsp[CHUNKS_LEN(STACK) - 1])) #define DATA_FULL(STACK,TYPE) ((void*) CURRENT_DSP(STACK,TYPE) >= \ (CURRENT_CHUNK(STACK) + (STACK).chunk_size)) #define CSP_PUSH(STACK) (*(++(STACK).csp) = malloc((STACK).chunk_size)) #define CURRENT_DATP(STACK,TYPE) (((TYPE**)(STACK).dsp)[CHUNKS_LEN(STACK) - 1]) #define PREVIOUS_DATP(STACK,TYPE) (((TYPE**)(STACK).dsp)[CHUNKS_LEN(STACK) - 2]) #define ALLOC_DAT(STACK,TYPE) (++CURRENT_DATP(STACK,TYPE)) #define INIT_STACK(STACK,TYPE) \ { int i; \ (STACK).chunk_size = PAGES_PER_CHUNK * pagesize; \ (STACK).max_dats = (STACK).chunk_size / sizeof (TYPE); \ CSP_PUSH(STACK); \ for( i = 0; i < MAX_CHUNKS; i++){ \ (STACK).dsp[i] += pagesize; \ } \ } //Stack-specific macros (called directly from code (safety enforcement) #define INIT_ODAT() (INIT_STACK(ocs, struct odat)) #define CURRENT_ODAT() (CURRENT_DATP(ocs,struct odat)) #define ODAT_FULL() (DATA_FULL(ocs,struct odat)) #define ODAT_ALLOC() (ALLOC_DAT(ocs,struct odat)) #define OCS_FULL() (CHUNKS_FULL(ocs)) #define INIT_VDAT() (INIT_STACK(vcs, struct vdat)) #define CURRENT_VDAT() (CURRENT_DATP(vcs,struct vdat)) #define VDAT_FULL() (DATA_FULL(vcs,struct vdat)) #define VDAT_ALLOC() (ALLOC_DAT(vcs,struct vdat)) #define VCS_FULL() (CHUNKS_FULL(vcs)) #define INIT_CDAT() (INIT_STACK(ccs, struct cdat)) #define CURRENT_CDAT() (CURRENT_DATP(ccs,struct cdat)) #define CDAT_FULL() (DATA_FULL(ccs, struct cdat)) #define CDAT_ALLOC() (ALLOC_DAT(ccs, struct cdat)) #define CCS_FULL() (CHUNKS_FULL(ccs)) #define INIT_SET() (INIT_STACK(scs, struct set)) #define CURRENT_SET() (CURRENT_DATP(scs, struct set)) #define SET_FULL() (DATA_FULL(scs, struct set)) #define SET_ALLOC() (ALLOC_DAT(scs, struct set)) #define SCS_FULL() (CHUNKS_FULL(scs)) #define INIT_LINK() (INIT_STACK(lcs, struct link)) #define CURRENT_LINK() (CURRENT_DATP(lcs,struct link)) #define LDAT_FULL() (DATA_FULL(lcs, struct link)) #define LDAT_ALLOC() (ALLOC_DAT(lcs, struct link)) #define LCS_FULL() (CHUNKS_FULL(lcs)) #define INIT_POST() (INIT_STACK(rcs, struct ref)) #define CURRENT_POST() (CURRENT_DATP(pcs,struct ref)) #define POST_FULL() (DATA_FULL(pcs,struct ref)) #define POST_ALLOC() (ALLOC_DAT(pcs,struct ref)) #define PCS_FULL() (CHUNKS_FULL(pcs)) #define INIT_REF() (INIT_STACK(rcs, struct ref)) #define CURRENT_REF() (CURRENT_DATP(rcs,struct ref)) #define PREVIOUS_REF() (PREVIOUS_DATP(rcs, struct ref)) #define REF_FULL() (DATA_FULL(rcs,struct ref)) #define REF_ALLOC() (ALLOC_DAT(rcs,struct ref)) #define RCS_FULL() (CHUNKS_FULL(rcs)) //Metadata #define CURRENT_MODEL() (CURRENT_VDAT()->model_list[CURRENT_VDAT()->num_models]) /* Dynamically allocate memory for a class data structure, or cdat, after a class has been identified in a grammar. We also create a stack of class pointers so that we can access the cdat during processing of that cdats sets and elements, a requirement because the nature of recursive classes prevents us from accessing the cdat based on the previous index into cdat_buf, which is a list of all allocated cdats /* Cdats: A cdat is a class data structure. Cdats serve as the central */ /* data types of the IR. Cdats contain pointers to their subclasses so that the relationship between */ /* classes can be determined, but the subclasses are not represented inside */ /* of the cdat itself but rather in subsequent cdats in cdat_buf. We */ /* can determine the number of subclasses (the last index into cdat_buf */ /* that represents a subclass of some arbitrary cdat) each cdat has by */ /* incrementing num_classes during parse time. */ /* TODO: Should classes point to their parent class? */ /* TODO: Talk more about cdat set structure */ struct cdat { struct name name; int idx; int num_classes; int num_sets; struct cdat* class_list[MAX_CLASSES]; struct set* set_list[MAX_SETS]; }; /* Sets: What is a set? Instantiation? Associations? Containment? Usage? The set is populated at parse time AFTER the elements are populated, due to the nature of bottom up parsing. */ struct set { int cdat_idx; int num_sets; struct set* set_list[MAX_SETS]; }; /* Refs: Each set/ele has a reference to its object data (odat) through a refid. refids are unsigned 64 byte integers that map to the hex values RGBA. During the construction of the directory structure, users can choose a RGBA value for each object that any other object can refer to via links (see link). If a user does not choose an RGBA value, then the object is given one from the system space. We maintain a doubly linked list of refs in the ref_buf at parse time so that links can be resolved after the parsing of the directory structure is complete. For every 16th ref, we create a post so that we can reduce on the search time for a random access. */ struct ref { int type; //TODO: Is this needed? struct ref* nextref; struct ref* lastref; struct odat* odatp; int refid; //0xFFFFFF->digit }; /* Links: At parse time, a set/ele can include a link in their grammar representation instead of the actual data and this signifies to the APC that that set/ele wishes to use the data of another set/ele, either its video data (vdat) or object data (odat). The link itself contains the type of link it is, the refid OR name, and which set/ele created the link. During parse time, links can be made to o/vdats that have yet to be parsed. In order to accomodate for this, we resolve all links AFTER parse time by iterating through the link_buf, finding the refid that was stored for some object (if the refid exists), and creating a relative pointer from the original object to the data that was linked */ /* TODO: Explain links more betta */ struct olink { int src_refid; }; struct vlink { int src_refid; struct name src_animname; struct name src_namelist[MAX_DEPTH]; }; struct mlink { int src_refid; struct name src_mapname; struct name src_namelist[MAX_DEPTH]; }; union link_t { struct vlink vlink; struct mlink mlink; struct olink olink; }; /* From: src odat ()To: dest odat (refid)*/ struct link { int type; //1 = olink, 2 = vlink, 3 = mlink union link_t link_t; int dest_refid; //if it exists struct odat* dest_odatp; }; struct map { struct name name; int height; int width; uint8_t filepath[FPATH_MAX]; }; /* Odats: Odats consist of the object data necessary for each object. Odats are sometimes referred to as archetypes at compile-time, in order to distinguish the difference from a runtime object and a compile-time object. TODO: Need more info about objects at runtime, to described the reasoning behind odat structure at compile-time*/ struct odat { struct name name; int refid; int ismap; int vdat_idx; struct link* linkp; struct vdat* vdatp; struct odat* parent_odatp; // odat == set ? null : set refid struct ref* refp; /* pointer to it's ref on ref_list */ struct map map; //only valid if odat ismap }; /* A framesheet is a grouping of animation frames in a single direction (N,W,S,E) */ struct framesheet { int width; int height; int num_frames; }; /* A model is a collection of framesheets for every direction (N,W,S,E,NW,NE,SW,SE)*/ /* NAMED spritesheet */ struct model { struct name name; uint8_t filepath[PATH_MAX]; struct framesheet spritesheet[8]; //one for each }; /* Vdat: Vdats are the video data of each object. They can not be created as a stand alone object (because they consist solely of animation information and not the map which the animation manipulates). Vdats have a list of models for every animation that the vdats odat can do for that vdat*/ struct vdat { struct odat* creator; //pointer to odat that made this vdat int num_models; uint8_t filename[FNAME_MAX]; int height; int width; uint8_t filepath[FPATH_MAX]; struct model model_list[MAX_MODELS]; }; struct set_frame { struct name namelist[MAX_DEPTH]; int num_names; struct set* setp; struct odat* odatp; } ; struct set_stack { struct set_frame set_frames[MAX_DEPTH]; int curr_depth; //used to get most recently created set/odat + to check for undefined parents of namelists }; //"type free" chunk stacking struct chunk_stack { void* chunks[MAX_CHUNKS]; void* *csp; //chunk stack pointer void* dsp[MAX_CHUNKS]; //dat stack pointer (per chunk) int chunk_size; //size of a chunk (including its forfeited page) int max_dats; //number of dats per chunk for this stack } ocs, vcs, ccs, rcs, lcs, pcs, scs; //odat, vdat, cdat, ref, link, post stacks /* The cdat_stack is a stack pointers to cdat pointers, the top of which is the cdat that is currently being parsed. Whenever a new cdat is recognized by the grammar (CLOPEN), a cdat is pushed onto the cdat_stack, and we refer to this cdat through the macro CURR_CDAT. By keeping a cdat_stack, we have access to the current cdat so that the elements and sets can populate themselves in the cdat accordingly. */ struct cdat* cdat_stack[MAX_CLASSES]; struct cdat** cdat_stackp; struct set_stack ss; struct name set_namelist[MAX_DEPTH]; int set_numnames = 0; struct name link_namelist[MAX_DEPTH]; int link_numnames = 0; int num_cdats = 0; int num_odats = 0; int num_vdats = 0; int num_sets = 0; int num_refs = 0; int ss_refid = 0x0FFFFFFF; /* system space for refids */ int num_posts = 0; int num_links = 0; int num_models = 0; long pagesize = 0; /* The initalization function of the IR. */ int ir_init() { struct name name; uint8_t root[4] = "root"; u8_stpncpy(name.name, root, 4); pagesize = sysconf(_SC_PAGESIZE); printf("pagesize is %l\n", pagesize); INIT_CDAT(); *cdat_stackp = CURRENT_CDAT(); name_u8_cpy(&(*cdat_stackp)->name, &name); INIT_ODAT(); INIT_VDAT(); VDAT_ALLOC(); //NULL vdat VDAT_ALLOC(); //First vdat req. because alloc_vdat happens after vdat is reduced INIT_SET(); INIT_LINK(); INIT_REF(); INIT_POST(); return 0; } void ir_quit() { int i; for(i = 0; i < CHUNKS_LEN(ccs) ; i++) { free(ccs.chunks[i]); } for(i = 0; i < CHUNKS_LEN(ocs); i++) { free(ocs.chunks[i]); } for(i = 0; i < CHUNKS_LEN(vcs) ; i++) { free(vcs.chunks[i]); } for(i = 0; i < CHUNKS_LEN(rcs); i++) { free(rcs.chunks[i]); } for(i = 0; i < CHUNKS_LEN(lcs); i++) { free(lcs.chunks[i]); } for(i = 0; i < CHUNKS_LEN(pcs); i++) { free(pcs.chunks[i]); } } struct cdat* alloc_cdat() { num_cdats++; if(CDAT_FULL()) { if(CCS_FULL()) { fprintf(stderr, "You have allocated to many (%d) cdats ", num_cdats); exit(EXIT_FAILURE); } else CSP_PUSH(ccs); } else CDAT_ALLOC(); return CURRENT_CDAT(); } //these should probably be inline struct odat* alloc_odat () { num_odats++; if(ODAT_FULL()) { if(!OCS_FULL()) { fprintf(stderr, "You have allocated to many (%d) odats ", num_odats); exit(EXIT_FAILURE); } else CSP_PUSH(ocs); } else ODAT_ALLOC(); return CURRENT_ODAT(); } void alloc_vdat () { num_vdats++; if(VDAT_FULL()) { if(!VCS_FULL()) { fprintf(stderr, "You have allocated to many (%d) vdats ", num_vdats); exit(EXIT_FAILURE); } else CSP_PUSH(vcs); } else VDAT_ALLOC(); } struct set* alloc_set () { num_sets++; if(SET_FULL()) { if(!SCS_FULL()) { fprintf(stderr, "You have allocated to many (%d) sets ", num_sets); exit(EXIT_FAILURE); } else CSP_PUSH(scs); } else SET_ALLOC(); return CURRENT_SET(); } struct link* alloc_link () { num_links++; if(LDAT_FULL()) { if(!LCS_FULL()) { fprintf(stderr, "You have allocated to many (%d) links ", num_links); exit(EXIT_FAILURE); } else CSP_PUSH(lcs); } else LDAT_ALLOC(); return CURRENT_LINK(); } struct ref* alloc_ref () { num_refs++; if(REF_FULL()) { if(!RCS_FULL()) { fprintf(stderr, "You have allocated to many (%d) refs ", num_refs); exit(EXIT_FAILURE); } else CSP_PUSH(rcs); } else REF_ALLOC(); if(num_refs % 16 == 0) { CURRENT_POST() = CURRENT_REF(); inc_posts(); } return CURRENT_REF(); } void inc_posts() { num_posts++; if(POST_FULL()) { if(!PCS_FULL()) { fprintf(stderr, "You have allocated to many (%d) refs ", num_posts); exit(EXIT_FAILURE); } else CSP_PUSH(pcs); } else POST_ALLOC(); } struct cdat* curr_cdat () { return (*cdat_stackp); } struct odat* curr_odat () { return CURRENT_ODAT(); } struct vdat* curr_vdat () { return CURRENT_VDAT(); } struct set* curr_cdat_set () { return CURRENT_SET(); } struct set* curr_set (int depth) { int i; struct set* setp; for(i = 0; i <= depth; i++) { if(!(setp = setp->set_list[setp->num_sets])) { printf("You are trying to access a set that does not exist irmem.c\n"); return NULL; } } return setp; } struct ref* curr_ref () { return CURRENT_REF(); } struct ref* prev_ref () { return PREVIOUS_REF(); } struct model* curr_model () { return &CURRENT_MODEL(); } /* IR.C*/ void push_cdat ( name ) struct name* name; { struct cdat* curr_cdatp; curr_cdatp = alloc_cdat(); name_u8_cpy(&curr_cdatp->name, name); curr_cdatp->idx = num_cdats; /* Set the cdat as a subclass of the previous cdat */ (*cdat_stackp)->class_list[(*cdat_stackp)->num_classes] = curr_cdatp; /* Push the cdat onto the cdat_stack */ *++cdat_stackp = curr_cdatp; } void pop_cdat () { cdat_stackp--; } void insert_set_name ( name ) struct name* name; { //Push name onto current namelist, set the set_namelist. name_u8_cpy(&set_namelist[set_numnames++], name); } void insert_set_namelist ( name ) struct name* name; { int depth, nameidx, i; insert_set_name(name); //Check if entire string matches first? Only possible if namelist is contiguous (uint8_t strings seperated by \0) //Create odats/sets for each name in namelist where nameidx > ns_depth //first check if any parts of namelist matches what is currently on namestack //we can gauruntee that from ns_depth + 1 -> set_numnames namelists dont match. x //if name_list doesnt match, from the first depth at which namelist doesnt match //remove the nameframes namelist (zero out ones below?) and replace with current namelist, //then allocate a new odat and set it to the current set_frame. for( depth = 0; depth < set_numnames ; depth++ ) { for (nameidx = 0; nameidx <= depth; nameidx++) { if( name_u8_cmp(&set_namelist[nameidx], &ss.set_frames[depth].namelist[nameidx]) != 0 ) { /* Populate the namelist of the set at the current depth */ for(i = 0; i <= depth; i++) name_u8_cpy(&ss.set_frames[depth].namelist[i], &set_namelist[i]); /* Alloc set and odat */ ss.set_frames[depth].odatp = alloc_odat(); ss.set_frames[depth].setp = alloc_set(); /* populate set/odat name and cdat_idx */ name_u8_cpy(&ss.set_frames[depth].odatp->name, &set_namelist[depth]); ss.set_frames[depth].setp->cdat_idx = ( *cdat_stackp)->idx; /* Insert allocated set and odat into their respective trees if there is a depth (they have parents) */ if(depth) { ss.set_frames[depth].odatp->parent_odatp = ss.set_frames[depth-1].odatp; if(ss.set_frames[depth-1].setp->num_sets < MAX_SETS) ss.set_frames[depth-1].setp->set_list[ss.set_frames[depth-1].setp->num_sets++] = ss.set_frames[depth].setp; else { printf("you have allocated too many sets in insert_namelist()\n"); //TODO: EXIT() } } else /* no parent set, so assign to cdat set_list */ { ss.set_frames[depth].odatp->parent_odatp = NULL; //no parent odat = NULL. if(curr_cdat_set()->num_sets < MAX_SETS) curr_cdat_set()->set_list[curr_cdat_set()->num_sets++] = ss.set_frames[depth].setp; else { printf("you have allocated too many sets in insert_namelist()\n"); //TODO: EXIT() } } ss.set_frames[depth].num_names = set_numnames; ss.curr_depth = depth; } } } done: ; } /*. We create new odats for each map variant that are children of the current odat/set , set their name as the map name, and identify them by marking them as a map. This lets us distinguish between sibling odatsthat have the same name because the map of the parent odat had the same name as another, regular odat*/ #define CURR_SS_FRAME() (ss.set_frames[ss.curr_depth]) #define CURR_SS_SETP() (CURR_SS_FRAME().setp) #define CURR_SS_ODATP() (CURR_SS_FRAME().odatp) void insert_map ( name, direction, height, width, refid, filepath ) struct name* name; int direction, height, width, refid; uint8_t* filepath; { int i; struct odat* curr_mem_odatp; //pointer to odat in odat_buf struct set* curr_mem_setp; //pointer to set in set_buf struct link* linkp; curr_mem_odatp = alloc_odat(); curr_mem_setp = alloc_set(); //Create a new odat, make its parent be the set. Make a set for mdat, its name should //be the name of the odat + name of model. That makes a conflict beween odats that are named //the same thing as the model of a sibling odat that was created from a map. They can have //same name if the map odat is marked. So mark the map odat. //insert parent odat curr_mem_odatp->parent_odatp = CURR_SS_ODATP(); //insert into set_list if(CURR_SS_SETP()->num_sets < MAX_SETS) CURR_SS_SETP()->set_list[CURR_SS_SETP()->num_sets++] = curr_mem_setp; else { printf("You have allocated to many sets, error in insert_map()\n"); //TODO: EXIT() } //indicate that newly created odat is a map curr_mem_odatp->ismap = 1; //set odat and set name name_u8_cpy(&curr_mem_odatp->name, name); /* set cdat idx values for both set and odat */ curr_mem_setp->cdat_idx = num_cdats; /* Generate refid if needed, put into ref_buf */ if(!refid) refid = ss_refid++; insert_ref(curr_mem_odatp, refid); /* If current odatp on stack has a link, then we need to make our own link. just set the vdat_idx */ if(CURR_SS_ODATP()->vdat_idx = 0) { //alloc a link linkp = alloc_link(); linkp->type = CURR_SS_ODATP()->linkp->type; linkp->dest_odatp = CURR_SS_ODATP(); linkp->dest_refid = refid; linkp->link_t.mlink.src_refid = CURR_SS_ODATP()->linkp->link_t.mlink.src_refid; /* Copy the animation name of the vlink*/ name_u8_cpy(&linkp->link_t.vlink.src_animname, &CURR_SS_ODATP()->linkp->link_t.vlink.src_animname); /* Copy the namelist of the vlink*/ for(i = 0; i < MAX_DEPTH; i++) name_u8_cpy(&linkp->link_t.vlink.src_namelist[i], &CURR_SS_ODATP()->linkp->link_t.vlink.src_namelist[i]); } else curr_mem_odatp->vdat_idx = CURR_SS_ODATP()->vdat_idx; } /* 11/22 Each vdat has a multiple models. Each model has 8 framesheets, one in each direction, that create a spritesheet. Inserting framesheets into the correct model is just a matter of checking whether or not the last models name matches the current one. We can never get a framesheet that is for the same model before AND after some other model, due to alphasorting of the files in each directory */ void insert_framesheet ( model_name, direction, height, width, refid, filepath ) struct name* model_name; int direction, height, width, refid; uint8_t* filepath; { struct vdat* curr_vdatp; struct model* curr_modelp; static struct name last_model_name[32]; curr_vdatp = curr_vdat(); /* If the model name changed, that means there are no more framesheets for that model to be processed, a guaruntee we make b/c the filenames are alphabetically sorted */ if(!name_u8_cmp(last_model_name, model_name)) { if(curr_vdatp->num_models) curr_vdatp->num_models++; num_models++; // total number of models } if(CURR_SS_ODATP()->refid == 0) { if(!refid) refid = ss_refid++; insert_ref(CURR_SS_ODATP(), refid);//given a odatp and a refid, insert the odatp into the ref_buf. //push ref into ref_buf. } else printf("error: redefining a previously set refid\n"); curr_modelp = curr_model(); name_u8_cpy(&curr_modelp->name, model_name); curr_modelp->spritesheet[direction].height = height; curr_modelp->spritesheet[direction].width = width; name_u8_cpy(last_model_name, model_name); } //src_path is stored in link_namelist void insert_mlink ( src_mapname, src_refid) struct name* src_mapname; int src_refid; { struct link* linkp; int i; linkp = alloc_link(); /* set type */ linkp->type = 3; /* set the name of the src map for the link, if a name exists */ if(src_mapname) name_u8_cpy(&linkp->link_t.mlink.src_mapname, src_mapname); /* Set the source ref id of the link */ linkp->link_t.mlink.src_refid = src_refid; /* Copy the entire namelist of the link, if it exists */ for(i = 0; i < link_numnames; i--) //TODO MAX_DEPTH -> link_namelist_num?? { name_u8_cpy(&linkp->link_t.mlink.src_namelist[i], &link_namelist[i]); name_u8_set(&link_namelist[i], (ucs4_t) 0); } link_numnames = 0; linkp->dest_odatp = CURR_SS_ODATP();//current odat on set_stack } void insert_link_name ( name ) struct name* name; { //Push name onto current namelist, set the set_namelist. name_u8_cpy(&link_namelist[link_numnames++], name); } /* Nearly identical to mlink */ void insert_vlink ( src_animname, src_refid ) struct name* src_animname; int src_refid; { struct link* linkp; int i; linkp = alloc_link(); /* set type */ linkp->type = 2; /* set the name of the src animname for the link, if a name exists */ if(src_animname) name_u8_cpy(&linkp->link_t.vlink.src_animname, src_animname); /* Set the source ref id of the link */ linkp->link_t.mlink.src_refid = src_refid; /* Copy the entire namelist of the link, if it exists */ for(i = 0; i < link_numnames; i++) //TODO MAX_DEPTH -> link_namelist_num?? { name_u8_cpy(&linkp->link_t.vlink.src_namelist[i], &link_namelist[i]); name_u8_set(&link_namelist[i], (ucs4_t) 0);//set to null for next link_namelist } linkp->dest_odatp = CURR_SS_ODATP();//current odat on set_stack } /* TODO: Do we really need to store the prev/next pointer? iterating through the ref_buf could be achieved by iterating until the num_refs anyway. */ void insert_ref ( odatp, refid ) struct odat* odatp; int refid; { struct ref* curr_refp; struct ref* prev_refp; curr_refp = alloc_ref(); prev_refp = prev_ref(); prev_refp->nextref = curr_refp; curr_refp->lastref = prev_refp; curr_refp->odatp = odatp; curr_refp->refid = refid; if(refid % 16) { POST_ALLOC(); CURRENT_POST()->refid = refid; CURRENT_POST()->odatp = odatp; } } void insert_vdat () { struct odat* curr_ss_odatp; struct vdat* curr_vdatp; curr_vdatp->creator = curr_ss_odatp; curr_ss_odatp->vdat_idx = num_vdats; curr_ss_odatp->vdatp = curr_vdatp; alloc_vdat(); } void insert_refid_statement ( refid ) int refid; { CURR_SS_ODATP()->refid = refid; } #if 0 /* Called in the reduction of a set. While both odats (eles and sets) have identical label terminals, we are unable to give a single grammatical rule for both due to how we allocate odats in the odat buf. Due to the nature of bottom up parsing, the set label is recognized first, and then the sets elements are recognized. This means that after we have processed the sets elemenets, the curr_odat is going to be the last element and NOT the set that was first allocated. To get around this, we create a global variable set_odatp that will store the pointer to the odat when it is first allocated (in insert_set_label()) so that insert_set() can have access to it. Curr set points the sets representation in the cdat, curr_set_odatp points to the sets representation as an odat*/ //TODO: Add insert_set_ref() //TODO: Is this the correct allocation scheme? No do the one ken suggested void insert_s_name ( struct name* name ) { struct set* curr_setp; curr_setp = curr_set(); curr_set_odatp = alloc_odat(); u8_cpy(curr_set_odatp->name, name, 32); u8_cpy(curr_setp->name, name, 32); curr_set_odatp->parent_odatp = NULL; } /* Inserting a olink instead of a set. Set is really just a placeholder for another set. Allocate the memory for the set so taht it can be populated*/ void insert_set_olink ( int refid ) { struct set* curr_setp; curr_setp = curr_set(); curr_setp->refid = refid; } void insert_set_vlink ( int refid, uint8_t* anim_name ) { struct cdat* curr_cdatp; struct odat* curr_odatp; struct link* curr_linkp; curr_cdatp = curr_cdat(); curr_odatp = curr_odat(); curr_linkp = alloc_link(); /* Insert vlink into link_stack so that it gets processed at output time */ curr_linkp->type = 2; /* Store the target odat information*/ curr_linkp->link_t.vlink.refid = refid; u8_cpy(curr_linkp->link_t.vlink.anim_name, anim_name, 32); /* Store the linking odat/cdat information */ curr_linkp->classp = curr_cdatp; curr_linkp->odatp = curr_odatp; curr_linkp->set_idx = curr_cdatp->num_sets; // curr_linkp->ele_idx = -1; } /* Svlinks dont have animation names */ void insert_set_svlink ( int refid ) { struct cdat* curr_cdatp; struct link* curr_linkp; curr_cdatp = curr_cdat(); curr_linkp = alloc_link(); /* Insert svlink into link_stack so that it gets processed at output time */ curr_linkp->type = 3; curr_linkp->classp = curr_cdatp; curr_linkp->set_idx = curr_cdatp->num_sets; // curr_linkp->ele_idx = -1; curr_linkp->link_t.svlink.refid = refid; } /* At the point of reducing to a set, most of the sets odat information has already been populated during the reduction of its right hand side non terminals (hitbox, root, quad_list). */ void insert_set () { int refid; struct odat* curr_odatp; struct cdat* curr_cdatp; struct set* curr_setp; struct ref* prev_refp; struct ref* curr_refp; struct vdat* curr_vdatp; curr_odatp = curr_set_odatp; //allocated at insert_set_label curr_cdatp = curr_cdat(); curr_setp = curr_set(); prev_refp = curr_ref(); curr_refp = alloc_ref(); curr_vdatp = curr_vdat(); curr_vdatp->creator = curr_set_odatp; curr_setp->cdat_idx = curr_cdatp->idx; //does a set need its class idx? u8_cpy(curr_setp->name, curr_odatp->name, 32); curr_cdatp->num_sets++; curr_odatp->cdat_idx = curr_cdatp->idx; curr_odatp->refp = curr_refp; refid = curr_setp->refid; // refid set by insert_set_label(name, refid) curr_refp->refid = refid; curr_refp->lastref = prev_refp; curr_refp->odatp = curr_odatp; prev_refp->nextref = curr_refp; } /* Created as a seperate function, instead of setting the ODATS vdat_id and calling inc_vdat() inside of insert_set(), to account for the set reduction where a vdat is not created (o/v/svlinks). */ void insert_set_vdatid () { struct vdat* curr_vdatp; curr_vdatp = curr_vdat(); curr_set_odatp->vdat_id = num_vdats; //no vdat_id for odats that have vlinks/svlinks curr_set_odatp->vdatp = curr_vdatp; curr_set_odatp = NULL; //This sets odat shouldnt be modified after populating odats vdat info } /* Populates the odat name and refid for odat, allocate the odat here for the rest of the functions to use via curr_odat(). */ void insert_ele_label ( uint8_t* name, int refid ) { struct odat* curr_odatp; curr_odatp = alloc_odat(); u8_cpy(curr_odatp->name, name, 32); curr_odatp->map[0] = 0; if(refid != -1) curr_odatp->refid = refid; else curr_odatp->refid = ss_refid++; } /* We don't make an odat here, at output time we will resolve the refid to the corresponding odat. */ void insert_ele_olink ( int refid ) { /* Do nothing because we already know the refid that the odat needs for this element (in the quad_file) */ } void insert_ele_vlink ( int refid, uint8_t* anim_name ) { struct cdat* curr_cdatp; struct set* curr_setp; struct link* curr_linkp; curr_cdatp = curr_cdat(); curr_setp = curr_set(); curr_linkp = alloc_link(); /* Insert vlink into link_stack so that it gets processed at output time */ curr_linkp->classp = curr_cdatp; curr_linkp->type = 2; curr_linkp->set_idx = curr_cdatp->num_sets; //curr_linkp->ele_idx = curr_setp->num_ele; curr_linkp->link_t.vlink.refid = refid; u8_cpy(curr_linkp->link_t.vlink.anim_name, anim_name, 32); } void insert_ele_svlink ( int refid ) { struct cdat* curr_cdatp; struct set* curr_setp; struct link* curr_linkp; curr_cdatp = curr_cdat(); curr_setp = curr_set(); curr_linkp = alloc_link(); curr_linkp->classp = curr_cdatp; curr_linkp->type = 3; //curr_linkp->ele_idx = curr_setp->num_ele; curr_linkp->link_t.svlink.refid = refid; } //Insert element into odat_buf and cdatpages void insert_ele() { int refid; struct cdat* curr_cdatp; struct odat* curr_odatp; struct vdat* curr_vdatp; struct set* curr_setp; struct ele* curr_elep; struct ref* curr_refp; struct ref* prev_refp; curr_odatp = curr_odat(); //malloced @ insert_ele_label curr_vdatp = curr_vdat(); curr_setp = curr_set(); prev_refp = curr_ref(); curr_refp = alloc_ref(); curr_vdatp->creator = curr_odatp; /* Populate odat for ele */ curr_odatp->cdat_idx = curr_cdatp->idx; curr_odatp->refp = curr_refp; curr_odatp->parent_odatp = curr_set_odatp; refid = curr_odatp->refid; curr_refp->refid = refid; curr_refp->lastref = prev_refp; curr_refp->odatp = curr_odatp; prev_refp->nextref = curr_refp; } void insert_ele_vdatid () { struct odat* curr_odatp; curr_odatp = curr_odat(); curr_odatp->vdat_id = num_vdats; } #endif /* void */ /* insert_quad */ /* ( int x, int y, int z, int refid */ /* ) */ /* { */ /* struct quad* curr_quadp; */ /* curr_quadp = curr_quad(); */ /* curr_quadp->x = x; */ /* curr_quadp->y = y; */ /* curr_quadp->z = z; */ /* curr_quadp->refid = refid; */ /* } */ /* /\* serting the hitbox into the set */ /* odat. Elements that don't have */ /* a hitbox will use the sets root. *\/ */ /* void */ /* insert_hitbox */ /* ( int hitbox */ /* ) */ /* { struct odat* curr_odatp; */ /* curr_odatp = curr_odat(); */ /* curr_odatp->hitbox = hitbox; */ /* } */ /* /\* Inserting the root into the set */ /* odat. Elements that don't have */ /* a root will use the sets root. *\/ */ /* void */ /* insert_root */ /* ( int x, */ /* int y, */ /* int z */ /* ) */ /* { struct odat* curr_odatp; */ /* curr_odatp = curr_odat(); */ /* curr_odatp->root.x = x; */ /* curr_odatp->root.y = y; */ /* curr_odatp->root.z = z; */ /* } */ /* void */ /* insert_frame_pointer */ /* ( uint8_t direction, */ /* void* frame */ /* ) */ /* { struct model* curr_modelp; */ /* curr_modelp = curr_model(); */ /* curr_modelp->spritesheet[(int)direction].frames[curr_modelp->spritesheet[(int)direction].num_frames++] = frame; */ /* } */