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