コード例 #1
0
ファイル: pr_edict.c プロジェクト: se-sss/ezquake-source
void PR_InitPatchTables (void)
{
	int i;

	if (pr_nqprogs) {
		memcpy (pr_globaloffsetpatch, pr_globaloffsetpatch_nq, sizeof(pr_globaloffsetpatch));
		for (i = 0; i < 106; i++) {
			pr_fieldoffsetpatch[i] = (i < 8) ? i : (i < 25) ? i + 1 :
				(i < 28) ? i + (102 - 25) : (i < 73) ? i - 2 :
				(i < 74) ? i + (105 - 73) : (i < 105) ? i - 3 : /* (i == 105) */ 8;
		}

		for (i=0 ; i<progs->numfielddefs ; i++)
			pr_fielddefs[i].ofs = PR_FIELDOFS(pr_fielddefs[i].ofs);
	}
	else
	{
		memset (pr_globaloffsetpatch, 0, sizeof(pr_globaloffsetpatch));

		for (i = 0; i < 106; i++)
			pr_fieldoffsetpatch[i] = i;
	}
}
コード例 #2
0
ファイル: pr_edict.cpp プロジェクト: luaman/zq
/*
===============
PR_LoadProgs
===============
*/
void PR_LoadProgs (void)
{
	int	i;
	char	num[32];
	static int lumpsize[6] = { sizeof(dstatement_t), sizeof(ddef_t),
		sizeof(ddef_t), sizeof(dfunction_t), 4, 4 };
	int	filesize = 0;
	const char	*progsname;

	progs = NULL;

	// decide whether to load qwprogs.dat, progs.dat or spprogs.dat

#ifdef WITH_NQPROGS
	if (Cvar_Value("sv_forcenqprogs"))
		goto use_progs;
#endif

	if (!deathmatch.value)
	{
		if (Q_stricmp(com_gamedirfile, "qw") && 
			strcmp(com_gamedirfile, ""))
		{
			// if we're using a custom mod, anything
			// in gamedir is preferred to stock *progs.dat
			qbool check;
			check = FS_FindFile ("spprogs.dat");
			if (check && file_from_gamedir)
				goto use_spprogs;
#ifdef WITH_NQPROGS
			check = FS_FindFile ("progs.dat");
			if (check && file_from_gamedir)
				goto use_progs;
#endif
			check = FS_FindFile ("qwprogs.dat");
			if (check && file_from_gamedir)
				goto use_qwprogs;
		}

use_spprogs:
		progs = (dprograms_t *) FS_LoadHunkFile ("spprogs.dat");
		progsname = "spprogs.dat";
		pr_nqprogs = false;

		if (!progs) {
#ifdef WITH_NQPROGS
use_progs:
			progs = (dprograms_t *)FS_LoadHunkFile ("progs.dat");
			progsname = "progs.dat";
			pr_nqprogs = true;
		}
#endif
		if (!progs) {
use_qwprogs:
			progs = (dprograms_t *)FS_LoadHunkFile ("qwprogs.dat");
			progsname = "qwprogs.dat";
			pr_nqprogs = false;
		}
	}
	else	// deathmatch
	{
		if (Q_stricmp(com_gamedirfile, "qw") && 
			strcmp(com_gamedirfile, ""))
		{
			qbool check;
			check = FS_FindFile ("qwprogs.dat");
			if (check && file_from_gamedir)
				goto dm_use_qwprogs;
#ifdef WITH_NQPROGS
			check = FS_FindFile ("progs.dat");
			if (check && file_from_gamedir)
				goto dm_use_progs;
#endif
		}

dm_use_qwprogs:
		progs = (dprograms_t *) FS_LoadHunkFile ("qwprogs.dat");
		progsname = "qwprogs.dat";
		pr_nqprogs = false;

		if (!progs) {
#ifdef WITH_NQPROGS
dm_use_progs:
			progs = (dprograms_t *)FS_LoadHunkFile ("progs.dat");
			progsname = "progs.dat";
			pr_nqprogs = true;
		}
#endif
	}

	if (!progs)
		Host_Error ("PR_LoadProgs: couldn't load progs.dat");

	filesize = fs_filesize;

	if (filesize < (int)sizeof(*progs))
		Host_Error("%s is corrupt", progsname);

	Com_DPrintf ("Using %s (%i bytes).\n", progsname, filesize);

// add prog crc to the serverinfo
	sprintf (num, "%i", CRC_Block ((byte *)progs, filesize));
	svs.info.set("*progs", num);

// byte swap the header
	for (i = 0; i < sizeof(*progs)/4; i++)
		((int *)progs)[i] = LittleLong ( ((int *)progs)[i] );		

	if (progs->version != PROG_VERSION)
		Host_Error ("progs.dat has wrong version number (%i should be %i)", progs->version, PROG_VERSION);
	if (progs->crc != (pr_nqprogs ? NQ_PROGHEADER_CRC : PROGHEADER_CRC))
		Host_Error ("You must have the qwprogs.dat from QuakeWorld installed");

// check lump offsets and sizes
	for (i = 0; i < 6; i ++) {
		if (((int *)progs)[i*2 + 2] < sizeof(*progs)
			|| ((int *)progs)[i*2 + 2] + ((int *)progs)[i*2 + 3]*lumpsize[i] > filesize)
		Host_Error("progs.dat is corrupt");
	}

	pr_functions = (dfunction_t *)((byte *)progs + progs->ofs_functions);
	pr_strings = (char *)progs + progs->ofs_strings;
	pr_globaldefs = (ddef_t *)((byte *)progs + progs->ofs_globaldefs);
	pr_fielddefs = (ddef_t *)((byte *)progs + progs->ofs_fielddefs);
	pr_statements = (dstatement_t *)((byte *)progs + progs->ofs_statements);
	pr_global_struct = (globalvars_t *)((byte *)progs + progs->ofs_globals);

	pr_globals = (float *)pr_global_struct;

	PR_InitStrings ();

	pr_edict_size = progs->entityfields * 4 + sizeof (edict_t) - sizeof(entvars_t);
	
// byte swap the lumps
	for (i=0 ; i<progs->numstatements ; i++)
	{
		pr_statements[i].op = LittleShort(pr_statements[i].op);
		pr_statements[i].a = LittleShort(pr_statements[i].a);
		pr_statements[i].b = LittleShort(pr_statements[i].b);
		pr_statements[i].c = LittleShort(pr_statements[i].c);
	}

	for (i=0 ; i<progs->numfunctions; i++)
	{
	pr_functions[i].first_statement = LittleLong (pr_functions[i].first_statement);
	pr_functions[i].parm_start = LittleLong (pr_functions[i].parm_start);
	pr_functions[i].s_name = LittleLong (pr_functions[i].s_name);
	pr_functions[i].s_file = LittleLong (pr_functions[i].s_file);
	pr_functions[i].numparms = LittleLong (pr_functions[i].numparms);
	pr_functions[i].locals = LittleLong (pr_functions[i].locals);
	}	

	for (i=0 ; i<progs->numglobaldefs ; i++)
	{
		pr_globaldefs[i].type = LittleShort (pr_globaldefs[i].type);
		pr_globaldefs[i].ofs = LittleShort (pr_globaldefs[i].ofs);
		pr_globaldefs[i].s_name = LittleLong (pr_globaldefs[i].s_name);
	}

	for (i=0 ; i<progs->numfielddefs ; i++)
	{
		pr_fielddefs[i].type = LittleShort (pr_fielddefs[i].type);
		if (pr_fielddefs[i].type & DEF_SAVEGLOBAL)
			Host_Error ("PR_LoadProgs: pr_fielddefs[i].type & DEF_SAVEGLOBAL");
		pr_fielddefs[i].ofs = LittleShort (pr_fielddefs[i].ofs);
		pr_fielddefs[i].s_name = LittleLong (pr_fielddefs[i].s_name);
	}


	for (i=0 ; i<progs->numglobals ; i++)
		((int *)pr_globals)[i] = LittleLong (((int *)pr_globals)[i]);


#ifdef WITH_NQPROGS
	if (pr_nqprogs) {
		memcpy (pr_globaloffsetpatch, pr_globaloffsetpatch_nq, sizeof(pr_globaloffsetpatch));
		for (i = 0; i < 106; i++) {
			pr_fieldoffsetpatch[i] = (i < 8) ? i : (i < 25) ? i + 1 :
				(i < 28) ? i + (102 - 25) : (i < 73) ? i - 2 :
				(i < 74) ? i + (105 - 73) : (i < 105) ? i - 3 : /* (i == 105) */ 8;
		}

		for (i=0 ; i<progs->numfielddefs ; i++)
			pr_fielddefs[i].ofs = PR_FIELDOFS(pr_fielddefs[i].ofs);
	}
	else
	{
		memset (pr_globaloffsetpatch, 0, sizeof(pr_globaloffsetpatch));

		for (i = 0; i < 106; i++)
			pr_fieldoffsetpatch[i] = i;
	}
#endif

	// find optional QC-exported functions
	SpectatorConnect = ED_FindFunctionOffset ("SpectatorConnect");
	SpectatorThink = ED_FindFunctionOffset ("SpectatorThink");
	SpectatorDisconnect = ED_FindFunctionOffset ("SpectatorDisconnect");
	GE_ClientCommand = ED_FindFunctionOffset ("GE_ClientCommand");
	GE_ConsoleCommand = ED_FindFunctionOffset ("GE_ConsoleCommand");
	GE_PausedTic = ED_FindFunctionOffset ("GE_PausedTic");
	GE_ShouldPause = ED_FindFunctionOffset ("GE_ShouldPause");

	// find optional QC-exported fields
	fofs_maxspeed = ED_FindFieldOffset ("maxspeed");
	fofs_gravity = ED_FindFieldOffset ("gravity");
	fofs_items2 = ED_FindFieldOffset ("items2");
	fofs_movement = ED_FindFieldOffset ("movement");
	fofs_vw_index = ED_FindFieldOffset ("vw_index");
	for (i = 3; i < 8; i++)
		fofs_buttonX[i-3] = ED_FindFieldOffset(va("button%i", i));

	// reset stuff like ZQ_CLIENTCOMMAND, progs must enable it explicitly
	memset (&pr_ext_enabled, sizeof(pr_ext_enabled), 0);

	PR_Exec_Init ();
}
コード例 #3
0
/*
====================
PR_ExecuteProgram

The interpretation main loop
====================
*/
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 == 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:
		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_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_game)
			PR_RunError ("assignment to world entity");
		c->_int = (byte *)((int *)&ed->v + PR_FIELDOFS(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 + PR_FIELDOFS(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 + PR_FIELDOFS(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 += (short)st->b - 1;	// offset the s++
		break;

	case OP_IF:
		if (a->_int)
			s += (short)st->b - 1;	// offset the s++
		break;

	case OP_GOTO:
		s += (short)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);
		ed->v.nextthink = pr_global_struct->time + 0.1;
		ed->v.frame = a->_float;
		ed->v.think = b->function;
		break;

	default:
		PR_RunError ("Bad opcode %i", st->op);
	}
}

}