--- /dev/null
+#define PROGSUSED
+#include "progsint.h"
+
+#define HunkAlloc BADGDFG sdfhhsf FHS
+
+void PR_SetBuiltins(int type);
+/*
+progstate_t *pr_progstate;
+progsnum_t pr_typecurrent;
+int maxprogs;
+
+progstate_t *current_progstate;
+int numshares;
+
+sharedvar_t *shares; //shared globals, not including parms
+int maxshares;
+*/
+
+pbool PR_SwitchProgs(progfuncs_t *progfuncs, progsnum_t type)
+{
+ if ((unsigned)type >= maxprogs)
+ PR_RunError(progfuncs, "QCLIB: Bad prog type - %i", type);
+// Sys_Error("Bad prog type - %i", type);
+
+ if (pr_progstate[(unsigned)type].progs == NULL) //we havn't loaded it yet, for some reason
+ return false;
+
+ current_progstate = &pr_progstate[(unsigned)type];
+
+ pr_typecurrent = type;
+
+ return true;
+}
+
+void PR_MoveParms(progfuncs_t *progfuncs, progsnum_t progs1, progsnum_t progs2) //from 2 to 1
+{
+ unsigned int a;
+ progstate_t *p1;
+ progstate_t *p2;
+
+ if (progs1 == progs2)
+ return; //don't bother coping variables to themselves...
+
+ p1 = &pr_progstate[(int)progs1];
+ p2 = &pr_progstate[(int)progs2];
+
+ if ((unsigned)progs1 >= maxprogs || !p1->globals)
+ Sys_Error("QCLIB: Bad prog type - %i", progs1);
+ if ((unsigned)progs2 >= maxprogs || !p2->globals)
+ Sys_Error("QCLIB: Bad prog type - %i", progs2);
+
+ //copy parms.
+ for (a = 0; a < MAX_PARMS;a++)
+ {
+ *(int *)&p1->globals[OFS_PARM0+3*a ] = *(int *)&p2->globals[OFS_PARM0+3*a ];
+ *(int *)&p1->globals[OFS_PARM0+3*a+1] = *(int *)&p2->globals[OFS_PARM0+3*a+1];
+ *(int *)&p1->globals[OFS_PARM0+3*a+2] = *(int *)&p2->globals[OFS_PARM0+3*a+2];
+ }
+ p1->globals[OFS_RETURN] = p2->globals[OFS_RETURN];
+ p1->globals[OFS_RETURN+1] = p2->globals[OFS_RETURN+1];
+ p1->globals[OFS_RETURN+2] = p2->globals[OFS_RETURN+2];
+
+ //move the vars defined as shared.
+ for (a = 0; a < numshares; a++)//fixme: make offset per progs
+ {
+ memmove(&((int *)p1->globals)[shares[a].varofs], &((int *)p2->globals)[shares[a].varofs], shares[a].size*4);
+/* ((int *)p1->globals)[shares[a].varofs] = ((int *)p2->globals)[shares[a].varofs];
+ if (shares[a].size > 1)
+ {
+ ((int *)p1->globals)[shares[a].varofs+1] = ((int *)p2->globals)[shares[a].varofs+1];
+ if (shares[a].size > 2)
+ ((int *)p1->globals)[shares[a].varofs+2] = ((int *)p2->globals)[shares[a].varofs+2];
+ }
+*/
+ }
+}
+
+progsnum_t PR_LoadProgs(progfuncs_t *progfuncs, char *s, int headercrc, builtin_t *builtins, int numbuiltins)
+{
+ unsigned int a;
+ progsnum_t oldtype;
+ oldtype = pr_typecurrent;
+ for (a = 0; a < maxprogs; a++)
+ {
+ if (pr_progstate[a].progs == NULL)
+ {
+ pr_typecurrent = a;
+ current_progstate = &pr_progstate[a];
+ if (PR_ReallyLoadProgs(progfuncs, s, headercrc, &pr_progstate[a], false)) //try and load it
+ {
+ current_progstate->builtins = builtins;
+ current_progstate->numbuiltins = numbuiltins;
+
+#ifdef QCJIT
+ if (prinst->usejit)
+ prinst->usejit = PR_GenerateJit(progfuncs);
+#endif
+ if (oldtype>=0)
+ PR_SwitchProgs(progfuncs, oldtype);
+ return a; //we could load it. Yay!
+ }
+ if (oldtype!=-1)
+ PR_SwitchProgs(progfuncs, oldtype);
+ return -1; // loading failed.
+ }
+ }
+ PR_SwitchProgs(progfuncs, oldtype);
+ return -1;
+}
+
+void PR_ShiftParms(progfuncs_t *progfuncs, int amount)
+{
+ int a;
+ for (a = 0; a < MAX_PARMS - amount;a++)
+ *(int *)&pr_globals[OFS_PARM0+3*a] = *(int *)&pr_globals[OFS_PARM0+3*(amount+a)];
+}
+
+//forget a progs
+void PR_Clear(progfuncs_t *progfuncs)
+{
+ unsigned int a;
+ for (a = 0; a < maxprogs; a++)
+ {
+ pr_progstate[a].progs = NULL;
+ }
+}
+
+
+
+void QC_StartShares(progfuncs_t *progfuncs)
+{
+ numshares = 0;
+ maxshares = 32;
+ if (shares)
+ memfree(shares);
+ shares = memalloc(sizeof(sharedvar_t)*maxshares);
+}
+void QC_AddSharedVar(progfuncs_t *progfuncs, int start, int size) //fixme: make offset per progs and optional
+{
+ int ofs;
+ unsigned int a;
+
+ if (numshares >= maxshares)
+ {
+ void *buf;
+ buf = shares;
+ maxshares += 16;
+ shares = memalloc(sizeof(sharedvar_t)*maxshares);
+
+ memcpy(shares, buf, sizeof(sharedvar_t)*numshares);
+
+ memfree(buf);
+ }
+ ofs = start;
+ for (a = 0; a < numshares; a++)
+ {
+ if (shares[a].varofs+shares[a].size == ofs)
+ {
+ shares[a].size += size; //expand size.
+ return;
+ }
+ if (shares[a].varofs == start)
+ return;
+ }
+
+
+ shares[numshares].varofs = start;
+ shares[numshares].size = size;
+ numshares++;
+}
+
+
+//void ShowWatch(void);
+
+void QC_InitShares(progfuncs_t *progfuncs)
+{
+// ShowWatch();
+ if (!field) //don't make it so we will just need to remalloc everything
+ {
+ maxfields = 64;
+ field = memalloc(sizeof(fdef_t) * maxfields);
+ }
+
+ numfields = 0;
+ progfuncs->fieldadjust = 0;
+}
+
+void QC_FlushProgsOffsets(progfuncs_t *progfuncs)
+{ //sets the fields up for loading a new progs.
+ //fields are matched by name to other progs
+ //not by offset
+ unsigned int i;
+ for (i = 0; i < numfields; i++)
+ field[i].progsofs = -1;
+}
+
+
+//called if a global is defined as a field
+//returns offset.
+
+//vectors must be added before any of their corresponding _x/y/z vars
+//in this way, even screwed up progs work.
+
+//requestedpos is the offset the engine WILL put it at.
+//origionaloffs is used to track matching field offsets. fields with the same progs offset overlap
+
+//note: we probably suffer from progs with renamed system globals.
+int QC_RegisterFieldVar(progfuncs_t *progfuncs, unsigned int type, char *name, int engineofs, int progsofs)
+{
+// progstate_t *p;
+// int pnum;
+ unsigned int i;
+ int namelen;
+ int ofs;
+
+ int fnum;
+
+ if (!name) //engine can use this to offset all progs fields
+ { //which fixes constant field offsets (some ktpro arrays)
+ progfuncs->fieldadjust = fields_size/4;
+ return 0;
+ }
+
+
+ prinst->reorganisefields = true;
+
+ //look for an existing match
+ for (i = 0; i < numfields; i++)
+ {
+ if (!strcmp(name, field[i].name))
+ {
+ if (field[i].type != type)
+ {
+ printf("Field type mismatch on \"%s\"\n", name);
+ continue;
+ }
+ if (!progfuncs->fieldadjust && engineofs>=0)
+ if ((unsigned)engineofs/4 != field[i].ofs)
+ Sys_Error("Field %s at wrong offset", name);
+
+ if (field[i].progsofs == -1)
+ field[i].progsofs = progsofs;
+// printf("Dupfield %s %i -> %i\n", name, field[i].progsofs,field[i].ofs);
+ return field[i].ofs-progfuncs->fieldadjust; //got a match
+ }
+ }
+
+ if (numfields+1>maxfields)
+ {
+ fdef_t *nf;
+ i = maxfields;
+ maxfields += 32;
+ nf = memalloc(sizeof(fdef_t) * maxfields);
+ memcpy(nf, field, sizeof(fdef_t) * i);
+ memfree(field);
+ field = nf;
+ }
+
+ //try to add a new one
+ fnum = numfields;
+ numfields++;
+ field[fnum].name = name;
+ if (type == ev_vector)
+ {
+ char *n;
+ namelen = strlen(name)+5;
+
+ n=PRHunkAlloc(progfuncs, namelen);
+ sprintf(n, "%s_x", name);
+ ofs = QC_RegisterFieldVar(progfuncs, ev_float, n, engineofs, progsofs);
+ field[fnum].ofs = ofs+progfuncs->fieldadjust;
+
+ n=PRHunkAlloc(progfuncs, namelen);
+ sprintf(n, "%s_y", name);
+ QC_RegisterFieldVar(progfuncs, ev_float, n, (engineofs==-1)?-1:(engineofs+4), (progsofs==-1)?-1:progsofs+1);
+
+ n=PRHunkAlloc(progfuncs, namelen);
+ sprintf(n, "%s_z", name);
+ QC_RegisterFieldVar(progfuncs, ev_float, n, (engineofs==-1)?-1:(engineofs+8), (progsofs==-1)?-1:progsofs+2);
+ }
+ else if (engineofs >= 0)
+ { //the engine is setting up a list of required field indexes.
+
+ //paranoid checking of the offset.
+ /* for (i = 0; i < numfields-1; i++)
+ {
+ if (field[i].ofs == ((unsigned)engineofs)/4)
+ {
+ if (type == ev_float && field[i].type == ev_vector) //check names
+ {
+ if (strncmp(field[i].name, name, strlen(field[i].name)))
+ Sys_Error("Duplicated offset");
+ }
+ else
+ Sys_Error("Duplicated offset");
+ }
+ }*/
+ if (engineofs&3)
+ Sys_Error("field %s is %i&3", name, engineofs);
+ field[fnum].ofs = ofs = engineofs/4;
+ }
+ else
+ { //we just found a new fieldname inside a progs
+ field[fnum].ofs = ofs = fields_size/4; //add on the end
+
+ //if the progs field offset matches annother offset in the same progs, make it match up with the earlier one.
+ if (progsofs>=0)
+ {
+ for (i = 0; i < numfields-1; i++)
+ {
+ if (field[i].progsofs == (unsigned)progsofs)
+ {
+// printf("found union field %s %i -> %i\n", field[i].name, field[i].progsofs, field[i].ofs);
+ field[fnum].ofs = ofs = field[i].ofs;
+ break;
+ }
+ }
+ }
+ }
+// if (type != ev_vector)
+ if (fields_size < (ofs+type_size[type])*4)
+ fields_size = (ofs+type_size[type])*4;
+
+ if (max_fields_size && fields_size > max_fields_size)
+ Sys_Error("Allocated too many additional fields after ents were inited.");
+ field[fnum].type = type;
+
+ field[fnum].progsofs = progsofs;
+
+// printf("Field %s %i -> %i\n", name, field[fnum].progsofs,field[fnum].ofs);
+
+ //we've finished setting the structure
+ return ofs - progfuncs->fieldadjust;
+}
+
+
+//called if a global is defined as a field
+void QC_AddSharedFieldVar(progfuncs_t *progfuncs, int num, char *stringtable)
+{
+// progstate_t *p;
+// int pnum;
+ unsigned int i, o;
+
+ char *s;
+
+ //look for an existing match not needed, cos we look a little later too.
+ /*
+ for (i = 0; i < numfields; i++)
+ {
+ if (!strcmp(pr_globaldefs[num].s_name, field[i].s_name))
+ {
+ //really we should look for a field def
+
+ *(int *)&pr_globals[pr_globaldefs[num].ofs] = field[i].ofs; //got a match
+
+ return;
+ }
+ }
+ */
+
+ switch(current_progstate->intsize)
+ {
+ case 24:
+ case 16:
+ for (i=1 ; i<pr_progs->numfielddefs; i++)
+ {
+ if (!strcmp(pr_fielddefs16[i].s_name+stringtable, pr_globaldefs16[num].s_name+stringtable))
+ {
+// int old = *(int *)&pr_globals[pr_globaldefs16[num].ofs];
+ *(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]);
+
+// printf("Field %s %i -> %i\n", pr_globaldefs16[num].s_name+stringtable, old, *(int *)&pr_globals[pr_globaldefs16[num].ofs]);
+ return;
+ }
+ }
+
+ s = pr_globaldefs16[num].s_name+stringtable;
+
+ for (i = 0; i < numfields; i++)
+ {
+ o = field[i].progsofs;
+ if (o == *(unsigned int *)&pr_globals[pr_globaldefs16[num].ofs])
+ {
+// int old = *(int *)&pr_globals[pr_globaldefs16[num].ofs];
+ *(int *)&pr_globals[pr_globaldefs16[num].ofs] = field[i].ofs-progfuncs->fieldadjust;
+// printf("Field %s %i -> %i\n", pr_globaldefs16[num].s_name+stringtable, old, *(int *)&pr_globals[pr_globaldefs16[num].ofs]);
+ return;
+ }
+ }
+
+ //oh well, must be a parameter.
+// if (*(int *)&pr_globals[pr_globaldefs16[num].ofs])
+// 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]);
+ return;
+ case 32:
+ for (i=1 ; i<pr_progs->numfielddefs; i++)
+ {
+ if (!strcmp(pr_fielddefs32[i].s_name+stringtable, pr_globaldefs32[num].s_name+stringtable))
+ {
+ *(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]);
+ return;
+ }
+ }
+
+ s = pr_globaldefs32[num].s_name+stringtable;
+
+ for (i = 0; i < numfields; i++)
+ {
+ o = field[i].progsofs;
+ if (o == *(unsigned int *)&pr_globals[pr_globaldefs32[num].ofs])
+ {
+ *(int *)&pr_globals[pr_globaldefs32[num].ofs] = field[i].ofs-progfuncs->fieldadjust;
+ return;
+ }
+ }
+
+ //oh well, must be a parameter.
+ if (*(int *)&pr_globals[pr_globaldefs32[num].ofs])
+ 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]);
+ return;
+ default:
+ Sys_Error("Bad bits");
+ break;
+ }
+ Sys_Error("Should be unreachable");
+}
+