]> icculus.org git repositories - divverent/darkplaces.git/blob - prvm_edict.c
reorganized SV_FlyMove to merge the two paths (new simple/old complex approaches)
[divverent/darkplaces.git] / prvm_edict.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 // AK new vm 
21
22 #include "quakedef.h"
23
24 prvm_prog_t *prog;
25
26 static prvm_prog_t prog_list[PRVM_MAXPROGS];
27
28 int             prvm_type_size[8] = {1,sizeof(string_t)/4,1,3,1,1,sizeof(func_t)/4,sizeof(void *)/4};
29
30 ddef_t *PRVM_ED_FieldAtOfs(int ofs);
31 qboolean PRVM_ED_ParseEpair(prvm_edict_t *ent, ddef_t *key, const char *s);
32
33 // LordHavoc: optional runtime bounds checking (speed drain, but worth it for security, on by default - breaks most QCCX features (used by CRMod and others))
34 cvar_t  prvm_boundscheck = {0, "prvm_boundscheck", "1"};
35 // LordHavoc: prints every opcode as it executes - warning: this is significant spew
36 cvar_t  prvm_traceqc = {0, "prvm_traceqc", "0"};
37
38 ddef_t *PRVM_ED_FindField (const char *name);
39 mfunction_t *PRVM_ED_FindFunction (const char *name);
40
41 //============================================================================
42 // mempool handling
43
44 /*
45 ===============
46 PRVM_MEM_Alloc
47 ===============
48 */
49 void PRVM_MEM_Alloc()
50 {
51         int i;
52
53         // reserve space for the null entity aka world
54         // check bound of max_edicts
55         prog->max_edicts = bound(1, prog->max_edicts, prog->limit_edicts);
56         prog->num_edicts = bound(1, prog->num_edicts, prog->max_edicts);        
57
58         // edictprivate_size has to be min as big prvm_edict_private_t
59         prog->edictprivate_size = max(prog->edictprivate_size,(int)sizeof(prvm_edict_private_t)); 
60
61         // alloc edicts
62         prog->edicts = Mem_Alloc(prog->edicts_mempool,prog->limit_edicts * sizeof(prvm_edict_t));
63         
64         // alloc edict private space
65         prog->edictprivate = Mem_Alloc(prog->edicts_mempool, prog->max_edicts * prog->edictprivate_size);
66         
67         // alloc edict fields
68         prog->edictsfields = Mem_Alloc(prog->edicts_mempool, prog->max_edicts * prog->edict_size);
69
70         // set edict pointers
71         for(i = 0; i < prog->max_edicts; i++)
72         {
73                 prog->edicts[i].e = (prvm_edict_private_t *)((qbyte  *)prog->edictprivate + i * prog->edictprivate_size);
74                 prog->edicts[i].v = (void*)((qbyte *)prog->edictsfields + i * prog->edict_size);
75         }
76 }
77
78 /*
79 ===============
80 PRVM_MEM_IncreaseEdicts
81 ===============
82 */
83 void PRVM_MEM_IncreaseEdicts()
84 {
85         int             i;
86         int             oldmaxedicts = prog->max_edicts; 
87         void    *oldedictsfields = prog->edictsfields;
88         void    *oldedictprivate = prog->edictprivate;
89         
90         if(prog->max_edicts >= prog->limit_edicts)
91                 return;
92         
93         PRVM_GCALL(begin_increase_edicts)();
94
95         // increase edicts
96         prog->max_edicts = min(prog->max_edicts + 256, prog->limit_edicts);
97
98         prog->edictsfields = Mem_Alloc(prog->edicts_mempool, prog->max_edicts * prog->edict_size);
99         prog->edictprivate = Mem_Alloc(prog->edicts_mempool, prog->max_edicts * prog->edictprivate_size);
100
101         memcpy(prog->edictsfields, oldedictsfields, oldmaxedicts * prog->edict_size);
102         memcpy(prog->edictprivate, oldedictprivate, oldmaxedicts * prog->edictprivate_size);
103
104         //set e and v pointers
105         for(i = 0; i < prog->max_edicts; i++)
106         {
107                 prog->edicts[i].e = (prvm_edict_private_t *)((qbyte  *)prog->edictprivate + i * prog->edictprivate_size);
108                 prog->edicts[i].v = (void*)((qbyte *)prog->edictsfields + i * prog->edict_size);
109         }
110
111         PRVM_GCALL(end_increase_edicts)();
112
113         Mem_Free(oldedictsfields);
114         Mem_Free(oldedictprivate);
115 }
116
117 //============================================================================
118 // normal prvm
119
120 int PRVM_ED_FindFieldOffset(const char *field)
121 {
122         ddef_t *d;
123         d = PRVM_ED_FindField(field);
124         if (!d)
125                 return 0;
126         return d->ofs*4;
127 }
128
129 qboolean PRVM_ProgLoaded(int prognr)
130 {
131         if(prognr < 0 || prognr >= PRVM_MAXPROGS)
132                 return FALSE;
133
134         return (prog_list[prognr].loaded ? TRUE : FALSE);
135 }
136
137 /*
138 =================
139 PRVM_SetProgFromString
140 =================
141 */
142 // perhaps add a return value when the str doesnt exist
143 qboolean PRVM_SetProgFromString(const char *str)
144 {
145         int i = 0;
146         for(; i < PRVM_MAXPROGS ; i++)
147                 if(prog_list[i].name && !strcmp(prog_list[i].name,str))
148                 {
149                         if(prog_list[i].loaded)
150                         {
151                                 prog = &prog_list[i];
152                                 return TRUE;
153                         }
154                         else
155                         {
156                                 Con_Printf("%s not loaded !\n",PRVM_NAME);
157                                 return FALSE;
158                         }
159                 }
160
161         Con_Printf("Invalid program name %s !\n", str);
162         return FALSE;
163 }
164
165 /*
166 =================
167 PRVM_SetProg
168 =================
169 */
170 void PRVM_SetProg(int prognr)
171 {
172         if(prognr && prognr < PRVM_MAXPROGS)
173         {       
174                 if(prog_list[prognr].loaded)
175                         prog = &prog_list[prognr];
176                 else
177                         PRVM_ERROR("%i(%s) not loaded !\n", prognr, PRVM_NAME);
178                 return;
179         }
180         PRVM_ERROR("Invalid program number %i\n", prognr);
181 }
182
183 /*
184 =================
185 PRVM_ED_ClearEdict
186
187 Sets everything to NULL
188 =================
189 */
190 void PRVM_ED_ClearEdict (prvm_edict_t *e)
191 {
192         int num;
193         memset (e->v, 0, prog->progs->entityfields * 4);
194         e->e->free = false;
195         // LordHavoc: for consistency set these here
196         num = PRVM_NUM_FOR_EDICT(e) - 1;
197
198         // AK: Let the init_edict function determine if something needs to be initialized
199         PRVM_GCALL(init_edict)(num);    
200 }
201
202 /*
203 =================
204 PRVM_ED_Alloc
205
206 Either finds a free edict, or allocates a new one.
207 Try to avoid reusing an entity that was recently freed, because it
208 can cause the client to think the entity morphed into something else
209 instead of being removed and recreated, which can cause interpolated
210 angles and bad trails.
211 =================
212 */
213 prvm_edict_t *PRVM_ED_Alloc (void)
214 {
215         int                     i;
216         prvm_edict_t            *e;
217
218         // the client qc dont need maxclients
219         // thus it doesnt need to use svs.maxclients
220         // AK:  changed i=svs.maxclients+1
221         // AK:  changed so the edict 0 wont spawn -> used as reserved/world entity
222         //              although the menu/client has no world
223         for (i = 1;i < prog->num_edicts;i++)
224         {
225                 e = PRVM_EDICT_NUM(i);
226                 // the first couple seconds of server time can involve a lot of
227                 // freeing and allocating, so relax the replacement policy
228                 if (e->e->free && ( e->e->freetime < 2 || (*prog->time - e->e->freetime) > 0.5 ) )
229                 {
230                         PRVM_ED_ClearEdict (e);
231                         return e;
232                 }
233         }
234
235         if (i == MAX_EDICTS)
236                 PRVM_ERROR ("%s: PRVM_ED_Alloc: no free edicts",PRVM_NAME);
237
238         prog->num_edicts++;
239         if (prog->num_edicts >= prog->max_edicts)
240                 PRVM_MEM_IncreaseEdicts();
241
242         e = PRVM_EDICT_NUM(i);
243         PRVM_ED_ClearEdict (e);
244
245         return e;
246 }
247
248 /*
249 =================
250 PRVM_ED_Free
251
252 Marks the edict as free
253 FIXME: walk all entities and NULL out references to this entity
254 =================
255 */
256 void PRVM_ED_Free (prvm_edict_t *ed)
257 {
258         // dont delete the null entity (world)
259         if(PRVM_NUM_FOR_EDICT(ed) == 0)
260                 return;
261
262         PRVM_GCALL(free_edict)(ed);
263
264         ed->e->free = true;
265         ed->e->freetime = *prog->time;
266 }
267
268 //===========================================================================
269
270 /*
271 ============
272 PRVM_ED_GlobalAtOfs
273 ============
274 */
275 ddef_t *PRVM_ED_GlobalAtOfs (int ofs)
276 {
277         ddef_t          *def;
278         int                     i;
279
280         for (i=0 ; i<prog->progs->numglobaldefs ; i++)
281         {
282                 def = &prog->globaldefs[i];
283                 if (def->ofs == ofs)
284                         return def;
285         }
286         return NULL;
287 }
288
289 /*
290 ============
291 PRVM_ED_FieldAtOfs
292 ============
293 */
294 ddef_t *PRVM_ED_FieldAtOfs (int ofs)
295 {
296         ddef_t          *def;
297         int                     i;
298
299         for (i=0 ; i<prog->progs->numfielddefs ; i++)
300         {
301                 def = &prog->fielddefs[i];
302                 if (def->ofs == ofs)
303                         return def;
304         }
305         return NULL;
306 }
307
308 /*
309 ============
310 PRVM_ED_FindField
311 ============
312 */
313 ddef_t *PRVM_ED_FindField (const char *name)
314 {
315         ddef_t *def;
316         int i;
317
318         for (i=0 ; i<prog->progs->numfielddefs ; i++)
319         {
320                 def = &prog->fielddefs[i];
321                 if (!strcmp(PRVM_GetString(def->s_name), name))
322                         return def;
323         }
324         return NULL;
325 }
326
327 /*
328 ============
329 PRVM_ED_FindGlobal
330 ============
331 */
332 ddef_t *PRVM_ED_FindGlobal (const char *name)
333 {
334         ddef_t *def;
335         int i;
336
337         for (i=0 ; i<prog->progs->numglobaldefs ; i++)
338         {
339                 def = &prog->globaldefs[i];
340                 if (!strcmp(PRVM_GetString(def->s_name), name))
341                         return def;
342         }
343         return NULL;
344 }
345
346
347 /*
348 ============
349 PRVM_ED_FindFunction
350 ============
351 */
352 mfunction_t *PRVM_ED_FindFunction (const char *name)
353 {
354         mfunction_t             *func;
355         int                             i;
356
357         for (i=0 ; i<prog->progs->numfunctions ; i++)
358         {
359                 func = &prog->functions[i];
360                 if (!strcmp(PRVM_GetString(func->s_name), name))
361                         return func;
362         }
363         return NULL;
364 }
365
366
367 /*
368 ============
369 PRVM_ValueString
370
371 Returns a string describing *data in a type specific manner
372 =============
373 */
374 char *PRVM_ValueString (etype_t type, prvm_eval_t *val)
375 {
376         static char line[1024]; // LordHavoc: enlarged a bit (was 256)
377         ddef_t *def;
378         mfunction_t *f;
379         int n;
380
381         type &= ~DEF_SAVEGLOBAL;
382
383         switch (type)
384         {
385         case ev_string:
386                 sprintf (line, "%s", PRVM_GetString(val->string));
387                 break;
388         case ev_entity:
389                 n = val->edict;
390                 if (n < 0 || n >= MAX_EDICTS)
391                         sprintf (line, "entity %i (invalid!)", n);
392                 else
393                         sprintf (line, "entity %i", n);
394                 break;
395         case ev_function:
396                 f = prog->functions + val->function;
397                 sprintf (line, "%s()", PRVM_GetString(f->s_name));
398                 break;
399         case ev_field:
400                 def = PRVM_ED_FieldAtOfs ( val->_int );
401                 sprintf (line, ".%s", PRVM_GetString(def->s_name));
402                 break;
403         case ev_void:
404                 sprintf (line, "void");
405                 break;
406         case ev_float:
407                 // LordHavoc: changed from %5.1f to %10.4f
408                 sprintf (line, "%10.4f", val->_float);
409                 break;
410         case ev_vector:
411                 // LordHavoc: changed from %5.1f to %10.4f
412                 sprintf (line, "'%10.4f %10.4f %10.4f'", val->vector[0], val->vector[1], val->vector[2]);
413                 break;
414         case ev_pointer:
415                 sprintf (line, "pointer");
416                 break;
417         default:
418                 sprintf (line, "bad type %i", type);
419                 break;
420         }
421
422         return line;
423 }
424
425 /*
426 ============
427 PRVM_UglyValueString
428
429 Returns a string describing *data in a type specific manner
430 Easier to parse than PR_ValueString
431 =============
432 */
433 char *PRVM_UglyValueString (etype_t type, prvm_eval_t *val)
434 {
435         static char line[4096];
436         int i;
437         char *s;
438         ddef_t *def;
439         mfunction_t *f;
440         
441         type &= ~DEF_SAVEGLOBAL;
442         
443         switch (type)
444         {
445         case ev_string:
446                 // Parse the string a bit to turn special characters
447                 // (like newline, specifically) into escape codes,
448                 // this fixes saving games from various mods
449                 s = PRVM_GetString (val->string);
450                 for (i = 0;i < (int)sizeof(line) - 2 && *s;)
451                 {
452                         if (*s == '\n')
453                         {
454                                 line[i++] = '\\';
455                                 line[i++] = 'n';
456                         }
457                         else if (*s == '\r')
458                         {
459                                 line[i++] = '\\';
460                                 line[i++] = 'r';
461                         }
462                         else
463                                 line[i++] = *s;
464                         s++;
465                 }
466                 line[i] = '\0';
467                 break;
468         case ev_entity:
469                 snprintf (line, sizeof (line), "%i", PRVM_NUM_FOR_EDICT(PRVM_PROG_TO_EDICT(val->edict)));
470                 break;
471         case ev_function:
472                 f = pr_functions + val->function;
473                 snprintf (line, sizeof (line), "%s", PRVM_GetString(f->s_name));
474                 break;
475         case ev_field:
476                 def = PRVM_ED_FieldAtOfs ( val->_int );
477                 snprintf (line, sizeof (line), ".%s", PRVM_GetString(def->s_name));
478                 break;
479         case ev_void:
480                 snprintf (line, sizeof (line), "void");
481                 break;
482         case ev_float:
483                 snprintf (line, sizeof (line), "%f", val->_float);
484                 break;
485         case ev_vector:
486                 snprintf (line, sizeof (line), "%f %f %f", val->vector[0], val->vector[1], val->vector[2]);
487                 break;
488         default:
489                 snprintf (line, sizeof (line), "bad type %i", type);
490                 break;
491         }
492         
493         return line;
494 }
495
496 /*
497 ============
498 PRVM_GlobalString
499
500 Returns a string with a description and the contents of a global,
501 padded to 20 field width
502 ============
503 */
504 char *PRVM_GlobalString (int ofs)
505 {
506         char    *s;
507         int             i;
508         ddef_t  *def;
509         void    *val;
510         static char     line[128];
511
512         val = (void *)&prog->globals[ofs];
513         def = PRVM_ED_GlobalAtOfs(ofs);
514         if (!def)
515                 sprintf (line,"%i(?)", ofs);
516         else
517         {
518                 s = PRVM_ValueString (def->type, val);
519                 sprintf (line,"%i(%s)%s", ofs, PRVM_GetString(def->s_name), s);
520         }
521
522         i = strlen(line);
523         for ( ; i<20 ; i++)
524                 strcat (line," ");
525         strcat (line," ");
526
527         return line;
528 }
529
530 char *PRVM_GlobalStringNoContents (int ofs)
531 {
532         int             i;
533         ddef_t  *def;
534         static char     line[128];
535
536         def = PRVM_ED_GlobalAtOfs(ofs);
537         if (!def)
538                 sprintf (line,"%i(?)", ofs);
539         else
540                 sprintf (line,"%i(%s)", ofs, PRVM_GetString(def->s_name));
541
542         i = strlen(line);
543         for ( ; i<20 ; i++)
544                 strcat (line," ");
545         strcat (line," ");
546
547         return line;
548 }
549
550
551 /*
552 =============
553 PRVM_ED_Print
554
555 For debugging
556 =============
557 */
558 // LordHavoc: optimized this to print out much more quickly (tempstring)
559 // LordHavoc: changed to print out every 4096 characters (incase there are a lot of fields to print)
560 void PRVM_ED_Print (prvm_edict_t *ed)
561 {
562         int             l;
563         ddef_t  *d;
564         int             *v;
565         int             i, j;
566         char    *name;
567         int             type;
568         char    tempstring[8192], tempstring2[260]; // temporary string buffers
569
570         if (ed->e->free)
571         {
572                 Con_Printf ("%s: FREE\n",PRVM_NAME);
573                 return;
574         }
575
576         tempstring[0] = 0;
577         sprintf(tempstring, "\n%s EDICT %i:\n", PRVM_NAME, PRVM_NUM_FOR_EDICT(ed));
578         for (i=1 ; i<prog->progs->numfielddefs ; i++)
579         {
580                 d = &prog->fielddefs[i];
581                 name = PRVM_GetString(d->s_name);
582                 if (name[strlen(name)-2] == '_')
583                         continue;       // skip _x, _y, _z vars
584
585                 v = (int *)((char *)ed->v + d->ofs*4);
586
587         // if the value is still all 0, skip the field
588                 type = d->type & ~DEF_SAVEGLOBAL;
589
590                 for (j=0 ; j<prvm_type_size[type] ; j++)
591                         if (v[j])
592                                 break;
593                 if (j == prvm_type_size[type])
594                         continue;
595
596                 if (strlen(name) > 256)
597                 {
598                         strncpy(tempstring2, name, 256);
599                         tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
600                         tempstring2[259] = 0;
601                         name = tempstring2;
602                 }
603                 strcat(tempstring, name);
604                 for (l = strlen(name);l < 14;l++)
605                         strcat(tempstring, " ");
606                 strcat(tempstring, " ");
607
608                 name = PRVM_ValueString(d->type, (prvm_eval_t *)v);
609                 if (strlen(name) > 256)
610                 {
611                         strncpy(tempstring2, name, 256);
612                         tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
613                         tempstring2[259] = 0;
614                         name = tempstring2;
615                 }
616                 strcat(tempstring, name);
617                 strcat(tempstring, "\n");
618                 if (strlen(tempstring) >= 4096)
619                 {
620                         Con_Printf("%s", tempstring);
621                         tempstring[0] = 0;
622                 }
623         }
624         if (tempstring[0])
625                 Con_Printf("%s", tempstring);
626 }
627
628 /*
629 =============
630 PRVM_ED_Write
631
632 For savegames
633 =============
634 */
635 void PRVM_ED_Write (qfile_t *f, prvm_edict_t *ed)
636 {
637         ddef_t  *d;
638         int             *v;
639         int             i, j;
640         char    *name;
641         int             type;
642
643         FS_Printf (f, "{\n");
644
645         if (ed->e->free)
646         {
647                 FS_Printf (f, "}\n");
648                 return;
649         }
650
651         for (i=1 ; i<prog->progs->numfielddefs ; i++)
652         {
653                 d = &prog->fielddefs[i];
654                 name = PRVM_GetString(d->s_name);
655                 if (name[strlen(name)-2] == '_')
656                         continue;       // skip _x, _y, _z vars
657
658                 v = (int *)((char *)ed->v + d->ofs*4);
659
660         // if the value is still all 0, skip the field
661                 type = d->type & ~DEF_SAVEGLOBAL;
662                 for (j=0 ; j<prvm_type_size[type] ; j++)
663                         if (v[j])
664                                 break;
665                 if (j == prvm_type_size[type])
666                         continue;
667
668                 FS_Printf (f,"\"%s\" ",name);
669                 FS_Printf (f,"\"%s\"\n", PRVM_UglyValueString(d->type, (prvm_eval_t *)v));
670         }
671
672         FS_Printf (f, "}\n");
673 }
674
675 void PRVM_ED_PrintNum (int ent)
676 {
677         PRVM_ED_Print (PRVM_EDICT_NUM(ent));
678 }
679
680 /*
681 =============
682 PRVM_ED_PrintEdicts_f
683
684 For debugging, prints all the entities in the current server
685 =============
686 */
687 void PRVM_ED_PrintEdicts_f (void)
688 {
689         int             i;
690
691         if(Cmd_Argc() != 2)
692         {
693                 Con_Printf("prvm_edicts <program name>\n");
694                 return;
695         }
696         
697         PRVM_Begin;
698         if(!PRVM_SetProgFromString(Cmd_Argv(1)))
699                 return;
700
701         Con_Printf ("%s: %i entities\n", PRVM_NAME, prog->num_edicts);
702         for (i=0 ; i<prog->num_edicts ; i++)
703                 PRVM_ED_PrintNum (i);
704
705         PRVM_End;
706 }
707
708 /*
709 =============
710 PRVM_ED_PrintEdict_f
711
712 For debugging, prints a single edict
713 =============
714 */
715 void PRVM_ED_PrintEdict_f (void)
716 {
717         int             i;
718
719         if(Cmd_Argc() != 3)
720         {
721                 Con_Printf("prvm_edict <program name> <edict number>\n");
722                 return;
723         }
724
725         PRVM_Begin;
726         if(!PRVM_SetProgFromString(Cmd_Argv(1)))
727                 return;
728
729         i = atoi (Cmd_Argv(2));
730         if (i >= prog->num_edicts)
731         {
732                 Con_Printf("Bad edict number\n");
733                 PRVM_End;
734                 return;
735         }
736         PRVM_ED_PrintNum (i);
737
738         PRVM_End;
739 }
740
741 /*
742 =============
743 PRVM_ED_Count
744
745 For debugging
746 =============
747 */
748 // 2 possibilities : 1. just displaying the active edict count
749 //                                       2. making a function pointer [x]
750 void PRVM_ED_Count_f (void)
751 {
752         int             i;
753         prvm_edict_t    *ent;
754         int             active;
755
756         if(Cmd_Argc() != 2)
757         {
758                 Con_Printf("prvm_count <program name>\n");
759                 return;
760         }
761
762         PRVM_Begin;
763         if(!PRVM_SetProgFromString(Cmd_Argv(1)))
764                 return;
765
766         if(prog->count_edicts)
767                 prog->count_edicts();
768         else
769         {
770                 active = 0;
771                 for (i=0 ; i<prog->num_edicts ; i++)
772                 {
773                         ent = PRVM_EDICT_NUM(i);
774                         if (ent->e->free)
775                                 continue;
776                         active++;
777                 }
778                 
779                 Con_Printf ("num_edicts:%3i\n", prog->num_edicts);
780                 Con_Printf ("active    :%3i\n", active);
781         }
782
783         PRVM_End;
784 }
785
786 /*
787 ==============================================================================
788
789                                         ARCHIVING GLOBALS
790
791 FIXME: need to tag constants, doesn't really work
792 ==============================================================================
793 */
794
795 /*
796 =============
797 PRVM_ED_WriteGlobals
798 =============
799 */
800 void PRVM_ED_WriteGlobals (qfile_t *f)
801 {
802         ddef_t          *def;
803         int                     i;
804         char            *name;
805         int                     type;
806
807         FS_Printf (f,"{\n");
808         for (i=0 ; i<prog->progs->numglobaldefs ; i++)
809         {
810                 def = &prog->globaldefs[i];
811                 type = def->type;
812                 if ( !(def->type & DEF_SAVEGLOBAL) )
813                         continue;
814                 type &= ~DEF_SAVEGLOBAL;
815
816                 if (type != ev_string && type != ev_float && type != ev_entity)
817                         continue;
818
819                 name = PRVM_GetString(def->s_name);
820                 FS_Printf (f,"\"%s\" ", name);
821                 FS_Printf (f,"\"%s\"\n", PRVM_UglyValueString(type, (prvm_eval_t *)&prog->globals[def->ofs]));
822         }
823         FS_Printf (f,"}\n");
824 }
825
826 /*
827 =============
828 PRVM_ED_ParseGlobals
829 =============
830 */
831 void PRVM_ED_ParseGlobals (const char *data)
832 {
833         char keyname[1024]; // LordHavoc: good idea? bad idea?  was 64
834         ddef_t *key;
835
836         while (1)
837         {
838                 // parse key
839                 if (!COM_ParseToken(&data, false))
840                         PRVM_ERROR ("PRVM_ED_ParseEntity: EOF without closing brace");
841                 if (com_token[0] == '}')
842                         break;
843
844                 strcpy (keyname, com_token);
845
846                 // parse value
847                 if (!COM_ParseToken(&data, false))
848                         PRVM_ERROR ("PRVM_ED_ParseEntity: EOF without closing brace");
849
850                 if (com_token[0] == '}')
851                         PRVM_ERROR ("PRVM_ED_ParseEntity: closing brace without data");
852
853                 key = PRVM_ED_FindGlobal (keyname);
854                 if (!key)
855                 {
856                         Con_DPrintf ("'%s' is not a global on %s\n", keyname, PRVM_NAME);
857                         continue;
858                 }
859
860                 if (!PRVM_ED_ParseEpair(NULL, key, com_token))
861                         PRVM_ERROR ("PRVM_ED_ParseGlobals: parse error");
862         }
863 }
864
865 //============================================================================
866
867
868 /*
869 =============
870 PRVM_ED_NewString
871 =============
872 */
873 char *PRVM_ED_NewString (const char *string)
874 {
875         char *new, *new_p;
876         int i,l;
877
878         l = strlen(string) + 1;
879         new = Mem_Alloc(prog->edictstring_mempool, l);
880         new_p = new;
881
882         for (i=0 ; i< l ; i++)
883         {
884                 if (string[i] == '\\' && i < l-1)
885                 {
886                         i++;
887                         if (string[i] == 'n')
888                                 *new_p++ = '\n';
889                         else
890                                 *new_p++ = '\\';
891                 }
892                 else
893                         *new_p++ = string[i];
894         }
895
896         return new;
897 }
898
899 /*
900 =============
901 PRVM_ED_ParseEval
902
903 Can parse either fields or globals
904 returns false if error
905 =============
906 */
907 qboolean PRVM_ED_ParseEpair(prvm_edict_t *ent, ddef_t *key, const char *s)
908 {
909         int i;
910         ddef_t *def;
911         prvm_eval_t *val;
912         mfunction_t *func;
913
914         if (ent)
915                 val = (prvm_eval_t *)((int *)ent->v + key->ofs);
916         else
917                 val = (prvm_eval_t *)((int *)pr_globals + key->ofs);
918         switch (key->type & ~DEF_SAVEGLOBAL)
919         {
920         case ev_string:
921                 val->string = PRVM_SetString(PRVM_ED_NewString(s));
922                 break;
923
924         case ev_float:
925                 while (*s && *s <= ' ')
926                         s++;
927                 val->_float = atof(s);
928                 break;
929
930         case ev_vector:
931                 for (i = 0;i < 3;i++)
932                 {
933                         while (*s && *s <= ' ')
934                                 s++;
935                         if (!*s)
936                                 break;
937                         val->vector[i] = atof(s);
938                         while (*s > ' ')
939                                 s++;
940                         if (!*s)
941                                 break;
942                 }
943                 break;
944
945         case ev_entity:
946                 while (*s && *s <= ' ')
947                         s++;
948                 i = atoi(s);
949                 if (i < 0 || i >= MAX_EDICTS)
950                         Con_Printf("PRVM_ED_ParseEpair: ev_entity reference too large (edict %i >= MAX_EDICTS %i) on %s\n", i, MAX_EDICTS, PRVM_NAME);
951                 while (i >= prog->max_edicts)
952                         PRVM_MEM_IncreaseEdicts();
953                         //SV_IncreaseEdicts();
954                 // if SV_IncreaseEdicts was called the base pointer needs to be updated
955                 if (ent)
956                         val = (prvm_eval_t *)((int *)ent->v + key->ofs);
957                 val->edict = PRVM_EDICT_TO_PROG(EDICT_NUM(i));
958                 break;
959
960         case ev_field:
961                 def = PRVM_ED_FindField(s);
962                 if (!def)
963                 {
964                         Con_DPrintf("PRVM_ED_ParseEpair: Can't find field %s in %s\n", s, PRVM_NAME);
965                         return false;
966                 }
967                 val->_int = PRVM_G_INT(def->ofs);
968                 break;
969
970         case ev_function:
971                 func = PRVM_ED_FindFunction(s);
972                 if (!func)
973                 {
974                         Con_Printf ("PRVM_ED_ParseEpair: Can't find function %s in %s\n", s, PRVM_NAME);
975                         return false;
976                 }
977                 val->function = func - prog->functions;
978                 break;
979
980         default:
981                 Con_Printf("PRVM_ED_ParseEpair: Unknown key->type %i for key \"%s\" on %s\n", key->type, PR_GetString(key->s_name), PRVM_NAME);
982                 return false;
983         }
984         return true;
985 }
986
987 /*
988 =============
989 PRVM_ED_EdictSet_f
990
991 Console command to set a field of a specified edict
992 =============
993 */
994 void PRVM_ED_EdictSet_f(void)
995 {
996         prvm_edict_t *ed;
997         ddef_t *key;
998
999         if(Cmd_Argc() != 5)
1000         {
1001                 Con_Printf("prvm_edictset <program name> <edict number> <field> <value>\n");
1002                 return;
1003         }
1004
1005         PRVM_Begin;
1006         if(!PRVM_SetProgFromString(Cmd_Argv(1)))
1007         {
1008                 Con_Printf("Wrong program name %s !\n", Cmd_Argv(1));
1009                 return;
1010         }
1011
1012         ed = PRVM_EDICT_NUM(atoi(Cmd_Argv(2)));
1013
1014         if((key = PRVM_ED_FindField(Cmd_Argv(3))) == 0)
1015         {
1016                 Con_Printf("Key %s not found !\n", Cmd_Argv(3));
1017                 return;
1018         }
1019
1020         PRVM_ED_ParseEpair(ed, key, Cmd_Argv(4));
1021
1022         PRVM_End;
1023 }
1024
1025 /*
1026 ====================
1027 PRVM_ED_ParseEdict
1028
1029 Parses an edict out of the given string, returning the new position
1030 ed should be a properly initialized empty edict.
1031 Used for initial level load and for savegames.
1032 ====================
1033 */
1034 const char *PRVM_ED_ParseEdict (const char *data, prvm_edict_t *ent)
1035 {
1036         ddef_t *key;
1037         qboolean anglehack;
1038         qboolean init;
1039         char keyname[256];
1040         int n;
1041
1042         init = false;
1043
1044 // clear it
1045         if (ent != prog->edicts)        // hack
1046                 memset (ent->v, 0, prog->progs->entityfields * 4);
1047
1048 // go through all the dictionary pairs
1049         while (1)
1050         {
1051         // parse key
1052                 if (!COM_ParseToken(&data, false))
1053                         PRVM_ERROR ("PRVM_ED_ParseEntity: EOF without closing brace");
1054                 if (com_token[0] == '}')
1055                         break;
1056
1057                 // anglehack is to allow QuakeEd to write single scalar angles
1058                 // and allow them to be turned into vectors. (FIXME...)
1059                 if (!strcmp(com_token, "angle"))
1060                 {
1061                         strcpy (com_token, "angles");
1062                         anglehack = true;
1063                 }
1064                 else
1065                         anglehack = false;
1066
1067                 // FIXME: change light to _light to get rid of this hack
1068                 if (!strcmp(com_token, "light"))
1069                         strcpy (com_token, "light_lev");        // hack for single light def
1070
1071                 strcpy (keyname, com_token);
1072
1073                 // another hack to fix keynames with trailing spaces
1074                 n = strlen(keyname);
1075                 while (n && keyname[n-1] == ' ')
1076                 {
1077                         keyname[n-1] = 0;
1078                         n--;
1079                 }
1080
1081         // parse value
1082                 if (!COM_ParseToken(&data, false))
1083                         PRVM_ERROR ("PRVM_ED_ParseEntity: EOF without closing brace");
1084
1085                 if (com_token[0] == '}')
1086                         PRVM_ERROR ("PRVM_ED_ParseEntity: closing brace without data");
1087
1088                 init = true;
1089
1090 // keynames with a leading underscore are used for utility comments,
1091 // and are immediately discarded by quake
1092                 if (keyname[0] == '_')
1093                         continue;
1094
1095                 key = PRVM_ED_FindField (keyname);
1096                 if (!key)
1097                 {
1098                         Con_DPrintf ("%s: '%s' is not a field\n", PRVM_NAME, keyname);
1099                         continue;
1100                 }
1101
1102                 if (anglehack)
1103                 {
1104                         char    temp[32];
1105                         strcpy (temp, com_token);
1106                         sprintf (com_token, "0 %s 0", temp);
1107                 }
1108
1109                 if (!PRVM_ED_ParseEpair(ent, key, com_token))
1110                         PRVM_ERROR ("PRVM_ED_ParseEdict: parse error");
1111         }
1112
1113         if (!init)
1114                 ent->e->free = true;
1115
1116         return data;
1117 }
1118
1119
1120 /*
1121 ================
1122 PRVM_ED_LoadFromFile
1123
1124 The entities are directly placed in the array, rather than allocated with
1125 PRVM_ED_Alloc, because otherwise an error loading the map would have entity
1126 number references out of order.
1127
1128 Creates a server's entity / program execution context by
1129 parsing textual entity definitions out of an ent file.
1130
1131 Used for both fresh maps and savegame loads.  A fresh map would also need
1132 to call PRVM_ED_CallSpawnFunctions () to let the objects initialize themselves.
1133 ================
1134 */
1135 void PRVM_ED_LoadFromFile (const char *data)
1136 {
1137         prvm_edict_t *ent;
1138         int parsed, inhibited, spawned, died;
1139         mfunction_t *func;
1140
1141         parsed = 0;
1142         inhibited = 0;
1143         spawned = 0;
1144         died = 0;
1145
1146
1147 // parse ents
1148         while (1)
1149         {
1150 // parse the opening brace
1151                 if (!COM_ParseToken(&data, false))
1152                         break;
1153                 if (com_token[0] != '{')
1154                         PRVM_ERROR ("PRVM_ED_LoadFromFile: %s: found %s when expecting {", PRVM_NAME, com_token);
1155
1156                 // CHANGED: this is not conform to ED_LoadFromFile
1157                 if(!prog->num_edicts) 
1158                         ent = PRVM_EDICT_NUM(0);
1159                 else 
1160                         ent = PRVM_ED_Alloc();
1161
1162                 data = PRVM_ED_ParseEdict (data, ent);
1163                 parsed++;
1164
1165                 // remove the entity ?
1166                 if(prog->load_edict && !prog->load_edict(ent))
1167                 {
1168                         PRVM_ED_Free(ent);
1169                         inhibited++;
1170                         continue;
1171                 }
1172
1173 //
1174 // immediately call spawn function, but only if there is a self global and a classname
1175 //
1176                 if(prog->self && prog->flag & PRVM_FE_CLASSNAME)
1177                 {
1178                         string_t handle =  *(string_t*)&((float*)ent->v)[PRVM_ED_FindFieldOffset("classname")];
1179                         if (!handle)
1180                         {
1181                                 Con_Printf ("No classname for:\n");
1182                                 PRVM_ED_Print (ent);
1183                                 PRVM_ED_Free (ent);
1184                                 continue;
1185                         }
1186                         
1187                         // look for the spawn function
1188                         func = PRVM_ED_FindFunction (PRVM_GetString(handle));
1189                         
1190                         if (!func)
1191                         {
1192                                 if (developer.integer) // don't confuse non-developers with errors
1193                                 {
1194                                         Con_Printf ("No spawn function for:\n");
1195                                         PRVM_ED_Print (ent);
1196                                 }
1197                                 PRVM_ED_Free (ent);
1198                                 continue;
1199                         }
1200                         
1201                         // self = ent
1202                         PRVM_G_INT(prog->self->ofs) = PRVM_EDICT_TO_PROG(ent);
1203                         PRVM_ExecuteProgram (func - prog->functions, "");
1204                 }
1205         
1206                 spawned++;
1207                 if (ent->e->free)
1208                         died++;
1209         }
1210
1211         Con_DPrintf ("%s: %i new entities parsed, %i new inhibited, %i (%i new) spawned (whereas %i removed self, %i stayed)\n", PRVM_NAME, parsed, inhibited, prog->num_edicts, spawned, died, spawned - died);
1212 }       
1213
1214 // not used
1215 /*
1216 typedef struct dpfield_s
1217 {
1218         int type;
1219         char *string;
1220 }
1221 dpfield_t;
1222
1223 #define DPFIELDS (sizeof(dpfields) / sizeof(dpfield_t))
1224
1225 dpfield_t dpfields[] =
1226 {
1227 };
1228 */
1229
1230 /*
1231 ===============
1232 PRVM_ResetProg
1233 ===============
1234 */
1235
1236 void PRVM_ResetProg()
1237 {
1238         /*mempool_t *t1, *t2, *t3;
1239
1240         t1 = prog->progs_mempool;
1241         t2 = prog->edictstring_mempool;
1242         t3 = prog->edicts_mempool;
1243         
1244         Mem_EmptyPool(prog->progs_mempool);
1245         Mem_EmptyPool(prog->edictstring_mempool);
1246         Mem_EmptyPool(prog->edicts_mempool);*/
1247         Mem_FreePool(&prog->progs_mempool);
1248         Mem_FreePool(&prog->edictstring_mempool);
1249         Mem_FreePool(&prog->edicts_mempool);
1250         
1251         memset(prog,0,sizeof(prvm_prog_t));
1252         
1253         /*prog->time = &prog->_time;
1254         
1255         prog->progs_mempool = t1;
1256         prog->edictstring_mempool = t2;
1257         prog->edicts_mempool = t3;*/
1258
1259         PRVM_GCALL(reset_cmd)();
1260 }
1261
1262 /*
1263 ===============
1264 PRVM_LoadProgs
1265 ===============
1266 */
1267 void PRVM_LoadProgs (const char * filename, int numrequiredfunc, char **required_func)
1268 {
1269         int i;
1270         dstatement_t *st;
1271         ddef_t *infielddefs;
1272         void *temp;
1273         dfunction_t *dfunctions;
1274
1275         Mem_EmptyPool(prog->progs_mempool);
1276         Mem_EmptyPool(prog->edictstring_mempool);
1277
1278         temp = FS_LoadFile (filename, false);
1279         if (temp == 0)
1280                 PRVM_ERROR ("PRVM_LoadProgs: couldn't load %s for %s", filename, PRVM_NAME);
1281
1282         prog->progs = (dprograms_t *)Mem_Alloc(prog->progs_mempool, fs_filesize);
1283
1284         memcpy(prog->progs, temp, fs_filesize);
1285         Mem_Free(temp);
1286
1287         Con_DPrintf ("%s programs occupy %iK.\n", PRVM_NAME, fs_filesize/1024);
1288
1289         pr_crc = CRC_Block((qbyte *)prog->progs, fs_filesize);
1290
1291 // byte swap the header
1292         for (i = 0;i < (int) sizeof(*prog->progs) / 4;i++)
1293                 ((int *)prog->progs)[i] = LittleLong ( ((int *)prog->progs)[i] );
1294
1295         if (prog->progs->version != PROG_VERSION)
1296                 PRVM_ERROR ("%s: %s has wrong version number (%i should be %i)", PRVM_NAME, filename, prog->progs->version, PROG_VERSION);
1297         if (prog->progs->crc != prog->crc)
1298                 PRVM_ERROR ("%s: %s system vars have been modified, progdefs.h is out of date", PRVM_NAME, filename);
1299
1300         //pr_functions = (dfunction_t *)((qbyte *)progs + progs->ofs_functions);
1301         dfunctions = (dfunction_t *)((qbyte *)prog->progs + prog->progs->ofs_functions);
1302         prog->strings = (char *)prog->progs + prog->progs->ofs_strings;
1303         prog->globaldefs = (ddef_t *)((qbyte *)prog->progs + prog->progs->ofs_globaldefs);
1304
1305         // we need to expand the fielddefs list to include all the engine fields,
1306         // so allocate a new place for it
1307         infielddefs = (ddef_t *)((qbyte *)prog->progs + prog->progs->ofs_fielddefs);
1308         //                                                                                              ( + DPFIELDS                       )
1309         prog->fielddefs = Mem_Alloc(prog->progs_mempool, prog->progs->numfielddefs * sizeof(ddef_t));
1310
1311         prog->statements = (dstatement_t *)((qbyte *)prog->progs + prog->progs->ofs_statements);
1312
1313         // moved edict_size calculation down below field adding code
1314
1315         //pr_global_struct = (globalvars_t *)((qbyte *)progs + progs->ofs_globals);
1316         prog->globals = (float *)((qbyte *)prog->progs + prog->progs->ofs_globals);
1317
1318 // byte swap the lumps
1319         for (i=0 ; i<prog->progs->numstatements ; i++)
1320         {
1321                 prog->statements[i].op = LittleShort(prog->statements[i].op);
1322                 prog->statements[i].a = LittleShort(prog->statements[i].a);
1323                 prog->statements[i].b = LittleShort(prog->statements[i].b);
1324                 prog->statements[i].c = LittleShort(prog->statements[i].c);
1325         }
1326
1327         prog->functions = Mem_Alloc(prog->progs_mempool, sizeof(mfunction_t) * prog->progs->numfunctions);
1328         for (i = 0;i < prog->progs->numfunctions;i++)
1329         {
1330                 prog->functions[i].first_statement = LittleLong (dfunctions[i].first_statement);
1331                 prog->functions[i].parm_start = LittleLong (dfunctions[i].parm_start);
1332                 prog->functions[i].s_name = LittleLong (dfunctions[i].s_name);
1333                 prog->functions[i].s_file = LittleLong (dfunctions[i].s_file);
1334                 prog->functions[i].numparms = LittleLong (dfunctions[i].numparms);
1335                 prog->functions[i].locals = LittleLong (dfunctions[i].locals);
1336                 memcpy(prog->functions[i].parm_size, dfunctions[i].parm_size, sizeof(dfunctions[i].parm_size));
1337         }
1338
1339         for (i=0 ; i<prog->progs->numglobaldefs ; i++)
1340         {
1341                 prog->globaldefs[i].type = LittleShort (prog->globaldefs[i].type);
1342                 prog->globaldefs[i].ofs = LittleShort (prog->globaldefs[i].ofs);
1343                 prog->globaldefs[i].s_name = LittleLong (prog->globaldefs[i].s_name);
1344         }
1345
1346         // copy the progs fields to the new fields list
1347         for (i = 0;i < prog->progs->numfielddefs;i++)
1348         {
1349                 prog->fielddefs[i].type = LittleShort (infielddefs[i].type);
1350                 if (prog->fielddefs[i].type & DEF_SAVEGLOBAL)
1351                         PRVM_ERROR ("PRVM_LoadProgs: prog->fielddefs[i].type & DEF_SAVEGLOBAL in %s", PRVM_NAME);
1352                 prog->fielddefs[i].ofs = LittleShort (infielddefs[i].ofs);
1353                 prog->fielddefs[i].s_name = LittleLong (infielddefs[i].s_name);
1354         }
1355
1356 /*      // append the darkplaces fields
1357         for (i = 0;i < (int) DPFIELDS;i++)
1358         {
1359                 pr_fielddefs[progs->numfielddefs].type = dpfields[i].type;
1360                 pr_fielddefs[progs->numfielddefs].ofs = progs->entityfields;
1361                 pr_fielddefs[progs->numfielddefs].s_name = PR_SetString(dpfields[i].string);
1362                 if (pr_fielddefs[progs->numfielddefs].type == ev_vector)
1363                         progs->entityfields += 3;
1364                 else
1365                         progs->entityfields++;
1366                 progs->numfielddefs++;
1367         }*/
1368
1369         // check required functions
1370         for(i=0 ; i < numrequiredfunc ; i++)
1371                 if(PRVM_ED_FindFunction(required_func[i]) == 0)
1372                         PRVM_ERROR("%s: %s not found in %s\n",PRVM_NAME, required_func[i], filename);
1373
1374         for (i=0 ; i<prog->progs->numglobals ; i++)
1375                 ((int *)prog->globals)[i] = LittleLong (((int *)prog->globals)[i]);
1376
1377         // moved edict_size calculation down here, below field adding code
1378         // LordHavoc: this no longer includes the edict_t header
1379         prog->edict_size = prog->progs->entityfields * 4;
1380         prog->edictareasize = prog->edict_size * MAX_EDICTS;
1381
1382         // LordHavoc: bounds check anything static
1383         for (i = 0,st = prog->statements;i < prog->progs->numstatements;i++,st++)
1384         {
1385                 switch (st->op)
1386                 {
1387                 case OP_IF:
1388                 case OP_IFNOT:
1389                         if ((unsigned short) st->a >= prog->progs->numglobals || st->b + i < 0 || st->b + i >= prog->progs->numstatements)
1390                                 PRVM_ERROR("PRVM_LoadProgs: out of bounds IF/IFNOT (statement %d) in %s\n", i, PRVM_NAME);
1391                         break;
1392                 case OP_GOTO:
1393                         if (st->a + i < 0 || st->a + i >= prog->progs->numstatements)
1394                                 PRVM_ERROR("PRVM_LoadProgs: out of bounds GOTO (statement %d) in %s\n", i, PRVM_NAME);
1395                         break;
1396                 // global global global
1397                 case OP_ADD_F:
1398                 case OP_ADD_V:
1399                 case OP_SUB_F:
1400                 case OP_SUB_V:
1401                 case OP_MUL_F:
1402                 case OP_MUL_V:
1403                 case OP_MUL_FV:
1404                 case OP_MUL_VF:
1405                 case OP_DIV_F:
1406                 case OP_BITAND:
1407                 case OP_BITOR:
1408                 case OP_GE:
1409                 case OP_LE:
1410                 case OP_GT:
1411                 case OP_LT:
1412                 case OP_AND:
1413                 case OP_OR:
1414                 case OP_EQ_F:
1415                 case OP_EQ_V:
1416                 case OP_EQ_S:
1417                 case OP_EQ_E:
1418                 case OP_EQ_FNC:
1419                 case OP_NE_F:
1420                 case OP_NE_V:
1421                 case OP_NE_S:
1422                 case OP_NE_E:
1423                 case OP_NE_FNC:
1424                 case OP_ADDRESS:
1425                 case OP_LOAD_F:
1426                 case OP_LOAD_FLD:
1427                 case OP_LOAD_ENT:
1428                 case OP_LOAD_S:
1429                 case OP_LOAD_FNC:
1430                 case OP_LOAD_V:
1431                         if ((unsigned short) st->a >= prog->progs->numglobals || (unsigned short) st->b >= prog->progs->numglobals || (unsigned short) st->c >= prog->progs->numglobals)
1432                                 PRVM_ERROR("PRVM_LoadProgs: out of bounds global index (statement %d)\n", i);
1433                         break;
1434                 // global none global
1435                 case OP_NOT_F:
1436                 case OP_NOT_V:
1437                 case OP_NOT_S:
1438                 case OP_NOT_FNC:
1439                 case OP_NOT_ENT:
1440                         if ((unsigned short) st->a >= prog->progs->numglobals || (unsigned short) st->c >= prog->progs->numglobals)
1441                                 PRVM_ERROR("PRVM_LoadProgs: out of bounds global index (statement %d) in %s\n", i, PRVM_NAME);
1442                         break;
1443                 // 2 globals
1444                 case OP_STOREP_F:
1445                 case OP_STOREP_ENT:
1446                 case OP_STOREP_FLD:
1447                 case OP_STOREP_S:
1448                 case OP_STOREP_FNC:
1449                 case OP_STORE_F:
1450                 case OP_STORE_ENT:
1451                 case OP_STORE_FLD:
1452                 case OP_STORE_S:
1453                 case OP_STORE_FNC:
1454                 case OP_STATE:
1455                 case OP_STOREP_V:
1456                 case OP_STORE_V:
1457                         if ((unsigned short) st->a >= prog->progs->numglobals || (unsigned short) st->b >= prog->progs->numglobals)
1458                                 PRVM_ERROR("PRVM_LoadProgs: out of bounds global index (statement %d)\n in %s", i, PRVM_NAME);
1459                         break;
1460                 // 1 global
1461                 case OP_CALL0:
1462                 case OP_CALL1:
1463                 case OP_CALL2:
1464                 case OP_CALL3:
1465                 case OP_CALL4:
1466                 case OP_CALL5:
1467                 case OP_CALL6:
1468                 case OP_CALL7:
1469                 case OP_CALL8:
1470                 case OP_DONE:
1471                 case OP_RETURN:
1472                         if ((unsigned short) st->a >= prog->progs->numglobals)
1473                                 PRVM_ERROR("PRVM_LoadProgs: out of bounds global index (statement %d) in %s\n", i, PRVM_NAME);
1474                         break;
1475                 default:
1476                         PRVM_ERROR("PRVM_LoadProgs: unknown opcode %d at statement %d in %s\n", st->op, i, PRVM_NAME);
1477                         break;
1478                 }
1479         }
1480
1481         PRVM_Init_Exec();
1482
1483         prog->loaded = TRUE;
1484         
1485         // set flags & ddef_ts in prog
1486         
1487         prog->flag = 0;
1488         
1489         prog->self = PRVM_ED_FindGlobal("self");
1490
1491         if(PRVM_ED_FindGlobal("time"))
1492                 prog->time = &PRVM_G_FLOAT(PRVM_ED_FindGlobal("time")->ofs);
1493
1494         if(PRVM_ED_FindField ("chain"))
1495                 prog->flag |= PRVM_FE_CHAIN;
1496
1497         if(PRVM_ED_FindField ("classname"))
1498                 prog->flag |= PRVM_FE_CLASSNAME; 
1499
1500         if(PRVM_ED_FindField ("nextthink") && PRVM_ED_FindField ("frame") && PRVM_ED_FindField ("think") 
1501                 && prog->flag && prog->self) 
1502                 prog->flag |= PRVM_OP_STATE;
1503         
1504         PRVM_GCALL(reset_cmd)();
1505         PRVM_GCALL(init_cmd)();
1506
1507         // init mempools
1508         PRVM_MEM_Alloc();
1509 }
1510
1511
1512 void PRVM_Fields_f (void)
1513 {
1514         int i, j, ednum, used, usedamount;
1515         int *counts;
1516         char tempstring[5000], tempstring2[260], *name;
1517         prvm_edict_t *ed;
1518         ddef_t *d;
1519         int *v;
1520
1521         // TODO
1522         /*
1523         if (!sv.active)
1524         {
1525                 Con_Printf("no progs loaded\n");
1526                 return;
1527         }
1528         */
1529
1530         if(Cmd_Argc() != 2)
1531         {
1532                 Con_Printf("prvm_fields <program name>\n");
1533                 return;
1534         }
1535
1536         PRVM_Begin;
1537         if(!PRVM_SetProgFromString(Cmd_Argv(1)))
1538                 return;
1539
1540         counts = Mem_Alloc(tempmempool, prog->progs->numfielddefs * sizeof(int));
1541         for (ednum = 0;ednum < prog->max_edicts;ednum++)
1542         {
1543                 ed = PRVM_EDICT_NUM(ednum);
1544                 if (ed->e->free)
1545                         continue;
1546                 for (i = 1;i < prog->progs->numfielddefs;i++)
1547                 {
1548                         d = &prog->fielddefs[i];
1549                         name = PRVM_GetString(d->s_name);
1550                         if (name[strlen(name)-2] == '_')
1551                                 continue;       // skip _x, _y, _z vars
1552                         v = (int *)((char *)ed->v + d->ofs*4);
1553                         // if the value is still all 0, skip the field
1554                         for (j = 0;j < prvm_type_size[d->type & ~DEF_SAVEGLOBAL];j++)
1555                         {
1556                                 if (v[j])
1557                                 {
1558                                         counts[i]++;
1559                                         break;
1560                                 }
1561                         }
1562                 }
1563         }
1564         used = 0;
1565         usedamount = 0;
1566         tempstring[0] = 0;
1567         for (i = 0;i < prog->progs->numfielddefs;i++)
1568         {
1569                 d = &prog->fielddefs[i];
1570                 name = PRVM_GetString(d->s_name);
1571                 if (name[strlen(name)-2] == '_')
1572                         continue;       // skip _x, _y, _z vars
1573                 switch(d->type & ~DEF_SAVEGLOBAL)
1574                 {
1575                 case ev_string:
1576                         strcat(tempstring, "string   ");
1577                         break;
1578                 case ev_entity:
1579                         strcat(tempstring, "entity   ");
1580                         break;
1581                 case ev_function:
1582                         strcat(tempstring, "function ");
1583                         break;
1584                 case ev_field:
1585                         strcat(tempstring, "field    ");
1586                         break;
1587                 case ev_void:
1588                         strcat(tempstring, "void     ");
1589                         break;
1590                 case ev_float:
1591                         strcat(tempstring, "float    ");
1592                         break;
1593                 case ev_vector:
1594                         strcat(tempstring, "vector   ");
1595                         break;
1596                 case ev_pointer:
1597                         strcat(tempstring, "pointer  ");
1598                         break;
1599                 default:
1600                         sprintf (tempstring2, "bad type %i ", d->type & ~DEF_SAVEGLOBAL);
1601                         strcat(tempstring, tempstring2);
1602                         break;
1603                 }
1604                 if (strlen(name) > 256)
1605                 {
1606                         strncpy(tempstring2, name, 256);
1607                         tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
1608                         tempstring2[259] = 0;
1609                         name = tempstring2;
1610                 }
1611                 strcat(tempstring, name);
1612                 for (j = strlen(name);j < 25;j++)
1613                         strcat(tempstring, " ");
1614                 sprintf(tempstring2, "%5d", counts[i]);
1615                 strcat(tempstring, tempstring2);
1616                 strcat(tempstring, "\n");
1617                 if (strlen(tempstring) >= 4096)
1618                 {
1619                         Con_Printf("%s", tempstring);
1620                         tempstring[0] = 0;
1621                 }
1622                 if (counts[i])
1623                 {
1624                         used++;
1625                         usedamount += prvm_type_size[d->type & ~DEF_SAVEGLOBAL];
1626                 }
1627         }
1628         Mem_Free(counts);
1629         Con_Printf("%s: %i entity fields (%i in use), totalling %i bytes per edict (%i in use), %i edicts allocated, %i bytes total spent on edict fields (%i needed)\n", PRVM_NAME, prog->progs->entityfields, used, prog->progs->entityfields * 4, usedamount * 4, prog->max_edicts, prog->progs->entityfields * 4 * prog->max_edicts, usedamount * 4 * prog->max_edicts);
1630
1631         PRVM_End;
1632 }
1633
1634 void PRVM_Globals_f (void)
1635 {
1636         int i;
1637         // TODO
1638         /*if (!sv.active)
1639         {
1640                 Con_Printf("no progs loaded\n");
1641                 return;
1642         }*/
1643         if(Cmd_Argc () != 2)
1644         {
1645                 Con_Printf("prvm_globals <program name>\n");
1646                 return;
1647         }
1648
1649         PRVM_Begin;
1650         if(!PRVM_SetProgFromString (Cmd_Argv (1)))
1651                 return;
1652
1653         Con_Printf("%s :", PRVM_NAME);
1654
1655         for (i = 0;i < prog->progs->numglobaldefs;i++)
1656                 Con_Printf("%s\n", PRVM_GetString(prog->globaldefs[i].s_name));
1657         Con_Printf("%i global variables, totalling %i bytes\n", prog->progs->numglobals, prog->progs->numglobals * 4);
1658
1659         PRVM_End;
1660 }
1661
1662 /*
1663 ===============
1664 PRVM_Init
1665 ===============
1666 */
1667 void PRVM_Init (void)
1668 {
1669         Cmd_AddCommand ("prvm_edict", PRVM_ED_PrintEdict_f);
1670         Cmd_AddCommand ("prvm_edicts", PRVM_ED_PrintEdicts_f);
1671         Cmd_AddCommand ("prvm_edictcount", PRVM_ED_Count_f);
1672         Cmd_AddCommand ("prvm_profile", PRVM_Profile_f);
1673         Cmd_AddCommand ("prvm_fields", PRVM_Fields_f);
1674         Cmd_AddCommand ("prvm_globals", PRVM_Globals_f);
1675         Cmd_AddCommand ("prvm_edictset", PRVM_ED_EdictSet_f);
1676         // LordHavoc: optional runtime bounds checking (speed drain, but worth it for security, on by default - breaks most QCCX features (used by CRMod and others))
1677         Cvar_RegisterVariable (&prvm_boundscheck);
1678         Cvar_RegisterVariable (&prvm_traceqc);
1679
1680         //VM_Cmd_Init();
1681 }
1682
1683 /*
1684 ===============
1685 PRVM_InitProg
1686 ===============
1687 */
1688 void PRVM_InitProg(int prognr)
1689 {
1690         if(prognr < 0 || prognr >= PRVM_MAXPROGS)
1691                 Sys_Error("PRVM_InitProg: Invalid program number %i\n",prognr);
1692
1693         prog = &prog_list[prognr];
1694
1695         if(prog->loaded)
1696                 PRVM_ResetProg();
1697
1698         memset(prog, 0, sizeof(prvm_prog_t));
1699
1700         prog->time = &prog->_time;
1701 }
1702
1703 int PRVM_GetProgNr()
1704 {
1705         return prog - prog_list;
1706 }
1707
1708 // LordHavoc: turned PRVM_EDICT_NUM into a #define for speed reasons
1709 prvm_edict_t *PRVM_EDICT_NUM_ERROR(int n, char *filename, int fileline)
1710 {
1711         PRVM_ERROR ("PRVM_EDICT_NUM: %s: bad number %i (called at %s:%i)", PRVM_NAME, n, filename, fileline);
1712         return NULL;
1713 }
1714
1715 void PRVM_ProcessError(void)
1716 {
1717         if(prog)
1718                 PRVM_GCALL(error_cmd)();
1719 }
1720
1721 /*
1722 int NUM_FOR_EDICT_ERROR(edict_t *e)
1723 {
1724         Host_Error ("NUM_FOR_EDICT: bad pointer %p (world is %p, entity number would be %i)", e, sv.edicts, e - sv.edicts);
1725         return 0;
1726 }
1727
1728 int NUM_FOR_EDICT(edict_t *e)
1729 {
1730         int n;
1731         n = e - sv.edicts;
1732         if ((unsigned int)n >= MAX_EDICTS)
1733                 Host_Error ("NUM_FOR_EDICT: bad pointer");
1734         return n;
1735 }
1736
1737 //int NoCrash_NUM_FOR_EDICT(edict_t *e)
1738 //{
1739 //      return e - sv.edicts;
1740 //}
1741
1742 //#define       EDICT_TO_PROG(e) ((qbyte *)(((edict_t *)e)->v) - (qbyte *)(sv.edictsfields))
1743 //#define PROG_TO_EDICT(e) (sv.edicts + ((e) / (progs->entityfields * 4)))
1744 int EDICT_TO_PROG(edict_t *e)
1745 {
1746         int n;
1747         n = e - sv.edicts;
1748         if ((unsigned int)n >= (unsigned int)sv.max_edicts)
1749                 Host_Error("EDICT_TO_PROG: invalid edict %8p (number %i compared to world at %8p)\n", e, n, sv.edicts);
1750         return n;// EXPERIMENTAL
1751         //return (qbyte *)e->v - (qbyte *)sv.edictsfields;
1752 }
1753 edict_t *PROG_TO_EDICT(int n)
1754 {
1755         if ((unsigned int)n >= (unsigned int)sv.max_edicts)
1756                 Host_Error("PROG_TO_EDICT: invalid edict number %i\n", n);
1757         return sv.edicts + n; // EXPERIMENTAL
1758         //return sv.edicts + ((n) / (progs->entityfields * 4));
1759 }
1760 */
1761