Fix for the problem that SDL applications exited
[AROS-Contrib.git] / Games / Quake / pr_exec.c
blob4f2aa363e62850676a62c8eeeb2ddf1f903b8f17
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
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.
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.
13 See the GNU General Public License for more details.
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.
21 #include "quakedef.h"
28 typedef struct
30 int s;
31 dfunction_t *f;
32 } prstack_t;
34 #define MAX_STACK_DEPTH 32
35 prstack_t pr_stack[MAX_STACK_DEPTH];
36 int pr_depth;
38 #define LOCALSTACK_SIZE 2048
39 int localstack[LOCALSTACK_SIZE];
40 int localstack_used;
43 qboolean pr_trace;
44 dfunction_t *pr_xfunction;
45 int pr_xstatement;
48 int pr_argc;
50 char *pr_opnames[] =
52 "DONE",
54 "MUL_F",
55 "MUL_V",
56 "MUL_FV",
57 "MUL_VF",
59 "DIV",
61 "ADD_F",
62 "ADD_V",
64 "SUB_F",
65 "SUB_V",
67 "EQ_F",
68 "EQ_V",
69 "EQ_S",
70 "EQ_E",
71 "EQ_FNC",
73 "NE_F",
74 "NE_V",
75 "NE_S",
76 "NE_E",
77 "NE_FNC",
79 "LE",
80 "GE",
81 "LT",
82 "GT",
84 "INDIRECT",
85 "INDIRECT",
86 "INDIRECT",
87 "INDIRECT",
88 "INDIRECT",
89 "INDIRECT",
91 "ADDRESS",
93 "STORE_F",
94 "STORE_V",
95 "STORE_S",
96 "STORE_ENT",
97 "STORE_FLD",
98 "STORE_FNC",
100 "STOREP_F",
101 "STOREP_V",
102 "STOREP_S",
103 "STOREP_ENT",
104 "STOREP_FLD",
105 "STOREP_FNC",
107 "RETURN",
109 "NOT_F",
110 "NOT_V",
111 "NOT_S",
112 "NOT_ENT",
113 "NOT_FNC",
115 "IF",
116 "IFNOT",
118 "CALL0",
119 "CALL1",
120 "CALL2",
121 "CALL3",
122 "CALL4",
123 "CALL5",
124 "CALL6",
125 "CALL7",
126 "CALL8",
128 "STATE",
130 "GOTO",
132 "AND",
133 "OR",
135 "BITAND",
136 "BITOR"
139 char *PR_GlobalString (int ofs);
140 char *PR_GlobalStringNoContents (int ofs);
143 //=============================================================================
146 =================
147 PR_PrintStatement
148 =================
150 void PR_PrintStatement (dstatement_t *s)
152 int i;
154 if ( (unsigned)s->op < sizeof(pr_opnames)/sizeof(pr_opnames[0]))
156 Con_Printf ("%s ", pr_opnames[s->op]);
157 i = strlen(pr_opnames[s->op]);
158 for ( ; i<10 ; i++)
159 Con_Printf (" ");
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)
166 Con_Printf ("branch %i",s->a);
168 else if ( (unsigned)(s->op - OP_STORE_F) < 6)
170 Con_Printf ("%s",PR_GlobalString(s->a));
171 Con_Printf ("%s", PR_GlobalStringNoContents(s->b));
173 else
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));
182 Con_Printf ("\n");
186 ============
187 PR_StackTrace
188 ============
190 void PR_StackTrace (void)
192 dfunction_t *f;
193 int i;
195 if (pr_depth == 0)
197 Con_Printf ("<NO STACK>\n");
198 return;
201 pr_stack[pr_depth].f = pr_xfunction;
202 for (i=pr_depth ; i>=0 ; i--)
204 f = pr_stack[i].f;
206 if (!f)
208 Con_Printf ("<NO FUNCTION>\n");
210 else
211 Con_Printf ("%12s : %s\n", pr_strings + f->s_file, pr_strings + f->s_name);
217 ============
218 PR_Profile_f
220 ============
222 void PR_Profile_f (void)
224 dfunction_t *f, *best;
225 int max;
226 int num;
227 int i;
229 num = 0;
232 max = 0;
233 best = NULL;
234 for (i=0 ; i<progs->numfunctions ; i++)
236 f = &pr_functions[i];
237 if (f->profile > max)
239 max = f->profile;
240 best = f;
243 if (best)
245 if (num < 10)
246 Con_Printf ("%7i %s\n", best->profile, pr_strings+best->s_name);
247 num++;
248 best->profile = 0;
250 } while (best);
255 ============
256 PR_RunError
258 Aborts the currently executing function
259 ============
261 void PR_RunError (char *error, ...)
263 va_list argptr;
264 char string[1024];
266 va_start (argptr,error);
267 vsprintf (string,error,argptr);
268 va_end (argptr);
270 PR_PrintStatement (pr_statements + pr_xstatement);
271 PR_StackTrace ();
272 Con_Printf ("%s\n", string);
274 pr_depth = 0; // dump the stack so host_error can shutdown functions
276 Host_Error ("Program error");
280 ============================================================================
281 PR_ExecuteProgram
283 The interpretation main loop
284 ============================================================================
288 ====================
289 PR_EnterFunction
291 Returns the new program statement counter
292 ====================
294 int PR_EnterFunction (dfunction_t *f)
296 int i, j, c, o;
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");
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");
309 for (i=0 ; i < c ; i++)
310 localstack[localstack_used+i] = ((int *)pr_globals)[f->parm_start + i];
311 localstack_used += c;
313 // copy parameters
314 o = f->parm_start;
315 for (i=0 ; i<f->numparms ; i++)
317 for (j=0 ; j<f->parm_size[i] ; j++)
319 ((int *)pr_globals)[o] = ((int *)pr_globals)[OFS_PARM0+i*3+j];
320 o++;
324 pr_xfunction = f;
325 return f->first_statement - 1; // offset the s++
329 ====================
330 PR_LeaveFunction
331 ====================
333 int PR_LeaveFunction (void)
335 int i, c;
337 if (pr_depth <= 0)
338 Sys_Error ("prog stack underflow");
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");
346 for (i=0 ; i < c ; i++)
347 ((int *)pr_globals)[pr_xfunction->parm_start + i] = localstack[localstack_used+i];
349 // up stack
350 pr_depth--;
351 pr_xfunction = pr_stack[pr_depth].f;
352 return pr_stack[pr_depth].s;
357 ====================
358 PR_ExecuteProgram
359 ====================
361 void PR_ExecuteProgram (func_t fnum)
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;
373 if (!fnum || fnum >= progs->numfunctions)
375 if (pr_global_struct->self)
376 ED_Print (PROG_TO_EDICT(pr_global_struct->self));
377 Host_Error ("PR_ExecuteProgram: NULL function");
380 f = &pr_functions[fnum];
382 runaway = 100000;
383 pr_trace = false;
385 // make a stack frame
386 exitdepth = pr_depth;
388 s = PR_EnterFunction (f);
390 while (1)
392 s++; // next statement
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];
399 if (!--runaway)
400 PR_RunError ("runaway loop error");
402 pr_xfunction->profile++;
403 pr_xstatement = s;
405 if (pr_trace)
406 PR_PrintStatement (st);
408 switch (st->op)
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;
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;
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;
447 case OP_DIV_F:
448 c->_float = a->_float / b->_float;
449 break;
451 case OP_BITAND:
452 c->_float = (int)a->_float & (int)b->_float;
453 break;
455 case OP_BITOR:
456 c->_float = (int)a->_float | (int)b->_float;
457 break;
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;
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;
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;
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;
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;
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;
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 *)((int *)&ed->v + b->_int) - (byte *)sv.edicts;
569 break;
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 *)((int *)&ed->v + b->_int);
581 c->_int = a->_int;
582 break;
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 *)((int *)&ed->v + 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;
595 //==================
597 case OP_IFNOT:
598 if (!a->_int)
599 s += st->b - 1; // offset the s++
600 break;
602 case OP_IF:
603 if (a->_int)
604 s += st->b - 1; // offset the s++
605 break;
607 case OP_GOTO:
608 s += st->a - 1; // offset the s++
609 break;
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");
624 newf = &pr_functions[a->function];
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;
635 s = PR_EnterFunction (newf);
636 break;
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];
644 s = PR_LeaveFunction ();
645 if (pr_depth == exitdepth)
646 return; // all done
647 break;
649 case OP_STATE:
650 ed = PROG_TO_EDICT(pr_global_struct->self);
651 #ifdef FPS_20
652 ed->v.nextthink = pr_global_struct->time + 0.05;
653 #else
654 ed->v.nextthink = pr_global_struct->time + 0.1;
655 #endif
656 if (a->_float != ed->v.frame)
658 ed->v.frame = a->_float;
660 ed->v.think = b->function;
661 break;
663 default:
664 PR_RunError ("Bad opcode %i", st->op);