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