432581393f98eba20912c39ed53d791b334420f2
[henge/apc.git] / src / 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 <stdlib.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 <string.h> //memset
13 #include <unistd.h> //u8_* functions
14 #include "apc.h"
15
16
17 extern
18 int
19 name_u8_cpy(struct name*, struct name*);
20
21 extern
22 int
23 name_u8_cmp(struct name*, struct name*);
24
25 extern
26 int
27 name_u8_set(struct name*, ucs4_t);
28
29 int
30 ir_init(void);
31 struct cdat*
32 alloc_cdat(void);
33 struct odat*
34 alloc_odat(void);
35 void
36 alloc_vdat(void);
37 struct link*
38 alloc_link(void);
39 struct ref*
40 alloc_ref(void);
41 struct set*
42 alloc_set(void);
43 struct cdat*
44 curr_cdat(void);
45 struct odat*
46 curr_odat(void);
47 struct vdat*
48 curr_vdat(void);
49 struct map*
50 curr_map(void);
51 struct set*
52 curr_cdat_set(void);
53 struct set*
54 curr_set(void);
55 struct ref*
56 curr_ref(void);
57 struct model*
58 curr_model(void);
59
60 /* ir.c */
61 void
62 inc_posts(void);
63 void
64 push_cdat(struct name*);
65 void
66 pop_cdat(void);
67 void
68 insert_refid(int);
69 void
70 insert_link_name(struct name*);
71 void
72 insert_link_namelist(struct name*);
73 void
74 insert_ss_name(struct name*);
75 void
76 insert_ss_namelist(struct name*);
77 void
78 insert_mlink(struct name*, int);
79 void
80 insert_vlink(struct name*, int);
81 void
82 insert_ref(struct odat*, int);
83 void
84 alloc_vdat(void);
85 void
86 insert_vdat(void);
87 void
88 insert_map(struct name*, int, int, int, int, uint8_t*);
89 void
90 insert_framesheet(struct name*, int, int, int, int, uint8_t*);
91
92
93
94 //type safety handled by macro expansion (do not call these directly from code, make dependent macros for access to these)
95 #define CHUNKS_LEN(STACK) ((STACK).csp - (STACK).chunks)
96 #define CURRENT_CHUNK(STACK) ((STACK).chunks[CHUNKS_LEN(STACK) - 1])
97 #define CHUNKS_FULL(STACK) ( (STACK).csp >= \
98 (STACK).chunks + MAX_CHUNKS * (STACK).chunk_size)
99 #define CURRENT_DSP(STACK,TYPE) ((TYPE*) ((STACK).dsp[CHUNKS_LEN(STACK) - 1]))
100 #define DATA_FULL(STACK,TYPE) ((void*) CURRENT_DSP(STACK,TYPE) >= \
101 (CURRENT_CHUNK(STACK) + (STACK).chunk_size))
102 #define CSP_PUSH(STACK) (*(++(STACK).csp) = malloc((STACK).chunk_size))
103 #define CURRENT_DATP(STACK,TYPE) (((TYPE**)(STACK).dsp)[CHUNKS_LEN(STACK) - 1])
104 #define PREVIOUS_DATP(STACK,TYPE) (((TYPE**)(STACK).dsp)[CHUNKS_LEN(STACK) - 2])
105 #define ALLOC_DAT(STACK,TYPE) (++CURRENT_DATP(STACK,TYPE))
106 #define INIT_STACK(STACK,TYPE) \
107 { int i; \
108 (STACK).chunk_size = PAGES_PER_CHUNK * pagesize; \
109 (STACK).max_dats = (STACK).chunk_size / sizeof (TYPE); \
110 CSP_PUSH(STACK); \
111 for( i = 0; i < MAX_CHUNKS; i++){ \
112 (STACK).dsp[i] += pagesize; \
113 } \
114 }
115 //Stack-specific macros (called directly from code (safety enforcement)
116 #define INIT_ODAT() (INIT_STACK(ocs, struct odat))
117 #define CURRENT_ODAT() (CURRENT_DATP(ocs,struct odat))
118 #define ODAT_FULL() (DATA_FULL(ocs,struct odat))
119 #define ODAT_ALLOC() (ALLOC_DAT(ocs,struct odat))
120 #define OCS_FULL() (CHUNKS_FULL(ocs))
121 #define INIT_VDAT() (INIT_STACK(vcs, struct vdat))
122 #define CURRENT_VDAT() (CURRENT_DATP(vcs,struct vdat))
123 #define VDAT_FULL() (DATA_FULL(vcs,struct vdat))
124 #define VDAT_ALLOC() (ALLOC_DAT(vcs,struct vdat))
125 #define VCS_FULL() (CHUNKS_FULL(vcs))
126 #define INIT_CDAT() (INIT_STACK(ccs, struct cdat))
127 #define CURRENT_CDAT() (CURRENT_DATP(ccs,struct cdat))
128 #define CDAT_FULL() (DATA_FULL(ccs, struct cdat))
129 #define CDAT_ALLOC() (ALLOC_DAT(ccs, struct cdat))
130 #define CCS_FULL() (CHUNKS_FULL(ccs))
131 #define INIT_SET() (INIT_STACK(scs, struct set))
132 #define CURRENT_SET() (CURRENT_DATP(scs, struct set))
133 #define SET_FULL() (DATA_FULL(scs, struct set))
134 #define SET_ALLOC() (ALLOC_DAT(scs, struct set))
135 #define SCS_FULL() (CHUNKS_FULL(scs))
136 #define INIT_LINK() (INIT_STACK(lcs, struct link))
137 #define CURRENT_LINK() (CURRENT_DATP(lcs,struct link))
138 #define LDAT_FULL() (DATA_FULL(lcs, struct link))
139 #define LDAT_ALLOC() (ALLOC_DAT(lcs, struct link))
140 #define LCS_FULL() (CHUNKS_FULL(lcs))
141 #define INIT_POST() (INIT_STACK(rcs, struct ref))
142 #define CURRENT_POST() (CURRENT_DATP(pcs,struct ref))
143 #define POST_FULL() (DATA_FULL(pcs,struct ref))
144 #define POST_ALLOC() (ALLOC_DAT(pcs,struct ref))
145 #define PCS_FULL() (CHUNKS_FULL(pcs))
146 #define INIT_REF() (INIT_STACK(rcs, struct ref))
147 #define CURRENT_REF() (CURRENT_DATP(rcs,struct ref))
148 #define PREVIOUS_REF() (PREVIOUS_DATP(rcs, struct ref))
149 #define REF_FULL() (DATA_FULL(rcs,struct ref))
150 #define REF_ALLOC() (ALLOC_DAT(rcs,struct ref))
151 #define RCS_FULL() (CHUNKS_FULL(rcs))
152 //Metadata
153 #define CURRENT_MODEL() (CURRENT_VDAT()->model_list[CURRENT_VDAT()->num_models])
154
155
156
157
158 /* Cdats: A cdat is a class data structure. Cdats serve as the central */
159 /* data types of the IR. Cdats contain pointers to their subclasses so that the relationship between */
160 /* classes can be determined, but the subclasses are not represented inside */
161 /* of the cdat itself but rather in subsequent cdats in cdat_buf. We */
162 /* can determine the number of subclasses (the last index into cdat_buf */
163 /* that represents a subclass of some arbitrary cdat) each cdat has by */
164 /* incrementing num_classes during parse time. */
165 /* TODO: Should classes point to their parent class? */
166 /* TODO: Talk more about cdat set structure */
167
168 struct cdat {
169 struct name name;
170 int idx;
171 int num_classes;
172 int num_sets;
173 struct cdat* class_list[MAX_CLASSES];
174 struct set* set_list[MAX_SETS];
175 };
176
177
178 struct set {
179 int cdat_idx;
180 int num_sets;
181 struct set* set_list[MAX_SETS];
182 };
183
184 struct ref {
185 struct ref* nextref;
186 struct ref* lastref;
187 struct odat* odatp;
188 int refid; //0xFFFFFF->digit
189 };
190
191 struct olink {
192 int src_refid;
193 };
194
195 struct vlink {
196 int src_refid;
197 struct name src_animname;
198 struct name src_namelist[MAX_DEPTH];
199 };
200
201 struct mlink {
202 int src_refid;
203 struct name src_mapname;
204 struct name src_namelist[MAX_DEPTH];
205
206 };
207
208 union link_t {
209 struct vlink vlink;
210 struct mlink mlink;
211 struct olink olink;
212 };
213
214
215 /* Links are a mechanism for designers to indicate in the grammar that a odat, vdat, or map
216 is defined elsewhere and that the link should be replaced with the specified odat/vdat/map */
217 struct link {
218 int type; //1 = olink, 2 = vlink, 3 = mlink
219 union link_t link_t;
220 int dest_refid; //if it exists
221 struct odat* dest_odatp;
222
223 };
224
225 struct map {
226 struct name name;
227 int height;
228 int width;
229 uint8_t filepath[FPATH_MAX];
230 };
231
232 /* Odats: Odats consist of the object data necessary for
233 each object. Odats are sometimes referred to as archetypes
234 at compile-time, in order to distinguish the difference from
235 a runtime object and a compile-time object.
236 TODO: Need more info about objects at runtime, to described
237 the reasoning behind odat structure at compile-time*/
238 struct odat {
239 struct name name;
240 int refid;
241 int ismap;
242 int vdat_idx;
243 struct link* linkp;
244 struct vdat* vdatp;
245 struct odat* parent_odatp; /* null if parent is a cdat */
246 struct ref* refp; /* pointer to it's ref on ref_list */
247 struct map map; /* only valid if odat ismap */
248
249 };
250
251 /* A framesheet is a grouping of animation frames in a single direction (N,W,S,E, etc.). Framesheets
252 also hold the framesheet dimensions and the filepath to the png of the framesheet so the file can be opened
253 and the png data can be extracted. */
254 struct framesheet {
255 int width;
256 int height;
257 uint8_t filepath[FPATH_MAX];
258 int num_frames;
259
260 };
261
262 /* A model is a collection of framesheets for every
263 direction (N,W,S,E,NW,NE,SW,SE). Currently, users can only define
264 framesheets in the APC grammar, which are inserted into the current model*/
265 struct model {
266 struct name name;
267 struct framesheet spritesheet[8]; //one for each
268 };
269
270 /* Vdat: Vdats are the video data of each object. Vdats have a list of models for every
271 animation that the vdats odat can do for that vdat. */
272 struct vdat {
273 struct odat* creator; //pointer to odat that made this vdat
274 int num_models;
275 struct model model_list[MAX_MODELS];
276 };
277
278 /* An entry on the set_stack that describes the namelist and relevant information for
279 the current set that is being processed in the parser. For each set name,
280 there is a corresponding set/odat that is created when set names are encountered. */
281
282 struct set_frame
283 { struct name namelist[MAX_DEPTH];
284 int num_names;
285 struct set* setp;
286 struct odat* odatp;
287 } ;
288
289 /* Stores the last defined set at every depth */
290 struct set_stack
291 { struct set_frame set_frames[MAX_DEPTH];
292 int curr_depth; //used to get most recently created set/odat + to check for undefined parents of namelists
293 };
294
295
296 //"type free" chunk stacking
297 struct chunk_stack
298 { void* chunks[MAX_CHUNKS];
299 void* *csp; //chunk stack pointer
300 void* dsp[MAX_CHUNKS]; //dat stack pointer (per chunk)
301 int chunk_size; //size of a chunk (including its forfeited page)
302 int max_dats; //number of dats per chunk for this stack
303 } ocs, vcs, ccs, rcs, lcs, pcs, scs; //odat, vdat, cdat, ref, link, post stacks
304
305 /* The cdat_stack is a stack pointers to cdat pointers, the top of which is
306 the cdat that is currently being parsed. Whenever a new cdat is recognized
307 by the grammar (CLOPEN), a cdat is pushed onto the cdat_stack, and we refer
308 to this cdat through the macro CURR_CDAT. By keeping a cdat_stack, we have
309 access to the current cdat so that the elements and sets can populate themselves
310 in the cdat accordingly. */
311
312 struct cdat* cdat_stack[MAX_CLASSES];
313 struct cdat** cdat_stackp;
314
315
316
317 struct set_stack ss;
318 struct name set_namelist[MAX_DEPTH];
319 int set_numnames = 0;
320
321 struct name link_namelist[MAX_DEPTH];
322 int link_numnames = 0;
323
324 int num_cdats = 0;
325 int num_odats = 0;
326 int num_vdats = 0;
327 int num_sets = 0;
328 int num_refs = 0;
329 int ss_refid = 0x0FFFFFFF; /* system space for refids */
330 int num_posts = 0;
331 int num_links = 0;
332 int num_models = 0;
333 long pagesize = 0;
334
335
336 /* The initalization function of the IR. */
337 int
338 ir_init()
339 { struct name name;
340
341
342 uint8_t root[4] = "root";
343
344 u8_stpncpy(name.name, root, 4);
345
346 pagesize = sysconf(_SC_PAGESIZE);
347
348 INIT_CDAT();
349 *cdat_stackp = CURRENT_CDAT();
350 name_u8_cpy(&(*cdat_stackp)->name, &name);
351
352 INIT_ODAT();
353 INIT_VDAT();
354 VDAT_ALLOC(); //NULL vdat
355 VDAT_ALLOC(); //First vdat req. because alloc_vdat happens after vdat is reduced
356 INIT_SET();
357 INIT_LINK();
358 INIT_REF();
359 INIT_POST();
360
361
362 return 0;
363
364 }
365
366 void
367 ir_quit()
368 {
369 int i;
370
371 for(i = 0; i < CHUNKS_LEN(ccs) ; i++)
372 {
373 free(ccs.chunks[i]);
374 }
375 for(i = 0; i < CHUNKS_LEN(ocs); i++)
376 {
377 free(ocs.chunks[i]);
378 }
379 for(i = 0; i < CHUNKS_LEN(vcs) ; i++)
380 {
381 free(vcs.chunks[i]);
382 }
383 for(i = 0; i < CHUNKS_LEN(rcs); i++)
384 {
385 free(rcs.chunks[i]);
386 }
387 for(i = 0; i < CHUNKS_LEN(lcs); i++)
388 {
389 free(lcs.chunks[i]);
390 }
391 for(i = 0; i < CHUNKS_LEN(pcs); i++)
392 {
393 free(pcs.chunks[i]);
394 }
395
396 }
397
398 struct cdat*
399 alloc_cdat()
400 {
401 num_cdats++;
402 if(CDAT_FULL())
403 { if(CCS_FULL())
404 { fprintf(stderr, "You have allocated to many (%d) cdats ", num_cdats);
405 exit(EXIT_FAILURE);
406 }
407 else
408 CSP_PUSH(ccs);
409 }
410 else
411 CDAT_ALLOC();
412
413 return CURRENT_CDAT();
414 }
415
416 //these should probably be inline
417 struct odat*
418 alloc_odat
419 ()
420 {
421 num_odats++;
422 if(ODAT_FULL())
423 { if(!OCS_FULL())
424 { fprintf(stderr, "You have allocated to many (%d) odats ", num_odats);
425 exit(EXIT_FAILURE);
426 }
427 else
428 CSP_PUSH(ocs);
429 }
430 else
431 ODAT_ALLOC();
432
433 return CURRENT_ODAT();
434 }
435
436 void
437 alloc_vdat
438 ()
439 { num_vdats++;
440 if(VDAT_FULL())
441 { if(!VCS_FULL())
442 { fprintf(stderr, "You have allocated to many (%d) vdats ", num_vdats);
443 exit(EXIT_FAILURE);
444 }
445 else
446 CSP_PUSH(vcs);
447 }
448 else
449 VDAT_ALLOC();
450
451
452 }
453
454 struct set*
455 alloc_set
456 ()
457 { num_sets++;
458 if(SET_FULL())
459 { if(!SCS_FULL())
460 { fprintf(stderr, "You have allocated to many (%d) sets ", num_sets);
461 exit(EXIT_FAILURE);
462 }
463 else
464 CSP_PUSH(scs);
465 }
466 else
467 SET_ALLOC();
468
469 return CURRENT_SET();
470 }
471
472
473 struct link*
474 alloc_link
475 ()
476 { num_links++;
477 if(LDAT_FULL())
478 { if(!LCS_FULL())
479 { fprintf(stderr, "You have allocated to many (%d) links ", num_links);
480 exit(EXIT_FAILURE);
481 }
482 else
483 CSP_PUSH(lcs);
484 }
485 else
486 LDAT_ALLOC();
487
488 return CURRENT_LINK();
489
490 }
491
492 struct ref*
493 alloc_ref
494 ()
495 { num_refs++;
496 if(REF_FULL())
497 { if(!RCS_FULL())
498 { fprintf(stderr, "You have allocated to many (%d) refs ", num_refs);
499 exit(EXIT_FAILURE);
500 }
501 else
502 CSP_PUSH(rcs);
503 }
504 else
505 REF_ALLOC();
506
507
508 if(num_refs % 16 == 0)
509 { CURRENT_POST() = CURRENT_REF();
510 inc_posts();
511 }
512
513 return CURRENT_REF();
514 }
515
516 void
517 inc_posts()
518 { num_posts++;
519 if(POST_FULL())
520 { if(!PCS_FULL())
521 { fprintf(stderr, "You have allocated to many (%d) refs ", num_posts);
522 exit(EXIT_FAILURE);
523 }
524 else
525 CSP_PUSH(pcs);
526 }
527 else
528 POST_ALLOC();
529
530 }
531
532 struct cdat*
533 curr_cdat
534 ()
535 {
536 return (*cdat_stackp);
537 }
538
539 struct odat*
540 curr_odat
541 ()
542 {
543 return CURRENT_ODAT();
544 }
545
546 struct vdat*
547 curr_vdat
548 ()
549 {
550 return CURRENT_VDAT();
551 }
552 struct set*
553 curr_cdat_set
554 ()
555 {
556 return CURRENT_SET();
557 }
558
559 struct ref*
560 curr_ref
561 ()
562 {
563 return CURRENT_REF();
564 }
565 struct ref*
566 prev_ref
567 ()
568 {
569 return PREVIOUS_REF();
570 }
571 struct model*
572 curr_model
573 ()
574 {
575 return &CURRENT_MODEL();
576 }
577
578 /* IR.C*/
579 void
580 push_cdat
581 ( struct name* name )
582 {
583 struct cdat* curr_cdatp;
584
585 curr_cdatp = alloc_cdat();
586
587 name_u8_cpy(&curr_cdatp->name, name);
588 curr_cdatp->idx = num_cdats;
589
590 /* Set the cdat as a subclass of the previous cdat */
591 (*cdat_stackp)->class_list[(*cdat_stackp)->num_classes++] = curr_cdatp;
592 /* Push the cdat onto the cdat_stack */
593 *++cdat_stackp = curr_cdatp;
594
595 }
596
597 void
598 pop_cdat
599 ()
600 {
601 cdat_stackp--;
602 }
603
604
605
606 void
607 insert_set_name
608 ( struct name* name )
609 {
610 //Push name onto current namelist, set the set_namelist.
611 name_u8_cpy(&set_namelist[set_numnames++], name);
612
613 }
614
615
616 /* Called at the last name of a sets namelist. Inserts the set namelist
617 onto the set_stack at the appropriate depth i.e. the number of names in
618 the namelist. If each name in the namelist at every depth matches, nothing happens. For every
619 name on the namelist that doesnt match what is currently on the set_stack,
620 a new set/odat is created at the depth that it describes. E.g. a set name
621 of A_B_C is a depth of 3 and is represented in the set_stack as A, A_B and A_B_C.
622 If a new set namelist is defined, X_Y, the new set_stack will become X, X_Y. */
623
624 void
625 insert_set_namelist
626 ( struct name* name )
627 { int depth, nameidx, i;
628
629 insert_set_name(name);
630
631
632 for( depth = 0; depth < set_numnames ; depth++ )
633 { for (nameidx = 0; nameidx <= depth; nameidx++)
634 { if( name_u8_cmp(&set_namelist[nameidx], &ss.set_frames[depth].namelist[nameidx]) != 0 )
635 { /* Populate the namelist of the set at the current depth */
636 for(i = 0; i <= depth; i++)
637 name_u8_cpy(&ss.set_frames[depth].namelist[i], &set_namelist[i]);
638
639 /* Alloc set and odat */
640 ss.set_frames[depth].odatp = alloc_odat();
641 ss.set_frames[depth].setp = alloc_set();
642
643 /* populate set/odat name and cdat_idx */
644 name_u8_cpy(&ss.set_frames[depth].odatp->name, &set_namelist[depth]);
645 ss.set_frames[depth].setp->cdat_idx = ( *cdat_stackp)->idx;
646
647 /* Insert allocated set and odat into their respective trees if there is a depth
648 (they have parents) */
649 if(depth)
650 { ss.set_frames[depth].odatp->parent_odatp = ss.set_frames[depth-1].odatp;
651 if(ss.set_frames[depth-1].setp->num_sets < MAX_SETS)
652 ss.set_frames[depth-1].setp->set_list[ss.set_frames[depth-1].setp->num_sets++] = ss.set_frames[depth].setp;
653 else
654 { printf("you have allocated too many sets in insert_namelist()\n");
655 //TODO: EXIT()
656 }
657 }
658 else /* no parent set, so assign to cdat set_list */
659 { ss.set_frames[depth].odatp->parent_odatp = NULL; //no parent odat = NULL.
660 if(curr_cdat_set()->num_sets < MAX_SETS)
661 curr_cdat_set()->set_list[curr_cdat_set()->num_sets++] = ss.set_frames[depth].setp;
662 else
663 { printf("you have allocated too many sets in insert_namelist()\n");
664 //TODO: EXIT()
665 }
666 }
667
668
669 ss.set_frames[depth].num_names = set_numnames;
670 ss.curr_depth = depth;
671
672 /* Every set has a vdat, but some won't be populated because the namelist that instantiated */
673 /* the set might not have a SS statement that populates the models of the vdat. This is ok */
674 /* because 1) IR is supposed to be bloated so that binary out isnt 2) this functionality */
675 /* preserves the assumptions that insert_framesheet() makes when it calls curr_vdat() */
676 alloc_vdat();
677 }
678
679 }
680
681 }
682
683 /* Set to 0 to reset for next set_namelist */
684 set_numnames = 0;
685 }
686
687
688 /* We create new odats for each map variant that are children of the current odat/set
689 set their name as the map name, and identify them by marking them as a map. This lets
690 us distinguish between sibling odats that have the same name because the map of the parent
691 odat had the same name as another, regular odat. */
692 #define CURR_SS_FRAME() (ss.set_frames[ss.curr_depth])
693 #define CURR_SS_SETP() (CURR_SS_FRAME().setp)
694 #define CURR_SS_ODATP() (CURR_SS_FRAME().odatp)
695 void
696 insert_map
697 ( struct name* name, int direction, int height, int width, int refid, uint8_t* filepath )
698 { int i;
699 struct odat* curr_map_odatp; //pointer to odat in odat_buf
700 struct set* curr_map_setp; //pointer to set in set_buf
701 struct link* linkp;
702
703 curr_map_odatp = alloc_odat();
704 curr_map_setp = alloc_set();
705 /* Create a new odat, make its parent be the set. Make a set for mdat, its name should */
706 /* be the name of the odat + name of model. That makes a conflict beween odats that are named */
707 /* the same thing as the model of a sibling odat that was created from a map. They can have */
708 /* same name if the map odat is marked. So mark the map odat. */
709
710 /* insert parent odat */
711 curr_map_odatp->parent_odatp = CURR_SS_ODATP();
712
713 /* insert into set_list */
714 if(CURR_SS_SETP()->num_sets < MAX_SETS)
715 CURR_SS_SETP()->set_list[CURR_SS_SETP()->num_sets++] = curr_map_setp;
716 else
717 { printf("You have allocated to many sets, error in insert_map()\n");
718 //TODO: EXIT()
719 }
720
721 /* indicate that newly created odat is a map */
722 curr_map_odatp->ismap = 1;
723 /* set odat and set name */
724 name_u8_cpy(&curr_map_odatp->name, name);
725
726 /* set cdat idx values for both set and odat */
727 curr_map_setp->cdat_idx = num_cdats;
728
729 /* Insert map information into the odats map */
730 curr_map_odatp->map.height = height;
731 curr_map_odatp->map.width = width;
732 u8_stpncpy(curr_map_odatp->map.filepath, filepath, FPATH_MAX);
733
734
735 /* Generate refid if needed, put into ref_buf */
736 if(!refid)
737 refid = ss_refid++;
738
739 insert_ref(curr_map_odatp, refid);
740
741 /* If current odatp on stack has a link, then we need to make our own link. just set the vdat_idx */
742 if(CURR_SS_ODATP()->vdat_idx == 0)
743 { linkp = alloc_link();
744 linkp->type = CURR_SS_ODATP()->linkp->type;
745 linkp->dest_odatp = CURR_SS_ODATP();
746 linkp->dest_refid = refid;
747 linkp->link_t.mlink.src_refid = CURR_SS_ODATP()->linkp->link_t.mlink.src_refid;
748
749 /* Copy the animation name of the vlink*/
750 name_u8_cpy(&linkp->link_t.vlink.src_animname, &CURR_SS_ODATP()->linkp->link_t.vlink.src_animname);
751 /* Copy the namelist of the vlink*/
752 for(i = 0; i < MAX_DEPTH; i++)
753 name_u8_cpy(&linkp->link_t.vlink.src_namelist[i], &CURR_SS_ODATP()->linkp->link_t.vlink.src_namelist[i]);
754 }
755 else
756 curr_map_odatp->vdat_idx = CURR_SS_ODATP()->vdat_idx;
757
758 }
759
760
761 /* 11/22 Each vdat has a multiple models. Each model has 8 framesheets, one in each
762 direction, that create a spritesheet. Inserting framesheets into the correct
763 model is just a matter of checking whether or not the last models name matches
764 the current one. We can never get a framesheet that is for the same model before
765 AND after some other model, due to alphasorting of the files in each directory */
766 void
767 insert_framesheet
768 ( struct name* model_name, int direction, int height, int width, int refid, uint8_t* filepath )
769 { struct vdat* curr_vdatp;
770 struct model* curr_modelp;
771 static struct name last_model_name[32];
772
773 curr_vdatp = curr_vdat();
774
775 /* If the model name changed, that means there are no more
776 framesheets for that model to be processed, a guaruntee we make
777 b/c the filenames are alphabetically sorted */
778 if(!name_u8_cmp(last_model_name, model_name))
779 { if(curr_vdatp->num_models)
780 curr_vdatp->num_models++;
781 num_models++; // total number of models
782 }
783
784
785 if(CURR_SS_ODATP()->refid == 0)
786 { if(!refid)
787 refid = ss_refid++;
788 insert_ref(CURR_SS_ODATP(), refid); /* given a odatp and a refid, insert the odatp into the ref_buf. */
789 }
790 else
791 printf("error: redefining a previously set refid\n");
792
793 curr_modelp = curr_model();
794
795 name_u8_cpy(&curr_modelp->name, model_name);
796 curr_modelp->spritesheet[direction].height = height;
797 curr_modelp->spritesheet[direction].width = width;
798 u8_stpncpy(curr_modelp->spritesheet[direction].filepath, filepath, FPATH_MAX);
799
800 name_u8_cpy(last_model_name, model_name);
801
802 }
803
804
805 void
806 insert_mlink
807 ( struct name* src_mapname, int src_refid)
808 { struct link* linkp;
809 int i;
810
811 linkp = alloc_link();
812
813 /* set type */
814 linkp->type = 3;
815 /* set the name of the src map for the link, if a name exists */
816 if(src_mapname)
817 name_u8_cpy(&linkp->link_t.mlink.src_mapname, src_mapname);
818 /* Set the source ref id of the link */
819 linkp->link_t.mlink.src_refid = src_refid;
820
821 /* Copy the entire namelist of the link, if it exists */
822 for(i = 0; i < link_numnames; i--)
823 { name_u8_cpy(&linkp->link_t.mlink.src_namelist[i], &link_namelist[i]);
824 name_u8_set(&link_namelist[i], (ucs4_t) 0);
825 }
826 link_numnames = 0;
827
828 linkp->dest_odatp = CURR_SS_ODATP();//current odat on set_stack
829
830 }
831
832
833 void
834 insert_link_name
835 ( struct name* name )
836 {
837 //Push name onto current namelist, set the set_namelist.
838 name_u8_cpy(&link_namelist[link_numnames++], name);
839
840 }
841
842
843 /* Nearly identical to mlink */
844 void
845 insert_vlink
846 ( struct name* src_animname, int src_refid )
847 { struct link* linkp;
848 int i;
849
850 linkp = alloc_link();
851
852 /* set type */
853 linkp->type = 2;
854
855 /* set the name of the src animname for the link, if a name exists */
856 if(src_animname)
857 name_u8_cpy(&linkp->link_t.vlink.src_animname, src_animname);
858
859 /* Set the source ref id of the link */
860 linkp->link_t.mlink.src_refid = src_refid;
861
862 /* Copy the entire namelist of the link, if it exists */
863 for(i = 0; i < link_numnames; i++)
864 { name_u8_cpy(&linkp->link_t.vlink.src_namelist[i], &link_namelist[i]);
865 name_u8_set(&link_namelist[i], (ucs4_t) 0);//set to null for next link_namelist
866 }
867 link_numnames = 0;
868
869 linkp->dest_odatp = CURR_SS_ODATP();//current odat on set_stack
870
871 }
872
873
874 /* TODO: Do we really need to store the prev/next pointer? iterating through the
875 ref_buf could be achieved by iterating until the num_refs anyway. */
876 void
877 insert_ref
878 ( struct odat* odatp, int refid )
879 { struct ref* curr_refp;
880 struct ref* prev_refp;
881
882 curr_refp = alloc_ref();
883 prev_refp = prev_ref();
884
885 prev_refp->nextref = curr_refp;
886 curr_refp->lastref = prev_refp;
887
888 curr_refp->odatp = odatp;
889 curr_refp->refid = refid;
890
891 if(refid % 16)
892 { POST_ALLOC();
893 CURRENT_POST()->refid = refid;
894 CURRENT_POST()->odatp = odatp;
895 }
896
897 }
898
899
900 void
901 insert_refid
902 ( int refid )
903 { CURR_SS_ODATP()->refid = refid;
904 }
905
906
907 void
908 insert_vdat
909 ()
910 { struct vdat* curr_vdatp;
911
912 curr_vdatp = curr_vdat();
913
914 curr_vdatp->creator = CURR_SS_ODATP();
915 CURR_SS_ODATP()->vdat_idx = num_vdats;
916 CURR_SS_ODATP()->vdatp = curr_vdatp;
917 alloc_vdat();
918 }