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