vdats now record the odat that creates them
[henge/webcc.git] / src / apc / ir.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
15
16 /* functions needed from irmem.c */
17 extern
18 void
19 ir_init(void);
20
21 extern
22 struct cdat*
23 alloc_cdat(void);
24
25 extern
26 struct odat*
27 alloc_odat(void);
28
29 extern
30 void
31 alloc_vdat(void);
32
33 extern
34 struct link*
35 alloc_link(void);
36
37 extern
38 struct ref*
39 alloc_ref(void);
40
41 extern
42 struct cdat*
43 curr_cdat(void);
44
45 extern
46 struct odat*
47 curr_odat(void);
48
49 extern
50 struct vdat*
51 curr_vdat(void);
52
53 extern
54 struct ele*
55 curr_ele(void);
56
57 extern
58 struct set*
59 curr_set(void);
60
61 extern
62 struct ref*
63 prev_ref(void);
64
65 extern
66 struct quad*
67 curr_quad(void);
68
69 extern
70 struct model*
71 curr_model(void);
72
73 /* struct definitions needed from irmem.c */
74 extern int num_cdats;
75 extern struct cdat** cdat_stackp;
76 extern struct odat* curr_set_odatp;
77 extern uint64_t ss_ref_id;
78
79 extern int num_vdats;
80 /* Dynamically allocate memory for a class data structure,
81 or cdat, after a class has been identified in a grammar.
82 We also create a stack of class pointers so that
83 we can access the cdat during processing of that
84 cdats sets and elements, a requirement because the
85 nature of recursive classes prevents us from accessing
86 the cdat based on the previous index into cdat_buf,
87 which is a list of all allocated cdats*/
88 void
89 push_cdat
90 ( char* name
91 )
92 {
93 struct cdat* curr_cdatp;
94
95 curr_cdatp = alloc_cdat();
96
97 memmove(curr_cdatp->name, name, 32);
98 curr_cdatp->idx = num_cdats;
99
100 /* Set the cdat as a subclass of the previous cdat */
101 (*cdat_stackp)->class_list[(*cdat_stackp)->num_classes] = curr_cdatp;
102 /* Push the cdat onto the cdat_stack */
103 *++cdat_stackp = curr_cdatp;
104
105 }
106
107 void
108 pop_cdat
109 ()
110 {
111 *cdat_stackp = NULL;
112 cdat_stackp--;
113 }
114
115 /* Called in the reduction of a set. While both odats (eles and sets)
116 have identical label terminals, we are unable to give a single grammatical rule
117 for both due to how we allocate odats in the odat buf. Due to the
118 nature of bottom up parsing, the set label is recognized first, and then the
119 sets elements are recognized. This means that after we have processed the sets elemenets,
120 the curr_odat is going to be the last element and NOT the set that was first allocated.
121 To get around this, we create a global variable set_odatp that will store the pointer
122 to the odat when it is first allocated (in insert_set_label()) so that insert_set() can
123 have access to it. */
124
125 void
126 insert_set_label
127 ( char* name,
128 uint64_t ref_id
129 )
130 {
131 struct set* curr_setp;
132
133 curr_setp = curr_set();
134 curr_set_odatp = alloc_odat();
135
136 memmove(curr_set_odatp->name, name, 32);
137 memmove(curr_setp->name, name, 32);
138 curr_setp->ref_id = ref_id;
139
140 }
141 void
142 insert_set_olink
143 ( uint64_t ref_id
144 )
145 {
146 struct set* curr_setp;
147 struct cdat* curr_cdatp;
148 struct link* curr_linkp;
149
150 curr_setp = curr_set();
151 curr_cdatp = curr_cdat();
152 curr_linkp = alloc_link();
153
154 curr_setp->cdat_idx = curr_cdatp->idx;
155 curr_setp->ref_id = ref_id; /* Will be resolved to offset
156 when link is processed */
157 curr_linkp->type = 1;
158 curr_linkp->link_t.olink.ref_id = ref_id;
159 curr_linkp->cdat_idx = curr_cdatp->idx;
160 curr_linkp->set_idx = curr_cdatp->num_sets++;
161 curr_linkp->ele_idx = -1;
162
163 }
164
165 void
166 insert_set_vlink
167 ( uint64_t ref_id,
168 char* anim_name
169 )
170 {
171 struct cdat* curr_cdatp;
172 struct link* curr_linkp;
173
174 curr_cdatp = curr_cdat();
175 curr_linkp = alloc_link();
176
177 /* Insert vlink into link_stack so that it gets processed at
178 output time */
179 curr_linkp->type = 2;
180 curr_linkp->link_t.vlink.ref_id = ref_id;
181 curr_linkp->cdat_idx = curr_cdatp->idx;
182 curr_linkp->set_idx = curr_cdatp->num_sets;
183 curr_linkp->ele_idx = -1;
184 memmove(curr_linkp->link_t.vlink.anim_name, anim_name, 32);
185
186 }
187
188 /* Svlinks dont have animation names */
189 void
190 insert_set_svlink
191 ( uint64_t ref_id
192 )
193 {
194 struct cdat* curr_cdatp;
195 struct link* curr_linkp;
196
197 curr_cdatp = curr_cdat();
198 curr_linkp = alloc_link();
199
200 /* Insert svlink into link_stack so that it gets processed at
201 output time */
202 curr_linkp->type = 3;
203 curr_linkp->cdat_idx = curr_cdatp->idx;
204 curr_linkp->set_idx = curr_cdatp->num_sets;
205 curr_linkp->ele_idx = -1;
206 curr_linkp->link_t.svlink.ref_id = ref_id;
207
208 }
209
210 /* At the point of reducing to a set, most of the
211 sets odat information has already been populated
212 during the reduction of its right hand side
213 non terminals (hitbox, root, quad_list). */
214 void
215 insert_set
216 ()
217 { uint64_t ref_id;
218 struct odat* curr_odatp;
219 struct cdat* curr_cdatp;
220 struct set* curr_setp;
221 struct ref* prev_refp;
222 struct ref* curr_refp;
223 struct vdat* curr_vdatp;
224
225 curr_odatp = curr_set_odatp; //allocated at insert_set_label, preserved in global space
226 curr_cdatp = curr_cdat();
227 curr_setp = curr_set();
228 prev_refp = prev_ref();
229 curr_refp = alloc_ref();
230 curr_vdatp = curr_vdat();
231
232 curr_vdatp->creator = curr_set_odatp;
233
234 curr_setp->cdat_idx = curr_cdatp->idx; //does a set need its class idx?
235 memmove(curr_setp->name, curr_odatp->name, 32);
236 curr_cdatp->num_sets++;
237
238 curr_odatp->cdat_idx = curr_cdatp->idx;
239 curr_odatp->refp = curr_refp;
240
241 ref_id = curr_setp->ref_id; // ref_id set by insert_set_label(name, ref_id)
242
243 if(ref_id == -1) /* user did not define a ref_id */
244 { ref_id = ss_ref_id;
245 ss_ref_id++;
246 }
247
248 curr_refp->ref_id = ref_id;
249 curr_refp->lastref = prev_refp;
250 curr_refp->odatp = curr_odatp;
251 prev_refp->nextref = curr_refp;
252
253
254
255 }
256 /* Created as a seperate function, instead of setting the ODATS vdat_id and
257 calling inc_vdat() inside of insert_set(), to account for the set reduction
258 where a vdat is not created (o/v/svlinks). */
259 void
260 insert_set_vdatid
261 ()
262 {
263 curr_set_odatp->vdat_id = num_vdats; //no vdat_id for odats that have vlinks/svlinks
264 curr_set_odatp = NULL; //So this sets odat cant be modified after (which would be a bug)
265 }
266
267 /* Populates both the odat name and ref_id
268 for odat and ele */
269 void
270 insert_ele_label
271 ( char* name,
272 uint64_t ref_id
273 )
274 {
275 struct ele* curr_elep;
276 struct odat* curr_odatp;
277
278 curr_elep = curr_ele();
279 curr_odatp = alloc_odat();
280
281 memmove(curr_odatp->name, name, 32);
282
283 memmove(curr_elep->name, name, 32);
284 curr_elep->ref_id = ref_id;
285 }
286
287 /* We don't make an odat here, at output time we will resolve
288 the ref_id to the corresponding odat. */
289 void
290 insert_ele_olink
291 ( uint64_t ref_id
292 )
293 {
294 struct cdat* curr_cdatp;
295 struct set* curr_setp;
296 struct ele* curr_elep;
297 struct link* curr_linkp;
298
299 curr_cdatp = curr_cdat();
300 curr_elep = curr_ele();
301 curr_linkp = alloc_link();
302
303 curr_elep->cdat_idx = curr_cdatp->idx;
304 curr_elep->ref_id = ref_id;
305
306 curr_linkp->type = 1;
307 curr_linkp->link_t.olink.ref_id = ref_id;
308 curr_linkp->cdat_idx = curr_cdatp->idx;
309 curr_linkp->set_idx = curr_cdatp->num_sets++;
310 curr_linkp->ele_idx = curr_setp->num_ele++;
311
312 }
313
314 void
315 insert_ele_vlink
316 ( uint64_t ref_id,
317 char* anim_name
318 )
319 {
320 struct cdat* curr_cdatp;
321 struct set* curr_setp;
322 struct link* curr_linkp;
323
324 curr_cdatp = curr_cdat();
325 curr_setp = curr_set();
326 curr_linkp = alloc_link();
327
328 /* Insert vlink into link_stack so that it gets processed at
329 output time */
330 curr_linkp->cdat_idx = curr_cdatp->idx;
331 curr_linkp->type = 2;
332 curr_linkp->set_idx = curr_cdatp->num_sets;
333 curr_linkp->ele_idx = curr_setp->num_ele;
334 curr_linkp->link_t.vlink.ref_id = ref_id;
335 memmove(curr_linkp->link_t.vlink.anim_name, anim_name, 32);
336
337 }
338
339 void
340 insert_ele_svlink
341 ( uint64_t ref_id
342 )
343 {
344 struct cdat* curr_cdatp;
345 struct set* curr_setp;
346 struct link* curr_linkp;
347
348 curr_cdatp = curr_cdat();
349 curr_setp = curr_set();
350 curr_linkp = alloc_link();
351
352 curr_linkp->cdat_idx = curr_cdatp->idx;
353 curr_linkp->type = 3;
354
355 curr_linkp->ele_idx = curr_setp->num_ele;
356 curr_linkp->link_t.svlink.ref_id = ref_id;
357
358
359 }
360
361 //Insert element into odat_buf and cdatpages
362 void
363 insert_ele()
364 {
365 uint64_t ref_id;
366 struct cdat* curr_cdatp;
367 struct odat* curr_odatp;
368 struct vdat* curr_vdatp;
369 struct set* curr_setp;
370 struct ele* curr_elep;
371 struct ref* curr_refp;
372 struct ref* prev_refp;
373
374
375 curr_cdatp = curr_cdat();
376 curr_odatp = curr_odat(); //malloced @ insert_ele_label
377 curr_vdatp = curr_vdat();
378 curr_setp = curr_set();
379 curr_elep = curr_ele();
380 curr_refp = alloc_ref();
381 prev_refp = prev_ref();
382
383 curr_vdatp->creator = curr_odatp;
384 /* Populate ele in cdat */
385 curr_elep->cdat_idx = curr_cdatp->idx;
386 curr_setp->num_ele++;
387
388 /* Populate odat for ele */
389 curr_odatp->cdat_idx = curr_cdatp->idx;
390 curr_odatp->refp = curr_refp;
391
392 /* Add ele to ref_buf */
393 ref_id = curr_elep->ref_id;
394
395 if(ref_id == -1) /* user did not define a ref_id so */
396 { ref_id = ss_ref_id;
397 ss_ref_id++;
398 }
399
400 curr_refp->ref_id = ref_id;
401 curr_refp->lastref = prev_refp;
402 curr_refp->odatp = curr_odatp;
403 prev_refp->nextref = curr_refp;
404
405 }
406
407 void
408 insert_ele_vdatid
409 ()
410 { struct odat* curr_odatp;
411 curr_odatp = curr_odat();
412 curr_odatp->vdat_id = num_vdats;
413 }
414
415 void
416 insert_quad
417 ( int x,
418 int y,
419 int z,
420 uint64_t ref_id
421 )
422 {
423
424 struct quad* curr_quadp;
425 struct odat* curr_odatp;
426
427 curr_quadp = curr_quad();
428 curr_odatp = curr_odat();
429
430 curr_quadp->x = x;
431 curr_quadp->y = y;
432 curr_quadp->z = z;
433 curr_quadp->ref_id = ref_id;
434 curr_odatp->num_quads++;
435 }
436
437 /* Inserting the hitbox into the set
438 odat. Elements that don't have
439 a hitbox will use the sets root. */
440 void
441 insert_hitbox
442 ( int hitbox
443 )
444 { struct odat* curr_odatp;
445
446 curr_odatp = curr_odat();
447 curr_odatp->hitbox = hitbox;
448 }
449
450 /* Inserting the root into the set
451 odat. Elements that don't have
452 a root will use the sets root. */
453 void
454 insert_root
455 ( int x,
456 int y,
457 int z
458 )
459 { struct odat* curr_odatp;
460
461 curr_odatp = curr_odat();
462 curr_odatp->root.x = x;
463 curr_odatp->root.y = y;
464 curr_odatp->root.z = z;
465 }
466
467
468 void
469 insert_framesheet
470 ( char direction,
471 char* name,
472 uint64_t ref_id,
473 int height ,
474 int width,
475 int num_frames
476 )
477 { struct vdat* curr_vdatp;
478 struct model* curr_modelp;
479
480 curr_vdatp = curr_vdat();
481 curr_modelp = curr_model();
482
483 curr_modelp->spritesheet[(int)direction].height = height;
484 curr_modelp->spritesheet[(int)direction].width = width;
485 curr_modelp->spritesheet[(int)direction].num_frames = num_frames;
486 curr_vdatp->num_models++;
487 }
488
489 void
490 insert_frame_pointer
491 ( char direction,
492 void* frame
493 )
494 { struct model* curr_modelp;
495
496 curr_modelp = curr_model();
497
498 curr_modelp->spritesheet[(int)direction].frames[curr_modelp->spritesheet[(int)direction].num_frames++] = frame;
499 }
500