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