apparently M_ToggleMenu_f is not what to call... Call_MR_ToggleMenu_f is
[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                 strlcpy (line, PRVM_GetString (val->string), sizeof (line));
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                 strlcpy (line, PRVM_GetString (f->s_name), sizeof (line));
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                         memcpy (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                         memcpy (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_Print(tempstring);
621                         tempstring[0] = 0;
622                 }
623         }
624         if (tempstring[0])
625                 Con_Print(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_Print(f, "{\n");
644
645         if (ed->e->free)
646         {
647                 FS_Print(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_Print(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_Print("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_Print("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_Print("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_Print("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_Print(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_Print(f,"}\n");
824 }
825
826 /*
827 =============
828 PRVM_ED_ParseGlobals
829 =============
830 */
831 void PRVM_ED_ParseGlobals (const char *data)
832 {
833         char keyname[1024]; // LordHavoc: good idea? bad idea?  was 64
834         ddef_t *key;
835
836         while (1)
837         {
838                 // parse key
839                 if (!COM_ParseToken(&data, false))
840                         PRVM_ERROR ("PRVM_ED_ParseEntity: EOF without closing brace");
841                 if (com_token[0] == '}')
842                         break;
843
844                 strcpy (keyname, com_token);
845
846                 // parse value
847                 if (!COM_ParseToken(&data, false))
848                         PRVM_ERROR ("PRVM_ED_ParseEntity: EOF without closing brace");
849
850                 if (com_token[0] == '}')
851                         PRVM_ERROR ("PRVM_ED_ParseEntity: closing brace without data");
852
853                 key = PRVM_ED_FindGlobal (keyname);
854                 if (!key)
855                 {
856                         Con_DPrintf("'%s' is not a global on %s\n", keyname, PRVM_NAME);
857                         continue;
858                 }
859
860                 if (!PRVM_ED_ParseEpair(NULL, key, com_token))
861                         PRVM_ERROR ("PRVM_ED_ParseGlobals: parse error");
862         }
863 }
864
865 //============================================================================
866
867
868 /*
869 =============
870 PRVM_ED_NewString
871 =============
872 */
873 char *PRVM_ED_NewString (const char *string)
874 {
875         char *new, *new_p;
876         int i,l;
877
878         l = strlen(string) + 1;
879         new = Mem_Alloc(prog->edictstring_mempool, l);
880         new_p = new;
881
882         for (i=0 ; i< l ; i++)
883         {
884                 if (string[i] == '\\' && i < l-1)
885                 {
886                         i++;
887                         if (string[i] == 'n')
888                                 *new_p++ = '\n';
889                         else
890                                 *new_p++ = '\\';
891                 }
892                 else
893                         *new_p++ = string[i];
894         }
895
896         return new;
897 }
898
899 /*
900 =============
901 PRVM_ED_ParseEval
902
903 Can parse either fields or globals
904 returns false if error
905 =============
906 */
907 qboolean PRVM_ED_ParseEpair(prvm_edict_t *ent, ddef_t *key, const char *s)
908 {
909         int i;
910         ddef_t *def;
911         prvm_eval_t *val;
912         mfunction_t *func;
913
914         if (ent)
915                 val = (prvm_eval_t *)((int *)ent->v + key->ofs);
916         else
917                 val = (prvm_eval_t *)((int *)pr_globals + key->ofs);
918         switch (key->type & ~DEF_SAVEGLOBAL)
919         {
920         case ev_string:
921                 val->string = PRVM_SetString(PRVM_ED_NewString(s));
922                 break;
923
924         case ev_float:
925                 while (*s && *s <= ' ')
926                         s++;
927                 val->_float = atof(s);
928                 break;
929
930         case ev_vector:
931                 for (i = 0;i < 3;i++)
932                 {
933                         while (*s && *s <= ' ')
934                                 s++;
935                         if (!*s)
936                                 break;
937                         val->vector[i] = atof(s);
938                         while (*s > ' ')
939                                 s++;
940                         if (!*s)
941                                 break;
942                 }
943                 break;
944
945         case ev_entity:
946                 while (*s && *s <= ' ')
947                         s++;
948                 i = atoi(s);
949                 if (i < 0 || i >= MAX_EDICTS)
950                         Con_Printf("PRVM_ED_ParseEpair: ev_entity reference too large (edict %i >= MAX_EDICTS %i) on %s\n", i, MAX_EDICTS, PRVM_NAME);
951                 while (i >= prog->max_edicts)
952                         PRVM_MEM_IncreaseEdicts();
953                         //SV_IncreaseEdicts();
954                 // if SV_IncreaseEdicts was called the base pointer needs to be updated
955                 if (ent)
956                         val = (prvm_eval_t *)((int *)ent->v + key->ofs);
957                 val->edict = PRVM_EDICT_TO_PROG(EDICT_NUM(i));
958                 break;
959
960         case ev_field:
961                 def = PRVM_ED_FindField(s);
962                 if (!def)
963                 {
964                         Con_DPrintf("PRVM_ED_ParseEpair: Can't find field %s in %s\n", s, PRVM_NAME);
965                         return false;
966                 }
967                 val->_int = PRVM_G_INT(def->ofs);
968                 break;
969
970         case ev_function:
971                 func = PRVM_ED_FindFunction(s);
972                 if (!func)
973                 {
974                         Con_Printf("PRVM_ED_ParseEpair: Can't find function %s in %s\n", s, PRVM_NAME);
975                         return false;
976                 }
977                 val->function = func - prog->functions;
978                 break;
979
980         default:
981                 Con_Printf("PRVM_ED_ParseEpair: Unknown key->type %i for key \"%s\" on %s\n", key->type, PR_GetString(key->s_name), PRVM_NAME);
982                 return false;
983         }
984         return true;
985 }
986
987 /*
988 =============
989 PRVM_ED_EdictSet_f
990
991 Console command to set a field of a specified edict
992 =============
993 */
994 void PRVM_ED_EdictSet_f(void)
995 {
996         prvm_edict_t *ed;
997         ddef_t *key;
998
999         if(Cmd_Argc() != 5)
1000         {
1001                 Con_Print("prvm_edictset <program name> <edict number> <field> <value>\n");
1002                 return;
1003         }
1004
1005         PRVM_Begin;
1006         if(!PRVM_SetProgFromString(Cmd_Argv(1)))
1007         {
1008                 Con_Printf("Wrong program name %s !\n", Cmd_Argv(1));
1009                 return;
1010         }
1011
1012         ed = PRVM_EDICT_NUM(atoi(Cmd_Argv(2)));
1013
1014         if((key = PRVM_ED_FindField(Cmd_Argv(3))) == 0)
1015         {
1016                 Con_Printf("Key %s not found !\n", Cmd_Argv(3));
1017                 return;
1018         }
1019
1020         PRVM_ED_ParseEpair(ed, key, Cmd_Argv(4));
1021
1022         PRVM_End;
1023 }
1024
1025 /*
1026 ====================
1027 PRVM_ED_ParseEdict
1028
1029 Parses an edict out of the given string, returning the new position
1030 ed should be a properly initialized empty edict.
1031 Used for initial level load and for savegames.
1032 ====================
1033 */
1034 const char *PRVM_ED_ParseEdict (const char *data, prvm_edict_t *ent)
1035 {
1036         ddef_t *key;
1037         qboolean anglehack;
1038         qboolean init;
1039         char keyname[256];
1040         int n;
1041
1042         init = false;
1043
1044 // clear it
1045         if (ent != prog->edicts)        // hack
1046                 memset (ent->v, 0, prog->progs->entityfields * 4);
1047
1048 // go through all the dictionary pairs
1049         while (1)
1050         {
1051         // parse key
1052                 if (!COM_ParseToken(&data, false))
1053                         PRVM_ERROR ("PRVM_ED_ParseEntity: EOF without closing brace");
1054                 if (com_token[0] == '}')
1055                         break;
1056
1057                 // anglehack is to allow QuakeEd to write single scalar angles
1058                 // and allow them to be turned into vectors. (FIXME...)
1059                 if (!strcmp(com_token, "angle"))
1060                 {
1061                         strcpy (com_token, "angles");
1062                         anglehack = true;
1063                 }
1064                 else
1065                         anglehack = false;
1066
1067                 // FIXME: change light to _light to get rid of this hack
1068                 if (!strcmp(com_token, "light"))
1069                         strcpy (com_token, "light_lev");        // hack for single light def
1070
1071                 strcpy (keyname, com_token);
1072
1073                 // another hack to fix keynames with trailing spaces
1074                 n = strlen(keyname);
1075                 while (n && keyname[n-1] == ' ')
1076                 {
1077                         keyname[n-1] = 0;
1078                         n--;
1079                 }
1080
1081         // parse value
1082                 if (!COM_ParseToken(&data, false))
1083                         PRVM_ERROR ("PRVM_ED_ParseEntity: EOF without closing brace");
1084
1085                 if (com_token[0] == '}')
1086                         PRVM_ERROR ("PRVM_ED_ParseEntity: closing brace without data");
1087
1088                 init = true;
1089
1090 // keynames with a leading underscore are used for utility comments,
1091 // and are immediately discarded by quake
1092                 if (keyname[0] == '_')
1093                         continue;
1094
1095                 key = PRVM_ED_FindField (keyname);
1096                 if (!key)
1097                 {
1098                         Con_DPrintf("%s: '%s' is not a field\n", PRVM_NAME, keyname);
1099                         continue;
1100                 }
1101
1102                 if (anglehack)
1103                 {
1104                         char    temp[32];
1105                         strcpy (temp, com_token);
1106                         sprintf (com_token, "0 %s 0", temp);
1107                 }
1108
1109                 if (!PRVM_ED_ParseEpair(ent, key, com_token))
1110                         PRVM_ERROR ("PRVM_ED_ParseEdict: parse error");
1111         }
1112
1113         if (!init)
1114                 ent->e->free = true;
1115
1116         return data;
1117 }
1118
1119
1120 /*
1121 ================
1122 PRVM_ED_LoadFromFile
1123
1124 The entities are directly placed in the array, rather than allocated with
1125 PRVM_ED_Alloc, because otherwise an error loading the map would have entity
1126 number references out of order.
1127
1128 Creates a server's entity / program execution context by
1129 parsing textual entity definitions out of an ent file.
1130
1131 Used for both fresh maps and savegame loads.  A fresh map would also need
1132 to call PRVM_ED_CallSpawnFunctions () to let the objects initialize themselves.
1133 ================
1134 */
1135 void PRVM_ED_LoadFromFile (const char *data)
1136 {
1137         prvm_edict_t *ent;
1138         int parsed, inhibited, spawned, died;
1139         mfunction_t *func;
1140
1141         parsed = 0;
1142         inhibited = 0;
1143         spawned = 0;
1144         died = 0;
1145
1146
1147 // parse ents
1148         while (1)
1149         {
1150 // parse the opening brace
1151                 if (!COM_ParseToken(&data, false))
1152                         break;
1153                 if (com_token[0] != '{')
1154                         PRVM_ERROR ("PRVM_ED_LoadFromFile: %s: found %s when expecting {", PRVM_NAME, com_token);
1155
1156                 // CHANGED: this is not conform to ED_LoadFromFile
1157                 if(!prog->num_edicts) 
1158                         ent = PRVM_EDICT_NUM(0);
1159                 else 
1160                         ent = PRVM_ED_Alloc();
1161
1162                 data = PRVM_ED_ParseEdict (data, ent);
1163                 parsed++;
1164
1165                 // remove the entity ?
1166                 if(prog->load_edict && !prog->load_edict(ent))
1167                 {
1168                         PRVM_ED_Free(ent);
1169                         inhibited++;
1170                         continue;
1171                 }
1172
1173 //
1174 // immediately call spawn function, but only if there is a self global and a classname
1175 //
1176                 if(prog->self && prog->flag & PRVM_FE_CLASSNAME)
1177                 {
1178                         string_t handle =  *(string_t*)&((float*)ent->v)[PRVM_ED_FindFieldOffset("classname")];
1179                         if (!handle)
1180                         {
1181                                 Con_Print("No classname for:\n");
1182                                 PRVM_ED_Print(ent);
1183                                 PRVM_ED_Free (ent);
1184                                 continue;
1185                         }
1186                         
1187                         // look for the spawn function
1188                         func = PRVM_ED_FindFunction (PRVM_GetString(handle));
1189                         
1190                         if (!func)
1191                         {
1192                                 if (developer.integer) // don't confuse non-developers with errors
1193                                 {
1194                                         Con_Print("No spawn function for:\n");
1195                                         PRVM_ED_Print(ent);
1196                                 }
1197                                 PRVM_ED_Free (ent);
1198                                 continue;
1199                         }
1200                         
1201                         // self = ent
1202                         PRVM_G_INT(prog->self->ofs) = PRVM_EDICT_TO_PROG(ent);
1203                         PRVM_ExecuteProgram (func - prog->functions, "");
1204                 }
1205         
1206                 spawned++;
1207                 if (ent->e->free)
1208                         died++;
1209         }
1210
1211         Con_DPrintf("%s: %i new entities parsed, %i new inhibited, %i (%i new) spawned (whereas %i removed self, %i stayed)\n", PRVM_NAME, parsed, inhibited, prog->num_edicts, spawned, died, spawned - died);
1212 }       
1213
1214 // not used
1215 /*
1216 typedef struct dpfield_s
1217 {
1218         int type;
1219         char *string;
1220 }
1221 dpfield_t;
1222
1223 #define DPFIELDS (sizeof(dpfields) / sizeof(dpfield_t))
1224
1225 dpfield_t dpfields[] =
1226 {
1227 };
1228 */
1229
1230 /*
1231 ===============
1232 PRVM_ResetProg
1233 ===============
1234 */
1235
1236 void PRVM_ResetProg()
1237 {
1238         /*mempool_t *t1, *t2, *t3;
1239
1240         t1 = prog->progs_mempool;
1241         t2 = prog->edictstring_mempool;
1242         t3 = prog->edicts_mempool;
1243         
1244         Mem_EmptyPool(prog->progs_mempool);
1245         Mem_EmptyPool(prog->edictstring_mempool);
1246         Mem_EmptyPool(prog->edicts_mempool);*/
1247         Mem_FreePool(&prog->progs_mempool);
1248         Mem_FreePool(&prog->edictstring_mempool);
1249         Mem_FreePool(&prog->edicts_mempool);
1250         
1251         memset(prog,0,sizeof(prvm_prog_t));
1252         
1253         /*prog->time = &prog->_time;
1254         
1255         prog->progs_mempool = t1;
1256         prog->edictstring_mempool = t2;
1257         prog->edicts_mempool = t3;*/
1258
1259         PRVM_GCALL(reset_cmd)();
1260 }
1261
1262 /*
1263 ===============
1264 PRVM_LoadProgs
1265 ===============
1266 */
1267 void PRVM_LoadProgs (const char * filename, int numrequiredfunc, char **required_func)
1268 {
1269         int i;
1270         dstatement_t *st;
1271         ddef_t *infielddefs;
1272         dfunction_t *dfunctions;
1273
1274         Mem_EmptyPool(prog->progs_mempool);
1275         Mem_EmptyPool(prog->edictstring_mempool);
1276
1277         prog->progs = (dprograms_t *)FS_LoadFile (filename, prog->progs_mempool, false);
1278         if (prog->progs == NULL)
1279                 PRVM_ERROR ("PRVM_LoadProgs: couldn't load %s for %s", filename, PRVM_NAME);
1280
1281         Con_DPrintf("%s programs occupy %iK.\n", PRVM_NAME, fs_filesize/1024);
1282
1283         pr_crc = CRC_Block((qbyte *)prog->progs, fs_filesize);
1284
1285 // byte swap the header
1286         for (i = 0;i < (int) sizeof(*prog->progs) / 4;i++)
1287                 ((int *)prog->progs)[i] = LittleLong ( ((int *)prog->progs)[i] );
1288
1289         if (prog->progs->version != PROG_VERSION)
1290                 PRVM_ERROR ("%s: %s has wrong version number (%i should be %i)", PRVM_NAME, filename, prog->progs->version, PROG_VERSION);
1291         if (prog->progs->crc != prog->crc)
1292                 PRVM_ERROR ("%s: %s system vars have been modified, progdefs.h is out of date", PRVM_NAME, filename);
1293
1294         //pr_functions = (dfunction_t *)((qbyte *)progs + progs->ofs_functions);
1295         dfunctions = (dfunction_t *)((qbyte *)prog->progs + prog->progs->ofs_functions);
1296         prog->strings = (char *)prog->progs + prog->progs->ofs_strings;
1297         prog->globaldefs = (ddef_t *)((qbyte *)prog->progs + prog->progs->ofs_globaldefs);
1298
1299         // we need to expand the fielddefs list to include all the engine fields,
1300         // so allocate a new place for it
1301         infielddefs = (ddef_t *)((qbyte *)prog->progs + prog->progs->ofs_fielddefs);
1302         //                                                                                              ( + DPFIELDS                       )
1303         prog->fielddefs = Mem_Alloc(prog->progs_mempool, prog->progs->numfielddefs * sizeof(ddef_t));
1304
1305         prog->statements = (dstatement_t *)((qbyte *)prog->progs + prog->progs->ofs_statements);
1306
1307         // moved edict_size calculation down below field adding code
1308
1309         //pr_global_struct = (globalvars_t *)((qbyte *)progs + progs->ofs_globals);
1310         prog->globals = (float *)((qbyte *)prog->progs + prog->progs->ofs_globals);
1311
1312 // byte swap the lumps
1313         for (i=0 ; i<prog->progs->numstatements ; i++)
1314         {
1315                 prog->statements[i].op = LittleShort(prog->statements[i].op);
1316                 prog->statements[i].a = LittleShort(prog->statements[i].a);
1317                 prog->statements[i].b = LittleShort(prog->statements[i].b);
1318                 prog->statements[i].c = LittleShort(prog->statements[i].c);
1319         }
1320
1321         prog->functions = Mem_Alloc(prog->progs_mempool, sizeof(mfunction_t) * prog->progs->numfunctions);
1322         for (i = 0;i < prog->progs->numfunctions;i++)
1323         {
1324                 prog->functions[i].first_statement = LittleLong (dfunctions[i].first_statement);
1325                 prog->functions[i].parm_start = LittleLong (dfunctions[i].parm_start);
1326                 prog->functions[i].s_name = LittleLong (dfunctions[i].s_name);
1327                 prog->functions[i].s_file = LittleLong (dfunctions[i].s_file);
1328                 prog->functions[i].numparms = LittleLong (dfunctions[i].numparms);
1329                 prog->functions[i].locals = LittleLong (dfunctions[i].locals);
1330                 memcpy(prog->functions[i].parm_size, dfunctions[i].parm_size, sizeof(dfunctions[i].parm_size));
1331         }
1332
1333         for (i=0 ; i<prog->progs->numglobaldefs ; i++)
1334         {
1335                 prog->globaldefs[i].type = LittleShort (prog->globaldefs[i].type);
1336                 prog->globaldefs[i].ofs = LittleShort (prog->globaldefs[i].ofs);
1337                 prog->globaldefs[i].s_name = LittleLong (prog->globaldefs[i].s_name);
1338         }
1339
1340         // copy the progs fields to the new fields list
1341         for (i = 0;i < prog->progs->numfielddefs;i++)
1342         {
1343                 prog->fielddefs[i].type = LittleShort (infielddefs[i].type);
1344                 if (prog->fielddefs[i].type & DEF_SAVEGLOBAL)
1345                         PRVM_ERROR ("PRVM_LoadProgs: prog->fielddefs[i].type & DEF_SAVEGLOBAL in %s", PRVM_NAME);
1346                 prog->fielddefs[i].ofs = LittleShort (infielddefs[i].ofs);
1347                 prog->fielddefs[i].s_name = LittleLong (infielddefs[i].s_name);
1348         }
1349
1350 /*      // append the darkplaces fields
1351         for (i = 0;i < (int) DPFIELDS;i++)
1352         {
1353                 pr_fielddefs[progs->numfielddefs].type = dpfields[i].type;
1354                 pr_fielddefs[progs->numfielddefs].ofs = progs->entityfields;
1355                 pr_fielddefs[progs->numfielddefs].s_name = PR_SetString(dpfields[i].string);
1356                 if (pr_fielddefs[progs->numfielddefs].type == ev_vector)
1357                         progs->entityfields += 3;
1358                 else
1359                         progs->entityfields++;
1360                 progs->numfielddefs++;
1361         }*/
1362
1363         // check required functions
1364         for(i=0 ; i < numrequiredfunc ; i++)
1365                 if(PRVM_ED_FindFunction(required_func[i]) == 0)
1366                         PRVM_ERROR("%s: %s not found in %s\n",PRVM_NAME, required_func[i], filename);
1367
1368         for (i=0 ; i<prog->progs->numglobals ; i++)
1369                 ((int *)prog->globals)[i] = LittleLong (((int *)prog->globals)[i]);
1370
1371         // moved edict_size calculation down here, below field adding code
1372         // LordHavoc: this no longer includes the edict_t header
1373         prog->edict_size = prog->progs->entityfields * 4;
1374         prog->edictareasize = prog->edict_size * MAX_EDICTS;
1375
1376         // LordHavoc: bounds check anything static
1377         for (i = 0,st = prog->statements;i < prog->progs->numstatements;i++,st++)
1378         {
1379                 switch (st->op)
1380                 {
1381                 case OP_IF:
1382                 case OP_IFNOT:
1383                         if ((unsigned short) st->a >= prog->progs->numglobals || st->b + i < 0 || st->b + i >= prog->progs->numstatements)
1384                                 PRVM_ERROR("PRVM_LoadProgs: out of bounds IF/IFNOT (statement %d) in %s\n", i, PRVM_NAME);
1385                         break;
1386                 case OP_GOTO:
1387                         if (st->a + i < 0 || st->a + i >= prog->progs->numstatements)
1388                                 PRVM_ERROR("PRVM_LoadProgs: out of bounds GOTO (statement %d) in %s\n", i, PRVM_NAME);
1389                         break;
1390                 // global global global
1391                 case OP_ADD_F:
1392                 case OP_ADD_V:
1393                 case OP_SUB_F:
1394                 case OP_SUB_V:
1395                 case OP_MUL_F:
1396                 case OP_MUL_V:
1397                 case OP_MUL_FV:
1398                 case OP_MUL_VF:
1399                 case OP_DIV_F:
1400                 case OP_BITAND:
1401                 case OP_BITOR:
1402                 case OP_GE:
1403                 case OP_LE:
1404                 case OP_GT:
1405                 case OP_LT:
1406                 case OP_AND:
1407                 case OP_OR:
1408                 case OP_EQ_F:
1409                 case OP_EQ_V:
1410                 case OP_EQ_S:
1411                 case OP_EQ_E:
1412                 case OP_EQ_FNC:
1413                 case OP_NE_F:
1414                 case OP_NE_V:
1415                 case OP_NE_S:
1416                 case OP_NE_E:
1417                 case OP_NE_FNC:
1418                 case OP_ADDRESS:
1419                 case OP_LOAD_F:
1420                 case OP_LOAD_FLD:
1421                 case OP_LOAD_ENT:
1422                 case OP_LOAD_S:
1423                 case OP_LOAD_FNC:
1424                 case OP_LOAD_V:
1425                         if ((unsigned short) st->a >= prog->progs->numglobals || (unsigned short) st->b >= prog->progs->numglobals || (unsigned short) st->c >= prog->progs->numglobals)
1426                                 PRVM_ERROR("PRVM_LoadProgs: out of bounds global index (statement %d)\n", i);
1427                         break;
1428                 // global none global
1429                 case OP_NOT_F:
1430                 case OP_NOT_V:
1431                 case OP_NOT_S:
1432                 case OP_NOT_FNC:
1433                 case OP_NOT_ENT:
1434                         if ((unsigned short) st->a >= prog->progs->numglobals || (unsigned short) st->c >= prog->progs->numglobals)
1435                                 PRVM_ERROR("PRVM_LoadProgs: out of bounds global index (statement %d) in %s\n", i, PRVM_NAME);
1436                         break;
1437                 // 2 globals
1438                 case OP_STOREP_F:
1439                 case OP_STOREP_ENT:
1440                 case OP_STOREP_FLD:
1441                 case OP_STOREP_S:
1442                 case OP_STOREP_FNC:
1443                 case OP_STORE_F:
1444                 case OP_STORE_ENT:
1445                 case OP_STORE_FLD:
1446                 case OP_STORE_S:
1447                 case OP_STORE_FNC:
1448                 case OP_STATE:
1449                 case OP_STOREP_V:
1450                 case OP_STORE_V:
1451                         if ((unsigned short) st->a >= prog->progs->numglobals || (unsigned short) st->b >= prog->progs->numglobals)
1452                                 PRVM_ERROR("PRVM_LoadProgs: out of bounds global index (statement %d)\n in %s", i, PRVM_NAME);
1453                         break;
1454                 // 1 global
1455                 case OP_CALL0:
1456                 case OP_CALL1:
1457                 case OP_CALL2:
1458                 case OP_CALL3:
1459                 case OP_CALL4:
1460                 case OP_CALL5:
1461                 case OP_CALL6:
1462                 case OP_CALL7:
1463                 case OP_CALL8:
1464                 case OP_DONE:
1465                 case OP_RETURN:
1466                         if ((unsigned short) st->a >= prog->progs->numglobals)
1467                                 PRVM_ERROR("PRVM_LoadProgs: out of bounds global index (statement %d) in %s\n", i, PRVM_NAME);
1468                         break;
1469                 default:
1470                         PRVM_ERROR("PRVM_LoadProgs: unknown opcode %d at statement %d in %s\n", st->op, i, PRVM_NAME);
1471                         break;
1472                 }
1473         }
1474
1475         PRVM_Init_Exec();
1476
1477         prog->loaded = TRUE;
1478         
1479         // set flags & ddef_ts in prog
1480         
1481         prog->flag = 0;
1482         
1483         prog->self = PRVM_ED_FindGlobal("self");
1484
1485         if(PRVM_ED_FindGlobal("time"))
1486                 prog->time = &PRVM_G_FLOAT(PRVM_ED_FindGlobal("time")->ofs);
1487
1488         if(PRVM_ED_FindField ("chain"))
1489                 prog->flag |= PRVM_FE_CHAIN;
1490
1491         if(PRVM_ED_FindField ("classname"))
1492                 prog->flag |= PRVM_FE_CLASSNAME; 
1493
1494         if(PRVM_ED_FindField ("nextthink") && PRVM_ED_FindField ("frame") && PRVM_ED_FindField ("think") 
1495                 && prog->flag && prog->self) 
1496                 prog->flag |= PRVM_OP_STATE;
1497         
1498         PRVM_GCALL(reset_cmd)();
1499         PRVM_GCALL(init_cmd)();
1500
1501         // init mempools
1502         PRVM_MEM_Alloc();
1503 }
1504
1505
1506 void PRVM_Fields_f (void)
1507 {
1508         int i, j, ednum, used, usedamount;
1509         int *counts;
1510         char tempstring[5000], tempstring2[260], *name;
1511         prvm_edict_t *ed;
1512         ddef_t *d;
1513         int *v;
1514
1515         // TODO
1516         /*
1517         if (!sv.active)
1518         {
1519                 Con_Print("no progs loaded\n");
1520                 return;
1521         }
1522         */
1523
1524         if(Cmd_Argc() != 2)
1525         {
1526                 Con_Print("prvm_fields <program name>\n");
1527                 return;
1528         }
1529
1530         PRVM_Begin;
1531         if(!PRVM_SetProgFromString(Cmd_Argv(1)))
1532                 return;
1533
1534         counts = Mem_Alloc(tempmempool, prog->progs->numfielddefs * sizeof(int));
1535         for (ednum = 0;ednum < prog->max_edicts;ednum++)
1536         {
1537                 ed = PRVM_EDICT_NUM(ednum);
1538                 if (ed->e->free)
1539                         continue;
1540                 for (i = 1;i < prog->progs->numfielddefs;i++)
1541                 {
1542                         d = &prog->fielddefs[i];
1543                         name = PRVM_GetString(d->s_name);
1544                         if (name[strlen(name)-2] == '_')
1545                                 continue;       // skip _x, _y, _z vars
1546                         v = (int *)((char *)ed->v + d->ofs*4);
1547                         // if the value is still all 0, skip the field
1548                         for (j = 0;j < prvm_type_size[d->type & ~DEF_SAVEGLOBAL];j++)
1549                         {
1550                                 if (v[j])
1551                                 {
1552                                         counts[i]++;
1553                                         break;
1554                                 }
1555                         }
1556                 }
1557         }
1558         used = 0;
1559         usedamount = 0;
1560         tempstring[0] = 0;
1561         for (i = 0;i < prog->progs->numfielddefs;i++)
1562         {
1563                 d = &prog->fielddefs[i];
1564                 name = PRVM_GetString(d->s_name);
1565                 if (name[strlen(name)-2] == '_')
1566                         continue;       // skip _x, _y, _z vars
1567                 switch(d->type & ~DEF_SAVEGLOBAL)
1568                 {
1569                 case ev_string:
1570                         strcat(tempstring, "string   ");
1571                         break;
1572                 case ev_entity:
1573                         strcat(tempstring, "entity   ");
1574                         break;
1575                 case ev_function:
1576                         strcat(tempstring, "function ");
1577                         break;
1578                 case ev_field:
1579                         strcat(tempstring, "field    ");
1580                         break;
1581                 case ev_void:
1582                         strcat(tempstring, "void     ");
1583                         break;
1584                 case ev_float:
1585                         strcat(tempstring, "float    ");
1586                         break;
1587                 case ev_vector:
1588                         strcat(tempstring, "vector   ");
1589                         break;
1590                 case ev_pointer:
1591                         strcat(tempstring, "pointer  ");
1592                         break;
1593                 default:
1594                         sprintf (tempstring2, "bad type %i ", d->type & ~DEF_SAVEGLOBAL);
1595                         strcat(tempstring, tempstring2);
1596                         break;
1597                 }
1598                 if (strlen(name) > 256)
1599                 {
1600                         memcpy (tempstring2, name, 256);
1601                         tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
1602                         tempstring2[259] = 0;
1603                         name = tempstring2;
1604                 }
1605                 strcat(tempstring, name);
1606                 for (j = strlen(name);j < 25;j++)
1607                         strcat(tempstring, " ");
1608                 sprintf(tempstring2, "%5d", counts[i]);
1609                 strcat(tempstring, tempstring2);
1610                 strcat(tempstring, "\n");
1611                 if (strlen(tempstring) >= 4096)
1612                 {
1613                         Con_Print(tempstring);
1614                         tempstring[0] = 0;
1615                 }
1616                 if (counts[i])
1617                 {
1618                         used++;
1619                         usedamount += prvm_type_size[d->type & ~DEF_SAVEGLOBAL];
1620                 }
1621         }
1622         Mem_Free(counts);
1623         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);
1624
1625         PRVM_End;
1626 }
1627
1628 void PRVM_Globals_f (void)
1629 {
1630         int i;
1631         // TODO
1632         /*if (!sv.active)
1633         {
1634                 Con_Print("no progs loaded\n");
1635                 return;
1636         }*/
1637         if(Cmd_Argc () != 2)
1638         {
1639                 Con_Print("prvm_globals <program name>\n");
1640                 return;
1641         }
1642
1643         PRVM_Begin;
1644         if(!PRVM_SetProgFromString (Cmd_Argv (1)))
1645                 return;
1646
1647         Con_Printf("%s :", PRVM_NAME);
1648
1649         for (i = 0;i < prog->progs->numglobaldefs;i++)
1650                 Con_Printf("%s\n", PRVM_GetString(prog->globaldefs[i].s_name));
1651         Con_Printf("%i global variables, totalling %i bytes\n", prog->progs->numglobals, prog->progs->numglobals * 4);
1652
1653         PRVM_End;
1654 }
1655
1656 /*
1657 ===============
1658 PRVM_Global
1659 ===============
1660 */
1661 void PRVM_Global_f(void)
1662 {
1663         ddef_t *global;
1664         if( Cmd_Argc() != 3 ) {
1665                 Con_Printf( "prvm_global <program name> <global name>\n" );
1666                 return;
1667         }
1668
1669         PRVM_Begin;
1670         if( !PRVM_SetProgFromString( Cmd_Argv(1) ) )
1671                 return;
1672
1673         global = PRVM_ED_FindGlobal( Cmd_Argv(2) );
1674         if( !global )
1675                 Con_Printf( "No global '%s' in %s!\n", Cmd_Argv(2), Cmd_Argv(1) );
1676         else
1677                 Con_Printf( "%s: %s\n", Cmd_Argv(2), PRVM_ValueString( global->type, (prvm_eval_t *) &prog->globals[ global->ofs ] ) ); 
1678         PRVM_End;
1679 }
1680
1681 /*
1682 ===============
1683 PRVM_Init
1684 ===============
1685 */
1686 void PRVM_Init (void)
1687 {
1688         Cmd_AddCommand ("prvm_edict", PRVM_ED_PrintEdict_f);
1689         Cmd_AddCommand ("prvm_edicts", PRVM_ED_PrintEdicts_f);
1690         Cmd_AddCommand ("prvm_edictcount", PRVM_ED_Count_f);
1691         Cmd_AddCommand ("prvm_profile", PRVM_Profile_f);
1692         Cmd_AddCommand ("prvm_fields", PRVM_Fields_f);
1693         Cmd_AddCommand ("prvm_globals", PRVM_Globals_f);
1694         Cmd_AddCommand ("prvm_global", PRVM_Global_f);
1695         Cmd_AddCommand ("prvm_edictset", PRVM_ED_EdictSet_f);
1696         // LordHavoc: optional runtime bounds checking (speed drain, but worth it for security, on by default - breaks most QCCX features (used by CRMod and others))
1697         Cvar_RegisterVariable (&prvm_boundscheck);
1698         Cvar_RegisterVariable (&prvm_traceqc);
1699
1700         //VM_Cmd_Init();
1701 }
1702
1703 /*
1704 ===============
1705 PRVM_InitProg
1706 ===============
1707 */
1708 void PRVM_InitProg(int prognr)
1709 {
1710         if(prognr < 0 || prognr >= PRVM_MAXPROGS)
1711                 Sys_Error("PRVM_InitProg: Invalid program number %i\n",prognr);
1712
1713         prog = &prog_list[prognr];
1714
1715         if(prog->loaded)
1716                 PRVM_ResetProg();
1717
1718         memset(prog, 0, sizeof(prvm_prog_t));
1719
1720         prog->time = &prog->_time;
1721 }
1722
1723 int PRVM_GetProgNr()
1724 {
1725         return prog - prog_list;
1726 }
1727
1728 // LordHavoc: turned PRVM_EDICT_NUM into a #define for speed reasons
1729 prvm_edict_t *PRVM_EDICT_NUM_ERROR(int n, char *filename, int fileline)
1730 {
1731         PRVM_ERROR ("PRVM_EDICT_NUM: %s: bad number %i (called at %s:%i)", PRVM_NAME, n, filename, fileline);
1732         return NULL;
1733 }
1734
1735 void PRVM_ProcessError(void)
1736 {
1737         if(prog)
1738                 PRVM_GCALL(error_cmd)();
1739 }
1740
1741 /*
1742 int NUM_FOR_EDICT_ERROR(edict_t *e)
1743 {
1744         Host_Error ("NUM_FOR_EDICT: bad pointer %p (world is %p, entity number would be %i)", e, sv.edicts, e - sv.edicts);
1745         return 0;
1746 }
1747
1748 int NUM_FOR_EDICT(edict_t *e)
1749 {
1750         int n;
1751         n = e - sv.edicts;
1752         if ((unsigned int)n >= MAX_EDICTS)
1753                 Host_Error ("NUM_FOR_EDICT: bad pointer");
1754         return n;
1755 }
1756
1757 //int NoCrash_NUM_FOR_EDICT(edict_t *e)
1758 //{
1759 //      return e - sv.edicts;
1760 //}
1761
1762 //#define       EDICT_TO_PROG(e) ((qbyte *)(((edict_t *)e)->v) - (qbyte *)(sv.edictsfields))
1763 //#define PROG_TO_EDICT(e) (sv.edicts + ((e) / (progs->entityfields * 4)))
1764 int EDICT_TO_PROG(edict_t *e)
1765 {
1766         int n;
1767         n = e - sv.edicts;
1768         if ((unsigned int)n >= (unsigned int)sv.max_edicts)
1769                 Host_Error("EDICT_TO_PROG: invalid edict %8p (number %i compared to world at %8p)\n", e, n, sv.edicts);
1770         return n;// EXPERIMENTAL
1771         //return (qbyte *)e->v - (qbyte *)sv.edictsfields;
1772 }
1773 edict_t *PROG_TO_EDICT(int n)
1774 {
1775         if ((unsigned int)n >= (unsigned int)sv.max_edicts)
1776                 Host_Error("PROG_TO_EDICT: invalid edict number %i\n", n);
1777         return sv.edicts + n; // EXPERIMENTAL
1778         //return sv.edicts + ((n) / (progs->entityfields * 4));
1779 }
1780 */
1781