api with struct definitions in header file
[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
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 vlink 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->link_t.svlink.ref_id = ref_id;
206
207 }
208
209 /* At the point of reducing to a set, most of the
210 sets odat information has already been populated
211 during the reduction of its right hand side
212 non terminals (hitbox, root, quad_list). */
213 void
214 insert_set
215 ()
216 { uint64_t ref_id;
217 struct odat* curr_odatp;
218 struct cdat* curr_cdatp;
219 struct set* curr_setp;
220 struct ref* prev_refp;
221 struct ref* curr_refp;
222
223 curr_odatp = curr_set_odatp; //allocated at insert_set_label, preserved in global space
224 curr_cdatp = curr_cdat();
225 curr_setp = curr_set();
226 prev_refp = prev_ref();
227 curr_refp = alloc_ref();
228
229
230 curr_setp->cdat_idx = curr_cdatp->idx; //does a set need its class idx?
231 memmove(curr_setp->name, curr_odatp->name, 32);
232 curr_cdatp->num_sets++;
233
234 curr_odatp->cdat_idx = curr_cdatp->idx;
235 curr_odatp->refp = curr_refp;
236
237 ref_id = curr_setp->ref_id; // ref_id set by insert_set_label(name, ref_id)
238
239 if(ref_id == -1) /* user did not define a ref_id */
240 { ref_id = ss_ref_id;
241 ss_ref_id++;
242 }
243
244 curr_refp->ref_id = ref_id;
245 curr_refp->lastref = prev_refp;
246 curr_refp->odatp = curr_odatp;
247 prev_refp->nextref = curr_refp;
248
249
250
251 }
252 /* Created as a seperate function, instead of setting the ODATS vdat_id and
253 calling inc_vdat() inside of insert_set(), to account for the set reduction
254 where a vdat is not created (o/v/svlinks). */
255 void
256 insert_set_vdatid
257 ()
258 {
259 curr_set_odatp->vdat_id = num_vdats; //no vdat_id for odats that have vlinks/svlinks
260 curr_set_odatp = NULL; //So this sets odat cant be modified after (which would be a bug)
261 }
262
263 /* Populates both the odat name and ref_id
264 for odat and ele */
265 void
266 insert_ele_label
267 ( char* name,
268 uint64_t ref_id
269 )
270 {
271 struct ele* curr_elep;
272 struct odat* curr_odatp;
273
274 curr_elep = curr_ele();
275 curr_odatp = alloc_odat();
276
277 memmove(curr_odatp->name, name, 32);
278
279 memmove(curr_elep->name, name, 32);
280 curr_elep->ref_id = ref_id;
281 }
282
283 void
284 insert_ele_olink
285 ( uint64_t ref_id
286 )
287 {
288 struct cdat* curr_cdatp;
289 struct set* curr_setp;
290 struct ele* curr_elep;
291 struct link* curr_linkp;
292
293 curr_cdatp = curr_cdat();
294 curr_elep = curr_ele();
295 curr_linkp = alloc_link();
296
297 curr_elep->cdat_idx = curr_cdatp->idx;
298 curr_elep->ref_id = ref_id; /* Will be resolved to offset
299 when link is processed */
300 curr_linkp->type = 1;
301 curr_linkp->link_t.olink.ref_id = ref_id;
302 curr_linkp->cdat_idx = curr_cdatp->idx;
303 curr_linkp->set_idx = curr_cdatp->num_sets++;
304 curr_linkp->ele_idx = curr_setp->num_ele++;
305
306 }
307
308 void
309 insert_ele_vlink
310 ( uint64_t ref_id,
311 char* anim_name
312 )
313 {
314 struct cdat* curr_cdatp;
315 struct set* curr_setp;
316 struct link* curr_linkp;
317
318 curr_cdatp = curr_cdat();
319 curr_setp = curr_set();
320 curr_linkp = alloc_link();
321
322 /* Insert vlink into link_stack so that it gets processed at
323 output time */
324 curr_linkp->cdat_idx = curr_cdatp->idx;
325 curr_linkp->type = 2;
326 curr_linkp->set_idx = curr_cdatp->num_sets;
327 curr_linkp->ele_idx = curr_setp->num_ele;
328 curr_linkp->link_t.vlink.ref_id = ref_id;
329 memmove(curr_linkp->link_t.vlink.anim_name, anim_name, 32);
330
331 }
332
333 void
334 insert_ele_svlink
335 ( uint64_t ref_id
336 )
337 {
338 struct cdat* curr_cdatp;
339 struct set* curr_setp;
340 struct link* curr_linkp;
341
342 curr_cdatp = curr_cdat();
343 curr_setp = curr_set();
344 curr_linkp = alloc_link();
345
346 curr_linkp->cdat_idx = curr_cdatp->idx;
347 curr_linkp->type = 3;
348
349 curr_linkp->ele_idx = curr_setp->num_ele;
350 curr_linkp->link_t.svlink.ref_id = ref_id;
351
352
353 }
354
355 //Insert element into odat_buf and cdatpages
356 void
357 insert_ele()
358 {
359 uint64_t ref_id;
360 struct cdat* curr_cdatp;
361 struct odat* curr_odatp;
362 struct set* curr_setp;
363 struct ele* curr_elep;
364 struct ref* curr_refp;
365 struct ref* prev_refp;
366
367 curr_cdatp = curr_cdat();
368 curr_odatp = curr_odat(); //malloced @ insert_ele_label
369 curr_setp = curr_set();
370 curr_elep = curr_ele();
371 curr_refp = alloc_ref();
372 prev_refp = prev_ref();
373
374 /* Populate ele in cdat */
375 curr_elep->cdat_idx = curr_cdatp->idx;
376 curr_setp->num_ele++;
377
378 /* Populate odat for ele */
379 curr_odatp->cdat_idx = curr_cdatp->idx;
380 curr_odatp->refp = curr_refp;
381
382 /* Add ele to ref_buf */
383 ref_id = curr_elep->ref_id;
384
385 if(ref_id == -1) /* user did not define a ref_id so */
386 { ref_id = ss_ref_id;
387 ss_ref_id++;
388 }
389
390 curr_refp->ref_id = ref_id;
391 curr_refp->lastref = prev_refp;
392 curr_refp->odatp = curr_odatp;
393 prev_refp->nextref = curr_refp;
394
395 }
396
397 void
398 insert_ele_vdatid
399 ()
400 { struct odat* curr_odatp;
401 curr_odatp = curr_odat();
402 curr_odatp->vdat_id = num_vdats;
403 }
404
405 void
406 insert_quad
407 ( int x,
408 int y,
409 int z,
410 uint64_t ref_id
411 )
412 {
413
414 struct quad* curr_quadp;
415 struct odat* curr_odatp;
416
417 curr_quadp = curr_quad();
418 curr_odatp = curr_odat();
419
420 curr_quadp->x = x;
421 curr_quadp->y = y;
422 curr_quadp->z = z;
423 curr_quadp->ref_id = ref_id;
424 curr_odatp->num_quads++;
425 }
426
427 /* Inserting the hitbox into the set
428 odat. Elements that don't have
429 a hitbox will use the sets root. */
430 void
431 insert_hitbox
432 ( int hitbox
433 )
434 { struct odat* curr_odatp;
435
436 curr_odatp = curr_odat();
437 curr_odatp->hitbox = hitbox;
438 }
439
440 /* Inserting the root into the set
441 odat. Elements that don't have
442 a root will use the sets root. */
443 void
444 insert_root
445 ( int x,
446 int y,
447 int z
448 )
449 { struct odat* curr_odatp;
450
451 curr_odatp = curr_odat();
452 curr_odatp->root.x = x;
453 curr_odatp->root.y = y;
454 curr_odatp->root.z = z;
455 }
456
457
458 void
459 insert_framesheet
460 ( char direction,
461 char* name,
462 uint64_t ref_id,
463 int height ,
464 int width,
465 int num_frames
466 )
467 { struct vdat* curr_vdatp;
468 struct model* curr_modelp;
469
470 curr_vdatp = curr_vdat();
471 curr_modelp = curr_model();
472
473 curr_modelp->spritesheet[(int)direction].height = height;
474 curr_modelp->spritesheet[(int)direction].width = width;
475 curr_modelp->spritesheet[(int)direction].num_frames = num_frames;
476 curr_vdatp->num_models++;
477 }
478
479 void
480 insert_frame_pointer
481 ( char direction,
482 void* frame
483 )
484 { struct model* curr_modelp;
485
486 curr_modelp = curr_model();
487
488 curr_modelp->spritesheet[(int)direction].frames[curr_modelp->spritesheet[(int)direction].num_frames++] = frame;
489 }
490