2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
34 #define MAX_STACK_DEPTH 32
35 prstack_t pr_stack[MAX_STACK_DEPTH];
38 #define LOCALSTACK_SIZE 2048
39 int localstack[LOCALSTACK_SIZE];
44 dfunction_t *pr_xfunction;
139 char *PR_GlobalString (int ofs);
140 char *PR_GlobalStringNoContents (int ofs);
143 //=============================================================================
150 void PR_PrintStatement (dstatement_t *s)
154 if ( (unsigned)s->op < sizeof(pr_opnames)/sizeof(pr_opnames[0]))
156 Con_Printf ("%s ", pr_opnames[s->op]);
157 i = strlen(pr_opnames[s->op]);
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)
166 Con_Printf ("branch %i",s->a);
168 else if ( (unsigned)(s->op - OP_STORE_F) < 6)
170 Con_Printf ("%s",PR_GlobalString((unsigned short) s->a));
171 Con_Printf ("%s", PR_GlobalStringNoContents((unsigned short) s->b));
176 Con_Printf ("%s",PR_GlobalString((unsigned short) s->a));
178 Con_Printf ("%s",PR_GlobalString((unsigned short) s->b));
180 Con_Printf ("%s", PR_GlobalStringNoContents((unsigned short) s->c));
190 void PR_StackTrace (void)
197 Con_Printf ("<NO STACK>\n");
201 pr_stack[pr_depth].f = pr_xfunction;
202 for (i=pr_depth ; i>=0 ; i--)
208 Con_Printf ("<NO FUNCTION>\n");
211 Con_Printf ("%12s : %s\n", pr_strings + f->s_file, pr_strings + f->s_name);
222 void PR_Profile_f (void)
224 dfunction_t *f, *best;
234 for (i=0 ; i<progs->numfunctions ; i++)
236 f = &pr_functions[i];
237 if (f->profile > max)
246 Con_Printf ("%7i %s\n", best->profile, pr_strings+best->s_name);
258 Aborts the currently executing function
261 void PR_RunError (char *error, ...)
266 va_start (argptr,error);
267 vsprintf (string,error,argptr);
270 PR_PrintStatement (pr_statements + pr_xstatement);
272 Con_Printf ("%s\n", string);
274 pr_depth = 0; // dump the stack so host_error can shutdown functions
276 Host_Error ("Program error");
280 ============================================================================
283 The interpretation main loop
284 ============================================================================
291 Returns the new program statement counter
294 int PR_EnterFunction (dfunction_t *f)
298 pr_stack[pr_depth].s = pr_xstatement;
299 pr_stack[pr_depth].f = pr_xfunction;
301 if (pr_depth >= MAX_STACK_DEPTH)
302 PR_RunError ("stack overflow");
304 // save off any locals that the new function steps on
306 if (localstack_used + c > LOCALSTACK_SIZE)
307 PR_RunError ("PR_ExecuteProgram: locals stack overflow\n");
309 for (i=0 ; i < c ; i++)
310 localstack[localstack_used+i] = ((int *)pr_globals)[f->parm_start + i];
311 localstack_used += c;
315 for (i=0 ; i<f->numparms ; i++)
317 for (j=0 ; j<f->parm_size[i] ; j++)
319 ((int *)pr_globals)[o] = ((int *)pr_globals)[OFS_PARM0+i*3+j];
325 return f->first_statement - 1; // offset the s++
333 int PR_LeaveFunction (void)
338 Host_Error ("prog stack underflow");
340 // restore locals from the stack
341 c = pr_xfunction->locals;
342 localstack_used -= c;
343 if (localstack_used < 0)
344 PR_RunError ("PR_ExecuteProgram: locals stack underflow\n");
346 for (i=0 ; i < c ; i++)
347 ((int *)pr_globals)[pr_xfunction->parm_start + i] = localstack[localstack_used+i];
351 pr_xfunction = pr_stack[pr_depth].f;
352 return pr_stack[pr_depth].s;
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)
369 dfunction_t *f, *newf;
373 int profile, startprofile;
375 if (!fnum || fnum >= progs->numfunctions)
377 if (pr_global_struct->self)
378 ED_Print (PROG_TO_EDICT(pr_global_struct->self));
379 Host_Error ("PR_ExecuteProgram: NULL function");
382 f = &pr_functions[fnum];
386 // make a stack frame
387 exitdepth = pr_depth;
389 st = &pr_statements[PR_EnterFunction (f)];
390 startprofile = profile = 0;
392 if (pr_boundscheck.value)
397 if (++profile > 1000000) // LordHavoc: increased runaway loop limit 10x
399 pr_xstatement = st - pr_statements;
400 PR_RunError ("runaway loop error");
404 PR_PrintStatement (st);
409 OPC->_float = OPA->_float + OPB->_float;
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];
417 OPC->_float = OPA->_float - OPB->_float;
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];
425 OPC->_float = OPA->_float * OPB->_float;
428 OPC->_float = OPA->vector[0]*OPB->vector[0] + OPA->vector[1]*OPB->vector[1] + OPA->vector[2]*OPB->vector[2];
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];
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];
441 OPC->_float = OPA->_float / OPB->_float;
444 OPC->_float = (int)OPA->_float & (int)OPB->_float;
447 OPC->_float = (int)OPA->_float | (int)OPB->_float;
450 OPC->_float = OPA->_float >= OPB->_float;
453 OPC->_float = OPA->_float <= OPB->_float;
456 OPC->_float = OPA->_float > OPB->_float;
459 OPC->_float = OPA->_float < OPB->_float;
462 OPC->_float = OPA->_float && OPB->_float;
465 OPC->_float = OPA->_float || OPB->_float;
468 OPC->_float = !OPA->_float;
471 OPC->_float = !OPA->vector[0] && !OPA->vector[1] && !OPA->vector[2];
474 OPC->_float = !OPA->string || !pr_strings[OPA->string];
477 OPC->_float = !OPA->function;
480 OPC->_float = (PROG_TO_EDICT(OPA->edict) == sv.edicts);
483 OPC->_float = OPA->_float == OPB->_float;
486 OPC->_float = (OPA->vector[0] == OPB->vector[0]) && (OPA->vector[1] == OPB->vector[1]) && (OPA->vector[2] == OPB->vector[2]);
489 OPC->_float = !strcmp(pr_strings+OPA->string,pr_strings+OPB->string);
492 OPC->_float = OPA->_int == OPB->_int;
495 OPC->_float = OPA->function == OPB->function;
498 OPC->_float = OPA->_float != OPB->_float;
501 OPC->_float = (OPA->vector[0] != OPB->vector[0]) || (OPA->vector[1] != OPB->vector[1]) || (OPA->vector[2] != OPB->vector[2]);
504 OPC->_float = strcmp(pr_strings+OPA->string,pr_strings+OPB->string);
507 OPC->_float = OPA->_int != OPB->_int;
510 OPC->_float = OPA->function != OPB->function;
516 case OP_STORE_FLD: // integers
518 case OP_STORE_FNC: // pointers
519 OPB->_int = OPA->_int;
522 OPB->vector[0] = OPA->vector[0];
523 OPB->vector[1] = OPA->vector[1];
524 OPB->vector[2] = OPA->vector[2];
529 case OP_STOREP_FLD: // integers
531 case OP_STOREP_FNC: // pointers
532 if (OPB->_int < 0 || OPB->_int + 4 > pr_edictareasize)
534 pr_xstatement = st - pr_statements;
535 PR_RunError("Progs attempted to write to an out of bounds edict\n");
538 if (OPB->_int % pr_edict_size < ((byte *)&sv.edicts->v - (byte *)sv.edicts))
540 pr_xstatement = st - pr_statements;
541 PR_RunError("Progs attempted to write to an engine edict field\n");
544 ptr = (eval_t *)((byte *)sv.edicts + OPB->_int);
545 ptr->_int = OPA->_int;
548 if (OPB->_int < 0 || OPB->_int + 12 > pr_edictareasize)
550 pr_xstatement = st - pr_statements;
551 PR_RunError("Progs attempted to write to an out of bounds edict\n");
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];
561 if (OPA->edict < 0 || OPA->edict >= pr_edictareasize)
563 pr_xstatement = st - pr_statements;
564 PR_RunError("Progs attempted to address an out of bounds edict\n");
567 if (OPA->edict == 0 && sv.state == ss_active)
569 pr_xstatement = st - pr_statements;
570 PR_RunError ("assignment to world entity");
573 if (OPB->_int < 0 || OPB->_int >= progs->entityfields)
575 pr_xstatement = st - pr_statements;
576 PR_RunError("Progs attempted to address an invalid field in an edict\n");
579 ed = PROG_TO_EDICT(OPA->edict);
580 OPC->_int = (byte *)((int *)&ed->v + OPB->_int) - (byte *)sv.edicts;
588 if (OPA->edict < 0 || OPA->edict >= pr_edictareasize)
590 pr_xstatement = st - pr_statements;
591 PR_RunError("Progs attempted to read an out of bounds edict number\n");
594 if (OPB->_int < 0 || OPB->_int >= progs->entityfields)
596 pr_xstatement = st - pr_statements;
597 PR_RunError("Progs attempted to read an invalid field in an edict\n");
600 ed = PROG_TO_EDICT(OPA->edict);
601 OPC->_int = ((eval_t *)((int *)&ed->v + OPB->_int))->_int;
605 if (OPA->edict < 0 || OPA->edict >= pr_edictareasize)
607 pr_xstatement = st - pr_statements;
608 PR_RunError("Progs attempted to read an out of bounds edict number\n");
611 if (OPB->_int < 0 || OPB->_int + 2 >= progs->entityfields)
613 pr_xstatement = st - pr_statements;
614 PR_RunError("Progs attempted to read an invalid field in an edict\n");
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];
627 st += st->b - 1; // offset the s++
632 st += st->b - 1; // offset the s++
636 st += st->a - 1; // offset the s++
648 pr_xfunction->profile += profile - startprofile;
649 startprofile = profile;
650 pr_xstatement = st - pr_statements;
651 pr_argc = st->op - OP_CALL0;
653 PR_RunError ("NULL function");
655 newf = &pr_functions[OPA->function];
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");
666 st = &pr_statements[PR_EnterFunction (newf)];
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];
675 st = &pr_statements[PR_LeaveFunction ()];
676 if (pr_depth == exitdepth)
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;
688 pr_xstatement = st - pr_statements;
689 PR_RunError ("Bad opcode %i", st->op);
698 if (++profile > 1000000) // LordHavoc: increased runaway loop limit 10x
700 pr_xstatement = st - pr_statements;
701 PR_RunError ("runaway loop error");
705 PR_PrintStatement (st);
710 OPC->_float = OPA->_float + OPB->_float;
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];
718 OPC->_float = OPA->_float - OPB->_float;
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];
726 OPC->_float = OPA->_float * OPB->_float;
729 OPC->_float = OPA->vector[0]*OPB->vector[0] + OPA->vector[1]*OPB->vector[1] + OPA->vector[2]*OPB->vector[2];
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];
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];
742 OPC->_float = OPA->_float / OPB->_float;
745 OPC->_float = (int)OPA->_float & (int)OPB->_float;
748 OPC->_float = (int)OPA->_float | (int)OPB->_float;
751 OPC->_float = OPA->_float >= OPB->_float;
754 OPC->_float = OPA->_float <= OPB->_float;
757 OPC->_float = OPA->_float > OPB->_float;
760 OPC->_float = OPA->_float < OPB->_float;
763 OPC->_float = OPA->_float && OPB->_float;
766 OPC->_float = OPA->_float || OPB->_float;
769 OPC->_float = !OPA->_float;
772 OPC->_float = !OPA->vector[0] && !OPA->vector[1] && !OPA->vector[2];
775 OPC->_float = !OPA->string || !pr_strings[OPA->string];
778 OPC->_float = !OPA->function;
781 OPC->_float = (PROG_TO_EDICT(OPA->edict) == sv.edicts);
784 OPC->_float = OPA->_float == OPB->_float;
787 OPC->_float = (OPA->vector[0] == OPB->vector[0]) && (OPA->vector[1] == OPB->vector[1]) && (OPA->vector[2] == OPB->vector[2]);
790 OPC->_float = !strcmp(pr_strings+OPA->string,pr_strings+OPB->string);
793 OPC->_float = OPA->_int == OPB->_int;
796 OPC->_float = OPA->function == OPB->function;
799 OPC->_float = OPA->_float != OPB->_float;
802 OPC->_float = (OPA->vector[0] != OPB->vector[0]) || (OPA->vector[1] != OPB->vector[1]) || (OPA->vector[2] != OPB->vector[2]);
805 OPC->_float = strcmp(pr_strings+OPA->string,pr_strings+OPB->string);
808 OPC->_float = OPA->_int != OPB->_int;
811 OPC->_float = OPA->function != OPB->function;
817 case OP_STORE_FLD: // integers
819 case OP_STORE_FNC: // pointers
820 OPB->_int = OPA->_int;
823 OPB->vector[0] = OPA->vector[0];
824 OPB->vector[1] = OPA->vector[1];
825 OPB->vector[2] = OPA->vector[2];
830 case OP_STOREP_FLD: // integers
832 case OP_STOREP_FNC: // pointers
833 if (OPB->_int < 0 || OPB->_int + 4 > pr_edictareasize)
835 pr_xstatement = st - pr_statements;
836 PR_RunError("Progs attempted to write to an out of bounds edict\n");
839 if (OPB->_int % pr_edict_size < ((byte *)&sv.edicts->v - (byte *)sv.edicts))
841 pr_xstatement = st - pr_statements;
842 PR_RunError("Progs attempted to write to an engine edict field\n");
845 ptr = (eval_t *)((byte *)sv.edicts + OPB->_int);
846 ptr->_int = OPA->_int;
849 if (OPB->_int < 0 || OPB->_int + 12 > pr_edictareasize)
851 pr_xstatement = st - pr_statements;
852 PR_RunError("Progs attempted to write to an out of bounds edict\n");
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];
862 if (OPA->edict < 0 || OPA->edict >= pr_edictareasize)
864 pr_xstatement = st - pr_statements;
865 PR_RunError("Progs attempted to address an out of bounds edict\n");
868 if (OPA->edict == 0 && sv.state == ss_active)
870 pr_xstatement = st - pr_statements;
871 PR_RunError ("assignment to world entity");
874 if (OPB->_int < 0 || OPB->_int >= progs->entityfields)
876 pr_xstatement = st - pr_statements;
877 PR_RunError("Progs attempted to address an invalid field in an edict\n");
880 ed = PROG_TO_EDICT(OPA->edict);
881 OPC->_int = (byte *)((int *)&ed->v + OPB->_int) - (byte *)sv.edicts;
889 if (OPA->edict < 0 || OPA->edict >= pr_edictareasize)
891 pr_xstatement = st - pr_statements;
892 PR_RunError("Progs attempted to read an out of bounds edict number\n");
895 if (OPB->_int < 0 || OPB->_int >= progs->entityfields)
897 pr_xstatement = st - pr_statements;
898 PR_RunError("Progs attempted to read an invalid field in an edict\n");
901 ed = PROG_TO_EDICT(OPA->edict);
902 OPC->_int = ((eval_t *)((int *)&ed->v + OPB->_int))->_int;
906 if (OPA->edict < 0 || OPA->edict >= pr_edictareasize)
908 pr_xstatement = st - pr_statements;
909 PR_RunError("Progs attempted to read an out of bounds edict number\n");
912 if (OPB->_int < 0 || OPB->_int + 2 >= progs->entityfields)
914 pr_xstatement = st - pr_statements;
915 PR_RunError("Progs attempted to read an invalid field in an edict\n");
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];
928 st += st->b - 1; // offset the s++
933 st += st->b - 1; // offset the s++
937 st += st->a - 1; // offset the s++
949 pr_xfunction->profile += profile - startprofile;
950 startprofile = profile;
951 pr_xstatement = st - pr_statements;
952 pr_argc = st->op - OP_CALL0;
954 PR_RunError ("NULL function");
956 newf = &pr_functions[OPA->function];
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");
967 st = &pr_statements[PR_EnterFunction (newf)];
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];
976 st = &pr_statements[PR_LeaveFunction ()];
977 if (pr_depth == exitdepth)
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;
990 // LordHavoc: to be enabled when Progs version 7 (or whatever it will be numbered) is finalized
993 OPC->_int = OPA->_int + OPB->_int;
996 OPC->_int = OPA->_int + (int) OPB->_float;
999 OPC->_float = OPA->_float + (float) OPB->_int;
1002 OPC->_int = OPA->_int - OPB->_int;
1005 OPC->_int = OPA->_int - (int) OPB->_float;
1008 OPC->_float = OPA->_float - (float) OPB->_int;
1011 OPC->_int = OPA->_int * OPB->_int;
1014 OPC->_int = OPA->_int * (int) OPB->_float;
1017 OPC->_float = OPA->_float * (float) OPB->_int;
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];
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];
1033 OPC->_int = OPA->_int / OPB->_int;
1036 OPC->_int = OPA->_int / (int) OPB->_float;
1039 OPC->_float = OPA->_float / (float) OPB->_int;
1042 OPC->_float = OPA->_int;
1045 OPC->_int = OPA->_float;
1048 OPC->_int = OPA->_int & OPB->_int;
1051 OPC->_int = OPA->_int | OPB->_int;
1054 OPC->_int = OPA->_int & (int)OPB->_float;
1057 OPC->_int = OPA->_int | (int)OPB->_float;
1060 OPC->_float = (int)OPA->_float & OPB->_int;
1063 OPC->_float = (int)OPA->_float | OPB->_int;
1066 OPC->_float = OPA->_int >= OPB->_int;
1069 OPC->_float = OPA->_int <= OPB->_int;
1072 OPC->_float = OPA->_int > OPB->_int;
1075 OPC->_float = OPA->_int < OPB->_int;
1078 OPC->_float = OPA->_int && OPB->_int;
1081 OPC->_float = OPA->_int || OPB->_int;
1084 OPC->_float = (float)OPA->_int >= OPB->_float;
1087 OPC->_float = (float)OPA->_int <= OPB->_float;
1090 OPC->_float = (float)OPA->_int > OPB->_float;
1093 OPC->_float = (float)OPA->_int < OPB->_float;
1096 OPC->_float = (float)OPA->_int && OPB->_float;
1099 OPC->_float = (float)OPA->_int || OPB->_float;
1102 OPC->_float = OPA->_float >= (float)OPB->_int;
1105 OPC->_float = OPA->_float <= (float)OPB->_int;
1108 OPC->_float = OPA->_float > (float)OPB->_int;
1111 OPC->_float = OPA->_float < (float)OPB->_int;
1114 OPC->_float = OPA->_float && (float)OPB->_int;
1117 OPC->_float = OPA->_float || (float)OPB->_int;
1120 OPC->_float = !OPA->_int;
1123 OPC->_float = OPA->_int == OPB->_int;
1126 OPC->_float = (float)OPA->_int == OPB->_float;
1129 OPC->_float = OPA->_float == (float)OPB->_int;
1132 OPC->_float = OPA->_int != OPB->_int;
1135 OPC->_float = (float)OPA->_int != OPB->_float;
1138 OPC->_float = OPA->_float != (float)OPB->_int;
1141 OPB->_int = OPA->_int;
1144 if (OPB->_int < 0 || OPB->_int + 4 > pr_edictareasize)
1146 pr_xstatement = st - pr_statements;
1147 PR_RunError("Progs attempted to write to an out of bounds edict\n");
1150 if (OPB->_int % pr_edict_size < ((byte *)&sv.edicts->v - (byte *)sv.edicts))
1152 pr_xstatement = st - pr_statements;
1153 PR_RunError("Progs attempted to write to an engine edict field\n");
1156 ptr = (eval_t *)((byte *)sv.edicts + OPB->_int);
1157 ptr->_int = OPA->_int;
1160 if (OPA->edict < 0 || OPA->edict >= pr_edictareasize)
1162 pr_xstatement = st - pr_statements;
1163 PR_RunError("Progs attempted to read an out of bounds edict number\n");
1166 if (OPB->_int < 0 || OPB->_int >= progs->entityfields)
1168 pr_xstatement = st - pr_statements;
1169 PR_RunError("Progs attempted to read an invalid field in an edict\n");
1172 ed = PROG_TO_EDICT(OPA->edict);
1173 OPC->_int = ((eval_t *)((int *)&ed->v + OPB->_int))->_int;
1178 case OP_GSTOREP_ENT:
1179 case OP_GSTOREP_FLD: // integers
1181 case OP_GSTOREP_FNC: // pointers
1182 if (OPB->_int < 0 || OPB->_int >= pr_globaldefs)
1184 pr_xstatement = st - pr_statements;
1185 PR_RunError("Progs attempted to write to an invalid indexed global\n");
1188 pr_globals[OPB->_int] = OPA->_float;
1191 if (OPB->_int < 0 || OPB->_int + 2 >= pr_globaldefs)
1193 pr_xstatement = st - pr_statements;
1194 PR_RunError("Progs attempted to write to an invalid indexed global\n");
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];
1203 i = OPA->_int + (int) OPB->_float;
1204 if (i < 0 || i >= pr_globaldefs)
1206 pr_xstatement = st - pr_statements;
1207 PR_RunError("Progs attempted to address an out of bounds global\n");
1210 OPC->_float = pr_globals[i];
1219 if (OPA->_int < 0 || OPA->_int >= pr_globaldefs)
1221 pr_xstatement = st - pr_statements;
1222 PR_RunError("Progs attempted to read an invalid indexed global\n");
1225 OPC->_float = pr_globals[OPA->_int];
1229 if (OPA->_int < 0 || OPA->_int + 2 >= pr_globaldefs)
1231 pr_xstatement = st - pr_statements;
1232 PR_RunError("Progs attempted to read an invalid indexed global\n");
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];
1241 if (OPA->_int < 0 || OPA->_int >= st->b)
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);
1250 //==================
1253 pr_xstatement = st - pr_statements;
1254 PR_RunError ("Bad opcode %i", st->op);