/*!@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 //malloc #include //extern //scanner_scanpixels(int*, int); /* functions needed from irmem.c */ extern void ir_init(void); extern struct cdat* alloc_cdat(void); extern struct odat* alloc_odat(void); extern struct vdat* alloc_vdat(void); extern void alloc_mdat(void); extern struct link* alloc_link(void); extern struct ref* alloc_ref(void); extern struct cdat* curr_cdat(void); extern struct odat* curr_odat(void); extern struct map* curr_map(void); extern struct map* alloc_map(void); extern struct vdat* curr_vdat(void); extern struct set* curr_set(void); extern struct ref* curr_ref(void); extern struct quad* curr_quad(void); extern struct model* curr_model(void); extern struct quad* curr_quad(void); /* struct definitions needed from irmem.c */ extern int num_cdats; extern struct cdat** cdat_stackp; extern struct odat* curr_set_odatp; extern int ss_ref_id; extern int num_vdats; /* 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*/ void push_cdat ( uint8_t* name ) { struct cdat* curr_cdatp; curr_cdatp = alloc_cdat(); u8_cpy(curr_cdatp->name, name, 32); 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--; } /* Every odat has a single map variant. We track the odats that have related map variants by adding the name of the map to the end of the odat name. E.g. for an odat with name A and map variants a,b,c we get A_a, A_b, A_c. We create new odats for each map variant*/ void insert_map ( uint8_t* name, int height, int width, uint8_t* filepath ) { struct odat* curr_odatp; int curr_odat_vdatid; curr_odatp = curr_odat(); curr_odat_vdatid = curr_odatp->vdat_id; if(curr_odatp->map.name[0] != 0) //odat already has a map so make a new odat { curr_odatp = alloc_odat(); curr_odatp->vdat_id = curr_odat_vdatid; } /* Add a delimiter '_' in between odat name and map variant name */ u8_strcat(curr_odatp->map.name, (uint8_t*) '_'); u8_strcat(curr_odatp->map.name, name); u8_strcpy(curr_odatp->map.filepath, filepath); curr_odatp->map.height = height; curr_odatp->map.width = width; } /* 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*/ void insert_set_label ( uint8_t* name, int ref_id ) { 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; curr_set_odatp->map.name[0] = 0; if(ref_id != -1) { curr_set_odatp->ref_id = ref_id; curr_setp->ref_id = ref_id; } else { curr_setp->ref_id = ss_ref_id; curr_set_odatp->ref_id = ss_ref_id++; } } /* 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 ref_id ) { struct set* curr_setp; curr_setp = curr_set(); curr_setp->ref_id = ref_id; } void insert_set_vlink ( int ref_id, 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.ref_id = ref_id; 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 ref_id ) { 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.ref_id = ref_id; } /* 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 ref_id; 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; ref_id = curr_setp->ref_id; // ref_id set by insert_set_label(name, ref_id) curr_refp->ref_id = ref_id; 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 ref_id 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 ref_id ) { struct odat* curr_odatp; curr_odatp = alloc_odat(); u8_cpy(curr_odatp->name, name, 32); curr_odatp->map.name[0] = 0; if(ref_id != -1) curr_odatp->ref_id = ref_id; else curr_odatp->ref_id = ss_ref_id++; } /* We don't make an odat here, at output time we will resolve the ref_id to the corresponding odat. */ void insert_ele_olink ( int ref_id ) { /* Do nothing because we already know the ref_id that the odat needs for this element (in the quad_file) */ } void insert_ele_vlink ( int ref_id, 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.ref_id = ref_id; u8_cpy(curr_linkp->link_t.vlink.anim_name, anim_name, 32); } void insert_ele_svlink ( int ref_id ) { 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.ref_id = ref_id; } //Insert element into odat_buf and cdatpages void insert_ele() { int ref_id; 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; ref_id = curr_odatp->ref_id; curr_refp->ref_id = ref_id; 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; } void insert_vdat (uint8_t* filename, int height, int width, uint8_t* filepath) { struct vdat* curr_vdatp; int filename_len, filepath_len; curr_vdatp = alloc_vdat(); u8_strcpy(curr_vdatp->filename, filename); u8_strcpy(curr_vdatp->filepath, filepath); curr_vdatp->height = height; curr_vdatp->width = width; curr_vdatp->creator = curr_odat(); } /* void */ /* insert_quad */ /* ( int x, int y, int z, int ref_id */ /* ) */ /* { */ /* struct quad* curr_quadp; */ /* curr_quadp = curr_quad(); */ /* curr_quadp->x = x; */ /* curr_quadp->y = y; */ /* curr_quadp->z = z; */ /* curr_quadp->ref_id = ref_id; */ /* } */ /* /\* 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_framesheet */ /* ( uint8_t direction, */ /* uint8_t* name, */ /* int ref_id, */ /* int height , */ /* int width, */ /* int num_frames */ /* ) */ /* { struct vdat* curr_vdatp; */ /* struct model* curr_modelp; */ /* curr_vdatp = curr_vdat(); */ /* curr_modelp = curr_model(); */ /* curr_modelp->spritesheet[(int)direction].height = height; */ /* curr_modelp->spritesheet[(int)direction].width = width; */ /* curr_modelp->spritesheet[(int)direction].num_frames = num_frames; */ /* curr_vdatp->num_models++; */ /* } */ /* 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; */ /* } */