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