1 /*
2  * pr_exec.c -- PROGS execution
3  * $Id: pr_exec.c 6039 2018-05-30 04:01:21Z sezero $
4  *
5  * Copyright (C) 1996-1997  Id Software, Inc.
6  * Copyright (C) 1997-1998  Raven Software Corp.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or (at
11  * your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16  *
17  * See the GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22  */
23 
24 
25 // HEADER FILES ------------------------------------------------------------
26 
27 #include "quakedef.h"
28 #include "q_ctype.h"
29 
30 // MACROS ------------------------------------------------------------------
31 
32 #define MAX_STACK_DEPTH	64	/* was 32 */
33 #define LOCALSTACK_SIZE	2048
34 
35 // TYPES -------------------------------------------------------------------
36 
37 typedef struct
38 {
39 	int		s;
40 	dfunction_t	*f;
41 } prstack_t;
42 
43 /* switch types */
44 enum {
45 	SWITCH_F,
46 	SWITCH_V,
47 	SWITCH_S,
48 	SWITCH_E,
49 	SWITCH_FNC
50 };
51 
52 // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
53 
54 const char *PR_GlobalString(int ofs);
55 const char *PR_GlobalStringNoContents(int ofs);
56 
57 // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
58 
59 // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
60 
61 static int EnterFunction(dfunction_t *f);
62 static int LeaveFunction(void);
63 static void PrintStatement(dstatement_t *s);
64 static void PrintCallHistory(void);
65 
66 // EXTERNAL DATA DECLARATIONS ----------------------------------------------
67 
68 // PUBLIC DATA DEFINITIONS -------------------------------------------------
69 
70 qboolean	pr_trace;
71 dfunction_t	*pr_xfunction;
72 int		pr_xstatement;
73 int		pr_argc;
74 
75 // PRIVATE DATA DEFINITIONS ------------------------------------------------
76 
77 static prstack_t pr_stack[MAX_STACK_DEPTH];
78 static int pr_depth;
79 static int localstack[LOCALSTACK_SIZE];
80 static int localstack_used;
81 
82 static const char *pr_opnames[] =
83 {
84 	"DONE",
85 	"MUL_F", "MUL_V",  "MUL_FV", "MUL_VF",
86 	"DIV",
87 	"ADD_F", "ADD_V",
88 	"SUB_F", "SUB_V",
89 	"EQ_F", "EQ_V", "EQ_S", "EQ_E", "EQ_FNC",
90 	"NE_F", "NE_V", "NE_S", "NE_E", "NE_FNC",
91 	"LE", "GE", "LT", "GT",
92 	"INDIRECT", "INDIRECT", "INDIRECT",
93 	"INDIRECT", "INDIRECT", "INDIRECT",
94 	"ADDRESS",
95 	"STORE_F", "STORE_V", "STORE_S",
96 	"STORE_ENT", "STORE_FLD", "STORE_FNC",
97 	"STOREP_F", "STOREP_V", "STOREP_S",
98 	"STOREP_ENT", "STOREP_FLD", "STOREP_FNC",
99 	"RETURN",
100 	"NOT_F", "NOT_V", "NOT_S", "NOT_ENT", "NOT_FNC",
101 	"IF", "IFNOT",
102 	"CALL0", "CALL1", "CALL2", "CALL3", "CALL4",
103 	"CALL5", "CALL6", "CALL7", "CALL8",
104 	"STATE",
105 	"GOTO",
106 	"AND", "OR",
107 	"BITAND", "BITOR",
108 	"OP_MULSTORE_F", "OP_MULSTORE_V", "OP_MULSTOREP_F", "OP_MULSTOREP_V",
109 	"OP_DIVSTORE_F", "OP_DIVSTOREP_F",
110 	"OP_ADDSTORE_F", "OP_ADDSTORE_V", "OP_ADDSTOREP_F", "OP_ADDSTOREP_V",
111 	"OP_SUBSTORE_F", "OP_SUBSTORE_V", "OP_SUBSTOREP_F", "OP_SUBSTOREP_V",
112 	"OP_FETCH_GBL_F",
113 	"OP_FETCH_GBL_V",
114 	"OP_FETCH_GBL_S",
115 	"OP_FETCH_GBL_E",
116 	"OP_FETCH_GBL_FNC",
117 	"OP_CSTATE", "OP_CWSTATE",
118 
119 	"OP_THINKTIME",
120 
121 	"OP_BITSET", "OP_BITSETP", "OP_BITCLR",	"OP_BITCLRP",
122 
123 	"OP_RAND0", "OP_RAND1",	"OP_RAND2",	"OP_RANDV0", "OP_RANDV1", "OP_RANDV2",
124 
125 	"OP_SWITCH_F", "OP_SWITCH_V", "OP_SWITCH_S", "OP_SWITCH_E", "OP_SWITCH_FNC",
126 
127 	"OP_CASE",
128 	"OP_CASERANGE"
129 
130 };
131 
132 // CODE --------------------------------------------------------------------
133 
134 //==========================================================================
135 //
136 // PR_ExecuteProgram
137 //
138 //==========================================================================
139 
140 #if 0
141 #define OPA ((eval_t *)&pr_globals[(unsigned short)st->a])
142 #define OPB ((eval_t *)&pr_globals[(unsigned short)st->b])
143 #define OPC ((eval_t *)&pr_globals[(unsigned short)st->c])
144 #else
145 /* unsigned short casts were needed with progs version 6.
146  * we are now processing progs internally as version 7. */
147 #define OPA ((eval_t *)&pr_globals[st->a])
148 #define OPB ((eval_t *)&pr_globals[st->b])
149 #define OPC ((eval_t *)&pr_globals[st->c])
150 #endif
151 
PR_ExecuteProgram(func_t fnum)152 void PR_ExecuteProgram (func_t fnum)
153 {
154 	eval_t		*ptr, *a, *b, *c;
155 	float		*vecptr;
156 	dstatement_t	*st;
157 	dfunction_t	*f, *newf;
158 	edict_t		*ed;
159 	int		jump_ofs;
160 	int exitdepth;
161 	int profile, startprofile;
162 	/* switch/case support:  */
163 	int	case_type = -1;
164 	float	switch_float = 0;
165 
166 	if (!fnum || fnum >= progs->numfunctions)
167 	{
168 		if (*sv_globals.self)
169 		{
170 			ED_Print(PROG_TO_EDICT(*sv_globals.self));
171 		}
172 		Host_Error("%s: NULL function", __thisfunc__);
173 	}
174 
175 	f = &pr_functions[fnum];
176 
177 	pr_trace = false;
178 
179 	exitdepth = pr_depth;
180 
181 	st = &pr_statements[EnterFunction(f)];
182 	startprofile = profile = 0;
183 
184     while (1)
185     {
186 	st++;	/* next statement */
187 	a = OPA;
188 	b = OPB;
189 	c = OPC;
190 
191 	if (++profile > 100000)
192 	{
193 		pr_xstatement = st - pr_statements;
194 		PR_RunError("runaway loop error");
195 	}
196 
197 	if (pr_trace)
198 	{
199 		PrintStatement(st);
200 	}
201 
202 	switch (st->op)
203 	{
204 	case OP_ADD_F:
205 		c->_float = a->_float + b->_float;
206 		break;
207 	case OP_ADD_V:
208 		c->vector[0] = a->vector[0] + b->vector[0];
209 		c->vector[1] = a->vector[1] + b->vector[1];
210 		c->vector[2] = a->vector[2] + b->vector[2];
211 		break;
212 
213 	case OP_SUB_F:
214 		c->_float = a->_float - b->_float;
215 		break;
216 	case OP_SUB_V:
217 		c->vector[0] = a->vector[0] - b->vector[0];
218 		c->vector[1] = a->vector[1] - b->vector[1];
219 		c->vector[2] = a->vector[2] - b->vector[2];
220 		break;
221 
222 	case OP_MUL_F:
223 		c->_float = a->_float * b->_float;
224 		break;
225 	case OP_MUL_V:
226 		c->_float = a->vector[0] * b->vector[0] +
227 			    a->vector[1] * b->vector[1] +
228 			    a->vector[2] * b->vector[2];
229 		break;
230 	case OP_MUL_FV:
231 		c->vector[0] = a->_float * b->vector[0];
232 		c->vector[1] = a->_float * b->vector[1];
233 		c->vector[2] = a->_float * b->vector[2];
234 		break;
235 	case OP_MUL_VF:
236 		c->vector[0] = b->_float * a->vector[0];
237 		c->vector[1] = b->_float * a->vector[1];
238 		c->vector[2] = b->_float * a->vector[2];
239 		break;
240 
241 	case OP_DIV_F:
242 		c->_float = a->_float / b->_float;
243 		break;
244 
245 	case OP_BITAND:
246 		c->_float = (int)a->_float & (int)b->_float;
247 		break;
248 
249 	case OP_BITOR:
250 		c->_float = (int)a->_float | (int)b->_float;
251 		break;
252 
253 	case OP_GE:
254 		c->_float = a->_float >= b->_float;
255 		break;
256 	case OP_LE:
257 		c->_float = a->_float <= b->_float;
258 		break;
259 	case OP_GT:
260 		c->_float = a->_float > b->_float;
261 		break;
262 	case OP_LT:
263 		c->_float = a->_float < b->_float;
264 		break;
265 	case OP_AND:
266 		c->_float = a->_float && b->_float;
267 		break;
268 	case OP_OR:
269 		c->_float = a->_float || b->_float;
270 		break;
271 
272 	case OP_NOT_F:
273 		c->_float = !a->_float;
274 		break;
275 	case OP_NOT_V:
276 		c->_float = !a->vector[0] && !a->vector[1] && !a->vector[2];
277 		break;
278 	case OP_NOT_S:
279 		c->_float = !a->string || !*PR_GetString(a->string);
280 		break;
281 	case OP_NOT_FNC:
282 		c->_float = !a->function;
283 		break;
284 	case OP_NOT_ENT:
285 		c->_float = (PROG_TO_EDICT(a->edict) == sv.edicts);
286 		break;
287 
288 	case OP_EQ_F:
289 		c->_float = a->_float == b->_float;
290 		break;
291 	case OP_EQ_V:
292 		c->_float = (a->vector[0] == b->vector[0]) &&
293 			    (a->vector[1] == b->vector[1]) &&
294 			    (a->vector[2] == b->vector[2]);
295 		break;
296 	case OP_EQ_S:
297 		c->_float = !strcmp(PR_GetString(a->string), PR_GetString(b->string));
298 		break;
299 	case OP_EQ_E:
300 		c->_float = a->_int == b->_int;
301 		break;
302 	case OP_EQ_FNC:
303 		c->_float = a->function == b->function;
304 		break;
305 
306 	case OP_NE_F:
307 		c->_float = a->_float != b->_float;
308 		break;
309 	case OP_NE_V:
310 		c->_float = (a->vector[0] != b->vector[0]) ||
311 			    (a->vector[1] != b->vector[1]) ||
312 			    (a->vector[2] != b->vector[2]);
313 		break;
314 	case OP_NE_S:
315 		c->_float = strcmp(PR_GetString(a->string), PR_GetString(b->string));
316 		break;
317 	case OP_NE_E:
318 		c->_float = a->_int != b->_int;
319 		break;
320 	case OP_NE_FNC:
321 		c->_float = a->function != b->function;
322 		break;
323 
324 	case OP_STORE_F:
325 	case OP_STORE_ENT:
326 	case OP_STORE_FLD:	// integers
327 	case OP_STORE_S:
328 	case OP_STORE_FNC:	// pointers
329 		b->_int = a->_int;
330 		break;
331 	case OP_STORE_V:
332 		b->vector[0] = a->vector[0];
333 		b->vector[1] = a->vector[1];
334 		b->vector[2] = a->vector[2];
335 		break;
336 
337 	case OP_STOREP_F:
338 	case OP_STOREP_ENT:
339 	case OP_STOREP_FLD:	// integers
340 	case OP_STOREP_S:
341 	case OP_STOREP_FNC:	// pointers
342 		ptr = (eval_t *)((byte *)sv.edicts + b->_int);
343 		ptr->_int = a->_int;
344 		break;
345 	case OP_STOREP_V:
346 		ptr = (eval_t *)((byte *)sv.edicts + b->_int);
347 		ptr->vector[0] = a->vector[0];
348 		ptr->vector[1] = a->vector[1];
349 		ptr->vector[2] = a->vector[2];
350 		break;
351 
352 	case OP_MULSTORE_F:	// f *= f
353 		b->_float *= a->_float;
354 		break;
355 	case OP_MULSTORE_V:	// v *= f
356 		b->vector[0] *= a->_float;
357 		b->vector[1] *= a->_float;
358 		b->vector[2] *= a->_float;
359 		break;
360 	case OP_MULSTOREP_F:	// e.f *= f
361 		ptr = (eval_t *)((byte *)sv.edicts + b->_int);
362 		c->_float = (ptr->_float *= a->_float);
363 		break;
364 	case OP_MULSTOREP_V:	// e.v *= f
365 		ptr = (eval_t *)((byte *)sv.edicts + b->_int);
366 		c->vector[0] = (ptr->vector[0] *= a->_float);
367 		c->vector[0] = (ptr->vector[1] *= a->_float);
368 		c->vector[0] = (ptr->vector[2] *= a->_float);
369 		break;
370 
371 	case OP_DIVSTORE_F:	// f /= f
372 		b->_float /= a->_float;
373 		break;
374 	case OP_DIVSTOREP_F:	// e.f /= f
375 		ptr = (eval_t *)((byte *)sv.edicts + b->_int);
376 		c->_float = (ptr->_float /= a->_float);
377 		break;
378 
379 	case OP_ADDSTORE_F:	// f += f
380 		b->_float += a->_float;
381 		break;
382 	case OP_ADDSTORE_V:	// v += v
383 		b->vector[0] += a->vector[0];
384 		b->vector[1] += a->vector[1];
385 		b->vector[2] += a->vector[2];
386 		break;
387 	case OP_ADDSTOREP_F:	// e.f += f
388 		ptr = (eval_t *)((byte *)sv.edicts + b->_int);
389 		c->_float = (ptr->_float += a->_float);
390 		break;
391 	case OP_ADDSTOREP_V:	// e.v += v
392 		ptr = (eval_t *)((byte *)sv.edicts + b->_int);
393 		c->vector[0] = (ptr->vector[0] += a->vector[0]);
394 		c->vector[1] = (ptr->vector[1] += a->vector[1]);
395 		c->vector[2] = (ptr->vector[2] += a->vector[2]);
396 		break;
397 
398 	case OP_SUBSTORE_F:	// f -= f
399 		b->_float -= a->_float;
400 		break;
401 	case OP_SUBSTORE_V:	// v -= v
402 		b->vector[0] -= a->vector[0];
403 		b->vector[1] -= a->vector[1];
404 		b->vector[2] -= a->vector[2];
405 		break;
406 	case OP_SUBSTOREP_F:	// e.f -= f
407 		ptr = (eval_t *)((byte *)sv.edicts + b->_int);
408 		c->_float = (ptr->_float -= a->_float);
409 		break;
410 	case OP_SUBSTOREP_V:	// e.v -= v
411 		ptr = (eval_t *)((byte *)sv.edicts + b->_int);
412 		c->vector[0] = (ptr->vector[0] -= a->vector[0]);
413 		c->vector[1] = (ptr->vector[1] -= a->vector[1]);
414 		c->vector[2] = (ptr->vector[2] -= a->vector[2]);
415 		break;
416 
417 	case OP_ADDRESS:
418 		ed = PROG_TO_EDICT(a->edict);
419 #ifdef PARANOID
420 		NUM_FOR_EDICT(ed);	// Make sure it's in range
421 #endif
422 		if (ed == (edict_t *)sv.edicts && sv.state == ss_active)
423 		{
424 			pr_xstatement = st - pr_statements;
425 			PR_RunError("assignment to world entity");
426 		}
427 		c->_int = (byte *)((int *)&ed->v + b->_int) - (byte *)sv.edicts;
428 		break;
429 
430 	case OP_LOAD_F:
431 	case OP_LOAD_FLD:
432 	case OP_LOAD_ENT:
433 	case OP_LOAD_S:
434 	case OP_LOAD_FNC:
435 		ed = PROG_TO_EDICT(a->edict);
436 #ifdef PARANOID
437 		NUM_FOR_EDICT(ed);	// Make sure it's in range
438 #endif
439 		ptr = (eval_t *)((int *)&ed->v + b->_int);
440 		c->_int = ptr->_int;
441 		break;
442 
443 	case OP_LOAD_V:
444 		ed = PROG_TO_EDICT(a->edict);
445 #ifdef PARANOID
446 		NUM_FOR_EDICT(ed);	// Make sure it's in range
447 #endif
448 		ptr = (eval_t *)((int *)&ed->v + b->_int);
449 		c->vector[0] = ptr->vector[0];
450 		c->vector[1] = ptr->vector[1];
451 		c->vector[2] = ptr->vector[2];
452 		break;
453 
454 	case OP_FETCH_GBL_F:
455 	case OP_FETCH_GBL_S:
456 	case OP_FETCH_GBL_E:
457 	case OP_FETCH_GBL_FNC:
458 	  {	int i = (int)b->_float;
459 		if (i < 0 || i > G_INT(st->a - 1))
460 		{
461 			pr_xstatement = st - pr_statements;
462 			PR_RunError("array index out of bounds: %d", i);
463 		}
464 		ptr = (eval_t *)&pr_globals[st->a + i];
465 		c->_int = ptr->_int;
466 	  }	break;
467 	case OP_FETCH_GBL_V:
468 	  {	int i = (int)b->_float;
469 		if (i < 0 || i > G_INT(st->a - 1))
470 		{
471 			pr_xstatement = st - pr_statements;
472 			PR_RunError("array index out of bounds: %d", i);
473 		}
474 		ptr = (eval_t *)&pr_globals[st->a + (i * 3)];
475 		c->vector[0] = ptr->vector[0];
476 		c->vector[1] = ptr->vector[1];
477 		c->vector[2] = ptr->vector[2];
478 	  }	break;
479 
480 	case OP_IFNOT:
481 		if (!a->_int)
482 		{
483 		/* Pa3PyX: a, b, and c used to be signed shorts for progs v6,
484 		 * now they are signed ints.  The problem is, they were used
485 		 * as signed sometimes and as unsigned other times - most of
486 		 * the time they were used as unsigned with an explicit cast
487 		 * in PR_ExecuteProgram().  When we convert the old progs to
488 		 * to the new format in PR_ConvertOldStmts(), we zero-extend
489 		 * them instead of sign-extending them for that reason: if we
490 		 * sign-extend them, most of the code will not work - we will
491 		 * have negative array offsets in PR_ExecuteProgram(), among
492 		 * other things.  Note that they are cast to unsigned short
493 		 * in PR_ConvertOldStmts() prior to assigning them to what is
494 		 * now int.  There are a few instances where these shorts are
495 		 * used as signed as in the case below where negative offsets
496 		 * are needed.  Since we now have a zero-extended number in a,
497 		 * b, and c, we must change it back to signed short, so that
498 		 * when it is added with and assigned to an int, the result
499 		 * ends up sign-extended and we get a proper negative offset,
500 		 * if there is one.
501 		 */
502 			jump_ofs = st->b;
503 			if (is_progs_v6) jump_ofs = (signed short)jump_ofs;
504 			st += jump_ofs - 1;	/* -1 to offset the st++ */
505 		}
506 		break;
507 
508 	case OP_IF:
509 		if (a->_int)
510 		{
511 			jump_ofs = st->b;
512 			if (is_progs_v6) jump_ofs = (signed short)jump_ofs;
513 			st += jump_ofs - 1;	/* -1 to offset the st++ */
514 		}
515 		break;
516 
517 	case OP_GOTO:
518 		jump_ofs = st->a;
519 		if (is_progs_v6) jump_ofs = (signed short)jump_ofs;
520 		st += jump_ofs - 1;	/* -1 to offset the st++ */
521 		break;
522 
523 	case OP_CALL8:
524 	case OP_CALL7:
525 	case OP_CALL6:
526 	case OP_CALL5:
527 	case OP_CALL4:
528 	case OP_CALL3:
529 	case OP_CALL2:	// Copy second arg to shared space
530 		vecptr = G_VECTOR(OFS_PARM1);
531 		VectorCopy(c->vector, vecptr);
532 	case OP_CALL1:	// Copy first arg to shared space
533 		vecptr = G_VECTOR(OFS_PARM0);
534 		VectorCopy(b->vector, vecptr);
535 	case OP_CALL0:
536 		pr_xfunction->profile += profile - startprofile;
537 		startprofile = profile;
538 		pr_xstatement = st - pr_statements;
539 		pr_argc = st->op - OP_CALL0;
540 		if (!a->function)
541 		{
542 			PR_RunError("NULL function");
543 		}
544 		newf = &pr_functions[a->function];
545 		if (newf->first_statement < 0)
546 		{ // Built-in function
547 			int i = -newf->first_statement;
548 			if (i >= pr_numbuiltins)
549 			{
550 				PR_RunError("Bad builtin call number %d", i);
551 			}
552 			pr_builtins[i]();
553 			break;
554 		}
555 		// Normal function
556 		st = &pr_statements[EnterFunction(newf)];
557 		break;
558 
559 	case OP_DONE:
560 	case OP_RETURN:
561 	  {
562 		float *retptr = &pr_globals[OFS_RETURN];
563 		float *valptr = &pr_globals[st->a];
564 		pr_xfunction->profile += profile - startprofile;
565 		startprofile = profile;
566 		pr_xstatement = st - pr_statements;
567 		*retptr++ = *valptr++;
568 		*retptr++ = *valptr++;
569 		*retptr   = *valptr;
570 		st = &pr_statements[LeaveFunction()];
571 		if (pr_depth == exitdepth)
572 		{ // Done
573 			return;
574 		}
575 	  }	break;
576 
577 	case OP_STATE:
578 		ed = PROG_TO_EDICT(*sv_globals.self);
579 /* Id 1.07 changes
580 #ifdef FPS_20
581 		ed->v.nextthink = *sv_globals.time + 0.05;
582 #else
583 		ed->v.nextthink = *sv_globals.time + 0.1;
584 #endif
585 */
586 		ed->v.nextthink = *sv_globals.time + HX_FRAME_TIME;
587 		ed->v.frame = a->_float;
588 		ed->v.think = b->function;
589 		break;
590 
591 	case OP_CSTATE:	// Cycle state
592 	  {	int startFrame, endFrame;
593 		ed = PROG_TO_EDICT(*sv_globals.self);
594 		ed->v.nextthink = *sv_globals.time + HX_FRAME_TIME;
595 		ed->v.think = pr_xfunction - pr_functions;
596 		*sv_globals.cycle_wrapped = false;
597 		startFrame = (int)a->_float;
598 		endFrame = (int)b->_float;
599 		if (startFrame <= endFrame)
600 		{ // Increment
601 			if (ed->v.frame < startFrame || ed->v.frame > endFrame)
602 			{
603 				ed->v.frame = startFrame;
604 			}
605 			else
606 			{
607 				ed->v.frame++;
608 				if (ed->v.frame > endFrame)
609 				{
610 					*sv_globals.cycle_wrapped = true;
611 					ed->v.frame = startFrame;
612 				}
613 			}
614 		}
615 		else
616 		{ // Decrement
617 			if (ed->v.frame > startFrame || ed->v.frame < endFrame)
618 			{
619 				ed->v.frame = startFrame;
620 			}
621 			else
622 			{
623 				ed->v.frame--;
624 				if (ed->v.frame < endFrame)
625 				{
626 					*sv_globals.cycle_wrapped = true;
627 					ed->v.frame = startFrame;
628 				}
629 			}
630 		}
631 	  }	break;
632 
633 	case OP_CWSTATE:	// Cycle weapon state
634 	  {	int startFrame, endFrame;
635 		ed = PROG_TO_EDICT(*sv_globals.self);
636 		ed->v.nextthink = *sv_globals.time + HX_FRAME_TIME;
637 		ed->v.think = pr_xfunction - pr_functions;
638 		*sv_globals.cycle_wrapped = false;
639 		startFrame = (int)a->_float;
640 		endFrame = (int)b->_float;
641 		if (startFrame <= endFrame)
642 		{ // Increment
643 			if (ed->v.weaponframe < startFrame
644 				|| ed->v.weaponframe > endFrame)
645 			{
646 				ed->v.weaponframe = startFrame;
647 			}
648 			else
649 			{
650 				ed->v.weaponframe++;
651 				if (ed->v.weaponframe > endFrame)
652 				{
653 					*sv_globals.cycle_wrapped = true;
654 					ed->v.weaponframe = startFrame;
655 				}
656 			}
657 		}
658 		else
659 		{ // Decrement
660 			if (ed->v.weaponframe > startFrame
661 				|| ed->v.weaponframe < endFrame)
662 			{
663 				ed->v.weaponframe = startFrame;
664 			}
665 			else
666 			{
667 				ed->v.weaponframe--;
668 				if (ed->v.weaponframe < endFrame)
669 				{
670 					*sv_globals.cycle_wrapped = true;
671 					ed->v.weaponframe = startFrame;
672 				}
673 			}
674 		}
675 	  }	break;
676 
677 	case OP_THINKTIME:
678 		ed = PROG_TO_EDICT(a->edict);
679 #ifdef PARANOID
680 		NUM_FOR_EDICT(ed);	// Make sure it's in range
681 #endif
682 		if (ed == (edict_t *)sv.edicts && sv.state == ss_active)
683 		{
684 			pr_xstatement = st - pr_statements;
685 			PR_RunError("assignment to world entity");
686 		}
687 		ed->v.nextthink = *sv_globals.time + b->_float;
688 		break;
689 
690 	case OP_BITSET:		// f (+) f
691 		b->_float = (int)b->_float | (int)a->_float;
692 		break;
693 	case OP_BITSETP:	// e.f (+) f
694 		ptr = (eval_t *)((byte *)sv.edicts + b->_int);
695 		ptr->_float = (int)ptr->_float | (int)a->_float;
696 		break;
697 	case OP_BITCLR:		// f (-) f
698 		b->_float = (int)b->_float & ~((int)a->_float);
699 		break;
700 	case OP_BITCLRP:	// e.f (-) f
701 		ptr = (eval_t *)((byte *)sv.edicts + b->_int);
702 		ptr->_float = (int)ptr->_float & ~((int)a->_float);
703 		break;
704 
705 	case OP_RAND0:
706 	  {	float val;
707 		val = rand() * (1.0 / RAND_MAX);
708 		G_FLOAT(OFS_RETURN) = val;
709 	  }	break;
710 	case OP_RAND1:
711 	  {	float val;
712 		val = rand() * (1.0 / RAND_MAX) * a->_float;
713 		G_FLOAT(OFS_RETURN) = val;
714 	  }	break;
715 	case OP_RAND2:
716 	  {	float val;
717 		if (a->_float < b->_float)
718 		{
719 			val = a->_float + (rand() * (1.0 / RAND_MAX) * (b->_float - a->_float));
720 		}
721 		else
722 		{
723 			val = b->_float + (rand() * (1.0 / RAND_MAX) * (a->_float - b->_float));
724 		}
725 		G_FLOAT(OFS_RETURN) = val;
726 	  }	break;
727 	case OP_RANDV0:
728 	  {	float val;
729 		float *retptr = &G_FLOAT(OFS_RETURN);
730 		val = rand() * (1.0 / RAND_MAX);
731 		*retptr++ = val;
732 		val = rand() * (1.0 / RAND_MAX);
733 		*retptr++ = val;
734 		val = rand() * (1.0 / RAND_MAX);
735 		*retptr   = val;
736 	  }	break;
737 	case OP_RANDV1:
738 	  {	float val;
739 		float *retptr = &G_FLOAT(OFS_RETURN);
740 		val = rand() * (1.0 / RAND_MAX) * a->vector[0];
741 		*retptr++ = val;
742 		val = rand() * (1.0 / RAND_MAX) * a->vector[1];
743 		*retptr++ = val;
744 		val = rand() * (1.0 / RAND_MAX) * a->vector[2];
745 		*retptr   = val;
746 	  }	break;
747 	case OP_RANDV2:
748 	  {	float val;
749 		int	i;
750 		float *retptr = &G_FLOAT(OFS_RETURN);
751 		for (i = 0; i < 3; i++)
752 		{
753 			if (a->vector[i] < b->vector[i])
754 			{
755 				val = a->vector[i] + (rand() * (1.0 / RAND_MAX) * (b->vector[i] - a->vector[i]));
756 			}
757 			else
758 			{
759 				val = b->vector[i] + (rand() * (1.0 / RAND_MAX) * (a->vector[i] - b->vector[i]));
760 			}
761 			*retptr++ = val;
762 		}
763 	  }	break;
764 	case OP_SWITCH_F:
765 		case_type = SWITCH_F;
766 		switch_float = a->_float;
767 		jump_ofs = st->b;
768 		if (is_progs_v6) jump_ofs = (signed short)jump_ofs;
769 		st += jump_ofs - 1;	/* -1 to offset the st++ */
770 		break;
771 	case OP_SWITCH_V:
772 	case OP_SWITCH_S:
773 	case OP_SWITCH_E:
774 	case OP_SWITCH_FNC:
775 		pr_xstatement = st - pr_statements;
776 		PR_RunError("%s not done yet!", pr_opnames[st->op]);
777 		break;
778 
779 	case OP_CASERANGE:
780 		if (case_type != SWITCH_F)
781 		{
782 			pr_xstatement = st - pr_statements;
783 			PR_RunError("caserange fucked!");
784 		}
785 		if ((switch_float >= a->_float) && (switch_float <= b->_float))
786 		{
787 			jump_ofs = st->c;
788 			if (is_progs_v6) jump_ofs = (signed short)jump_ofs;
789 			st += jump_ofs - 1;	/* -1 to offset the st++ */
790 		}
791 		break;
792 	case OP_CASE:
793 		switch (case_type)
794 		{
795 		case SWITCH_F:
796 			if (switch_float == a->_float)
797 			{
798 				jump_ofs = st->b;
799 				if (is_progs_v6) jump_ofs = (signed short)jump_ofs;
800 				st += jump_ofs - 1;	/* -1 to offset the st++ */
801 			}
802 			break;
803 		case SWITCH_V:
804 		case SWITCH_S:
805 		case SWITCH_E:
806 		case SWITCH_FNC:
807 			pr_xstatement = st - pr_statements;
808 			PR_RunError("OP_CASE for %s not done yet!",
809 					pr_opnames[case_type + OP_SWITCH_F - SWITCH_F]);
810 			break;
811 		default:
812 			pr_xstatement = st - pr_statements;
813 			PR_RunError("fucked case!");
814 		}
815 		break;
816 
817 	default:
818 		pr_xstatement = st - pr_statements;
819 		PR_RunError("Bad opcode %i", st->op);
820 	}
821     }	/* end of while(1) loop */
822 }
823 #undef OPA
824 #undef OPB
825 #undef OPC
826 
827 
828 //==========================================================================
829 //
830 // EnterFunction
831 //
832 //==========================================================================
833 
EnterFunction(dfunction_t * f)834 static int EnterFunction (dfunction_t *f)
835 {
836 	int	i, j, c, o;
837 
838 	pr_stack[pr_depth].s = pr_xstatement;
839 	pr_stack[pr_depth].f = pr_xfunction;
840 	pr_depth++;
841 	if (pr_depth >= MAX_STACK_DEPTH)
842 	{
843 		PR_RunError("stack overflow");
844 	}
845 
846 	// save off any locals that the new function steps on
847 	c = f->locals;
848 	if (localstack_used + c > LOCALSTACK_SIZE)
849 	{
850 		PR_RunError ("%s: locals stack overflow", __thisfunc__);
851 	}
852 
853 	for (i = 0; i < c ; i++)
854 	{
855 		localstack[localstack_used + i] = ((int *)pr_globals)[f->parm_start + i];
856 	}
857 	localstack_used += c;
858 
859 	// copy parameters
860 	o = f->parm_start;
861 	for (i = 0; i < f->numparms; i++)
862 	{
863 		for (j = 0; j < f->parm_size[i]; j++)
864 		{
865 			((int *)pr_globals)[o] = ((int *)pr_globals)[OFS_PARM0 + i*3 + j];
866 			o++;
867 		}
868 	}
869 
870 	pr_xfunction = f;
871 	return f->first_statement - 1;	// offset the s++
872 }
873 
874 
875 //==========================================================================
876 //
877 // LeaveFunction
878 //
879 //==========================================================================
880 
LeaveFunction(void)881 static int LeaveFunction (void)
882 {
883 	int	i, c;
884 
885 	if (pr_depth <= 0)
886 	{
887 		Host_Error("prog stack underflow");
888 	}
889 
890 	// Restore locals from the stack
891 	c = pr_xfunction->locals;
892 	localstack_used -= c;
893 	if (localstack_used < 0)
894 	{
895 		PR_RunError("%s: locals stack underflow", __thisfunc__);
896 	}
897 
898 	for (i = 0; i < c; i++)
899 	{
900 		((int *)pr_globals)[pr_xfunction->parm_start + i] = localstack[localstack_used + i];
901 	}
902 
903 	// up stack
904 	pr_depth--;
905 	pr_xfunction = pr_stack[pr_depth].f;
906 	return pr_stack[pr_depth].s;
907 }
908 
909 
910 //==========================================================================
911 //
912 // PR_RunError
913 //
914 //==========================================================================
915 
PR_RunError(const char * error,...)916 void PR_RunError (const char *error, ...)
917 {
918 	va_list	argptr;
919 	char	string[1024];
920 
921 	va_start (argptr, error);
922 	q_vsnprintf (string, sizeof(string), error, argptr);
923 	va_end (argptr);
924 
925 	PrintStatement(pr_statements + pr_xstatement);
926 	PrintCallHistory();
927 
928 	Con_Printf("%s\n", string);
929 
930 	pr_depth = 0;	// dump the stack so host_error can shutdown functions
931 
932 	Host_Error("Program error");
933 }
934 
935 
936 //==========================================================================
937 //
938 // PrintCallHistory
939 //
940 //==========================================================================
941 
PrintCallHistory(void)942 static void PrintCallHistory (void)
943 {
944 	int		i;
945 	dfunction_t	*f;
946 
947 	if (pr_depth == 0)
948 	{
949 		Con_Printf("<NO STACK>\n");
950 		return;
951 	}
952 
953 	pr_stack[pr_depth].f = pr_xfunction;
954 	for (i = pr_depth; i >= 0; i--)
955 	{
956 		f = pr_stack[i].f;
957 		if (!f)
958 		{
959 			Con_Printf("<NO FUNCTION>\n");
960 		}
961 		else
962 		{
963 			Con_Printf("%12s : %s\n", PR_GetString(f->s_file), PR_GetString(f->s_name));
964 		}
965 	}
966 }
967 
968 
969 //==========================================================================
970 //
971 // PrintStatement
972 //
973 //==========================================================================
974 
PrintStatement(dstatement_t * s)975 static void PrintStatement (dstatement_t *s)
976 {
977 	int	i;
978 
979 	if ((unsigned int)s->op < sizeof(pr_opnames)/sizeof(pr_opnames[0]))
980 	{
981 		Con_Printf("%s ", pr_opnames[s->op]);
982 		i = strlen(pr_opnames[s->op]);
983 		for ( ; i < 10; i++)
984 		{
985 			Con_Printf(" ");
986 		}
987 	}
988 
989 	if (s->op == OP_IF || s->op == OP_IFNOT)
990 	{
991 		Con_Printf("%sbranch %i", PR_GlobalString(s->a), s->b);
992 	}
993 	else if (s->op == OP_GOTO)
994 	{
995 		Con_Printf("branch %i", s->a);
996 	}
997 	else if ((unsigned int)(s->op-OP_STORE_F) < 6)
998 	{
999 		Con_Printf("%s", PR_GlobalString(s->a));
1000 		Con_Printf("%s", PR_GlobalStringNoContents(s->b));
1001 	}
1002 	else
1003 	{
1004 		if (s->a)
1005 		{
1006 			Con_Printf("%s", PR_GlobalString(s->a));
1007 		}
1008 		if (s->b)
1009 		{
1010 			Con_Printf("%s", PR_GlobalString(s->b));
1011 		}
1012 		if (s->c)
1013 		{
1014 			Con_Printf("%s", PR_GlobalStringNoContents(s->c));
1015 		}
1016 	}
1017 	Con_Printf("\n");
1018 }
1019 
1020 
1021 //==========================================================================
1022 //
1023 // PR_Profile_f
1024 //
1025 //==========================================================================
1026 
PR_Profile_f(void)1027 void PR_Profile_f (void)
1028 {
1029 	int		i, j;
1030 	int		pmax;
1031 	dfunction_t	*f, *bestFunc;
1032 	int		total;
1033 	int		funcCount;
1034 	qboolean	byHC;
1035 	const char	*saveName = NULL;
1036 	FILE	*saveFile = NULL;
1037 	int		currentFile;
1038 	int		bestFile;
1039 	int		tally;
1040 	const char	*s;
1041 
1042 	if (!sv.active)
1043 		return;
1044 
1045 	byHC = false;
1046 	funcCount = 10;
1047 	for (i = 1; i < Cmd_Argc(); i++)
1048 	{
1049 		s = Cmd_Argv(i);
1050 		if (*s == 'h' || *s == 'H')
1051 		{ // Sort by HC source file
1052 			byHC = true;
1053 		}
1054 		else if (*s == 's' || *s == 'S')
1055 		{ // Save to file
1056 			if (i + 1 < Cmd_Argc() && !q_isdigit(*Cmd_Argv(i + 1)))
1057 			{
1058 				i++;
1059 				saveName = FS_MakePath(FS_USERDIR, NULL, Cmd_Argv(i));
1060 			}
1061 			else
1062 			{
1063 				saveName = FS_MakePath(FS_USERDIR, NULL, "profile.txt");
1064 			}
1065 		}
1066 		else if (q_isdigit(*s))
1067 		{ // Specify function count
1068 			funcCount = atoi(Cmd_Argv(i));
1069 			if (funcCount < 1)
1070 			{
1071 				funcCount = 1;
1072 			}
1073 		}
1074 	}
1075 
1076 	total = 0;
1077 	for (i = 0; i < progs->numfunctions; i++)
1078 	{
1079 		total += pr_functions[i].profile;
1080 	}
1081 
1082 	if (saveName)
1083 	{ // Create the output file
1084 		saveFile = fopen(saveName, "w");
1085 		if (saveFile == NULL)
1086 			Con_Printf("Could not open %s\n", saveName);
1087 	}
1088 
1089 	if (byHC == false)
1090 	{
1091 		j = 0;
1092 		do
1093 		{
1094 			pmax = 0;
1095 			bestFunc = NULL;
1096 			for (i = 0; i < progs->numfunctions; i++)
1097 			{
1098 				f = &pr_functions[i];
1099 				if (f->profile > pmax)
1100 				{
1101 					pmax = f->profile;
1102 					bestFunc = f;
1103 				}
1104 			}
1105 			if (bestFunc)
1106 			{
1107 				if (j < funcCount)
1108 				{
1109 					if (saveFile)
1110 					{
1111 						fprintf(saveFile, "%05.2f %s\n",
1112 								((float)bestFunc->profile / (float)total) * 100.0,
1113 								PR_GetString(bestFunc->s_name));
1114 					}
1115 					else
1116 					{
1117 						Con_Printf("%05.2f %s\n",
1118 								((float)bestFunc->profile / (float)total) * 100.0,
1119 								PR_GetString(bestFunc->s_name));
1120 					}
1121 				}
1122 				j++;
1123 				bestFunc->profile = 0;
1124 			}
1125 		} while (bestFunc);
1126 
1127 		if (saveFile)
1128 		{
1129 			fclose(saveFile);
1130 		}
1131 		return;
1132 	}
1133 
1134 	currentFile = -1;
1135 	do
1136 	{
1137 		tally = 0;
1138 		bestFile = Q_MAXINT;
1139 		for (i = 0; i < progs->numfunctions; i++)
1140 		{
1141 			if (pr_functions[i].s_file > currentFile
1142 				&& pr_functions[i].s_file < bestFile)
1143 			{
1144 				bestFile = pr_functions[i].s_file;
1145 				tally = pr_functions[i].profile;
1146 				continue;
1147 			}
1148 			if (pr_functions[i].s_file == bestFile)
1149 			{
1150 				tally += pr_functions[i].profile;
1151 			}
1152 		}
1153 		currentFile = bestFile;
1154 		if (tally && currentFile != Q_MAXINT)
1155 		{
1156 			if (saveFile)
1157 			{
1158 				fprintf(saveFile, "\"%s\"\n", PR_GetString(currentFile));
1159 			}
1160 			else
1161 			{
1162 				Con_Printf("\"%s\"\n", PR_GetString(currentFile));
1163 			}
1164 
1165 			j = 0;
1166 			do
1167 			{
1168 				pmax = 0;
1169 				bestFunc = NULL;
1170 				for (i = 0; i < progs->numfunctions; i++)
1171 				{
1172 					f = &pr_functions[i];
1173 					if (f->s_file == currentFile && f->profile > pmax)
1174 					{
1175 						pmax = f->profile;
1176 						bestFunc = f;
1177 					}
1178 				}
1179 				if (bestFunc)
1180 				{
1181 					if (j < funcCount)
1182 					{
1183 						if (saveFile)
1184 						{
1185 							fprintf(saveFile, "   %05.2f %s\n",
1186 									((float)bestFunc->profile / (float)total) * 100.0,
1187 									PR_GetString(bestFunc->s_name));
1188 						}
1189 						else
1190 						{
1191 							Con_Printf("   %05.2f %s\n",
1192 									((float)bestFunc->profile / (float)total) * 100.0,
1193 									PR_GetString(bestFunc->s_name));
1194 						}
1195 					}
1196 					j++;
1197 					bestFunc->profile = 0;
1198 				}
1199 			} while (bestFunc);
1200 		}
1201 	} while (currentFile != Q_MAXINT);
1202 
1203 	if (saveFile)
1204 	{
1205 		fclose(saveFile);
1206 	}
1207 }
1208 
1209