4 #define HunkAlloc BADGDFG sdfhhsf FHS
6 void PR_SetBuiltins(int type);
8 progstate_t *pr_progstate;
9 progsnum_t pr_typecurrent;
12 progstate_t *current_progstate;
15 sharedvar_t *shares; //shared globals, not including parms
19 pbool PR_SwitchProgs(progfuncs_t *progfuncs, progsnum_t type)
21 if ((unsigned)type >= maxprogs)
26 current_progstate = NULL;
29 PR_RunError(progfuncs, "QCLIB: Bad prog type - %i", type);
30 // Sys_Error("Bad prog type - %i", type);
33 if (pr_progstate[(unsigned)type].progs == NULL) //we havn't loaded it yet, for some reason
36 current_progstate = &pr_progstate[(unsigned)type];
38 pr_typecurrent = type;
43 void PR_MoveParms(progfuncs_t *progfuncs, progsnum_t newpr, progsnum_t oldpr) //from 2 to 1
50 return; //don't bother coping variables to themselves...
52 np = &pr_progstate[(int)newpr];
53 op = &pr_progstate[(int)oldpr];
55 if ((unsigned)newpr >= maxprogs || !np->globals)
56 PR_RunError(progfuncs, "QCLIB: Bad prog type - %i", newpr);
57 if ((unsigned)oldpr >= maxprogs || !op->globals)
61 for (a = 0; a < MAX_PARMS;a++)
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];
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];
71 //move the vars defined as shared.
72 for (a = 0; a < numshares; a++)//fixme: make offset per progs
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)
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];
86 progsnum_t PR_LoadProgs(progfuncs_t *progfuncs, char *s, int headercrc, builtin_t *builtins, int numbuiltins)
90 oldtype = pr_typecurrent;
91 for (a = 0; a < maxprogs; a++)
93 if (pr_progstate[a].progs == NULL)
96 current_progstate = &pr_progstate[a];
97 if (PR_ReallyLoadProgs(progfuncs, s, headercrc, &pr_progstate[a], false)) //try and load it
99 current_progstate->builtins = builtins;
100 current_progstate->numbuiltins = numbuiltins;
101 if (a <= progfuncs->numprogs)
102 progfuncs->numprogs = a+1;
105 current_progstate->jit = PR_GenerateJit(progfuncs);
108 PR_SwitchProgs(progfuncs, oldtype);
109 return a; //we could load it. Yay!
111 PR_SwitchProgs(progfuncs, oldtype);
112 return -1; // loading failed.
115 PR_SwitchProgs(progfuncs, oldtype);
119 void PR_ShiftParms(progfuncs_t *progfuncs, int amount)
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)];
127 void PR_Clear(progfuncs_t *progfuncs)
130 for (a = 0; a < maxprogs; a++)
133 if (pr_progstate[a].jit)
134 PR_CloseJit(pr_progstate[a].jit);
136 pr_progstate[a].progs = NULL;
142 void QC_StartShares(progfuncs_t *progfuncs)
148 shares = memalloc(sizeof(sharedvar_t)*maxshares);
150 void QC_AddSharedVar(progfuncs_t *progfuncs, int start, int size) //fixme: make offset per progs and optional
155 if (numshares >= maxshares)
160 shares = memalloc(sizeof(sharedvar_t)*maxshares);
162 memcpy(shares, buf, sizeof(sharedvar_t)*numshares);
167 for (a = 0; a < numshares; a++)
169 if (shares[a].varofs+shares[a].size == ofs)
171 shares[a].size += size; //expand size.
174 if (shares[a].varofs == start)
179 shares[numshares].varofs = start;
180 shares[numshares].size = size;
185 //void ShowWatch(void);
187 void QC_InitShares(progfuncs_t *progfuncs)
190 if (!field) //don't make it so we will just need to remalloc everything
193 field = memalloc(sizeof(fdef_t) * maxfields);
197 progfuncs->fieldadjust = 0;
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
205 for (i = 0; i < numfields; i++)
206 field[i].progsofs = -1;
210 //called if a global is defined as a field
213 //vectors must be added before any of their corresponding _x/y/z vars
214 //in this way, even screwed up progs work.
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
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)
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;
237 prinst->reorganisefields = true;
239 //look for an existing match
240 for (i = 0; i < numfields; i++)
242 if (!strcmp(name, field[i].name))
244 if (field[i].type != type)
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.
250 if (field[i].type != ev_vector || type != ev_float)
252 printf("Field type mismatch on \"%s\". %i != %i\n", name, field[i].type, type);
256 if (!progfuncs->fieldadjust && engineofs>=0)
257 if ((unsigned)engineofs/4 != field[i].ofs)
258 Sys_Error("Field %s at wrong offset", name);
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
267 if (numfields+1>maxfields)
272 nf = memalloc(sizeof(fdef_t) * maxfields);
273 memcpy(nf, field, sizeof(fdef_t) * i);
278 //try to add a new one
281 field[fnum].name = name;
282 if (type == ev_vector)
285 namelen = strlen(name)+5;
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;
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);
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);
300 else if (engineofs >= 0)
301 { //the engine is setting up a list of required field indexes.
303 //paranoid checking of the offset.
304 /* for (i = 0; i < numfields-1; i++)
306 if (field[i].ofs == ((unsigned)engineofs)/4)
308 if (type == ev_float && field[i].type == ev_vector) //check names
310 if (strncmp(field[i].name, name, strlen(field[i].name)))
311 Sys_Error("Duplicated offset");
314 Sys_Error("Duplicated offset");
318 Sys_Error("field %s is %i&3", name, (int)engineofs);
319 field[fnum].ofs = ofs = engineofs/4;
322 { //we just found a new fieldname inside a progs
323 field[fnum].ofs = ofs = fields_size/4; //add on the end
325 //if the progs field offset matches annother offset in the same progs, make it match up with the earlier one.
328 for (i = 0; i < numfields-1; i++)
330 if (field[i].progsofs == (unsigned)progsofs)
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;
339 // if (type != ev_vector)
340 if (fields_size < (ofs+type_size[type])*4)
341 fields_size = (ofs+type_size[type])*4;
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;
347 field[fnum].progsofs = progsofs;
349 // printf("Field %s %i -> %i\n", name, field[fnum].progsofs,field[fnum].ofs);
351 //we've finished setting the structure
352 return ofs - progfuncs->fieldadjust;
356 //called if a global is defined as a field
357 void QC_AddSharedFieldVar(progfuncs_t *progfuncs, int num, char *stringtable)
365 //look for an existing match not needed, cos we look a little later too.
367 for (i = 0; i < numfields; i++)
369 if (!strcmp(pr_globaldefs[num].s_name, field[i].s_name))
371 //really we should look for a field def
373 *(int *)&pr_globals[pr_globaldefs[num].ofs] = field[i].ofs; //got a match
380 switch(current_progstate->structtype)
384 for (i=1 ; i<pr_progs->numfielddefs; i++)
386 if (!strcmp(pr_fielddefs16[i].s_name+stringtable, pr_globaldefs16[num].s_name+stringtable))
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]);
391 // printf("Field %s %i -> %i\n", pr_globaldefs16[num].s_name+stringtable, old, *(int *)&pr_globals[pr_globaldefs16[num].ofs]);
396 s = pr_globaldefs16[num].s_name+stringtable;
398 for (i = 0; i < numfields; i++)
400 o = field[i].progsofs;
401 if (o == *(unsigned int *)&pr_globals[pr_globaldefs16[num].ofs])
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]);
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]);
416 for (i=1 ; i<pr_progs->numfielddefs; i++)
418 if (!strcmp(pr_fielddefs32[i].s_name+stringtable, pr_globaldefs32[num].s_name+stringtable))
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]);
425 s = pr_globaldefs32[num].s_name+stringtable;
427 for (i = 0; i < numfields; i++)
429 o = field[i].progsofs;
430 if (o == *(unsigned int *)&pr_globals[pr_globaldefs32[num].ofs])
432 *(int *)&pr_globals[pr_globaldefs32[num].ofs] = field[i].ofs-progfuncs->fieldadjust;
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]);
442 Sys_Error("Bad bits");
445 Sys_Error("Should be unreachable");