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