void PR_ExecuteProgram (func_t fnum) { eval_t *a, *b, *c; int s, runaway, i, exitdepth; dstatement_t *st; dfunction_t *f, *newf; edict_t *ed; eval_t *ptr; //Tei: enhanced vm #if 0 //TODO: this able self.think = remove(); // ..test this. If work, enable. if (fnum<0) { //Call a builtin i = -fnum; if (i >= pr_numbuiltins) PR_RunError ("Bad builtin call number '%d'", i); pr_builtins[i] (); return; } #endif if (!fnum || fnum >= progs->numfunctions) { if (pr_global_struct->self) ED_Print (PROG_TO_EDICT(pr_global_struct->self)); Host_Error ("PR_ExecuteProgram: NULL function"); } f = &pr_functions[fnum]; runaway = 1000000;//Tei: x10 deeper functions pr_trace = false; // make a stack frame exitdepth = pr_depth; s = PR_EnterFunction (f); while (1) { s++; // next statement st = &pr_statements[s]; a = (eval_t *) &pr_globals[st->a]; b = (eval_t *) &pr_globals[st->b]; c = (eval_t *) &pr_globals[st->c]; if (--runaway == 0) PR_RunError ("runaway loop error"); pr_xfunction->profile++; pr_xstatement = s; if (pr_trace) PR_PrintStatement (st); switch (st->op) { case OP_ADD_F: c->_float = a->_float + b->_float; break; case OP_ADD_V: VectorAdd(a->vector, b->vector, c->vector); break; case OP_SUB_F: c->_float = a->_float - b->_float; break; case OP_SUB_V: VectorSubtract(a->vector, b->vector, c->vector); break; case OP_MUL_F: c->_float = a->_float * b->_float; break; case OP_MUL_V: c->_float = a->vector[0] * b->vector[0] + a->vector[1] * b->vector[1] + a->vector[2] * b->vector[2]; break; case OP_MUL_FV: VectorScale(b->vector, a->_float, c->vector); break; case OP_MUL_VF: VectorScale(a->vector, b->_float, c->vector); break; case OP_DIV_F: c->_float = a->_float / b->_float; break; case OP_BITAND: c->_float = (int) a->_float & (int) b->_float; break; case OP_BITOR: c->_float = (int) a->_float | (int) b->_float; break; case OP_GE: c->_float = a->_float >= b->_float; break; case OP_LE: c->_float = a->_float <= b->_float; break; case OP_GT: c->_float = a->_float > b->_float; break; case OP_LT: c->_float = a->_float < b->_float; break; case OP_AND: c->_float = a->_float && b->_float; break; case OP_OR: c->_float = a->_float || b->_float; break; case OP_NOT_F: c->_float = !a->_float; break; case OP_NOT_V: c->_float = !a->vector[0] && !a->vector[1] && !a->vector[2]; break; case OP_NOT_S: c->_float = !a->string || !*PR_GetString(a->string); break; case OP_NOT_FNC: c->_float = !a->function; break; case OP_NOT_ENT: c->_float = (PROG_TO_EDICT(a->edict) == sv.edicts); break; case OP_EQ_F: c->_float = a->_float == b->_float; break; case OP_EQ_V: c->_float = VectorCompare(a->vector, b->vector); break; case OP_EQ_S: c->_float = !strcmp(PR_GetString(a->string), PR_GetString(b->string)); break; case OP_EQ_E: c->_float = a->_int == b->_int; break; case OP_EQ_FNC: c->_float = a->function == b->function; break; case OP_NE_F: c->_float = a->_float != b->_float; break; case OP_NE_V: c->_float = !VectorCompare(a->vector, b->vector); break; case OP_NE_S: c->_float = strcmp(PR_GetString(a->string), PR_GetString(b->string)); break; case OP_NE_E: c->_float = a->_int != b->_int; break; case OP_NE_FNC: c->_float = a->function != b->function; break; //================== case OP_STORE_F: case OP_STORE_ENT: case OP_STORE_FLD: // integers case OP_STORE_S: case OP_STORE_FNC: // pointers b->_int = a->_int; break; case OP_STORE_V: VectorCopy(a->vector, b->vector); break; case OP_STOREP_F: case OP_STOREP_ENT: case OP_STOREP_FLD: // integers case OP_STOREP_S: case OP_STOREP_FNC: // pointers ptr = (eval_t *) ((byte *) sv.edicts + b->_int); ptr->_int = a->_int; break; case OP_STOREP_V: ptr = (eval_t *)((byte *)sv.edicts + b->_int); VectorCopy(a->vector, ptr->vector); break; case OP_ADDRESS: ed = PROG_TO_EDICT(a->edict); #ifdef PARANOID NUM_FOR_EDICT(ed); // make sure it's in range #endif if (ed == (edict_t *) sv.edicts && sv.state == ss_active) PR_RunError ("assignment to world entity"); c->_int = (byte *) ((int *) &ed->v + b->_int) - (byte *) sv.edicts; break; case OP_LOAD_F: case OP_LOAD_FLD: case OP_LOAD_ENT: case OP_LOAD_S: case OP_LOAD_FNC: ed = PROG_TO_EDICT(a->edict); #ifdef PARANOID NUM_FOR_EDICT(ed); // make sure it's in range #endif a = (eval_t *) ((int *) &ed->v + b->_int); c->_int = a->_int; break; case OP_LOAD_V: ed = PROG_TO_EDICT(a->edict); #ifdef PARANOID NUM_FOR_EDICT(ed); // make sure it's in range #endif a = (eval_t *) ((int *) &ed->v + b->_int); VectorCopy(a->vector, c->vector); break; //================== case OP_IFNOT: if (!a->_int) s += st->b - 1; // offset the s++ break; case OP_IF: if (a->_int) s += st->b - 1; // offset the s++ break; case OP_GOTO: s += st->a - 1; // offset the s++ break; case OP_CALL0: case OP_CALL1: case OP_CALL2: case OP_CALL3: case OP_CALL4: case OP_CALL5: case OP_CALL6: case OP_CALL7: case OP_CALL8: pr_argc = st->op - OP_CALL0; if (!a->function) PR_RunError ("NULL function"); newf = &pr_functions[a->function]; if (newf->first_statement < 0) { // negative statements are built in functions i = -newf->first_statement; if (i < pr_numbuiltins && pr_builtins[i]) pr_builtins[i](); else PR_RunError ("No such builtin #%i", i); break; } s = PR_EnterFunction (newf); break; case OP_DONE: case OP_RETURN: pr_globals[OFS_RETURN] = pr_globals[st->a]; pr_globals[OFS_RETURN + 1] = pr_globals[st->a + 1]; pr_globals[OFS_RETURN + 2] = pr_globals[st->a + 2]; s = PR_LeaveFunction (); if (pr_depth == exitdepth) return; // all done break; case OP_STATE: ed = PROG_TO_EDICT(pr_global_struct->self); ed->v.nextthink = pr_global_struct->time + 0.1; if (a->_float != ed->v.frame) ed->v.frame = a->_float; ed->v.think = b->function; break; default: PR_RunError ("Bad opcode %i", st->op); } } }
/* ================ ED_LoadFromFile The entities are directly placed in the array, rather than allocated with ED_Alloc, because otherwise an error loading the map would have entity number references out of order. Creates a server's entity / program execution context by parsing textual entity definitions out of an ent file. Used for both fresh maps and savegame loads. A fresh map would also need to call ED_CallSpawnFunctions () to let the objects initialize themselves. ================ */ void ED_LoadFromFile (char *data) { extern cvar_t cl_curlybraces; edict_t *ent; int inhibit; dfunction_t *func; float curlybraces_oldvalue = cl_curlybraces.value; if (curlybraces_oldvalue) { Cvar_SetValue(&cl_curlybraces, 0); } ent = NULL; inhibit = 0; pr_global_struct->time = sv.time; // parse ents while (1) { // parse the opening brace data = COM_Parse (data); if (!data) break; if (com_token[0] != '{') SV_Error ("ED_LoadFromFile: found %s when expecting {",com_token); if (!ent) ent = EDICT_NUM(0); else ent = ED_Alloc (); data = ED_ParseEdict (data, ent); // remove things from different skill levels or deathmatch if ((int)deathmatch.value) { if (((int)ent->v.spawnflags & SPAWNFLAG_NOT_DEATHMATCH)) { ED_Free (ent); inhibit++; continue; } } else if ((current_skill == 0 && ((int)ent->v.spawnflags & SPAWNFLAG_NOT_EASY)) || (current_skill == 1 && ((int)ent->v.spawnflags & SPAWNFLAG_NOT_MEDIUM)) || (current_skill >= 2 && ((int)ent->v.spawnflags & SPAWNFLAG_NOT_HARD)) ) { ED_Free (ent); inhibit++; continue; } // // immediately call spawn function // if (!ent->v.classname) { Con_Printf ("No classname for:\n"); ED_Print (ent); ED_Free (ent); continue; } // look for the spawn function func = ED_FindFunction ( PR_GetString(ent->v.classname) ); if (!func) { Con_Printf ("No spawn function for:\n"); ED_Print (ent); ED_Free (ent); continue; } pr_global_struct->self = EDICT_TO_PROG(ent); PR_ExecuteProgram (func - pr_functions); SV_FlushSignon(); } Con_DPrintf ("%i entities inhibited\n", inhibit); if (curlybraces_oldvalue) { Cvar_SetValue(&cl_curlybraces, curlybraces_oldvalue); } }
/* ==================== PR_ExecuteProgram ==================== */ void PR_ExecuteProgram (func_t fnum) { eval_t *a, *b, *c; int s; dstatement_t *st; dfunction_t *f, *newf; int runaway; int i; edict_t *ed; int exitdepth; eval_t *ptr; // 2001-09-14 Enhanced BuiltIn Function System (EBFS) by Maddes start char *funcname; char *remaphint; // 2001-09-14 Enhanced BuiltIn Function System (EBFS) by Maddes end if (!fnum || fnum >= progs->numfunctions) { if (pr_global_struct->self) ED_Print (PROG_TO_EDICT(pr_global_struct->self)); Host_Error ("PR_ExecuteProgram: NULL function"); } f = &pr_functions[fnum]; runaway = RUNAWAY; //was 100000; pr_trace = false; // make a stack frame exitdepth = pr_depth; s = PR_EnterFunction (f); while (1) { s++; // next statement pr_xstatement = s; pr_xfunction->profile++; st = &pr_statements[s]; a = (eval_t *)&pr_globals[st->a]; b = (eval_t *)&pr_globals[st->b]; c = (eval_t *)&pr_globals[st->c]; if (!--runaway) PR_RunError ("runaway loop error"); if (runaway < RUNAWAY - RUNAWAY_STEP + 1 && runaway % RUNAWAY_STEP == 0) { Con_Printf ("PR_ExecuteProgram: runaway loop %d\n", runaway / RUNAWAY_STEP); SCR_UpdateScreen (); // Force screen update S_ClearBuffer (); // Avoid looping sounds } if (pr_trace) PR_PrintStatement (st); switch (st->op) { case OP_ADD_F: c->_float = a->_float + b->_float; break; case OP_ADD_V: c->vector[0] = a->vector[0] + b->vector[0]; c->vector[1] = a->vector[1] + b->vector[1]; c->vector[2] = a->vector[2] + b->vector[2]; break; case OP_SUB_F: c->_float = a->_float - b->_float; break; case OP_SUB_V: c->vector[0] = a->vector[0] - b->vector[0]; c->vector[1] = a->vector[1] - b->vector[1]; c->vector[2] = a->vector[2] - b->vector[2]; break; case OP_MUL_F: c->_float = a->_float * b->_float; break; case OP_MUL_V: c->_float = a->vector[0]*b->vector[0] + a->vector[1]*b->vector[1] + a->vector[2]*b->vector[2]; break; case OP_MUL_FV: c->vector[0] = a->_float * b->vector[0]; c->vector[1] = a->_float * b->vector[1]; c->vector[2] = a->_float * b->vector[2]; break; case OP_MUL_VF: c->vector[0] = b->_float * a->vector[0]; c->vector[1] = b->_float * a->vector[1]; c->vector[2] = b->_float * a->vector[2]; break; case OP_DIV_F: c->_float = a->_float / b->_float; break; case OP_BITAND: c->_float = (int)a->_float & (int)b->_float; break; case OP_BITOR: c->_float = (int)a->_float | (int)b->_float; break; case OP_GE: c->_float = a->_float >= b->_float; break; case OP_LE: c->_float = a->_float <= b->_float; break; case OP_GT: c->_float = a->_float > b->_float; break; case OP_LT: c->_float = a->_float < b->_float; break; case OP_AND: c->_float = a->_float && b->_float; break; case OP_OR: c->_float = a->_float || b->_float; break; case OP_NOT_F: c->_float = !a->_float; break; case OP_NOT_V: c->_float = !a->vector[0] && !a->vector[1] && !a->vector[2]; break; case OP_NOT_S: c->_float = !a->string || !pr_strings[a->string]; break; case OP_NOT_FNC: c->_float = !a->function; break; case OP_NOT_ENT: c->_float = (PROG_TO_EDICT(a->edict) == sv.edicts); break; case OP_EQ_F: c->_float = a->_float == b->_float; break; case OP_EQ_V: c->_float = (a->vector[0] == b->vector[0]) && (a->vector[1] == b->vector[1]) && (a->vector[2] == b->vector[2]); break; case OP_EQ_S: c->_float = !strcmp(pr_strings+a->string,pr_strings+b->string); break; case OP_EQ_E: c->_float = a->_int == b->_int; break; case OP_EQ_FNC: c->_float = a->function == b->function; break; case OP_NE_F: c->_float = a->_float != b->_float; break; case OP_NE_V: c->_float = (a->vector[0] != b->vector[0]) || (a->vector[1] != b->vector[1]) || (a->vector[2] != b->vector[2]); break; case OP_NE_S: c->_float = strcmp(pr_strings+a->string,pr_strings+b->string); break; case OP_NE_E: c->_float = a->_int != b->_int; break; case OP_NE_FNC: c->_float = a->function != b->function; break; //================== case OP_STORE_F: case OP_STORE_ENT: case OP_STORE_FLD: // integers case OP_STORE_S: case OP_STORE_FNC: // pointers b->_int = a->_int; break; case OP_STORE_V: b->vector[0] = a->vector[0]; b->vector[1] = a->vector[1]; b->vector[2] = a->vector[2]; break; case OP_STOREP_F: case OP_STOREP_ENT: case OP_STOREP_FLD: // integers case OP_STOREP_S: case OP_STOREP_FNC: // pointers ptr = (eval_t *)((byte *)sv.edicts + b->_int); ptr->_int = a->_int; break; case OP_STOREP_V: ptr = (eval_t *)((byte *)sv.edicts + b->_int); ptr->vector[0] = a->vector[0]; ptr->vector[1] = a->vector[1]; ptr->vector[2] = a->vector[2]; break; case OP_ADDRESS: ed = PROG_TO_EDICT(a->edict); #ifdef PARANOID NUM_FOR_EDICT(ed); // make sure it's in range #endif if (ed == (edict_t *)sv.edicts && sv.state == ss_active) PR_RunError ("assignment to world entity"); c->_int = (byte *)((int *)&ed->v + b->_int) - (byte *)sv.edicts; break; case OP_LOAD_F: case OP_LOAD_FLD: case OP_LOAD_ENT: case OP_LOAD_S: case OP_LOAD_FNC: ed = PROG_TO_EDICT(a->edict); #ifdef PARANOID NUM_FOR_EDICT(ed); // make sure it's in range #endif a = (eval_t *)((int *)&ed->v + b->_int); c->_int = a->_int; break; case OP_LOAD_V: ed = PROG_TO_EDICT(a->edict); #ifdef PARANOID NUM_FOR_EDICT(ed); // make sure it's in range #endif a = (eval_t *)((int *)&ed->v + b->_int); c->vector[0] = a->vector[0]; c->vector[1] = a->vector[1]; c->vector[2] = a->vector[2]; break; //================== case OP_IFNOT: if (!a->_int) s += st->b - 1; // offset the s++ break; case OP_IF: if (a->_int) s += st->b - 1; // offset the s++ break; case OP_GOTO: s += st->a - 1; // offset the s++ break; case OP_CALL0: case OP_CALL1: case OP_CALL2: case OP_CALL3: case OP_CALL4: case OP_CALL5: case OP_CALL6: case OP_CALL7: case OP_CALL8: pr_argc = st->op - OP_CALL0; if (!a->function) PR_RunError ("NULL function"); newf = &pr_functions[a->function]; if (newf->first_statement < 0) { // negative statements are built in functions i = -newf->first_statement; // 2001-09-14 Enhanced BuiltIn Function System (EBFS) by Maddes start if ( (i >= pr_numbuiltins)||(pr_builtins[i] == pr_ebfs_builtins[0].function) ) { funcname = pr_strings + newf->s_name; if (pr_builtin_remap.value) { remaphint = NULL; } else { remaphint = "Try \"builtin remapping\" by setting PR_BUILTIN_REMAP to 1\n"; } PR_RunError ("Bad builtin call number %i for %s\n", i, funcname, remaphint); } // 2001-09-14 Enhanced BuiltIn Function System (EBFS) by Maddes end pr_builtins[i] (); break; } s = PR_EnterFunction (newf); break; case OP_DONE: case OP_RETURN: pr_globals[OFS_RETURN] = pr_globals[st->a]; pr_globals[OFS_RETURN+1] = pr_globals[st->a+1]; pr_globals[OFS_RETURN+2] = pr_globals[st->a+2]; s = PR_LeaveFunction (); if (pr_depth == exitdepth) return; // all done break; case OP_STATE: ed = PROG_TO_EDICT(pr_global_struct->self); #ifdef FPS_20 ed->v.nextthink = pr_global_struct->time + 0.05; #else ed->v.nextthink = pr_global_struct->time + 0.1; #endif if (a->_float != ed->v.frame) { ed->v.frame = a->_float; } ed->v.think = b->function; break; default: PR_RunError ("Bad opcode %i", st->op); } } }
void ED_PrintNum (int ent) { ED_Print (EDICT_NUM(ent)); }
void PR_ExecuteProgram(func_t fnum) { int i; int s; eval_t *a, *b, *c; eval_t *ptr; dstatement_t *st; dfunction_t *f, *newf; int runaway; edict_t *ed; int exitdepth; int startFrame; int endFrame; float val; int case_type=-1; float switch_float; if(!fnum || fnum >= progs->numfunctions) { if(pr_global_struct->self) { ED_Print(PROG_TO_EDICT(pr_global_struct->self)); } Host_Error("PR_ExecuteProgram: NULL function"); } f = &pr_functions[fnum]; runaway = 100000; pr_trace = false; exitdepth = pr_depth; s = EnterFunction(f); #ifdef TIMESNAP_ACTIVE ProgsTimer(); // Init #endif while (1) { s++; // Next statement st = &pr_statements[s]; a = (eval_t *)&pr_globals[(unsigned short)st->a]; b = (eval_t *)&pr_globals[(unsigned short)st->b]; c = (eval_t *)&pr_globals[(unsigned short)st->c]; if(!--runaway) { PR_RunError("runaway loop error"); } #ifndef TIMESNAP_ACTIVE pr_xfunction->profile++; #endif pr_xstatement = s; if(pr_trace) { PrintStatement(st); } switch(st->op) { case OP_ADD_F: c->_float = a->_float + b->_float; break; case OP_ADD_V: c->vector[0] = a->vector[0] + b->vector[0]; c->vector[1] = a->vector[1] + b->vector[1]; c->vector[2] = a->vector[2] + b->vector[2]; break; case OP_SUB_F: c->_float = a->_float - b->_float; break; case OP_SUB_V: c->vector[0] = a->vector[0] - b->vector[0]; c->vector[1] = a->vector[1] - b->vector[1]; c->vector[2] = a->vector[2] - b->vector[2]; break; case OP_MUL_F: c->_float = a->_float * b->_float; break; case OP_MUL_V: c->_float = a->vector[0]*b->vector[0] + a->vector[1]*b->vector[1] + a->vector[2]*b->vector[2]; break; case OP_MUL_FV: c->vector[0] = a->_float * b->vector[0]; c->vector[1] = a->_float * b->vector[1]; c->vector[2] = a->_float * b->vector[2]; break; case OP_MUL_VF: c->vector[0] = b->_float * a->vector[0]; c->vector[1] = b->_float * a->vector[1]; c->vector[2] = b->_float * a->vector[2]; break; case OP_DIV_F: c->_float = a->_float / b->_float; break; case OP_BITAND: c->_float = (int)a->_float & (int)b->_float; break; case OP_BITOR: c->_float = (int)a->_float | (int)b->_float; break; case OP_GE: c->_float = a->_float >= b->_float; break; case OP_LE: c->_float = a->_float <= b->_float; break; case OP_GT: c->_float = a->_float > b->_float; break; case OP_LT: c->_float = a->_float < b->_float; break; case OP_AND: c->_float = a->_float && b->_float; break; case OP_OR: c->_float = a->_float || b->_float; break; case OP_NOT_F: c->_float = !a->_float; break; case OP_NOT_V: c->_float = !a->vector[0] && !a->vector[1] && !a->vector[2]; break; case OP_NOT_S: c->_float = !a->string || !pr_strings[a->string]; break; case OP_NOT_FNC: c->_float = !a->function; break; case OP_NOT_ENT: c->_float = (PROG_TO_EDICT(a->edict) == sv.edicts); break; case OP_EQ_F: c->_float = a->_float == b->_float; break; case OP_EQ_V: c->_float = (a->vector[0] == b->vector[0]) && (a->vector[1] == b->vector[1]) && (a->vector[2] == b->vector[2]); break; case OP_EQ_S: c->_float = !strcmp(pr_strings+a->string,pr_strings+b->string); break; case OP_EQ_E: c->_float = a->_int == b->_int; break; case OP_EQ_FNC: c->_float = a->function == b->function; break; case OP_NE_F: c->_float = a->_float != b->_float; break; case OP_NE_V: c->_float = (a->vector[0] != b->vector[0]) || (a->vector[1] != b->vector[1]) || (a->vector[2] != b->vector[2]); break; case OP_NE_S: c->_float = strcmp(pr_strings+a->string,pr_strings+b->string); break; case OP_NE_E: c->_float = a->_int != b->_int; break; case OP_NE_FNC: c->_float = a->function != b->function; break; case OP_STORE_F: case OP_STORE_ENT: case OP_STORE_FLD: // integers case OP_STORE_S: case OP_STORE_FNC: // pointers b->_int = a->_int; break; case OP_STORE_V: b->vector[0] = a->vector[0]; b->vector[1] = a->vector[1]; b->vector[2] = a->vector[2]; break; case OP_STOREP_F: case OP_STOREP_ENT: case OP_STOREP_FLD: // integers case OP_STOREP_S: case OP_STOREP_FNC: // pointers ptr = (eval_t *)((byte *)sv.edicts + b->_int); ptr->_int = a->_int; break; case OP_STOREP_V: ptr = (eval_t *)((byte *)sv.edicts + b->_int); ptr->vector[0] = a->vector[0]; ptr->vector[1] = a->vector[1]; ptr->vector[2] = a->vector[2]; break; case OP_MULSTORE_F: // f *= f b->_float *= a->_float; break; case OP_MULSTORE_V: // v *= f b->vector[0] *= a->_float; b->vector[1] *= a->_float; b->vector[2] *= a->_float; break; case OP_MULSTOREP_F: // e.f *= f ptr = (eval_t *)((byte *)sv.edicts+b->_int); c->_float = (ptr->_float *= a->_float); break; case OP_MULSTOREP_V: // e.v *= f ptr = (eval_t *)((byte *)sv.edicts+b->_int); c->vector[0] = (ptr->vector[0] *= a->_float); c->vector[0] = (ptr->vector[1] *= a->_float); c->vector[0] = (ptr->vector[2] *= a->_float); break; case OP_DIVSTORE_F: // f /= f b->_float /= a->_float; break; case OP_DIVSTOREP_F: // e.f /= f ptr = (eval_t *)((byte *)sv.edicts+b->_int); c->_float = (ptr->_float /= a->_float); break; case OP_ADDSTORE_F: // f += f b->_float += a->_float; break; case OP_ADDSTORE_V: // v += v b->vector[0] += a->vector[0]; b->vector[1] += a->vector[1]; b->vector[2] += a->vector[2]; break; case OP_ADDSTOREP_F: // e.f += f ptr = (eval_t *)((byte *)sv.edicts+b->_int); c->_float = (ptr->_float += a->_float); break; case OP_ADDSTOREP_V: // e.v += v ptr = (eval_t *)((byte *)sv.edicts+b->_int); c->vector[0] = (ptr->vector[0] += a->vector[0]); c->vector[1] = (ptr->vector[1] += a->vector[1]); c->vector[2] = (ptr->vector[2] += a->vector[2]); break; case OP_SUBSTORE_F: // f -= f b->_float -= a->_float; break; case OP_SUBSTORE_V: // v -= v b->vector[0] -= a->vector[0]; b->vector[1] -= a->vector[1]; b->vector[2] -= a->vector[2]; break; case OP_SUBSTOREP_F: // e.f -= f ptr = (eval_t *)((byte *)sv.edicts+b->_int); c->_float = (ptr->_float -= a->_float); break; case OP_SUBSTOREP_V: // e.v -= v ptr = (eval_t *)((byte *)sv.edicts+b->_int); c->vector[0] = (ptr->vector[0] -= a->vector[0]); c->vector[1] = (ptr->vector[1] -= a->vector[1]); c->vector[2] = (ptr->vector[2] -= a->vector[2]); break; case OP_ADDRESS: ed = PROG_TO_EDICT(a->edict); #ifdef PARANOID NUM_FOR_EDICT(ed); // Make sure it's in range #endif if(ed == (edict_t *)sv.edicts && sv.state == ss_active) { PR_RunError("assignment to world entity"); } c->_int = (byte *)((int *)&ed->v + b->_int)-(byte *)sv.edicts; break; case OP_LOAD_F: case OP_LOAD_FLD: case OP_LOAD_ENT: case OP_LOAD_S: case OP_LOAD_FNC: ed = PROG_TO_EDICT(a->edict); #ifdef PARANOID NUM_FOR_EDICT(ed); // Make sure it's in range #endif a = (eval_t *)((int *)&ed->v+b->_int); c->_int = a->_int; break; case OP_LOAD_V: ed = PROG_TO_EDICT(a->edict); #ifdef PARANOID NUM_FOR_EDICT(ed); // Make sure it's in range #endif a = (eval_t *)((int *)&ed->v + b->_int); c->vector[0] = a->vector[0]; c->vector[1] = a->vector[1]; c->vector[2] = a->vector[2]; break; case OP_FETCH_GBL_F: case OP_FETCH_GBL_S: case OP_FETCH_GBL_E: case OP_FETCH_GBL_FNC: i = (int)b->_float; if(i < 0 || i > G_INT((unsigned short)st->a - 1)) { PR_RunError("array index out of bounds: %d", i); } a = (eval_t *)&pr_globals[(unsigned short)st->a + i]; c->_int = a->_int; break; case OP_FETCH_GBL_V: i = (int)b->_float; if(i < 0 || i > G_INT((unsigned short)st->a - 1)) { PR_RunError("array index out of bounds: %d", i); } a = (eval_t *)&pr_globals[(unsigned short)st->a +((int)b->_float)*3]; c->vector[0] = a->vector[0]; c->vector[1] = a->vector[1]; c->vector[2] = a->vector[2]; break; case OP_IFNOT: if(!a->_int) { s += st->b-1; // -1 to offset the s++ } break; case OP_IF: if(a->_int) { s += st->b-1; // -1 to offset the s++ } break; case OP_GOTO: s += st->a-1; // -1 to offset the s++ break; case OP_CALL8: case OP_CALL7: case OP_CALL6: case OP_CALL5: case OP_CALL4: case OP_CALL3: case OP_CALL2: // Copy second arg to shared space VectorCopy(c->vector, G_VECTOR(OFS_PARM1)); case OP_CALL1: // Copy first arg to shared space VectorCopy(b->vector, G_VECTOR(OFS_PARM0)); case OP_CALL0: pr_argc = st->op-OP_CALL0; if(!a->function) { PR_RunError("NULL function"); } newf = &pr_functions[a->function]; if(newf->first_statement < 0) { // Built-in function i = -newf->first_statement; if(i >= pr_numbuiltins) { PR_RunError("Bad builtin call number"); } pr_builtins[i](); break; } // Normal function #ifdef TIMESNAP_ACTIVE pr_xfunction->profile += ProgsTimer(); #endif s = EnterFunction(newf); break; case OP_DONE: case OP_RETURN: pr_globals[OFS_RETURN] = pr_globals[(unsigned short)st->a]; pr_globals[OFS_RETURN+1] = pr_globals[(unsigned short)st->a+1]; pr_globals[OFS_RETURN+2] = pr_globals[(unsigned short)st->a+2]; #ifdef TIMESNAP_ACTIVE pr_xfunction->profile += ProgsTimer(); #endif s = LeaveFunction(); if(pr_depth == exitdepth) { // Done return; } break; case OP_STATE: ed = PROG_TO_EDICT(pr_global_struct->self); /* Id 1.07 changes #ifdef FPS_20 ed->v.nextthink = pr_global_struct->time + 0.05; #else ed->v.nextthink = pr_global_struct->time + 0.1; #endif */ ed->v.nextthink = pr_global_struct->time+HX_FRAME_TIME; if(a->_float != ed->v.frame) { ed->v.frame = a->_float; } ed->v.think = b->function; break; case OP_CSTATE: // Cycle state ed = PROG_TO_EDICT(pr_global_struct->self); ed->v.nextthink = pr_global_struct->time+HX_FRAME_TIME; ed->v.think = pr_xfunction-pr_functions; pr_global_struct->cycle_wrapped = false; startFrame = (int)a->_float; endFrame = (int)b->_float; if(startFrame <= endFrame) { // Increment if(ed->v.frame < startFrame || ed->v.frame > endFrame) { ed->v.frame = startFrame; break; } ed->v.frame++; if(ed->v.frame > endFrame) { pr_global_struct->cycle_wrapped = true; ed->v.frame = startFrame; } break; } // Decrement if(ed->v.frame > startFrame || ed->v.frame < endFrame) { ed->v.frame = startFrame; break; } ed->v.frame--; if(ed->v.frame < endFrame) { pr_global_struct->cycle_wrapped = true; ed->v.frame = startFrame; } break; case OP_CWSTATE: // Cycle weapon state ed = PROG_TO_EDICT(pr_global_struct->self); ed->v.nextthink = pr_global_struct->time+HX_FRAME_TIME; ed->v.think = pr_xfunction-pr_functions; pr_global_struct->cycle_wrapped = false; startFrame = (int)a->_float; endFrame = (int)b->_float; if(startFrame <= endFrame) { // Increment if(ed->v.weaponframe < startFrame || ed->v.weaponframe > endFrame) { ed->v.weaponframe = startFrame; break; } ed->v.weaponframe++; if(ed->v.weaponframe > endFrame) { pr_global_struct->cycle_wrapped = true; ed->v.weaponframe = startFrame; } break; } // Decrement if(ed->v.weaponframe > startFrame || ed->v.weaponframe < endFrame) { ed->v.weaponframe = startFrame; break; } ed->v.weaponframe--; if(ed->v.weaponframe < endFrame) { pr_global_struct->cycle_wrapped = true; ed->v.weaponframe = startFrame; } break; case OP_THINKTIME: ed = PROG_TO_EDICT(a->edict); #ifdef PARANOID NUM_FOR_EDICT(ed); // Make sure it's in range #endif if(ed == (edict_t *)sv.edicts && sv.state == ss_active) { PR_RunError("assignment to world entity"); } ed->v.nextthink = pr_global_struct->time+b->_float; break; case OP_BITSET: // f (+) f b->_float = (int)b->_float | (int)a->_float; break; case OP_BITSETP: // e.f (+) f ptr = (eval_t *)((byte *)sv.edicts+b->_int); ptr->_float = (int)ptr->_float | (int)a->_float; break; case OP_BITCLR: // f (-) f b->_float = (int)b->_float & ~((int)a->_float); break; case OP_BITCLRP: // e.f (-) f ptr = (eval_t *)((byte *)sv.edicts+b->_int); ptr->_float = (int)ptr->_float & ~((int)a->_float); break; case OP_RAND0: val = rand()*(1.0/RAND_MAX);//(rand()&0x7fff)/((float)0x7fff); G_FLOAT(OFS_RETURN) = val; break; case OP_RAND1: val = rand()*(1.0/RAND_MAX)*a->_float; G_FLOAT(OFS_RETURN) = val; break; case OP_RAND2: if(a->_float < b->_float) { val = a->_float+(rand()*(1.0/RAND_MAX) *(b->_float-a->_float)); } else { val = b->_float+(rand()*(1.0/RAND_MAX) *(a->_float-b->_float)); } G_FLOAT(OFS_RETURN) = val; break; case OP_RANDV0: val = rand()*(1.0/RAND_MAX); G_FLOAT(OFS_RETURN+0) = val; val = rand()*(1.0/RAND_MAX); G_FLOAT(OFS_RETURN+1) = val; val = rand()*(1.0/RAND_MAX); G_FLOAT(OFS_RETURN+2) = val; break; case OP_RANDV1: val = rand()*(1.0/RAND_MAX)*a->vector[0]; G_FLOAT(OFS_RETURN+0) = val; val = rand()*(1.0/RAND_MAX)*a->vector[1]; G_FLOAT(OFS_RETURN+1) = val; val = rand()*(1.0/RAND_MAX)*a->vector[2]; G_FLOAT(OFS_RETURN+2) = val; break; case OP_RANDV2: for(i = 0; i < 3; i++) { if(a->vector[i] < b->vector[i]) { val = a->vector[i]+(rand()*(1.0/RAND_MAX) *(b->vector[i]-a->vector[i])); } else { val = b->vector[i]+(rand()*(1.0/RAND_MAX) *(a->vector[i]-b->vector[i])); } G_FLOAT(OFS_RETURN+i) = val; } break; case OP_SWITCH_F: case_type = SWITCH_F; switch_float = a->_float; s += st->b-1; // -1 to offset the s++ break; case OP_SWITCH_V: PR_RunError("switch v not done yet!"); break; case OP_SWITCH_S: PR_RunError("switch s not done yet!"); break; case OP_SWITCH_E: PR_RunError("switch e not done yet!"); break; case OP_SWITCH_FNC: PR_RunError("switch fnc not done yet!"); break; case OP_CASERANGE: if (case_type!=SWITCH_F) PR_RunError("caserange f****d!"); if((switch_float >= a->_float) && (switch_float <= b->_float)) { s += st->c-1; // -1 to offset the s++ } break; case OP_CASE: switch (case_type) { case SWITCH_F: if(switch_float == a->_float) { s += st->b-1; // -1 to offset the s++ } break; case SWITCH_V: case SWITCH_S: case SWITCH_E: case SWITCH_FNC: PR_RunError("case not done yet!"); break; default: PR_RunError("f****d case!"); } break; default: PR_RunError("Bad opcode %i", st->op); } } }
void PR_ExecuteProgram (func_t fnum) { eval_t *ptr, *a, *b, *c; float *vecptr; dstatement_t *st; dfunction_t *f, *newf; edict_t *ed; int jump_ofs; int exitdepth; int profile, startprofile; /* switch/case support: */ int case_type = -1; float switch_float = 0; if (!fnum || fnum >= progs->numfunctions) { if (*sv_globals.self) { ED_Print(PROG_TO_EDICT(*sv_globals.self)); } Host_Error("%s: NULL function", __thisfunc__); } f = &pr_functions[fnum]; pr_trace = false; exitdepth = pr_depth; st = &pr_statements[EnterFunction(f)]; startprofile = profile = 0; while (1) { st++; /* next statement */ a = OPA; b = OPB; c = OPC; if (++profile > 100000) { pr_xstatement = st - pr_statements; PR_RunError("runaway loop error"); } if (pr_trace) { PrintStatement(st); } switch (st->op) { case OP_ADD_F: c->_float = a->_float + b->_float; break; case OP_ADD_V: c->vector[0] = a->vector[0] + b->vector[0]; c->vector[1] = a->vector[1] + b->vector[1]; c->vector[2] = a->vector[2] + b->vector[2]; break; case OP_SUB_F: c->_float = a->_float - b->_float; break; case OP_SUB_V: c->vector[0] = a->vector[0] - b->vector[0]; c->vector[1] = a->vector[1] - b->vector[1]; c->vector[2] = a->vector[2] - b->vector[2]; break; case OP_MUL_F: c->_float = a->_float * b->_float; break; case OP_MUL_V: c->_float = a->vector[0] * b->vector[0] + a->vector[1] * b->vector[1] + a->vector[2] * b->vector[2]; break; case OP_MUL_FV: c->vector[0] = a->_float * b->vector[0]; c->vector[1] = a->_float * b->vector[1]; c->vector[2] = a->_float * b->vector[2]; break; case OP_MUL_VF: c->vector[0] = b->_float * a->vector[0]; c->vector[1] = b->_float * a->vector[1]; c->vector[2] = b->_float * a->vector[2]; break; case OP_DIV_F: c->_float = a->_float / b->_float; break; case OP_BITAND: c->_float = (int)a->_float & (int)b->_float; break; case OP_BITOR: c->_float = (int)a->_float | (int)b->_float; break; case OP_GE: c->_float = a->_float >= b->_float; break; case OP_LE: c->_float = a->_float <= b->_float; break; case OP_GT: c->_float = a->_float > b->_float; break; case OP_LT: c->_float = a->_float < b->_float; break; case OP_AND: c->_float = a->_float && b->_float; break; case OP_OR: c->_float = a->_float || b->_float; break; case OP_NOT_F: c->_float = !a->_float; break; case OP_NOT_V: c->_float = !a->vector[0] && !a->vector[1] && !a->vector[2]; break; case OP_NOT_S: c->_float = !a->string || !*PR_GetString(a->string); break; case OP_NOT_FNC: c->_float = !a->function; break; case OP_NOT_ENT: c->_float = (PROG_TO_EDICT(a->edict) == sv.edicts); break; case OP_EQ_F: c->_float = a->_float == b->_float; break; case OP_EQ_V: c->_float = (a->vector[0] == b->vector[0]) && (a->vector[1] == b->vector[1]) && (a->vector[2] == b->vector[2]); break; case OP_EQ_S: c->_float = !strcmp(PR_GetString(a->string), PR_GetString(b->string)); break; case OP_EQ_E: c->_float = a->_int == b->_int; break; case OP_EQ_FNC: c->_float = a->function == b->function; break; case OP_NE_F: c->_float = a->_float != b->_float; break; case OP_NE_V: c->_float = (a->vector[0] != b->vector[0]) || (a->vector[1] != b->vector[1]) || (a->vector[2] != b->vector[2]); break; case OP_NE_S: c->_float = strcmp(PR_GetString(a->string), PR_GetString(b->string)); break; case OP_NE_E: c->_float = a->_int != b->_int; break; case OP_NE_FNC: c->_float = a->function != b->function; break; case OP_STORE_F: case OP_STORE_ENT: case OP_STORE_FLD: // integers case OP_STORE_S: case OP_STORE_FNC: // pointers b->_int = a->_int; break; case OP_STORE_V: b->vector[0] = a->vector[0]; b->vector[1] = a->vector[1]; b->vector[2] = a->vector[2]; break; case OP_STOREP_F: case OP_STOREP_ENT: case OP_STOREP_FLD: // integers case OP_STOREP_S: case OP_STOREP_FNC: // pointers ptr = (eval_t *)((byte *)sv.edicts + b->_int); ptr->_int = a->_int; break; case OP_STOREP_V: ptr = (eval_t *)((byte *)sv.edicts + b->_int); ptr->vector[0] = a->vector[0]; ptr->vector[1] = a->vector[1]; ptr->vector[2] = a->vector[2]; break; case OP_MULSTORE_F: // f *= f b->_float *= a->_float; break; case OP_MULSTORE_V: // v *= f b->vector[0] *= a->_float; b->vector[1] *= a->_float; b->vector[2] *= a->_float; break; case OP_MULSTOREP_F: // e.f *= f ptr = (eval_t *)((byte *)sv.edicts + b->_int); c->_float = (ptr->_float *= a->_float); break; case OP_MULSTOREP_V: // e.v *= f ptr = (eval_t *)((byte *)sv.edicts + b->_int); c->vector[0] = (ptr->vector[0] *= a->_float); c->vector[0] = (ptr->vector[1] *= a->_float); c->vector[0] = (ptr->vector[2] *= a->_float); break; case OP_DIVSTORE_F: // f /= f b->_float /= a->_float; break; case OP_DIVSTOREP_F: // e.f /= f ptr = (eval_t *)((byte *)sv.edicts + b->_int); c->_float = (ptr->_float /= a->_float); break; case OP_ADDSTORE_F: // f += f b->_float += a->_float; break; case OP_ADDSTORE_V: // v += v b->vector[0] += a->vector[0]; b->vector[1] += a->vector[1]; b->vector[2] += a->vector[2]; break; case OP_ADDSTOREP_F: // e.f += f ptr = (eval_t *)((byte *)sv.edicts + b->_int); c->_float = (ptr->_float += a->_float); break; case OP_ADDSTOREP_V: // e.v += v ptr = (eval_t *)((byte *)sv.edicts + b->_int); c->vector[0] = (ptr->vector[0] += a->vector[0]); c->vector[1] = (ptr->vector[1] += a->vector[1]); c->vector[2] = (ptr->vector[2] += a->vector[2]); break; case OP_SUBSTORE_F: // f -= f b->_float -= a->_float; break; case OP_SUBSTORE_V: // v -= v b->vector[0] -= a->vector[0]; b->vector[1] -= a->vector[1]; b->vector[2] -= a->vector[2]; break; case OP_SUBSTOREP_F: // e.f -= f ptr = (eval_t *)((byte *)sv.edicts + b->_int); c->_float = (ptr->_float -= a->_float); break; case OP_SUBSTOREP_V: // e.v -= v ptr = (eval_t *)((byte *)sv.edicts + b->_int); c->vector[0] = (ptr->vector[0] -= a->vector[0]); c->vector[1] = (ptr->vector[1] -= a->vector[1]); c->vector[2] = (ptr->vector[2] -= a->vector[2]); break; case OP_ADDRESS: ed = PROG_TO_EDICT(a->edict); #ifdef PARANOID NUM_FOR_EDICT(ed); // Make sure it's in range #endif if (ed == (edict_t *)sv.edicts && sv.state == ss_active) { pr_xstatement = st - pr_statements; PR_RunError("assignment to world entity"); } c->_int = (byte *)((int *)&ed->v + b->_int) - (byte *)sv.edicts; break; case OP_LOAD_F: case OP_LOAD_FLD: case OP_LOAD_ENT: case OP_LOAD_S: case OP_LOAD_FNC: ed = PROG_TO_EDICT(a->edict); #ifdef PARANOID NUM_FOR_EDICT(ed); // Make sure it's in range #endif ptr = (eval_t *)((int *)&ed->v + b->_int); c->_int = ptr->_int; break; case OP_LOAD_V: ed = PROG_TO_EDICT(a->edict); #ifdef PARANOID NUM_FOR_EDICT(ed); // Make sure it's in range #endif ptr = (eval_t *)((int *)&ed->v + b->_int); c->vector[0] = ptr->vector[0]; c->vector[1] = ptr->vector[1]; c->vector[2] = ptr->vector[2]; break; case OP_FETCH_GBL_F: case OP_FETCH_GBL_S: case OP_FETCH_GBL_E: case OP_FETCH_GBL_FNC: { int i = (int)b->_float; if (i < 0 || i > G_INT(st->a - 1)) { pr_xstatement = st - pr_statements; PR_RunError("array index out of bounds: %d", i); } ptr = (eval_t *)&pr_globals[st->a + i]; c->_int = ptr->_int; } break; case OP_FETCH_GBL_V: { int i = (int)b->_float; if (i < 0 || i > G_INT(st->a - 1)) { pr_xstatement = st - pr_statements; PR_RunError("array index out of bounds: %d", i); } ptr = (eval_t *)&pr_globals[st->a + (i * 3)]; c->vector[0] = ptr->vector[0]; c->vector[1] = ptr->vector[1]; c->vector[2] = ptr->vector[2]; } break; case OP_IFNOT: if (!a->_int) { /* Pa3PyX: a, b, and c used to be signed shorts for progs v6, * now they are signed ints. The problem is, they were used * as signed sometimes and as unsigned other times - most of * the time they were used as unsigned with an explicit cast * in PR_ExecuteProgram(). When we convert the old progs to * to the new format in PR_ConvertOldStmts(), we zero-extend * them instead of sign-extending them for that reason: if we * sign-extend them, most of the code will not work - we will * have negative array offsets in PR_ExecuteProgram(), among * other things. Note that they are cast to unsigned short * in PR_ConvertOldStmts() prior to assigning them to what is * now int. There are a few instances where these shorts are * used as signed as in the case below where negative offsets * are needed. Since we now have a zero-extended number in a, * b, and c, we must change it back to signed short, so that * when it is added with and assigned to an int, the result * ends up sign-extended and we get a proper negative offset, * if there is one. */ jump_ofs = st->b; if (is_progs_v6) jump_ofs = (signed short)jump_ofs; st += jump_ofs - 1; /* -1 to offset the st++ */ } break; case OP_IF: if (a->_int) { jump_ofs = st->b; if (is_progs_v6) jump_ofs = (signed short)jump_ofs; st += jump_ofs - 1; /* -1 to offset the st++ */ } break; case OP_GOTO: jump_ofs = st->a; if (is_progs_v6) jump_ofs = (signed short)jump_ofs; st += jump_ofs - 1; /* -1 to offset the st++ */ break; case OP_CALL8: case OP_CALL7: case OP_CALL6: case OP_CALL5: case OP_CALL4: case OP_CALL3: case OP_CALL2: // Copy second arg to shared space vecptr = G_VECTOR(OFS_PARM1); VectorCopy(c->vector, vecptr); case OP_CALL1: // Copy first arg to shared space vecptr = G_VECTOR(OFS_PARM0); VectorCopy(b->vector, vecptr); case OP_CALL0: pr_xfunction->profile += profile - startprofile; startprofile = profile; pr_xstatement = st - pr_statements; pr_argc = st->op - OP_CALL0; if (!a->function) { PR_RunError("NULL function"); } newf = &pr_functions[a->function]; if (newf->first_statement < 0) { // Built-in function int i = -newf->first_statement; if (i >= pr_numbuiltins) { PR_RunError("Bad builtin call number %d", i); } pr_builtins[i](); break; } // Normal function st = &pr_statements[EnterFunction(newf)]; break; case OP_DONE: case OP_RETURN: { float *retptr = &pr_globals[OFS_RETURN]; float *valptr = &pr_globals[st->a]; pr_xfunction->profile += profile - startprofile; startprofile = profile; pr_xstatement = st - pr_statements; *retptr++ = *valptr++; *retptr++ = *valptr++; *retptr = *valptr; st = &pr_statements[LeaveFunction()]; if (pr_depth == exitdepth) { // Done return; } } break; case OP_STATE: ed = PROG_TO_EDICT(*sv_globals.self); /* Id 1.07 changes #ifdef FPS_20 ed->v.nextthink = *sv_globals.time + 0.05; #else ed->v.nextthink = *sv_globals.time + 0.1; #endif */ ed->v.nextthink = *sv_globals.time + HX_FRAME_TIME; ed->v.frame = a->_float; ed->v.think = b->function; break; case OP_CSTATE: // Cycle state { int startFrame, endFrame; ed = PROG_TO_EDICT(*sv_globals.self); ed->v.nextthink = *sv_globals.time + HX_FRAME_TIME; ed->v.think = pr_xfunction - pr_functions; *sv_globals.cycle_wrapped = false; startFrame = (int)a->_float; endFrame = (int)b->_float; if (startFrame <= endFrame) { // Increment if (ed->v.frame < startFrame || ed->v.frame > endFrame) { ed->v.frame = startFrame; } else { ed->v.frame++; if (ed->v.frame > endFrame) { *sv_globals.cycle_wrapped = true; ed->v.frame = startFrame; } } } else { // Decrement if (ed->v.frame > startFrame || ed->v.frame < endFrame) { ed->v.frame = startFrame; } else { ed->v.frame--; if (ed->v.frame < endFrame) { *sv_globals.cycle_wrapped = true; ed->v.frame = startFrame; } } } } break; case OP_CWSTATE: // Cycle weapon state { int startFrame, endFrame; ed = PROG_TO_EDICT(*sv_globals.self); ed->v.nextthink = *sv_globals.time + HX_FRAME_TIME; ed->v.think = pr_xfunction - pr_functions; *sv_globals.cycle_wrapped = false; startFrame = (int)a->_float; endFrame = (int)b->_float; if (startFrame <= endFrame) { // Increment if (ed->v.weaponframe < startFrame || ed->v.weaponframe > endFrame) { ed->v.weaponframe = startFrame; } else { ed->v.weaponframe++; if (ed->v.weaponframe > endFrame) { *sv_globals.cycle_wrapped = true; ed->v.weaponframe = startFrame; } } } else { // Decrement if (ed->v.weaponframe > startFrame || ed->v.weaponframe < endFrame) { ed->v.weaponframe = startFrame; } else { ed->v.weaponframe--; if (ed->v.weaponframe < endFrame) { *sv_globals.cycle_wrapped = true; ed->v.weaponframe = startFrame; } } } } break; case OP_THINKTIME: ed = PROG_TO_EDICT(a->edict); #ifdef PARANOID NUM_FOR_EDICT(ed); // Make sure it's in range #endif if (ed == (edict_t *)sv.edicts && sv.state == ss_active) { pr_xstatement = st - pr_statements; PR_RunError("assignment to world entity"); } ed->v.nextthink = *sv_globals.time + b->_float; break; case OP_BITSET: // f (+) f b->_float = (int)b->_float | (int)a->_float; break; case OP_BITSETP: // e.f (+) f ptr = (eval_t *)((byte *)sv.edicts + b->_int); ptr->_float = (int)ptr->_float | (int)a->_float; break; case OP_BITCLR: // f (-) f b->_float = (int)b->_float & ~((int)a->_float); break; case OP_BITCLRP: // e.f (-) f ptr = (eval_t *)((byte *)sv.edicts + b->_int); ptr->_float = (int)ptr->_float & ~((int)a->_float); break; case OP_RAND0: { float val; val = rand() * (1.0 / RAND_MAX); G_FLOAT(OFS_RETURN) = val; } break; case OP_RAND1: { float val; val = rand() * (1.0 / RAND_MAX) * a->_float; G_FLOAT(OFS_RETURN) = val; } break; case OP_RAND2: { float val; if (a->_float < b->_float) { val = a->_float + (rand() * (1.0 / RAND_MAX) * (b->_float - a->_float)); } else { val = b->_float + (rand() * (1.0 / RAND_MAX) * (a->_float - b->_float)); } G_FLOAT(OFS_RETURN) = val; } break; case OP_RANDV0: { float val; float *retptr = &G_FLOAT(OFS_RETURN); val = rand() * (1.0 / RAND_MAX); *retptr++ = val; val = rand() * (1.0 / RAND_MAX); *retptr++ = val; val = rand() * (1.0 / RAND_MAX); *retptr = val; } break; case OP_RANDV1: { float val; float *retptr = &G_FLOAT(OFS_RETURN); val = rand() * (1.0 / RAND_MAX) * a->vector[0]; *retptr++ = val; val = rand() * (1.0 / RAND_MAX) * a->vector[1]; *retptr++ = val; val = rand() * (1.0 / RAND_MAX) * a->vector[2]; *retptr = val; } break; case OP_RANDV2: { float val; int i; float *retptr = &G_FLOAT(OFS_RETURN); for (i = 0; i < 3; i++) { if (a->vector[i] < b->vector[i]) { val = a->vector[i] + (rand() * (1.0 / RAND_MAX) * (b->vector[i] - a->vector[i])); } else { val = b->vector[i] + (rand() * (1.0 / RAND_MAX) * (a->vector[i] - b->vector[i])); } *retptr++ = val; } } break; case OP_SWITCH_F: case_type = SWITCH_F; switch_float = a->_float; jump_ofs = st->b; if (is_progs_v6) jump_ofs = (signed short)jump_ofs; st += jump_ofs - 1; /* -1 to offset the st++ */ break; case OP_SWITCH_V: case OP_SWITCH_S: case OP_SWITCH_E: case OP_SWITCH_FNC: pr_xstatement = st - pr_statements; PR_RunError("%s not done yet!", pr_opnames[st->op]); break; case OP_CASERANGE: if (case_type != SWITCH_F) { pr_xstatement = st - pr_statements; PR_RunError("caserange f****d!"); } if ((switch_float >= a->_float) && (switch_float <= b->_float)) { jump_ofs = st->c; if (is_progs_v6) jump_ofs = (signed short)jump_ofs; st += jump_ofs - 1; /* -1 to offset the st++ */ } break; case OP_CASE: switch (case_type) { case SWITCH_F: if (switch_float == a->_float) { jump_ofs = st->b; if (is_progs_v6) jump_ofs = (signed short)jump_ofs; st += jump_ofs - 1; /* -1 to offset the st++ */ } break; case SWITCH_V: case SWITCH_S: case SWITCH_E: case SWITCH_FNC: pr_xstatement = st - pr_statements; PR_RunError("OP_CASE for %s not done yet!", pr_opnames[case_type + OP_SWITCH_F - SWITCH_F]); break; default: pr_xstatement = st - pr_statements; PR_RunError("f****d case!"); } break; default: pr_xstatement = st - pr_statements; PR_RunError("Bad opcode %i", st->op); } } /* end of while(1) loop */ }
/* ==================== PR_ExecuteProgram ==================== */ void PR_ExecuteProgram (func_t fnum) { eval_t *a, *b, *c; int s; dstatement_t *st; dfunction_t *f, *newf; int runaway; int i; edict_t *ed; int exitdepth; eval_t *ptr; if (!fnum || fnum >= progs->numfunctions) { if (pr_global_struct->self) ED_Print (PROG_TO_EDICT(pr_global_struct->self)); Host_Error ("PR_ExecuteProgram: NULL function"); } f = &pr_functions[fnum]; runaway = 100000; pr_trace = false; // make a stack frame exitdepth = pr_depth; s = PR_EnterFunction (f); while (1) { s++; // next statement st = &pr_statements[s]; a = (eval_t *)&pr_globals[st->a]; b = (eval_t *)&pr_globals[st->b]; c = (eval_t *)&pr_globals[st->c]; if (!--runaway) PR_RunError ("runaway loop error"); pr_xfunction->profile++; pr_xstatement = s; if (pr_trace) PR_PrintStatement (st); switch (st->op) { case OP_ADD_F: c->_float = a->_float + b->_float; break; case OP_ADD_V: c->vector[0] = a->vector[0] + b->vector[0]; c->vector[1] = a->vector[1] + b->vector[1]; c->vector[2] = a->vector[2] + b->vector[2]; break; case OP_SUB_F: c->_float = a->_float - b->_float; break; case OP_SUB_V: c->vector[0] = a->vector[0] - b->vector[0]; c->vector[1] = a->vector[1] - b->vector[1]; c->vector[2] = a->vector[2] - b->vector[2]; break; case OP_MUL_F: c->_float = a->_float * b->_float; break; case OP_MUL_V: c->_float = a->vector[0]*b->vector[0] + a->vector[1]*b->vector[1] + a->vector[2]*b->vector[2]; break; case OP_MUL_FV: c->vector[0] = a->_float * b->vector[0]; c->vector[1] = a->_float * b->vector[1]; c->vector[2] = a->_float * b->vector[2]; break; case OP_MUL_VF: c->vector[0] = b->_float * a->vector[0]; c->vector[1] = b->_float * a->vector[1]; c->vector[2] = b->_float * a->vector[2]; break; case OP_DIV_F: c->_float = a->_float / b->_float; break; case OP_BITAND: c->_float = (int)a->_float & (int)b->_float; break; case OP_BITOR: c->_float = (int)a->_float | (int)b->_float; break; case OP_GE: c->_float = a->_float >= b->_float; break; case OP_LE: c->_float = a->_float <= b->_float; break; case OP_GT: c->_float = a->_float > b->_float; break; case OP_LT: c->_float = a->_float < b->_float; break; case OP_AND: c->_float = a->_float && b->_float; break; case OP_OR: c->_float = a->_float || b->_float; break; case OP_NOT_F: c->_float = !a->_float; break; case OP_NOT_V: c->_float = !a->vector[0] && !a->vector[1] && !a->vector[2]; break; case OP_NOT_S: c->_float = !a->string || !pr_strings[a->string]; break; case OP_NOT_FNC: c->_float = !a->function; break; case OP_NOT_ENT: c->_float = (PROG_TO_EDICT(a->edict) == sv.edicts); break; case OP_EQ_F: c->_float = a->_float == b->_float; break; case OP_EQ_V: c->_float = (a->vector[0] == b->vector[0]) && (a->vector[1] == b->vector[1]) && (a->vector[2] == b->vector[2]); break; case OP_EQ_S: c->_float = !strcmp(pr_strings+a->string,pr_strings+b->string); break; case OP_EQ_E: c->_float = a->_int == b->_int; break; case OP_EQ_FNC: c->_float = a->function == b->function; break; case OP_NE_F: c->_float = a->_float != b->_float; break; case OP_NE_V: c->_float = (a->vector[0] != b->vector[0]) || (a->vector[1] != b->vector[1]) || (a->vector[2] != b->vector[2]); break; case OP_NE_S: c->_float = strcmp(pr_strings+a->string,pr_strings+b->string); break; case OP_NE_E: c->_float = a->_int != b->_int; break; case OP_NE_FNC: c->_float = a->function != b->function; break; //================== case OP_STORE_F: case OP_STORE_ENT: case OP_STORE_FLD: // integers case OP_STORE_S: case OP_STORE_FNC: // pointers b->_int = a->_int; break; case OP_STORE_V: b->vector[0] = a->vector[0]; b->vector[1] = a->vector[1]; b->vector[2] = a->vector[2]; break; case OP_STOREP_F: case OP_STOREP_ENT: case OP_STOREP_FLD: // integers case OP_STOREP_S: case OP_STOREP_FNC: // pointers ptr = (eval_t *)((byte *)sv.edicts + b->_int); ptr->_int = a->_int; break; case OP_STOREP_V: ptr = (eval_t *)((byte *)sv.edicts + b->_int); ptr->vector[0] = a->vector[0]; ptr->vector[1] = a->vector[1]; ptr->vector[2] = a->vector[2]; break; case OP_ADDRESS: ed = PROG_TO_EDICT(a->edict); #ifdef PARANOID NUM_FOR_EDICT(ed); // make sure it's in range #endif if (ed == (edict_t *)sv.edicts && sv.state == ss_active) PR_RunError ("assignment to world entity"); c->_int = (byte *)((int *)&ed->v + b->_int) - (byte *)sv.edicts; break; case OP_LOAD_F: case OP_LOAD_FLD: case OP_LOAD_ENT: case OP_LOAD_S: case OP_LOAD_FNC: ed = PROG_TO_EDICT(a->edict); #ifdef PARANOID NUM_FOR_EDICT(ed); // make sure it's in range #endif a = (eval_t *)((int *)&ed->v + b->_int); c->_int = a->_int; break; case OP_LOAD_V: ed = PROG_TO_EDICT(a->edict); #ifdef PARANOID NUM_FOR_EDICT(ed); // make sure it's in range #endif a = (eval_t *)((int *)&ed->v + b->_int); c->vector[0] = a->vector[0]; c->vector[1] = a->vector[1]; c->vector[2] = a->vector[2]; break; //================== case OP_IFNOT: if (!a->_int) s += st->b - 1; // offset the s++ break; case OP_IF: if (a->_int) s += st->b - 1; // offset the s++ break; case OP_GOTO: s += st->a - 1; // offset the s++ break; case OP_CALL0: case OP_CALL1: case OP_CALL2: case OP_CALL3: case OP_CALL4: case OP_CALL5: case OP_CALL6: case OP_CALL7: case OP_CALL8: pr_argc = st->op - OP_CALL0; if (!a->function) PR_RunError ("NULL function"); newf = &pr_functions[a->function]; if (newf->first_statement < 0) { // negative statements are built in functions i = -newf->first_statement; if (i >= pr_numbuiltins) PR_RunError ("Bad builtin call number"); pr_builtins[i] (); break; } s = PR_EnterFunction (newf); break; case OP_DONE: case OP_RETURN: pr_globals[OFS_RETURN] = pr_globals[st->a]; pr_globals[OFS_RETURN+1] = pr_globals[st->a+1]; pr_globals[OFS_RETURN+2] = pr_globals[st->a+2]; s = PR_LeaveFunction (); if (pr_depth == exitdepth) return; // all done break; case OP_STATE: ed = PROG_TO_EDICT(pr_global_struct->self); #ifdef FPS_20 ed->v.nextthink = pr_global_struct->time + 0.05; #else ed->v.nextthink = pr_global_struct->time + 0.1; #endif if (a->_float != ed->v.frame) { ed->v.frame = a->_float; } ed->v.think = b->function; break; default: PR_RunError ("Bad opcode %i", st->op); } } }
void PR_ExecuteProgram (progs_t *pr, func_t fnum) { dstatement_t *st; dfunction_t *f, *newf; edict_t *ed; int exitdepth; eval_t *ptr; int profile, startprofile; if (!fnum || fnum >= pr->progs->numfunctions) { if (pr->pr_global_struct->self) ED_Print (pr, PROG_TO_EDICT (pr, pr->pr_global_struct->self)); SV_Error ("PR_ExecuteProgram: NULL function"); } f = &pr->pr_functions[fnum]; pr->pr_trace = false; // make a stack frame exitdepth = pr->pr_depth; st = &pr->pr_statements[PR_EnterFunction (pr, f)]; startprofile = profile = 0; while (1) { st++; if (++profile > 1000000) // LordHavoc: increased runaway loop // limit 10x { pr->pr_xstatement = st - pr->pr_statements; PR_RunError (pr, "runaway loop error"); } if (pr->pr_trace) PR_PrintStatement (pr, st); switch (st->op) { case OP_ADD_F: OPC->_float = OPA->_float + OPB->_float; break; case OP_ADD_V: OPC->vector[0] = OPA->vector[0] + OPB->vector[0]; OPC->vector[1] = OPA->vector[1] + OPB->vector[1]; OPC->vector[2] = OPA->vector[2] + OPB->vector[2]; break; case OP_SUB_F: OPC->_float = OPA->_float - OPB->_float; break; case OP_SUB_V: OPC->vector[0] = OPA->vector[0] - OPB->vector[0]; OPC->vector[1] = OPA->vector[1] - OPB->vector[1]; OPC->vector[2] = OPA->vector[2] - OPB->vector[2]; break; case OP_MUL_F: OPC->_float = OPA->_float * OPB->_float; break; case OP_MUL_V: OPC->_float = OPA->vector[0] * OPB->vector[0] + OPA->vector[1] * OPB->vector[1] + OPA->vector[2] * OPB->vector[2]; break; case OP_MUL_FV: OPC->vector[0] = OPA->_float * OPB->vector[0]; OPC->vector[1] = OPA->_float * OPB->vector[1]; OPC->vector[2] = OPA->_float * OPB->vector[2]; break; case OP_MUL_VF: OPC->vector[0] = OPB->_float * OPA->vector[0]; OPC->vector[1] = OPB->_float * OPA->vector[1]; OPC->vector[2] = OPB->_float * OPA->vector[2]; break; case OP_DIV_F: OPC->_float = OPA->_float / OPB->_float; break; case OP_BITAND: OPC->_float = (int) OPA->_float & (int) OPB->_float; break; case OP_BITOR: OPC->_float = (int) OPA->_float | (int) OPB->_float; break; case OP_GE: OPC->_float = OPA->_float >= OPB->_float; break; case OP_LE: OPC->_float = OPA->_float <= OPB->_float; break; case OP_GT: OPC->_float = OPA->_float > OPB->_float; break; case OP_LT: OPC->_float = OPA->_float < OPB->_float; break; case OP_AND: OPC->_float = OPA->_float && OPB->_float; break; case OP_OR: OPC->_float = OPA->_float || OPB->_float; break; case OP_NOT_F: OPC->_float = !OPA->_float; break; case OP_NOT_V: OPC->_float = VectorIsNull(OPA->vector); break; case OP_NOT_S: OPC->_float = !OPA->string || !*PR_GetString (pr, OPA->string); break; case OP_NOT_FNC: OPC->_float = !OPA->function; break; case OP_NOT_ENT: OPC->_float = (PROG_TO_EDICT (pr, OPA->edict) == *pr->edicts); break; case OP_EQ_F: OPC->_float = OPA->_float == OPB->_float; break; case OP_EQ_V: OPC->_float = (OPA->vector[0] == OPB->vector[0]) && (OPA->vector[1] == OPB->vector[1]) && (OPA->vector[2] == OPB->vector[2]); break; case OP_EQ_S: OPC->_float = !strcmp (PR_GetString (pr, OPA->string), PR_GetString (pr, OPB->string)); break; case OP_EQ_E: OPC->_float = OPA->_int == OPB->_int; break; case OP_EQ_FNC: OPC->_float = OPA->function == OPB->function; break; case OP_NE_F: OPC->_float = OPA->_float != OPB->_float; break; case OP_NE_V: OPC->_float = (OPA->vector[0] != OPB->vector[0]) || (OPA->vector[1] != OPB->vector[1]) || (OPA->vector[2] != OPB->vector[2]); break; case OP_NE_S: OPC->_float = strcmp (PR_GetString (pr, OPA->string), PR_GetString (pr, OPB->string)); break; case OP_NE_E: OPC->_float = OPA->_int != OPB->_int; break; case OP_NE_FNC: OPC->_float = OPA->function != OPB->function; break; // ================== case OP_STORE_F: case OP_STORE_ENT: case OP_STORE_FLD: // integers case OP_STORE_S: case OP_STORE_FNC: // pointers OPB->_int = OPA->_int; break; case OP_STORE_V: OPB->vector[0] = OPA->vector[0]; OPB->vector[1] = OPA->vector[1]; OPB->vector[2] = OPA->vector[2]; break; case OP_STOREP_F: case OP_STOREP_ENT: case OP_STOREP_FLD: // integers case OP_STOREP_S: case OP_STOREP_FNC: // pointers if (pr_boundscheck->int_val && (OPB->_int < 0 || OPB->_int + 4 > pr->pr_edictareasize)) { pr->pr_xstatement = st - pr->pr_statements; PR_RunError (pr, "Progs attempted to write to an out of bounds edict\n"); return; } if (pr_boundscheck->int_val && (OPB->_int % pr->pr_edict_size < ((byte *) & (*pr->edicts)->v - (byte *) *pr->edicts))) { pr->pr_xstatement = st - pr->pr_statements; PR_RunError (pr, "Progs attempted to write to an engine edict field\n"); return; } ptr = (eval_t *) ((byte *) *pr->edicts + OPB->_int); ptr->_int = OPA->_int; break; case OP_STOREP_V: if (pr_boundscheck->int_val && (OPB->_int < 0 || OPB->_int + 12 > pr->pr_edictareasize)) { pr->pr_xstatement = st - pr->pr_statements; PR_RunError (pr, "Progs attempted to write to an out of bounds edict\n"); return; } ptr = (eval_t *) ((byte *) *pr->edicts + OPB->_int); ptr->vector[0] = OPA->vector[0]; ptr->vector[1] = OPA->vector[1]; ptr->vector[2] = OPA->vector[2]; break; case OP_ADDRESS: if (pr_boundscheck->int_val && (OPA->edict < 0 || OPA->edict >= pr->pr_edictareasize)) { pr->pr_xstatement = st - pr->pr_statements; PR_RunError (pr, "Progs attempted to address an out of bounds edict\n"); return; } if (pr_boundscheck->int_val && (OPA->edict == 0 && pr->null_bad)) { pr->pr_xstatement = st - pr->pr_statements; PR_RunError (pr, "assignment to world entity"); return; } if (pr_boundscheck->int_val && (OPB->_int < 0 || OPB->_int >= pr->progs->entityfields)) { pr->pr_xstatement = st - pr->pr_statements; PR_RunError (pr, "Progs attempted to address an invalid field in an edict\n"); return; } ed = PROG_TO_EDICT (pr, OPA->edict); OPC->_int = (byte *) ((int *) &ed->v + OPB->_int) - (byte *) *pr->edicts; break; case OP_LOAD_F: case OP_LOAD_FLD: case OP_LOAD_ENT: case OP_LOAD_S: case OP_LOAD_FNC: if (pr_boundscheck->int_val && (OPA->edict < 0 || OPA->edict >= pr->pr_edictareasize)) { pr->pr_xstatement = st - pr->pr_statements; PR_RunError (pr, "Progs attempted to read an out of bounds edict number\n"); return; } if (pr_boundscheck->int_val && (OPB->_int < 0 || OPB->_int >= pr->progs->entityfields)) { pr->pr_xstatement = st - pr->pr_statements; PR_RunError (pr, "Progs attempted to read an invalid field in an edict\n"); return; } ed = PROG_TO_EDICT (pr, OPA->edict); OPC->_int = ((eval_t *) ((int *) &ed->v + OPB->_int))->_int; break; case OP_LOAD_V: if (pr_boundscheck->int_val && (OPA->edict < 0 || OPA->edict >= pr->pr_edictareasize)) { pr->pr_xstatement = st - pr->pr_statements; PR_RunError (pr, "Progs attempted to read an out of bounds edict number\n"); return; } if (pr_boundscheck->int_val && (OPB->_int < 0 || OPB->_int + 2 >= pr->progs->entityfields)) { pr->pr_xstatement = st - pr->pr_statements; PR_RunError (pr, "Progs attempted to read an invalid field in an edict\n"); return; } ed = PROG_TO_EDICT (pr, OPA->edict); OPC->vector[0] = ((eval_t *) ((int *) &ed->v + OPB->_int))->vector[0]; OPC->vector[1] = ((eval_t *) ((int *) &ed->v + OPB->_int))->vector[1]; OPC->vector[2] = ((eval_t *) ((int *) &ed->v + OPB->_int))->vector[2]; break; // ================== case OP_IFNOT: if (!OPA->_int) st += st->b - 1; // offset the s++ break; case OP_IF: if (OPA->_int) st += st->b - 1; // offset the s++ break; case OP_GOTO: st += st->a - 1; // offset the s++ break; case OP_CALL0: case OP_CALL1: case OP_CALL2: case OP_CALL3: case OP_CALL4: case OP_CALL5: case OP_CALL6: case OP_CALL7: case OP_CALL8: pr->pr_xfunction->profile += profile - startprofile; startprofile = profile; pr->pr_xstatement = st - pr->pr_statements; pr->pr_argc = st->op - OP_CALL0; if (!OPA->function) PR_RunError (pr, "NULL function"); newf = &pr->pr_functions[OPA->function]; if (newf->first_statement < 0) { // negative // statements are // built in functions int i = -newf->first_statement; if (i >= pr_numbuiltins) PR_RunError (pr, "Bad builtin call number"); pr_builtins[i] (pr); break; } st = &pr->pr_statements[PR_EnterFunction (pr, newf)]; break; case OP_DONE: case OP_RETURN: pr->pr_globals[OFS_RETURN] = pr->pr_globals[(unsigned short) st->a]; pr->pr_globals[OFS_RETURN + 1] = pr->pr_globals[(unsigned short) st->a + 1]; pr->pr_globals[OFS_RETURN + 2] = pr->pr_globals[(unsigned short) st->a + 2]; st = &pr->pr_statements[PR_LeaveFunction (pr)]; if (pr->pr_depth == exitdepth) return; // all done break; case OP_STATE: ed = PROG_TO_EDICT (pr, pr->pr_global_struct->self); ed->v.v.nextthink = pr->pr_global_struct->time + 0.1; ed->v.v.frame = OPA->_float; ed->v.v.think = OPB->function; break; // LordHavoc: to be enabled when Progs version 7 (or whatever it will be numbered) is finalized /* case OP_ADD_I: OPC->_int = OPA->_int + OPB->_int; break; case OP_ADD_IF: OPC->_int = OPA->_int + (int) OPB->_float; break; case OP_ADD_FI: OPC->_float = OPA->_float + (float) OPB->_int; break; case OP_SUB_I: OPC->_int = OPA->_int - OPB->_int; break; case OP_SUB_IF: OPC->_int = OPA->_int - (int) OPB->_float; break; case OP_SUB_FI: OPC->_float = OPA->_float - (float) OPB->_int; break; case OP_MUL_I: OPC->_int = OPA->_int * OPB->_int; break; case OP_MUL_IF: OPC->_int = OPA->_int * (int) OPB->_float; break; case OP_MUL_FI: OPC->_float = OPA->_float * (float) OPB->_int; break; case OP_MUL_VI: OPC->vector[0] = (float) OPB->_int * OPA->vector[0]; OPC->vector[1] = (float) OPB->_int * OPA->vector[1]; OPC->vector[2] = (float) OPB->_int * OPA->vector[2]; break; case OP_DIV_VF: { float temp = 1.0f / OPB->_float; OPC->vector[0] = temp * OPA->vector[0]; OPC->vector[1] = temp * OPA->vector[1]; OPC->vector[2] = temp * OPA->vector[2]; } break; case OP_DIV_I: OPC->_int = OPA->_int / OPB->_int; break; case OP_DIV_IF: OPC->_int = OPA->_int / (int) OPB->_float; break; case OP_DIV_FI: OPC->_float = OPA->_float / (float) OPB->_int; break; case OP_CONV_IF: OPC->_float = OPA->_int; break; case OP_CONV_FI: OPC->_int = OPA->_float; break; case OP_BITAND_I: OPC->_int = OPA->_int & OPB->_int; break; case OP_BITOR_I: OPC->_int = OPA->_int | OPB->_int; break; case OP_BITAND_IF: OPC->_int = OPA->_int & (int) OPB->_float; break; case OP_BITOR_IF: OPC->_int = OPA->_int | (int) OPB->_float; break; case OP_BITAND_FI: OPC->_float = (int) OPA->_float & OPB->_int; break; case OP_BITOR_FI: OPC->_float = (int) OPA->_float | OPB->_int; break; case OP_GE_I: OPC->_float = OPA->_int >= OPB->_int; break; case OP_LE_I: OPC->_float = OPA->_int <= OPB->_int; break; case OP_GT_I: OPC->_float = OPA->_int > OPB->_int; break; case OP_LT_I: OPC->_float = OPA->_int < OPB->_int; break; case OP_AND_I: OPC->_float = OPA->_int && OPB->_int; break; case OP_OR_I: OPC->_float = OPA->_int || OPB->_int; break; case OP_GE_IF: OPC->_float = (float) OPA->_int >= OPB->_float; break; case OP_LE_IF: OPC->_float = (float) OPA->_int <= OPB->_float; break; case OP_GT_IF: OPC->_float = (float) OPA->_int > OPB->_float; break; case OP_LT_IF: OPC->_float = (float) OPA->_int < OPB->_float; break; case OP_AND_IF: OPC->_float = (float) OPA->_int && OPB->_float; break; case OP_OR_IF: OPC->_float = (float) OPA->_int || OPB->_float; break; case OP_GE_FI: OPC->_float = OPA->_float >= (float) OPB->_int; break; case OP_LE_FI: OPC->_float = OPA->_float <= (float) OPB->_int; break; case OP_GT_FI: OPC->_float = OPA->_float > (float) OPB->_int; break; case OP_LT_FI: OPC->_float = OPA->_float < (float) OPB->_int; break; case OP_AND_FI: OPC->_float = OPA->_float && (float) OPB->_int; break; case OP_OR_FI: OPC->_float = OPA->_float || (float) OPB->_int; break; case OP_NOT_I: OPC->_float = !OPA->_int; break; case OP_EQ_I: OPC->_float = OPA->_int == OPB->_int; break; case OP_EQ_IF: OPC->_float = (float) OPA->_int == OPB->_float; break; case OP_EQ_FI: OPC->_float = OPA->_float == (float) OPB->_int; break; case OP_NE_I: OPC->_float = OPA->_int != OPB->_int; break; case OP_NE_IF: OPC->_float = (float) OPA->_int != OPB->_float; break; case OP_NE_FI: OPC->_float = OPA->_float != (float) OPB->_int; break; case OP_STORE_I: OPB->_int = OPA->_int; break; case OP_STOREP_I: if (pr_boundscheck->int_val && (OPB->_int < 0 || OPB->_int + 4 > pr->pr_edictareasize)) { pr->pr_xstatement = st - pr->pr_statements; PR_RunError (pr, "Progs attempted to write to an out of bounds edict\n"); return; } if (pr_boundscheck->int_val && (OPB->_int % pr->pr_edict_size < ((byte *) & (*pr->edicts)->v - (byte *) *pr->edicts))) { pr->pr_xstatement = st - pr->pr_statements; PR_RunError (pr, "Progs attempted to write to an engine edict field\n"); return; } ptr = (eval_t *) ((byte *) *pr->edicts + OPB->_int); ptr->_int = OPA->_int; break; case OP_LOAD_I: if (pr_boundscheck->int_val && (OPA->edict < 0 || OPA->edict >= pr->pr_edictareasize)) { pr->pr_xstatement = st - pr->pr_statements; PR_RunError (pr, "Progs attempted to read an out of bounds edict number\n"); return; } if (pr_boundscheck->int_val && (OPB->_int < 0 || OPB->_int >= pr->progs->entityfields)) { pr->pr_xstatement = st - pr->pr_statements; PR_RunError (pr, "Progs attempted to read an invalid field in an edict\n"); return; } ed = PROG_TO_EDICT (pr, OPA->edict); OPC->_int = ((eval_t *) ((int *) &ed->v + OPB->_int))->_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 if (pr_boundscheck->int_val && (OPB->_int < 0 || OPB->_int >= pr->pr_globaldefs)) { pr->pr_xstatement = st - pr->pr_statements; PR_RunError (pr, "Progs attempted to write to an invalid indexed global\n"); return; } pr->pr_globals[OPB->_int] = OPA->_float; break; case OP_GSTOREP_V: if (pr_boundscheck->int_val && (OPB->_int < 0 || OPB->_int + 2 >= pr->pr_globaldefs)) { pr->pr_xstatement = st - pr->pr_statements; PR_RunError (pr, "Progs attempted to write to an invalid indexed global\n"); return; } pr->pr_globals[OPB->_int] = OPA->vector[0]; pr->pr_globals[OPB->_int + 1] = OPA->vector[1]; pr->pr_globals[OPB->_int + 2] = OPA->vector[2]; break; case OP_GADDRESS: i = OPA->_int + (int) OPB->_float; if (pr_boundscheck->int_val && (i < 0 || i >= pr->pr_globaldefs)) { pr->pr_xstatement = st - pr->pr_statements; PR_RunError (pr, "Progs attempted to address an out of bounds global\n"); return; } OPC->_float = pr->pr_globals[i]; break; case OP_GLOAD_I: case OP_GLOAD_F: case OP_GLOAD_FLD: case OP_GLOAD_ENT: case OP_GLOAD_S: case OP_GLOAD_FNC: if (pr_boundscheck->int_val && (OPA->_int < 0 || OPA->_int >= pr->pr_globaldefs)) { pr->pr_xstatement = st - pr->pr_statements; PR_RunError (pr, "Progs attempted to read an invalid indexed global\n"); return; } OPC->_float = pr->pr_globals[OPA->_int]; break; case OP_GLOAD_V: if (pr_boundscheck->int_val && (OPA->_int < 0 || OPA->_int + 2 >= pr->pr_globaldefs)) { pr->pr_xstatement = st - pr->pr_statements; PR_RunError (pr, "Progs attempted to read an invalid indexed global\n"); return; } OPC->vector[0] = pr->pr_globals[OPA->_int]; OPC->vector[1] = pr->pr_globals[OPA->_int + 1]; OPC->vector[2] = pr->pr_globals[OPA->_int + 2]; break; case OP_BOUNDCHECK: if (OPA->_int < 0 || OPA->_int >= st->b) { pr->pr_xstatement = st - pr->pr_statements; PR_RunError (pr, "Progs boundcheck failed at line number %d, value is < 0 or >= %d\n", st->b, st->c); return; } break; */ default: pr->pr_xstatement = st - pr->pr_statements; PR_RunError (pr, "Bad opcode %i", st->op); } } }