]> de.git.xonotic.org Git - voretournament/voretournament.git/blob - misc/source/fteqcc-src/execloop.h
08d0ce9fd55a4bde5e18ccf80efbf902856bb080
[voretournament/voretournament.git] / misc / source / fteqcc-src / execloop.h
1 //qc execution code.
2 //we have two conditions.
3 //one allows us to debug and trace through our code, the other doesn't.
4
5 //hopefully, the compiler will do a great job at optimising this code for us, where required.
6 //if it dosn't, then bum.
7
8 //the general overhead should be reduced significantly, and I would be supprised if it did run slower.
9
10 //run away loops are checked for ONLY on gotos and function calls. This might give a poorer check, but it will run faster overall.
11
12 //Appears to work fine.
13
14 #if INTSIZE == 16
15 #define cont cont16
16 #define reeval reeval16
17 #define st st16
18 #define pr_statements pr_statements16
19 #define fakeop fakeop16
20 #define dstatement_t dstatement16_t
21 #define sofs signed short
22 #define uofs unsigned short
23 #elif INTSIZE == 32
24 #define cont cont32
25 #define reeval reeval32
26 #define st st32
27 #define pr_statements pr_statements32
28 #define fakeop fakeop32
29 #define dstatement_t dstatement32_t
30 #define sofs signed int
31 #define uofs unsigned int
32 #elif INTSIZE == 24
33 #error INTSIZE should be set to 32.
34 #else
35 #error Bad cont size
36 #endif
37
38 #define ENGINEPOINTER(p) ((char*)(p) - progfuncs->stringtable)
39 #define QCPOINTER(p) (eval_t *)(p->_int+progfuncs->stringtable)
40 #define QCPOINTERM(p) (eval_t *)((p)+progfuncs->stringtable)
41
42 //rely upon just st
43 {
44 #ifdef DEBUGABLE
45 cont:   //last statement may have been a breakpoint             
46         s = st-pr_statements;
47         s+=1;
48         s=ShowStep(progfuncs, s);
49         st = pr_statements + s;
50
51 reeval:
52         switch (st->op & ~0x8000)
53 #else
54         st++;
55         switch (st->op)
56 #endif
57         {
58         case OP_ADD_F:
59                 OPC->_float = OPA->_float + OPB->_float;
60                 break;
61         case OP_ADD_V:
62                 OPC->_vector[0] = OPA->_vector[0] + OPB->_vector[0];
63                 OPC->_vector[1] = OPA->_vector[1] + OPB->_vector[1];
64                 OPC->_vector[2] = OPA->_vector[2] + OPB->_vector[2];
65                 break;
66
67         case OP_SUB_F:
68                 OPC->_float = OPA->_float - OPB->_float;
69                 break;
70         case OP_SUB_V:
71                 OPC->_vector[0] = OPA->_vector[0] - OPB->_vector[0];
72                 OPC->_vector[1] = OPA->_vector[1] - OPB->_vector[1];
73                 OPC->_vector[2] = OPA->_vector[2] - OPB->_vector[2];
74                 break;
75
76         case OP_MUL_F:
77                 OPC->_float = OPA->_float * OPB->_float;
78                 break;
79         case OP_MUL_V:
80                 OPC->_float = OPA->_vector[0]*OPB->_vector[0]
81                                 + OPA->_vector[1]*OPB->_vector[1]
82                                 + OPA->_vector[2]*OPB->_vector[2];
83                 break;
84         case OP_MUL_FV:
85                 OPC->_vector[0] = OPA->_float * OPB->_vector[0];
86                 OPC->_vector[1] = OPA->_float * OPB->_vector[1];
87                 OPC->_vector[2] = OPA->_float * OPB->_vector[2];
88                 break;
89         case OP_MUL_VF:
90                 OPC->_vector[0] = OPB->_float * OPA->_vector[0];
91                 OPC->_vector[1] = OPB->_float * OPA->_vector[1];
92                 OPC->_vector[2] = OPB->_float * OPA->_vector[2];
93                 break;
94
95         case OP_DIV_F:
96                 OPC->_float = OPA->_float / OPB->_float;
97                 break;
98         case OP_DIV_VF:
99                 OPC->_vector[0] = OPB->_float / OPA->_vector[0];
100                 OPC->_vector[1] = OPB->_float / OPA->_vector[1];
101                 OPC->_vector[2] = OPB->_float / OPA->_vector[2];
102                 break;
103
104         case OP_BITAND_F:
105                 OPC->_float = (float)((int)OPA->_float & (int)OPB->_float);
106                 break;
107
108         case OP_BITOR_F:
109                 OPC->_float = (float)((int)OPA->_float | (int)OPB->_float);
110                 break;
111
112
113         case OP_GE_F:
114                 OPC->_float = (float)(OPA->_float >= OPB->_float);
115                 break;
116         case OP_GE_I:
117                 OPC->_int = (int)(OPA->_int >= OPB->_int);
118                 break;
119         case OP_GE_IF:
120                 OPC->_float = (float)(OPA->_int >= OPB->_float);
121                 break;
122         case OP_GE_FI:
123                 OPC->_float = (float)(OPA->_float >= OPB->_int);
124                 break;
125
126         case OP_LE_F:
127                 OPC->_float = (float)(OPA->_float <= OPB->_float);
128                 break;
129         case OP_LE_I:
130                 OPC->_int = (int)(OPA->_int <= OPB->_int);
131                 break;
132         case OP_LE_IF:
133                 OPC->_float = (float)(OPA->_int <= OPB->_float);
134                 break;
135         case OP_LE_FI:
136                 OPC->_float = (float)(OPA->_float <= OPB->_int);
137                 break;
138
139         case OP_GT_F:
140                 OPC->_float = (float)(OPA->_float > OPB->_float);
141                 break;
142         case OP_GT_I:
143                 OPC->_int = (int)(OPA->_int > OPB->_int);
144                 break;
145         case OP_GT_IF:
146                 OPC->_float = (float)(OPA->_int > OPB->_float);
147                 break;
148         case OP_GT_FI:
149                 OPC->_float = (float)(OPA->_float > OPB->_int);
150                 break;
151
152         case OP_LT_F:
153                 OPC->_float = (float)(OPA->_float < OPB->_float);
154                 break;
155         case OP_LT_I:
156                 OPC->_int = (int)(OPA->_int < OPB->_int);
157                 break;
158         case OP_LT_IF:
159                 OPC->_float = (float)(OPA->_int < OPB->_float);
160                 break;
161         case OP_LT_FI:
162                 OPC->_float = (float)(OPA->_float < OPB->_int);
163                 break;
164
165         case OP_AND_F:
166                 OPC->_float = (float)(OPA->_float && OPB->_float);
167                 break;
168         case OP_OR_F:
169                 OPC->_float = (float)(OPA->_float || OPB->_float);
170                 break;
171
172         case OP_NOT_F:
173                 OPC->_float = (float)(!OPA->_float);
174                 break;
175         case OP_NOT_V:
176                 OPC->_float = (float)(!OPA->_vector[0] && !OPA->_vector[1] && !OPA->_vector[2]);
177                 break;
178         case OP_NOT_S:
179                 OPC->_float = (float)(!(OPA->string) || !*PR_StringToNative(progfuncs, OPA->string));
180                 break;
181         case OP_NOT_FNC:
182                 OPC->_float = (float)(!(OPA->function & ~0xff000000));
183                 break;
184         case OP_NOT_ENT:
185                 OPC->_float = (float)(PROG_TO_EDICT(progfuncs, OPA->edict) == (edictrun_t *)sv_edicts);
186                 break;
187
188         case OP_EQ_F:
189                 OPC->_float = (float)(OPA->_float == OPB->_float);
190                 break;
191         case OP_EQ_IF:
192                 OPC->_float = (float)(OPA->_int == OPB->_float);
193                 break;
194         case OP_EQ_FI:
195                 OPC->_float = (float)(OPA->_float == OPB->_int);
196                 break;
197
198
199         case OP_EQ_V:
200                 OPC->_float = (float)((OPA->_vector[0] == OPB->_vector[0]) &&
201                                         (OPA->_vector[1] == OPB->_vector[1]) &&
202                                         (OPA->_vector[2] == OPB->_vector[2]));
203                 break;
204         case OP_EQ_S:
205                 if (OPA->string==OPB->string)
206                         OPC->_float = true;
207                 else if (!OPA->string)
208                 {
209                         if (!OPB->string || !*PR_StringToNative(progfuncs, OPB->string))
210                                 OPC->_float = true;
211                         else
212                                 OPC->_float = false;
213                 }
214                 else if (!OPB->string)
215                 {
216                         if (!OPA->string || !*PR_StringToNative(progfuncs, OPA->string))
217                                 OPC->_float = true;
218                         else
219                                 OPC->_float = false;
220                 }
221                 else
222                         OPC->_float = (float)(!strcmp(PR_StringToNative(progfuncs, OPA->string),PR_StringToNative(progfuncs, OPB->string)));
223                 break;
224         case OP_EQ_E:
225                 OPC->_float = (float)(OPA->_int == OPB->_int);
226                 break;
227         case OP_EQ_FNC:
228                 OPC->_float = (float)(OPA->function == OPB->function);
229                 break;
230
231
232         case OP_NE_F:
233                 OPC->_float = (float)(OPA->_float != OPB->_float);
234                 break;
235         case OP_NE_V:
236                 OPC->_float = (float)((OPA->_vector[0] != OPB->_vector[0]) ||
237                                         (OPA->_vector[1] != OPB->_vector[1]) ||
238                                         (OPA->_vector[2] != OPB->_vector[2]));
239                 break;
240         case OP_NE_S:
241                 if (OPA->string==OPB->string)
242                         OPC->_float = false;
243                 else if (!OPA->string)
244                 {
245                         if (!OPB->string || !*(PR_StringToNative(progfuncs, OPB->string)))
246                                 OPC->_float = false;
247                         else
248                                 OPC->_float = true;
249                 }
250                 else if (!OPB->string)
251                 {
252                         if (!OPA->string || !*PR_StringToNative(progfuncs, OPA->string))
253                                 OPC->_float = false;
254                         else
255                                 OPC->_float = true;
256                 }
257                 else
258                         OPC->_float = (float)(strcmp(PR_StringToNative(progfuncs, OPA->string),PR_StringToNative(progfuncs, OPB->string)));             
259                 break;
260         case OP_NE_E:
261                 OPC->_float = (float)(OPA->_int != OPB->_int);
262                 break;
263         case OP_NE_FNC:
264                 OPC->_float = (float)(OPA->function != OPB->function);
265                 break;
266
267 //==================
268         case OP_STORE_IF:
269                 OPB->_float = (float)OPA->_int;
270                 break;
271         case OP_STORE_FI:
272                 OPB->_int = (int)OPA->_float;
273                 break;
274                 
275         case OP_STORE_F:
276         case OP_STORE_ENT:
277         case OP_STORE_FLD:              // integers
278         case OP_STORE_S:
279         case OP_STORE_I:
280         case OP_STORE_FNC:              // pointers
281         case OP_STORE_P:
282                 OPB->_int = OPA->_int;
283                 break;
284         case OP_STORE_V:
285                 OPB->_vector[0] = OPA->_vector[0];
286                 OPB->_vector[1] = OPA->_vector[1];
287                 OPB->_vector[2] = OPA->_vector[2];
288                 break;
289
290         //store a value to a pointer
291         case OP_STOREP_IF:
292                 if ((unsigned int)OPB->_int >= addressableused)
293                 {
294                         pr_xstatement = st-pr_statements;
295                         PR_RunError (progfuncs, "bad pointer write in %s", progfuncs->stringtable + pr_xfunction->s_name);
296                 }
297                 ptr = QCPOINTER(OPB);
298                 ptr->_float = (float)OPA->_int;
299                 break;
300         case OP_STOREP_FI:
301                 if ((unsigned int)OPB->_int >= addressableused)
302                 {
303                         pr_xstatement = st-pr_statements;
304                         PR_RunError (progfuncs, "bad pointer write in %s", progfuncs->stringtable + pr_xfunction->s_name);
305                 }
306                 ptr = QCPOINTER(OPB);
307                 ptr->_int = (int)OPA->_float;
308                 break;
309         case OP_STOREP_I:
310                 if ((unsigned int)OPB->_int >= addressableused)
311                 {
312                         pr_xstatement = st-pr_statements;
313                         PR_RunError (progfuncs, "bad pointer write in %s", progfuncs->stringtable + pr_xfunction->s_name);
314                 }
315                 ptr = QCPOINTER(OPB);
316                 ptr->_int = OPA->_int;
317                 break;
318         case OP_STOREP_F:
319         case OP_STOREP_ENT:
320         case OP_STOREP_FLD:             // integers
321         case OP_STOREP_S:
322         case OP_STOREP_FNC:             // pointers
323                 if ((unsigned int)OPB->_int >= addressableused)
324                 {
325                         pr_xstatement = st-pr_statements;
326                         PR_RunError (progfuncs, "bad pointer write in %s", progfuncs->stringtable + pr_xfunction->s_name);
327                 }
328                 ptr = QCPOINTER(OPB);
329                 ptr->_int = OPA->_int;
330                 break;
331         case OP_STOREP_V:
332                 if ((unsigned int)OPB->_int >= addressableused)
333                 {
334                         pr_xstatement = st-pr_statements;
335                         PR_RunError (progfuncs, "bad pointer write in %s", progfuncs->stringtable + pr_xfunction->s_name);
336                 }
337                 ptr = QCPOINTER(OPB);
338                 ptr->_vector[0] = OPA->_vector[0];
339                 ptr->_vector[1] = OPA->_vector[1];
340                 ptr->_vector[2] = OPA->_vector[2];
341                 break;
342
343         case OP_STOREP_C:       //store character in a string
344                 if ((unsigned int)OPB->_int >= addressableused)
345                 {
346                         pr_xstatement = st-pr_statements;
347                         PR_RunError (progfuncs, "bad pointer write in %s", progfuncs->stringtable + pr_xfunction->s_name);
348                 }
349                 ptr = QCPOINTER(OPB);
350                 *(unsigned char *)ptr = (char)OPA->_float;
351                 break;
352
353         case OP_MULSTORE_F: // f *= f
354                 OPB->_float *= OPA->_float;
355                 break;
356         case OP_MULSTORE_V: // v *= f
357                 OPB->_vector[0] *= OPA->_float;
358                 OPB->_vector[1] *= OPA->_float;
359                 OPB->_vector[2] *= OPA->_float;
360                 break;
361         case OP_MULSTOREP_F: // e.f *= f
362                 if ((unsigned int)OPB->_int >= addressableused)
363                 {
364                         pr_xstatement = st-pr_statements;
365                         PR_RunError (progfuncs, "bad pointer write in %s", progfuncs->stringtable + pr_xfunction->s_name);
366                 }
367                 ptr = QCPOINTER(OPB);
368                 OPC->_float = (ptr->_float *= OPA->_float);
369                 break;
370         case OP_MULSTOREP_V: // e.v *= f
371                 ptr = QCPOINTER(OPB);
372                 OPC->_vector[0] = (ptr->_vector[0] *= OPA->_float);
373                 OPC->_vector[0] = (ptr->_vector[1] *= OPA->_float);
374                 OPC->_vector[0] = (ptr->_vector[2] *= OPA->_float);
375                 break;
376
377         case OP_DIVSTORE_F: // f /= f
378                 OPB->_float /= OPA->_float;
379                 break;
380         case OP_DIVSTOREP_F: // e.f /= f
381                 ptr = QCPOINTER(OPB);
382                 OPC->_float = (ptr->_float /= OPA->_float);
383                 break;
384
385         case OP_ADDSTORE_F: // f += f
386                 OPB->_float += OPA->_float;
387                 break;
388         case OP_ADDSTORE_V: // v += v
389                 OPB->_vector[0] += OPA->_vector[0];
390                 OPB->_vector[1] += OPA->_vector[1];
391                 OPB->_vector[2] += OPA->_vector[2];
392                 break;
393         case OP_ADDSTOREP_F: // e.f += f
394                 ptr = QCPOINTER(OPB);
395                 OPC->_float = (ptr->_float += OPA->_float);
396                 break;
397         case OP_ADDSTOREP_V: // e.v += v
398                 ptr = QCPOINTER(OPB);
399                 OPC->_vector[0] = (ptr->_vector[0] += OPA->_vector[0]);
400                 OPC->_vector[1] = (ptr->_vector[1] += OPA->_vector[1]);
401                 OPC->_vector[2] = (ptr->_vector[2] += OPA->_vector[2]);
402                 break;
403
404         case OP_SUBSTORE_F: // f -= f
405                 OPB->_float -= OPA->_float;
406                 break;
407         case OP_SUBSTORE_V: // v -= v
408                 OPB->_vector[0] -= OPA->_vector[0];
409                 OPB->_vector[1] -= OPA->_vector[1];
410                 OPB->_vector[2] -= OPA->_vector[2];
411                 break;
412         case OP_SUBSTOREP_F: // e.f -= f
413                 ptr = QCPOINTER(OPB);
414                 OPC->_float = (ptr->_float -= OPA->_float);
415                 break;
416         case OP_SUBSTOREP_V: // e.v -= v
417                 ptr = QCPOINTER(OPB);
418                 OPC->_vector[0] = (ptr->_vector[0] -= OPA->_vector[0]);
419                 OPC->_vector[1] = (ptr->_vector[1] -= OPA->_vector[1]);
420                 OPC->_vector[2] = (ptr->_vector[2] -= OPA->_vector[2]);
421                 break;
422
423
424         //get a pointer to a field var
425         case OP_ADDRESS:
426                 if ((unsigned)OPA->edict >= (unsigned)maxedicts)
427                 {
428 #ifndef DEBUGABLE
429                         pr_trace++;
430                         printf("OP_ADDRESS references invalid entity in %s", progfuncs->stringtable + pr_xfunction->s_name);
431                         st--;
432                         goto cont;
433 #else
434                         PR_RunError (progfuncs, "OP_ADDRESS references invalid entity in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name));
435 #endif
436                 }
437                 ed = PROG_TO_EDICT(progfuncs, OPA->edict);
438 #ifdef PARANOID
439                 NUM_FOR_EDICT(ed);              // make sure it's in range
440 #endif
441                 if (!ed || ed->readonly)
442                 {
443                         pr_xstatement = st-pr_statements;
444 #ifndef DEBUGABLE
445                         //boot it over to the debugger
446                         pr_trace++;
447                         printf("assignment to read-only entity in %s", progfuncs->stringtable + pr_xfunction->s_name);
448                         st--;
449                         goto cont;
450 #else
451                         {
452                                 ddef16_t *d16;
453                                 fdef_t *f;
454                                 d16 = ED_GlobalAtOfs16(progfuncs, st->a);
455                                 f = ED_FieldAtOfs(progfuncs, OPB->_int + progfuncs->fieldadjust);
456                                 PR_RunError (progfuncs, "assignment to read-only entity in %s (%s.%s)", PR_StringToNative(progfuncs, pr_xfunction->s_name), PR_StringToNative(progfuncs, d16->s_name), f?f->name:NULL);
457                         }
458 #endif
459                 }
460
461 //Whilst the next block would technically be correct, we don't use it as it breaks too many quake mods.
462 //              if (ed->isfree)
463 //              {
464 //                      pr_xstatement = st-pr_statements;
465 //                      PR_RunError (progfuncs, "assignment to free entitiy in %s", progfuncs->stringtable + pr_xfunction->s_name);
466 //              }
467                 OPC->_int = ENGINEPOINTER((((int *)edvars(ed)) + OPB->_int + progfuncs->fieldadjust));
468                 break;
469
470         //load a field to a value
471         case OP_LOAD_I:
472         case OP_LOAD_F:
473         case OP_LOAD_FLD:
474         case OP_LOAD_ENT:
475         case OP_LOAD_S:
476         case OP_LOAD_FNC:
477                 if ((unsigned)OPA->edict >= (unsigned)maxedicts)
478                         PR_RunError (progfuncs, "OP_LOAD references invalid entity in %s", progfuncs->stringtable + pr_xfunction->s_name);
479                 ed = PROG_TO_EDICT(progfuncs, OPA->edict);
480 #ifdef PARANOID
481                 NUM_FOR_EDICT(ed);              // make sure it's in range
482 #endif
483                 ptr = (eval_t *)(((int *)edvars(ed)) + OPB->_int + progfuncs->fieldadjust);
484                 OPC->_int = ptr->_int;
485                 break;
486
487         case OP_LOAD_V:
488                 if ((unsigned)OPA->edict >= (unsigned)maxedicts)
489                         PR_RunError (progfuncs, "OP_LOAD_V references invalid entity in %s", progfuncs->stringtable + pr_xfunction->s_name);
490                 ed = PROG_TO_EDICT(progfuncs, OPA->edict);
491 #ifdef PARANOID
492                 NUM_FOR_EDICT(ed);              // make sure it's in range
493 #endif
494                 ptr = (eval_t *)(((int *)edvars(ed)) + OPB->_int + progfuncs->fieldadjust);
495                 OPC->_vector[0] = ptr->_vector[0];
496                 OPC->_vector[1] = ptr->_vector[1];
497                 OPC->_vector[2] = ptr->_vector[2];
498                 break;  
499                 
500 //==================
501
502         case OP_IFNOT_S:
503                 RUNAWAYCHECK();
504                 if (!OPA->string || !PR_StringToNative(progfuncs, OPA->string))
505                         st += (sofs)st->b - 1;  // offset the s++
506                 break;
507
508         case OP_IFNOT_F:
509                 RUNAWAYCHECK();
510                 if (!OPA->_float)
511                         st += (sofs)st->b - 1;  // offset the s++
512                 break;
513
514         case OP_IFNOT_I:
515                 RUNAWAYCHECK();
516                 if (!OPA->_int)
517                         st += (sofs)st->b - 1;  // offset the s++
518                 break;
519
520         case OP_IF_S:
521                 RUNAWAYCHECK();
522                 if (OPA->string && PR_StringToNative(progfuncs, OPA->string))
523                         st += (sofs)st->b - 1;  // offset the s++
524                 break;
525
526         case OP_IF_F:
527                 RUNAWAYCHECK();
528                 if (OPA->_int)
529                         st += (sofs)st->b - 1;  // offset the s++
530                 break;
531
532         case OP_IF_I:
533                 RUNAWAYCHECK();
534                 if (OPA->_int)
535                         st += (sofs)st->b - 1;  // offset the s++
536                 break;
537                 
538         case OP_GOTO:
539                 RUNAWAYCHECK();
540                 st += (sofs)st->a - 1;  // offset the s++
541                 break;
542
543         case OP_CALL8H:
544         case OP_CALL7H:
545         case OP_CALL6H:
546         case OP_CALL5H:
547         case OP_CALL4H:
548         case OP_CALL3H:
549         case OP_CALL2H:
550                 G_VECTOR(OFS_PARM1)[0] = OPC->_vector[0];
551                 G_VECTOR(OFS_PARM1)[1] = OPC->_vector[1];
552                 G_VECTOR(OFS_PARM1)[2] = OPC->_vector[2];
553         case OP_CALL1H:
554                 G_VECTOR(OFS_PARM0)[0] = OPB->_vector[0];
555                 G_VECTOR(OFS_PARM0)[1] = OPB->_vector[1];
556                 G_VECTOR(OFS_PARM0)[2] = OPB->_vector[2];
557
558         case OP_CALL8:
559         case OP_CALL7:
560         case OP_CALL6:
561         case OP_CALL5:
562         case OP_CALL4:
563         case OP_CALL3:
564         case OP_CALL2:
565         case OP_CALL1:
566         case OP_CALL0:
567                 RUNAWAYCHECK();
568                 pr_xstatement = st-pr_statements;
569
570
571                 if (st->op > OP_CALL8)
572                         pr_argc = st->op - (OP_CALL1H-1);
573                 else
574                         pr_argc = st->op - OP_CALL0;
575                 fnum = OPA->function;
576                 if ((fnum & ~0xff000000)==0)
577                 {
578                         PR_RunError(progfuncs, "NULL function from qc (%s).\n", progfuncs->stringtable + pr_xfunction->s_name);
579 #ifndef DEBUGABLE
580                         goto cont;
581 #endif
582                         break;
583                 }
584 /*
585 {
586         static char buffer[1024*1024*8];
587         int size = sizeof buffer;
588                 progfuncs->save_ents(progfuncs, buffer, &size, 0);
589 }*/
590
591
592                 p=pr_typecurrent;
593 //about to switch. needs caching.
594
595                 //if it's an external call, switch now (before any function pointers are used)
596                 PR_MoveParms(progfuncs, (fnum & 0xff000000)>>24, p);
597                 PR_SwitchProgs(progfuncs, (fnum & 0xff000000)>>24);
598
599                 newf = &pr_functions[fnum & ~0xff000000];
600
601                 if (newf->first_statement < 0)
602                 {       // negative statements are built in functions
603
604 if (pr_typecurrent != 0)
605 {
606         PR_MoveParms(progfuncs, 0, pr_typecurrent);
607         PR_SwitchProgs(progfuncs, 0);
608 }
609                         i = -newf->first_statement;
610 //                      p = pr_typecurrent;
611                         progfuncs->lastcalledbuiltinnumber = i;
612                         if (i < externs->numglobalbuiltins)
613                         {
614                                 prinst->numtempstringsstack = prinst->numtempstrings;
615                                 (*externs->globalbuiltins[i]) (progfuncs, (struct globalvars_s *)current_progstate->globals);
616                                 if (prinst->continuestatement!=-1)
617                                 {
618                                         st=&pr_statements[prinst->continuestatement];
619                                         prinst->continuestatement=-1;
620                                         break;
621                                 }
622                         }
623                         else
624                         {
625                                 i -= externs->numglobalbuiltins;
626                                 if (i >= current_progstate->numbuiltins)
627                                 {
628 //                                      if (newf->first_statement == -0x7fffffff)
629 //                                              ((builtin_t)newf->profile) (progfuncs, (struct globalvars_s *)current_progstate->globals);
630 //                                      else
631                                                 PR_RunError (progfuncs, "Bad builtin call number - %i", -newf->first_statement);
632                                 }
633                                 else
634                                         current_progstate->builtins [i] (progfuncs, (struct globalvars_s *)current_progstate->globals);
635                         }
636                         PR_MoveParms(progfuncs, p, pr_typecurrent);
637 //                      memcpy(&pr_progstate[p].globals[OFS_RETURN], &current_progstate->globals[OFS_RETURN], sizeof(vec3_t));
638                         PR_SwitchProgs(progfuncs, (progsnum_t)p);
639
640 //#ifndef DEBUGABLE     //decide weather non debugger wants to start debugging.
641                         s = st-pr_statements;
642                         goto restart;
643 //#endif
644 //                      break;
645                 }
646 //              PR_MoveParms((OPA->function & 0xff000000)>>24, pr_typecurrent);
647 //              PR_SwitchProgs((OPA->function & 0xff000000)>>24);
648                 s = PR_EnterFunction (progfuncs, newf, p);
649                 st = &pr_statements[s];
650                 
651                 goto restart;
652 //              break;
653
654         case OP_DONE:
655         case OP_RETURN:
656
657                 RUNAWAYCHECK();
658
659                 pr_globals[OFS_RETURN] = pr_globals[st->a];
660                 pr_globals[OFS_RETURN+1] = pr_globals[st->a+1];
661                 pr_globals[OFS_RETURN+2] = pr_globals[st->a+2];
662 /*
663 {
664         static char buffer[1024*1024*8];
665         int size = sizeof buffer;
666                 progfuncs->save_ents(progfuncs, buffer, &size, 0);
667 }
668 */
669                 s = PR_LeaveFunction (progfuncs);
670                 st = &pr_statements[s];         
671                 if (pr_depth == prinst->exitdepth)
672                 {               
673                         return;         // all done
674                 }
675                 goto restart;
676 //              break;
677
678         case OP_STATE:
679                 externs->stateop(progfuncs, OPA->_float, OPB->function);
680                 break;
681
682         case OP_ADD_I:          
683                 OPC->_int = OPA->_int + OPB->_int;
684                 break;
685         case OP_ADD_FI:
686                 OPC->_float = OPA->_float + (float)OPB->_int;
687                 break;
688         case OP_ADD_IF:
689                 OPC->_float = (float)OPA->_int + OPB->_float;
690                 break;
691   
692         case OP_SUB_I:
693                 OPC->_int = OPA->_int - OPB->_int;
694                 break;
695         case OP_SUB_FI:
696                 OPC->_float = OPA->_float - (float)OPB->_int;
697                 break;
698         case OP_SUB_IF:
699                 OPC->_float = (float)OPA->_int - OPB->_float;
700                 break;
701
702         case OP_CONV_ITOF:
703                 OPC->_float = (float)OPA->_int;
704                 break;
705         case OP_CONV_FTOI:
706                 OPC->_int = (int)OPA->_float;
707                 break;
708
709         case OP_CP_ITOF:
710                 ptr = (eval_t *)(((qbyte *)sv_edicts) + OPA->_int);
711                 OPC->_float = (float)ptr->_int;
712                 break;
713
714         case OP_CP_FTOI:
715                 ptr = (eval_t *)(((qbyte *)sv_edicts) + OPA->_int);
716                 OPC->_int = (int)ptr->_float;
717                 break;
718
719         case OP_BITAND_I:
720                 OPC->_int = (OPA->_int & OPB->_int);
721                 break;
722         
723         case OP_BITOR_I:
724                 OPC->_int = (OPA->_int | OPB->_int);
725                 break;
726
727         case OP_MUL_I:          
728                 OPC->_int = OPA->_int * OPB->_int;
729                 break;
730         case OP_DIV_I:
731                 if (OPB->_int == 0)     //no division by zero allowed...
732                         OPC->_int = 0;
733                 else
734                         OPC->_int = OPA->_int / OPB->_int;
735                 break;
736         case OP_EQ_I:
737                 OPC->_int = (OPA->_int == OPB->_int);
738                 break;
739         case OP_NE_I:
740                 OPC->_int = (OPA->_int != OPB->_int);
741                 break;
742         
743
744         //array/structure reading/writing.
745         case OP_GLOBALADDRESS:
746                 OPC->_int = ENGINEPOINTER(&OPA->_int + OPB->_int);
747                 break;
748         case OP_POINTER_ADD:    //pointer to 32 bit (remember to *3 for vectors)
749                 OPC->_int = OPA->_int + OPB->_int*4;
750                 break;
751
752         case OP_LOADA_I:
753         case OP_LOADA_F:
754         case OP_LOADA_FLD:
755         case OP_LOADA_ENT:
756         case OP_LOADA_S:
757         case OP_LOADA_FNC:
758                 ptr = (eval_t *)(&OPA->_int + OPB->_int);
759                 OPC->_int = ptr->_int;
760                 break;
761
762         case OP_LOADA_V:
763                 ptr = (eval_t *)(&OPA->_int + OPB->_int);
764                 OPC->_vector[0] = ptr->_vector[0];
765                 OPC->_vector[1] = ptr->_vector[1];
766                 OPC->_vector[2] = ptr->_vector[2];
767                 break;
768
769
770
771         case OP_ADD_SF: //(char*)c = (char*)a + (float)b
772                 OPC->_int = OPA->_int + (int)OPB->_float;
773                 break;
774         case OP_SUB_S:  //(float)c = (char*)a - (char*)b
775                 OPC->_int = OPA->_int - OPB->_int;
776                 break;
777         case OP_LOADP_C:        //load character from a string
778                 ptr = QCPOINTERM(OPA->_int + (int)OPB->_float);
779                 OPC->_float = *(unsigned char *)ptr;
780                 break;
781         case OP_LOADP_I:
782         case OP_LOADP_F:
783         case OP_LOADP_FLD:
784         case OP_LOADP_ENT:
785         case OP_LOADP_S:
786         case OP_LOADP_FNC:
787                 ptr = QCPOINTERM(OPA->_int + OPB->_int);
788                 OPC->_int = ptr->_int;
789                 break;
790
791         case OP_LOADP_V:
792                 ptr = QCPOINTERM(OPA->_int + OPB->_int);
793                 OPC->_vector[0] = ptr->_vector[0];
794                 OPC->_vector[1] = ptr->_vector[1];
795                 OPC->_vector[2] = ptr->_vector[2];
796                 break;
797
798         case OP_XOR_I:
799                 OPC->_int = OPA->_int ^ OPB->_int;
800                 break;
801         case OP_RSHIFT_I:
802                 OPC->_int = OPA->_int >> OPB->_int;
803                 break;
804         case OP_LSHIFT_I:
805                 OPC->_int = OPA->_int << OPB->_int;
806                 break;
807
808
809         case OP_FETCH_GBL_F:
810         case OP_FETCH_GBL_S:
811         case OP_FETCH_GBL_E:
812         case OP_FETCH_GBL_FNC:
813                 i = (int)OPB->_float;
814                 if(i < 0 || i > ((eval_t *)&glob[st->a-1])->_int)
815                 {
816                         PR_RunError(progfuncs, "array index out of bounds: %s[%d]", PR_GlobalStringNoContents(progfuncs, st->a), i);
817                 }
818                 t = (eval_t *)&pr_globals[(uofs)st->a + i];
819                 OPC->_int = t->_int;
820                 break;
821         case OP_FETCH_GBL_V:
822                 i = (int)OPB->_float;
823                 if(i < 0 || i > ((eval_t *)&glob[st->a-1])->_int)
824                 {
825                         PR_RunError(progfuncs, "array index out of bounds: %s[%d]", PR_GlobalStringNoContents(progfuncs, st->a), i);
826                 }
827                 t = (eval_t *)&pr_globals[(uofs)st->a + i*3];
828                 OPC->_vector[0] = t->_vector[0];
829                 OPC->_vector[1] = t->_vector[1];
830                 OPC->_vector[2] = t->_vector[2];
831                 break;
832
833         case OP_CSTATE:
834                 externs->cstateop(progfuncs, OPA->_float, OPB->_float, fnum);
835                 break;
836
837         case OP_CWSTATE:
838                 externs->cwstateop(progfuncs, OPA->_float, OPB->_float, fnum);
839                 break;
840
841         case OP_THINKTIME:
842                 externs->thinktimeop(progfuncs, (struct edict_s *)PROG_TO_EDICT(progfuncs, OPA->edict), OPB->_float);
843                 break;
844
845
846         case OP_BITSET: // b (+) a
847                 OPB->_float = (float)((int)OPB->_float | (int)OPA->_float);
848                 break;
849         case OP_BITSETP: // .b (+) a
850                 ptr = QCPOINTER(OPB);
851                 ptr->_float = (float)((int)ptr->_float | (int)OPA->_float);
852                 break;
853         case OP_BITCLR: // b (-) a
854                 OPB->_float = (float)((int)OPB->_float & ~((int)OPA->_float));
855                 break;
856         case OP_BITCLRP: // .b (-) a
857                 ptr = QCPOINTER(OPB);
858                 ptr->_float = (float)((int)ptr->_float & ~((int)OPA->_float));
859                 break;
860
861         case OP_RAND0:
862                 G_FLOAT(OFS_RETURN) = (rand()&0x7fff)/((float)0x7fff);
863                 break;
864         case OP_RAND1:
865                 G_FLOAT(OFS_RETURN) = (rand()&0x7fff)/((float)0x7fff)*OPA->_float;
866                 break;
867         case OP_RAND2:
868                 if(OPA->_float < OPB->_float)
869                 {
870                         G_FLOAT(OFS_RETURN) = OPA->_float+((rand()&0x7fff)/((float)0x7fff)
871                                 *(OPB->_float-OPA->_float));
872                 }
873                 else
874                 {
875                         G_FLOAT(OFS_RETURN) = OPB->_float+((rand()&0x7fff)/((float)0x7fff)
876                                 *(OPA->_float-OPB->_float));
877                 }
878                 break;
879         case OP_RANDV0:
880                 G_FLOAT(OFS_RETURN+0) = (rand()&0x7fff)/((float)0x7fff);
881                 G_FLOAT(OFS_RETURN+1) = (rand()&0x7fff)/((float)0x7fff);
882                 G_FLOAT(OFS_RETURN+2) = (rand()&0x7fff)/((float)0x7fff);
883                 break;
884         case OP_RANDV1:
885                 G_FLOAT(OFS_RETURN+0) = (rand()&0x7fff)/((float)0x7fff)*OPA->_vector[0];
886                 G_FLOAT(OFS_RETURN+1) = (rand()&0x7fff)/((float)0x7fff)*OPA->_vector[1];
887                 G_FLOAT(OFS_RETURN+2) = (rand()&0x7fff)/((float)0x7fff)*OPA->_vector[2];
888                 break;
889         case OP_RANDV2:
890                 for(i = 0; i < 3; i++)
891                 {
892                         if(OPA->_vector[i] < OPB->_vector[i])
893                         {
894                                 G_FLOAT(OFS_RETURN+i) = OPA->_vector[i]+((rand()&0x7fff)/((float)0x7fff)
895                                         *(OPB->_vector[i]-OPA->_vector[i]));
896                         }
897                         else
898                         {
899                                 G_FLOAT(OFS_RETURN+i) = OPB->_vector[i]+(rand()*(1.0f/RAND_MAX)
900                                         *(OPA->_vector[i]-OPB->_vector[i]));
901                         }
902                 }
903                 break;
904
905
906         case OP_SWITCH_F:
907         case OP_SWITCH_V:
908         case OP_SWITCH_S:
909         case OP_SWITCH_E:
910         case OP_SWITCH_FNC:
911                 swtch = OPA;
912                 swtchtype = st->op;
913                 RUNAWAYCHECK();
914                 st += (sofs)st->b - 1;  // offset the st++
915                 break;
916         case OP_CASE:
917                 switch(swtchtype)
918                 {
919                 case OP_SWITCH_F:
920                         if (swtch->_float == OPA->_float)
921                         {
922                                 RUNAWAYCHECK();
923                                 st += (sofs)st->b-1; // -1 to offset the s++
924                         }
925                         break;
926                 case OP_SWITCH_E:
927                 case OP_SWITCH_FNC:
928                         if (swtch->_int == OPA->_int)
929                         {
930                                 RUNAWAYCHECK();
931                                 st += (sofs)st->b-1; // -1 to offset the s++
932                         }
933                         break;
934                 case OP_SWITCH_S:
935                         if (swtch->_int == OPA->_int)
936                         {
937                                 RUNAWAYCHECK();
938                                 st += (sofs)st->b-1; // -1 to offset the s++
939                         }
940                         if ((!swtch->_int && PR_StringToNative(progfuncs, OPA->string)) || (!OPA->_int && PR_StringToNative(progfuncs, swtch->string))) //one is null (cannot be not both).
941                                 break;
942                         if (!strcmp(PR_StringToNative(progfuncs, swtch->string), PR_StringToNative(progfuncs, OPA->string)))
943                         {
944                                 RUNAWAYCHECK();
945                                 st += (sofs)st->b-1; // -1 to offset the s++
946                         }
947                         break;
948                 case OP_SWITCH_V:
949                         if (swtch->_vector[0] == OPA->_vector[0] && swtch->_vector[1] == OPA->_vector[1] && swtch->_vector[2] == OPA->_vector[2])
950                         {
951                                 RUNAWAYCHECK();
952                                 st += (sofs)st->b-1; // -1 to offset the s++
953                         }
954                         break;
955                 default:
956                         PR_RunError (progfuncs, "OP_CASE with bad/missing OP_SWITCH %i", swtchtype);
957                         break;
958                 }
959                 break;
960         case OP_CASERANGE:
961                 switch(swtchtype)
962                 {
963                 case OP_SWITCH_F:
964                         if (swtch->_float >= OPA->_float && swtch->_float <= OPB->_float)
965                         {
966                                 RUNAWAYCHECK();
967                                 st += (sofs)st->c-1; // -1 to offset the s++
968                         }
969                         break;
970                 default:
971                         PR_RunError (progfuncs, "OP_CASERANGE with bad/missing OP_SWITCH %i", swtchtype);
972                 }
973                 break;
974
975
976
977
978
979
980
981
982
983         case OP_BITAND_IF:
984                 OPC->_int = (OPA->_int & (int)OPB->_float);
985                 break;
986         case OP_BITOR_IF:
987                 OPC->_int = (OPA->_int | (int)OPB->_float);
988                 break;
989         case OP_BITAND_FI:
990                 OPC->_int = ((int)OPA->_float & OPB->_int);
991                 break;
992         case OP_BITOR_FI:
993                 OPC->_int = ((int)OPA->_float | OPB->_int);
994                 break;
995
996         case OP_MUL_IF:
997                 OPC->_float = (OPA->_int * OPB->_float);
998                 break;
999         case OP_MUL_FI:
1000                 OPC->_float = (OPA->_float * OPB->_int);
1001                 break;
1002
1003         case OP_MUL_VI:
1004                 OPC->_vector[0] = OPA->_vector[0] * OPB->_int;
1005                 OPC->_vector[1] = OPA->_vector[0] * OPB->_int;
1006                 OPC->_vector[2] = OPA->_vector[0] * OPB->_int;
1007                 break;
1008         case OP_MUL_IV:
1009                 OPC->_vector[0] = OPB->_int * OPA->_vector[0];
1010                 OPC->_vector[1] = OPB->_int * OPA->_vector[1];
1011                 OPC->_vector[2] = OPB->_int * OPA->_vector[2];
1012                 break;
1013
1014         case OP_DIV_IF:
1015                 OPC->_float = (OPA->_int / OPB->_float);
1016                 break;
1017         case OP_DIV_FI:
1018                 OPC->_float = (OPA->_float / OPB->_int);
1019                 break;
1020
1021         case OP_AND_I:
1022                 OPC->_int = (OPA->_int && OPB->_int);
1023                 break;
1024         case OP_OR_I:
1025                 OPC->_int = (OPA->_int || OPB->_int);
1026                 break;
1027
1028         case OP_AND_IF:
1029                 OPC->_int = (OPA->_int && OPB->_float);
1030                 break;
1031         case OP_OR_IF:
1032                 OPC->_int = (OPA->_int || OPB->_float);
1033                 break;
1034
1035         case OP_AND_FI:
1036                 OPC->_int = (OPA->_float && OPB->_int);
1037                 break;
1038         case OP_OR_FI:
1039                 OPC->_int = (OPA->_float || OPB->_int);
1040                 break;
1041
1042         case OP_NOT_I:
1043                 OPC->_int = !OPA->_int;
1044                 break;
1045
1046         case OP_NE_IF:
1047                 OPC->_int = (OPA->_int != OPB->_float);
1048                 break;
1049         case OP_NE_FI:
1050                 OPC->_int = (OPA->_float != OPB->_int);
1051                 break;
1052
1053         case OP_GSTOREP_I:
1054         case OP_GSTOREP_F:
1055         case OP_GSTOREP_ENT:
1056         case OP_GSTOREP_FLD:            // integers
1057         case OP_GSTOREP_S:
1058         case OP_GSTOREP_FNC:            // pointers
1059         case OP_GSTOREP_V:
1060         case OP_GADDRESS:
1061         case OP_GLOAD_I:
1062         case OP_GLOAD_F:
1063         case OP_GLOAD_FLD:
1064         case OP_GLOAD_ENT:
1065         case OP_GLOAD_S:
1066         case OP_GLOAD_FNC:
1067                 pr_xstatement = st-pr_statements;
1068                 PR_RunError(progfuncs, "Extra opcode not implemented\n");
1069                 break;
1070
1071         case OP_BOUNDCHECK:
1072                 if ((unsigned int)OPA->_int < (unsigned int)st->c || (unsigned int)OPA->_int >= (unsigned int)st->b)
1073                 {
1074                         pr_xstatement = st-pr_statements;
1075                         PR_RunError(progfuncs, "Progs boundcheck failed. Value is %i.", OPA->_int);
1076                 }
1077                 break;
1078 /*      case OP_PUSH:
1079                 OPC->_int = ENGINEPOINTER(&localstack[localstack_used+pr_spushed]);
1080                 pr_spushed += OPA->_int;
1081                 if (pr_spushed + localstack_used >= LOCALSTACK_SIZE)
1082                 {
1083                         pr_spushed = 0;
1084                         pr_xstatement = st-pr_statements;
1085                         PR_RunError(progfuncs, "Progs pushed too much");
1086                 }
1087                 break;
1088         case OP_POP:
1089                 pr_spushed -= OPA->_int;
1090                 if (pr_spushed < 0)
1091                 {
1092                         pr_spushed = 0;
1093                         pr_xstatement = st-pr_statements;
1094                         PR_RunError(progfuncs, "Progs poped more than it pushed");
1095                 }
1096                 break;
1097 */
1098         default:                                        
1099                 if (st->op & 0x8000)    //break point!
1100                 {
1101                         pr_xstatement = s = st-pr_statements;
1102
1103                         printf("Break point hit in %s.\n", pr_xfunction->s_name+progfuncs->stringtable);
1104                         if (pr_trace<1)
1105                                 pr_trace=1;     //this is what it's for
1106
1107                         s = ShowStep(progfuncs, s);
1108                         st = &pr_statements[s]; //let the user move execution
1109                         pr_xstatement = s = st-pr_statements;
1110
1111                         goto reeval;    //reexecute
1112                 }
1113                 pr_xstatement = st-pr_statements;
1114                 PR_RunError (progfuncs, "Bad opcode %i", st->op);
1115         }
1116 }
1117
1118
1119 #undef cont
1120 #undef reeval
1121 #undef st
1122 #undef pr_statements
1123 #undef fakeop
1124 #undef dstatement_t
1125 #undef sofs
1126 #undef uofs
1127
1128 #undef ENGINEPOINTER
1129 #undef QCPOINTER
1130 #undef QCPOINTERM
1131