]> icculus.org git repositories - divverent/darkplaces.git/blob - pr_exec.c
added cl_explosions and cl_stainmaps cvars, which will be used soon...
[divverent/darkplaces.git] / pr_exec.c
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 typedef struct
25 {
26         int                             s;
27         dfunction_t             *f;
28 } prstack_t;
29
30 #define MAX_STACK_DEPTH         32
31 prstack_t       pr_stack[MAX_STACK_DEPTH];
32 int                     pr_depth = 0;
33
34 #define LOCALSTACK_SIZE         2048
35 int                     localstack[LOCALSTACK_SIZE];
36 int                     localstack_used;
37
38
39 qboolean        pr_trace;
40 dfunction_t     *pr_xfunction;
41 int                     pr_xstatement;
42
43
44 int             pr_argc;
45
46 char *pr_opnames[] =
47 {
48 "DONE",
49
50 "MUL_F",
51 "MUL_V", 
52 "MUL_FV",
53 "MUL_VF",
54  
55 "DIV",
56
57 "ADD_F",
58 "ADD_V", 
59   
60 "SUB_F",
61 "SUB_V",
62
63 "EQ_F",
64 "EQ_V",
65 "EQ_S", 
66 "EQ_E",
67 "EQ_FNC",
68  
69 "NE_F",
70 "NE_V", 
71 "NE_S",
72 "NE_E", 
73 "NE_FNC",
74  
75 "LE",
76 "GE",
77 "LT",
78 "GT", 
79
80 "INDIRECT",
81 "INDIRECT",
82 "INDIRECT", 
83 "INDIRECT", 
84 "INDIRECT",
85 "INDIRECT", 
86
87 "ADDRESS", 
88
89 "STORE_F",
90 "STORE_V",
91 "STORE_S",
92 "STORE_ENT",
93 "STORE_FLD",
94 "STORE_FNC",
95
96 "STOREP_F",
97 "STOREP_V",
98 "STOREP_S",
99 "STOREP_ENT",
100 "STOREP_FLD",
101 "STOREP_FNC",
102
103 "RETURN",
104   
105 "NOT_F",
106 "NOT_V",
107 "NOT_S", 
108 "NOT_ENT", 
109 "NOT_FNC", 
110   
111 "IF",
112 "IFNOT",
113   
114 "CALL0",
115 "CALL1",
116 "CALL2",
117 "CALL3",
118 "CALL4",
119 "CALL5",
120 "CALL6",
121 "CALL7",
122 "CALL8",
123   
124 "STATE",
125
126 "GOTO", 
127   
128 "AND",
129 "OR", 
130
131 "BITAND",
132 "BITOR"
133 };
134
135 char *PR_GlobalString (int ofs);
136 char *PR_GlobalStringNoContents (int ofs);
137
138
139 //=============================================================================
140
141 /*
142 =================
143 PR_PrintStatement
144 =================
145 */
146 void PR_PrintStatement (dstatement_t *s)
147 {
148         int             i;
149         
150         if ( (unsigned)s->op < sizeof(pr_opnames)/sizeof(pr_opnames[0]))
151         {
152                 Con_Printf ("%s ",  pr_opnames[s->op]);
153                 i = strlen(pr_opnames[s->op]);
154                 for ( ; i<10 ; i++)
155                         Con_Printf (" ");
156         }
157                 
158         if (s->op == OP_IF || s->op == OP_IFNOT)
159                 Con_Printf ("%sbranch %i",PR_GlobalString((unsigned short) s->a),s->b);
160         else if (s->op == OP_GOTO)
161         {
162                 Con_Printf ("branch %i",s->a);
163         }
164         else if ( (unsigned)(s->op - OP_STORE_F) < 6)
165         {
166                 Con_Printf ("%s",PR_GlobalString((unsigned short) s->a));
167                 Con_Printf ("%s", PR_GlobalStringNoContents((unsigned short) s->b));
168         }
169         else
170         {
171                 if (s->a)
172                         Con_Printf ("%s",PR_GlobalString((unsigned short) s->a));
173                 if (s->b)
174                         Con_Printf ("%s",PR_GlobalString((unsigned short) s->b));
175                 if (s->c)
176                         Con_Printf ("%s", PR_GlobalStringNoContents((unsigned short) s->c));
177         }
178         Con_Printf ("\n");
179 }
180
181 /*
182 ============
183 PR_StackTrace
184 ============
185 */
186 void PR_StackTrace (void)
187 {
188         dfunction_t     *f;
189         int                     i;
190
191         pr_stack[pr_depth].s = pr_xstatement;
192         pr_stack[pr_depth].f = pr_xfunction;
193         for (i = pr_depth;i > 0;i--)
194         {
195                 f = pr_stack[i].f;
196
197                 if (!f)
198                         Con_Printf ("<NULL FUNCTION>\n");
199                 else
200                         Con_Printf ("%12s : %s : statement %i\n", pr_strings + f->s_file, pr_strings + f->s_name, pr_stack[i].s - f->first_statement);
201         }
202 }
203
204
205 /*
206 ============
207 PR_Profile_f
208
209 ============
210 */
211 void PR_Profile_f (void)
212 {
213         dfunction_t     *f, *best;
214         int                     max;
215         int                     num;
216         int                     i;
217
218         num = 0;
219         do
220         {
221                 max = 0;
222                 best = NULL;
223                 for (i=0 ; i<progs->numfunctions ; i++)
224                 {
225                         f = &pr_functions[i];
226                         if (f->profile > max)
227                         {
228                                 max = f->profile;
229                                 best = f;
230                         }
231                 }
232                 if (best)
233                 {
234                         if (num < 10)
235                                 Con_Printf ("%7i %s\n", best->profile, pr_strings+best->s_name);
236                         num++;
237                         best->profile = 0;
238                 }
239         } while (best);
240 }
241
242
243 /*
244 ============
245 PR_RunError
246
247 Aborts the currently executing function
248 ============
249 */
250 void PR_RunError (char *error, ...)
251 {
252         int                     i;
253         va_list         argptr;
254         char            string[1024];
255
256         va_start (argptr,error);
257         vsprintf (string,error,argptr);
258         va_end (argptr);
259
260         if (pr_xfunction)
261         {
262                 for (i = -4;i <= 0;i++)
263                         if (pr_xstatement + i >= pr_xfunction->first_statement)
264                                 PR_PrintStatement (pr_statements + pr_xstatement + i);
265         }
266         else
267                 Con_Printf("null function executing??\n");
268         PR_StackTrace ();
269         Con_Printf ("%s\n", string);
270
271         pr_depth = 0;           // dump the stack so host_error can shutdown functions
272
273         Host_Error ("Program error");
274 }
275
276 /*
277 ============================================================================
278 PR_ExecuteProgram
279
280 The interpretation main loop
281 ============================================================================
282 */
283
284 /*
285 ====================
286 PR_EnterFunction
287
288 Returns the new program statement counter
289 ====================
290 */
291 int PR_EnterFunction (dfunction_t *f)
292 {
293         int             i, j, c, o;
294
295         if (!f)
296                 PR_RunError ("PR_EnterFunction: NULL function\n");
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                 Host_Error ("prog stack underflow");
339
340         if (!pr_xfunction)
341                 PR_RunError ("PR_LeaveFunction: NULL function\n");
342 // restore locals from the stack
343         c = pr_xfunction->locals;
344         localstack_used -= c;
345         if (localstack_used < 0)
346                 PR_RunError ("PR_ExecuteProgram: locals stack underflow\n");
347
348         for (i=0 ; i < c ; i++)
349                 ((int *)pr_globals)[pr_xfunction->parm_start + i] = localstack[localstack_used+i];
350
351 // up stack
352         pr_depth--;
353         pr_xfunction = pr_stack[pr_depth].f;
354         return pr_stack[pr_depth].s;
355 }
356
357 /*
358 ====================
359 PR_ExecuteProgram
360 ====================
361 */
362 // LordHavoc: optimized
363 #define OPA ((eval_t *)&pr_globals[(unsigned short) st->a])
364 #define OPB ((eval_t *)&pr_globals[(unsigned short) st->b])
365 #define OPC ((eval_t *)&pr_globals[(unsigned short) st->c])
366 extern cvar_t pr_boundscheck;
367 void PR_ExecuteProgram (func_t fnum, char *errormessage)
368 {
369         dstatement_t    *st;
370         dfunction_t     *f, *newf;
371         edict_t *ed;
372         eval_t  *ptr;
373         int             profile, startprofile, cachedpr_trace, exitdepth;
374
375         if (!fnum || fnum >= progs->numfunctions)
376         {
377                 if (pr_global_struct->self)
378                         ED_Print (PROG_TO_EDICT(pr_global_struct->self));
379                 Host_Error ("PR_ExecuteProgram: %s", errormessage);
380         }
381
382         f = &pr_functions[fnum];
383
384         pr_trace = false;
385
386         // we know we're done when pr_depth drops to this
387         exitdepth = pr_depth;
388
389 // make a stack frame
390         st = &pr_statements[PR_EnterFunction (f)];
391         startprofile = profile = 0;
392
393 chooseexecprogram:
394         cachedpr_trace = pr_trace;
395         if (pr_boundscheck.integer)
396         {
397 #define PRBOUNDSCHECK 1
398                 if (pr_trace)
399                 {
400 #define PRTRACE 1
401 #include "pr_execprogram.h"
402                 }
403                 else
404                 {
405 #undef PRTRACE
406 #include "pr_execprogram.h"
407                 }
408         }
409         else
410         {
411 #undef PRBOUNDSCHECK
412                 if (pr_trace)
413                 {
414 #define PRTRACE 1
415 #include "pr_execprogram.h"
416                 }
417                 else
418                 {
419 #undef PRTRACE
420 #include "pr_execprogram.h"
421                 }
422         }
423 }
424