diff options
Diffstat (limited to 'apps/plugins/sdl/progs/quake/pr_exec.c')
-rw-r--r-- | apps/plugins/sdl/progs/quake/pr_exec.c | 668 |
1 files changed, 668 insertions, 0 deletions
diff --git a/apps/plugins/sdl/progs/quake/pr_exec.c b/apps/plugins/sdl/progs/quake/pr_exec.c new file mode 100644 index 0000000000..4f2aa363e6 --- /dev/null +++ b/apps/plugins/sdl/progs/quake/pr_exec.c | |||
@@ -0,0 +1,668 @@ | |||
1 | /* | ||
2 | Copyright (C) 1996-1997 Id Software, Inc. | ||
3 | |||
4 | This program is free software; you can redistribute it and/or | ||
5 | modify it under the terms of the GNU General Public License | ||
6 | as published by the Free Software Foundation; either version 2 | ||
7 | of the License, or (at your option) any later version. | ||
8 | |||
9 | This program is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
12 | |||
13 | See the GNU General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with this program; if not, write to the Free Software | ||
17 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
18 | |||
19 | */ | ||
20 | |||
21 | #include "quakedef.h" | ||
22 | |||
23 | |||
24 | /* | ||
25 | |||
26 | */ | ||
27 | |||
28 | typedef struct | ||
29 | { | ||
30 | int s; | ||
31 | dfunction_t *f; | ||
32 | } prstack_t; | ||
33 | |||
34 | #define MAX_STACK_DEPTH 32 | ||
35 | prstack_t pr_stack[MAX_STACK_DEPTH]; | ||
36 | int pr_depth; | ||
37 | |||
38 | #define LOCALSTACK_SIZE 2048 | ||
39 | int localstack[LOCALSTACK_SIZE]; | ||
40 | int localstack_used; | ||
41 | |||
42 | |||
43 | qboolean pr_trace; | ||
44 | dfunction_t *pr_xfunction; | ||
45 | int pr_xstatement; | ||
46 | |||
47 | |||
48 | int pr_argc; | ||
49 | |||
50 | char *pr_opnames[] = | ||
51 | { | ||
52 | "DONE", | ||
53 | |||
54 | "MUL_F", | ||
55 | "MUL_V", | ||
56 | "MUL_FV", | ||
57 | "MUL_VF", | ||
58 | |||
59 | "DIV", | ||
60 | |||
61 | "ADD_F", | ||
62 | "ADD_V", | ||
63 | |||
64 | "SUB_F", | ||
65 | "SUB_V", | ||
66 | |||
67 | "EQ_F", | ||
68 | "EQ_V", | ||
69 | "EQ_S", | ||
70 | "EQ_E", | ||
71 | "EQ_FNC", | ||
72 | |||
73 | "NE_F", | ||
74 | "NE_V", | ||
75 | "NE_S", | ||
76 | "NE_E", | ||
77 | "NE_FNC", | ||
78 | |||
79 | "LE", | ||
80 | "GE", | ||
81 | "LT", | ||
82 | "GT", | ||
83 | |||
84 | "INDIRECT", | ||
85 | "INDIRECT", | ||
86 | "INDIRECT", | ||
87 | "INDIRECT", | ||
88 | "INDIRECT", | ||
89 | "INDIRECT", | ||
90 | |||
91 | "ADDRESS", | ||
92 | |||
93 | "STORE_F", | ||
94 | "STORE_V", | ||
95 | "STORE_S", | ||
96 | "STORE_ENT", | ||
97 | "STORE_FLD", | ||
98 | "STORE_FNC", | ||
99 | |||
100 | "STOREP_F", | ||
101 | "STOREP_V", | ||
102 | "STOREP_S", | ||
103 | "STOREP_ENT", | ||
104 | "STOREP_FLD", | ||
105 | "STOREP_FNC", | ||
106 | |||
107 | "RETURN", | ||
108 | |||
109 | "NOT_F", | ||
110 | "NOT_V", | ||
111 | "NOT_S", | ||
112 | "NOT_ENT", | ||
113 | "NOT_FNC", | ||
114 | |||
115 | "IF", | ||
116 | "IFNOT", | ||
117 | |||
118 | "CALL0", | ||
119 | "CALL1", | ||
120 | "CALL2", | ||
121 | "CALL3", | ||
122 | "CALL4", | ||
123 | "CALL5", | ||
124 | "CALL6", | ||
125 | "CALL7", | ||
126 | "CALL8", | ||
127 | |||
128 | "STATE", | ||
129 | |||
130 | "GOTO", | ||
131 | |||
132 | "AND", | ||
133 | "OR", | ||
134 | |||
135 | "BITAND", | ||
136 | "BITOR" | ||
137 | }; | ||
138 | |||
139 | char *PR_GlobalString (int ofs); | ||
140 | char *PR_GlobalStringNoContents (int ofs); | ||
141 | |||
142 | |||
143 | //============================================================================= | ||
144 | |||
145 | /* | ||
146 | ================= | ||
147 | PR_PrintStatement | ||
148 | ================= | ||
149 | */ | ||
150 | void PR_PrintStatement (dstatement_t *s) | ||
151 | { | ||
152 | int i; | ||
153 | |||
154 | if ( (unsigned)s->op < sizeof(pr_opnames)/sizeof(pr_opnames[0])) | ||
155 | { | ||
156 | Con_Printf ("%s ", pr_opnames[s->op]); | ||
157 | i = strlen(pr_opnames[s->op]); | ||
158 | for ( ; i<10 ; i++) | ||
159 | Con_Printf (" "); | ||
160 | } | ||
161 | |||
162 | if (s->op == OP_IF || s->op == OP_IFNOT) | ||
163 | Con_Printf ("%sbranch %i",PR_GlobalString(s->a),s->b); | ||
164 | else if (s->op == OP_GOTO) | ||
165 | { | ||
166 | Con_Printf ("branch %i",s->a); | ||
167 | } | ||
168 | else if ( (unsigned)(s->op - OP_STORE_F) < 6) | ||
169 | { | ||
170 | Con_Printf ("%s",PR_GlobalString(s->a)); | ||
171 | Con_Printf ("%s", PR_GlobalStringNoContents(s->b)); | ||
172 | } | ||
173 | else | ||
174 | { | ||
175 | if (s->a) | ||
176 | Con_Printf ("%s",PR_GlobalString(s->a)); | ||
177 | if (s->b) | ||
178 | Con_Printf ("%s",PR_GlobalString(s->b)); | ||
179 | if (s->c) | ||
180 | Con_Printf ("%s", PR_GlobalStringNoContents(s->c)); | ||
181 | } | ||
182 | Con_Printf ("\n"); | ||
183 | } | ||
184 | |||
185 | /* | ||
186 | ============ | ||
187 | PR_StackTrace | ||
188 | ============ | ||
189 | */ | ||
190 | void PR_StackTrace (void) | ||
191 | { | ||
192 | dfunction_t *f; | ||
193 | int i; | ||
194 | |||
195 | if (pr_depth == 0) | ||
196 | { | ||
197 | Con_Printf ("<NO STACK>\n"); | ||
198 | return; | ||
199 | } | ||
200 | |||
201 | pr_stack[pr_depth].f = pr_xfunction; | ||
202 | for (i=pr_depth ; i>=0 ; i--) | ||
203 | { | ||
204 | f = pr_stack[i].f; | ||
205 | |||
206 | if (!f) | ||
207 | { | ||
208 | Con_Printf ("<NO FUNCTION>\n"); | ||
209 | } | ||
210 | else | ||
211 | Con_Printf ("%12s : %s\n", pr_strings + f->s_file, pr_strings + f->s_name); | ||
212 | } | ||
213 | } | ||
214 | |||
215 | |||
216 | /* | ||
217 | ============ | ||
218 | PR_Profile_f | ||
219 | |||
220 | ============ | ||
221 | */ | ||
222 | void PR_Profile_f (void) | ||
223 | { | ||
224 | dfunction_t *f, *best; | ||
225 | int max; | ||
226 | int num; | ||
227 | int i; | ||
228 | |||
229 | num = 0; | ||
230 | do | ||
231 | { | ||
232 | max = 0; | ||
233 | best = NULL; | ||
234 | for (i=0 ; i<progs->numfunctions ; i++) | ||
235 | { | ||
236 | f = &pr_functions[i]; | ||
237 | if (f->profile > max) | ||
238 | { | ||
239 | max = f->profile; | ||
240 | best = f; | ||
241 | } | ||
242 | } | ||
243 | if (best) | ||
244 | { | ||
245 | if (num < 10) | ||
246 | Con_Printf ("%7i %s\n", best->profile, pr_strings+best->s_name); | ||
247 | num++; | ||
248 | best->profile = 0; | ||
249 | } | ||
250 | } while (best); | ||
251 | } | ||
252 | |||
253 | |||
254 | /* | ||
255 | ============ | ||
256 | PR_RunError | ||
257 | |||
258 | Aborts the currently executing function | ||
259 | ============ | ||
260 | */ | ||
261 | void PR_RunError (char *error, ...) | ||
262 | { | ||
263 | va_list argptr; | ||
264 | char string[1024]; | ||
265 | |||
266 | va_start (argptr,error); | ||
267 | vsprintf (string,error,argptr); | ||
268 | va_end (argptr); | ||
269 | |||
270 | PR_PrintStatement (pr_statements + pr_xstatement); | ||
271 | PR_StackTrace (); | ||
272 | Con_Printf ("%s\n", string); | ||
273 | |||
274 | pr_depth = 0; // dump the stack so host_error can shutdown functions | ||
275 | |||
276 | Host_Error ("Program error"); | ||
277 | } | ||
278 | |||
279 | /* | ||
280 | ============================================================================ | ||
281 | PR_ExecuteProgram | ||
282 | |||
283 | The interpretation main loop | ||
284 | ============================================================================ | ||
285 | */ | ||
286 | |||
287 | /* | ||
288 | ==================== | ||
289 | PR_EnterFunction | ||
290 | |||
291 | Returns the new program statement counter | ||
292 | ==================== | ||
293 | */ | ||
294 | int PR_EnterFunction (dfunction_t *f) | ||
295 | { | ||
296 | int i, j, c, o; | ||
297 | |||
298 | pr_stack[pr_depth].s = pr_xstatement; | ||
299 | pr_stack[pr_depth].f = pr_xfunction; | ||
300 | pr_depth++; | ||
301 | if (pr_depth >= MAX_STACK_DEPTH) | ||
302 | PR_RunError ("stack overflow"); | ||
303 | |||
304 | // save off any locals that the new function steps on | ||
305 | c = f->locals; | ||
306 | if (localstack_used + c > LOCALSTACK_SIZE) | ||
307 | PR_RunError ("PR_ExecuteProgram: locals stack overflow\n"); | ||
308 | |||
309 | for (i=0 ; i < c ; i++) | ||
310 | localstack[localstack_used+i] = ((int *)pr_globals)[f->parm_start + i]; | ||
311 | localstack_used += c; | ||
312 | |||
313 | // copy parameters | ||
314 | o = f->parm_start; | ||
315 | for (i=0 ; i<f->numparms ; i++) | ||
316 | { | ||
317 | for (j=0 ; j<f->parm_size[i] ; j++) | ||
318 | { | ||
319 | ((int *)pr_globals)[o] = ((int *)pr_globals)[OFS_PARM0+i*3+j]; | ||
320 | o++; | ||
321 | } | ||
322 | } | ||
323 | |||
324 | pr_xfunction = f; | ||
325 | return f->first_statement - 1; // offset the s++ | ||
326 | } | ||
327 | |||
328 | /* | ||
329 | ==================== | ||
330 | PR_LeaveFunction | ||
331 | ==================== | ||
332 | */ | ||
333 | int PR_LeaveFunction (void) | ||
334 | { | ||
335 | int i, c; | ||
336 | |||
337 | if (pr_depth <= 0) | ||
338 | Sys_Error ("prog stack underflow"); | ||
339 | |||
340 | // restore locals from the stack | ||
341 | c = pr_xfunction->locals; | ||
342 | localstack_used -= c; | ||
343 | if (localstack_used < 0) | ||
344 | PR_RunError ("PR_ExecuteProgram: locals stack underflow\n"); | ||
345 | |||
346 | for (i=0 ; i < c ; i++) | ||
347 | ((int *)pr_globals)[pr_xfunction->parm_start + i] = localstack[localstack_used+i]; | ||
348 | |||
349 | // up stack | ||
350 | pr_depth--; | ||
351 | pr_xfunction = pr_stack[pr_depth].f; | ||
352 | return pr_stack[pr_depth].s; | ||
353 | } | ||
354 | |||
355 | |||
356 | /* | ||
357 | ==================== | ||
358 | PR_ExecuteProgram | ||
359 | ==================== | ||
360 | */ | ||
361 | void PR_ExecuteProgram (func_t fnum) | ||
362 | { | ||
363 | eval_t *a, *b, *c; | ||
364 | int s; | ||
365 | dstatement_t *st; | ||
366 | dfunction_t *f, *newf; | ||
367 | int runaway; | ||
368 | int i; | ||
369 | edict_t *ed; | ||
370 | int exitdepth; | ||
371 | eval_t *ptr; | ||
372 | |||
373 | if (!fnum || fnum >= progs->numfunctions) | ||
374 | { | ||
375 | if (pr_global_struct->self) | ||
376 | ED_Print (PROG_TO_EDICT(pr_global_struct->self)); | ||
377 | Host_Error ("PR_ExecuteProgram: NULL function"); | ||
378 | } | ||
379 | |||
380 | f = &pr_functions[fnum]; | ||
381 | |||
382 | runaway = 100000; | ||
383 | pr_trace = false; | ||
384 | |||
385 | // make a stack frame | ||
386 | exitdepth = pr_depth; | ||
387 | |||
388 | s = PR_EnterFunction (f); | ||
389 | |||
390 | while (1) | ||
391 | { | ||
392 | s++; // next statement | ||
393 | |||
394 | st = &pr_statements[s]; | ||
395 | a = (eval_t *)&pr_globals[st->a]; | ||
396 | b = (eval_t *)&pr_globals[st->b]; | ||
397 | c = (eval_t *)&pr_globals[st->c]; | ||
398 | |||
399 | if (!--runaway) | ||
400 | PR_RunError ("runaway loop error"); | ||
401 | |||
402 | pr_xfunction->profile++; | ||
403 | pr_xstatement = s; | ||
404 | |||
405 | if (pr_trace) | ||
406 | PR_PrintStatement (st); | ||
407 | |||
408 | switch (st->op) | ||
409 | { | ||
410 | case OP_ADD_F: | ||
411 | c->_float = a->_float + b->_float; | ||
412 | break; | ||
413 | case OP_ADD_V: | ||
414 | c->vector[0] = a->vector[0] + b->vector[0]; | ||
415 | c->vector[1] = a->vector[1] + b->vector[1]; | ||
416 | c->vector[2] = a->vector[2] + b->vector[2]; | ||
417 | break; | ||
418 | |||
419 | case OP_SUB_F: | ||
420 | c->_float = a->_float - b->_float; | ||
421 | break; | ||
422 | case OP_SUB_V: | ||
423 | c->vector[0] = a->vector[0] - b->vector[0]; | ||
424 | c->vector[1] = a->vector[1] - b->vector[1]; | ||
425 | c->vector[2] = a->vector[2] - b->vector[2]; | ||
426 | break; | ||
427 | |||
428 | case OP_MUL_F: | ||
429 | c->_float = a->_float * b->_float; | ||
430 | break; | ||
431 | case OP_MUL_V: | ||
432 | c->_float = a->vector[0]*b->vector[0] | ||
433 | + a->vector[1]*b->vector[1] | ||
434 | + a->vector[2]*b->vector[2]; | ||
435 | break; | ||
436 | case OP_MUL_FV: | ||
437 | c->vector[0] = a->_float * b->vector[0]; | ||
438 | c->vector[1] = a->_float * b->vector[1]; | ||
439 | c->vector[2] = a->_float * b->vector[2]; | ||
440 | break; | ||
441 | case OP_MUL_VF: | ||
442 | c->vector[0] = b->_float * a->vector[0]; | ||
443 | c->vector[1] = b->_float * a->vector[1]; | ||
444 | c->vector[2] = b->_float * a->vector[2]; | ||
445 | break; | ||
446 | |||
447 | case OP_DIV_F: | ||
448 | c->_float = a->_float / b->_float; | ||
449 | break; | ||
450 | |||
451 | case OP_BITAND: | ||
452 | c->_float = (int)a->_float & (int)b->_float; | ||
453 | break; | ||
454 | |||
455 | case OP_BITOR: | ||
456 | c->_float = (int)a->_float | (int)b->_float; | ||
457 | break; | ||
458 | |||
459 | |||
460 | case OP_GE: | ||
461 | c->_float = a->_float >= b->_float; | ||
462 | break; | ||
463 | case OP_LE: | ||
464 | c->_float = a->_float <= b->_float; | ||
465 | break; | ||
466 | case OP_GT: | ||
467 | c->_float = a->_float > b->_float; | ||
468 | break; | ||
469 | case OP_LT: | ||
470 | c->_float = a->_float < b->_float; | ||
471 | break; | ||
472 | case OP_AND: | ||
473 | c->_float = a->_float && b->_float; | ||
474 | break; | ||
475 | case OP_OR: | ||
476 | c->_float = a->_float || b->_float; | ||
477 | break; | ||
478 | |||
479 | case OP_NOT_F: | ||
480 | c->_float = !a->_float; | ||
481 | break; | ||
482 | case OP_NOT_V: | ||
483 | c->_float = !a->vector[0] && !a->vector[1] && !a->vector[2]; | ||
484 | break; | ||
485 | case OP_NOT_S: | ||
486 | c->_float = !a->string || !pr_strings[a->string]; | ||
487 | break; | ||
488 | case OP_NOT_FNC: | ||
489 | c->_float = !a->function; | ||
490 | break; | ||
491 | case OP_NOT_ENT: | ||
492 | c->_float = (PROG_TO_EDICT(a->edict) == sv.edicts); | ||
493 | break; | ||
494 | |||
495 | case OP_EQ_F: | ||
496 | c->_float = a->_float == b->_float; | ||
497 | break; | ||
498 | case OP_EQ_V: | ||
499 | c->_float = (a->vector[0] == b->vector[0]) && | ||
500 | (a->vector[1] == b->vector[1]) && | ||
501 | (a->vector[2] == b->vector[2]); | ||
502 | break; | ||
503 | case OP_EQ_S: | ||
504 | c->_float = !strcmp(pr_strings+a->string,pr_strings+b->string); | ||
505 | break; | ||
506 | case OP_EQ_E: | ||
507 | c->_float = a->_int == b->_int; | ||
508 | break; | ||
509 | case OP_EQ_FNC: | ||
510 | c->_float = a->function == b->function; | ||
511 | break; | ||
512 | |||
513 | |||
514 | case OP_NE_F: | ||
515 | c->_float = a->_float != b->_float; | ||
516 | break; | ||
517 | case OP_NE_V: | ||
518 | c->_float = (a->vector[0] != b->vector[0]) || | ||
519 | (a->vector[1] != b->vector[1]) || | ||
520 | (a->vector[2] != b->vector[2]); | ||
521 | break; | ||
522 | case OP_NE_S: | ||
523 | c->_float = strcmp(pr_strings+a->string,pr_strings+b->string); | ||
524 | break; | ||
525 | case OP_NE_E: | ||
526 | c->_float = a->_int != b->_int; | ||
527 | break; | ||
528 | case OP_NE_FNC: | ||
529 | c->_float = a->function != b->function; | ||
530 | break; | ||
531 | |||
532 | //================== | ||
533 | case OP_STORE_F: | ||
534 | case OP_STORE_ENT: | ||
535 | case OP_STORE_FLD: // integers | ||
536 | case OP_STORE_S: | ||
537 | case OP_STORE_FNC: // pointers | ||
538 | b->_int = a->_int; | ||
539 | break; | ||
540 | case OP_STORE_V: | ||
541 | b->vector[0] = a->vector[0]; | ||
542 | b->vector[1] = a->vector[1]; | ||
543 | b->vector[2] = a->vector[2]; | ||
544 | break; | ||
545 | |||
546 | case OP_STOREP_F: | ||
547 | case OP_STOREP_ENT: | ||
548 | case OP_STOREP_FLD: // integers | ||
549 | case OP_STOREP_S: | ||
550 | case OP_STOREP_FNC: // pointers | ||
551 | ptr = (eval_t *)((byte *)sv.edicts + b->_int); | ||
552 | ptr->_int = a->_int; | ||
553 | break; | ||
554 | case OP_STOREP_V: | ||
555 | ptr = (eval_t *)((byte *)sv.edicts + b->_int); | ||
556 | ptr->vector[0] = a->vector[0]; | ||
557 | ptr->vector[1] = a->vector[1]; | ||
558 | ptr->vector[2] = a->vector[2]; | ||
559 | break; | ||
560 | |||
561 | case OP_ADDRESS: | ||
562 | ed = PROG_TO_EDICT(a->edict); | ||
563 | #ifdef PARANOID | ||
564 | NUM_FOR_EDICT(ed); // make sure it's in range | ||
565 | #endif | ||
566 | if (ed == (edict_t *)sv.edicts && sv.state == ss_active) | ||
567 | PR_RunError ("assignment to world entity"); | ||
568 | c->_int = (byte *)((int *)&ed->v + b->_int) - (byte *)sv.edicts; | ||
569 | break; | ||
570 | |||
571 | case OP_LOAD_F: | ||
572 | case OP_LOAD_FLD: | ||
573 | case OP_LOAD_ENT: | ||
574 | case OP_LOAD_S: | ||
575 | case OP_LOAD_FNC: | ||
576 | ed = PROG_TO_EDICT(a->edict); | ||
577 | #ifdef PARANOID | ||
578 | NUM_FOR_EDICT(ed); // make sure it's in range | ||
579 | #endif | ||
580 | a = (eval_t *)((int *)&ed->v + b->_int); | ||
581 | c->_int = a->_int; | ||
582 | break; | ||
583 | |||
584 | case OP_LOAD_V: | ||
585 | ed = PROG_TO_EDICT(a->edict); | ||
586 | #ifdef PARANOID | ||
587 | NUM_FOR_EDICT(ed); // make sure it's in range | ||
588 | #endif | ||
589 | a = (eval_t *)((int *)&ed->v + b->_int); | ||
590 | c->vector[0] = a->vector[0]; | ||
591 | c->vector[1] = a->vector[1]; | ||
592 | c->vector[2] = a->vector[2]; | ||
593 | break; | ||
594 | |||
595 | //================== | ||
596 | |||
597 | case OP_IFNOT: | ||
598 | if (!a->_int) | ||
599 | s += st->b - 1; // offset the s++ | ||
600 | break; | ||
601 | |||
602 | case OP_IF: | ||
603 | if (a->_int) | ||
604 | s += st->b - 1; // offset the s++ | ||
605 | break; | ||
606 | |||
607 | case OP_GOTO: | ||
608 | s += st->a - 1; // offset the s++ | ||
609 | break; | ||
610 | |||
611 | case OP_CALL0: | ||
612 | case OP_CALL1: | ||
613 | case OP_CALL2: | ||
614 | case OP_CALL3: | ||
615 | case OP_CALL4: | ||
616 | case OP_CALL5: | ||
617 | case OP_CALL6: | ||
618 | case OP_CALL7: | ||
619 | case OP_CALL8: | ||
620 | pr_argc = st->op - OP_CALL0; | ||
621 | if (!a->function) | ||
622 | PR_RunError ("NULL function"); | ||
623 | |||
624 | newf = &pr_functions[a->function]; | ||
625 | |||
626 | if (newf->first_statement < 0) | ||
627 | { // negative statements are built in functions | ||
628 | i = -newf->first_statement; | ||
629 | if (i >= pr_numbuiltins) | ||
630 | PR_RunError ("Bad builtin call number"); | ||
631 | pr_builtins[i] (); | ||
632 | break; | ||
633 | } | ||
634 | |||
635 | s = PR_EnterFunction (newf); | ||
636 | break; | ||
637 | |||
638 | case OP_DONE: | ||
639 | case OP_RETURN: | ||
640 | pr_globals[OFS_RETURN] = pr_globals[st->a]; | ||
641 | pr_globals[OFS_RETURN+1] = pr_globals[st->a+1]; | ||
642 | pr_globals[OFS_RETURN+2] = pr_globals[st->a+2]; | ||
643 | |||
644 | s = PR_LeaveFunction (); | ||
645 | if (pr_depth == exitdepth) | ||
646 | return; // all done | ||
647 | break; | ||
648 | |||
649 | case OP_STATE: | ||
650 | ed = PROG_TO_EDICT(pr_global_struct->self); | ||
651 | #ifdef FPS_20 | ||
652 | ed->v.nextthink = pr_global_struct->time + 0.05; | ||
653 | #else | ||
654 | ed->v.nextthink = pr_global_struct->time + 0.1; | ||
655 | #endif | ||
656 | if (a->_float != ed->v.frame) | ||
657 | { | ||
658 | ed->v.frame = a->_float; | ||
659 | } | ||
660 | ed->v.think = b->function; | ||
661 | break; | ||
662 | |||
663 | default: | ||
664 | PR_RunError ("Bad opcode %i", st->op); | ||
665 | } | ||
666 | } | ||
667 | |||
668 | } | ||