Home | History | Annotate | Download | only in WinQuake
      1 /*
      2 Copyright (C) 1996-1997 Id Software, Inc.
      3 
      4 This program is free software; you can redistribute it and/or
      5 modify it under the terms of the GNU General Public License
      6 as published by the Free Software Foundation; either version 2
      7 of the License, or (at your option) any later version.
      8 
      9 This program is distributed in the hope that it will be useful,
     10 but WITHOUT ANY WARRANTY; without even the implied warranty of
     11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
     12 
     13 See the GNU General Public License for more details.
     14 
     15 You should have received a copy of the GNU General Public License
     16 along with this program; if not, write to the Free Software
     17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
     18 
     19 */
     20 
     21 #include "quakedef.h"
     22 
     23 
     24 /*
     25 
     26 */
     27 
     28 typedef struct
     29 {
     30 	int				s;
     31 	dfunction_t		*f;
     32 } prstack_t;
     33 
     34 #define	MAX_STACK_DEPTH		32
     35 prstack_t	pr_stack[MAX_STACK_DEPTH];
     36 int			pr_depth;
     37 
     38 #define	LOCALSTACK_SIZE		2048
     39 int			localstack[LOCALSTACK_SIZE];
     40 int			localstack_used;
     41 
     42 
     43 qboolean	pr_trace;
     44 dfunction_t	*pr_xfunction;
     45 int			pr_xstatement;
     46 
     47 
     48 int		pr_argc;
     49 
     50 const char *pr_opnames[] =
     51 {
     52 "DONE",
     53 
     54 "MUL_F",
     55 "MUL_V",
     56 "MUL_FV",
     57 "MUL_VF",
     58 
     59 "DIV",
     60 
     61 "ADD_F",
     62 "ADD_V",
     63 
     64 "SUB_F",
     65 "SUB_V",
     66 
     67 "EQ_F",
     68 "EQ_V",
     69 "EQ_S",
     70 "EQ_E",
     71 "EQ_FNC",
     72 
     73 "NE_F",
     74 "NE_V",
     75 "NE_S",
     76 "NE_E",
     77 "NE_FNC",
     78 
     79 "LE",
     80 "GE",
     81 "LT",
     82 "GT",
     83 
     84 "INDIRECT",
     85 "INDIRECT",
     86 "INDIRECT",
     87 "INDIRECT",
     88 "INDIRECT",
     89 "INDIRECT",
     90 
     91 "ADDRESS",
     92 
     93 "STORE_F",
     94 "STORE_V",
     95 "STORE_S",
     96 "STORE_ENT",
     97 "STORE_FLD",
     98 "STORE_FNC",
     99 
    100 "STOREP_F",
    101 "STOREP_V",
    102 "STOREP_S",
    103 "STOREP_ENT",
    104 "STOREP_FLD",
    105 "STOREP_FNC",
    106 
    107 "RETURN",
    108 
    109 "NOT_F",
    110 "NOT_V",
    111 "NOT_S",
    112 "NOT_ENT",
    113 "NOT_FNC",
    114 
    115 "IF",
    116 "IFNOT",
    117 
    118 "CALL0",
    119 "CALL1",
    120 "CALL2",
    121 "CALL3",
    122 "CALL4",
    123 "CALL5",
    124 "CALL6",
    125 "CALL7",
    126 "CALL8",
    127 
    128 "STATE",
    129 
    130 "GOTO",
    131 
    132 "AND",
    133 "OR",
    134 
    135 "BITAND",
    136 "BITOR"
    137 };
    138 
    139 char *PR_GlobalString (int ofs);
    140 char *PR_GlobalStringNoContents (int ofs);
    141 
    142 
    143 //=============================================================================
    144 
    145 /*
    146 =================
    147 PR_PrintStatement
    148 =================
    149 */
    150 void PR_PrintStatement (dstatement_t *s)
    151 {
    152 	int		i;
    153 
    154 	if ( (unsigned)s->op < sizeof(pr_opnames)/sizeof(pr_opnames[0]))
    155 	{
    156 		Con_Printf ("%s ",  pr_opnames[s->op]);
    157 		i = strlen(pr_opnames[s->op]);
    158 		for ( ; i<10 ; i++)
    159 			Con_Printf (" ");
    160 	}
    161 
    162 	if (s->op == OP_IF || s->op == OP_IFNOT)
    163 		Con_Printf ("%sbranch %i",PR_GlobalString(s->a),s->b);
    164 	else if (s->op == OP_GOTO)
    165 	{
    166 		Con_Printf ("branch %i",s->a);
    167 	}
    168 	else if ( (unsigned)(s->op - OP_STORE_F) < 6)
    169 	{
    170 		Con_Printf ("%s",PR_GlobalString(s->a));
    171 		Con_Printf ("%s", PR_GlobalStringNoContents(s->b));
    172 	}
    173 	else
    174 	{
    175 		if (s->a)
    176 			Con_Printf ("%s",PR_GlobalString(s->a));
    177 		if (s->b)
    178 			Con_Printf ("%s",PR_GlobalString(s->b));
    179 		if (s->c)
    180 			Con_Printf ("%s", PR_GlobalStringNoContents(s->c));
    181 	}
    182 	Con_Printf ("\n");
    183 }
    184 
    185 /*
    186 ============
    187 PR_StackTrace
    188 ============
    189 */
    190 void PR_StackTrace (void)
    191 {
    192 	dfunction_t	*f;
    193 	int			i;
    194 
    195 	if (pr_depth == 0)
    196 	{
    197 		Con_Printf ("<NO STACK>\n");
    198 		return;
    199 	}
    200 
    201 	pr_stack[pr_depth].f = pr_xfunction;
    202 	for (i=pr_depth ; i>=0 ; i--)
    203 	{
    204 		f = pr_stack[i].f;
    205 
    206 		if (!f)
    207 		{
    208 			Con_Printf ("<NO FUNCTION>\n");
    209 		}
    210 		else
    211 			Con_Printf ("%12s : %s\n", pr_strings + f->s_file, pr_strings + f->s_name);
    212 	}
    213 }
    214 
    215 
    216 /*
    217 ============
    218 PR_Profile_f
    219 
    220 ============
    221 */
    222 void PR_Profile_f (void)
    223 {
    224 	dfunction_t	*f, *best;
    225 	int			max;
    226 	int			num;
    227 	int			i;
    228 
    229 	num = 0;
    230 	do
    231 	{
    232 		max = 0;
    233 		best = NULL;
    234 		for (i=0 ; i<progs->numfunctions ; i++)
    235 		{
    236 			f = &pr_functions[i];
    237 			if (f->profile > max)
    238 			{
    239 				max = f->profile;
    240 				best = f;
    241 			}
    242 		}
    243 		if (best)
    244 		{
    245 			if (num < 10)
    246 				Con_Printf ("%7i %s\n", best->profile, pr_strings+best->s_name);
    247 			num++;
    248 			best->profile = 0;
    249 		}
    250 	} while (best);
    251 }
    252 
    253 
    254 /*
    255 ============
    256 PR_RunError
    257 
    258 Aborts the currently executing function
    259 ============
    260 */
    261 void PR_RunError (const char *error, ...)
    262 {
    263 	va_list		argptr;
    264 	char		string[1024];
    265 
    266 	va_start (argptr,error);
    267 	vsprintf (string,error,argptr);
    268 	va_end (argptr);
    269 
    270 	PR_PrintStatement (pr_statements + pr_xstatement);
    271 	PR_StackTrace ();
    272 	Con_Printf ("%s\n", string);
    273 
    274 	pr_depth = 0;		// dump the stack so host_error can shutdown functions
    275 
    276 	Host_Error ("Program error");
    277 }
    278 
    279 /*
    280 ============================================================================
    281 PR_ExecuteProgram
    282 
    283 The interpretation main loop
    284 ============================================================================
    285 */
    286 
    287 /*
    288 ====================
    289 PR_EnterFunction
    290 
    291 Returns the new program statement counter
    292 ====================
    293 */
    294 int PR_EnterFunction (dfunction_t *f)
    295 {
    296 	int		i, j, c, o;
    297 
    298 	pr_stack[pr_depth].s = pr_xstatement;
    299 	pr_stack[pr_depth].f = pr_xfunction;
    300 	pr_depth++;
    301 	if (pr_depth >= MAX_STACK_DEPTH)
    302 		PR_RunError ("stack overflow");
    303 
    304 // save off any locals that the new function steps on
    305 	c = f->locals;
    306 	if (localstack_used + c > LOCALSTACK_SIZE)
    307 		PR_RunError ("PR_ExecuteProgram: locals stack overflow\n");
    308 
    309 	for (i=0 ; i < c ; i++)
    310 		localstack[localstack_used+i] = ((int *)pr_globals)[f->parm_start + i];
    311 	localstack_used += c;
    312 
    313 // copy parameters
    314 	o = f->parm_start;
    315 	for (i=0 ; i<f->numparms ; i++)
    316 	{
    317 		for (j=0 ; j<f->parm_size[i] ; j++)
    318 		{
    319 			((int *)pr_globals)[o] = ((int *)pr_globals)[OFS_PARM0+i*3+j];
    320 			o++;
    321 		}
    322 	}
    323 
    324 	pr_xfunction = f;
    325 	return f->first_statement - 1;	// offset the s++
    326 }
    327 
    328 /*
    329 ====================
    330 PR_LeaveFunction
    331 ====================
    332 */
    333 int PR_LeaveFunction (void)
    334 {
    335 	int		i, c;
    336 
    337 	if (pr_depth <= 0)
    338 		Sys_Error ("prog stack underflow");
    339 
    340 // restore locals from the stack
    341 	c = pr_xfunction->locals;
    342 	localstack_used -= c;
    343 	if (localstack_used < 0)
    344 		PR_RunError ("PR_ExecuteProgram: locals stack underflow\n");
    345 
    346 	for (i=0 ; i < c ; i++)
    347 		((int *)pr_globals)[pr_xfunction->parm_start + i] = localstack[localstack_used+i];
    348 
    349 // up stack
    350 	pr_depth--;
    351 	pr_xfunction = pr_stack[pr_depth].f;
    352 	return pr_stack[pr_depth].s;
    353 }
    354 
    355 
    356 /*
    357 ====================
    358 PR_ExecuteProgram
    359 ====================
    360 */
    361 void PR_ExecuteProgram (func_t fnum)
    362 {
    363 	eval_t	*a, *b, *c;
    364 	int			s;
    365 	dstatement_t	*st;
    366 	dfunction_t	*f, *newf;
    367 	int		runaway;
    368 	int		i;
    369 	edict_t	*ed;
    370 	int		exitdepth;
    371 	eval_t	*ptr;
    372 
    373 	if (!fnum || fnum >= progs->numfunctions)
    374 	{
    375 		if (pr_global_struct->self)
    376 			ED_Print (PROG_TO_EDICT(pr_global_struct->self));
    377 		Host_Error ("PR_ExecuteProgram: NULL function");
    378 	}
    379 
    380 	f = &pr_functions[fnum];
    381 
    382 	runaway = 100000;
    383 	pr_trace = false;
    384 
    385 // make a stack frame
    386 	exitdepth = pr_depth;
    387 
    388 	s = PR_EnterFunction (f);
    389 
    390 while (1)
    391 {
    392 	s++;	// next statement
    393 
    394 	st = &pr_statements[s];
    395 	a = (eval_t *)&pr_globals[st->a];
    396 	b = (eval_t *)&pr_globals[st->b];
    397 	c = (eval_t *)&pr_globals[st->c];
    398 
    399 	if (!--runaway)
    400 		PR_RunError ("runaway loop error");
    401 
    402 	pr_xfunction->profile++;
    403 	pr_xstatement = s;
    404 
    405 	if (pr_trace)
    406 		PR_PrintStatement (st);
    407 
    408 	switch (st->op)
    409 	{
    410 	case OP_ADD_F:
    411 		c->_float = a->_float + b->_float;
    412 		break;
    413 	case OP_ADD_V:
    414 		c->vector[0] = a->vector[0] + b->vector[0];
    415 		c->vector[1] = a->vector[1] + b->vector[1];
    416 		c->vector[2] = a->vector[2] + b->vector[2];
    417 		break;
    418 
    419 	case OP_SUB_F:
    420 		c->_float = a->_float - b->_float;
    421 		break;
    422 	case OP_SUB_V:
    423 		c->vector[0] = a->vector[0] - b->vector[0];
    424 		c->vector[1] = a->vector[1] - b->vector[1];
    425 		c->vector[2] = a->vector[2] - b->vector[2];
    426 		break;
    427 
    428 	case OP_MUL_F:
    429 		c->_float = a->_float * b->_float;
    430 		break;
    431 	case OP_MUL_V:
    432 		c->_float = a->vector[0]*b->vector[0]
    433 				+ a->vector[1]*b->vector[1]
    434 				+ a->vector[2]*b->vector[2];
    435 		break;
    436 	case OP_MUL_FV:
    437 		c->vector[0] = a->_float * b->vector[0];
    438 		c->vector[1] = a->_float * b->vector[1];
    439 		c->vector[2] = a->_float * b->vector[2];
    440 		break;
    441 	case OP_MUL_VF:
    442 		c->vector[0] = b->_float * a->vector[0];
    443 		c->vector[1] = b->_float * a->vector[1];
    444 		c->vector[2] = b->_float * a->vector[2];
    445 		break;
    446 
    447 	case OP_DIV_F:
    448 		c->_float = a->_float / b->_float;
    449 		break;
    450 
    451 	case OP_BITAND:
    452 		c->_float = (int)a->_float & (int)b->_float;
    453 		break;
    454 
    455 	case OP_BITOR:
    456 		c->_float = (int)a->_float | (int)b->_float;
    457 		break;
    458 
    459 
    460 	case OP_GE:
    461 		c->_float = a->_float >= b->_float;
    462 		break;
    463 	case OP_LE:
    464 		c->_float = a->_float <= b->_float;
    465 		break;
    466 	case OP_GT:
    467 		c->_float = a->_float > b->_float;
    468 		break;
    469 	case OP_LT:
    470 		c->_float = a->_float < b->_float;
    471 		break;
    472 	case OP_AND:
    473 		c->_float = a->_float && b->_float;
    474 		break;
    475 	case OP_OR:
    476 		c->_float = a->_float || b->_float;
    477 		break;
    478 
    479 	case OP_NOT_F:
    480 		c->_float = !a->_float;
    481 		break;
    482 	case OP_NOT_V:
    483 		c->_float = !a->vector[0] && !a->vector[1] && !a->vector[2];
    484 		break;
    485 	case OP_NOT_S:
    486 		c->_float = !a->string || !pr_strings[a->string];
    487 		break;
    488 	case OP_NOT_FNC:
    489 		c->_float = !a->function;
    490 		break;
    491 	case OP_NOT_ENT:
    492 		c->_float = (PROG_TO_EDICT(a->edict) == sv.edicts);
    493 		break;
    494 
    495 	case OP_EQ_F:
    496 		c->_float = a->_float == b->_float;
    497 		break;
    498 	case OP_EQ_V:
    499 		c->_float = (a->vector[0] == b->vector[0]) &&
    500 					(a->vector[1] == b->vector[1]) &&
    501 					(a->vector[2] == b->vector[2]);
    502 		break;
    503 	case OP_EQ_S:
    504 		c->_float = !strcmp(pr_strings+a->string,pr_strings+b->string);
    505 		break;
    506 	case OP_EQ_E:
    507 		c->_float = a->_int == b->_int;
    508 		break;
    509 	case OP_EQ_FNC:
    510 		c->_float = a->function == b->function;
    511 		break;
    512 
    513 
    514 	case OP_NE_F:
    515 		c->_float = a->_float != b->_float;
    516 		break;
    517 	case OP_NE_V:
    518 		c->_float = (a->vector[0] != b->vector[0]) ||
    519 					(a->vector[1] != b->vector[1]) ||
    520 					(a->vector[2] != b->vector[2]);
    521 		break;
    522 	case OP_NE_S:
    523 		c->_float = strcmp(pr_strings+a->string,pr_strings+b->string);
    524 		break;
    525 	case OP_NE_E:
    526 		c->_float = a->_int != b->_int;
    527 		break;
    528 	case OP_NE_FNC:
    529 		c->_float = a->function != b->function;
    530 		break;
    531 
    532 //==================
    533 	case OP_STORE_F:
    534 	case OP_STORE_ENT:
    535 	case OP_STORE_FLD:		// integers
    536 	case OP_STORE_S:
    537 	case OP_STORE_FNC:		// pointers
    538 		b->_int = a->_int;
    539 		break;
    540 	case OP_STORE_V:
    541 		b->vector[0] = a->vector[0];
    542 		b->vector[1] = a->vector[1];
    543 		b->vector[2] = a->vector[2];
    544 		break;
    545 
    546 	case OP_STOREP_F:
    547 	case OP_STOREP_ENT:
    548 	case OP_STOREP_FLD:		// integers
    549 	case OP_STOREP_S:
    550 	case OP_STOREP_FNC:		// pointers
    551 		ptr = (eval_t *)((byte *)sv.edicts + b->_int);
    552 		ptr->_int = a->_int;
    553 		break;
    554 	case OP_STOREP_V:
    555 		ptr = (eval_t *)((byte *)sv.edicts + b->_int);
    556 		ptr->vector[0] = a->vector[0];
    557 		ptr->vector[1] = a->vector[1];
    558 		ptr->vector[2] = a->vector[2];
    559 		break;
    560 
    561 	case OP_ADDRESS:
    562 		ed = PROG_TO_EDICT(a->edict);
    563 #ifdef PARANOID
    564 		NUM_FOR_EDICT(ed);		// make sure it's in range
    565 #endif
    566 		if (ed == (edict_t *)sv.edicts && sv.state == ss_active)
    567 			PR_RunError ("assignment to world entity");
    568 		c->_int = (byte *)(ed->u.i + b->_int) - (byte *)sv.edicts;
    569 		break;
    570 
    571 	case OP_LOAD_F:
    572 	case OP_LOAD_FLD:
    573 	case OP_LOAD_ENT:
    574 	case OP_LOAD_S:
    575 	case OP_LOAD_FNC:
    576 		ed = PROG_TO_EDICT(a->edict);
    577 #ifdef PARANOID
    578 		NUM_FOR_EDICT(ed);		// make sure it's in range
    579 #endif
    580 		a = (eval_t *)(ed->u.i + b->_int);
    581 		c->_int = a->_int;
    582 		break;
    583 
    584 	case OP_LOAD_V:
    585 		ed = PROG_TO_EDICT(a->edict);
    586 #ifdef PARANOID
    587 		NUM_FOR_EDICT(ed);		// make sure it's in range
    588 #endif
    589 		a = (eval_t *)(ed->u.i + b->_int);
    590 		c->vector[0] = a->vector[0];
    591 		c->vector[1] = a->vector[1];
    592 		c->vector[2] = a->vector[2];
    593 		break;
    594 
    595 //==================
    596 
    597 	case OP_IFNOT:
    598 		if (!a->_int)
    599 			s += st->b - 1;	// offset the s++
    600 		break;
    601 
    602 	case OP_IF:
    603 		if (a->_int)
    604 			s += st->b - 1;	// offset the s++
    605 		break;
    606 
    607 	case OP_GOTO:
    608 		s += st->a - 1;	// offset the s++
    609 		break;
    610 
    611 	case OP_CALL0:
    612 	case OP_CALL1:
    613 	case OP_CALL2:
    614 	case OP_CALL3:
    615 	case OP_CALL4:
    616 	case OP_CALL5:
    617 	case OP_CALL6:
    618 	case OP_CALL7:
    619 	case OP_CALL8:
    620 		pr_argc = st->op - OP_CALL0;
    621 		if (!a->function)
    622 			PR_RunError ("NULL function");
    623 
    624 		newf = &pr_functions[a->function];
    625 
    626 		if (newf->first_statement < 0)
    627 		{	// negative statements are built in functions
    628 			i = -newf->first_statement;
    629 			if (i >= pr_numbuiltins)
    630 				PR_RunError ("Bad builtin call number");
    631 			pr_builtins[i] ();
    632 			break;
    633 		}
    634 
    635 		s = PR_EnterFunction (newf);
    636 		break;
    637 
    638 	case OP_DONE:
    639 	case OP_RETURN:
    640 		pr_globals[OFS_RETURN] = pr_globals[st->a];
    641 		pr_globals[OFS_RETURN+1] = pr_globals[st->a+1];
    642 		pr_globals[OFS_RETURN+2] = pr_globals[st->a+2];
    643 
    644 		s = PR_LeaveFunction ();
    645 		if (pr_depth == exitdepth)
    646 			return;		// all done
    647 		break;
    648 
    649 	case OP_STATE:
    650 		ed = PROG_TO_EDICT(pr_global_struct->self);
    651 #ifdef FPS_20
    652 		ed->u.v.nextthink = pr_global_struct->time + 0.05;
    653 #else
    654 		ed->u.v.nextthink = pr_global_struct->time + 0.1;
    655 #endif
    656 		if (a->_float != ed->u.v.frame)
    657 		{
    658 			ed->u.v.frame = a->_float;
    659 		}
    660 		ed->u.v.think = b->function;
    661 		break;
    662 
    663 	default:
    664 		PR_RunError ("Bad opcode %i", st->op);
    665 	}
    666 }
    667 
    668 }
    669