#error Bad cont size
#endif
+#ifdef DEBUGABLE
+#define OPCODE (st->op & ~0x8000)
+#else
+#define OPCODE (st->op)
+#endif
+
#define ENGINEPOINTER(p) ((char*)(p) - progfuncs->stringtable)
#define QCPOINTER(p) (eval_t *)(p->_int+progfuncs->stringtable)
#define QCPOINTERM(p) (eval_t *)((p)+progfuncs->stringtable)
st = pr_statements + s;
reeval:
- switch (st->op & ~0x8000)
#else
st++;
- switch (st->op)
#endif
+ switch (OPCODE)
{
case OP_ADD_F:
OPC->_float = OPA->_float + OPB->_float;
if ((unsigned int)OPB->_int >= addressableused)
{
pr_xstatement = st-pr_statements;
- PR_RunError (progfuncs, "bad pointer write in %s", progfuncs->stringtable + pr_xfunction->s_name);
+ PR_RunError (progfuncs, "bad pointer write in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name));
}
ptr = QCPOINTER(OPB);
ptr->_float = (float)OPA->_int;
if ((unsigned int)OPB->_int >= addressableused)
{
pr_xstatement = st-pr_statements;
- PR_RunError (progfuncs, "bad pointer write in %s", progfuncs->stringtable + pr_xfunction->s_name);
+ PR_RunError (progfuncs, "bad pointer write in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name));
}
ptr = QCPOINTER(OPB);
ptr->_int = (int)OPA->_float;
break;
case OP_STOREP_I:
+ case OP_GSTOREP_I:
if ((unsigned int)OPB->_int >= addressableused)
{
pr_xstatement = st-pr_statements;
- PR_RunError (progfuncs, "bad pointer write in %s", progfuncs->stringtable + pr_xfunction->s_name);
+ PR_RunError (progfuncs, "bad pointer write in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name));
}
ptr = QCPOINTER(OPB);
ptr->_int = OPA->_int;
break;
case OP_STOREP_F:
+ case OP_GSTOREP_F:
case OP_STOREP_ENT:
+ case OP_GSTOREP_ENT:
case OP_STOREP_FLD: // integers
+ case OP_GSTOREP_FLD:
case OP_STOREP_S:
+ case OP_GSTOREP_S:
case OP_STOREP_FNC: // pointers
+ case OP_GSTOREP_FNC:
if ((unsigned int)OPB->_int >= addressableused)
{
pr_xstatement = st-pr_statements;
- PR_RunError (progfuncs, "bad pointer write in %s", progfuncs->stringtable + pr_xfunction->s_name);
+ PR_RunError (progfuncs, "bad pointer write in %s (%x >= %x)", PR_StringToNative(progfuncs, pr_xfunction->s_name), OPB->_int, addressableused);
}
ptr = QCPOINTER(OPB);
ptr->_int = OPA->_int;
break;
case OP_STOREP_V:
+ case OP_GSTOREP_V:
if ((unsigned int)OPB->_int >= addressableused)
{
pr_xstatement = st-pr_statements;
- PR_RunError (progfuncs, "bad pointer write in %s", progfuncs->stringtable + pr_xfunction->s_name);
+ PR_RunError (progfuncs, "bad pointer write in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name));
}
ptr = QCPOINTER(OPB);
ptr->_vector[0] = OPA->_vector[0];
if ((unsigned int)OPB->_int >= addressableused)
{
pr_xstatement = st-pr_statements;
- PR_RunError (progfuncs, "bad pointer write in %s", progfuncs->stringtable + pr_xfunction->s_name);
+ PR_RunError (progfuncs, "bad pointer write in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name));
}
ptr = QCPOINTER(OPB);
*(unsigned char *)ptr = (char)OPA->_float;
case OP_MULSTORE_F: // f *= f
OPB->_float *= OPA->_float;
break;
- case OP_MULSTORE_V: // v *= f
+ case OP_MULSTORE_VF: // v *= f
OPB->_vector[0] *= OPA->_float;
OPB->_vector[1] *= OPA->_float;
OPB->_vector[2] *= OPA->_float;
if ((unsigned int)OPB->_int >= addressableused)
{
pr_xstatement = st-pr_statements;
- PR_RunError (progfuncs, "bad pointer write in %s", progfuncs->stringtable + pr_xfunction->s_name);
+ PR_RunError (progfuncs, "bad pointer write in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name));
}
ptr = QCPOINTER(OPB);
OPC->_float = (ptr->_float *= OPA->_float);
break;
- case OP_MULSTOREP_V: // e.v *= f
+ case OP_MULSTOREP_VF: // e.v *= f
+ if ((unsigned int)OPB->_int >= addressableused)
+ {
+ pr_xstatement = st-pr_statements;
+ PR_RunError (progfuncs, "bad pointer write in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name));
+ }
ptr = QCPOINTER(OPB);
OPC->_vector[0] = (ptr->_vector[0] *= OPA->_float);
OPC->_vector[0] = (ptr->_vector[1] *= OPA->_float);
OPB->_float /= OPA->_float;
break;
case OP_DIVSTOREP_F: // e.f /= f
+ if ((unsigned int)OPB->_int >= addressableused)
+ {
+ pr_xstatement = st-pr_statements;
+ PR_RunError (progfuncs, "bad pointer write in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name));
+ }
ptr = QCPOINTER(OPB);
OPC->_float = (ptr->_float /= OPA->_float);
break;
OPB->_vector[2] += OPA->_vector[2];
break;
case OP_ADDSTOREP_F: // e.f += f
+ if ((unsigned int)OPB->_int >= addressableused)
+ {
+ pr_xstatement = st-pr_statements;
+ PR_RunError (progfuncs, "bad pointer write in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name));
+ }
ptr = QCPOINTER(OPB);
OPC->_float = (ptr->_float += OPA->_float);
break;
case OP_ADDSTOREP_V: // e.v += v
+ if ((unsigned int)OPB->_int >= addressableused)
+ {
+ pr_xstatement = st-pr_statements;
+ PR_RunError (progfuncs, "bad pointer write in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name));
+ }
ptr = QCPOINTER(OPB);
OPC->_vector[0] = (ptr->_vector[0] += OPA->_vector[0]);
OPC->_vector[1] = (ptr->_vector[1] += OPA->_vector[1]);
OPB->_vector[2] -= OPA->_vector[2];
break;
case OP_SUBSTOREP_F: // e.f -= f
+ if ((unsigned int)OPB->_int >= addressableused)
+ {
+ pr_xstatement = st-pr_statements;
+ PR_RunError (progfuncs, "bad pointer write in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name));
+ }
ptr = QCPOINTER(OPB);
OPC->_float = (ptr->_float -= OPA->_float);
break;
case OP_SUBSTOREP_V: // e.v -= v
+ if ((unsigned int)OPB->_int >= addressableused)
+ {
+ pr_xstatement = st-pr_statements;
+ PR_RunError (progfuncs, "bad pointer write in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name));
+ }
ptr = QCPOINTER(OPB);
OPC->_vector[0] = (ptr->_vector[0] -= OPA->_vector[0]);
OPC->_vector[1] = (ptr->_vector[1] -= OPA->_vector[1]);
{
#ifndef DEBUGABLE
pr_trace++;
- printf("OP_ADDRESS references invalid entity in %s", progfuncs->stringtable + pr_xfunction->s_name);
+ printf("OP_ADDRESS references invalid entity in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name));
st--;
goto cont;
#else
#ifndef DEBUGABLE
//boot it over to the debugger
pr_trace++;
- printf("assignment to read-only entity in %s", progfuncs->stringtable + pr_xfunction->s_name);
+ printf("assignment to read-only entity in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name));
st--;
goto cont;
#else
fdef_t *f;
d16 = ED_GlobalAtOfs16(progfuncs, st->a);
f = ED_FieldAtOfs(progfuncs, OPB->_int + progfuncs->fieldadjust);
- PR_RunError (progfuncs, "assignment to read-only entity in %s (%s.%s)", PR_StringToNative(progfuncs, pr_xfunction->s_name), PR_StringToNative(progfuncs, d16->s_name), f?f->name:NULL);
+ printf ("assignment to read-only entity in %s (%s.%s)\n", PR_StringToNative(progfuncs, pr_xfunction->s_name), d16?PR_StringToNative(progfuncs, d16->s_name):NULL, f?f->name:NULL);
}
#endif
}
// if (ed->isfree)
// {
// pr_xstatement = st-pr_statements;
-// PR_RunError (progfuncs, "assignment to free entitiy in %s", progfuncs->stringtable + pr_xfunction->s_name);
+// PR_RunError (progfuncs, "assignment to free entitiy in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name));
// }
OPC->_int = ENGINEPOINTER((((int *)edvars(ed)) + OPB->_int + progfuncs->fieldadjust));
break;
case OP_LOAD_S:
case OP_LOAD_FNC:
if ((unsigned)OPA->edict >= (unsigned)maxedicts)
- PR_RunError (progfuncs, "OP_LOAD references invalid entity in %s", progfuncs->stringtable + pr_xfunction->s_name);
+ PR_RunError (progfuncs, "OP_LOAD references invalid entity in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name));
ed = PROG_TO_EDICT(progfuncs, OPA->edict);
#ifdef PARANOID
NUM_FOR_EDICT(ed); // make sure it's in range
case OP_LOAD_V:
if ((unsigned)OPA->edict >= (unsigned)maxedicts)
- PR_RunError (progfuncs, "OP_LOAD_V references invalid entity in %s", progfuncs->stringtable + pr_xfunction->s_name);
+ PR_RunError (progfuncs, "OP_LOAD_V references invalid entity in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name));
ed = PROG_TO_EDICT(progfuncs, OPA->edict);
#ifdef PARANOID
NUM_FOR_EDICT(ed); // make sure it's in range
RUNAWAYCHECK();
pr_xstatement = st-pr_statements;
-
- if (st->op > OP_CALL8)
- pr_argc = st->op - (OP_CALL1H-1);
+ if (OPCODE > OP_CALL8)
+ pr_argc = OPCODE - (OP_CALL1H-1);
else
- pr_argc = st->op - OP_CALL0;
+ pr_argc = OPCODE - OP_CALL0;
fnum = OPA->function;
if ((fnum & ~0xff000000)==0)
{
- PR_RunError(progfuncs, "NULL function from qc (%s).\n", progfuncs->stringtable + pr_xfunction->s_name);
+ PR_RunError(progfuncs, "NULL function from qc (%s).\n", PR_StringToNative(progfuncs, pr_xfunction->s_name));
#ifndef DEBUGABLE
goto cont;
#endif
progfuncs->save_ents(progfuncs, buffer, &size, 0);
}*/
-
- p=pr_typecurrent;
+ {
+ int callerprogs=pr_typecurrent;
//about to switch. needs caching.
//if it's an external call, switch now (before any function pointers are used)
- PR_MoveParms(progfuncs, (fnum & 0xff000000)>>24, p);
+ PR_MoveParms(progfuncs, (fnum & 0xff000000)>>24, callerprogs);
PR_SwitchProgs(progfuncs, (fnum & 0xff000000)>>24);
newf = &pr_functions[fnum & ~0xff000000];
if (newf->first_statement < 0)
{ // negative statements are built in functions
-
-if (pr_typecurrent != 0)
-{
- PR_MoveParms(progfuncs, 0, pr_typecurrent);
- PR_SwitchProgs(progfuncs, 0);
-}
+ /*calling a builtin in another progs may affect that other progs' globals instead, is the theory anyway, so args and stuff need to move over*/
+ if (pr_typecurrent != 0)
+ {
+ PR_MoveParms(progfuncs, 0, pr_typecurrent);
+ PR_SwitchProgs(progfuncs, 0);
+ }
i = -newf->first_statement;
// p = pr_typecurrent;
progfuncs->lastcalledbuiltinnumber = i;
else
current_progstate->builtins [i] (progfuncs, (struct globalvars_s *)current_progstate->globals);
}
- PR_MoveParms(progfuncs, p, pr_typecurrent);
+ PR_MoveParms(progfuncs, callerprogs, pr_typecurrent);
// memcpy(&pr_progstate[p].globals[OFS_RETURN], ¤t_progstate->globals[OFS_RETURN], sizeof(vec3_t));
- PR_SwitchProgs(progfuncs, (progsnum_t)p);
+ PR_SwitchProgs(progfuncs, (progsnum_t)callerprogs);
//#ifndef DEBUGABLE //decide weather non debugger wants to start debugging.
s = st-pr_statements;
}
// PR_MoveParms((OPA->function & 0xff000000)>>24, pr_typecurrent);
// PR_SwitchProgs((OPA->function & 0xff000000)>>24);
- s = PR_EnterFunction (progfuncs, newf, p);
+ s = PR_EnterFunction (progfuncs, newf, callerprogs);
st = &pr_statements[s];
+ }
goto restart;
// break;
//array/structure reading/writing.
case OP_GLOBALADDRESS:
- OPC->_int = ENGINEPOINTER(&OPA->_int + OPB->_int);
+ OPC->_int = ENGINEPOINTER(&OPA->_int + OPB->_int); /*pointer arithmatic*/
break;
case OP_POINTER_ADD: //pointer to 32 bit (remember to *3 for vectors)
OPC->_int = OPA->_int + OPB->_int*4;
case OP_LOADA_ENT:
case OP_LOADA_S:
case OP_LOADA_FNC:
- ptr = (eval_t *)(&OPA->_int + OPB->_int);
+ ptr = (eval_t *)(&OPA->_int + OPB->_int); /*pointer arithmatic*/
OPC->_int = ptr->_int;
break;
OPC->_int = OPA->_int - OPB->_int;
break;
case OP_LOADP_C: //load character from a string
- ptr = QCPOINTERM(OPA->_int + (int)OPB->_float);
+ i = (unsigned int)OPA->_int + (unsigned int)OPB->_float;
+ if ((unsigned int)i >= addressableused)
+ {
+ i = (unsigned int)OPB->_float;
+ ptr = (eval_t*)PR_StringToNative(progfuncs, OPA->_int);
+ if ((size_t)i > strlen((char*)ptr))
+ {
+ pr_xstatement = st-pr_statements;
+ PR_RunError (progfuncs, "bad pointer read in %s (%i bytes into %s)", PR_StringToNative(progfuncs, pr_xfunction->s_name), i, ptr);
+ }
+ ptr = (eval_t*)((char*)ptr + i);
+ }
+ else
+ ptr = QCPOINTERM(i);
OPC->_float = *(unsigned char *)ptr;
break;
case OP_LOADP_I:
case OP_LOADP_ENT:
case OP_LOADP_S:
case OP_LOADP_FNC:
- ptr = QCPOINTERM(OPA->_int + OPB->_int);
+ i = OPA->_int + OPB->_int*4;
+ if ((unsigned int)i >= addressableused)
+ {
+ pr_xstatement = st-pr_statements;
+ PR_RunError (progfuncs, "bad pointer read in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name));
+ }
+ ptr = QCPOINTERM(OPA->_int + OPB->_int*4);
OPC->_int = ptr->_int;
break;
case OP_LOADP_V:
- ptr = QCPOINTERM(OPA->_int + OPB->_int);
+ i = OPA->_int + OPB->_int*4;
+ if ((unsigned int)i >= addressableused)
+ {
+ pr_xstatement = st-pr_statements;
+ PR_RunError (progfuncs, "bad pointer read in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name));
+ }
+ ptr = QCPOINTERM(i);
OPC->_vector[0] = ptr->_vector[0];
OPC->_vector[1] = ptr->_vector[1];
OPC->_vector[2] = ptr->_vector[2];
i = (int)OPB->_float;
if(i < 0 || i > ((eval_t *)&glob[st->a-1])->_int)
{
- PR_RunError(progfuncs, "array index out of bounds: %s[%d]", PR_GlobalStringNoContents(progfuncs, st->a), i);
+ PR_RunError(progfuncs, "array index out of bounds: %s[%d] (max %d)", PR_GlobalStringNoContents(progfuncs, st->a), i, ((eval_t *)&glob[st->a-1])->_int);
}
t = (eval_t *)&pr_globals[(uofs)st->a + i];
OPC->_int = t->_int;
OPB->_float = (float)((int)OPB->_float | (int)OPA->_float);
break;
case OP_BITSETP: // .b (+) a
+ if ((unsigned int)OPB->_int >= addressableused)
+ {
+ pr_xstatement = st-pr_statements;
+ PR_RunError (progfuncs, "bad pointer write in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name));
+ }
ptr = QCPOINTER(OPB);
ptr->_float = (float)((int)ptr->_float | (int)OPA->_float);
break;
OPB->_float = (float)((int)OPB->_float & ~((int)OPA->_float));
break;
case OP_BITCLRP: // .b (-) a
+ if ((unsigned int)OPB->_int >= addressableused)
+ {
+ pr_xstatement = st-pr_statements;
+ PR_RunError (progfuncs, "bad pointer write in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name));
+ }
ptr = QCPOINTER(OPB);
ptr->_float = (float)((int)ptr->_float & ~((int)OPA->_float));
break;
case OP_RAND0:
- G_FLOAT(OFS_RETURN) = (rand()&0x7fff)/((float)0x7fff);
+ OPC->_float = (rand()&0x7fff)/((float)0x7fff);
break;
case OP_RAND1:
- G_FLOAT(OFS_RETURN) = (rand()&0x7fff)/((float)0x7fff)*OPA->_float;
+ OPC->_float = (rand()&0x7fff)/((float)0x7fff)*OPA->_float;
break;
case OP_RAND2:
if(OPA->_float < OPB->_float)
{
- G_FLOAT(OFS_RETURN) = OPA->_float+((rand()&0x7fff)/((float)0x7fff)
+ OPC->_float = OPA->_float+((rand()&0x7fff)/((float)0x7fff)
*(OPB->_float-OPA->_float));
}
else
{
- G_FLOAT(OFS_RETURN) = OPB->_float+((rand()&0x7fff)/((float)0x7fff)
+ OPC->_float = OPB->_float+((rand()&0x7fff)/((float)0x7fff)
*(OPA->_float-OPB->_float));
}
break;
case OP_RANDV0:
- G_FLOAT(OFS_RETURN+0) = (rand()&0x7fff)/((float)0x7fff);
- G_FLOAT(OFS_RETURN+1) = (rand()&0x7fff)/((float)0x7fff);
- G_FLOAT(OFS_RETURN+2) = (rand()&0x7fff)/((float)0x7fff);
+ OPC->_vector[0] = (rand()&0x7fff)/((float)0x7fff);
+ OPC->_vector[1] = (rand()&0x7fff)/((float)0x7fff);
+ OPC->_vector[2] = (rand()&0x7fff)/((float)0x7fff);
break;
case OP_RANDV1:
- G_FLOAT(OFS_RETURN+0) = (rand()&0x7fff)/((float)0x7fff)*OPA->_vector[0];
- G_FLOAT(OFS_RETURN+1) = (rand()&0x7fff)/((float)0x7fff)*OPA->_vector[1];
- G_FLOAT(OFS_RETURN+2) = (rand()&0x7fff)/((float)0x7fff)*OPA->_vector[2];
+ OPC->_vector[0] = (rand()&0x7fff)/((float)0x7fff)*OPA->_vector[0];
+ OPC->_vector[1] = (rand()&0x7fff)/((float)0x7fff)*OPA->_vector[1];
+ OPC->_vector[2] = (rand()&0x7fff)/((float)0x7fff)*OPA->_vector[2];
break;
case OP_RANDV2:
for(i = 0; i < 3; i++)
{
if(OPA->_vector[i] < OPB->_vector[i])
{
- G_FLOAT(OFS_RETURN+i) = OPA->_vector[i]+((rand()&0x7fff)/((float)0x7fff)
+ OPC->_vector[i] = OPA->_vector[i]+((rand()&0x7fff)/((float)0x7fff)
*(OPB->_vector[i]-OPA->_vector[i]));
}
else
{
- G_FLOAT(OFS_RETURN+i) = OPB->_vector[i]+(rand()*(1.0f/RAND_MAX)
+ OPC->_vector[i] = OPB->_vector[i]+(rand()*(1.0f/RAND_MAX)
*(OPA->_vector[i]-OPB->_vector[i]));
}
}
case OP_SWITCH_E:
case OP_SWITCH_FNC:
swtch = OPA;
- swtchtype = st->op;
+ swtchtype = OPCODE;
RUNAWAYCHECK();
st += (sofs)st->b - 1; // offset the st++
break;
OPC->_int = (OPA->_float != OPB->_int);
break;
- case OP_GSTOREP_I:
- case OP_GSTOREP_F:
- case OP_GSTOREP_ENT:
- case OP_GSTOREP_FLD: // integers
- case OP_GSTOREP_S:
- case OP_GSTOREP_FNC: // pointers
- case OP_GSTOREP_V:
case OP_GADDRESS:
case OP_GLOAD_I:
case OP_GLOAD_F:
if ((unsigned int)OPA->_int < (unsigned int)st->c || (unsigned int)OPA->_int >= (unsigned int)st->b)
{
pr_xstatement = st-pr_statements;
- PR_RunError(progfuncs, "Progs boundcheck failed. Value is %i.", OPA->_int);
+ PR_RunError(progfuncs, "Progs boundcheck failed. Value is %i. Must be between %u and %u", OPA->_int, st->c, st->b);
}
break;
/* case OP_PUSH:
{
pr_xstatement = s = st-pr_statements;
- printf("Break point hit in %s.\n", pr_xfunction->s_name+progfuncs->stringtable);
+ printf("Break point hit in %s.\n", PR_StringToNative(progfuncs, pr_xfunction->s_name));
if (pr_trace<1)
pr_trace=1; //this is what it's for
#undef dstatement_t
#undef sofs
#undef uofs
+#undef OPCODE
#undef ENGINEPOINTER
#undef QCPOINTER