addin irmem.c
[henge/webcc.git] / src / apc / irmem.c
1 /*!@file
2 \brief IR Memory Implementation
3 \details Intermediary memory management
4 \author Jordan Lavatai
5 \date Aug 2016
6 ----------------------------------------------------------------------------*/
7 #include <errno.h>
8 #include <stdio.h>
9 #include <stdint.h> //uint64_t
10 #include <string.h> //memmove
11 #include <stdlib.h> //malloc
12 #include <apc/ir.h>
13
14 #define CURR_CDAT (*cdat_stackp)
15 #define CURR_SET set_list[CURR_CDAT->num_sets]
16 #define CURR_ELE ele_list[CURR_CDAT->CURR_SET.num_ele]
17 #define PREV_REF (ref_buf[num_refs-1])
18 #define CURR_REF (ref_buf[num_refs])
19 #define PREV_ODAT (odat_buf[num_odats-1])
20 #define CURR_ODAT (odat_buf[num_odats])
21 #define CURR_VDAT (vdat_buf[num_vdats])
22 #define PREV_VDAT (vdat_buf[num_vdats-1])
23 #define CURR_MODEL model_list[CURR_VDAT->num_models]
24 #define CURR_LINK (link_buf[num_links])
25 #define CURR_POST (post_buf[num_posts])
26
27 void
28 inc_odat(void);
29 void
30 inc_vdat(void);
31 void
32 inc_link(void);
33 void
34 inc_ref(void);
35 void
36 ir_init(void);
37 void
38 malloc_cdat(void);
39
40
41
42 /* General: All information from the directory structure is stored in */
43 /* five buffers that comprise the IR: cdat_buf, odat_buf, vdat_buf, ref_buf */
44 /* and link_buf. Each buf corresponds to the data structure that it stores. */
45 /* The storage techique for all bufs (except cdat) is the same. Each bufs member first */
46 /* populates its struct and then allocates the space for the next member */
47 /* and increments the buf index. This means that we have to allocate the */
48 /* very first member of each buf at ir_init(), so that we don't segfault */
49 /* as the first member attempts to access memory that its previous member */
50 /* didn't allocate (because it doesnt exist). We access the buf members */
51 /* through standard array indexing but conceal the tediousness of array */
52 /* indexing with macros. E.g. without macros, acessing an elements name */
53 /* member would look like (split up to not go over line char limit): */
54 /* (*cdat_stackp)->set_list[(*cdat_stackp)->num_sets] */
55 /* .ele_list[(*cdat_stackp)->set_list[(*cdat_stackp->num_sets)].num_ele].name */
56
57 /* For cdats in cdat_buf, we allocate the memory for a cdat once a cdat
58 is recognized in the grammar. Cdat_buf is different from the other bufs
59 because cdats have a root cdat that all cdats are a subclass of. This root
60 cdat can have a set_list like other cdats. */
61
62 /* Elements: Ele stands for element and has two representations in the IR. */
63 /* In the cdat_buf eles store their name, cdat_idx (their classes index in */
64 /* the cdat_buf) and the ref_id (refer to ref ). In the odat_buf, eles store */
65 /* their object data (odat). At output time, the ref_id is dereferenced to */
66 /* determine the elements odat which is the data that the engine expects */
67 /* from an element. */
68
69
70 /* All bufs are of pointers to their respective structs. When a buf is full */
71 /* (number of data structs pointers >= max number of data struct pointers), */
72 /* we need to allocate a more pointers for that buf. Allocate these */
73 /* pointers a page at a time (1024 = Page bytes (4096)/bytes per pointer(4)) */
74
75 struct ele {
76 char name[32];
77 uint64_t ref_id;
78 int cdat_idx;
79 };
80
81 /* Sets: The set is similar to the ele, but it contains a list of its */
82 /* elements. The set is populated at parse time AFTER the elements are */
83 /* populated, due to the nature of bottom up parsing. */
84
85 struct set {
86 char name[32];
87 uint64_t ref_id;
88 int cdat_idx;
89 int num_ele;
90 struct ele ele_list[MAX_ELES];
91 };
92
93 /* Cdats: A cdat is a class data structure. Cdats serve as the central */
94 /* data types of the IR. At output, the cdat_buf is iterated through and */
95 /* each is written to the output file. For each cdat, sets and element */
96 /* ref_ids must be dereferenced to determine the odat information. Cdats */
97 /* contain pointers to their subclasses so that the relationship between */
98 /* classes can be determined, but the subclasses are not represented inside */
99 /* of the cdat itself but rather in the subsequent cdats in cdat_buf. We */
100 /* can determine the number of subclasses (the last index into cdat_buf */
101 /* that represents a subclass of some arbitrary cdat) each cdat has by */
102 /* incrementing num_classes during parse time. */
103 /* TODO: Should classes point to their parent class? */
104
105 struct cdat {
106 char name[32];
107 int idx;
108 int num_classes;
109 int num_sets;
110 struct cdat* class_list[MAX_CLASSES];
111 struct set set_list[MAX_SETS];
112 };
113
114 /* There are an unknown amount of cdats at compile time, so we maintain */
115 /* a cdat_buf of cdat pointers that can be expanded as needed. */
116 struct cdat* cdat_buf[PTRS_IN_PAGE];
117
118 /* The cdat_stack is a stack pointers to cdat pointers, the top of which is
119 the cdat that is currently being parsed. Whenever a new cdat is recognized
120 by the grammar (CLOPEN), a cdat is pushed onto the cdat_stack, and we refer
121 to this cdat through the macro CURR_CDAT. By keeping a cdat_stack, we have
122 access to the current cdat so that the elements and sets can populate themselves
123 in the cdat accordingly. */
124
125 struct cdat* cdat_stack[PTRS_IN_PAGE];
126 struct cdat** cdat_stackp;
127 int num_cdats = 0;
128 int curr_max_cdats = PTRS_IN_PAGE;
129
130 /* Refs: Each set/ele has a reference to its object data (odat) through a ref_id.
131 Ref_ids are unsigned 64 byte integers that map to the hex values RGBA. During
132 the construction of the directory structure, users can choose a RGBA value for
133 each object that any other object can refer to via links (see link). If a user
134 does not choose an RGBA value, then the object is given one from the system space.
135 We maintain a doubly linked list of refs in the ref_buf at parse time so that
136 links can be resolved after the parsing of the directory structure is complete.
137 For every 16th ref, we create a post so that we can reduce on the search time for
138 a random access. */
139
140 struct ref {
141 int type;
142 struct ref* nextref;
143 struct ref* lastref;
144 struct odat* odatp;
145 uint64_t ref_id; //0xFFFFFF->digit
146 };
147
148
149 /* Like the cdat_buf, ref_buf stores pointers to refs and can
150 increase in size */
151 struct ref* ref_buf[PTRS_IN_PAGE];
152 int num_refs = 0;
153 int curr_max_refs = PTRS_IN_PAGE;
154 uint64_t ss_ref_id = 0x00FFFFFF; /* system space for ref_ids */
155
156 /* posts for ref_buf */
157 struct ref* post_buf[PTRS_IN_PAGE];
158 int num_posts = 0;
159 int curr_max_posts = PTRS_IN_PAGE;
160
161 /* Links: At parse time, a set/ele can include a link in their
162 grammar representation instead of the actual data and this signifies
163 to the APC that that set/ele wishes to use the data of another
164 set/ele, either its video data (vdat) or object data (odat). The link
165 itself contains the type of link it is, the ref_id OR name, and
166 which set/ele created the link. During parse time, links can be made
167 to o/vdats that have yet to be parsed. In order to accomodate for this,
168 we resolve all links AFTER parse time by iterating through the link_buf,
169 finding the ref_id that was stored for some object (if the ref_id exists),
170 and creating a relative pointer from the original object to the data that
171 was linked */
172
173 /* Svlinks stand for short vlink, which is a link to a vdat
174 TODO: diff btwn vlink*/
175
176 struct svlink {
177 uint64_t ref_id;
178 };
179
180 /* A vlink is what it sounds like, a link to a vdat
181 TODO: model link? */
182 struct vlink {
183 uint64_t ref_id;
184 char anim_name[32];
185 };
186
187 /* Olinks are links to odats */
188 struct olink {
189 uint64_t ref_id;
190 };
191
192 union link_t {
193 struct olink olink;
194 struct vlink vlink;
195 struct svlink svlink;
196 };
197
198 struct link {
199 int type; //1 = olink, 2 = vlink, 3 = svlink
200 union link_t link_t;
201 int cdat_idx;
202 int set_idx;
203 int ele_idx;
204 };
205
206 /* link_buf contains all the links that
207 we encountered during parse time that need
208 to be resolved to an offset at output time.
209 This does not include quad refs, because
210 those are already known to need to be resolved */
211 struct link* link_buf[PTRS_IN_PAGE];
212 int num_links = 0;
213 int curr_max_links = PTRS_IN_PAGE;
214
215
216 /* Odats: Odats consist of the object data necessary for
217 each object. Odats are sometimes referred to as archetypes
218 at compile-time, in order to distinguish the difference from
219 a runtime object and a compile-time object.
220 TODO: Need more info about objects at runtime, to described
221 the reasoning behind odat structure at compile-time*/
222
223 /* Each set has a quad_list or a list of quads. The quad_list
224 is the ? */
225 struct quad {
226 int x, y, z;
227 uint64_t ref_id; //rgba
228 };
229
230 struct root {
231 int x, y, z;
232 };
233
234 struct odat {
235 char name[32];
236 int vdat_id;
237 int cdat_idx;
238 int hitbox;
239 struct root root;
240 struct ref* refp; /* pointer to it's ref on ref_list */
241 int num_quads;
242 struct quad quad_list[MAX_QUADS];
243 };
244 struct odat* odat_buf[PTRS_IN_PAGE];
245 int num_odats = 0;
246 int curr_max_odats = PTRS_IN_PAGE;
247
248 /* A framesheet is a grouping of animation frames in
249 a single direction (N,W,S,E) */
250 struct framesheet {
251 int width;
252 int height;
253 int num_frames;
254 void* frames[MAX_FRAMES];
255 };
256
257 /* A model is a collection of framesheets for every
258 direction (N,W,S,E,NW,NE,SW,SE)*/
259 /* NAMED spritesheet */
260 struct model {
261 char name[32];
262 struct framesheet spritesheet[8]; //one for each
263 };
264
265 /* Vdat: Vdats are the video data of each object. They can not be
266 created as a stand alone object (because they consist solely
267 of animation information and not the skeleton on which the
268 animation manipulates). Vdats have a list of models for every
269 animation that the vdats odat can do for that vdat*/
270 struct vdat {
271 struct odat* creator; //pointer to odat that made this vdat
272 int num_models;
273 struct model model_list[MAX_MODELS];
274 };
275
276 struct vdat* vdat_buf[PTRS_IN_PAGE];
277 int num_vdats = 0;
278 int curr_max_vdats = PTRS_IN_PAGE;
279
280
281 /* The initalization function of the IR. Mallocs the
282 first c/v/odat and the first links and refs and
283 inits the cdat_stack */
284 void
285 ir_init()
286 {
287
288 /* Init root cdat and stack */
289 char root[4] = "root";
290
291 cdat_buf[num_cdats] = (struct cdat*) malloc(sizeof(struct cdat) );
292 cdat_buf[num_cdats]->idx = 0;
293 memmove(cdat_buf[num_cdats]->name, root, 4);
294
295 cdat_stackp = cdat_stack;
296 *cdat_stackp = cdat_buf[num_cdats++];
297
298 /* Init first odat */
299 if( (CURR_ODAT = (struct odat*) malloc(sizeof(struct odat))) == NULL)
300 perror("malloc first odat failed");
301
302 /* init first vdat*/
303 if( (CURR_VDAT = (struct vdat*) malloc(sizeof(struct vdat))) == NULL)
304 perror("malloc first vdat failed");
305
306 /* Init first ref */
307 if( (CURR_REF = (struct ref*) malloc(sizeof(struct ref))) == NULL)
308 perror("malloc first ref failed");
309
310 /* Init first link */
311 if( (CURR_LINK = (struct link*) malloc(sizeof(struct link))) == NULL)
312 perror("malloc first link failed");
313
314 /* Init first post */
315 if( (CURR_POST = (struct ref*) malloc(sizeof(struct ref))) == NULL)
316 perror("malloc first post failed");
317 }
318
319 //TODO: FREE MEMORY!
320 void
321 malloc_cdat()
322 {
323 if(curr_max_cdats <= num_cdats)
324 { if( (realloc((void*) cdat_buf, PTRS_IN_PAGE * 4)) == NULL)
325 perror("realloc cdat_buf failed");
326 curr_max_cdats += PTRS_IN_PAGE;
327 if( (realloc( (void*) cdat_stack, PTRS_IN_PAGE * 4)) == NULL) //increase cdat_stack also
328 perror("realloc cdat_stack failed");
329 }
330 if( (cdat_buf[num_cdats] = (struct cdat*) malloc(sizeof (struct cdat)) ) == NULL )
331 perror("malloc cdat failed");
332
333
334 }
335
336 /* Dynamically allocate memory for a class data structure,
337 or cdat, after a class has been identified in a grammar.
338 We also create a stack of class pointers so that
339 we can access the cdat during processing of that
340 cdats sets and elements, a requirement because the
341 nature of recursive classes prevents us from accessing
342 the cdat based on the previous index into cdat_buf,
343 which is a list of all allocated cdats*/
344 void
345 push_cdat
346 ( char* name
347 )
348 {
349 malloc_cdat();
350
351 memmove(cdat_buf[num_cdats]->name, name, 32);
352 cdat_buf[num_cdats]->idx = num_cdats;
353
354 /* Set the cdat as a class of the previous cdat */
355 (*cdat_stackp)->class_list[(*cdat_stackp)->num_classes++] = cdat_buf[num_cdats];
356
357 /* Push the cdat onto the cdat_stack */
358 *++cdat_stackp = cdat_buf[num_cdats++];
359
360 }
361
362 void
363 pop_cdat
364 ()
365 {
366 *cdat_stackp = NULL;
367 cdat_stackp--;
368 }
369
370 void
371 inc_posts
372 ()
373 {
374 num_posts++;
375 if(num_posts >= curr_max_posts)
376 { if( (realloc((void*) post_buf, PTRS_IN_PAGE * 4)) == NULL)
377 perror("realloc post_buf failed");
378 curr_max_posts += PTRS_IN_PAGE;
379 }
380 if( (CURR_POST = (struct ref*) malloc(sizeof (struct ref))) == NULL)
381 perror("malloc post failed");
382
383 }
384 void
385 inc_odat
386 ()
387 {
388 num_odats++;
389 if(num_odats >= curr_max_odats)
390 { if( (realloc((void*) odat_buf, PTRS_IN_PAGE * 4)) == NULL)
391 perror("realloc odat_buf failed");
392 curr_max_odats += PTRS_IN_PAGE;
393 }
394 if( (CURR_ODAT = (struct odat*) malloc(sizeof (struct odat))) == NULL)
395 perror("malloc odat failed");
396
397 }
398
399 void
400 inc_vdat
401 ()
402 {
403 num_vdats++;
404 if(num_vdats >= curr_max_vdats)
405 { if( (realloc((void*) vdat_buf, PTRS_IN_PAGE * 4)) == NULL)
406 perror("realloc vdat_buf failed");
407 curr_max_vdats += PTRS_IN_PAGE;
408 }
409 if((CURR_VDAT = (struct vdat*) malloc(sizeof (struct vdat))) == NULL)
410 perror("malloc vdat failed");
411
412 }
413
414 void
415 inc_link
416 ()
417 {
418 num_links++;
419 if(num_links >= curr_max_links)
420 { if( (realloc((void*) link_buf, PTRS_IN_PAGE * 4)) == NULL)
421 perror("realloc vdat_buf failed");
422 curr_max_links += PTRS_IN_PAGE;
423 }
424 if((CURR_LINK = (struct link*) malloc(sizeof (struct link))) == NULL)
425 perror("malloc link failed");
426 }
427
428 void
429 inc_ref
430 ()
431 {
432
433 if(num_refs % 16 == 0)
434 { CURR_POST = CURR_REF;
435 inc_posts();
436 }
437
438 num_refs++;
439 if(num_refs >= curr_max_refs)
440 { if( (realloc((void*) ref_buf, PTRS_IN_PAGE * 4)) == NULL)
441 perror("realloc ref_buf failed");
442 curr_max_refs += PTRS_IN_PAGE;
443 }
444 if((CURR_REF = (struct ref*) malloc(sizeof (struct ref))) == NULL)
445 perror("malloc ref failed");
446 }
447 /* Called in the reduction of a set. While both odats (eles and sets)
448 have identical label terminals, we are unable to give a single grammatical rule
449 for both due to how we allocate odats in the odat buf. Due to the
450 nature of bottom up parsing, all the elements will be inserted into the
451 odat_buf first, and then the set that contains these element is inserted. Since
452 the sets label comes before the element list in the grammar, we would be giving an element
453 a set label in its respective odat, which would then be replaced by the
454 elements label. Instead, we store the label in the sets representation inside
455 CURR_CDAT and after we are done parsing the element_list and know that the CURR_ODAT
456 is the set, we populate the sets label members in CURR_ODAT with the values we stored
457 previously in CURR_CDAT. */
458
459 void
460 insert_set_label
461 ( char* name,
462 uint64_t ref_id
463 )
464 {
465 memmove(CURR_CDAT->CURR_SET.name,name,32);
466 memmove(&CURR_CDAT->CURR_SET.ref_id,&ref_id,64);
467
468 }
469 void
470 insert_set_olink
471 ( uint64_t ref_id
472 )
473 {
474 CURR_CDAT->CURR_SET.cdat_idx = CURR_CDAT->idx;
475 CURR_CDAT->CURR_SET.ref_id = ref_id; /* Will be resolved to offset
476 when link is processed */
477 CURR_LINK->type = 1;
478 CURR_LINK->link_t.olink.ref_id = ref_id;
479 CURR_LINK->cdat_idx = CURR_CDAT->idx;
480 CURR_LINK->set_idx = CURR_CDAT->num_sets++;
481 CURR_LINK->ele_idx = -1;
482
483 inc_link();
484 }
485
486 void
487 insert_set_vlink
488 ( uint64_t ref_id,
489 char* anim_name
490 )
491 {
492 /* Insert vlink into link_stack so that it gets processed at
493 output time */
494 CURR_LINK->cdat_idx = CURR_CDAT->idx;
495 CURR_LINK->set_idx = CURR_CDAT->num_sets;
496 CURR_LINK->type = 2;
497 CURR_LINK->link_t.vlink.ref_id = ref_id;
498 memmove(CURR_LINK->link_t.vlink.anim_name, anim_name, 32);
499
500
501 }
502
503 void
504 insert_set_svlink
505 ( uint64_t ref_id
506 )
507 {
508
509 /* Insert vlink into link_stack so that it gets processed at
510 output time */
511 CURR_LINK->cdat_idx = CURR_CDAT->idx;
512 CURR_LINK->set_idx = CURR_CDAT->num_sets;
513 CURR_LINK->type = 3;
514 CURR_LINK->link_t.svlink.ref_id = ref_id;
515
516 }
517
518 /* At the point of reducing to a set, most of the
519 sets odat information has already been populated
520 during the reduction of its right hand side
521 non terminals (hitbox, root, quad_list). */
522 void
523 insert_set
524 ()
525 {
526 uint64_t ref_id;
527
528 ref_id = CURR_CDAT->CURR_SET.ref_id;
529
530 CURR_CDAT->CURR_SET.cdat_idx = CURR_CDAT->idx;
531 memmove(CURR_ODAT->name, CURR_CDAT->CURR_SET.name, 32);
532 CURR_CDAT->num_sets++;
533
534 CURR_ODAT->cdat_idx = CURR_CDAT->idx;
535 CURR_ODAT->refp = CURR_REF;
536
537
538 CURR_REF->lastref = PREV_REF;
539 PREV_REF->nextref = CURR_REF;
540 CURR_REF->odatp = CURR_ODAT;
541
542
543 if(ref_id == -1) /* user did not define a ref_id so */
544 { ref_id = ss_ref_id;
545 ss_ref_id++;
546 }
547
548 CURR_REF->ref_id = ref_id;
549
550 inc_ref();
551 inc_odat();
552 }
553 /* Created as a seperate function, instead of setting the ODATS vdat_id and
554 calling inc_vdat() inside of insert_set(), to account for the set reduction
555 where a vdat is not created (o/v/svlinks). Because insert_set/ele is always
556 called before insert_vdat, and thus increments the CURR_ODAT to be the next
557 ODAT to be populated, insert_vdat() targets the last ODAT that was populated,
558 via PREV_ODAT. */
559
560 void
561 insert_vdat
562 ()
563 {
564 PREV_ODAT->vdat_id = num_vdats; //NULL for vlink, svlink
565 inc_vdat();
566 }
567
568 /* Populates both the odat name and ref_id
569 for element. */
570 void
571 insert_ele_label
572 ( char* name,
573 uint64_t ref_id
574 )
575 {
576 memmove(CURR_CDAT->CURR_SET.CURR_ELE.name, name, 32);
577 memmove(&CURR_CDAT->CURR_SET.ele_list[CURR_CDAT->CURR_SET.ref_id].ref_id, &ref_id, 64);
578 }
579
580 void
581 insert_ele_olink
582 ( uint64_t ref_id
583 )
584 {
585 CURR_CDAT->CURR_SET.CURR_ELE.cdat_idx = CURR_CDAT->idx;
586 CURR_CDAT->CURR_SET.CURR_ELE.ref_id = ref_id; /* Will be resolved to offset
587 when link is processed */
588 CURR_LINK->type = 1;
589 CURR_LINK->link_t.olink.ref_id = ref_id;
590 CURR_LINK->cdat_idx = CURR_CDAT->idx;
591 CURR_LINK->set_idx = CURR_CDAT->num_sets++;
592 CURR_LINK->ele_idx = CURR_CDAT->CURR_SET.num_ele++;
593
594 }
595
596 void
597 insert_ele_vlink
598 ( uint64_t ref_id,
599 char* anim_name
600 )
601 {
602
603 /* Insert vlink into link_stack so that it gets processed at
604 output time */
605 CURR_LINK->cdat_idx = CURR_CDAT->idx;
606 CURR_LINK->type = 2;
607 CURR_LINK->set_idx = CURR_CDAT->num_sets;
608 CURR_LINK->ele_idx = CURR_CDAT->CURR_SET.num_ele;
609 CURR_LINK->link_t.vlink.ref_id = ref_id;
610 memmove(CURR_LINK->link_t.vlink.anim_name, anim_name, 32);
611
612 }
613
614 void
615 insert_ele_svlink
616 ( uint64_t ref_id
617 )
618 {
619
620 CURR_LINK->cdat_idx = CURR_CDAT->idx;
621 CURR_LINK->type = 3;
622 CURR_LINK->set_idx = CURR_CDAT->num_sets;
623 CURR_LINK->ele_idx = CURR_CDAT->CURR_SET.num_ele;
624 CURR_LINK->link_t.svlink.ref_id = ref_id;
625
626
627 }
628
629 //Insert element into odat_buf and cdatpages
630 void
631 insert_ele()
632 {
633 uint64_t ref_id;
634
635 ref_id = CURR_CDAT->CURR_SET.CURR_ELE.ref_id;
636
637 CURR_CDAT->CURR_SET.CURR_ELE.cdat_idx = CURR_CDAT->idx;
638 memmove(CURR_ODAT->name,CURR_CDAT->CURR_SET.CURR_ELE.name, 32);
639 CURR_CDAT->CURR_SET.num_ele++;
640
641 CURR_ODAT->cdat_idx = CURR_CDAT->idx;
642 CURR_ODAT->refp = CURR_REF;
643
644 if(ref_id == -1) /* user did not define a ref_id so */
645 { ref_id = ss_ref_id;
646 ss_ref_id++;
647 }
648
649 CURR_REF->ref_id = ref_id;
650
651 inc_odat();
652 inc_ref();
653
654 }
655
656 void
657 insert_framesheet
658 ( char direction,
659 char* name,
660 uint64_t ref_id,
661 int height ,
662 int width,
663 int num_frames
664 )
665 {
666 CURR_VDAT->CURR_MODEL.spritesheet[(int)direction].height = height;
667 CURR_VDAT->CURR_MODEL.spritesheet[(int)direction].width = width;
668 CURR_VDAT->CURR_MODEL.spritesheet[(int)direction].num_frames = num_frames;
669 CURR_VDAT->num_models++;
670 }
671
672 void
673 insert_quad
674 ( int x,
675 int y,
676 int z,
677 uint64_t ref_id
678 )
679 #define CURR_QUAD (CURR_ODAT->quad_list[CURR_ODAT->num_quads])
680 {
681 CURR_QUAD.x = x;
682 CURR_QUAD.y = y;
683 CURR_QUAD.z = z;
684 CURR_QUAD.ref_id = ref_id;
685 CURR_ODAT->num_quads++;
686 }
687
688 /* Inserting the hitbox into the set
689 odat. Elements that don't have
690 a hitbox will use the sets root. */
691 void
692 insert_hitbox
693 ( int hitbox
694 )
695 {
696 CURR_ODAT->hitbox = hitbox;
697 }
698
699 /* Inserting the root into the set
700 odat. Elements that don't have
701 a root will use the sets root. */
702 void
703 insert_root
704 ( int x,
705 int y,
706 int z
707 )
708 {
709
710 CURR_ODAT->root.x = x;
711 CURR_ODAT->root.y = y;
712 CURR_ODAT->root.z = z;
713 }
714
715 void
716 insert_frame_pointer
717 ( char direction,
718 void* frame
719 )
720 {
721 CURR_VDAT->CURR_MODEL.spritesheet[(int)direction].frames[CURR_VDAT->CURR_MODEL.spritesheet[(int)direction].num_frames++] = frame;
722 }
723