示例#1
0
文件: pr_exec.c 项目: jogi1/camquake
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);
		}
	}
}
示例#2
0
/*
================
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);
	}
}
示例#3
0
/*
====================
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);
	}
}

}
示例#4
0
void ED_PrintNum (int ent)
{
	ED_Print (EDICT_NUM(ent));
}
示例#5
0
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);
	}
}

}
示例#6
0
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 */
}
示例#7
0
文件: pr_exec.cpp 项目: m4c0/Quake
/*
====================
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);
	}
}

}
示例#8
0
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);
		}
	}
}