static void PF_walkmove() { edict_t ent = PROG_TO_EDICT(pr_global_struct.self); float yaw = G_FLOAT(q_shared.OFS_PARM0); float dist = G_FLOAT(q_shared.OFS_PARM1); if (((int)ent.v.flags & (q_shared.FL_ONGROUND | q_shared.FL_FLY | q_shared.FL_SWIM)) == 0) { G_FLOAT((float)0); return; } yaw = (float)(yaw * Math.PI * 2.0 / 360.0); v3f move; move.x = (float)Math.Cos(yaw) * dist; move.y = (float)Math.Sin(yaw) * dist; move.z = 0; // save program state, because SV_movestep may call other progs dfunction_t oldf = pr_xfunction; int oldself = pr_global_struct.self; G_FLOAT((float)(SV_movestep(ent, ref move, true) ? 1 : 0)); // restore program state pr_xfunction = oldf; pr_global_struct.self = oldself; }
/* * ==================== * PR_LeaveFunction * ==================== */ static int PR_LeaveFunction() { int i, c; if (pr_depth <= 0) { sys_linux.Sys_Error("prog stack underflow"); } // restore locals from the stack c = pr_xfunction.locals; localstack_used -= c; if (localstack_used < 0) { PR_RunError("PR_ExecuteProgram: locals stack underflow\n"); } for (i = 0; i < c; i++) { pr_globals_write(pr_xfunction.parm_start + i, localstack[localstack_used + i]); } // up stack pr_depth--; pr_xfunction = pr_stack[pr_depth].f; return(pr_stack[pr_depth].s); }
public static int PR_LeaveFunction() { if (pr_depth <= 0) { Sys_Error("prog stack underflow"); } // restore locals from the stack int c = pr_xfunction.locals; localstack_used -= c; if (localstack_used < 0) { PR_RunError("PR_ExecuteProgram: locals stack underflow\n"); } for (int i = 0; i < c; i++) { Set(pr_xfunction.parm_start + i, localstack[localstack_used + i]); //((int*)pr_globals)[pr_xfunction->parm_start + i] = localstack[localstack_used + i]; } // up stack pr_depth--; pr_xfunction = pr_stack[pr_depth].f; return(pr_stack[pr_depth].s); }
public static void PR_Profile_f() { if (pr_functions == null) { return; } dfunction_t best; int num = 0; do { int max = 0; best = null; for (int i = 0; i < pr_functions.Length; i++) { dfunction_t f = pr_functions[i]; if (f.profile > max) { max = f.profile; best = f; } } if (best != null) { if (num < 10) { Con_Printf("{0,7} {1}\n", best.profile, GetString(best.s_name)); } num++; best.profile = 0; } } while (best != null); }
static unsafe string PR_ValueString(etype_t type, void *val) { string result; type &= (etype_t) ~q_shared.DEF_SAVEGLOBAL; switch (type) { case etype_t.ev_string: result = GetString(*(int *)val); break; case etype_t.ev_entity: result = "entity " + NUM_FOR_EDICT(PROG_TO_EDICT(*(int *)val)); break; case etype_t.ev_function: dfunction_t f = pr_functions[*(int *)val]; result = GetString(f.s_name) + "()"; break; case etype_t.ev_field: ddef_t def = ED_FieldAtOfs(*(int *)val); result = "." + GetString(def.s_name); break; case etype_t.ev_void: result = "void"; break; case etype_t.ev_float: result = (*(float *)val).ToString("F1", CultureInfo.InvariantCulture.NumberFormat); break; case etype_t.ev_vector: result = String.Format(CultureInfo.InvariantCulture.NumberFormat, "{0,5:F1} {1,5:F1} {2,5:F1}", ((float *)val)[0], ((float *)val)[1], ((float *)val)[2]); break; case etype_t.ev_pointer: result = "pointer"; break; default: result = "bad type " + type.ToString(); break; } return(result); }
static unsafe string PR_UglyValueString(etype_t type, eval_t *val) { type &= (etype_t) ~q_shared.DEF_SAVEGLOBAL; string result; switch (type) { case etype_t.ev_string: result = GetString(val->_string); break; case etype_t.ev_entity: result = NUM_FOR_EDICT(PROG_TO_EDICT(val->edict)).ToString(); break; case etype_t.ev_function: dfunction_t f = pr_functions[val->function]; result = GetString(f.s_name); break; case etype_t.ev_field: ddef_t def = ED_FieldAtOfs(val->_int); result = GetString(def.s_name); break; case etype_t.ev_void: result = "void"; break; case etype_t.ev_float: result = val->_float.ToString("F6", CultureInfo.InvariantCulture.NumberFormat); break; case etype_t.ev_vector: result = String.Format(CultureInfo.InvariantCulture.NumberFormat, "{0:F6} {1:F6} {2:F6}", val->vector[0], val->vector[1], val->vector[2]); break; default: result = "bad type " + type.ToString(); break; } return(result); }
/* * ============================================================================ * PR_ExecuteProgram * * The interpretation main loop * ============================================================================ */ /* * ==================== * PR_EnterFunction * * Returns the new program statement counter * ==================== */ public static int PR_EnterFunction(dfunction_t f) { int i, j, c, o; pr_stack[pr_depth].s = pr_xstatement; pr_stack[pr_depth].f = pr_xfunction; pr_depth++; if (pr_depth >= MAX_STACK_DEPTH) { PR_RunError("stack overflow"); } // save off any locals that the new function steps on c = f.locals; if (localstack_used + c > LOCALSTACK_SIZE) { PR_RunError("PR_ExecuteProgram: locals stack overflow\n"); } for (i = 0; i < c; i++) { localstack[localstack_used + i] = cast_int(pr_globals_read(f.parm_start + i)); } localstack_used += c; // copy parameters o = f.parm_start; for (i = 0; i < f.numparms; i++) { for (j = 0; j < f.parm_size[i]; j++) { pr_globals_write(o, pr_globals_read(OFS_PARM0 + i * 3 + j)); o++; } } pr_xfunction = f; return(f.first_statement - 1); // offset the s++ }
public static unsafe int PR_EnterFunction(dfunction_t f) { pr_stack[pr_depth].s = pr_xstatement; pr_stack[pr_depth].f = pr_xfunction; pr_depth++; if (pr_depth >= q_shared.MAX_STACK_DEPTH) { PR_RunError("stack overflow"); } // save off any locals that the new function steps on int c = f.locals; if (localstack_used + c > q_shared.LOCALSTACK_SIZE) { PR_RunError("PR_ExecuteProgram: locals stack overflow\n"); } for (int i = 0; i < c; i++) { localstack[localstack_used + i] = *(int *)Get(f.parm_start + i); } localstack_used += c; // copy parameters int o = f.parm_start; for (int i = 0; i < f.numparms; i++) { for (int j = 0; j < f.parm_size[i]; j++) { Set(o, *(int *)Get(q_shared.OFS_PARM0 + i * 3 + j)); o++; } } pr_xfunction = f; return(f.first_statement - 1); // offset the s++ }
public static void PR_StackTrace() { if (pr_depth == 0) { Con_Printf("<NO STACK>\n"); return; } pr_stack[pr_depth].f = pr_xfunction; for (int i = pr_depth; i >= 0; i--) { dfunction_t f = pr_stack[i].f; if (f == null) { Con_Printf("<NO FUNCTION>\n"); } else { Con_Printf("{0,12} : {1}\n", GetString(f.s_file), GetString(f.s_name)); } } }
/* ==================== PR_LeaveFunction ==================== */ static int PR_LeaveFunction() { int i, c; if (pr_depth <= 0) sys_linux.Sys_Error ("prog stack underflow"); // restore locals from the stack c = pr_xfunction.locals; localstack_used -= c; if (localstack_used < 0) PR_RunError ("PR_ExecuteProgram: locals stack underflow\n"); for (i = 0; i < c; i++) pr_globals_write(pr_xfunction.parm_start + i, localstack[localstack_used + i]); // up stack pr_depth--; pr_xfunction = pr_stack[pr_depth].f; return pr_stack[pr_depth].s; }
/* ==================== PR_ExecuteProgram ==================== */ public static void PR_ExecuteProgram(dfunction_t fnum) { /* eval_t *a, *b, *c;*/ int s; dstatement_t st; dfunction_t newf; /*dfunction_t *f;*/ 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 (fnum); while (true) { s++; // next statement st = pr_statements[s]; if (--runaway == 0) PR_RunError("runaway loop error"); pr_xfunction.profile++; pr_xstatement = s; if (pr_trace) PR_PrintStatement(st); if (st.c == 7505) st.c = st.c; bool eval; switch ((opcode_t)st.op) { case opcode_t.OP_ADD_F: //c->_float = a->_float + b->_float; pr_globals_write(st.c, (double)(cast_float(pr_globals_read(st.a)) + cast_float(pr_globals_read(st.b)))); break; case opcode_t.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];*/ pr_globals_write(st.c, (double)(cast_float(pr_globals_read(st.a)) + cast_float(pr_globals_read(st.b)))); pr_globals_write(st.c + 1, (double)(cast_float(pr_globals_read(st.a + 1)) + cast_float(pr_globals_read(st.b + 1)))); pr_globals_write(st.c + 2, (double)(cast_float(pr_globals_read(st.a + 2)) + cast_float(pr_globals_read(st.b + 2)))); break; case opcode_t.OP_SUB_F: //c->_float = a->_float - b->_float; pr_globals_write(st.c, (double)(cast_float(pr_globals_read(st.a)) - cast_float(pr_globals_read(st.b)))); break; case opcode_t.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];*/ pr_globals_write(st.c, (double)(cast_float(pr_globals_read(st.a)) - cast_float(pr_globals_read(st.b)))); pr_globals_write(st.c + 1, (double)(cast_float(pr_globals_read(st.a + 1)) - cast_float(pr_globals_read(st.b + 1)))); pr_globals_write(st.c + 2, (double)(cast_float(pr_globals_read(st.a + 2)) - cast_float(pr_globals_read(st.b + 2)))); break; case opcode_t.OP_MUL_F: //c->_float = a->_float * b->_float; pr_globals_write(st.c, (double)(cast_float(pr_globals_read(st.a)) * cast_float(pr_globals_read(st.b)))); break; case opcode_t.OP_MUL_V: /*c->_float = a->vector[0] * b->vector[0] + a->vector[1] * b->vector[1] + a->vector[2] * b->vector[2];*/ double res = (double)(cast_float(pr_globals_read(st.a)) * cast_float(pr_globals_read(st.b)) + cast_float(pr_globals_read(st.a + 1)) * cast_float(pr_globals_read(st.b + 1)) + cast_float(pr_globals_read(st.a + 2)) * cast_float(pr_globals_read(st.b + 2))); pr_globals_write(st.c, res); break; /*case opcode_t.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 opcode_t.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];*/ pr_globals_write(st.c, (double)(cast_float(pr_globals_read(st.b)) * cast_float(pr_globals_read(st.a)))); pr_globals_write(st.c + 1, (double)(cast_float(pr_globals_read(st.b + 1)) * cast_float(pr_globals_read(st.a + 1)))); pr_globals_write(st.c + 2, (double)(cast_float(pr_globals_read(st.b + 2)) * cast_float(pr_globals_read(st.a + 2)))); break; case opcode_t.OP_BITAND: //c->_float = (int)a->_float & (int)b->_float; pr_globals_write(st.c, (double)((int)cast_float(pr_globals_read(st.a)) & (int)cast_float(pr_globals_read(st.b)))); break; case opcode_t.OP_BITOR: //c->_float = (int)a->_float | (int)b->_float; pr_globals_write(st.c, (double)((int)cast_float(pr_globals_read(st.a)) | (int)cast_float(pr_globals_read(st.b)))); break; case opcode_t.OP_GE: //c->_float = a->_float >= b->_float; pr_globals_write(st.c, (double)(cast_float(pr_globals_read(st.a)) >= cast_float(pr_globals_read(st.b)) ? 1 : 0)); break; case opcode_t.OP_LE: //c->_float = a->_float <= b->_float; pr_globals_write(st.c, (double)(cast_float(pr_globals_read(st.a)) <= cast_float(pr_globals_read(st.b)) ? 1 : 0)); break; case opcode_t.OP_GT: //c->_float = a->_float > b->_float; pr_globals_write(st.c, (double)(cast_float(pr_globals_read(st.a)) > cast_float(pr_globals_read(st.b)) ? 1 : 0)); break; case opcode_t.OP_LT: //c->_float = a->_float < b->_float; pr_globals_write(st.c, (double)(cast_float(pr_globals_read(st.a)) < cast_float(pr_globals_read(st.b)) ? 1 : 0)); break; case opcode_t.OP_AND: //c->_float = a->_float && b->_float; pr_globals_write(st.c, (double)(cast_float(pr_globals_read(st.a)) != 0 && cast_float(pr_globals_read(st.b)) != 0 ? 1 : 0)); break; case opcode_t.OP_OR: //c->_float = a->_float || b->_float; pr_globals_write(st.c, (double)(cast_float(pr_globals_read(st.a)) != 0 || cast_float(pr_globals_read(st.b)) != 0 ? 1 : 0)); break; case opcode_t.OP_NOT_F: //c->_float = !a->_float; pr_globals_write(st.c, (double)(cast_float(pr_globals_read(st.a)) == 0 ? 1 : 0)); break; case opcode_t.OP_NOT_S: //c->_float = !a->string || !pr_strings[a->string]; int astring = cast_int(pr_globals_read(st.a)); pr_globals_write(st.c, (double)(((astring == 0) || (pr_string(astring) == null)) ? 1 : 0)); break; case opcode_t.OP_NOT_FNC: //c->_float = !a->function; pr_globals_write(st.c, (double)(cast_int(pr_globals_read(st.a)) == 0 ? 1 : 0)); break; case opcode_t.OP_NOT_ENT: //c->_float = (PROG_TO_EDICT(a->edict) == sv.edicts); pr_globals_write(st.c, (double)(PROG_TO_EDICT(cast_int(pr_globals_read(st.a))) == server.sv.edicts[0] ? 1 : 0)); break; case opcode_t.OP_EQ_F: //c->_float = a->_float == b->_float; pr_globals_write(st.c, (double)(cast_float(pr_globals_read(st.a)) == cast_float(pr_globals_read(st.b)) ? 1 : 0)); break; case opcode_t.OP_EQ_V: /*c->_float = (a->vector[0] == b->vector[0]) && (a->vector[1] == b->vector[1]) && (a->vector[2] == b->vector[2]);*/ eval = (cast_float(pr_globals_read(st.a)) == cast_float(pr_globals_read(st.b))) && (cast_float(pr_globals_read(st.a + 1)) == cast_float(pr_globals_read(st.b + 1))) && (cast_float(pr_globals_read(st.a + 2)) == cast_float(pr_globals_read(st.b + 2))); pr_globals_write(st.c, (double)(eval ? 1 : 0)); break; case opcode_t.OP_EQ_S: //c->_float = !strcmp(pr_strings+a->string,pr_strings+b->string); pr_globals_write(st.c, (double)(pr_string(cast_int(pr_globals_read(st.a))).CompareTo(pr_string(cast_int(pr_globals_read(st.b)))) == 0 ? 1 : 0)); break; case opcode_t.OP_NE_V: /*c->_float = (a->vector[0] != b->vector[0]) || (a->vector[1] != b->vector[1]) || (a->vector[2] != b->vector[2]);*/ eval = (cast_float(pr_globals_read(st.a)) != cast_float(pr_globals_read(st.b))) || (cast_float(pr_globals_read(st.a + 1)) != cast_float(pr_globals_read(st.b + 1))) || (cast_float(pr_globals_read(st.a + 2)) != cast_float(pr_globals_read(st.b + 2))); pr_globals_write(st.c, (double)(eval ? 1 : 0)); break; //================== case opcode_t.OP_STORE_F: case opcode_t.OP_STORE_ENT: case opcode_t.OP_STORE_FLD: // integers case opcode_t.OP_STORE_S: case opcode_t.OP_STORE_FNC: // pointers pr_globals_write(st.b, pr_globals_read(st.a)); break; case opcode_t.OP_STORE_V: /*b->vector[0] = a->vector[0]; b->vector[1] = a->vector[1]; b->vector[2] = a->vector[2];*/ pr_globals_write(st.b, (double)cast_float(pr_globals_read(st.a))); pr_globals_write(st.b + 1, (double)cast_float(pr_globals_read(st.a + 1))); pr_globals_write(st.b + 2, (double)cast_float(pr_globals_read(st.a + 2))); break; case opcode_t.OP_STOREP_F: case opcode_t.OP_STOREP_ENT: case opcode_t.OP_STOREP_FLD: // integers case opcode_t.OP_STOREP_S: case opcode_t.OP_STOREP_FNC: // pointers //ptr = (eval_t*)((byte*)sv.edicts + b->_int); //ptr->_int = a->_int; writeptr(cast_int(pr_globals_read(st.b)), cast_int(pr_globals_read(st.a))); break; case opcode_t.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]; writeptr(cast_int(pr_globals_read(st.b)), cast_int(pr_globals_read(st.a))); writeptr(cast_int(pr_globals_read(st.b)) + 1, cast_int(pr_globals_read(st.a + 1))); writeptr(cast_int(pr_globals_read(st.b)) + 2, cast_int(pr_globals_read(st.a + 2))); break; case opcode_t.OP_ADDRESS: ed = PROG_TO_EDICT(cast_int(pr_globals_read(st.a))); if (ed == server.sv.edicts[0] && server.sv.state == server.server_state_t.ss_active) PR_RunError ("assignment to world entity"); //c->_int = (byte *)((int *)&ed->v + b->_int) - (byte *)sv.edicts; pr_globals_write(st.c, ed.index * pr_edict_size + 96 + cast_int(pr_globals_read(st.b)) * 4); break; case opcode_t.OP_LOAD_F: case opcode_t.OP_LOAD_FLD: case opcode_t.OP_LOAD_ENT: case opcode_t.OP_LOAD_S: case opcode_t.OP_LOAD_FNC: ed = PROG_TO_EDICT(cast_int(pr_globals_read(st.a))); //a = (eval_t *)((int *)&ed->v + b->_int); //c->_int = a->_int; pr_globals_write(st.c, cast_int(readptr(ed.index * pr_edict_size + 96 + cast_int(pr_globals_read(st.b)) * 4))); break; case opcode_t.OP_LOAD_V: ed = PROG_TO_EDICT(cast_int(pr_globals_read(st.a))); //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]; pr_globals_write(st.c, (double)cast_float(readptr(ed.index * pr_edict_size + 96 + cast_int(pr_globals_read(st.b)) * 4))); pr_globals_write(st.c + 1, (double)cast_float(readptr(ed.index * pr_edict_size + 96 + (cast_int(pr_globals_read(st.b)) + 1) * 4))); pr_globals_write(st.c + 2, (double)cast_float(readptr(ed.index * pr_edict_size + 96 + (cast_int(pr_globals_read(st.b)) + 2) * 4))); break; //================== case opcode_t.OP_IFNOT: if (cast_int(pr_globals_read(st.a)) == 0) s += st.b - 1; // offset the s++ break; case opcode_t.OP_IF: if (cast_int(pr_globals_read(st.a)) != 0) s += st.b - 1; // offset the s++ break; case opcode_t.OP_GOTO: s += st.a - 1; // offset the s++ break; case opcode_t.OP_CALL0: case opcode_t.OP_CALL1: case opcode_t.OP_CALL2: case opcode_t.OP_CALL3: case opcode_t.OP_CALL4: case opcode_t.OP_CALL5: case opcode_t.OP_CALL6: case opcode_t.OP_CALL7: case opcode_t.OP_CALL8: pr_argc = st.op - (int)opcode_t.OP_CALL0; int afunction = cast_int(pr_globals_read(st.a)); if (afunction == 0) PR_RunError("NULL function"); newf = pr_functions[afunction]; 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 opcode_t.OP_DONE: case opcode_t.OP_RETURN: pr_globals_write(OFS_RETURN, pr_globals_read(st.a)); pr_globals_write(OFS_RETURN + 1, pr_globals_read(st.a + 1)); pr_globals_write(OFS_RETURN + 2, pr_globals_read(st.a + 2)); s = PR_LeaveFunction(); if (pr_depth == exitdepth) return; // all done break; case opcode_t.OP_STATE: ed = PROG_TO_EDICT(pr_global_struct[0].self); ed.v.nextthink = pr_global_struct[0].time + 0.1; if (cast_float(pr_globals_read(st.a)) != ed.v.frame) { ed.v.frame = cast_float(pr_globals_read(st.a)); } ed.v.think = cast_int(pr_globals_read(st.b)); break; default: break; } } }
/* ============================================================================ PR_ExecuteProgram The interpretation main loop ============================================================================ */ /* ==================== PR_EnterFunction Returns the new program statement counter ==================== */ public static int PR_EnterFunction(dfunction_t f) { int i, j, c, o; pr_stack[pr_depth].s = pr_xstatement; pr_stack[pr_depth].f = pr_xfunction; pr_depth++; if (pr_depth >= MAX_STACK_DEPTH) PR_RunError("stack overflow"); // save off any locals that the new function steps on c = f.locals; if (localstack_used + c > LOCALSTACK_SIZE) PR_RunError("PR_ExecuteProgram: locals stack overflow\n"); for (i = 0; i < c; i++) localstack[localstack_used + i] = cast_int(pr_globals_read(f.parm_start + i)); localstack_used += c; // copy parameters o = f.parm_start; for (i = 0; i < f.numparms; i++) { for (j = 0; j < f.parm_size[i]; j++) { pr_globals_write(o, pr_globals_read(OFS_PARM0 + i * 3 + j)); o++; } } pr_xfunction = f; return f.first_statement - 1; // offset the s++ }
/* * ==================== * PR_ExecuteProgram * ==================== */ public static void PR_ExecuteProgram(dfunction_t fnum) { /* eval_t *a, *b, *c;*/ int s; dstatement_t st; dfunction_t newf; /*dfunction_t *f;*/ 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(fnum); while (true) { s++; // next statement st = pr_statements[s]; if (--runaway == 0) { PR_RunError("runaway loop error"); } pr_xfunction.profile++; pr_xstatement = s; if (pr_trace) { PR_PrintStatement(st); } if (st.c == 7505) { st.c = st.c; } bool eval; switch ((opcode_t)st.op) { case opcode_t.OP_ADD_F: //c->_float = a->_float + b->_float; pr_globals_write(st.c, (double)(cast_float(pr_globals_read(st.a)) + cast_float(pr_globals_read(st.b)))); break; case opcode_t.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];*/ pr_globals_write(st.c, (double)(cast_float(pr_globals_read(st.a)) + cast_float(pr_globals_read(st.b)))); pr_globals_write(st.c + 1, (double)(cast_float(pr_globals_read(st.a + 1)) + cast_float(pr_globals_read(st.b + 1)))); pr_globals_write(st.c + 2, (double)(cast_float(pr_globals_read(st.a + 2)) + cast_float(pr_globals_read(st.b + 2)))); break; case opcode_t.OP_SUB_F: //c->_float = a->_float - b->_float; pr_globals_write(st.c, (double)(cast_float(pr_globals_read(st.a)) - cast_float(pr_globals_read(st.b)))); break; case opcode_t.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];*/ pr_globals_write(st.c, (double)(cast_float(pr_globals_read(st.a)) - cast_float(pr_globals_read(st.b)))); pr_globals_write(st.c + 1, (double)(cast_float(pr_globals_read(st.a + 1)) - cast_float(pr_globals_read(st.b + 1)))); pr_globals_write(st.c + 2, (double)(cast_float(pr_globals_read(st.a + 2)) - cast_float(pr_globals_read(st.b + 2)))); break; case opcode_t.OP_MUL_F: //c->_float = a->_float * b->_float; pr_globals_write(st.c, (double)(cast_float(pr_globals_read(st.a)) * cast_float(pr_globals_read(st.b)))); break; case opcode_t.OP_MUL_V: /*c->_float = a->vector[0] * b->vector[0] + a->vector[1] * b->vector[1] + a->vector[2] * b->vector[2];*/ double res = (double)(cast_float(pr_globals_read(st.a)) * cast_float(pr_globals_read(st.b)) + cast_float(pr_globals_read(st.a + 1)) * cast_float(pr_globals_read(st.b + 1)) + cast_float(pr_globals_read(st.a + 2)) * cast_float(pr_globals_read(st.b + 2))); pr_globals_write(st.c, res); break; /*case opcode_t.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 opcode_t.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];*/ pr_globals_write(st.c, (double)(cast_float(pr_globals_read(st.b)) * cast_float(pr_globals_read(st.a)))); pr_globals_write(st.c + 1, (double)(cast_float(pr_globals_read(st.b + 1)) * cast_float(pr_globals_read(st.a + 1)))); pr_globals_write(st.c + 2, (double)(cast_float(pr_globals_read(st.b + 2)) * cast_float(pr_globals_read(st.a + 2)))); break; case opcode_t.OP_BITAND: //c->_float = (int)a->_float & (int)b->_float; pr_globals_write(st.c, (double)((int)cast_float(pr_globals_read(st.a)) & (int)cast_float(pr_globals_read(st.b)))); break; case opcode_t.OP_BITOR: //c->_float = (int)a->_float | (int)b->_float; pr_globals_write(st.c, (double)((int)cast_float(pr_globals_read(st.a)) | (int)cast_float(pr_globals_read(st.b)))); break; case opcode_t.OP_GE: //c->_float = a->_float >= b->_float; pr_globals_write(st.c, (double)(cast_float(pr_globals_read(st.a)) >= cast_float(pr_globals_read(st.b)) ? 1 : 0)); break; case opcode_t.OP_LE: //c->_float = a->_float <= b->_float; pr_globals_write(st.c, (double)(cast_float(pr_globals_read(st.a)) <= cast_float(pr_globals_read(st.b)) ? 1 : 0)); break; case opcode_t.OP_GT: //c->_float = a->_float > b->_float; pr_globals_write(st.c, (double)(cast_float(pr_globals_read(st.a)) > cast_float(pr_globals_read(st.b)) ? 1 : 0)); break; case opcode_t.OP_LT: //c->_float = a->_float < b->_float; pr_globals_write(st.c, (double)(cast_float(pr_globals_read(st.a)) < cast_float(pr_globals_read(st.b)) ? 1 : 0)); break; case opcode_t.OP_AND: //c->_float = a->_float && b->_float; pr_globals_write(st.c, (double)(cast_float(pr_globals_read(st.a)) != 0 && cast_float(pr_globals_read(st.b)) != 0 ? 1 : 0)); break; case opcode_t.OP_OR: //c->_float = a->_float || b->_float; pr_globals_write(st.c, (double)(cast_float(pr_globals_read(st.a)) != 0 || cast_float(pr_globals_read(st.b)) != 0 ? 1 : 0)); break; case opcode_t.OP_NOT_F: //c->_float = !a->_float; pr_globals_write(st.c, (double)(cast_float(pr_globals_read(st.a)) == 0 ? 1 : 0)); break; case opcode_t.OP_NOT_S: //c->_float = !a->string || !pr_strings[a->string]; int astring = cast_int(pr_globals_read(st.a)); pr_globals_write(st.c, (double)(((astring == 0) || (pr_string(astring) == null)) ? 1 : 0)); break; case opcode_t.OP_NOT_FNC: //c->_float = !a->function; pr_globals_write(st.c, (double)(cast_int(pr_globals_read(st.a)) == 0 ? 1 : 0)); break; case opcode_t.OP_NOT_ENT: //c->_float = (PROG_TO_EDICT(a->edict) == sv.edicts); pr_globals_write(st.c, (double)(PROG_TO_EDICT(cast_int(pr_globals_read(st.a))) == server.sv.edicts[0] ? 1 : 0)); break; case opcode_t.OP_EQ_F: //c->_float = a->_float == b->_float; pr_globals_write(st.c, (double)(cast_float(pr_globals_read(st.a)) == cast_float(pr_globals_read(st.b)) ? 1 : 0)); break; case opcode_t.OP_EQ_V: /*c->_float = (a->vector[0] == b->vector[0]) && * (a->vector[1] == b->vector[1]) && * (a->vector[2] == b->vector[2]);*/ eval = (cast_float(pr_globals_read(st.a)) == cast_float(pr_globals_read(st.b))) && (cast_float(pr_globals_read(st.a + 1)) == cast_float(pr_globals_read(st.b + 1))) && (cast_float(pr_globals_read(st.a + 2)) == cast_float(pr_globals_read(st.b + 2))); pr_globals_write(st.c, (double)(eval ? 1 : 0)); break; case opcode_t.OP_EQ_S: //c->_float = !strcmp(pr_strings+a->string,pr_strings+b->string); pr_globals_write(st.c, (double)(pr_string(cast_int(pr_globals_read(st.a))).CompareTo(pr_string(cast_int(pr_globals_read(st.b)))) == 0 ? 1 : 0)); break; case opcode_t.OP_NE_V: /*c->_float = (a->vector[0] != b->vector[0]) || * (a->vector[1] != b->vector[1]) || * (a->vector[2] != b->vector[2]);*/ eval = (cast_float(pr_globals_read(st.a)) != cast_float(pr_globals_read(st.b))) || (cast_float(pr_globals_read(st.a + 1)) != cast_float(pr_globals_read(st.b + 1))) || (cast_float(pr_globals_read(st.a + 2)) != cast_float(pr_globals_read(st.b + 2))); pr_globals_write(st.c, (double)(eval ? 1 : 0)); break; //================== case opcode_t.OP_STORE_F: case opcode_t.OP_STORE_ENT: case opcode_t.OP_STORE_FLD: // integers case opcode_t.OP_STORE_S: case opcode_t.OP_STORE_FNC: // pointers pr_globals_write(st.b, pr_globals_read(st.a)); break; case opcode_t.OP_STORE_V: /*b->vector[0] = a->vector[0]; * b->vector[1] = a->vector[1]; * b->vector[2] = a->vector[2];*/ pr_globals_write(st.b, (double)cast_float(pr_globals_read(st.a))); pr_globals_write(st.b + 1, (double)cast_float(pr_globals_read(st.a + 1))); pr_globals_write(st.b + 2, (double)cast_float(pr_globals_read(st.a + 2))); break; case opcode_t.OP_STOREP_F: case opcode_t.OP_STOREP_ENT: case opcode_t.OP_STOREP_FLD: // integers case opcode_t.OP_STOREP_S: case opcode_t.OP_STOREP_FNC: // pointers //ptr = (eval_t*)((byte*)sv.edicts + b->_int); //ptr->_int = a->_int; writeptr(cast_int(pr_globals_read(st.b)), cast_int(pr_globals_read(st.a))); break; case opcode_t.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]; writeptr(cast_int(pr_globals_read(st.b)), cast_int(pr_globals_read(st.a))); writeptr(cast_int(pr_globals_read(st.b)) + 1, cast_int(pr_globals_read(st.a + 1))); writeptr(cast_int(pr_globals_read(st.b)) + 2, cast_int(pr_globals_read(st.a + 2))); break; case opcode_t.OP_ADDRESS: ed = PROG_TO_EDICT(cast_int(pr_globals_read(st.a))); if (ed == server.sv.edicts[0] && server.sv.state == server.server_state_t.ss_active) { PR_RunError("assignment to world entity"); } //c->_int = (byte *)((int *)&ed->v + b->_int) - (byte *)sv.edicts; pr_globals_write(st.c, ed.index * pr_edict_size + 96 + cast_int(pr_globals_read(st.b)) * 4); break; case opcode_t.OP_LOAD_F: case opcode_t.OP_LOAD_FLD: case opcode_t.OP_LOAD_ENT: case opcode_t.OP_LOAD_S: case opcode_t.OP_LOAD_FNC: ed = PROG_TO_EDICT(cast_int(pr_globals_read(st.a))); //a = (eval_t *)((int *)&ed->v + b->_int); //c->_int = a->_int; pr_globals_write(st.c, cast_int(readptr(ed.index * pr_edict_size + 96 + cast_int(pr_globals_read(st.b)) * 4))); break; case opcode_t.OP_LOAD_V: ed = PROG_TO_EDICT(cast_int(pr_globals_read(st.a))); //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]; pr_globals_write(st.c, (double)cast_float(readptr(ed.index * pr_edict_size + 96 + cast_int(pr_globals_read(st.b)) * 4))); pr_globals_write(st.c + 1, (double)cast_float(readptr(ed.index * pr_edict_size + 96 + (cast_int(pr_globals_read(st.b)) + 1) * 4))); pr_globals_write(st.c + 2, (double)cast_float(readptr(ed.index * pr_edict_size + 96 + (cast_int(pr_globals_read(st.b)) + 2) * 4))); break; //================== case opcode_t.OP_IFNOT: if (cast_int(pr_globals_read(st.a)) == 0) { s += st.b - 1; // offset the s++ } break; case opcode_t.OP_IF: if (cast_int(pr_globals_read(st.a)) != 0) { s += st.b - 1; // offset the s++ } break; case opcode_t.OP_GOTO: s += st.a - 1; // offset the s++ break; case opcode_t.OP_CALL0: case opcode_t.OP_CALL1: case opcode_t.OP_CALL2: case opcode_t.OP_CALL3: case opcode_t.OP_CALL4: case opcode_t.OP_CALL5: case opcode_t.OP_CALL6: case opcode_t.OP_CALL7: case opcode_t.OP_CALL8: pr_argc = st.op - (int)opcode_t.OP_CALL0; int afunction = cast_int(pr_globals_read(st.a)); if (afunction == 0) { PR_RunError("NULL function"); } newf = pr_functions[afunction]; 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 opcode_t.OP_DONE: case opcode_t.OP_RETURN: pr_globals_write(OFS_RETURN, pr_globals_read(st.a)); pr_globals_write(OFS_RETURN + 1, pr_globals_read(st.a + 1)); pr_globals_write(OFS_RETURN + 2, pr_globals_read(st.a + 2)); s = PR_LeaveFunction(); if (pr_depth == exitdepth) { return; // all done } break; case opcode_t.OP_STATE: ed = PROG_TO_EDICT(pr_global_struct[0].self); ed.v.nextthink = pr_global_struct[0].time + 0.1; if (cast_float(pr_globals_read(st.a)) != ed.v.frame) { ed.v.frame = cast_float(pr_globals_read(st.a)); } ed.v.think = cast_int(pr_globals_read(st.b)); break; default: break; } } }
/* ==================== PR_ExecuteProgram ==================== */ public static void PR_ExecuteProgram(dfunction_t fnum) { /* eval_t *a, *b, *c;*/ int s; dstatement_t st; dstatement_t_alt st_; dfunction_t newf; /*dfunction_t *f;*/ int runaway; int i; edict_t ed; int exitdepth; eval_t ptr; //try{ /*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 = true; // make a stack frame exitdepth = pr_depth; s = PR_EnterFunction(fnum); while (true) { s++; // next statement prNum++; st = pr_statements[s]; st_ = new dstatement_t_alt(st); eval_t a = st_.a; eval_t b = st_.b; eval_t c = st_.c; if (--runaway == 0) PR_RunError("runaway loop error"); pr_xfunction.profile++; pr_xstatement = s; if (pr_trace) { //PR_PrintStatement(st); //Debug.WriteLine(string.Format("a {0}: {1} {2} {3}", st.a, pr_globals_read(st.a), pr_globals_read(st.a + 1), pr_globals_read(st.a + 2))); //Debug.WriteLine(string.Format("b {0}: {1} {2} {3}", st.b, pr_globals_read(st.b), pr_globals_read(st.b + 1), pr_globals_read(st.b + 2))); //Debug.WriteLine(string.Format("c {0}: {1} {2} {3}", st.c, pr_globals_read(st.c), pr_globals_read(st.c + 1), pr_globals_read(st.c + 2))); //PR_StackTraceStr(); } //Debug.WriteLine(string.Format("prNum: {0}", prNum)); //Debug.WriteLine(string.Format("a: {0}", a, b, c)); //Debug.WriteLine(string.Format("b: {1}", a, b, c)); //Debug.WriteLine(string.Format("c: {2}", a, b, c)); switch ((opcode_t)st.op) { case opcode_t.OP_ADD_F: c._float = a._float + b._float; break; case opcode_t.OP_ADD_V: //var testWith = (float)a.vector[0] + (float)b.vector[0]; //var testWithout = a.vector[0] + b.vector[0]; //var testWithout2 = (float) (a.vector[0] + b.vector[0]); //var testglv1 = (globalval)testWith; //var testglv2 = (globalval)testWithout; //var testglv3 = (globalval)testWithout2; //var testWith4 = (globalval)((float)a.vector[0] + (float)b.vector[0]); //var testWithout4 = (globalval)(a.vector[0] + b.vector[0]); //var testWithout24 = (globalval)((float) (a.vector[0] + b.vector[0])); 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 opcode_t.OP_SUB_F: c._float = a._float - b._float; break; case opcode_t.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 opcode_t.OP_MUL_F: c._float = a._float * b._float; break; case opcode_t.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 opcode_t.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 opcode_t.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 opcode_t.OP_DIV_F: c._float = a._float / b._float; break; case opcode_t.OP_BITAND: c._float = (int)a._float & (int)b._float; break; case opcode_t.OP_BITOR: c._float = (int)a._float | (int)b._float; break; case opcode_t.OP_GE: c._float_b = a._float >= b._float; break; case opcode_t.OP_LE: c._float_b = a._float <= b._float ; break; case opcode_t.OP_GT: c._float_b = a._float > b._float; break; case opcode_t.OP_LT: c._float_b = a._float < b._float ; break; case opcode_t.OP_AND: c._float_b = a._float != 0 && b._float != 0 ; break; case opcode_t.OP_OR: c._float_b = a._float != 0 || b._float != 0; break; case opcode_t.OP_NOT_F: c._float_b = !a._float_b; break; case opcode_t.OP_NOT_S: c._float_b = (a.@string == 0) || string.IsNullOrEmpty(pr_string(a.@string)); break; case opcode_t.OP_NOT_FNC: c._float_b = a.function == 0; break; case opcode_t.OP_NOT_ENT: c._float_b = (PROG_TO_EDICT(a.edict) == server.sv.edicts[0]); break; case opcode_t.OP_EQ_F: c._float_b = a._float == b._float; break; case opcode_t.OP_EQ_V: c._float_b = (a.vector[0] == b.vector[0]) && (a.vector[1] == b.vector[1]) && (a.vector[2] == b.vector[2]); break; case opcode_t.OP_EQ_S: c._float_b = pr_string(a.@string).CompareTo(pr_string(b.@string)) == 0; break; case opcode_t. OP_EQ_E: c._float_b = a._int == b._int; break; case opcode_t.OP_NE_F: c._float_b = a._float != b._float; break; case opcode_t.OP_NE_V: c._float_b = (a.vector[0] != b.vector[0]) || (a.vector[1] != b.vector[1]) || (a.vector[2] != b.vector[2]); break; case opcode_t.OP_NE_S: c._float = pr_string(a.@string).CompareTo(pr_string(b.@string)); break; case opcode_t.OP_NE_E: c._float_b = a._int != b._int; break; case opcode_t.OP_NE_FNC: c._float_b = a.function != b.function; break; //================== case opcode_t.OP_STORE_F: case opcode_t.OP_STORE_ENT: case opcode_t.OP_STORE_FLD: // integers case opcode_t.OP_STORE_S: case opcode_t.OP_STORE_FNC: // pointers b._int = a._int; break; case opcode_t.OP_STORE_V: //b.vector[0] = a.vector[0]; //TIODO: SOME NUMBERS ARE ALWASY NAN! NEED TO DO SOMETHING ELSE? ALWAYS STORE AS INT? //b._int = a._int; // todo: fix properly, this is a work around for if there's a NaN - which acts differently in JS. not all float values can convert to int I guess...? //maybe pass globalval instead of float? // log out everythingh and compare to original quake? // break point if NaN // dont cast to float? // COULD USE REFLECTION TO GET FIELDS DIRECTLY AND INTERACT WITH THEM // and or use "dynamic" and skip the cast_float stuff // eval_t can be a wrapper around, and globals funcs will get field Type info b.vector[0] = a.vector[0]; b.vector[1] = a.vector[1]; b.vector[2] = a.vector[2]; break; case opcode_t.OP_STOREP_F: case opcode_t.OP_STOREP_ENT: case opcode_t.OP_STOREP_FLD: // integers case opcode_t.OP_STOREP_S: case opcode_t.OP_STOREP_FNC: // pointers //ptr = (eval_t*)((byte*)sv.edicts + b->_int); //ptr->_int = a->_int; //todo ptr = sv.edicts[b._int]; //ptr._int = a._int; //var test = server.sv.edicts[b._int]; writeptr(b._int, a._int); break; case opcode_t.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]; //ptr = getptr(b._int); //sv.edicts[b._int]; //ptr.vector[0] = a.vector[0] etc writeptr(b._int, a.vector[0], 0); writeptr(b._int, a.vector[1], 1); writeptr(b._int, a.vector[2], 2); break; case opcode_t.OP_ADDRESS: ed = PROG_TO_EDICT(a._int); if (ed == server.sv.edicts[0] && server.sv.state == server.server_state_t.ss_active) PR_RunError("assignment to world entity"); //c->_int = (byte *)((int *)&ed->v + b->_int) - (byte *)sv.edicts; c._int = ed.index * pr_edict_size + 96 + b._int * 4; break; case opcode_t.OP_LOAD_F: case opcode_t.OP_LOAD_FLD: case opcode_t.OP_LOAD_ENT: case opcode_t.OP_LOAD_S: case opcode_t.OP_LOAD_FNC: ed = PROG_TO_EDICT(a._int); //a = (eval_t *)((int *)&ed->v + b->_int); //c->_int = a->_int; c._int = cast_int(readptr(ed.index * pr_edict_size + 96 + b._int * 4)); break; case opcode_t.OP_LOAD_V: ed = PROG_TO_EDICT(a.edict); //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]; c.vector[0] = cast_float(readptr(ed.index * pr_edict_size + 96 + b._int * 4)); c.vector[1] = cast_float(readptr(ed.index * pr_edict_size + 96 + (b._int + 1) * 4)); c.vector[2] = cast_float(readptr(ed.index * pr_edict_size + 96 + (b._int + 2) * 4)); break; //================== case opcode_t.OP_IFNOT: if (a._int == 0) s += st.b - 1; // offset the s++ break; case opcode_t.OP_IF: if (a._int != 0) s += st.b - 1; // offset the s++ break; case opcode_t.OP_GOTO: s += st.a - 1; // offset the s++ break; case opcode_t.OP_CALL0: case opcode_t.OP_CALL1: case opcode_t.OP_CALL2: case opcode_t.OP_CALL3: case opcode_t.OP_CALL4: case opcode_t.OP_CALL5: case opcode_t.OP_CALL6: case opcode_t.OP_CALL7: case opcode_t.OP_CALL8: pr_argc = st.op - (int)opcode_t.OP_CALL0; int afunction = a.function; if (afunction == 0) PR_RunError("NULL function"); newf = pr_functions[afunction]; 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"); //Debug.WriteLine("pr_builtins " + i); if (pr_builtins[i] == null) Debug.WriteLine("pr_builtins " + i + " does not exist"); pr_builtins[i](); break; } s = PR_EnterFunction(newf); break; case opcode_t.OP_DONE: case opcode_t.OP_RETURN: pr_globals_write(OFS_RETURN, pr_globals_read(st.a)); pr_globals_write(OFS_RETURN + 1, pr_globals_read(st.a + 1)); pr_globals_write(OFS_RETURN + 2, pr_globals_read(st.a + 2)); s = PR_LeaveFunction(); if (pr_depth == exitdepth) return; // all done break; case opcode_t.OP_STATE: ed = PROG_TO_EDICT(pr_global_struct[0].self); ed.v.nextthink = pr_global_struct[0].time + 0.1; if (a._float != ed.v.frame) { ed.v.frame = a._float; } ed.v.think = b.function; break; default: Debug.WriteLine("******Bad opcode " + ((opcode_t)st.op) + " prNum: " + prNum); // todo: this works fine on winquake. need to comment out here //PR_RunError("Bad opcode " + st.op); break; } } //} //catch //{ // Debug.WriteLine("broked"); //} }
public unsafe static void PR_ExecuteProgram(int fnum) { if (fnum < 1 || fnum >= pr_functions.Length) { if (pr_global_struct.self != 0) { ED_Print(PROG_TO_EDICT(pr_global_struct.self)); } Host_Error("PR_ExecuteProgram: NULL function"); } dfunction_t f = pr_functions[fnum]; int runaway = 100000; pr_trace = false; // make a stack frame int exitdepth = pr_depth; int ofs; int s = PR_EnterFunction(f); edict_t ed; while (true) { s++; // next statement eval_t *a = (eval_t *)Get(pr_statements[s].a); eval_t *b = (eval_t *)Get(pr_statements[s].b); eval_t *c = (eval_t *)Get(pr_statements[s].c); if (--runaway == 0) { PR_RunError("runaway loop error"); } pr_xfunction.profile++; pr_xstatement = s; if (pr_trace) { PR_PrintStatement(ref pr_statements[s]); } switch ((OP)pr_statements[s].op) { case OP.OP_ADD_F: c->_float = a->_float + b->_float; break; case OP.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.OP_SUB_F: c->_float = a->_float - b->_float; break; case OP.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.OP_MUL_F: c->_float = a->_float * b->_float; break; case OP.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.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.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.OP_DIV_F: c->_float = a->_float / b->_float; break; case OP.OP_BITAND: c->_float = (int)a->_float & (int)b->_float; break; case OP.OP_BITOR: c->_float = (int)a->_float | (int)b->_float; break; case OP.OP_GE: c->_float = (a->_float >= b->_float) ? 1 : 0; break; case OP.OP_LE: c->_float = (a->_float <= b->_float) ? 1 : 0; break; case OP.OP_GT: c->_float = (a->_float > b->_float) ? 1 : 0; break; case OP.OP_LT: c->_float = (a->_float < b->_float) ? 1 : 0; break; case OP.OP_AND: c->_float = (a->_float != 0 && b->_float != 0) ? 1 : 0; break; case OP.OP_OR: c->_float = (a->_float != 0 || b->_float != 0) ? 1 : 0; break; case OP.OP_NOT_F: c->_float = (a->_float != 0) ? 0 : 1; break; case OP.OP_NOT_V: c->_float = (a->vector[0] == 0 && a->vector[1] == 0 && a->vector[2] == 0) ? 1 : 0; break; case OP.OP_NOT_S: c->_float = (a->_string == 0 || String.IsNullOrEmpty(GetString(a->_string))) ? 1 : 0; break; case OP.OP_NOT_FNC: c->_float = (a->function == 0) ? 1 : 0; break; case OP.OP_NOT_ENT: c->_float = (PROG_TO_EDICT(a->edict) == sv.edicts[0]) ? 1 : 0; break; case OP.OP_EQ_F: c->_float = (a->_float == b->_float) ? 1 : 0; break; case OP.OP_EQ_V: c->_float = ((a->vector[0] == b->vector[0]) && (a->vector[1] == b->vector[1]) && (a->vector[2] == b->vector[2])) ? 1 : 0; break; case OP.OP_EQ_S: c->_float = (GetString(a->_string) == GetString(b->_string)) ? 1 : 0; //!strcmp(pr_strings + a->_string, pr_strings + b->_string); break; case OP.OP_EQ_E: c->_float = (a->_int == b->_int) ? 1 : 0; break; case OP.OP_EQ_FNC: c->_float = (a->function == b->function) ? 1 : 0; break; case OP.OP_NE_F: c->_float = (a->_float != b->_float) ? 1 : 0; break; case OP.OP_NE_V: c->_float = ((a->vector[0] != b->vector[0]) || (a->vector[1] != b->vector[1]) || (a->vector[2] != b->vector[2])) ? 1 : 0; break; case OP.OP_NE_S: c->_float = (GetString(a->_string) != GetString(b->_string)) ? 1 : 0; //strcmp(pr_strings + a->_string, pr_strings + b->_string); break; case OP.OP_NE_E: c->_float = (a->_int != b->_int) ? 1 : 0; break; case OP.OP_NE_FNC: c->_float = (a->function != b->function) ? 1 : 0; break; case OP.OP_STORE_F: case OP.OP_STORE_ENT: case OP.OP_STORE_FLD: // integers case OP.OP_STORE_S: case OP.OP_STORE_FNC: // pointers b->_int = a->_int; break; case OP.OP_STORE_V: b->vector[0] = a->vector[0]; b->vector[1] = a->vector[1]; b->vector[2] = a->vector[2]; break; case OP.OP_STOREP_F: case OP.OP_STOREP_ENT: case OP.OP_STOREP_FLD: // integers case OP.OP_STOREP_S: case OP.OP_STOREP_FNC: // pointers ed = EdictFromAddr(b->_int, out ofs); ed.StoreInt(ofs, a); break; case OP.OP_STOREP_V: ed = EdictFromAddr(b->_int, out ofs); ed.StoreVector(ofs, a); break; case OP.OP_ADDRESS: ed = PROG_TO_EDICT(a->edict); if (ed == sv.edicts[0] && sv.active) { PR_RunError("assignment to world entity"); } c->_int = MakeAddr(a->edict, b->_int); break; case OP.OP_LOAD_F: case OP.OP_LOAD_FLD: case OP.OP_LOAD_ENT: case OP.OP_LOAD_S: case OP.OP_LOAD_FNC: ed = PROG_TO_EDICT(a->edict); ed.LoadInt(b->_int, c); break; case OP.OP_LOAD_V: ed = PROG_TO_EDICT(a->edict); ed.LoadVector(b->_int, c); break; case OP.OP_IFNOT: if (a->_int == 0) { s += pr_statements[s].b - 1; // offset the s++ } break; case OP.OP_IF: if (a->_int != 0) { s += pr_statements[s].b - 1; // offset the s++ } break; case OP.OP_GOTO: s += pr_statements[s].a - 1; // offset the s++ break; case OP.OP_CALL0: case OP.OP_CALL1: case OP.OP_CALL2: case OP.OP_CALL3: case OP.OP_CALL4: case OP.OP_CALL5: case OP.OP_CALL6: case OP.OP_CALL7: case OP.OP_CALL8: pr_argc = pr_statements[s].op - (int)OP.OP_CALL0; if (a->function == 0) { PR_RunError("NULL function"); } dfunction_t newf = pr_functions[a->function]; if (newf.first_statement < 0) { // negative statements are built in functions int i = -newf.first_statement; if (i >= pr_builtins.Length) { PR_RunError("Bad builtin call number"); } Execute(i); break; } s = PR_EnterFunction(newf); break; case OP.OP_DONE: case OP.OP_RETURN: float *ptr = (float *)_GlobalStructAddr; int sta = pr_statements[s].a; ptr[q_shared.OFS_RETURN + 0] = *(float *)Get(sta); ptr[q_shared.OFS_RETURN + 1] = *(float *)Get(sta + 1); ptr[q_shared.OFS_RETURN + 2] = *(float *)Get(sta + 2); s = PR_LeaveFunction(); if (pr_depth == exitdepth) { return; // all done } break; case OP.OP_STATE: ed = PROG_TO_EDICT(pr_global_struct.self); #if FPS_20 ed->v.nextthink = pr_global_struct->time + 0.05; #else ed.v.nextthink = pr_global_struct.time + 0.1f; #endif if (a->_float != ed.v.frame) { ed.v.frame = a->_float; } ed.v.think = b->function; break; default: PR_RunError("Bad opcode %i", pr_statements[s].op); break; } } }