fteqw/engine/qclib/pr_multi.c

423 lines
11 KiB
C

#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;
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 thier 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");
}