updated to version 1.50, build 75.
[divverent/darkplaces.git] / pr_exec.c
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 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((unsigned short) 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((unsigned short) s->a));
171                 Con_Printf ("%s", PR_GlobalStringNoContents((unsigned short) s->b));
172         }
173         else
174         {
175                 if (s->a)
176                         Con_Printf ("%s",PR_GlobalString((unsigned short) s->a));
177                 if (s->b)
178                         Con_Printf ("%s",PR_GlobalString((unsigned short) s->b));
179                 if (s->c)
180                         Con_Printf ("%s", PR_GlobalStringNoContents((unsigned short) 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 (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                 Host_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 // LordHavoc: optimized
362 #define OPA ((eval_t *)&pr_globals[(unsigned short) st->a])
363 #define OPB ((eval_t *)&pr_globals[(unsigned short) st->b])
364 #define OPC ((eval_t *)&pr_globals[(unsigned short) st->c])
365 extern cvar_t pr_boundscheck;
366 void PR_ExecuteProgram (func_t fnum)
367 {
368         dstatement_t    *st;
369         dfunction_t     *f, *newf;
370         edict_t *ed;
371         int             exitdepth;
372         eval_t  *ptr;
373         int             profile, startprofile;
374
375         if (!fnum || fnum >= progs->numfunctions)
376         {
377                 if (pr_global_struct->self)
378                         ED_Print (PROG_TO_EDICT(pr_global_struct->self));
379                 Host_Error ("PR_ExecuteProgram: NULL function");
380         }
381         
382         f = &pr_functions[fnum];
383
384         pr_trace = false;
385
386 // make a stack frame
387         exitdepth = pr_depth;
388
389         st = &pr_statements[PR_EnterFunction (f)];
390         startprofile = profile = 0;
391
392         if (pr_boundscheck.value)
393         {
394                 while (1)
395                 {
396                         st++;
397                         if (++profile > 1000000) // LordHavoc: increased runaway loop limit 10x
398                         {
399                                 pr_xstatement = st - pr_statements;
400                                 PR_RunError ("runaway loop error");
401                         }
402                         
403                         if (pr_trace)
404                                 PR_PrintStatement (st);
405
406                         switch (st->op)
407                         {
408                         case OP_ADD_F:
409                                 OPC->_float = OPA->_float + OPB->_float;
410                                 break;
411                         case OP_ADD_V:
412                                 OPC->vector[0] = OPA->vector[0] + OPB->vector[0];
413                                 OPC->vector[1] = OPA->vector[1] + OPB->vector[1];
414                                 OPC->vector[2] = OPA->vector[2] + OPB->vector[2];
415                                 break;
416                         case OP_SUB_F:
417                                 OPC->_float = OPA->_float - OPB->_float;
418                                 break;
419                         case OP_SUB_V:
420                                 OPC->vector[0] = OPA->vector[0] - OPB->vector[0];
421                                 OPC->vector[1] = OPA->vector[1] - OPB->vector[1];
422                                 OPC->vector[2] = OPA->vector[2] - OPB->vector[2];
423                                 break;
424                         case OP_MUL_F:
425                                 OPC->_float = OPA->_float * OPB->_float;
426                                 break;
427                         case OP_MUL_V:
428                                 OPC->_float = OPA->vector[0]*OPB->vector[0] + OPA->vector[1]*OPB->vector[1] + OPA->vector[2]*OPB->vector[2];
429                                 break;
430                         case OP_MUL_FV:
431                                 OPC->vector[0] = OPA->_float * OPB->vector[0];
432                                 OPC->vector[1] = OPA->_float * OPB->vector[1];
433                                 OPC->vector[2] = OPA->_float * OPB->vector[2];
434                                 break;
435                         case OP_MUL_VF:
436                                 OPC->vector[0] = OPB->_float * OPA->vector[0];
437                                 OPC->vector[1] = OPB->_float * OPA->vector[1];
438                                 OPC->vector[2] = OPB->_float * OPA->vector[2];
439                                 break;
440                         case OP_DIV_F:
441                                 OPC->_float = OPA->_float / OPB->_float;
442                                 break;
443                         case OP_BITAND:
444                                 OPC->_float = (int)OPA->_float & (int)OPB->_float;
445                                 break;
446                         case OP_BITOR:
447                                 OPC->_float = (int)OPA->_float | (int)OPB->_float;
448                                 break;
449                         case OP_GE:
450                                 OPC->_float = OPA->_float >= OPB->_float;
451                                 break;
452                         case OP_LE:
453                                 OPC->_float = OPA->_float <= OPB->_float;
454                                 break;
455                         case OP_GT:
456                                 OPC->_float = OPA->_float > OPB->_float;
457                                 break;
458                         case OP_LT:
459                                 OPC->_float = OPA->_float < OPB->_float;
460                                 break;
461                         case OP_AND:
462                                 OPC->_float = OPA->_float && OPB->_float;
463                                 break;
464                         case OP_OR:
465                                 OPC->_float = OPA->_float || OPB->_float;
466                                 break;
467                         case OP_NOT_F:
468                                 OPC->_float = !OPA->_float;
469                                 break;
470                         case OP_NOT_V:
471                                 OPC->_float = !OPA->vector[0] && !OPA->vector[1] && !OPA->vector[2];
472                                 break;
473                         case OP_NOT_S:
474                                 OPC->_float = !OPA->string || !pr_strings[OPA->string];
475                                 break;
476                         case OP_NOT_FNC:
477                                 OPC->_float = !OPA->function;
478                                 break;
479                         case OP_NOT_ENT:
480                                 OPC->_float = (PROG_TO_EDICT(OPA->edict) == sv.edicts);
481                                 break;
482                         case OP_EQ_F:
483                                 OPC->_float = OPA->_float == OPB->_float;
484                                 break;
485                         case OP_EQ_V:
486                                 OPC->_float = (OPA->vector[0] == OPB->vector[0]) && (OPA->vector[1] == OPB->vector[1]) && (OPA->vector[2] == OPB->vector[2]);
487                                 break;
488                         case OP_EQ_S:
489                                 OPC->_float = !strcmp(pr_strings+OPA->string,pr_strings+OPB->string);
490                                 break;
491                         case OP_EQ_E:
492                                 OPC->_float = OPA->_int == OPB->_int;
493                                 break;
494                         case OP_EQ_FNC:
495                                 OPC->_float = OPA->function == OPB->function;
496                                 break;
497                         case OP_NE_F:
498                                 OPC->_float = OPA->_float != OPB->_float;
499                                 break;
500                         case OP_NE_V:
501                                 OPC->_float = (OPA->vector[0] != OPB->vector[0]) || (OPA->vector[1] != OPB->vector[1]) || (OPA->vector[2] != OPB->vector[2]);
502                                 break;
503                         case OP_NE_S:
504                                 OPC->_float = strcmp(pr_strings+OPA->string,pr_strings+OPB->string);
505                                 break;
506                         case OP_NE_E:
507                                 OPC->_float = OPA->_int != OPB->_int;
508                                 break;
509                         case OP_NE_FNC:
510                                 OPC->_float = OPA->function != OPB->function;
511                                 break;
512
513                 //==================
514                         case OP_STORE_F:
515                         case OP_STORE_ENT:
516                         case OP_STORE_FLD:              // integers
517                         case OP_STORE_S:
518                         case OP_STORE_FNC:              // pointers
519                                 OPB->_int = OPA->_int;
520                                 break;
521                         case OP_STORE_V:
522                                 OPB->vector[0] = OPA->vector[0];
523                                 OPB->vector[1] = OPA->vector[1];
524                                 OPB->vector[2] = OPA->vector[2];
525                                 break;
526                                 
527                         case OP_STOREP_F:
528                         case OP_STOREP_ENT:
529                         case OP_STOREP_FLD:             // integers
530                         case OP_STOREP_S:
531                         case OP_STOREP_FNC:             // pointers
532                                 if (OPB->_int < 0 || OPB->_int + 4 > pr_edictareasize)
533                                 {
534                                         pr_xstatement = st - pr_statements;
535                                         PR_RunError("Progs attempted to write to an out of bounds edict\n");
536                                         return;
537                                 }
538                                 if (OPB->_int % pr_edict_size < ((byte *)&sv.edicts->v - (byte *)sv.edicts))
539                                 {
540                                         pr_xstatement = st - pr_statements;
541                                         PR_RunError("Progs attempted to write to an engine edict field\n");
542                                         return;
543                                 }
544                                 ptr = (eval_t *)((byte *)sv.edicts + OPB->_int);
545                                 ptr->_int = OPA->_int;
546                                 break;
547                         case OP_STOREP_V:
548                                 if (OPB->_int < 0 || OPB->_int + 12 > pr_edictareasize)
549                                 {
550                                         pr_xstatement = st - pr_statements;
551                                         PR_RunError("Progs attempted to write to an out of bounds edict\n");
552                                         return;
553                                 }
554                                 ptr = (eval_t *)((byte *)sv.edicts + OPB->_int);
555                                 ptr->vector[0] = OPA->vector[0];
556                                 ptr->vector[1] = OPA->vector[1];
557                                 ptr->vector[2] = OPA->vector[2];
558                                 break;
559                                 
560                         case OP_ADDRESS:
561                                 if (OPA->edict < 0 || OPA->edict >= pr_edictareasize)
562                                 {
563                                         pr_xstatement = st - pr_statements;
564                                         PR_RunError("Progs attempted to address an out of bounds edict\n");
565                                         return;
566                                 }
567                                 if (OPA->edict == 0 && sv.state == ss_active)
568                                 {
569                                         pr_xstatement = st - pr_statements;
570                                         PR_RunError ("assignment to world entity");
571                                         return;
572                                 }
573                                 if (OPB->_int < 0 || OPB->_int >= progs->entityfields)
574                                 {
575                                         pr_xstatement = st - pr_statements;
576                                         PR_RunError("Progs attempted to address an invalid field in an edict\n");
577                                         return;
578                                 }
579                                 ed = PROG_TO_EDICT(OPA->edict);
580                                 OPC->_int = (byte *)((int *)&ed->v + OPB->_int) - (byte *)sv.edicts;
581                                 break;
582                                 
583                         case OP_LOAD_F:
584                         case OP_LOAD_FLD:
585                         case OP_LOAD_ENT:
586                         case OP_LOAD_S:
587                         case OP_LOAD_FNC:
588                                 if (OPA->edict < 0 || OPA->edict >= pr_edictareasize)
589                                 {
590                                         pr_xstatement = st - pr_statements;
591                                         PR_RunError("Progs attempted to read an out of bounds edict number\n");
592                                         return;
593                                 }
594                                 if (OPB->_int < 0 || OPB->_int >= progs->entityfields)
595                                 {
596                                         pr_xstatement = st - pr_statements;
597                                         PR_RunError("Progs attempted to read an invalid field in an edict\n");
598                                         return;
599                                 }
600                                 ed = PROG_TO_EDICT(OPA->edict);
601                                 OPC->_int = ((eval_t *)((int *)&ed->v + OPB->_int))->_int;
602                                 break;
603
604                         case OP_LOAD_V:
605                                 if (OPA->edict < 0 || OPA->edict >= pr_edictareasize)
606                                 {
607                                         pr_xstatement = st - pr_statements;
608                                         PR_RunError("Progs attempted to read an out of bounds edict number\n");
609                                         return;
610                                 }
611                                 if (OPB->_int < 0 || OPB->_int + 2 >= progs->entityfields)
612                                 {
613                                         pr_xstatement = st - pr_statements;
614                                         PR_RunError("Progs attempted to read an invalid field in an edict\n");
615                                         return;
616                                 }
617                                 ed = PROG_TO_EDICT(OPA->edict);
618                                 OPC->vector[0] = ((eval_t *)((int *)&ed->v + OPB->_int))->vector[0];
619                                 OPC->vector[1] = ((eval_t *)((int *)&ed->v + OPB->_int))->vector[1];
620                                 OPC->vector[2] = ((eval_t *)((int *)&ed->v + OPB->_int))->vector[2];
621                                 break;
622                                 
623                 //==================
624
625                         case OP_IFNOT:
626                                 if (!OPA->_int)
627                                         st += st->b - 1;        // offset the s++
628                                 break;
629                                 
630                         case OP_IF:
631                                 if (OPA->_int)
632                                         st += st->b - 1;        // offset the s++
633                                 break;
634                                 
635                         case OP_GOTO:
636                                 st += st->a - 1;        // offset the s++
637                                 break;
638                                 
639                         case OP_CALL0:
640                         case OP_CALL1:
641                         case OP_CALL2:
642                         case OP_CALL3:
643                         case OP_CALL4:
644                         case OP_CALL5:
645                         case OP_CALL6:
646                         case OP_CALL7:
647                         case OP_CALL8:
648                                 pr_xfunction->profile += profile - startprofile;
649                                 startprofile = profile;
650                                 pr_xstatement = st - pr_statements;
651                                 pr_argc = st->op - OP_CALL0;
652                                 if (!OPA->function)
653                                         PR_RunError ("NULL function");
654
655                                 newf = &pr_functions[OPA->function];
656
657                                 if (newf->first_statement < 0)
658                                 {       // negative statements are built in functions
659                                         int i = -newf->first_statement;
660                                         if (i >= pr_numbuiltins)
661                                                 PR_RunError ("Bad builtin call number");
662                                         pr_builtins[i] ();
663                                         break;
664                                 }
665
666                                 st = &pr_statements[PR_EnterFunction (newf)];
667                                 break;
668
669                         case OP_DONE:
670                         case OP_RETURN:
671                                 pr_globals[OFS_RETURN] = pr_globals[(unsigned short) st->a];
672                                 pr_globals[OFS_RETURN+1] = pr_globals[(unsigned short) st->a+1];
673                                 pr_globals[OFS_RETURN+2] = pr_globals[(unsigned short) st->a+2];
674                         
675                                 st = &pr_statements[PR_LeaveFunction ()];
676                                 if (pr_depth == exitdepth)
677                                         return;         // all done
678                                 break;
679                                 
680                         case OP_STATE:
681                                 ed = PROG_TO_EDICT(pr_global_struct->self);
682                                 ed->v.nextthink = pr_global_struct->time + 0.1;
683                                 ed->v.frame = OPA->_float;
684                                 ed->v.think = OPB->function;
685                                 break;
686                                 
687                         default:
688                                 pr_xstatement = st - pr_statements;
689                                 PR_RunError ("Bad opcode %i", st->op);
690                         }
691                 }
692         }
693         else
694         {
695                 while (1)
696                 {
697                         st++;
698                         if (++profile > 1000000) // LordHavoc: increased runaway loop limit 10x
699                         {
700                                 pr_xstatement = st - pr_statements;
701                                 PR_RunError ("runaway loop error");
702                         }
703                         
704                         if (pr_trace)
705                                 PR_PrintStatement (st);
706
707                         switch (st->op)
708                         {
709                         case OP_ADD_F:
710                                 OPC->_float = OPA->_float + OPB->_float;
711                                 break;
712                         case OP_ADD_V:
713                                 OPC->vector[0] = OPA->vector[0] + OPB->vector[0];
714                                 OPC->vector[1] = OPA->vector[1] + OPB->vector[1];
715                                 OPC->vector[2] = OPA->vector[2] + OPB->vector[2];
716                                 break;
717                         case OP_SUB_F:
718                                 OPC->_float = OPA->_float - OPB->_float;
719                                 break;
720                         case OP_SUB_V:
721                                 OPC->vector[0] = OPA->vector[0] - OPB->vector[0];
722                                 OPC->vector[1] = OPA->vector[1] - OPB->vector[1];
723                                 OPC->vector[2] = OPA->vector[2] - OPB->vector[2];
724                                 break;
725                         case OP_MUL_F:
726                                 OPC->_float = OPA->_float * OPB->_float;
727                                 break;
728                         case OP_MUL_V:
729                                 OPC->_float = OPA->vector[0]*OPB->vector[0] + OPA->vector[1]*OPB->vector[1] + OPA->vector[2]*OPB->vector[2];
730                                 break;
731                         case OP_MUL_FV:
732                                 OPC->vector[0] = OPA->_float * OPB->vector[0];
733                                 OPC->vector[1] = OPA->_float * OPB->vector[1];
734                                 OPC->vector[2] = OPA->_float * OPB->vector[2];
735                                 break;
736                         case OP_MUL_VF:
737                                 OPC->vector[0] = OPB->_float * OPA->vector[0];
738                                 OPC->vector[1] = OPB->_float * OPA->vector[1];
739                                 OPC->vector[2] = OPB->_float * OPA->vector[2];
740                                 break;
741                         case OP_DIV_F:
742                                 OPC->_float = OPA->_float / OPB->_float;
743                                 break;
744                         case OP_BITAND:
745                                 OPC->_float = (int)OPA->_float & (int)OPB->_float;
746                                 break;
747                         case OP_BITOR:
748                                 OPC->_float = (int)OPA->_float | (int)OPB->_float;
749                                 break;
750                         case OP_GE:
751                                 OPC->_float = OPA->_float >= OPB->_float;
752                                 break;
753                         case OP_LE:
754                                 OPC->_float = OPA->_float <= OPB->_float;
755                                 break;
756                         case OP_GT:
757                                 OPC->_float = OPA->_float > OPB->_float;
758                                 break;
759                         case OP_LT:
760                                 OPC->_float = OPA->_float < OPB->_float;
761                                 break;
762                         case OP_AND:
763                                 OPC->_float = OPA->_float && OPB->_float;
764                                 break;
765                         case OP_OR:
766                                 OPC->_float = OPA->_float || OPB->_float;
767                                 break;
768                         case OP_NOT_F:
769                                 OPC->_float = !OPA->_float;
770                                 break;
771                         case OP_NOT_V:
772                                 OPC->_float = !OPA->vector[0] && !OPA->vector[1] && !OPA->vector[2];
773                                 break;
774                         case OP_NOT_S:
775                                 OPC->_float = !OPA->string || !pr_strings[OPA->string];
776                                 break;
777                         case OP_NOT_FNC:
778                                 OPC->_float = !OPA->function;
779                                 break;
780                         case OP_NOT_ENT:
781                                 OPC->_float = (PROG_TO_EDICT(OPA->edict) == sv.edicts);
782                                 break;
783                         case OP_EQ_F:
784                                 OPC->_float = OPA->_float == OPB->_float;
785                                 break;
786                         case OP_EQ_V:
787                                 OPC->_float = (OPA->vector[0] == OPB->vector[0]) && (OPA->vector[1] == OPB->vector[1]) && (OPA->vector[2] == OPB->vector[2]);
788                                 break;
789                         case OP_EQ_S:
790                                 OPC->_float = !strcmp(pr_strings+OPA->string,pr_strings+OPB->string);
791                                 break;
792                         case OP_EQ_E:
793                                 OPC->_float = OPA->_int == OPB->_int;
794                                 break;
795                         case OP_EQ_FNC:
796                                 OPC->_float = OPA->function == OPB->function;
797                                 break;
798                         case OP_NE_F:
799                                 OPC->_float = OPA->_float != OPB->_float;
800                                 break;
801                         case OP_NE_V:
802                                 OPC->_float = (OPA->vector[0] != OPB->vector[0]) || (OPA->vector[1] != OPB->vector[1]) || (OPA->vector[2] != OPB->vector[2]);
803                                 break;
804                         case OP_NE_S:
805                                 OPC->_float = strcmp(pr_strings+OPA->string,pr_strings+OPB->string);
806                                 break;
807                         case OP_NE_E:
808                                 OPC->_float = OPA->_int != OPB->_int;
809                                 break;
810                         case OP_NE_FNC:
811                                 OPC->_float = OPA->function != OPB->function;
812                                 break;
813
814                 //==================
815                         case OP_STORE_F:
816                         case OP_STORE_ENT:
817                         case OP_STORE_FLD:              // integers
818                         case OP_STORE_S:
819                         case OP_STORE_FNC:              // pointers
820                                 OPB->_int = OPA->_int;
821                                 break;
822                         case OP_STORE_V:
823                                 OPB->vector[0] = OPA->vector[0];
824                                 OPB->vector[1] = OPA->vector[1];
825                                 OPB->vector[2] = OPA->vector[2];
826                                 break;
827                                 
828                         case OP_STOREP_F:
829                         case OP_STOREP_ENT:
830                         case OP_STOREP_FLD:             // integers
831                         case OP_STOREP_S:
832                         case OP_STOREP_FNC:             // pointers
833                                 if (OPB->_int < 0 || OPB->_int + 4 > pr_edictareasize)
834                                 {
835                                         pr_xstatement = st - pr_statements;
836                                         PR_RunError("Progs attempted to write to an out of bounds edict\n");
837                                         return;
838                                 }
839                                 if (OPB->_int % pr_edict_size < ((byte *)&sv.edicts->v - (byte *)sv.edicts))
840                                 {
841                                         pr_xstatement = st - pr_statements;
842                                         PR_RunError("Progs attempted to write to an engine edict field\n");
843                                         return;
844                                 }
845                                 ptr = (eval_t *)((byte *)sv.edicts + OPB->_int);
846                                 ptr->_int = OPA->_int;
847                                 break;
848                         case OP_STOREP_V:
849                                 if (OPB->_int < 0 || OPB->_int + 12 > pr_edictareasize)
850                                 {
851                                         pr_xstatement = st - pr_statements;
852                                         PR_RunError("Progs attempted to write to an out of bounds edict\n");
853                                         return;
854                                 }
855                                 ptr = (eval_t *)((byte *)sv.edicts + OPB->_int);
856                                 ptr->vector[0] = OPA->vector[0];
857                                 ptr->vector[1] = OPA->vector[1];
858                                 ptr->vector[2] = OPA->vector[2];
859                                 break;
860                                 
861                         case OP_ADDRESS:
862                                 if (OPA->edict < 0 || OPA->edict >= pr_edictareasize)
863                                 {
864                                         pr_xstatement = st - pr_statements;
865                                         PR_RunError("Progs attempted to address an out of bounds edict\n");
866                                         return;
867                                 }
868                                 if (OPA->edict == 0 && sv.state == ss_active)
869                                 {
870                                         pr_xstatement = st - pr_statements;
871                                         PR_RunError ("assignment to world entity");
872                                         return;
873                                 }
874                                 if (OPB->_int < 0 || OPB->_int >= progs->entityfields)
875                                 {
876                                         pr_xstatement = st - pr_statements;
877                                         PR_RunError("Progs attempted to address an invalid field in an edict\n");
878                                         return;
879                                 }
880                                 ed = PROG_TO_EDICT(OPA->edict);
881                                 OPC->_int = (byte *)((int *)&ed->v + OPB->_int) - (byte *)sv.edicts;
882                                 break;
883                                 
884                         case OP_LOAD_F:
885                         case OP_LOAD_FLD:
886                         case OP_LOAD_ENT:
887                         case OP_LOAD_S:
888                         case OP_LOAD_FNC:
889                                 if (OPA->edict < 0 || OPA->edict >= pr_edictareasize)
890                                 {
891                                         pr_xstatement = st - pr_statements;
892                                         PR_RunError("Progs attempted to read an out of bounds edict number\n");
893                                         return;
894                                 }
895                                 if (OPB->_int < 0 || OPB->_int >= progs->entityfields)
896                                 {
897                                         pr_xstatement = st - pr_statements;
898                                         PR_RunError("Progs attempted to read an invalid field in an edict\n");
899                                         return;
900                                 }
901                                 ed = PROG_TO_EDICT(OPA->edict);
902                                 OPC->_int = ((eval_t *)((int *)&ed->v + OPB->_int))->_int;
903                                 break;
904
905                         case OP_LOAD_V:
906                                 if (OPA->edict < 0 || OPA->edict >= pr_edictareasize)
907                                 {
908                                         pr_xstatement = st - pr_statements;
909                                         PR_RunError("Progs attempted to read an out of bounds edict number\n");
910                                         return;
911                                 }
912                                 if (OPB->_int < 0 || OPB->_int + 2 >= progs->entityfields)
913                                 {
914                                         pr_xstatement = st - pr_statements;
915                                         PR_RunError("Progs attempted to read an invalid field in an edict\n");
916                                         return;
917                                 }
918                                 ed = PROG_TO_EDICT(OPA->edict);
919                                 OPC->vector[0] = ((eval_t *)((int *)&ed->v + OPB->_int))->vector[0];
920                                 OPC->vector[1] = ((eval_t *)((int *)&ed->v + OPB->_int))->vector[1];
921                                 OPC->vector[2] = ((eval_t *)((int *)&ed->v + OPB->_int))->vector[2];
922                                 break;
923                                 
924                 //==================
925
926                         case OP_IFNOT:
927                                 if (!OPA->_int)
928                                         st += st->b - 1;        // offset the s++
929                                 break;
930                                 
931                         case OP_IF:
932                                 if (OPA->_int)
933                                         st += st->b - 1;        // offset the s++
934                                 break;
935                                 
936                         case OP_GOTO:
937                                 st += st->a - 1;        // offset the s++
938                                 break;
939                                 
940                         case OP_CALL0:
941                         case OP_CALL1:
942                         case OP_CALL2:
943                         case OP_CALL3:
944                         case OP_CALL4:
945                         case OP_CALL5:
946                         case OP_CALL6:
947                         case OP_CALL7:
948                         case OP_CALL8:
949                                 pr_xfunction->profile += profile - startprofile;
950                                 startprofile = profile;
951                                 pr_xstatement = st - pr_statements;
952                                 pr_argc = st->op - OP_CALL0;
953                                 if (!OPA->function)
954                                         PR_RunError ("NULL function");
955
956                                 newf = &pr_functions[OPA->function];
957
958                                 if (newf->first_statement < 0)
959                                 {       // negative statements are built in functions
960                                         int i = -newf->first_statement;
961                                         if (i >= pr_numbuiltins)
962                                                 PR_RunError ("Bad builtin call number");
963                                         pr_builtins[i] ();
964                                         break;
965                                 }
966
967                                 st = &pr_statements[PR_EnterFunction (newf)];
968                                 break;
969
970                         case OP_DONE:
971                         case OP_RETURN:
972                                 pr_globals[OFS_RETURN] = pr_globals[(unsigned short) st->a];
973                                 pr_globals[OFS_RETURN+1] = pr_globals[(unsigned short) st->a+1];
974                                 pr_globals[OFS_RETURN+2] = pr_globals[(unsigned short) st->a+2];
975                         
976                                 st = &pr_statements[PR_LeaveFunction ()];
977                                 if (pr_depth == exitdepth)
978                                         return;         // all done
979                                 break;
980                                 
981                         case OP_STATE:
982                                 ed = PROG_TO_EDICT(pr_global_struct->self);
983                                 ed->v.nextthink = pr_global_struct->time + 0.1;
984                                 ed->v.frame = OPA->_float;
985                                 ed->v.think = OPB->function;
986                                 break;
987                                 
988                 //==================
989
990 // LordHavoc: to be enabled when Progs version 7 (or whatever it will be numbered) is finalized
991 /*
992                         case OP_ADD_I:
993                                 OPC->_int = OPA->_int + OPB->_int;
994                                 break;
995                         case OP_ADD_IF:
996                                 OPC->_int = OPA->_int + (int) OPB->_float;
997                                 break;
998                         case OP_ADD_FI:
999                                 OPC->_float = OPA->_float + (float) OPB->_int;
1000                                 break;
1001                         case OP_SUB_I:
1002                                 OPC->_int = OPA->_int - OPB->_int;
1003                                 break;
1004                         case OP_SUB_IF:
1005                                 OPC->_int = OPA->_int - (int) OPB->_float;
1006                                 break;
1007                         case OP_SUB_FI:
1008                                 OPC->_float = OPA->_float - (float) OPB->_int;
1009                                 break;
1010                         case OP_MUL_I:
1011                                 OPC->_int = OPA->_int * OPB->_int;
1012                                 break;
1013                         case OP_MUL_IF:
1014                                 OPC->_int = OPA->_int * (int) OPB->_float;
1015                                 break;
1016                         case OP_MUL_FI:
1017                                 OPC->_float = OPA->_float * (float) OPB->_int;
1018                                 break;
1019                         case OP_MUL_VI:
1020                                 OPC->vector[0] = (float) OPB->_int * OPA->vector[0];
1021                                 OPC->vector[1] = (float) OPB->_int * OPA->vector[1];
1022                                 OPC->vector[2] = (float) OPB->_int * OPA->vector[2];
1023                                 break;
1024                         case OP_DIV_VF:
1025                                 {
1026                                         float temp = 1.0f / OPB->_float;
1027                                         OPC->vector[0] = temp * OPA->vector[0];
1028                                         OPC->vector[1] = temp * OPA->vector[1];
1029                                         OPC->vector[2] = temp * OPA->vector[2];
1030                                 }
1031                                 break;
1032                         case OP_DIV_I:
1033                                 OPC->_int = OPA->_int / OPB->_int;
1034                                 break;
1035                         case OP_DIV_IF:
1036                                 OPC->_int = OPA->_int / (int) OPB->_float;
1037                                 break;
1038                         case OP_DIV_FI:
1039                                 OPC->_float = OPA->_float / (float) OPB->_int;
1040                                 break;
1041                         case OP_CONV_IF:
1042                                 OPC->_float = OPA->_int;
1043                                 break;
1044                         case OP_CONV_FI:
1045                                 OPC->_int = OPA->_float;
1046                                 break;
1047                         case OP_BITAND_I:
1048                                 OPC->_int = OPA->_int & OPB->_int;
1049                                 break;
1050                         case OP_BITOR_I:
1051                                 OPC->_int = OPA->_int | OPB->_int;
1052                                 break;
1053                         case OP_BITAND_IF:
1054                                 OPC->_int = OPA->_int & (int)OPB->_float;
1055                                 break;
1056                         case OP_BITOR_IF:
1057                                 OPC->_int = OPA->_int | (int)OPB->_float;
1058                                 break;
1059                         case OP_BITAND_FI:
1060                                 OPC->_float = (int)OPA->_float & OPB->_int;
1061                                 break;
1062                         case OP_BITOR_FI:
1063                                 OPC->_float = (int)OPA->_float | OPB->_int;
1064                                 break;
1065                         case OP_GE_I:
1066                                 OPC->_float = OPA->_int >= OPB->_int;
1067                                 break;
1068                         case OP_LE_I:
1069                                 OPC->_float = OPA->_int <= OPB->_int;
1070                                 break;
1071                         case OP_GT_I:
1072                                 OPC->_float = OPA->_int > OPB->_int;
1073                                 break;
1074                         case OP_LT_I:
1075                                 OPC->_float = OPA->_int < OPB->_int;
1076                                 break;
1077                         case OP_AND_I:
1078                                 OPC->_float = OPA->_int && OPB->_int;
1079                                 break;
1080                         case OP_OR_I:
1081                                 OPC->_float = OPA->_int || OPB->_int;
1082                                 break;
1083                         case OP_GE_IF:
1084                                 OPC->_float = (float)OPA->_int >= OPB->_float;
1085                                 break;
1086                         case OP_LE_IF:
1087                                 OPC->_float = (float)OPA->_int <= OPB->_float;
1088                                 break;
1089                         case OP_GT_IF:
1090                                 OPC->_float = (float)OPA->_int > OPB->_float;
1091                                 break;
1092                         case OP_LT_IF:
1093                                 OPC->_float = (float)OPA->_int < OPB->_float;
1094                                 break;
1095                         case OP_AND_IF:
1096                                 OPC->_float = (float)OPA->_int && OPB->_float;
1097                                 break;
1098                         case OP_OR_IF:
1099                                 OPC->_float = (float)OPA->_int || OPB->_float;
1100                                 break;
1101                         case OP_GE_FI:
1102                                 OPC->_float = OPA->_float >= (float)OPB->_int;
1103                                 break;
1104                         case OP_LE_FI:
1105                                 OPC->_float = OPA->_float <= (float)OPB->_int;
1106                                 break;
1107                         case OP_GT_FI:
1108                                 OPC->_float = OPA->_float > (float)OPB->_int;
1109                                 break;
1110                         case OP_LT_FI:
1111                                 OPC->_float = OPA->_float < (float)OPB->_int;
1112                                 break;
1113                         case OP_AND_FI:
1114                                 OPC->_float = OPA->_float && (float)OPB->_int;
1115                                 break;
1116                         case OP_OR_FI:
1117                                 OPC->_float = OPA->_float || (float)OPB->_int;
1118                                 break;
1119                         case OP_NOT_I:
1120                                 OPC->_float = !OPA->_int;
1121                                 break;
1122                         case OP_EQ_I:
1123                                 OPC->_float = OPA->_int == OPB->_int;
1124                                 break;
1125                         case OP_EQ_IF:
1126                                 OPC->_float = (float)OPA->_int == OPB->_float;
1127                                 break;
1128                         case OP_EQ_FI:
1129                                 OPC->_float = OPA->_float == (float)OPB->_int;
1130                                 break;
1131                         case OP_NE_I:
1132                                 OPC->_float = OPA->_int != OPB->_int;
1133                                 break;
1134                         case OP_NE_IF:
1135                                 OPC->_float = (float)OPA->_int != OPB->_float;
1136                                 break;
1137                         case OP_NE_FI:
1138                                 OPC->_float = OPA->_float != (float)OPB->_int;
1139                                 break;
1140                         case OP_STORE_I:
1141                                 OPB->_int = OPA->_int;
1142                                 break;
1143                         case OP_STOREP_I:
1144                                 if (OPB->_int < 0 || OPB->_int + 4 > pr_edictareasize)
1145                                 {
1146                                         pr_xstatement = st - pr_statements;
1147                                         PR_RunError("Progs attempted to write to an out of bounds edict\n");
1148                                         return;
1149                                 }
1150                                 if (OPB->_int % pr_edict_size < ((byte *)&sv.edicts->v - (byte *)sv.edicts))
1151                                 {
1152                                         pr_xstatement = st - pr_statements;
1153                                         PR_RunError("Progs attempted to write to an engine edict field\n");
1154                                         return;
1155                                 }
1156                                 ptr = (eval_t *)((byte *)sv.edicts + OPB->_int);
1157                                 ptr->_int = OPA->_int;
1158                                 break;
1159                         case OP_LOAD_I:
1160                                 if (OPA->edict < 0 || OPA->edict >= pr_edictareasize)
1161                                 {
1162                                         pr_xstatement = st - pr_statements;
1163                                         PR_RunError("Progs attempted to read an out of bounds edict number\n");
1164                                         return;
1165                                 }
1166                                 if (OPB->_int < 0 || OPB->_int >= progs->entityfields)
1167                                 {
1168                                         pr_xstatement = st - pr_statements;
1169                                         PR_RunError("Progs attempted to read an invalid field in an edict\n");
1170                                         return;
1171                                 }
1172                                 ed = PROG_TO_EDICT(OPA->edict);
1173                                 OPC->_int = ((eval_t *)((int *)&ed->v + OPB->_int))->_int;
1174                                 break;
1175
1176                         case OP_GSTOREP_I:
1177                         case OP_GSTOREP_F:
1178                         case OP_GSTOREP_ENT:
1179                         case OP_GSTOREP_FLD:            // integers
1180                         case OP_GSTOREP_S:
1181                         case OP_GSTOREP_FNC:            // pointers
1182                                 if (OPB->_int < 0 || OPB->_int >= pr_globaldefs)
1183                                 {
1184                                         pr_xstatement = st - pr_statements;
1185                                         PR_RunError("Progs attempted to write to an invalid indexed global\n");
1186                                         return;
1187                                 }
1188                                 pr_globals[OPB->_int] = OPA->_float;
1189                                 break;
1190                         case OP_GSTOREP_V:
1191                                 if (OPB->_int < 0 || OPB->_int + 2 >= pr_globaldefs)
1192                                 {
1193                                         pr_xstatement = st - pr_statements;
1194                                         PR_RunError("Progs attempted to write to an invalid indexed global\n");
1195                                         return;
1196                                 }
1197                                 pr_globals[OPB->_int  ] = OPA->vector[0];
1198                                 pr_globals[OPB->_int+1] = OPA->vector[1];
1199                                 pr_globals[OPB->_int+2] = OPA->vector[2];
1200                                 break;
1201                                 
1202                         case OP_GADDRESS:
1203                                 i = OPA->_int + (int) OPB->_float;
1204                                 if (i < 0 || i >= pr_globaldefs)
1205                                 {
1206                                         pr_xstatement = st - pr_statements;
1207                                         PR_RunError("Progs attempted to address an out of bounds global\n");
1208                                         return;
1209                                 }
1210                                 OPC->_float = pr_globals[i];
1211                                 break;
1212                                 
1213                         case OP_GLOAD_I:
1214                         case OP_GLOAD_F:
1215                         case OP_GLOAD_FLD:
1216                         case OP_GLOAD_ENT:
1217                         case OP_GLOAD_S:
1218                         case OP_GLOAD_FNC:
1219                                 if (OPA->_int < 0 || OPA->_int >= pr_globaldefs)
1220                                 {
1221                                         pr_xstatement = st - pr_statements;
1222                                         PR_RunError("Progs attempted to read an invalid indexed global\n");
1223                                         return;
1224                                 }
1225                                 OPC->_float = pr_globals[OPA->_int];
1226                                 break;
1227
1228                         case OP_GLOAD_V:
1229                                 if (OPA->_int < 0 || OPA->_int + 2 >= pr_globaldefs)
1230                                 {
1231                                         pr_xstatement = st - pr_statements;
1232                                         PR_RunError("Progs attempted to read an invalid indexed global\n");
1233                                         return;
1234                                 }
1235                                 OPC->vector[0] = pr_globals[OPA->_int  ];
1236                                 OPC->vector[1] = pr_globals[OPA->_int+1];
1237                                 OPC->vector[2] = pr_globals[OPA->_int+2];
1238                                 break;
1239
1240                         case OP_BOUNDCHECK:
1241                                 if (OPA->_int < 0 || OPA->_int >= st->b)
1242                                 {
1243                                         pr_xstatement = st - pr_statements;
1244                                         PR_RunError("Progs boundcheck failed at line number %d, value is < 0 or >= %d\n", st->b, st->c);
1245                                         return;
1246                                 }
1247                                 break;
1248
1249 */
1250                 //==================
1251
1252                         default:
1253                                 pr_xstatement = st - pr_statements;
1254                                 PR_RunError ("Bad opcode %i", st->op);
1255                         }
1256                 }
1257         }
1258 }