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