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