/*!@file \brief IR Memory Implementation \details Intermediary memory management \author Jordan Lavatai \date Aug 2016 ----------------------------------------------------------------------------*/ #include #include #include //uint64_t #include //memmove #include //malloc #include /* functions needed from irmem.c */ extern void ir_init(void); extern struct cdat* alloc_cdat(void); extern struct odat* alloc_odat(void); extern void alloc_vdat(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 vdat* curr_vdat(void); extern struct ele* curr_ele(void); extern struct set* curr_set(void); extern struct ref* prev_ref(void); extern struct quad* curr_quad(void); extern struct model* curr_model(void); /* struct definitions needed from irmem.c */ extern int num_cdats; extern struct cdat** cdat_stackp; extern struct odat* curr_set_odatp; extern uint64_t 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 ( char* name ) { struct cdat* curr_cdatp; curr_cdatp = alloc_cdat(); memmove(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 = NULL; cdat_stackp--; } /* 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. */ void insert_set_label ( char* name, uint64_t ref_id ) { struct set* curr_setp; curr_setp = curr_set(); curr_set_odatp = alloc_odat(); memmove(curr_set_odatp->name, name, 32); memmove(curr_setp->name, name, 32); curr_setp->ref_id = ref_id; } void insert_set_olink ( uint64_t ref_id ) { struct set* curr_setp; struct cdat* curr_cdatp; struct link* curr_linkp; curr_setp = curr_set(); curr_cdatp = curr_cdat(); curr_linkp = alloc_link(); curr_setp->cdat_idx = curr_cdatp->idx; curr_setp->ref_id = ref_id; /* Will be resolved to offset when link is processed */ curr_linkp->type = 1; curr_linkp->link_t.olink.ref_id = ref_id; curr_linkp->cdat_idx = curr_cdatp->idx; curr_linkp->set_idx = curr_cdatp->num_sets++; curr_linkp->ele_idx = -1; } void insert_set_vlink ( uint64_t ref_id, char* anim_name ) { struct cdat* curr_cdatp; struct link* curr_linkp; curr_cdatp = curr_cdat(); curr_linkp = alloc_link(); /* Insert vlink into link_stack so that it gets processed at output time */ curr_linkp->type = 2; curr_linkp->link_t.vlink.ref_id = ref_id; curr_linkp->cdat_idx = curr_cdatp->idx; curr_linkp->set_idx = curr_cdatp->num_sets; curr_linkp->ele_idx = -1; memmove(curr_linkp->link_t.vlink.anim_name, anim_name, 32); } /* Svlinks dont have animation names */ void insert_set_svlink ( uint64_t 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->cdat_idx = curr_cdatp->idx; 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 () { uint64_t 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, preserved in global space curr_cdatp = curr_cdat(); curr_setp = curr_set(); prev_refp = prev_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? memmove(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) if(ref_id == -1) /* user did not define a ref_id */ { ref_id = ss_ref_id; ss_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 () { curr_set_odatp->vdat_id = num_vdats; //no vdat_id for odats that have vlinks/svlinks curr_set_odatp = NULL; //So this sets odat cant be modified after (which would be a bug) } /* Populates both the odat name and ref_id for odat and ele */ void insert_ele_label ( char* name, uint64_t ref_id ) { struct ele* curr_elep; struct odat* curr_odatp; curr_elep = curr_ele(); curr_odatp = alloc_odat(); memmove(curr_odatp->name, name, 32); memmove(curr_elep->name, name, 32); curr_elep->ref_id = 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 ( uint64_t ref_id ) { struct cdat* curr_cdatp; struct set* curr_setp; struct ele* curr_elep; struct link* curr_linkp; curr_cdatp = curr_cdat(); curr_elep = curr_ele(); curr_linkp = alloc_link(); curr_elep->cdat_idx = curr_cdatp->idx; curr_elep->ref_id = ref_id; curr_linkp->type = 1; curr_linkp->link_t.olink.ref_id = ref_id; curr_linkp->cdat_idx = curr_cdatp->idx; curr_linkp->set_idx = curr_cdatp->num_sets++; curr_linkp->ele_idx = curr_setp->num_ele++; } void insert_ele_vlink ( uint64_t ref_id, char* 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->cdat_idx = curr_cdatp->idx; 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; memmove(curr_linkp->link_t.vlink.anim_name, anim_name, 32); } void insert_ele_svlink ( uint64_t 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->cdat_idx = curr_cdatp->idx; 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() { uint64_t 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_cdatp = curr_cdat(); curr_odatp = curr_odat(); //malloced @ insert_ele_label curr_vdatp = curr_vdat(); curr_setp = curr_set(); curr_elep = curr_ele(); curr_refp = alloc_ref(); prev_refp = prev_ref(); curr_vdatp->creator = curr_odatp; /* Populate ele in cdat */ curr_elep->cdat_idx = curr_cdatp->idx; curr_setp->num_ele++; /* Populate odat for ele */ curr_odatp->cdat_idx = curr_cdatp->idx; curr_odatp->refp = curr_refp; /* Add ele to ref_buf */ ref_id = curr_elep->ref_id; if(ref_id == -1) /* user did not define a ref_id so */ { ref_id = ss_ref_id; ss_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_quad ( int x, int y, int z, uint64_t ref_id ) { struct quad* curr_quadp; struct odat* curr_odatp; curr_quadp = curr_quad(); curr_odatp = curr_odat(); curr_quadp->x = x; curr_quadp->y = y; curr_quadp->z = z; curr_quadp->ref_id = ref_id; curr_odatp->num_quads++; } /* Inserting 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 ( char direction, char* name, uint64_t 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 ( char 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; }