]> de.git.xonotic.org Git - voretournament/voretournament.git/blob - misc/mediasource/extra/fteqcc-src/execloop.h
fteqcc source
[voretournament/voretournament.git] / misc / mediasource / extra / 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 #else
53         st++;
54 #endif
55
56         switch (st->op)
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:
105                 OPC->_float = (float)((int)OPA->_float & (int)OPB->_float);
106                 break;
107
108         case OP_BITOR:
109                 OPC->_float = (float)((int)OPA->_float | (int)OPB->_float);
110                 break;
111
112
113         case OP_GE:
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:
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:
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:
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:
166                 OPC->_float = (float)(OPA->_float && OPB->_float);
167                 break;
168         case OP_OR:
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:
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:
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_trace++;
579                         printf("NULL function from qc (%s).\n", progfuncs->stringtable + pr_xfunction->s_name);
580 #ifndef DEBUGABLE
581                         goto cont;
582 #endif
583                         break;
584                 }
585 /*
586 {
587         static char buffer[1024*1024*8];
588         int size = sizeof buffer;
589                 progfuncs->save_ents(progfuncs, buffer, &size, 0);
590 }*/
591
592
593                 p=pr_typecurrent;
594 //about to switch. needs caching.
595
596                 //if it's an external call, switch now (before any function pointers are used)
597                 PR_MoveParms(progfuncs, (fnum & 0xff000000)>>24, p);
598                 PR_SwitchProgs(progfuncs, (fnum & 0xff000000)>>24);
599
600                 newf = &pr_functions[fnum & ~0xff000000];
601
602                 if (newf->first_statement < 0)
603                 {       // negative statements are built in functions
604
605 if (pr_typecurrent != 0)
606 {
607         PR_MoveParms(progfuncs, 0, pr_typecurrent);
608         PR_SwitchProgs(progfuncs, 0);
609 }
610                         i = -newf->first_statement;
611 //                      p = pr_typecurrent;
612                         progfuncs->lastcalledbuiltinnumber = i;
613                         if (i < externs->numglobalbuiltins)
614                         {
615                                 prinst->numtempstringsstack = prinst->numtempstrings;
616                                 (*externs->globalbuiltins[i]) (progfuncs, (struct globalvars_s *)current_progstate->globals);
617                                 if (prinst->continuestatement!=-1)
618                                 {
619                                         st=&pr_statements[prinst->continuestatement];
620                                         prinst->continuestatement=-1;
621                                         break;
622                                 }
623                         }
624                         else
625                         {
626                                 i -= externs->numglobalbuiltins;
627                                 if (i >= current_progstate->numbuiltins)
628                                 {
629 //                                      if (newf->first_statement == -0x7fffffff)
630 //                                              ((builtin_t)newf->profile) (progfuncs, (struct globalvars_s *)current_progstate->globals);
631 //                                      else
632                                                 PR_RunError (progfuncs, "Bad builtin call number - %i", -newf->first_statement);
633                                 }
634                                 else
635                                         current_progstate->builtins [i] (progfuncs, (struct globalvars_s *)current_progstate->globals);
636                         }
637                         PR_MoveParms(progfuncs, p, pr_typecurrent);
638 //                      memcpy(&pr_progstate[p].globals[OFS_RETURN], &current_progstate->globals[OFS_RETURN], sizeof(vec3_t));
639                         PR_SwitchProgs(progfuncs, (progsnum_t)p);
640
641 //#ifndef DEBUGABLE     //decide weather non debugger wants to start debugging.
642                         s = st-pr_statements;
643                         goto restart;
644 //#endif
645 //                      break;
646                 }
647 //              PR_MoveParms((OPA->function & 0xff000000)>>24, pr_typecurrent);
648 //              PR_SwitchProgs((OPA->function & 0xff000000)>>24);
649                 s = PR_EnterFunction (progfuncs, newf, p);
650                 st = &pr_statements[s];
651                 
652                 goto restart;
653 //              break;
654
655         case OP_DONE:
656         case OP_RETURN:
657
658                 RUNAWAYCHECK();
659
660                 pr_globals[OFS_RETURN] = pr_globals[st->a];
661                 pr_globals[OFS_RETURN+1] = pr_globals[st->a+1];
662                 pr_globals[OFS_RETURN+2] = pr_globals[st->a+2];
663 /*
664 {
665         static char buffer[1024*1024*8];
666         int size = sizeof buffer;
667                 progfuncs->save_ents(progfuncs, buffer, &size, 0);
668 }
669 */
670                 s = PR_LeaveFunction (progfuncs);
671                 st = &pr_statements[s];         
672                 if (pr_depth == prinst->exitdepth)
673                 {               
674                         return;         // all done
675                 }
676                 goto restart;
677 //              break;
678
679         case OP_STATE:
680                 externs->stateop(progfuncs, OPA->_float, OPB->function);
681                 break;
682
683         case OP_ADD_I:          
684                 OPC->_int = OPA->_int + OPB->_int;
685                 break;
686         case OP_ADD_FI:
687                 OPC->_float = OPA->_float + (float)OPB->_int;
688                 break;
689         case OP_ADD_IF:
690                 OPC->_float = (float)OPA->_int + OPB->_float;
691                 break;
692   
693         case OP_SUB_I:
694                 OPC->_int = OPA->_int - OPB->_int;
695                 break;
696         case OP_SUB_FI:
697                 OPC->_float = OPA->_float - (float)OPB->_int;
698                 break;
699         case OP_SUB_IF:
700                 OPC->_float = (float)OPA->_int - OPB->_float;
701                 break;
702
703         case OP_CONV_ITOF:
704                 OPC->_float = (float)OPA->_int;
705                 break;
706         case OP_CONV_FTOI:
707                 OPC->_int = (int)OPA->_float;
708                 break;
709
710         case OP_CP_ITOF:
711                 ptr = (eval_t *)(((qbyte *)sv_edicts) + OPA->_int);
712                 OPC->_float = (float)ptr->_int;
713                 break;
714
715         case OP_CP_FTOI:
716                 ptr = (eval_t *)(((qbyte *)sv_edicts) + OPA->_int);
717                 OPC->_int = (int)ptr->_float;
718                 break;
719
720         case OP_BITAND_I:
721                 OPC->_int = (OPA->_int & OPB->_int);
722                 break;
723         
724         case OP_BITOR_I:
725                 OPC->_int = (OPA->_int | OPB->_int);
726                 break;
727
728         case OP_MUL_I:          
729                 OPC->_int = OPA->_int * OPB->_int;
730                 break;
731         case OP_DIV_I:
732                 if (OPB->_int == 0)     //no division by zero allowed...
733                         OPC->_int = 0;
734                 else
735                         OPC->_int = OPA->_int / OPB->_int;
736                 break;
737         case OP_EQ_I:
738                 OPC->_int = (OPA->_int == OPB->_int);
739                 break;
740         case OP_NE_I:
741                 OPC->_int = (OPA->_int != OPB->_int);
742                 break;
743         
744
745         //array/structure reading/riting.
746         case OP_GLOBALADDRESS:
747                 OPC->_int = ENGINEPOINTER(&OPA->_int + OPB->_int);
748                 break;
749         case OP_POINTER_ADD:    //pointer to 32 bit (remember to *3 for vectors)
750                 OPC->_int = OPA->_int + OPB->_int*4;
751                 break;
752
753         case OP_LOADA_I:
754         case OP_LOADA_F:
755         case OP_LOADA_FLD:
756         case OP_LOADA_ENT:
757         case OP_LOADA_S:
758         case OP_LOADA_FNC:
759                 ptr = (eval_t *)(&OPA->_int + OPB->_int);
760                 OPC->_int = ptr->_int;
761                 break;
762
763         case OP_LOADA_V:
764                 ptr = (eval_t *)(&OPA->_int + OPB->_int);
765                 OPC->_vector[0] = ptr->_vector[0];
766                 OPC->_vector[1] = ptr->_vector[1];
767                 OPC->_vector[2] = ptr->_vector[2];
768                 break;
769
770
771
772         case OP_ADD_SF: //(char*)c = (char*)a + (float)b
773                 OPC->_int = OPA->_int + (int)OPB->_float;
774                 break;
775         case OP_SUB_S:  //(float)c = (char*)a - (char*)b
776                 OPC->_int = OPA->_int - OPB->_int;
777                 break;
778         case OP_LOADP_C:        //load character from a string
779                 ptr = QCPOINTERM(OPA->_int + (int)OPB->_float);
780                 OPC->_float = *(unsigned char *)ptr;
781                 break;
782         case OP_LOADP_I:
783         case OP_LOADP_F:
784         case OP_LOADP_FLD:
785         case OP_LOADP_ENT:
786         case OP_LOADP_S:
787         case OP_LOADP_FNC:
788                 ptr = QCPOINTERM(OPA->_int + OPB->_int);
789                 OPC->_int = ptr->_int;
790                 break;
791
792         case OP_LOADP_V:
793                 ptr = QCPOINTERM(OPA->_int + OPB->_int);
794                 OPC->_vector[0] = ptr->_vector[0];
795                 OPC->_vector[1] = ptr->_vector[1];
796                 OPC->_vector[2] = ptr->_vector[2];
797                 break;
798
799         case OP_XOR_I:
800                 OPC->_int = OPA->_int ^ OPB->_int;
801                 break;
802         case OP_RSHIFT_I:
803                 OPC->_int = OPA->_int >> OPB->_int;
804                 break;
805         case OP_LSHIFT_I:
806                 OPC->_int = OPA->_int << OPB->_int;
807                 break;
808
809
810         case OP_FETCH_GBL_F:
811         case OP_FETCH_GBL_S:
812         case OP_FETCH_GBL_E:
813         case OP_FETCH_GBL_FNC:
814                 i = (int)OPB->_float;
815                 if(i < 0 || i > ((eval_t *)&glob[st->a-1])->_int)
816                 {
817                         PR_RunError(progfuncs, "array index out of bounds: %s[%d]", PR_GlobalStringNoContents(progfuncs, st->a), i);
818                 }
819                 t = (eval_t *)&pr_globals[(uofs)st->a + i];
820                 OPC->_int = t->_int;
821                 break;
822         case OP_FETCH_GBL_V:
823                 i = (int)OPB->_float;
824                 if(i < 0 || i > ((eval_t *)&glob[st->a-1])->_int)
825                 {
826                         PR_RunError(progfuncs, "array index out of bounds: %s[%d]", PR_GlobalStringNoContents(progfuncs, st->a), i);
827                 }
828                 t = (eval_t *)&pr_globals[(uofs)st->a
829                         +((int)OPB->_float)*3];
830                 OPC->_vector[0] = t->_vector[0];
831                 OPC->_vector[1] = t->_vector[1];
832                 OPC->_vector[2] = t->_vector[2];
833                 break;
834
835         case OP_CSTATE:
836                 externs->cstateop(progfuncs, OPA->_float, OPB->_float, fnum);
837                 break;
838
839         case OP_CWSTATE:
840                 externs->cwstateop(progfuncs, OPA->_float, OPB->_float, fnum);
841                 break;
842
843         case OP_THINKTIME:
844                 externs->thinktimeop(progfuncs, (struct edict_s *)PROG_TO_EDICT(progfuncs, OPA->edict), OPB->_float);
845                 break;
846
847
848         case OP_BITSET: // b (+) a
849                 OPB->_float = (float)((int)OPB->_float | (int)OPA->_float);
850                 break;
851         case OP_BITSETP: // .b (+) a
852                 ptr = QCPOINTER(OPB);
853                 ptr->_float = (float)((int)ptr->_float | (int)OPA->_float);
854                 break;
855         case OP_BITCLR: // b (-) a
856                 OPB->_float = (float)((int)OPB->_float & ~((int)OPA->_float));
857                 break;
858         case OP_BITCLRP: // .b (-) a
859                 ptr = QCPOINTER(OPB);
860                 ptr->_float = (float)((int)ptr->_float & ~((int)OPA->_float));
861                 break;
862
863         case OP_RAND0:
864                 G_FLOAT(OFS_RETURN) = (rand()&0x7fff)/((float)0x7fff);
865                 break;
866         case OP_RAND1:
867                 G_FLOAT(OFS_RETURN) = (rand()&0x7fff)/((float)0x7fff)*OPA->_float;
868                 break;
869         case OP_RAND2:
870                 if(OPA->_float < OPB->_float)
871                 {
872                         G_FLOAT(OFS_RETURN) = OPA->_float+((rand()&0x7fff)/((float)0x7fff)
873                                 *(OPB->_float-OPA->_float));
874                 }
875                 else
876                 {
877                         G_FLOAT(OFS_RETURN) = OPB->_float+((rand()&0x7fff)/((float)0x7fff)
878                                 *(OPA->_float-OPB->_float));
879                 }
880                 break;
881         case OP_RANDV0:
882                 G_FLOAT(OFS_RETURN+0) = (rand()&0x7fff)/((float)0x7fff);
883                 G_FLOAT(OFS_RETURN+1) = (rand()&0x7fff)/((float)0x7fff);
884                 G_FLOAT(OFS_RETURN+2) = (rand()&0x7fff)/((float)0x7fff);
885                 break;
886         case OP_RANDV1:
887                 G_FLOAT(OFS_RETURN+0) = (rand()&0x7fff)/((float)0x7fff)*OPA->_vector[0];
888                 G_FLOAT(OFS_RETURN+1) = (rand()&0x7fff)/((float)0x7fff)*OPA->_vector[1];
889                 G_FLOAT(OFS_RETURN+2) = (rand()&0x7fff)/((float)0x7fff)*OPA->_vector[2];
890                 break;
891         case OP_RANDV2:
892                 for(i = 0; i < 3; i++)
893                 {
894                         if(OPA->_vector[i] < OPB->_vector[i])
895                         {
896                                 G_FLOAT(OFS_RETURN+i) = OPA->_vector[i]+((rand()&0x7fff)/((float)0x7fff)
897                                         *(OPB->_vector[i]-OPA->_vector[i]));
898                         }
899                         else
900                         {
901                                 G_FLOAT(OFS_RETURN+i) = OPB->_vector[i]+(rand()*(1.0f/RAND_MAX)
902                                         *(OPA->_vector[i]-OPB->_vector[i]));
903                         }
904                 }
905                 break;
906
907
908         case OP_SWITCH_F:
909         case OP_SWITCH_V:
910         case OP_SWITCH_S:
911         case OP_SWITCH_E:
912         case OP_SWITCH_FNC:
913                 swtch = OPA;
914                 swtchtype = st->op;
915                 RUNAWAYCHECK();
916                 st += (sofs)st->b - 1;  // offset the st++
917                 break;
918         case OP_CASE:
919                 switch(swtchtype)
920                 {
921                 case OP_SWITCH_F:
922                         if (swtch->_float == OPA->_float)
923                         {
924                                 RUNAWAYCHECK();
925                                 st += (sofs)st->b-1; // -1 to offset the s++
926                         }
927                         break;
928                 case OP_SWITCH_E:
929                 case OP_SWITCH_FNC:
930                         if (swtch->_int == OPA->_int)
931                         {
932                                 RUNAWAYCHECK();
933                                 st += (sofs)st->b-1; // -1 to offset the s++
934                         }
935                         break;
936                 case OP_SWITCH_S:
937                         if (swtch->_int == OPA->_int)
938                         {
939                                 RUNAWAYCHECK();
940                                 st += (sofs)st->b-1; // -1 to offset the s++
941                         }
942                         if ((!swtch->_int && PR_StringToNative(progfuncs, OPA->string)) || (!OPA->_int && PR_StringToNative(progfuncs, swtch->string))) //one is null (cannot be not both).
943                                 break;
944                         if (!strcmp(PR_StringToNative(progfuncs, swtch->string), PR_StringToNative(progfuncs, OPA->string)))
945                         {
946                                 RUNAWAYCHECK();
947                                 st += (sofs)st->b-1; // -1 to offset the s++
948                         }
949                         break;
950                 case OP_SWITCH_V:
951                         if (swtch->_vector[0] == OPA->_vector[0] && swtch->_vector[1] == OPA->_vector[1] && swtch->_vector[2] == OPA->_vector[2])
952                         {
953                                 RUNAWAYCHECK();
954                                 st += (sofs)st->b-1; // -1 to offset the s++
955                         }
956                         break;
957                 default:
958                         PR_RunError (progfuncs, "OP_CASE with bad/missing OP_SWITCH %i", swtchtype);
959                         break;
960                 }
961                 break;
962         case OP_CASERANGE:
963                 switch(swtchtype)
964                 {
965                 case OP_SWITCH_F:
966                         if (swtch->_float >= OPA->_float && swtch->_float <= OPB->_float)
967                         {
968                                 RUNAWAYCHECK();
969                                 st += (sofs)st->c-1; // -1 to offset the s++
970                         }
971                         break;
972                 default:
973                         PR_RunError (progfuncs, "OP_CASERANGE with bad/missing OP_SWITCH %i", swtchtype);
974                 }
975                 break;
976
977
978
979
980
981
982
983
984
985         case OP_BITAND_IF:
986                 OPC->_int = (OPA->_int & (int)OPB->_float);
987                 break;
988         case OP_BITOR_IF:
989                 OPC->_int = (OPA->_int | (int)OPB->_float);
990                 break;
991         case OP_BITAND_FI:
992                 OPC->_int = ((int)OPA->_float & OPB->_int);
993                 break;
994         case OP_BITOR_FI:
995                 OPC->_int = ((int)OPA->_float | OPB->_int);
996                 break;
997
998         case OP_MUL_IF:
999                 OPC->_float = (OPA->_int * OPB->_float);
1000                 break;
1001         case OP_MUL_FI:
1002                 OPC->_float = (OPA->_float * OPB->_int);
1003                 break;
1004
1005         case OP_MUL_VI:
1006                 OPC->_vector[0] = OPA->_vector[0] * OPB->_int;
1007                 OPC->_vector[1] = OPA->_vector[0] * OPB->_int;
1008                 OPC->_vector[2] = OPA->_vector[0] * OPB->_int;
1009                 break;
1010         case OP_MUL_IV:
1011                 OPC->_vector[0] = OPB->_int * OPA->_vector[0];
1012                 OPC->_vector[1] = OPB->_int * OPA->_vector[1];
1013                 OPC->_vector[2] = OPB->_int * OPA->_vector[2];
1014                 break;
1015
1016         case OP_DIV_IF:
1017                 OPC->_float = (OPA->_int / OPB->_float);
1018                 break;
1019         case OP_DIV_FI:
1020                 OPC->_float = (OPA->_float / OPB->_int);
1021                 break;
1022
1023         case OP_AND_I:
1024                 OPC->_int = (OPA->_int && OPB->_int);
1025                 break;
1026         case OP_OR_I:
1027                 OPC->_int = (OPA->_int || OPB->_int);
1028                 break;
1029
1030         case OP_AND_IF:
1031                 OPC->_int = (OPA->_int && OPB->_float);
1032                 break;
1033         case OP_OR_IF:
1034                 OPC->_int = (OPA->_int || OPB->_float);
1035                 break;
1036
1037         case OP_AND_FI:
1038                 OPC->_int = (OPA->_float && OPB->_int);
1039                 break;
1040         case OP_OR_FI:
1041                 OPC->_int = (OPA->_float || OPB->_int);
1042                 break;
1043
1044         case OP_NOT_I:
1045                 OPC->_int = !OPA->_int;
1046                 break;
1047
1048         case OP_NE_IF:
1049                 OPC->_int = (OPA->_int != OPB->_float);
1050                 break;
1051         case OP_NE_FI:
1052                 OPC->_int = (OPA->_float != OPB->_int);
1053                 break;
1054
1055         case OP_GSTOREP_I:
1056         case OP_GSTOREP_F:
1057         case OP_GSTOREP_ENT:
1058         case OP_GSTOREP_FLD:            // integers
1059         case OP_GSTOREP_S:
1060         case OP_GSTOREP_FNC:            // pointers
1061         case OP_GSTOREP_V:
1062         case OP_GADDRESS:
1063         case OP_GLOAD_I:
1064         case OP_GLOAD_F:
1065         case OP_GLOAD_FLD:
1066         case OP_GLOAD_ENT:
1067         case OP_GLOAD_S:
1068         case OP_GLOAD_FNC:
1069                 pr_xstatement = st-pr_statements;
1070                 PR_RunError(progfuncs, "Extra opcode not implemented\n");
1071                 break;
1072
1073         case OP_BOUNDCHECK:
1074                 if ((unsigned int)OPA->_int < (unsigned int)st->c || (unsigned int)OPA->_int >= (unsigned int)st->b)
1075                 {
1076                         pr_xstatement = st-pr_statements;
1077                         PR_RunError(progfuncs, "Progs boundcheck failed. Value is %i.", OPA->_int);
1078                 }
1079                 break;
1080 /*      case OP_PUSH:
1081                 OPC->_int = ENGINEPOINTER(&localstack[localstack_used+pr_spushed]);
1082                 pr_spushed += OPA->_int;
1083                 if (pr_spushed + localstack_used >= LOCALSTACK_SIZE)
1084                 {
1085                         pr_spushed = 0;
1086                         pr_xstatement = st-pr_statements;
1087                         PR_RunError(progfuncs, "Progs pushed too much");
1088                 }
1089                 break;
1090         case OP_POP:
1091                 pr_spushed -= OPA->_int;
1092                 if (pr_spushed < 0)
1093                 {
1094                         pr_spushed = 0;
1095                         pr_xstatement = st-pr_statements;
1096                         PR_RunError(progfuncs, "Progs poped more than it pushed");
1097                 }
1098                 break;
1099 */
1100         default:                                        
1101                 if (st->op & 0x8000)    //break point!
1102                 {
1103                         pr_xstatement = s = st-pr_statements;
1104
1105                         printf("Break point hit in %s.\n", pr_xfunction->s_name+progfuncs->stringtable);
1106                         if (pr_trace<1)
1107                                 pr_trace=1;     //this is what it's for
1108
1109                         s = ShowStep(progfuncs, s);
1110                         st = &pr_statements[s]; //let the user move execution
1111                         pr_xstatement = s = st-pr_statements;
1112
1113 #if 0   //fakeop stuff - not practical, the rest of the code is more optimised, st needs to point at the correct statement
1114                         memcpy(&fakeop, st, sizeof(dstatement_t));      //don't hit the new statement as a break point, cos it's probably the same one.
1115                         fakeop.op &= ~0x8000;
1116                         st = &fakeop;   //a little remapping...
1117 #else
1118                         st->op &= ~0x8000;      //just remove the breakpoint and go around again, but this time in the debugger.
1119 #endif
1120
1121                         goto reeval;    //reexecute
1122                 }
1123                 pr_xstatement = st-pr_statements;
1124                 PR_RunError (progfuncs, "Bad opcode %i", st->op);
1125         }
1126 }
1127
1128
1129 #undef cont
1130 #undef reeval
1131 #undef st
1132 #undef pr_statements
1133 #undef fakeop
1134 #undef dstatement_t
1135 #undef sofs
1136 #undef uofs
1137
1138 #undef ENGINEPOINTER
1139 #undef QCPOINTER
1140 #undef QCPOINTERM
1141