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