summaryrefslogtreecommitdiff
path: root/apps/plugins/sdl/progs/quake/pr_exec.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/sdl/progs/quake/pr_exec.c')
-rw-r--r--apps/plugins/sdl/progs/quake/pr_exec.c668
1 files changed, 668 insertions, 0 deletions
diff --git a/apps/plugins/sdl/progs/quake/pr_exec.c b/apps/plugins/sdl/progs/quake/pr_exec.c
new file mode 100644
index 0000000000..4f2aa363e6
--- /dev/null
+++ b/apps/plugins/sdl/progs/quake/pr_exec.c
@@ -0,0 +1,668 @@
1/*
2Copyright (C) 1996-1997 Id Software, Inc.
3
4This program is free software; you can redistribute it and/or
5modify it under the terms of the GNU General Public License
6as published by the Free Software Foundation; either version 2
7of the License, or (at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13See the GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19*/
20
21#include "quakedef.h"
22
23
24/*
25
26*/
27
28typedef struct
29{
30 int s;
31 dfunction_t *f;
32} prstack_t;
33
34#define MAX_STACK_DEPTH 32
35prstack_t pr_stack[MAX_STACK_DEPTH];
36int pr_depth;
37
38#define LOCALSTACK_SIZE 2048
39int localstack[LOCALSTACK_SIZE];
40int localstack_used;
41
42
43qboolean pr_trace;
44dfunction_t *pr_xfunction;
45int pr_xstatement;
46
47
48int pr_argc;
49
50char *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
139char *PR_GlobalString (int ofs);
140char *PR_GlobalStringNoContents (int ofs);
141
142
143//=============================================================================
144
145/*
146=================
147PR_PrintStatement
148=================
149*/
150void 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============
187PR_StackTrace
188============
189*/
190void 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============
218PR_Profile_f
219
220============
221*/
222void 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============
256PR_RunError
257
258Aborts the currently executing function
259============
260*/
261void PR_RunError (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============================================================================
281PR_ExecuteProgram
282
283The interpretation main loop
284============================================================================
285*/
286
287/*
288====================
289PR_EnterFunction
290
291Returns the new program statement counter
292====================
293*/
294int 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====================
330PR_LeaveFunction
331====================
332*/
333int 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====================
358PR_ExecuteProgram
359====================
360*/
361void 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
390while (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 *)((int *)&ed->v + 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 *)((int *)&ed->v + 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 *)((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;
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->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)
657 {
658 ed->v.frame = a->_float;
659 }
660 ed->v.think = b->function;
661 break;
662
663 default:
664 PR_RunError ("Bad opcode %i", st->op);
665 }
666}
667
668}