Linux GLX, a lot of code shrinkage/cleanup, assembly support.
[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 /*
362 void PR_ExecuteProgram (func_t fnum)
363 {
364         eval_t  *a, *b, *c;
365         int                     s;
366         dstatement_t    *st;
367         dfunction_t     *f, *newf;
368         int             runaway;
369         int             i;
370         edict_t *ed;
371         int             exitdepth;
372         eval_t  *ptr;
373
374         if (!fnum || fnum >= progs->numfunctions)
375         {
376                 if (pr_global_struct->self)
377                         ED_Print (PROG_TO_EDICT(pr_global_struct->self));
378                 Host_Error ("PR_ExecuteProgram: NULL function");
379         }
380         
381         f = &pr_functions[fnum];
382
383         runaway = 100000;
384         pr_trace = false;
385
386 // make a stack frame
387         exitdepth = pr_depth;
388
389         s = PR_EnterFunction (f);
390         
391 while (1)
392 {
393         s++;    // next statement
394
395         st = &pr_statements[s];
396         // LordHavoc: fix for 32768 QC def limit (just added unsigned short typecast)
397         a = (eval_t *)&pr_globals[(unsigned short) st->a];
398         b = (eval_t *)&pr_globals[(unsigned short) st->b];
399         c = (eval_t *)&pr_globals[(unsigned short) st->c];
400         
401         if (!--runaway)
402                 PR_RunError ("runaway loop error");
403                 
404         pr_xfunction->profile++;
405         pr_xstatement = s;
406         
407         if (pr_trace)
408                 PR_PrintStatement (st);
409                 
410         switch (st->op)
411         {
412         case OP_ADD_F:
413                 c->_float = a->_float + b->_float;
414                 break;
415         case OP_ADD_V:
416                 c->vector[0] = a->vector[0] + b->vector[0];
417                 c->vector[1] = a->vector[1] + b->vector[1];
418                 c->vector[2] = a->vector[2] + b->vector[2];
419                 break;
420                 
421         case OP_SUB_F:
422                 c->_float = a->_float - b->_float;
423                 break;
424         case OP_SUB_V:
425                 c->vector[0] = a->vector[0] - b->vector[0];
426                 c->vector[1] = a->vector[1] - b->vector[1];
427                 c->vector[2] = a->vector[2] - b->vector[2];
428                 break;
429
430         case OP_MUL_F:
431                 c->_float = a->_float * b->_float;
432                 break;
433         case OP_MUL_V:
434                 c->_float = a->vector[0]*b->vector[0]
435                                 + a->vector[1]*b->vector[1]
436                                 + a->vector[2]*b->vector[2];
437                 break;
438         case OP_MUL_FV:
439                 c->vector[0] = a->_float * b->vector[0];
440                 c->vector[1] = a->_float * b->vector[1];
441                 c->vector[2] = a->_float * b->vector[2];
442                 break;
443         case OP_MUL_VF:
444                 c->vector[0] = b->_float * a->vector[0];
445                 c->vector[1] = b->_float * a->vector[1];
446                 c->vector[2] = b->_float * a->vector[2];
447                 break;
448
449         case OP_DIV_F:
450                 c->_float = a->_float / b->_float;
451                 break;
452         
453         case OP_BITAND:
454                 c->_float = (int)a->_float & (int)b->_float;
455                 break;
456         
457         case OP_BITOR:
458                 c->_float = (int)a->_float | (int)b->_float;
459                 break;
460         
461                 
462         case OP_GE:
463                 c->_float = a->_float >= b->_float;
464                 break;
465         case OP_LE:
466                 c->_float = a->_float <= b->_float;
467                 break;
468         case OP_GT:
469                 c->_float = a->_float > b->_float;
470                 break;
471         case OP_LT:
472                 c->_float = a->_float < b->_float;
473                 break;
474         case OP_AND:
475                 c->_float = a->_float && b->_float;
476                 break;
477         case OP_OR:
478                 c->_float = a->_float || b->_float;
479                 break;
480                 
481         case OP_NOT_F:
482                 c->_float = !a->_float;
483                 break;
484         case OP_NOT_V:
485                 c->_float = !a->vector[0] && !a->vector[1] && !a->vector[2];
486                 break;
487         case OP_NOT_S:
488                 c->_float = !a->string || !pr_strings[a->string];
489                 break;
490         case OP_NOT_FNC:
491                 c->_float = !a->function;
492                 break;
493         case OP_NOT_ENT:
494                 c->_float = (PROG_TO_EDICT(a->edict) == sv.edicts);
495                 break;
496
497         case OP_EQ_F:
498                 c->_float = a->_float == b->_float;
499                 break;
500         case OP_EQ_V:
501                 c->_float = (a->vector[0] == b->vector[0]) &&
502                                         (a->vector[1] == b->vector[1]) &&
503                                         (a->vector[2] == b->vector[2]);
504                 break;
505         case OP_EQ_S:
506                 c->_float = !strcmp(pr_strings+a->string,pr_strings+b->string);
507                 break;
508         case OP_EQ_E:
509                 c->_float = a->_int == b->_int;
510                 break;
511         case OP_EQ_FNC:
512                 c->_float = a->function == b->function;
513                 break;
514
515
516         case OP_NE_F:
517                 c->_float = a->_float != b->_float;
518                 break;
519         case OP_NE_V:
520                 c->_float = (a->vector[0] != b->vector[0]) ||
521                                         (a->vector[1] != b->vector[1]) ||
522                                         (a->vector[2] != b->vector[2]);
523                 break;
524         case OP_NE_S:
525                 c->_float = strcmp(pr_strings+a->string,pr_strings+b->string);
526                 break;
527         case OP_NE_E:
528                 c->_float = a->_int != b->_int;
529                 break;
530         case OP_NE_FNC:
531                 c->_float = a->function != b->function;
532                 break;
533
534 //==================
535         case OP_STORE_F:
536         case OP_STORE_ENT:
537         case OP_STORE_FLD:              // integers
538         case OP_STORE_S:
539         case OP_STORE_FNC:              // pointers
540                 b->_int = a->_int;
541                 break;
542         case OP_STORE_V:
543                 b->vector[0] = a->vector[0];
544                 b->vector[1] = a->vector[1];
545                 b->vector[2] = a->vector[2];
546                 break;
547                 
548         case OP_STOREP_F:
549         case OP_STOREP_ENT:
550         case OP_STOREP_FLD:             // integers
551         case OP_STOREP_S:
552         case OP_STOREP_FNC:             // pointers
553                 ptr = (eval_t *)((byte *)sv.edicts + b->_int);
554                 ptr->_int = a->_int;
555                 break;
556         case OP_STOREP_V:
557                 ptr = (eval_t *)((byte *)sv.edicts + b->_int);
558                 ptr->vector[0] = a->vector[0];
559                 ptr->vector[1] = a->vector[1];
560                 ptr->vector[2] = a->vector[2];
561                 break;
562                 
563         case OP_ADDRESS:
564                 ed = PROG_TO_EDICT(a->edict);
565 #ifdef PARANOID
566                 NUM_FOR_EDICT(ed);              // make sure it's in range
567 #endif
568                 if (ed == (edict_t *)sv.edicts && sv.state == ss_active)
569                         PR_RunError ("assignment to world entity");
570                 c->_int = (byte *)((int *)&ed->v + b->_int) - (byte *)sv.edicts;
571                 break;
572                 
573         case OP_LOAD_F:
574         case OP_LOAD_FLD:
575         case OP_LOAD_ENT:
576         case OP_LOAD_S:
577         case OP_LOAD_FNC:
578                 ed = PROG_TO_EDICT(a->edict);
579 #ifdef PARANOID
580                 NUM_FOR_EDICT(ed);              // make sure it's in range
581 #endif
582                 a = (eval_t *)((int *)&ed->v + b->_int);
583                 c->_int = a->_int;
584                 break;
585
586         case OP_LOAD_V:
587                 ed = PROG_TO_EDICT(a->edict);
588 #ifdef PARANOID
589                 NUM_FOR_EDICT(ed);              // make sure it's in range
590 #endif
591                 a = (eval_t *)((int *)&ed->v + b->_int);
592                 c->vector[0] = a->vector[0];
593                 c->vector[1] = a->vector[1];
594                 c->vector[2] = a->vector[2];
595                 break;
596                 
597 //==================
598
599         case OP_IFNOT:
600                 if (!a->_int)
601                         s += st->b - 1; // offset the s++
602                 break;
603                 
604         case OP_IF:
605                 if (a->_int)
606                         s += st->b - 1; // offset the s++
607                 break;
608                 
609         case OP_GOTO:
610                 s += st->a - 1; // offset the s++
611                 break;
612                 
613         case OP_CALL0:
614         case OP_CALL1:
615         case OP_CALL2:
616         case OP_CALL3:
617         case OP_CALL4:
618         case OP_CALL5:
619         case OP_CALL6:
620         case OP_CALL7:
621         case OP_CALL8:
622                 pr_argc = st->op - OP_CALL0;
623                 if (!a->function)
624                         PR_RunError ("NULL function");
625
626                 newf = &pr_functions[a->function];
627
628                 if (newf->first_statement < 0)
629                 {       // negative statements are built in functions
630                         i = -newf->first_statement;
631                         if (i >= pr_numbuiltins)
632                                 PR_RunError ("Bad builtin call number");
633                         pr_builtins[i] ();
634                         break;
635                 }
636
637                 s = PR_EnterFunction (newf);
638                 break;
639
640         case OP_DONE:
641         case OP_RETURN:
642                 pr_globals[OFS_RETURN] = pr_globals[st->a];
643                 pr_globals[OFS_RETURN+1] = pr_globals[st->a+1];
644                 pr_globals[OFS_RETURN+2] = pr_globals[st->a+2];
645         
646                 s = PR_LeaveFunction ();
647                 if (pr_depth == exitdepth)
648                         return;         // all done
649                 break;
650                 
651         case OP_STATE:
652                 ed = PROG_TO_EDICT(pr_global_struct->self);
653 #ifdef FPS_20
654                 ed->v.nextthink = pr_global_struct->time + 0.05;
655 #else
656                 ed->v.nextthink = pr_global_struct->time + 0.1;
657 #endif
658                 //if (a->_float != ed->v.frame) // LordHavoc: this was silly
659                 //{
660                         ed->v.frame = a->_float;
661                 //}
662                 ed->v.think = b->function;
663                 break;
664                 
665         default:
666                 PR_RunError ("Bad opcode %i", st->op);
667         }
668 }
669
670 }
671 */
672
673 // LordHavoc: optimized
674 #define OPA ((eval_t *)&pr_globals[(unsigned short) st->a])
675 #define OPB ((eval_t *)&pr_globals[(unsigned short) st->b])
676 #define OPC ((eval_t *)&pr_globals[(unsigned short) st->c])
677 extern cvar_t pr_boundscheck;
678 void PR_ExecuteProgram (func_t fnum)
679 {
680         dstatement_t    *st;
681         dfunction_t     *f, *newf;
682         edict_t *ed;
683         int             exitdepth;
684         eval_t  *ptr;
685         int             profile, startprofile;
686
687         if (!fnum || fnum >= progs->numfunctions)
688         {
689                 if (pr_global_struct->self)
690                         ED_Print (PROG_TO_EDICT(pr_global_struct->self));
691                 Host_Error ("PR_ExecuteProgram: NULL function");
692         }
693         
694         f = &pr_functions[fnum];
695
696         pr_trace = false;
697
698 // make a stack frame
699         exitdepth = pr_depth;
700
701         st = &pr_statements[PR_EnterFunction (f)];
702         startprofile = profile = 0;
703
704         if (pr_boundscheck.value)
705         {
706                 while (1)
707                 {
708                         st++;
709                         if (++profile > 1000000) // LordHavoc: increased runaway loop limited 10x
710                         {
711                                 pr_xstatement = st - pr_statements;
712                                 PR_RunError ("runaway loop error");
713                         }
714                         
715                         if (pr_trace)
716                                 PR_PrintStatement (st);
717
718                         switch (st->op)
719                         {
720                         case OP_ADD_F:
721                                 OPC->_float = OPA->_float + OPB->_float;
722                                 break;
723                         case OP_ADD_V:
724                                 OPC->vector[0] = OPA->vector[0] + OPB->vector[0];
725                                 OPC->vector[1] = OPA->vector[1] + OPB->vector[1];
726                                 OPC->vector[2] = OPA->vector[2] + OPB->vector[2];
727                                 break;
728                         case OP_SUB_F:
729                                 OPC->_float = OPA->_float - OPB->_float;
730                                 break;
731                         case OP_SUB_V:
732                                 OPC->vector[0] = OPA->vector[0] - OPB->vector[0];
733                                 OPC->vector[1] = OPA->vector[1] - OPB->vector[1];
734                                 OPC->vector[2] = OPA->vector[2] - OPB->vector[2];
735                                 break;
736                         case OP_MUL_F:
737                                 OPC->_float = OPA->_float * OPB->_float;
738                                 break;
739                         case OP_MUL_V:
740                                 OPC->_float = OPA->vector[0]*OPB->vector[0] + OPA->vector[1]*OPB->vector[1] + OPA->vector[2]*OPB->vector[2];
741                                 break;
742                         case OP_MUL_FV:
743                                 OPC->vector[0] = OPA->_float * OPB->vector[0];
744                                 OPC->vector[1] = OPA->_float * OPB->vector[1];
745                                 OPC->vector[2] = OPA->_float * OPB->vector[2];
746                                 break;
747                         case OP_MUL_VF:
748                                 OPC->vector[0] = OPB->_float * OPA->vector[0];
749                                 OPC->vector[1] = OPB->_float * OPA->vector[1];
750                                 OPC->vector[2] = OPB->_float * OPA->vector[2];
751                                 break;
752                         case OP_DIV_F:
753                                 OPC->_float = OPA->_float / OPB->_float;
754                                 break;
755                         case OP_BITAND:
756                                 OPC->_float = (int)OPA->_float & (int)OPB->_float;
757                                 break;
758                         case OP_BITOR:
759                                 OPC->_float = (int)OPA->_float | (int)OPB->_float;
760                                 break;
761                         case OP_GE:
762                                 OPC->_float = OPA->_float >= OPB->_float;
763                                 break;
764                         case OP_LE:
765                                 OPC->_float = OPA->_float <= OPB->_float;
766                                 break;
767                         case OP_GT:
768                                 OPC->_float = OPA->_float > OPB->_float;
769                                 break;
770                         case OP_LT:
771                                 OPC->_float = OPA->_float < OPB->_float;
772                                 break;
773                         case OP_AND:
774                                 OPC->_float = OPA->_float && OPB->_float;
775                                 break;
776                         case OP_OR:
777                                 OPC->_float = OPA->_float || OPB->_float;
778                                 break;
779                         case OP_NOT_F:
780                                 OPC->_float = !OPA->_float;
781                                 break;
782                         case OP_NOT_V:
783                                 OPC->_float = !OPA->vector[0] && !OPA->vector[1] && !OPA->vector[2];
784                                 break;
785                         case OP_NOT_S:
786                                 OPC->_float = !OPA->string || !pr_strings[OPA->string];
787                                 break;
788                         case OP_NOT_FNC:
789                                 OPC->_float = !OPA->function;
790                                 break;
791                         case OP_NOT_ENT:
792                                 OPC->_float = (PROG_TO_EDICT(OPA->edict) == sv.edicts);
793                                 break;
794                         case OP_EQ_F:
795                                 OPC->_float = OPA->_float == OPB->_float;
796                                 break;
797                         case OP_EQ_V:
798                                 OPC->_float = (OPA->vector[0] == OPB->vector[0]) && (OPA->vector[1] == OPB->vector[1]) && (OPA->vector[2] == OPB->vector[2]);
799                                 break;
800                         case OP_EQ_S:
801                                 OPC->_float = !strcmp(pr_strings+OPA->string,pr_strings+OPB->string);
802                                 break;
803                         case OP_EQ_E:
804                                 OPC->_float = OPA->_int == OPB->_int;
805                                 break;
806                         case OP_EQ_FNC:
807                                 OPC->_float = OPA->function == OPB->function;
808                                 break;
809                         case OP_NE_F:
810                                 OPC->_float = OPA->_float != OPB->_float;
811                                 break;
812                         case OP_NE_V:
813                                 OPC->_float = (OPA->vector[0] != OPB->vector[0]) || (OPA->vector[1] != OPB->vector[1]) || (OPA->vector[2] != OPB->vector[2]);
814                                 break;
815                         case OP_NE_S:
816                                 OPC->_float = strcmp(pr_strings+OPA->string,pr_strings+OPB->string);
817                                 break;
818                         case OP_NE_E:
819                                 OPC->_float = OPA->_int != OPB->_int;
820                                 break;
821                         case OP_NE_FNC:
822                                 OPC->_float = OPA->function != OPB->function;
823                                 break;
824
825                 //==================
826                         case OP_STORE_F:
827                         case OP_STORE_ENT:
828                         case OP_STORE_FLD:              // integers
829                         case OP_STORE_S:
830                         case OP_STORE_FNC:              // pointers
831                                 OPB->_int = OPA->_int;
832                                 break;
833                         case OP_STORE_V:
834                                 OPB->vector[0] = OPA->vector[0];
835                                 OPB->vector[1] = OPA->vector[1];
836                                 OPB->vector[2] = OPA->vector[2];
837                                 break;
838                                 
839                         case OP_STOREP_F:
840                         case OP_STOREP_ENT:
841                         case OP_STOREP_FLD:             // integers
842                         case OP_STOREP_S:
843                         case OP_STOREP_FNC:             // pointers
844                                 if (OPB->_int < 0 || OPB->_int + 4 > pr_edictareasize)
845                                 {
846                                         pr_xstatement = st - pr_statements;
847                                         PR_RunError("Progs attempted to write to an out of bounds edict\n");
848                                         return;
849                                 }
850                                 if (OPB->_int % pr_edict_size < ((byte *)&sv.edicts->v - (byte *)sv.edicts))
851                                 {
852                                         pr_xstatement = st - pr_statements;
853                                         PR_RunError("Progs attempted to write to an engine edict field\n");
854                                         return;
855                                 }
856                                 ptr = (eval_t *)((byte *)sv.edicts + OPB->_int);
857                                 ptr->_int = OPA->_int;
858                                 break;
859                         case OP_STOREP_V:
860                                 if (OPB->_int < 0 || OPB->_int + 12 > pr_edictareasize)
861                                 {
862                                         pr_xstatement = st - pr_statements;
863                                         PR_RunError("Progs attempted to write to an out of bounds edict\n");
864                                         return;
865                                 }
866                                 ptr = (eval_t *)((byte *)sv.edicts + OPB->_int);
867                                 ptr->vector[0] = OPA->vector[0];
868                                 ptr->vector[1] = OPA->vector[1];
869                                 ptr->vector[2] = OPA->vector[2];
870                                 break;
871                                 
872                         case OP_ADDRESS:
873                                 if (OPA->edict < 0 || OPA->edict >= pr_edictareasize)
874                                 {
875                                         pr_xstatement = st - pr_statements;
876                                         PR_RunError("Progs attempted to address an out of bounds edict\n");
877                                         return;
878                                 }
879                                 if (OPA->edict == 0 && sv.state == ss_active)
880                                 {
881                                         pr_xstatement = st - pr_statements;
882                                         PR_RunError ("assignment to world entity");
883                                         return;
884                                 }
885                                 if (OPB->_int < 0 || OPB->_int >= progs->entityfields)
886                                 {
887                                         pr_xstatement = st - pr_statements;
888                                         PR_RunError("Progs attempted to address an invalid field in an edict\n");
889                                         return;
890                                 }
891                                 ed = PROG_TO_EDICT(OPA->edict);
892                                 OPC->_int = (byte *)((int *)&ed->v + OPB->_int) - (byte *)sv.edicts;
893                                 break;
894                                 
895                         case OP_LOAD_F:
896                         case OP_LOAD_FLD:
897                         case OP_LOAD_ENT:
898                         case OP_LOAD_S:
899                         case OP_LOAD_FNC:
900                                 if (OPA->edict < 0 || OPA->edict >= pr_edictareasize)
901                                 {
902                                         pr_xstatement = st - pr_statements;
903                                         PR_RunError("Progs attempted to read an out of bounds edict number\n");
904                                         return;
905                                 }
906                                 if (OPB->_int < 0 || OPB->_int >= progs->entityfields)
907                                 {
908                                         pr_xstatement = st - pr_statements;
909                                         PR_RunError("Progs attempted to read an invalid field in an edict\n");
910                                         return;
911                                 }
912                                 ed = PROG_TO_EDICT(OPA->edict);
913                                 OPC->_int = ((eval_t *)((int *)&ed->v + OPB->_int))->_int;
914                                 break;
915
916                         case OP_LOAD_V:
917                                 if (OPA->edict < 0 || OPA->edict >= pr_edictareasize)
918                                 {
919                                         pr_xstatement = st - pr_statements;
920                                         PR_RunError("Progs attempted to read an out of bounds edict number\n");
921                                         return;
922                                 }
923                                 if (OPB->_int < 0 || OPB->_int + 2 >= progs->entityfields)
924                                 {
925                                         pr_xstatement = st - pr_statements;
926                                         PR_RunError("Progs attempted to read an invalid field in an edict\n");
927                                         return;
928                                 }
929                                 ed = PROG_TO_EDICT(OPA->edict);
930                                 OPC->vector[0] = ((eval_t *)((int *)&ed->v + OPB->_int))->vector[0];
931                                 OPC->vector[1] = ((eval_t *)((int *)&ed->v + OPB->_int))->vector[1];
932                                 OPC->vector[2] = ((eval_t *)((int *)&ed->v + OPB->_int))->vector[2];
933                                 break;
934                                 
935                 //==================
936
937                         case OP_IFNOT:
938                                 if (!OPA->_int)
939                                         st += st->b - 1;        // offset the s++
940                                 break;
941                                 
942                         case OP_IF:
943                                 if (OPA->_int)
944                                         st += st->b - 1;        // offset the s++
945                                 break;
946                                 
947                         case OP_GOTO:
948                                 st += st->a - 1;        // offset the s++
949                                 break;
950                                 
951                         case OP_CALL0:
952                         case OP_CALL1:
953                         case OP_CALL2:
954                         case OP_CALL3:
955                         case OP_CALL4:
956                         case OP_CALL5:
957                         case OP_CALL6:
958                         case OP_CALL7:
959                         case OP_CALL8:
960                                 pr_xfunction->profile += profile - startprofile;
961                                 startprofile = profile;
962                                 pr_xstatement = st - pr_statements;
963                                 pr_argc = st->op - OP_CALL0;
964                                 if (!OPA->function)
965                                         PR_RunError ("NULL function");
966
967                                 newf = &pr_functions[OPA->function];
968
969                                 if (newf->first_statement < 0)
970                                 {       // negative statements are built in functions
971                                         int i = -newf->first_statement;
972                                         if (i >= pr_numbuiltins)
973                                                 PR_RunError ("Bad builtin call number");
974                                         pr_builtins[i] ();
975                                         break;
976                                 }
977
978                                 st = &pr_statements[PR_EnterFunction (newf)];
979                                 break;
980
981                         case OP_DONE:
982                         case OP_RETURN:
983                                 pr_globals[OFS_RETURN] = pr_globals[(unsigned short) st->a];
984                                 pr_globals[OFS_RETURN+1] = pr_globals[(unsigned short) st->a+1];
985                                 pr_globals[OFS_RETURN+2] = pr_globals[(unsigned short) st->a+2];
986                         
987                                 st = &pr_statements[PR_LeaveFunction ()];
988                                 if (pr_depth == exitdepth)
989                                         return;         // all done
990                                 break;
991                                 
992                         case OP_STATE:
993                                 ed = PROG_TO_EDICT(pr_global_struct->self);
994                 #ifdef FPS_20
995                                 ed->v.nextthink = pr_global_struct->time + 0.05;
996                 #else
997                                 ed->v.nextthink = pr_global_struct->time + 0.1;
998                 #endif
999                                 ed->v.frame = OPA->_float;
1000                                 ed->v.think = OPB->function;
1001                                 break;
1002                                 
1003                         default:
1004                                 pr_xstatement = st - pr_statements;
1005                                 PR_RunError ("Bad opcode %i", st->op);
1006                         }
1007                 }
1008         }
1009         else
1010         {
1011                 while (1)
1012                 {
1013                         st++;
1014                         if (++profile > 1000000) // LordHavoc: increased runaway loop limited 10x
1015                         {
1016                                 pr_xstatement = st - pr_statements;
1017                                 PR_RunError ("runaway loop error");
1018                         }
1019                         
1020                         if (pr_trace)
1021                                 PR_PrintStatement (st);
1022
1023                         switch (st->op)
1024                         {
1025                         case OP_ADD_F:
1026                                 OPC->_float = OPA->_float + OPB->_float;
1027                                 break;
1028                         case OP_ADD_V:
1029                                 OPC->vector[0] = OPA->vector[0] + OPB->vector[0];
1030                                 OPC->vector[1] = OPA->vector[1] + OPB->vector[1];
1031                                 OPC->vector[2] = OPA->vector[2] + OPB->vector[2];
1032                                 break;
1033                         case OP_SUB_F:
1034                                 OPC->_float = OPA->_float - OPB->_float;
1035                                 break;
1036                         case OP_SUB_V:
1037                                 OPC->vector[0] = OPA->vector[0] - OPB->vector[0];
1038                                 OPC->vector[1] = OPA->vector[1] - OPB->vector[1];
1039                                 OPC->vector[2] = OPA->vector[2] - OPB->vector[2];
1040                                 break;
1041                         case OP_MUL_F:
1042                                 OPC->_float = OPA->_float * OPB->_float;
1043                                 break;
1044                         case OP_MUL_V:
1045                                 OPC->_float = OPA->vector[0]*OPB->vector[0] + OPA->vector[1]*OPB->vector[1] + OPA->vector[2]*OPB->vector[2];
1046                                 break;
1047                         case OP_MUL_FV:
1048                                 OPC->vector[0] = OPA->_float * OPB->vector[0];
1049                                 OPC->vector[1] = OPA->_float * OPB->vector[1];
1050                                 OPC->vector[2] = OPA->_float * OPB->vector[2];
1051                                 break;
1052                         case OP_MUL_VF:
1053                                 OPC->vector[0] = OPB->_float * OPA->vector[0];
1054                                 OPC->vector[1] = OPB->_float * OPA->vector[1];
1055                                 OPC->vector[2] = OPB->_float * OPA->vector[2];
1056                                 break;
1057                         case OP_DIV_F:
1058                                 OPC->_float = OPA->_float / OPB->_float;
1059                                 break;
1060                         case OP_BITAND:
1061                                 OPC->_float = (int)OPA->_float & (int)OPB->_float;
1062                                 break;
1063                         case OP_BITOR:
1064                                 OPC->_float = (int)OPA->_float | (int)OPB->_float;
1065                                 break;
1066                         case OP_GE:
1067                                 OPC->_float = OPA->_float >= OPB->_float;
1068                                 break;
1069                         case OP_LE:
1070                                 OPC->_float = OPA->_float <= OPB->_float;
1071                                 break;
1072                         case OP_GT:
1073                                 OPC->_float = OPA->_float > OPB->_float;
1074                                 break;
1075                         case OP_LT:
1076                                 OPC->_float = OPA->_float < OPB->_float;
1077                                 break;
1078                         case OP_AND:
1079                                 OPC->_float = OPA->_float && OPB->_float;
1080                                 break;
1081                         case OP_OR:
1082                                 OPC->_float = OPA->_float || OPB->_float;
1083                                 break;
1084                         case OP_NOT_F:
1085                                 OPC->_float = !OPA->_float;
1086                                 break;
1087                         case OP_NOT_V:
1088                                 OPC->_float = !OPA->vector[0] && !OPA->vector[1] && !OPA->vector[2];
1089                                 break;
1090                         case OP_NOT_S:
1091                                 OPC->_float = !OPA->string || !pr_strings[OPA->string];
1092                                 break;
1093                         case OP_NOT_FNC:
1094                                 OPC->_float = !OPA->function;
1095                                 break;
1096                         case OP_NOT_ENT:
1097                                 OPC->_float = (PROG_TO_EDICT(OPA->edict) == sv.edicts);
1098                                 break;
1099                         case OP_EQ_F:
1100                                 OPC->_float = OPA->_float == OPB->_float;
1101                                 break;
1102                         case OP_EQ_V:
1103                                 OPC->_float = (OPA->vector[0] == OPB->vector[0]) && (OPA->vector[1] == OPB->vector[1]) && (OPA->vector[2] == OPB->vector[2]);
1104                                 break;
1105                         case OP_EQ_S:
1106                                 OPC->_float = !strcmp(pr_strings+OPA->string,pr_strings+OPB->string);
1107                                 break;
1108                         case OP_EQ_E:
1109                                 OPC->_float = OPA->_int == OPB->_int;
1110                                 break;
1111                         case OP_EQ_FNC:
1112                                 OPC->_float = OPA->function == OPB->function;
1113                                 break;
1114                         case OP_NE_F:
1115                                 OPC->_float = OPA->_float != OPB->_float;
1116                                 break;
1117                         case OP_NE_V:
1118                                 OPC->_float = (OPA->vector[0] != OPB->vector[0]) || (OPA->vector[1] != OPB->vector[1]) || (OPA->vector[2] != OPB->vector[2]);
1119                                 break;
1120                         case OP_NE_S:
1121                                 OPC->_float = strcmp(pr_strings+OPA->string,pr_strings+OPB->string);
1122                                 break;
1123                         case OP_NE_E:
1124                                 OPC->_float = OPA->_int != OPB->_int;
1125                                 break;
1126                         case OP_NE_FNC:
1127                                 OPC->_float = OPA->function != OPB->function;
1128                                 break;
1129
1130                 //==================
1131                         case OP_STORE_F:
1132                         case OP_STORE_ENT:
1133                         case OP_STORE_FLD:              // integers
1134                         case OP_STORE_S:
1135                         case OP_STORE_FNC:              // pointers
1136                                 OPB->_int = OPA->_int;
1137                                 break;
1138                         case OP_STORE_V:
1139                                 OPB->vector[0] = OPA->vector[0];
1140                                 OPB->vector[1] = OPA->vector[1];
1141                                 OPB->vector[2] = OPA->vector[2];
1142                                 break;
1143                                 
1144                         case OP_STOREP_F:
1145                         case OP_STOREP_ENT:
1146                         case OP_STOREP_FLD:             // integers
1147                         case OP_STOREP_S:
1148                         case OP_STOREP_FNC:             // pointers
1149                                 if (OPB->_int < 0 || OPB->_int + 4 > pr_edictareasize)
1150                                 {
1151                                         pr_xstatement = st - pr_statements;
1152                                         PR_RunError("Progs attempted to write to an out of bounds edict\n");
1153                                         return;
1154                                 }
1155                                 if (OPB->_int % pr_edict_size < ((byte *)&sv.edicts->v - (byte *)sv.edicts))
1156                                 {
1157                                         pr_xstatement = st - pr_statements;
1158                                         PR_RunError("Progs attempted to write to an engine edict field\n");
1159                                         return;
1160                                 }
1161                                 ptr = (eval_t *)((byte *)sv.edicts + OPB->_int);
1162                                 ptr->_int = OPA->_int;
1163                                 break;
1164                         case OP_STOREP_V:
1165                                 if (OPB->_int < 0 || OPB->_int + 12 > pr_edictareasize)
1166                                 {
1167                                         pr_xstatement = st - pr_statements;
1168                                         PR_RunError("Progs attempted to write to an out of bounds edict\n");
1169                                         return;
1170                                 }
1171                                 ptr = (eval_t *)((byte *)sv.edicts + OPB->_int);
1172                                 ptr->vector[0] = OPA->vector[0];
1173                                 ptr->vector[1] = OPA->vector[1];
1174                                 ptr->vector[2] = OPA->vector[2];
1175                                 break;
1176                                 
1177                         case OP_ADDRESS:
1178                                 if (OPA->edict < 0 || OPA->edict >= pr_edictareasize)
1179                                 {
1180                                         pr_xstatement = st - pr_statements;
1181                                         PR_RunError("Progs attempted to address an out of bounds edict\n");
1182                                         return;
1183                                 }
1184                                 if (OPA->edict == 0 && sv.state == ss_active)
1185                                 {
1186                                         pr_xstatement = st - pr_statements;
1187                                         PR_RunError ("assignment to world entity");
1188                                         return;
1189                                 }
1190                                 if (OPB->_int < 0 || OPB->_int >= progs->entityfields)
1191                                 {
1192                                         pr_xstatement = st - pr_statements;
1193                                         PR_RunError("Progs attempted to address an invalid field in an edict\n");
1194                                         return;
1195                                 }
1196                                 ed = PROG_TO_EDICT(OPA->edict);
1197                                 OPC->_int = (byte *)((int *)&ed->v + OPB->_int) - (byte *)sv.edicts;
1198                                 break;
1199                                 
1200                         case OP_LOAD_F:
1201                         case OP_LOAD_FLD:
1202                         case OP_LOAD_ENT:
1203                         case OP_LOAD_S:
1204                         case OP_LOAD_FNC:
1205                                 if (OPA->edict < 0 || OPA->edict >= pr_edictareasize)
1206                                 {
1207                                         pr_xstatement = st - pr_statements;
1208                                         PR_RunError("Progs attempted to read an out of bounds edict number\n");
1209                                         return;
1210                                 }
1211                                 if (OPB->_int < 0 || OPB->_int >= progs->entityfields)
1212                                 {
1213                                         pr_xstatement = st - pr_statements;
1214                                         PR_RunError("Progs attempted to read an invalid field in an edict\n");
1215                                         return;
1216                                 }
1217                                 ed = PROG_TO_EDICT(OPA->edict);
1218                                 OPC->_int = ((eval_t *)((int *)&ed->v + OPB->_int))->_int;
1219                                 break;
1220
1221                         case OP_LOAD_V:
1222                                 if (OPA->edict < 0 || OPA->edict >= pr_edictareasize)
1223                                 {
1224                                         pr_xstatement = st - pr_statements;
1225                                         PR_RunError("Progs attempted to read an out of bounds edict number\n");
1226                                         return;
1227                                 }
1228                                 if (OPB->_int < 0 || OPB->_int + 2 >= progs->entityfields)
1229                                 {
1230                                         pr_xstatement = st - pr_statements;
1231                                         PR_RunError("Progs attempted to read an invalid field in an edict\n");
1232                                         return;
1233                                 }
1234                                 ed = PROG_TO_EDICT(OPA->edict);
1235                                 OPC->vector[0] = ((eval_t *)((int *)&ed->v + OPB->_int))->vector[0];
1236                                 OPC->vector[1] = ((eval_t *)((int *)&ed->v + OPB->_int))->vector[1];
1237                                 OPC->vector[2] = ((eval_t *)((int *)&ed->v + OPB->_int))->vector[2];
1238                                 break;
1239                                 
1240                 //==================
1241
1242                         case OP_IFNOT:
1243                                 if (!OPA->_int)
1244                                         st += st->b - 1;        // offset the s++
1245                                 break;
1246                                 
1247                         case OP_IF:
1248                                 if (OPA->_int)
1249                                         st += st->b - 1;        // offset the s++
1250                                 break;
1251                                 
1252                         case OP_GOTO:
1253                                 st += st->a - 1;        // offset the s++
1254                                 break;
1255                                 
1256                         case OP_CALL0:
1257                         case OP_CALL1:
1258                         case OP_CALL2:
1259                         case OP_CALL3:
1260                         case OP_CALL4:
1261                         case OP_CALL5:
1262                         case OP_CALL6:
1263                         case OP_CALL7:
1264                         case OP_CALL8:
1265                                 pr_xfunction->profile += profile - startprofile;
1266                                 startprofile = profile;
1267                                 pr_xstatement = st - pr_statements;
1268                                 pr_argc = st->op - OP_CALL0;
1269                                 if (!OPA->function)
1270                                         PR_RunError ("NULL function");
1271
1272                                 newf = &pr_functions[OPA->function];
1273
1274                                 if (newf->first_statement < 0)
1275                                 {       // negative statements are built in functions
1276                                         int i = -newf->first_statement;
1277                                         if (i >= pr_numbuiltins)
1278                                                 PR_RunError ("Bad builtin call number");
1279                                         pr_builtins[i] ();
1280                                         break;
1281                                 }
1282
1283                                 st = &pr_statements[PR_EnterFunction (newf)];
1284                                 break;
1285
1286                         case OP_DONE:
1287                         case OP_RETURN:
1288                                 pr_globals[OFS_RETURN] = pr_globals[(unsigned short) st->a];
1289                                 pr_globals[OFS_RETURN+1] = pr_globals[(unsigned short) st->a+1];
1290                                 pr_globals[OFS_RETURN+2] = pr_globals[(unsigned short) st->a+2];
1291                         
1292                                 st = &pr_statements[PR_LeaveFunction ()];
1293                                 if (pr_depth == exitdepth)
1294                                         return;         // all done
1295                                 break;
1296                                 
1297                         case OP_STATE:
1298                                 ed = PROG_TO_EDICT(pr_global_struct->self);
1299                 #ifdef FPS_20
1300                                 ed->v.nextthink = pr_global_struct->time + 0.05;
1301                 #else
1302                                 ed->v.nextthink = pr_global_struct->time + 0.1;
1303                 #endif
1304                                 ed->v.frame = OPA->_float;
1305                                 ed->v.think = OPB->function;
1306                                 break;
1307                                 
1308                 //==================
1309
1310 // LordHavoc: to be enabled when Progs version 7 (or whatever it will be numbered) is finalized
1311 /*
1312                         case OP_ADD_I:
1313                                 OPC->_int = OPA->_int + OPB->_int;
1314                                 break;
1315                         case OP_ADD_IF:
1316                                 OPC->_int = OPA->_int + (int) OPB->_float;
1317                                 break;
1318                         case OP_ADD_FI:
1319                                 OPC->_float = OPA->_float + (float) OPB->_int;
1320                                 break;
1321                         case OP_SUB_I:
1322                                 OPC->_int = OPA->_int - OPB->_int;
1323                                 break;
1324                         case OP_SUB_IF:
1325                                 OPC->_int = OPA->_int - (int) OPB->_float;
1326                                 break;
1327                         case OP_SUB_FI:
1328                                 OPC->_float = OPA->_float - (float) OPB->_int;
1329                                 break;
1330                         case OP_MUL_I:
1331                                 OPC->_int = OPA->_int * OPB->_int;
1332                                 break;
1333                         case OP_MUL_IF:
1334                                 OPC->_int = OPA->_int * (int) OPB->_float;
1335                                 break;
1336                         case OP_MUL_FI:
1337                                 OPC->_float = OPA->_float * (float) OPB->_int;
1338                                 break;
1339                         case OP_MUL_VI:
1340                                 OPC->vector[0] = (float) OPB->_int * OPA->vector[0];
1341                                 OPC->vector[1] = (float) OPB->_int * OPA->vector[1];
1342                                 OPC->vector[2] = (float) OPB->_int * OPA->vector[2];
1343                                 break;
1344                         case OP_DIV_VF:
1345                                 {
1346                                         float temp = 1.0f / OPB->_float;
1347                                         OPC->vector[0] = temp * OPA->vector[0];
1348                                         OPC->vector[1] = temp * OPA->vector[1];
1349                                         OPC->vector[2] = temp * OPA->vector[2];
1350                                 }
1351                                 break;
1352                         case OP_DIV_I:
1353                                 OPC->_int = OPA->_int / OPB->_int;
1354                                 break;
1355                         case OP_DIV_IF:
1356                                 OPC->_int = OPA->_int / (int) OPB->_float;
1357                                 break;
1358                         case OP_DIV_FI:
1359                                 OPC->_float = OPA->_float / (float) OPB->_int;
1360                                 break;
1361                         case OP_BITAND_I:
1362                                 OPC->_int = OPA->_int & OPB->_int;
1363                                 break;
1364                         case OP_BITOR_I:
1365                                 OPC->_int = OPA->_int | OPB->_int;
1366                                 break;
1367                         case OP_BITAND_IF:
1368                                 OPC->_int = OPA->_int & (int)OPB->_float;
1369                                 break;
1370                         case OP_BITOR_IF:
1371                                 OPC->_int = OPA->_int | (int)OPB->_float;
1372                                 break;
1373                         case OP_BITAND_FI:
1374                                 OPC->_float = (int)OPA->_float & OPB->_int;
1375                                 break;
1376                         case OP_BITOR_FI:
1377                                 OPC->_float = (int)OPA->_float | OPB->_int;
1378                                 break;
1379                         case OP_GE_I:
1380                                 OPC->_float = OPA->_int >= OPB->_int;
1381                                 break;
1382                         case OP_LE_I:
1383                                 OPC->_float = OPA->_int <= OPB->_int;
1384                                 break;
1385                         case OP_GT_I:
1386                                 OPC->_float = OPA->_int > OPB->_int;
1387                                 break;
1388                         case OP_LT_I:
1389                                 OPC->_float = OPA->_int < OPB->_int;
1390                                 break;
1391                         case OP_AND_I:
1392                                 OPC->_float = OPA->_int && OPB->_int;
1393                                 break;
1394                         case OP_OR_I:
1395                                 OPC->_float = OPA->_int || OPB->_int;
1396                                 break;
1397                         case OP_GE_IF:
1398                                 OPC->_float = (float)OPA->_int >= OPB->_float;
1399                                 break;
1400                         case OP_LE_IF:
1401                                 OPC->_float = (float)OPA->_int <= OPB->_float;
1402                                 break;
1403                         case OP_GT_IF:
1404                                 OPC->_float = (float)OPA->_int > OPB->_float;
1405                                 break;
1406                         case OP_LT_IF:
1407                                 OPC->_float = (float)OPA->_int < OPB->_float;
1408                                 break;
1409                         case OP_AND_IF:
1410                                 OPC->_float = (float)OPA->_int && OPB->_float;
1411                                 break;
1412                         case OP_OR_IF:
1413                                 OPC->_float = (float)OPA->_int || OPB->_float;
1414                                 break;
1415                         case OP_GE_FI:
1416                                 OPC->_float = OPA->_float >= (float)OPB->_int;
1417                                 break;
1418                         case OP_LE_FI:
1419                                 OPC->_float = OPA->_float <= (float)OPB->_int;
1420                                 break;
1421                         case OP_GT_FI:
1422                                 OPC->_float = OPA->_float > (float)OPB->_int;
1423                                 break;
1424                         case OP_LT_FI:
1425                                 OPC->_float = OPA->_float < (float)OPB->_int;
1426                                 break;
1427                         case OP_AND_FI:
1428                                 OPC->_float = OPA->_float && (float)OPB->_int;
1429                                 break;
1430                         case OP_OR_FI:
1431                                 OPC->_float = OPA->_float || (float)OPB->_int;
1432                                 break;
1433                         case OP_NOT_I:
1434                                 OPC->_float = !OPA->_int;
1435                                 break;
1436                         case OP_EQ_I:
1437                                 OPC->_float = OPA->_int == OPB->_int;
1438                                 break;
1439                         case OP_EQ_IF:
1440                                 OPC->_float = (float)OPA->_int == OPB->_float;
1441                                 break;
1442                         case OP_EQ_FI:
1443                                 OPC->_float = OPA->_float == (float)OPB->_int;
1444                                 break;
1445                         case OP_NE_I:
1446                                 OPC->_float = OPA->_int != OPB->_int;
1447                                 break;
1448                         case OP_NE_IF:
1449                                 OPC->_float = (float)OPA->_int != OPB->_float;
1450                                 break;
1451                         case OP_NE_FI:
1452                                 OPC->_float = OPA->_float != (float)OPB->_int;
1453                                 break;
1454                         case OP_STORE_I:
1455                                 OPB->_int = OPA->_int;
1456                                 break;
1457                         case OP_STOREP_I:
1458                                 if (OPB->_int < 0 || OPB->_int + 4 > pr_edictareasize)
1459                                 {
1460                                         pr_xstatement = st - pr_statements;
1461                                         PR_RunError("Progs attempted to write to an out of bounds edict\n");
1462                                         return;
1463                                 }
1464                                 if (OPB->_int % pr_edict_size < ((byte *)&sv.edicts->v - (byte *)sv.edicts))
1465                                 {
1466                                         pr_xstatement = st - pr_statements;
1467                                         PR_RunError("Progs attempted to write to an engine edict field\n");
1468                                         return;
1469                                 }
1470                                 ptr = (eval_t *)((byte *)sv.edicts + OPB->_int);
1471                                 ptr->_int = OPA->_int;
1472                                 break;
1473                         case OP_LOAD_I:
1474                                 if (OPA->edict < 0 || OPA->edict >= pr_edictareasize)
1475                                 {
1476                                         pr_xstatement = st - pr_statements;
1477                                         PR_RunError("Progs attempted to read an out of bounds edict number\n");
1478                                         return;
1479                                 }
1480                                 if (OPB->_int < 0 || OPB->_int >= progs->entityfields)
1481                                 {
1482                                         pr_xstatement = st - pr_statements;
1483                                         PR_RunError("Progs attempted to read an invalid field in an edict\n");
1484                                         return;
1485                                 }
1486                                 ed = PROG_TO_EDICT(OPA->edict);
1487                                 OPC->_int = ((eval_t *)((int *)&ed->v + OPB->_int))->_int;
1488                                 break;
1489
1490                         case OP_GSTOREP_I:
1491                         case OP_GSTOREP_F:
1492                         case OP_GSTOREP_ENT:
1493                         case OP_GSTOREP_FLD:            // integers
1494                         case OP_GSTOREP_S:
1495                         case OP_GSTOREP_FNC:            // pointers
1496                                 if (OPB->_int < 0 || OPB->_int >= pr_globaldefs)
1497                                 {
1498                                         pr_xstatement = st - pr_statements;
1499                                         PR_RunError("Progs attempted to write to an invalid indexed global\n");
1500                                         return;
1501                                 }
1502                                 pr_globals[OPB->_int] = OPA->_float;
1503                                 break;
1504                         case OP_GSTOREP_V:
1505                                 if (OPB->_int < 0 || OPB->_int + 2 >= pr_globaldefs)
1506                                 {
1507                                         pr_xstatement = st - pr_statements;
1508                                         PR_RunError("Progs attempted to write to an invalid indexed global\n");
1509                                         return;
1510                                 }
1511                                 pr_globals[OPB->_int  ] = OPA->vector[0];
1512                                 pr_globals[OPB->_int+1] = OPA->vector[1];
1513                                 pr_globals[OPB->_int+2] = OPA->vector[2];
1514                                 break;
1515                                 
1516                         case OP_GADDRESS:
1517                                 i = OPA->_int + (int) OPB->_float;
1518                                 if (i < 0 || i >= pr_globaldefs)
1519                                 {
1520                                         pr_xstatement = st - pr_statements;
1521                                         PR_RunError("Progs attempted to address an out of bounds global\n");
1522                                         return;
1523                                 }
1524                                 OPC->_float = pr_globals[i];
1525                                 break;
1526                                 
1527                         case OP_GLOAD_I:
1528                         case OP_GLOAD_F:
1529                         case OP_GLOAD_FLD:
1530                         case OP_GLOAD_ENT:
1531                         case OP_GLOAD_S:
1532                         case OP_GLOAD_FNC:
1533                                 if (OPA->_int < 0 || OPA->_int >= pr_globaldefs)
1534                                 {
1535                                         pr_xstatement = st - pr_statements;
1536                                         PR_RunError("Progs attempted to read an invalid indexed global\n");
1537                                         return;
1538                                 }
1539                                 OPC->_float = pr_globals[OPA->_int];
1540                                 break;
1541
1542                         case OP_GLOAD_V:
1543                                 if (OPA->_int < 0 || OPA->_int + 2 >= pr_globaldefs)
1544                                 {
1545                                         pr_xstatement = st - pr_statements;
1546                                         PR_RunError("Progs attempted to read an invalid indexed global\n");
1547                                         return;
1548                                 }
1549                                 OPC->vector[0] = pr_globals[OPA->_int  ];
1550                                 OPC->vector[1] = pr_globals[OPA->_int+1];
1551                                 OPC->vector[2] = pr_globals[OPA->_int+2];
1552                                 break;
1553
1554                         case OP_BOUNDCHECK:
1555                                 if (OPA->_int < 0 || OPA->_int >= st->b)
1556                                 {
1557                                         pr_xstatement = st - pr_statements;
1558                                         PR_RunError("Progs boundcheck failed at line number %d, value is < 0 or >= %d\n", st->b, st->c);
1559                                         return;
1560                                 }
1561                                 break;
1562
1563 */
1564                 //==================
1565
1566                         default:
1567                                 pr_xstatement = st - pr_statements;
1568                                 PR_RunError ("Bad opcode %i", st->op);
1569                         }
1570                 }
1571         }
1572 }