page allocation is wrong
[henge/webcc.git] / src / apc / ir.h
1 /*!@file
2 \brief Intermediate Representation (IR) between Directory Structure and Engine Grammar
3 \details The IR serves as a storage structure that is populated during the
4 parsing of the input directory structure. After parsing is complete,
5 the IR will be condensed (removed of excess allocated space) and then
6 output as the Engine Grammar. In this file we describe the semantic actions
7 that are called at each step, and the memory buffers that they populate.
8 See parser.y for the description on how the input grammar is constructed,
9 and where/when semantic actions are called.
10 TODO: or just write it here.
11 \author Jordan Lavatai
12 \date Aug 2016
13 ----------------------------------------------------------------------------*/
14
15
16 #include <stdint.h>
17
18 #define BUF_SIZE 256
19 #define MAX_SETS 256
20 #define MAX_ELES 256
21 #define MAX_QUADS 256
22 #define MAX_MODELS 256
23 #define MAX_POSTS 256
24 #define MAX_CLASS_DEPTH 256
25 #define MAX_CLASSES 256
26 #define MAX_FRAMES 256
27 #define PTRS_IN_PAGE 1024
28 #define MAX_CHUNKS 256
29 #define PAGES_PER_CHUNK 16
30
31 /* General: All information from the directory structure is stored in */
32 /* five buffers that comprise the IR: cdat_buf, odat_buf, vdat_buf, ref_buf */
33 /* and link_buf. Each buf corresponds to the data structure that it stores. */
34 /* The storage techique for all bufs (except cdat) is the same. Each bufs member first */
35 /* populates its struct and then allocates the space for the next member */
36 /* and increments the buf index. This means that we have to allocate the */
37 /* very first member of each buf at ir_init(), so that we don't segfault */
38 /* as the first member attempts to access memory that its previous member */
39 /* didn't allocate (because it doesnt exist). We access the buf members */
40 /* through standard array indexing but conceal the tediousness of array */
41 /* indexing with macros. E.g. without macros, acessing an elements name */
42 /* member would look like (split up to not go over line char limit): */
43 /* (*cdat_stackp)->set_list[(*cdat_stackp)->num_sets] */
44 /* .ele_list[(*cdat_stackp)->set_list[(*cdat_stackp->num_sets)].num_ele].name */
45
46 /* For cdats in cdat_buf, we allocate the memory for a cdat once a cdat
47 is recognized in the grammar. Cdat_buf is different from the other bufs
48 because cdats have a root cdat that all cdats are a subclass of. This root
49 cdat can have a set_list like other cdats. */
50
51 /* All bufs are of pointers to their respective structs. When a buf is full */
52 /* (number of data structs pointers >= max number of data struct pointers), */
53 /* we need to allocate a more pointers for that buf. Allocate these */
54 /* pointers a page at a time (1024 = Page bytes (4096)/bytes per pointer(4)) */
55
56 /* Sets: The set is similar to the ele, but it contains a list of its */
57 /* elements. The set is populated at parse time AFTER the elements are */
58 /* populated, due to the nature of bottom up parsing. */
59
60 struct set {
61 char name[32];
62 uint64_t ref_id;
63 int cdat_idx;
64 };
65
66 /* Cdats: A cdat is a class data structure. Cdats serve as the central */
67 /* data types of the IR. At output, the cdat_buf is iterated through and */
68 /* each is written to the output file. For each cdat, sets and element */
69 /* ref_ids must be dereferenced to determine the odat information. Cdats */
70 /* contain pointers to their subclasses so that the relationship between */
71 /* classes can be determined, but the subclasses are not represented inside */
72 /* of the cdat itself but rather in the subsequent cdats in cdat_buf. We */
73 /* can determine the number of subclasses (the last index into cdat_buf */
74 /* that represents a subclass of some arbitrary cdat) each cdat has by */
75 /* incrementing num_classes during parse time. */
76 /* TODO: Should classes point to their parent class? */
77
78 struct cdat {
79 char name[32];
80 int idx;
81 int num_classes;
82 int num_sets;
83 struct cdat* class_list[MAX_CLASSES];
84 struct set set_list[MAX_SETS];
85 };
86
87 /* There are an unknown amount of cdats at compile time, so we maintain */
88 /* a cdat_buf of cdat pointers that can be expanded as needed. */
89
90 /* The cdat_stack is a stack pointers to cdat pointers, the top of which is
91 the cdat that is currently being parsed. Whenever a new cdat is recognized
92 by the grammar (CLOPEN), a cdat is pushed onto the cdat_stack, and we refer
93 to this cdat through the macro CURR_CDAT. By keeping a cdat_stack, we have
94 access to the current cdat so that the elements and sets can populate themselves
95 in the cdat accordingly. */
96
97
98 /* Refs: Each set/ele has a reference to its object data (odat) through a ref_id.
99 Ref_ids are unsigned 64 byte integers that map to the hex values RGBA. During
100 the construction of the directory structure, users can choose a RGBA value for
101 each object that any other object can refer to via links (see link). If a user
102 does not choose an RGBA value, then the object is given one from the system space.
103 We maintain a doubly linked list of refs in the ref_buf at parse time so that
104 links can be resolved after the parsing of the directory structure is complete.
105 For every 16th ref, we create a post so that we can reduce on the search time for
106 a random access. */
107
108 struct ref {
109 int type;
110 struct ref* nextref;
111 struct ref* lastref;
112 struct odat* odatp;
113 uint64_t ref_id; //0xFFFFFF->digit
114 };
115
116
117 /* Like the cdat_buf, ref_buf stores pointers to refs and can
118 increase in size */
119
120 /* posts for ref_buf */
121
122 /* Links: At parse time, a set/ele can include a link in their
123 grammar representation instead of the actual data and this signifies
124 to the APC that that set/ele wishes to use the data of another
125 set/ele, either its video data (vdat) or object data (odat). The link
126 itself contains the type of link it is, the ref_id OR name, and
127 which set/ele created the link. During parse time, links can be made
128 to o/vdats that have yet to be parsed. In order to accomodate for this,
129 we resolve all links AFTER parse time by iterating through the link_buf,
130 finding the ref_id that was stored for some object (if the ref_id exists),
131 and creating a relative pointer from the original object to the data that
132 was linked */
133
134 /* Svlinks stand for short vlink, which is a link to a vdat
135 TODO: diff btwn vlink*/
136
137 struct svlink {
138 uint64_t ref_id;
139 };
140
141 /* A vlink is what it sounds like, a link to a vdat
142 TODO: model link? */
143 struct vlink {
144 uint64_t ref_id;
145 char anim_name[32];
146 };
147
148 /* Olinks are links to odats */
149 struct olink {
150 uint64_t ref_id;
151 };
152
153 union link_t {
154 struct olink olink;
155 struct vlink vlink;
156 struct svlink svlink;
157 };
158
159 struct link {
160 int type; //1 = olink, 2 = vlink, 3 = svlink
161 union link_t link_t;
162 int cdat_idx;
163 int set_idx;
164 int ele_idx;
165 };
166
167 /* link_buf contains all the links that
168 we encountered during parse time that need
169 to be resolved to an offset at output time.
170 This does not include quad refs, because
171 those are already known to need to be resolved */
172
173
174 /* Odats: Odats consist of the object data necessary for
175 each object. Odats are sometimes referred to as archetypes
176 at compile-time, in order to distinguish the difference from
177 a runtime object and a compile-time object.
178 TODO: Need more info about objects at runtime, to described
179 the reasoning behind odat structure at compile-time*/
180
181
182 struct root {
183 int x, y, z;
184 };
185
186 struct odat {
187 char name[32];
188 int vdat_id;
189 int cdat_idx;
190 int hitbox;
191 uint64_t ref_id;
192 struct root root;
193 struct ref* refp; /* pointer to it's ref on ref_list */
194 void* quad_filep;
195 };
196
197 struct odat* curr_set_odatp; //when a set has elements, insert_set() can no longer
198 //refer to its odat via curr_odat, so save the set odat.
199
200 /* A framesheet is a grouping of animation frames in
201 a single direction (N,W,S,E) */
202 struct framesheet {
203 int width;
204 int height;
205 int num_frames;
206 void* frames[MAX_FRAMES];
207 };
208
209 /* A model is a collection of framesheets for every
210 direction (N,W,S,E,NW,NE,SW,SE)*/
211 /* NAMED spritesheet */
212 struct model {
213 char name[32];
214 struct framesheet spritesheet[8]; //one for each
215 };
216
217 /* Vdat: Vdats are the video data of each object. They can not be
218 created as a stand alone object (because they consist solely
219 of animation information and not the skeleton on which the
220 animation manipulates). Vdats have a list of models for every
221 animation that the vdats odat can do for that vdat*/
222 struct vdat {
223 struct odat* creator; //pointer to odat that made this vdat
224 int num_models;
225 struct model model_list[MAX_MODELS];
226 };
227
228 /* Called after the cdat open operator has been recognized in grammar. Allocates
229 the space for a cdat on the cdat_buf, pushes that pointer onto
230 the cdat_stack */
231 void
232 push_cdat(char*);
233
234 /* Called after a cdat end operator has been recognized in grammar. Sets
235 top stack cdat ** to null and decrements stack pointer */
236 void
237 pop_cdat(void);
238
239 /* Called after an odat has been populated. Allocates memory for
240 the next odat. */
241
242 void
243 insert_set_label(char*, uint64_t);
244
245 /* Populate the sets representation in CURR_CDAT with a ref_id and insert a link
246 into the link_buf that will resolve the ref_id to an actual odat after parse time. */
247 void
248 insert_set_olink(uint64_t);
249
250 /* Put the vlink in the link_buf to be processed after parsetime */
251 void
252 insert_set_vlink(uint64_t, char*);
253
254 /* Put svlink in the link_buf to be processed after parsetime */
255 void
256 insert_set_svlink(uint64_t);
257
258 /* Called for every set reduction except for sets with olinks. Populates the
259 set data structures in the CDAT and in the ODAT. Uses the name and ref_id
260 from insert_set_label. Also inserts a ref into the ref_buf with the CURR_ODAT
261 pointer so that we can also resolve the odat from its ref_id. */
262 void
263 insert_set(void);
264
265 /* Insertion of eles is practically equivalent to how sets are inserted because both
266 share the same data type (ODAT). Like sets, eles have links, labels
267 and odats. Eles have the added notion of a parent set, and so must be inserted
268 into said parent set, but this is the only place they truly differ from sets. */
269
270 void
271 insert_set_vdatid(void);
272
273 void
274 insert_ele_label(char*, uint64_t);
275
276 /* Insert an ele olink into the CURR_ODAT */
277 void
278 insert_ele_olink(uint64_t);
279
280 /* Insert a ele vlink into CURR_ODAT*/
281 void
282 insert_ele_vlink(uint64_t, char*);
283
284 /* Inserts an ele short vlink into CURR_ODAT*/
285 void
286 insert_ele_svlink(uint64_t);
287
288 /* inserts ele into CURR_CLASS and CURR_ODAT */
289 void
290 insert_ele(void);
291
292 void
293 insert_ele_vdatid(void);
294
295 /* Inserts the hitbox into the CURR_ODAT */
296 void
297 insert_hitbox(int);
298
299 /* Inserts the root into the CURR_ODAT */
300 void
301 insert_root(int, int, int);
302
303 /* Inserts a quad into the CURR_ODAT */
304 void
305 insert_quad(void*);
306
307 void
308 insert_model(void);
309
310 void
311 insert_framesheet(char, char*, uint64_t, int, int, int);
312
313 void
314 insert_frame_pointer(char, void*);
315
316 void
317 alloc_vdat(void);