]> de.git.xonotic.org Git - voretournament/voretournament.git/blob - misc/source/fteqcc-src/pr_multi.c
Get VoreTournament code to compile with gmqcc. To be compiled with the same parameter...
[voretournament/voretournament.git] / misc / source / fteqcc-src / pr_multi.c
1 #define PROGSUSED
2 #include "progsint.h"
3
4 #define HunkAlloc BADGDFG sdfhhsf FHS
5
6 void PR_SetBuiltins(int type);
7 /*
8 progstate_t *pr_progstate;
9 progsnum_t pr_typecurrent;
10 int maxprogs;
11
12 progstate_t *current_progstate;
13 int numshares;
14
15 sharedvar_t *shares;    //shared globals, not including parms
16 int maxshares;
17 */
18
19 pbool PR_SwitchProgs(progfuncs_t *progfuncs, progsnum_t type)
20 {       
21         if ((unsigned)type >= maxprogs)
22         {
23                 if (type == -1)
24                 {
25                         pr_typecurrent = -1;
26                         current_progstate = NULL;
27                         return true;
28                 }
29                 PR_RunError(progfuncs, "QCLIB: Bad prog type - %i", type);
30 //              Sys_Error("Bad prog type - %i", type);
31         }
32
33         if (pr_progstate[(unsigned)type].progs == NULL) //we havn't loaded it yet, for some reason
34                 return false;   
35
36         current_progstate = &pr_progstate[(unsigned)type];
37
38         pr_typecurrent = type;
39
40         return true;
41 }
42
43 void PR_MoveParms(progfuncs_t *progfuncs, progsnum_t newpr, progsnum_t oldpr)   //from 2 to 1
44 {
45         unsigned int a;
46         progstate_t *np;
47         progstate_t *op;
48
49         if (newpr == oldpr)
50                 return; //don't bother coping variables to themselves...
51
52         np = &pr_progstate[(int)newpr];
53         op = &pr_progstate[(int)oldpr];
54
55         if ((unsigned)newpr >= maxprogs || !np->globals)
56                 PR_RunError(progfuncs, "QCLIB: Bad prog type - %i", newpr);
57         if ((unsigned)oldpr >= maxprogs || !op->globals)
58                 return;
59
60         //copy parms.
61         for (a = 0; a < MAX_PARMS;a++)
62         {
63                 *(int *)&np->globals[OFS_PARM0+3*a  ] = *(int *)&op->globals[OFS_PARM0+3*a  ];
64                 *(int *)&np->globals[OFS_PARM0+3*a+1] = *(int *)&op->globals[OFS_PARM0+3*a+1];
65                 *(int *)&np->globals[OFS_PARM0+3*a+2] = *(int *)&op->globals[OFS_PARM0+3*a+2];
66         }
67         np->globals[OFS_RETURN] = op->globals[OFS_RETURN];
68         np->globals[OFS_RETURN+1] = op->globals[OFS_RETURN+1];
69         np->globals[OFS_RETURN+2] = op->globals[OFS_RETURN+2];
70
71         //move the vars defined as shared.
72         for (a = 0; a < numshares; a++)//fixme: make offset per progs
73         {
74                 memmove(&((int *)np->globals)[shares[a].varofs], &((int *)op->globals)[shares[a].varofs], shares[a].size*4);
75 /*              ((int *)p1->globals)[shares[a].varofs] = ((int *)p2->globals)[shares[a].varofs];
76                 if (shares[a].size > 1)
77                 {
78                         ((int *)p1->globals)[shares[a].varofs+1] = ((int *)p2->globals)[shares[a].varofs+1];
79                         if (shares[a].size > 2)
80                                 ((int *)p1->globals)[shares[a].varofs+2] = ((int *)p2->globals)[shares[a].varofs+2];
81                 }
82 */
83         }
84 }
85
86 progsnum_t PR_LoadProgs(progfuncs_t *progfuncs, char *s, int headercrc, builtin_t *builtins, int numbuiltins)
87 {
88         unsigned int a;
89         progsnum_t oldtype;
90         oldtype = pr_typecurrent;       
91         for (a = 0; a < maxprogs; a++)
92         {
93                 if (pr_progstate[a].progs == NULL)
94                 {
95                         pr_typecurrent = a;
96                         current_progstate = &pr_progstate[a];
97                         if (PR_ReallyLoadProgs(progfuncs, s, headercrc, &pr_progstate[a], false))       //try and load it                       
98                         {
99                                 current_progstate->builtins = builtins;
100                                 current_progstate->numbuiltins = numbuiltins;
101                                 if (a <= progfuncs->numprogs)
102                                         progfuncs->numprogs = a+1;
103
104 #ifdef QCJIT
105                                 current_progstate->jit = PR_GenerateJit(progfuncs);
106 #endif
107                                 if (oldtype != -1)
108                                         PR_SwitchProgs(progfuncs, oldtype);
109                                 return a;       //we could load it. Yay!
110                         }
111                         PR_SwitchProgs(progfuncs, oldtype);
112                         return -1; // loading failed.
113                 }
114         }
115         PR_SwitchProgs(progfuncs, oldtype);
116         return -1;
117 }
118
119 void PR_ShiftParms(progfuncs_t *progfuncs, int amount)
120 {
121         int a;
122         for (a = 0; a < MAX_PARMS - amount;a++)
123                 *(int *)&pr_globals[OFS_PARM0+3*a] = *(int *)&pr_globals[OFS_PARM0+3*(amount+a)];
124 }
125
126 //forget a progs
127 void PR_Clear(progfuncs_t *progfuncs)
128 {
129         unsigned int a;
130         for (a = 0; a < maxprogs; a++)
131         {
132 #ifdef QCJIT
133                 if (pr_progstate[a].jit)
134                         PR_CloseJit(pr_progstate[a].jit);
135 #endif
136                 pr_progstate[a].progs = NULL;
137         }
138 }
139
140
141
142 void QC_StartShares(progfuncs_t *progfuncs)
143 {
144         numshares = 0;
145         maxshares = 32;
146         if (shares)
147                 memfree(shares);
148         shares = memalloc(sizeof(sharedvar_t)*maxshares);
149 }
150 void QC_AddSharedVar(progfuncs_t *progfuncs, int start, int size)       //fixme: make offset per progs and optional
151 {
152         int ofs;
153         unsigned int a;
154
155         if (numshares >= maxshares)
156         {
157                 void *buf;
158                 buf = shares;
159                 maxshares += 16;                
160                 shares = memalloc(sizeof(sharedvar_t)*maxshares);
161
162                 memcpy(shares, buf, sizeof(sharedvar_t)*numshares);
163
164                 memfree(buf);
165         }
166         ofs = start;
167         for (a = 0; a < numshares; a++)
168         {
169                 if (shares[a].varofs+shares[a].size == ofs)
170                 {
171                         shares[a].size += size; //expand size.
172                         return;
173                 }
174                 if (shares[a].varofs == start)
175                         return;
176         }
177
178
179         shares[numshares].varofs = start;
180         shares[numshares].size = size;
181         numshares++;
182 }
183
184
185 //void ShowWatch(void);
186
187 void QC_InitShares(progfuncs_t *progfuncs)
188 {
189 //      ShowWatch();
190         if (!field)     //don't make it so we will just need to remalloc everything
191         {
192                 maxfields = 64;
193                 field = memalloc(sizeof(fdef_t) * maxfields);
194         }
195
196         numfields = 0;
197         progfuncs->fieldadjust = 0;
198 }
199
200 void QC_FlushProgsOffsets(progfuncs_t *progfuncs)
201 {       //sets the fields up for loading a new progs.
202         //fields are matched by name to other progs
203         //not by offset
204         unsigned int i;
205         for (i = 0; i < numfields; i++)
206                 field[i].progsofs = -1;
207 }
208
209
210 //called if a global is defined as a field
211 //returns offset.
212
213 //vectors must be added before any of their corresponding _x/y/z vars
214 //in this way, even screwed up progs work.
215
216 //requestedpos is the offset the engine WILL put it at.
217 //origionaloffs is used to track matching field offsets. fields with the same progs offset overlap
218
219 //note: we probably suffer from progs with renamed system globals.
220 int QC_RegisterFieldVar(progfuncs_t *progfuncs, unsigned int type, char *name, signed long engineofs, signed long progsofs)
221 {
222 //      progstate_t *p;
223 //      int pnum;
224         unsigned int i;
225         int namelen;
226         int ofs;
227
228         int fnum;
229
230         if (!name)      //engine can use this to offset all progs fields
231         {                       //which fixes constant field offsets (some ktpro arrays)
232                 progfuncs->fieldadjust = fields_size/4;
233                 return 0;
234         }
235
236
237         prinst->reorganisefields = true;
238
239         //look for an existing match
240         for (i = 0; i < numfields; i++)
241         {               
242                 if (!strcmp(name, field[i].name))
243                 {
244                         if (field[i].type != type)
245                         {
246                                 /*Hexen2/DP compat hack: if the new type is a float and the original type is a vector, make the new def alias to the engine's _x field
247                                 this 'works around' the unused .vector color field used for rtlight colours vs the .float color used for particle colours (the float initialisers in map files will expand into the x slot safely).
248                                 qc/hc can work around this by just using .vector color/color_x instead, which is the same as this hack, but would resolve defs to allow rtlight colours.
249                                 */
250                                 if (field[i].type != ev_vector || type != ev_float)
251                                 {
252                                         printf("Field type mismatch on \"%s\". %i != %i\n", name, field[i].type, type);
253                                         continue;
254                                 }
255                         }
256                         if (!progfuncs->fieldadjust && engineofs>=0)
257                                 if ((unsigned)engineofs/4 != field[i].ofs)
258                                         Sys_Error("Field %s at wrong offset", name);
259
260                         if (field[i].progsofs == -1)
261                                 field[i].progsofs = progsofs;
262 //                      printf("Dupfield %s %i -> %i\n", name, field[i].progsofs,field[i].ofs);
263                         return field[i].ofs-progfuncs->fieldadjust;     //got a match
264                 }
265         }
266
267         if (numfields+1>maxfields)
268         {
269                 fdef_t *nf;
270                 i = maxfields;
271                 maxfields += 32;
272                 nf = memalloc(sizeof(fdef_t) * maxfields);
273                 memcpy(nf, field, sizeof(fdef_t) * i);
274                 memfree(field);
275                 field = nf;
276         }
277
278         //try to add a new one
279         fnum = numfields;
280         numfields++;
281         field[fnum].name = name;        
282         if (type == ev_vector)
283         {
284                 char *n;                
285                 namelen = strlen(name)+5;       
286
287                 n=PRHunkAlloc(progfuncs, namelen);
288                 sprintf(n, "%s_x", name);
289                 ofs = QC_RegisterFieldVar(progfuncs, ev_float, n, engineofs, progsofs);
290                 field[fnum].ofs = ofs+progfuncs->fieldadjust;
291
292                 n=PRHunkAlloc(progfuncs, namelen);
293                 sprintf(n, "%s_y", name);
294                 QC_RegisterFieldVar(progfuncs, ev_float, n, (engineofs==-1)?-1:(engineofs+4), (progsofs==-1)?-1:progsofs+1);
295
296                 n=PRHunkAlloc(progfuncs, namelen);
297                 sprintf(n, "%s_z", name);
298                 QC_RegisterFieldVar(progfuncs, ev_float, n, (engineofs==-1)?-1:(engineofs+8), (progsofs==-1)?-1:progsofs+2);
299         }
300         else if (engineofs >= 0)
301         {       //the engine is setting up a list of required field indexes.
302
303                 //paranoid checking of the offset.
304         /*      for (i = 0; i < numfields-1; i++)
305                 {
306                         if (field[i].ofs == ((unsigned)engineofs)/4)
307                         {
308                                 if (type == ev_float && field[i].type == ev_vector)     //check names
309                                 {
310                                         if (strncmp(field[i].name, name, strlen(field[i].name)))
311                                                 Sys_Error("Duplicated offset");
312                                 }
313                                 else
314                                         Sys_Error("Duplicated offset");
315                         }
316                 }*/
317                 if (engineofs&3)
318                         Sys_Error("field %s is %i&3", name, (int)engineofs);
319                 field[fnum].ofs = ofs = engineofs/4;
320         }
321         else
322         {       //we just found a new fieldname inside a progs
323                 field[fnum].ofs = ofs = fields_size/4;  //add on the end
324
325                 //if the progs field offset matches annother offset in the same progs, make it match up with the earlier one.
326                 if (progsofs>=0)
327                 {
328                         for (i = 0; i < numfields-1; i++)
329                         {
330                                 if (field[i].progsofs == (unsigned)progsofs)
331                                 {
332 //                                      printf("found union field %s %i -> %i\n", field[i].name, field[i].progsofs, field[i].ofs);
333                                         field[fnum].ofs = ofs = field[i].ofs;
334                                         break;
335                                 }
336                         }
337                 }
338         }
339 //      if (type != ev_vector)
340                 if (fields_size < (ofs+type_size[type])*4)
341                         fields_size = (ofs+type_size[type])*4;
342
343         if (max_fields_size && fields_size > max_fields_size)
344                 Sys_Error("Allocated too many additional fields after ents were inited.");
345         field[fnum].type = type;
346
347         field[fnum].progsofs = progsofs;
348
349 //      printf("Field %s %i -> %i\n", name, field[fnum].progsofs,field[fnum].ofs);
350         
351         //we've finished setting the structure  
352         return ofs - progfuncs->fieldadjust;
353 }
354
355
356 //called if a global is defined as a field
357 void QC_AddSharedFieldVar(progfuncs_t *progfuncs, int num, char *stringtable)
358 {
359 //      progstate_t *p;
360 //      int pnum;
361         unsigned int i, o;
362
363         char *s;
364
365         //look for an existing match not needed, cos we look a little later too.
366         /*
367         for (i = 0; i < numfields; i++)
368         {               
369                 if (!strcmp(pr_globaldefs[num].s_name, field[i].s_name))
370                 {
371                         //really we should look for a field def
372
373                         *(int *)&pr_globals[pr_globaldefs[num].ofs] = field[i].ofs;     //got a match
374
375                         return;
376                 }
377         }
378         */
379         
380         switch(current_progstate->structtype)
381         {
382         case PST_KKQWSV:
383         case PST_DEFAULT:
384                 for (i=1 ; i<pr_progs->numfielddefs; i++)
385                 {
386                         if (!strcmp(pr_fielddefs16[i].s_name+stringtable, pr_globaldefs16[num].s_name+stringtable))
387                         {
388 //                              int old = *(int *)&pr_globals[pr_globaldefs16[num].ofs];
389                                 *(int *)&pr_globals[pr_globaldefs16[num].ofs] = QC_RegisterFieldVar(progfuncs, pr_fielddefs16[i].type, pr_globaldefs16[num].s_name+stringtable, -1, *(int *)&pr_globals[pr_globaldefs16[num].ofs]);
390
391 //                              printf("Field %s %i -> %i\n", pr_globaldefs16[num].s_name+stringtable, old, *(int *)&pr_globals[pr_globaldefs16[num].ofs]);
392                                 return;
393                         }
394                 }
395
396                 s = pr_globaldefs16[num].s_name+stringtable;
397
398                 for (i = 0; i < numfields; i++)
399                 {
400                         o = field[i].progsofs;
401                         if (o == *(unsigned int *)&pr_globals[pr_globaldefs16[num].ofs])
402                         {
403 //                              int old = *(int *)&pr_globals[pr_globaldefs16[num].ofs];
404                                 *(int *)&pr_globals[pr_globaldefs16[num].ofs] = field[i].ofs-progfuncs->fieldadjust;
405 //                              printf("Field %s %i -> %i\n", pr_globaldefs16[num].s_name+stringtable, old, *(int *)&pr_globals[pr_globaldefs16[num].ofs]);
406                                 return;
407                         }
408                 }
409
410                 //oh well, must be a parameter.
411 //              if (*(int *)&pr_globals[pr_globaldefs16[num].ofs])
412 //                      Sys_Error("QCLIB: Global field var with no matching field \"%s\", from offset %i", pr_globaldefs16[num].s_name+stringtable, *(int *)&pr_globals[pr_globaldefs16[num].ofs]);
413                 return;
414         case PST_FTE32:
415         case PST_QTEST:
416                 for (i=1 ; i<pr_progs->numfielddefs; i++)
417                 {
418                         if (!strcmp(pr_fielddefs32[i].s_name+stringtable, pr_globaldefs32[num].s_name+stringtable))
419                         {
420                                 *(int *)&pr_globals[pr_globaldefs32[num].ofs] = QC_RegisterFieldVar(progfuncs, pr_fielddefs32[i].type, pr_globaldefs32[num].s_name+stringtable, -1, *(int *)&pr_globals[pr_globaldefs32[num].ofs]);
421                                 return;
422                         }
423                 }
424
425                 s = pr_globaldefs32[num].s_name+stringtable;
426
427                 for (i = 0; i < numfields; i++)
428                 {
429                         o = field[i].progsofs;
430                         if (o == *(unsigned int *)&pr_globals[pr_globaldefs32[num].ofs])
431                         {
432                                 *(int *)&pr_globals[pr_globaldefs32[num].ofs] = field[i].ofs-progfuncs->fieldadjust;
433                                 return;
434                         }
435                 }
436
437                 //oh well, must be a parameter.
438                 if (*(int *)&pr_globals[pr_globaldefs32[num].ofs])
439                         Sys_Error("QCLIB: Global field var with no matching field \"%s\", from offset %i", pr_globaldefs32[num].s_name+stringtable, *(int *)&pr_globals[pr_globaldefs32[num].ofs]);
440                 return;
441         default:
442                 Sys_Error("Bad bits");
443                 break;
444         }
445         Sys_Error("Should be unreachable");     
446 }
447