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