added in_pitch_min and in_pitch_max cvars to limit pitch (default: -90 to +90)
[divverent/darkplaces.git] / pr_execprogram.h
1                 while (1)
2                 {
3                         st++;
4                         if (++profile > 1000000) // LordHavoc: increased runaway loop limit 10x
5                         {
6                                 pr_xstatement = st - pr_statements;
7                                 PR_RunError ("runaway loop error");
8                         }
9
10 #if PRTRACE
11                         PR_PrintStatement (st);
12 #endif
13
14                         switch (st->op)
15                         {
16                         case OP_ADD_F:
17                                 OPC->_float = OPA->_float + OPB->_float;
18                                 break;
19                         case OP_ADD_V:
20                                 OPC->vector[0] = OPA->vector[0] + OPB->vector[0];
21                                 OPC->vector[1] = OPA->vector[1] + OPB->vector[1];
22                                 OPC->vector[2] = OPA->vector[2] + OPB->vector[2];
23                                 break;
24                         case OP_SUB_F:
25                                 OPC->_float = OPA->_float - OPB->_float;
26                                 break;
27                         case OP_SUB_V:
28                                 OPC->vector[0] = OPA->vector[0] - OPB->vector[0];
29                                 OPC->vector[1] = OPA->vector[1] - OPB->vector[1];
30                                 OPC->vector[2] = OPA->vector[2] - OPB->vector[2];
31                                 break;
32                         case OP_MUL_F:
33                                 OPC->_float = OPA->_float * OPB->_float;
34                                 break;
35                         case OP_MUL_V:
36                                 OPC->_float = OPA->vector[0]*OPB->vector[0] + OPA->vector[1]*OPB->vector[1] + OPA->vector[2]*OPB->vector[2];
37                                 break;
38                         case OP_MUL_FV:
39                                 OPC->vector[0] = OPA->_float * OPB->vector[0];
40                                 OPC->vector[1] = OPA->_float * OPB->vector[1];
41                                 OPC->vector[2] = OPA->_float * OPB->vector[2];
42                                 break;
43                         case OP_MUL_VF:
44                                 OPC->vector[0] = OPB->_float * OPA->vector[0];
45                                 OPC->vector[1] = OPB->_float * OPA->vector[1];
46                                 OPC->vector[2] = OPB->_float * OPA->vector[2];
47                                 break;
48                         case OP_DIV_F:
49                                 OPC->_float = OPA->_float / OPB->_float;
50                                 break;
51                         case OP_BITAND:
52                                 OPC->_float = (int)OPA->_float & (int)OPB->_float;
53                                 break;
54                         case OP_BITOR:
55                                 OPC->_float = (int)OPA->_float | (int)OPB->_float;
56                                 break;
57                         case OP_GE:
58                                 OPC->_float = OPA->_float >= OPB->_float;
59                                 break;
60                         case OP_LE:
61                                 OPC->_float = OPA->_float <= OPB->_float;
62                                 break;
63                         case OP_GT:
64                                 OPC->_float = OPA->_float > OPB->_float;
65                                 break;
66                         case OP_LT:
67                                 OPC->_float = OPA->_float < OPB->_float;
68                                 break;
69                         case OP_AND:
70                                 OPC->_float = OPA->_float && OPB->_float;
71                                 break;
72                         case OP_OR:
73                                 OPC->_float = OPA->_float || OPB->_float;
74                                 break;
75                         case OP_NOT_F:
76                                 OPC->_float = !OPA->_float;
77                                 break;
78                         case OP_NOT_V:
79                                 OPC->_float = !OPA->vector[0] && !OPA->vector[1] && !OPA->vector[2];
80                                 break;
81                         case OP_NOT_S:
82                                 OPC->_float = !OPA->string || !pr_strings[OPA->string];
83                                 break;
84                         case OP_NOT_FNC:
85                                 OPC->_float = !OPA->function;
86                                 break;
87                         case OP_NOT_ENT:
88                                 OPC->_float = (PROG_TO_EDICT(OPA->edict) == sv.edicts);
89                                 break;
90                         case OP_EQ_F:
91                                 OPC->_float = OPA->_float == OPB->_float;
92                                 break;
93                         case OP_EQ_V:
94                                 OPC->_float = (OPA->vector[0] == OPB->vector[0]) && (OPA->vector[1] == OPB->vector[1]) && (OPA->vector[2] == OPB->vector[2]);
95                                 break;
96                         case OP_EQ_S:
97                                 OPC->_float = !strcmp(pr_strings+OPA->string,pr_strings+OPB->string);
98                                 break;
99                         case OP_EQ_E:
100                                 OPC->_float = OPA->_int == OPB->_int;
101                                 break;
102                         case OP_EQ_FNC:
103                                 OPC->_float = OPA->function == OPB->function;
104                                 break;
105                         case OP_NE_F:
106                                 OPC->_float = OPA->_float != OPB->_float;
107                                 break;
108                         case OP_NE_V:
109                                 OPC->_float = (OPA->vector[0] != OPB->vector[0]) || (OPA->vector[1] != OPB->vector[1]) || (OPA->vector[2] != OPB->vector[2]);
110                                 break;
111                         case OP_NE_S:
112                                 OPC->_float = strcmp(pr_strings+OPA->string,pr_strings+OPB->string);
113                                 break;
114                         case OP_NE_E:
115                                 OPC->_float = OPA->_int != OPB->_int;
116                                 break;
117                         case OP_NE_FNC:
118                                 OPC->_float = OPA->function != OPB->function;
119                                 break;
120
121                 //==================
122                         case OP_STORE_F:
123                         case OP_STORE_ENT:
124                         case OP_STORE_FLD:              // integers
125                         case OP_STORE_S:
126                         case OP_STORE_FNC:              // pointers
127                                 OPB->_int = OPA->_int;
128                                 break;
129                         case OP_STORE_V:
130                                 OPB->vector[0] = OPA->vector[0];
131                                 OPB->vector[1] = OPA->vector[1];
132                                 OPB->vector[2] = OPA->vector[2];
133                                 break;
134
135                         case OP_STOREP_F:
136                         case OP_STOREP_ENT:
137                         case OP_STOREP_FLD:             // integers
138                         case OP_STOREP_S:
139                         case OP_STOREP_FNC:             // pointers
140 #if PRBOUNDSCHECK
141                                 if (OPB->_int < 0 || OPB->_int + 4 > pr_edictareasize)
142                                 {
143                                         pr_xstatement = st - pr_statements;
144                                         PR_RunError("Progs attempted to write to an out of bounds edict\n");
145                                         return;
146                                 }
147                                 if (OPB->_int % pr_edict_size < ((byte *)&sv.edicts->v - (byte *)sv.edicts))
148                                 {
149                                         pr_xstatement = st - pr_statements;
150                                         PR_RunError("Progs attempted to write to an engine edict field\n");
151                                         return;
152                                 }
153 #endif
154                                 ptr = (eval_t *)((byte *)sv.edicts + OPB->_int);
155                                 ptr->_int = OPA->_int;
156                                 break;
157                         case OP_STOREP_V:
158 #if PRBOUNDSCHECK
159                                 if (OPB->_int < 0 || OPB->_int + 12 > pr_edictareasize)
160                                 {
161                                         pr_xstatement = st - pr_statements;
162                                         PR_RunError("Progs attempted to write to an out of bounds edict\n");
163                                         return;
164                                 }
165 #endif
166                                 ptr = (eval_t *)((byte *)sv.edicts + OPB->_int);
167                                 ptr->vector[0] = OPA->vector[0];
168                                 ptr->vector[1] = OPA->vector[1];
169                                 ptr->vector[2] = OPA->vector[2];
170                                 break;
171
172                         case OP_ADDRESS:
173 #if PRBOUNDSCHECK
174                                 if (OPA->edict <= 0)
175                                 {
176                                         if (OPA->edict == 0 && sv.state == ss_active)
177                                         {
178                                                 pr_xstatement = st - pr_statements;
179                                                 PR_RunError ("assignment to world entity");
180                                                 return;
181                                         }
182                                         else
183                                         {
184                                                 pr_xstatement = st - pr_statements;
185                                                 PR_RunError("Progs attempted to address an out of bounds edict\n");
186                                                 return;
187                                         }
188                                 }
189                                 else if (OPA->edict >= pr_edictareasize)
190                                 {
191                                         pr_xstatement = st - pr_statements;
192                                         PR_RunError("Progs attempted to address an out of bounds edict\n");
193                                         return;
194                                 }
195                                 if (OPB->_int < 0 || OPB->_int >= progs->entityfields)
196                                 {
197                                         pr_xstatement = st - pr_statements;
198                                         PR_RunError("Progs attempted to address an invalid field in an edict\n");
199                                         return;
200                                 }
201 #else
202                                 if (OPA->edict == 0 && sv.state == ss_active)
203                                 {
204                                         pr_xstatement = st - pr_statements;
205                                         PR_RunError ("assignment to world entity");
206                                         return;
207                                 }
208 #endif
209                                 ed = PROG_TO_EDICT(OPA->edict);
210                                 OPC->_int = (byte *)((int *)&ed->v + OPB->_int) - (byte *)sv.edicts;
211                                 break;
212
213                         case OP_LOAD_F:
214                         case OP_LOAD_FLD:
215                         case OP_LOAD_ENT:
216                         case OP_LOAD_S:
217                         case OP_LOAD_FNC:
218 #if PRBOUNDSCHECK
219                                 if (OPA->edict < 0 || OPA->edict >= pr_edictareasize)
220                                 {
221                                         pr_xstatement = st - pr_statements;
222                                         PR_RunError("Progs attempted to read an out of bounds edict number\n");
223                                         return;
224                                 }
225                                 if (OPB->_int < 0 || OPB->_int >= progs->entityfields)
226                                 {
227                                         pr_xstatement = st - pr_statements;
228                                         PR_RunError("Progs attempted to read an invalid field in an edict\n");
229                                         return;
230                                 }
231 #endif
232                                 ed = PROG_TO_EDICT(OPA->edict);
233                                 OPC->_int = ((eval_t *)((int *)&ed->v + OPB->_int))->_int;
234                                 break;
235
236                         case OP_LOAD_V:
237 #if PRBOUNDSCHECK
238                                 if (OPA->edict < 0 || OPA->edict >= pr_edictareasize)
239                                 {
240                                         pr_xstatement = st - pr_statements;
241                                         PR_RunError("Progs attempted to read an out of bounds edict number\n");
242                                         return;
243                                 }
244                                 if (OPB->_int < 0 || OPB->_int + 2 >= progs->entityfields)
245                                 {
246                                         pr_xstatement = st - pr_statements;
247                                         PR_RunError("Progs attempted to read an invalid field in an edict\n");
248                                         return;
249                                 }
250 #endif
251                                 ed = PROG_TO_EDICT(OPA->edict);
252                                 OPC->vector[0] = ((eval_t *)((int *)&ed->v + OPB->_int))->vector[0];
253                                 OPC->vector[1] = ((eval_t *)((int *)&ed->v + OPB->_int))->vector[1];
254                                 OPC->vector[2] = ((eval_t *)((int *)&ed->v + OPB->_int))->vector[2];
255                                 break;
256
257                 //==================
258
259                         case OP_IFNOT:
260                                 if (!OPA->_int)
261                                         st += st->b - 1;        // offset the s++
262                                 break;
263
264                         case OP_IF:
265                                 if (OPA->_int)
266                                         st += st->b - 1;        // offset the s++
267                                 break;
268
269                         case OP_GOTO:
270                                 st += st->a - 1;        // offset the s++
271                                 break;
272
273                         case OP_CALL0:
274                         case OP_CALL1:
275                         case OP_CALL2:
276                         case OP_CALL3:
277                         case OP_CALL4:
278                         case OP_CALL5:
279                         case OP_CALL6:
280                         case OP_CALL7:
281                         case OP_CALL8:
282                                 pr_xfunction->profile += profile - startprofile;
283                                 startprofile = profile;
284                                 pr_xstatement = st - pr_statements;
285                                 pr_argc = st->op - OP_CALL0;
286                                 if (!OPA->function)
287                                         PR_RunError ("NULL function");
288
289                                 newf = &pr_functions[OPA->function];
290
291                                 if (newf->first_statement < 0)
292                                 {
293                                         // negative statements are built in functions
294                                         if ((-newf->first_statement) >= pr_numbuiltins)
295                                                 PR_RunError ("Bad builtin call number");
296                                         pr_builtins[-newf->first_statement] ();
297                                 }
298                                 else
299                                         st = pr_statements + PR_EnterFunction(newf);
300                                 break;
301
302                         case OP_DONE:
303                         case OP_RETURN:
304                                 pr_globals[OFS_RETURN] = pr_globals[(unsigned short) st->a];
305                                 pr_globals[OFS_RETURN+1] = pr_globals[(unsigned short) st->a+1];
306                                 pr_globals[OFS_RETURN+2] = pr_globals[(unsigned short) st->a+2];
307
308                                 st = pr_statements + PR_LeaveFunction();
309                                 if (pr_depth <= exitdepth)
310                                         return;         // all done
311                                 if (pr_trace != cachedpr_trace)
312                                         goto chooseexecprogram;
313                                 break;
314
315                         case OP_STATE:
316                                 ed = PROG_TO_EDICT(pr_global_struct->self);
317                                 ed->v.nextthink = pr_global_struct->time + 0.1;
318                                 ed->v.frame = OPA->_float;
319                                 ed->v.think = OPB->function;
320                                 break;
321
322 // LordHavoc: to be enabled when Progs version 7 (or whatever it will be numbered) is finalized
323 /*
324                         case OP_ADD_I:
325                                 OPC->_int = OPA->_int + OPB->_int;
326                                 break;
327                         case OP_ADD_IF:
328                                 OPC->_int = OPA->_int + (int) OPB->_float;
329                                 break;
330                         case OP_ADD_FI:
331                                 OPC->_float = OPA->_float + (float) OPB->_int;
332                                 break;
333                         case OP_SUB_I:
334                                 OPC->_int = OPA->_int - OPB->_int;
335                                 break;
336                         case OP_SUB_IF:
337                                 OPC->_int = OPA->_int - (int) OPB->_float;
338                                 break;
339                         case OP_SUB_FI:
340                                 OPC->_float = OPA->_float - (float) OPB->_int;
341                                 break;
342                         case OP_MUL_I:
343                                 OPC->_int = OPA->_int * OPB->_int;
344                                 break;
345                         case OP_MUL_IF:
346                                 OPC->_int = OPA->_int * (int) OPB->_float;
347                                 break;
348                         case OP_MUL_FI:
349                                 OPC->_float = OPA->_float * (float) OPB->_int;
350                                 break;
351                         case OP_MUL_VI:
352                                 OPC->vector[0] = (float) OPB->_int * OPA->vector[0];
353                                 OPC->vector[1] = (float) OPB->_int * OPA->vector[1];
354                                 OPC->vector[2] = (float) OPB->_int * OPA->vector[2];
355                                 break;
356                         case OP_DIV_VF:
357                                 {
358                                         float temp = 1.0f / OPB->_float;
359                                         OPC->vector[0] = temp * OPA->vector[0];
360                                         OPC->vector[1] = temp * OPA->vector[1];
361                                         OPC->vector[2] = temp * OPA->vector[2];
362                                 }
363                                 break;
364                         case OP_DIV_I:
365                                 OPC->_int = OPA->_int / OPB->_int;
366                                 break;
367                         case OP_DIV_IF:
368                                 OPC->_int = OPA->_int / (int) OPB->_float;
369                                 break;
370                         case OP_DIV_FI:
371                                 OPC->_float = OPA->_float / (float) OPB->_int;
372                                 break;
373                         case OP_CONV_IF:
374                                 OPC->_float = OPA->_int;
375                                 break;
376                         case OP_CONV_FI:
377                                 OPC->_int = OPA->_float;
378                                 break;
379                         case OP_BITAND_I:
380                                 OPC->_int = OPA->_int & OPB->_int;
381                                 break;
382                         case OP_BITOR_I:
383                                 OPC->_int = OPA->_int | OPB->_int;
384                                 break;
385                         case OP_BITAND_IF:
386                                 OPC->_int = OPA->_int & (int)OPB->_float;
387                                 break;
388                         case OP_BITOR_IF:
389                                 OPC->_int = OPA->_int | (int)OPB->_float;
390                                 break;
391                         case OP_BITAND_FI:
392                                 OPC->_float = (int)OPA->_float & OPB->_int;
393                                 break;
394                         case OP_BITOR_FI:
395                                 OPC->_float = (int)OPA->_float | OPB->_int;
396                                 break;
397                         case OP_GE_I:
398                                 OPC->_float = OPA->_int >= OPB->_int;
399                                 break;
400                         case OP_LE_I:
401                                 OPC->_float = OPA->_int <= OPB->_int;
402                                 break;
403                         case OP_GT_I:
404                                 OPC->_float = OPA->_int > OPB->_int;
405                                 break;
406                         case OP_LT_I:
407                                 OPC->_float = OPA->_int < OPB->_int;
408                                 break;
409                         case OP_AND_I:
410                                 OPC->_float = OPA->_int && OPB->_int;
411                                 break;
412                         case OP_OR_I:
413                                 OPC->_float = OPA->_int || OPB->_int;
414                                 break;
415                         case OP_GE_IF:
416                                 OPC->_float = (float)OPA->_int >= OPB->_float;
417                                 break;
418                         case OP_LE_IF:
419                                 OPC->_float = (float)OPA->_int <= OPB->_float;
420                                 break;
421                         case OP_GT_IF:
422                                 OPC->_float = (float)OPA->_int > OPB->_float;
423                                 break;
424                         case OP_LT_IF:
425                                 OPC->_float = (float)OPA->_int < OPB->_float;
426                                 break;
427                         case OP_AND_IF:
428                                 OPC->_float = (float)OPA->_int && OPB->_float;
429                                 break;
430                         case OP_OR_IF:
431                                 OPC->_float = (float)OPA->_int || OPB->_float;
432                                 break;
433                         case OP_GE_FI:
434                                 OPC->_float = OPA->_float >= (float)OPB->_int;
435                                 break;
436                         case OP_LE_FI:
437                                 OPC->_float = OPA->_float <= (float)OPB->_int;
438                                 break;
439                         case OP_GT_FI:
440                                 OPC->_float = OPA->_float > (float)OPB->_int;
441                                 break;
442                         case OP_LT_FI:
443                                 OPC->_float = OPA->_float < (float)OPB->_int;
444                                 break;
445                         case OP_AND_FI:
446                                 OPC->_float = OPA->_float && (float)OPB->_int;
447                                 break;
448                         case OP_OR_FI:
449                                 OPC->_float = OPA->_float || (float)OPB->_int;
450                                 break;
451                         case OP_NOT_I:
452                                 OPC->_float = !OPA->_int;
453                                 break;
454                         case OP_EQ_I:
455                                 OPC->_float = OPA->_int == OPB->_int;
456                                 break;
457                         case OP_EQ_IF:
458                                 OPC->_float = (float)OPA->_int == OPB->_float;
459                                 break;
460                         case OP_EQ_FI:
461                                 OPC->_float = OPA->_float == (float)OPB->_int;
462                                 break;
463                         case OP_NE_I:
464                                 OPC->_float = OPA->_int != OPB->_int;
465                                 break;
466                         case OP_NE_IF:
467                                 OPC->_float = (float)OPA->_int != OPB->_float;
468                                 break;
469                         case OP_NE_FI:
470                                 OPC->_float = OPA->_float != (float)OPB->_int;
471                                 break;
472                         case OP_STORE_I:
473                                 OPB->_int = OPA->_int;
474                                 break;
475                         case OP_STOREP_I:
476 #if PRBOUNDSCHECK
477                                 if (OPB->_int < 0 || OPB->_int + 4 > pr_edictareasize)
478                                 {
479                                         pr_xstatement = st - pr_statements;
480                                         PR_RunError("Progs attempted to write to an out of bounds edict\n");
481                                         return;
482                                 }
483                                 if (OPB->_int % pr_edict_size < ((byte *)&sv.edicts->v - (byte *)sv.edicts))
484                                 {
485                                         pr_xstatement = st - pr_statements;
486                                         PR_RunError("Progs attempted to write to an engine edict field\n");
487                                         return;
488                                 }
489 #endif
490                                 ptr = (eval_t *)((byte *)sv.edicts + OPB->_int);
491                                 ptr->_int = OPA->_int;
492                                 break;
493                         case OP_LOAD_I:
494 #if PRBOUNDSCHECK
495                                 if (OPA->edict < 0 || OPA->edict >= pr_edictareasize)
496                                 {
497                                         pr_xstatement = st - pr_statements;
498                                         PR_RunError("Progs attempted to read an out of bounds edict number\n");
499                                         return;
500                                 }
501                                 if (OPB->_int < 0 || OPB->_int >= progs->entityfields)
502                                 {
503                                         pr_xstatement = st - pr_statements;
504                                         PR_RunError("Progs attempted to read an invalid field in an edict\n");
505                                         return;
506                                 }
507 #endif
508                                 ed = PROG_TO_EDICT(OPA->edict);
509                                 OPC->_int = ((eval_t *)((int *)&ed->v + OPB->_int))->_int;
510                                 break;
511
512                         case OP_GSTOREP_I:
513                         case OP_GSTOREP_F:
514                         case OP_GSTOREP_ENT:
515                         case OP_GSTOREP_FLD:            // integers
516                         case OP_GSTOREP_S:
517                         case OP_GSTOREP_FNC:            // pointers
518 #if PRBOUNDSCHECK
519                                 if (OPB->_int < 0 || OPB->_int >= pr_globaldefs)
520                                 {
521                                         pr_xstatement = st - pr_statements;
522                                         PR_RunError("Progs attempted to write to an invalid indexed global\n");
523                                         return;
524                                 }
525 #endif
526                                 pr_globals[OPB->_int] = OPA->_float;
527                                 break;
528                         case OP_GSTOREP_V:
529 #if PRBOUNDSCHECK
530                                 if (OPB->_int < 0 || OPB->_int + 2 >= pr_globaldefs)
531                                 {
532                                         pr_xstatement = st - pr_statements;
533                                         PR_RunError("Progs attempted to write to an invalid indexed global\n");
534                                         return;
535                                 }
536 #endif
537                                 pr_globals[OPB->_int  ] = OPA->vector[0];
538                                 pr_globals[OPB->_int+1] = OPA->vector[1];
539                                 pr_globals[OPB->_int+2] = OPA->vector[2];
540                                 break;
541
542                         case OP_GADDRESS:
543                                 i = OPA->_int + (int) OPB->_float;
544 #if PRBOUNDSCHECK
545                                 if (i < 0 || i >= pr_globaldefs)
546                                 {
547                                         pr_xstatement = st - pr_statements;
548                                         PR_RunError("Progs attempted to address an out of bounds global\n");
549                                         return;
550                                 }
551 #endif
552                                 OPC->_float = pr_globals[i];
553                                 break;
554
555                         case OP_GLOAD_I:
556                         case OP_GLOAD_F:
557                         case OP_GLOAD_FLD:
558                         case OP_GLOAD_ENT:
559                         case OP_GLOAD_S:
560                         case OP_GLOAD_FNC:
561 #if PRBOUNDSCHECK
562                                 if (OPA->_int < 0 || OPA->_int >= pr_globaldefs)
563                                 {
564                                         pr_xstatement = st - pr_statements;
565                                         PR_RunError("Progs attempted to read an invalid indexed global\n");
566                                         return;
567                                 }
568 #endif
569                                 OPC->_float = pr_globals[OPA->_int];
570                                 break;
571
572                         case OP_GLOAD_V:
573 #if PRBOUNDSCHECK
574                                 if (OPA->_int < 0 || OPA->_int + 2 >= pr_globaldefs)
575                                 {
576                                         pr_xstatement = st - pr_statements;
577                                         PR_RunError("Progs attempted to read an invalid indexed global\n");
578                                         return;
579                                 }
580 #endif
581                                 OPC->vector[0] = pr_globals[OPA->_int  ];
582                                 OPC->vector[1] = pr_globals[OPA->_int+1];
583                                 OPC->vector[2] = pr_globals[OPA->_int+2];
584                                 break;
585
586                         case OP_BOUNDCHECK:
587                                 if (OPA->_int < 0 || OPA->_int >= st->b)
588                                 {
589                                         pr_xstatement = st - pr_statements;
590                                         PR_RunError("Progs boundcheck failed at line number %d, value is < 0 or >= %d\n", st->b, st->c);
591                                         return;
592                                 }
593                                 break;
594
595 */
596
597                         default:
598                                 pr_xstatement = st - pr_statements;
599                                 PR_RunError ("Bad opcode %i", st->op);
600                         }
601                 }