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