Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5131 clevermous 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 ("\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 ("\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 ; inumfunctions ; 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 ; inumparms ; i++)
316
	{
317
		for (j=0 ; jparm_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
}