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