2 Copyright (C) 1996-1997 Id Software, Inc.
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.
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.
13 See the GNU General Public License for more details.
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.
26 static prvm_prog_t prog_list[PRVM_MAXPROGS];
28 int prvm_type_size[8] = {1,sizeof(string_t)/4,1,3,1,1,sizeof(func_t)/4,sizeof(void *)/4};
30 ddef_t *PRVM_ED_FieldAtOfs(int ofs);
31 qboolean PRVM_ED_ParseEpair(prvm_edict_t *ent, ddef_t *key, const char *s);
33 // LordHavoc: optional runtime bounds checking (speed drain, but worth it for security, on by default - breaks most QCCX features (used by CRMod and others))
34 cvar_t prvm_boundscheck = {0, "prvm_boundscheck", "1"};
35 // LordHavoc: prints every opcode as it executes - warning: this is significant spew
36 cvar_t prvm_traceqc = {0, "prvm_traceqc", "0"};
38 ddef_t *PRVM_ED_FindField (const char *name);
39 mfunction_t *PRVM_ED_FindFunction (const char *name);
41 //============================================================================
53 // check bound of max_edicts
54 prog->max_edicts = min(prog->max_edicts,prog->limit_edicts);
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));
60 prog->edicts = Mem_Alloc(prog->edicts_mempool,prog->limit_edicts * sizeof(prvm_edict_t));
62 // alloc edict private space
63 prog->edictprivate = Mem_Alloc(prog->edicts_mempool, prog->max_edicts * prog->edictprivate_size);
66 prog->edictsfields = Mem_Alloc(prog->edicts_mempool, prog->max_edicts * prog->edict_size);
69 for(i = 0; i < prog->max_edicts; i++)
71 prog->edicts[i].e = (prvm_edict_private_t *)((qbyte *)prog->edictprivate + i * prog->edictprivate_size);
72 prog->edicts[i].v = (void*)((qbyte *)prog->edictsfields + i * prog->edict_size);
78 PRVM_MEM_IncreaseEdicts
81 void PRVM_MEM_IncreaseEdicts()
84 int oldmaxedicts = prog->max_edicts;
85 void *oldedictsfields = prog->edictsfields;
86 void *oldedictprivate = prog->edictprivate;
88 if(prog->max_edicts >= prog->limit_edicts)
91 PRVM_GCALL(begin_increase_edicts)();
94 prog->max_edicts = min(prog->max_edicts + 256, prog->limit_edicts);
96 prog->edictsfields = Mem_Alloc(prog->edicts_mempool, prog->max_edicts * prog->edict_size);
97 prog->edictprivate = Mem_Alloc(prog->edicts_mempool, prog->max_edicts * prog->edictprivate_size);
99 memcpy(prog->edictsfields, oldedictsfields, oldmaxedicts * prog->edict_size);
100 memcpy(prog->edictprivate, oldedictprivate, oldmaxedicts * prog->edictprivate_size);
102 //set e and v pointers
103 for(i = 0; i < prog->max_edicts; i++)
105 prog->edicts[i].e = (prvm_edict_private_t *)((qbyte *)prog->edictprivate + i * prog->edictprivate_size);
106 prog->edicts[i].v = (void*)((qbyte *)prog->edictsfields + i * prog->edict_size);
109 PRVM_GCALL(end_increase_edicts)();
111 Mem_Free(oldedictsfields);
112 Mem_Free(oldedictprivate);
115 //============================================================================
118 int PRVM_ED_FindFieldOffset(const char *field)
121 d = PRVM_ED_FindField(field);
127 qboolean PRVM_ProgLoaded(int prognr)
129 if(prognr < 0 || prognr >= PRVM_MAXPROGS)
132 return (prog_list[prognr].loaded ? TRUE : FALSE);
137 PRVM_SetProgFromString
140 // perhaps add a return value when the str doesnt exist
141 qboolean PRVM_SetProgFromString(const char *str)
144 for(; i < PRVM_MAXPROGS ; i++)
145 if(prog_list[i].name && !strcmp(prog_list[i].name,str))
147 if(prog_list[i].loaded)
149 prog = &prog_list[i];
154 Con_Printf("%s not loaded !\n",PRVM_NAME);
159 Con_Printf("Invalid program name %s !\n", str);
168 void PRVM_SetProg(int prognr)
170 if(prognr && prognr < PRVM_MAXPROGS)
172 if(prog_list[prognr].loaded)
173 prog = &prog_list[prognr];
175 PRVM_ERROR("%i(%s) not loaded !\n", prognr, PRVM_NAME);
178 PRVM_ERROR("Invalid program number %i\n", prognr);
185 Sets everything to NULL
188 void PRVM_ED_ClearEdict (prvm_edict_t *e)
191 memset (e->v, 0, prog->progs->entityfields * 4);
193 // LordHavoc: for consistency set these here
194 num = PRVM_NUM_FOR_EDICT(e) - 1;
196 // AK: Let the init_edict function determine if something needs to be initialized
197 PRVM_GCALL(init_edict)(num);
204 Either finds a free edict, or allocates a new one.
205 Try to avoid reusing an entity that was recently freed, because it
206 can cause the client to think the entity morphed into something else
207 instead of being removed and recreated, which can cause interpolated
208 angles and bad trails.
211 prvm_edict_t *PRVM_ED_Alloc (void)
216 // the client qc dont need maxclients
217 // thus it doesnt need to use svs.maxclients
218 // AK: changed i=svs.maxclients+1
219 for (i = 0;i < prog->num_edicts;i++)
221 e = PRVM_EDICT_NUM(i);
222 // the first couple seconds of server time can involve a lot of
223 // freeing and allocating, so relax the replacement policy
224 if (e->e->free && ( e->e->freetime < 2 || prog->time - e->e->freetime > 0.5 ) )
226 PRVM_ED_ClearEdict (e);
232 PRVM_ERROR ("%s: PRVM_ED_Alloc: no free edicts",PRVM_NAME);
235 if (prog->num_edicts >= prog->max_edicts)
236 PRVM_MEM_IncreaseEdicts();
238 e = PRVM_EDICT_NUM(i);
239 PRVM_ED_ClearEdict (e);
248 Marks the edict as free
249 FIXME: walk all entities and NULL out references to this entity
252 void PRVM_ED_Free (prvm_edict_t *ed)
254 PRVM_GCALL(free_edict)(ed);
257 ed->e->freetime = prog->time;
260 //===========================================================================
267 ddef_t *PRVM_ED_GlobalAtOfs (int ofs)
272 for (i=0 ; i<prog->progs->numglobaldefs ; i++)
274 def = &prog->globaldefs[i];
286 ddef_t *PRVM_ED_FieldAtOfs (int ofs)
291 for (i=0 ; i<prog->progs->numfielddefs ; i++)
293 def = &prog->fielddefs[i];
305 ddef_t *PRVM_ED_FindField (const char *name)
310 for (i=0 ; i<prog->progs->numfielddefs ; i++)
312 def = &prog->fielddefs[i];
313 if (!strcmp(PRVM_GetString(def->s_name), name))
324 ddef_t *PRVM_ED_FindGlobal (const char *name)
329 for (i=0 ; i<prog->progs->numglobaldefs ; i++)
331 def = &prog->globaldefs[i];
332 if (!strcmp(PRVM_GetString(def->s_name), name))
344 mfunction_t *PRVM_ED_FindFunction (const char *name)
349 for (i=0 ; i<prog->progs->numfunctions ; i++)
351 func = &prog->functions[i];
352 if (!strcmp(PRVM_GetString(func->s_name), name))
363 Returns a string describing *data in a type specific manner
366 char *PRVM_ValueString (etype_t type, prvm_eval_t *val)
368 static char line[1024]; // LordHavoc: enlarged a bit (was 256)
373 type &= ~DEF_SAVEGLOBAL;
378 sprintf (line, "%s", PRVM_GetString(val->string));
382 if (n < 0 || n >= MAX_EDICTS)
383 sprintf (line, "entity %i (invalid!)", n);
385 sprintf (line, "entity %i", n);
388 f = prog->functions + val->function;
389 sprintf (line, "%s()", PRVM_GetString(f->s_name));
392 def = PRVM_ED_FieldAtOfs ( val->_int );
393 sprintf (line, ".%s", PRVM_GetString(def->s_name));
396 sprintf (line, "void");
399 // LordHavoc: changed from %5.1f to %10.4f
400 sprintf (line, "%10.4f", val->_float);
403 // LordHavoc: changed from %5.1f to %10.4f
404 sprintf (line, "'%10.4f %10.4f %10.4f'", val->vector[0], val->vector[1], val->vector[2]);
407 sprintf (line, "pointer");
410 sprintf (line, "bad type %i", type);
421 Returns a string describing *data in a type specific manner
422 Easier to parse than PR_ValueString
425 char *PRVM_UglyValueString (etype_t type, prvm_eval_t *val)
427 static char line[4096];
433 type &= ~DEF_SAVEGLOBAL;
438 // Parse the string a bit to turn special characters
439 // (like newline, specifically) into escape codes,
440 // this fixes saving games from various mods
441 s = PRVM_GetString (val->string);
442 for (i = 0;i < (int)sizeof(line) - 2 && *s;)
461 snprintf (line, sizeof (line), "%i", PRVM_NUM_FOR_EDICT(PRVM_PROG_TO_EDICT(val->edict)));
464 f = pr_functions + val->function;
465 snprintf (line, sizeof (line), "%s", PRVM_GetString(f->s_name));
468 def = PRVM_ED_FieldAtOfs ( val->_int );
469 snprintf (line, sizeof (line), ".%s", PRVM_GetString(def->s_name));
472 snprintf (line, sizeof (line), "void");
475 snprintf (line, sizeof (line), "%f", val->_float);
478 snprintf (line, sizeof (line), "%f %f %f", val->vector[0], val->vector[1], val->vector[2]);
481 snprintf (line, sizeof (line), "bad type %i", type);
492 Returns a string with a description and the contents of a global,
493 padded to 20 field width
496 char *PRVM_GlobalString (int ofs)
502 static char line[128];
504 val = (void *)&prog->globals[ofs];
505 def = PRVM_ED_GlobalAtOfs(ofs);
507 sprintf (line,"%i(?)", ofs);
510 s = PRVM_ValueString (def->type, val);
511 sprintf (line,"%i(%s)%s", ofs, PRVM_GetString(def->s_name), s);
522 char *PRVM_GlobalStringNoContents (int ofs)
526 static char line[128];
528 def = PRVM_ED_GlobalAtOfs(ofs);
530 sprintf (line,"%i(?)", ofs);
532 sprintf (line,"%i(%s)", ofs, PRVM_GetString(def->s_name));
550 // LordHavoc: optimized this to print out much more quickly (tempstring)
551 // LordHavoc: changed to print out every 4096 characters (incase there are a lot of fields to print)
552 void PRVM_ED_Print (prvm_edict_t *ed)
560 char tempstring[8192], tempstring2[260]; // temporary string buffers
564 Con_Printf ("%s: FREE\n",PRVM_NAME);
569 sprintf(tempstring, "\n%s EDICT %i:\n", PRVM_NAME, PRVM_NUM_FOR_EDICT(ed));
570 for (i=1 ; i<prog->progs->numfielddefs ; i++)
572 d = &prog->fielddefs[i];
573 name = PRVM_GetString(d->s_name);
574 if (name[strlen(name)-2] == '_')
575 continue; // skip _x, _y, _z vars
577 v = (int *)((char *)ed->v + d->ofs*4);
579 // if the value is still all 0, skip the field
580 type = d->type & ~DEF_SAVEGLOBAL;
582 for (j=0 ; j<prvm_type_size[type] ; j++)
585 if (j == prvm_type_size[type])
588 if (strlen(name) > 256)
590 strncpy(tempstring2, name, 256);
591 tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
592 tempstring2[259] = 0;
595 strcat(tempstring, name);
596 for (l = strlen(name);l < 14;l++)
597 strcat(tempstring, " ");
598 strcat(tempstring, " ");
600 name = PRVM_ValueString(d->type, (prvm_eval_t *)v);
601 if (strlen(name) > 256)
603 strncpy(tempstring2, name, 256);
604 tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
605 tempstring2[259] = 0;
608 strcat(tempstring, name);
609 strcat(tempstring, "\n");
610 if (strlen(tempstring) >= 4096)
612 Con_Printf("%s", tempstring);
617 Con_Printf("%s", tempstring);
627 void PRVM_ED_Write (qfile_t *f, prvm_edict_t *ed)
635 FS_Printf (f, "{\n");
639 FS_Printf (f, "}\n");
643 for (i=1 ; i<prog->progs->numfielddefs ; i++)
645 d = &prog->fielddefs[i];
646 name = PRVM_GetString(d->s_name);
647 if (name[strlen(name)-2] == '_')
648 continue; // skip _x, _y, _z vars
650 v = (int *)((char *)ed->v + d->ofs*4);
652 // if the value is still all 0, skip the field
653 type = d->type & ~DEF_SAVEGLOBAL;
654 for (j=0 ; j<prvm_type_size[type] ; j++)
657 if (j == prvm_type_size[type])
660 FS_Printf (f,"\"%s\" ",name);
661 FS_Printf (f,"\"%s\"\n", PRVM_UglyValueString(d->type, (prvm_eval_t *)v));
664 FS_Printf (f, "}\n");
667 void PRVM_ED_PrintNum (int ent)
669 PRVM_ED_Print (PRVM_EDICT_NUM(ent));
674 PRVM_ED_PrintEdicts_f
676 For debugging, prints all the entities in the current server
679 void PRVM_ED_PrintEdicts_f (void)
685 Con_Print("prvm_edicts <program name>\n");
690 if(!PRVM_SetProgFromString(Cmd_Argv(1)))
693 Con_Printf ("%s: %i entities\n", PRVM_NAME, prog->num_edicts);
694 for (i=0 ; i<prog->num_edicts ; i++)
695 PRVM_ED_PrintNum (i);
704 For debugging, prints a single edict
707 void PRVM_ED_PrintEdict_f (void)
713 Con_Print("prvm_edict <program name> <edict number>\n");
718 if(!PRVM_SetProgFromString(Cmd_Argv(1)))
721 i = atoi (Cmd_Argv(2));
722 if (i >= prog->num_edicts)
724 Con_Printf("Bad edict number\n");
727 PRVM_ED_PrintNum (i);
739 // 2 possibilities : 1. just displaying the active edict count
740 // 2. making a function pointer [x]
741 void PRVM_ED_Count_f (void)
749 Con_Print("prvm_count <program name>\n");
754 if(!PRVM_SetProgFromString(Cmd_Argv(1)))
757 if(prog->count_edicts)
758 prog->count_edicts();
762 for (i=0 ; i<prog->num_edicts ; i++)
764 ent = PRVM_EDICT_NUM(i);
770 Con_Printf ("num_edicts:%3i\n", sv.num_edicts);
771 Con_Printf ("active :%3i\n", active);
778 ==============================================================================
782 FIXME: need to tag constants, doesn't really work
783 ==============================================================================
791 void PRVM_ED_WriteGlobals (qfile_t *f)
799 for (i=0 ; i<prog->progs->numglobaldefs ; i++)
801 def = &prog->globaldefs[i];
803 if ( !(def->type & DEF_SAVEGLOBAL) )
805 type &= ~DEF_SAVEGLOBAL;
807 if (type != ev_string && type != ev_float && type != ev_entity)
810 name = PRVM_GetString(def->s_name);
811 FS_Printf (f,"\"%s\" ", name);
812 FS_Printf (f,"\"%s\"\n", PRVM_UglyValueString(type, (prvm_eval_t *)&prog->globals[def->ofs]));
822 void PRVM_ED_ParseGlobals (const char *data)
824 char keyname[1024]; // LordHavoc: good idea? bad idea? was 64
830 if (!COM_ParseToken(&data, false))
831 PRVM_ERROR ("PRVM_ED_ParseEntity: EOF without closing brace");
832 if (com_token[0] == '}')
835 strcpy (keyname, com_token);
838 if (!COM_ParseToken(&data, false))
839 PRVM_ERROR ("PRVM_ED_ParseEntity: EOF without closing brace");
841 if (com_token[0] == '}')
842 PRVM_ERROR ("PRVM_ED_ParseEntity: closing brace without data");
844 key = PRVM_ED_FindGlobal (keyname);
847 Con_DPrintf ("'%s' is not a global on %s\n", keyname, PRVM_NAME);
851 if (!PRVM_ED_ParseEpair(NULL, key, com_token))
852 PRVM_ERROR ("PRVM_ED_ParseGlobals: parse error");
856 //============================================================================
864 char *PRVM_ED_NewString (const char *string)
869 l = strlen(string) + 1;
870 new = Mem_Alloc(prog->edictstring_mempool, l);
873 for (i=0 ; i< l ; i++)
875 if (string[i] == '\\' && i < l-1)
878 if (string[i] == 'n')
884 *new_p++ = string[i];
895 Can parse either fields or globals
896 returns false if error
899 qboolean PRVM_ED_ParseEpair(prvm_edict_t *ent, ddef_t *key, const char *s)
907 val = (prvm_eval_t *)((int *)ent->v + key->ofs);
909 val = (prvm_eval_t *)((int *)pr_globals + key->ofs);
910 switch (key->type & ~DEF_SAVEGLOBAL)
913 val->string = PRVM_SetString(ED_NewString(s));
917 while (*s && *s <= ' ')
919 val->_float = atof(s);
923 for (i = 0;i < 3;i++)
925 while (*s && *s <= ' ')
929 val->vector[i] = atof(s);
938 while (*s && *s <= ' ')
941 if (i < 0 || i >= MAX_EDICTS)
942 Con_Printf("PRVM_ED_ParseEpair: ev_entity reference too large (edict %i >= MAX_EDICTS %i) on %s\n", i, MAX_EDICTS, PRVM_NAME);
943 while (i >= prog->max_edicts)
944 PRVM_MEM_IncreaseEdicts();
945 //SV_IncreaseEdicts();
946 // if SV_IncreaseEdicts was called the base pointer needs to be updated
948 val = (prvm_eval_t *)((int *)ent->v + key->ofs);
949 val->edict = PRVM_EDICT_TO_PROG(EDICT_NUM(i));
953 def = PRVM_ED_FindField(s);
956 Con_DPrintf("PRVM_ED_ParseEpair: Can't find field %s on %s\n", s, PRVM_NAME);
959 val->_int = PRVM_G_INT(def->ofs);
963 func = PRVM_ED_FindFunction(s);
966 Con_Printf ("PRVM_ED_ParseEpair: Can't find function %s on %s\n", s, PRVM_NAME);
969 val->function = func - prog->functions;
973 Con_Printf("PRVM_ED_ParseEpair: Unknown key->type %i for key \"%s\" on %s\n", key->type, PR_GetString(key->s_name), PRVM_NAME);
983 Parses an edict out of the given string, returning the new position
984 ed should be a properly initialized empty edict.
985 Used for initial level load and for savegames.
988 const char *PRVM_ED_ParseEdict (const char *data, prvm_edict_t *ent)
999 if (ent != prog->edicts) // hack
1000 memset (ent->v, 0, prog->progs->entityfields * 4);
1002 // go through all the dictionary pairs
1006 if (!COM_ParseToken(&data, false))
1007 PRVM_ERROR ("PRVM_ED_ParseEntity: EOF without closing brace");
1008 if (com_token[0] == '}')
1011 // anglehack is to allow QuakeEd to write single scalar angles
1012 // and allow them to be turned into vectors. (FIXME...)
1013 if (!strcmp(com_token, "angle"))
1015 strcpy (com_token, "angles");
1021 // FIXME: change light to _light to get rid of this hack
1022 if (!strcmp(com_token, "light"))
1023 strcpy (com_token, "light_lev"); // hack for single light def
1025 strcpy (keyname, com_token);
1027 // another hack to fix heynames with trailing spaces
1028 n = strlen(keyname);
1029 while (n && keyname[n-1] == ' ')
1036 if (!COM_ParseToken(&data, false))
1037 PRVM_ERROR ("PRVM_ED_ParseEntity: EOF without closing brace");
1039 if (com_token[0] == '}')
1040 PRVM_ERROR ("PRVM_ED_ParseEntity: closing brace without data");
1044 // keynames with a leading underscore are used for utility comments,
1045 // and are immediately discarded by quake
1046 if (keyname[0] == '_')
1049 key = PRVM_ED_FindField (keyname);
1052 Con_DPrintf ("%s: '%s' is not a field\n", PRVM_NAME, keyname);
1059 strcpy (temp, com_token);
1060 sprintf (com_token, "0 %s 0", temp);
1063 if (!PRVM_ED_ParseEpair(ent, key, com_token))
1064 PRVM_ERROR ("PRVM_ED_ParseEdict: parse error");
1068 ent->e->free = true;
1076 PRVM_ED_LoadFromFile
1078 The entities are directly placed in the array, rather than allocated with
1079 PRVM_ED_Alloc, because otherwise an error loading the map would have entity
1080 number references out of order.
1082 Creates a server's entity / program execution context by
1083 parsing textual entity definitions out of an ent file.
1085 Used for both fresh maps and savegame loads. A fresh map would also need
1086 to call PRVM_ED_CallSpawnFunctions () to let the objects initialize themselves.
1089 void PRVM_ED_LoadFromFile (const char *data)
1092 int parsed, inhibited, spawned, died;
1102 if(prog->flag & PRVM_GE_TIME)
1103 PRVM_G_FLOAT(PRVM_ED_FindFieldOffset("time")) = prog->time;
1108 // parse the opening brace
1109 if (!COM_ParseToken(&data, false))
1111 if (com_token[0] != '{')
1112 PRVM_ERROR ("PRVM_ED_LoadFromFile: found %s when expecting (%s) {",com_token, PRVM_NAME);
1115 ent = PRVM_EDICT_NUM(0);
1117 ent = PRVM_ED_Alloc ();
1118 data = PRVM_ED_ParseEdict (data, ent);
1121 // remove the entity ?
1122 if(prog->load_edict && !prog->load_edict(ent))
1130 // immediately call spawn function, but only if there is a self global
1132 if(prog->self && prog->flag & PRVM_FE_CLASSNAME)
1134 string_t handle = *(string_t*)&((float*)ent->v)[PRVM_ED_FindFieldOffset("classname")];
1137 Con_Printf ("No classname for:\n");
1138 PRVM_ED_Print (ent);
1143 // look for the spawn function
1144 func = PRVM_ED_FindFunction (PRVM_GetString(handle));
1148 if (developer.integer) // don't confuse non-developers with errors
1150 Con_Printf ("No spawn function for:\n");
1151 PRVM_ED_Print (ent);
1158 PRVM_G_INT(prog->self->ofs) = PRVM_EDICT_TO_PROG(ent);
1159 PRVM_ExecuteProgram (func - prog->functions, "");
1167 Con_DPrintf ("%s: %i entities parsed, %i inhibited, %i spawned (%i removed self, %i stayed)\n", PRVM_NAME, parsed, inhibited, spawned, died, spawned - died);
1172 typedef struct dpfield_s
1179 #define DPFIELDS (sizeof(dpfields) / sizeof(dpfield_t))
1181 dpfield_t dpfields[] =
1192 void PRVM_ResetProg()
1194 mempool_t *t1, *t2, *t3;
1196 t1 = prog->progs_mempool;
1197 t2 = prog->edictstring_mempool;
1198 t3 = prog->edicts_mempool;
1200 Mem_EmptyPool(prog->progs_mempool);
1201 Mem_EmptyPool(prog->edictstring_mempool);
1202 Mem_EmptyPool(prog->edicts_mempool);
1204 memset(prog,0,sizeof(prvm_prog_t));
1207 prog->progs_mempool = t1;
1208 prog->edictstring_mempool = t2;
1209 prog->edicts_mempool = t3;
1211 PRVM_GCALL(reset_cmd)();
1219 void PRVM_LoadProgs (const char * filename, int numrequiredfunc, char **required_func)
1223 ddef_t *infielddefs;
1225 dfunction_t *dfunctions;
1227 Mem_EmptyPool(prog->progs_mempool);
1228 Mem_EmptyPool(prog->edictstring_mempool);
1230 temp = FS_LoadFile (filename, false);
1232 PRVM_ERROR ("PRVM_LoadProgs: couldn't load %s for %s", filename, PRVM_NAME);
1234 prog->progs = (dprograms_t *)Mem_Alloc(prog->progs_mempool, fs_filesize);
1236 memcpy(prog->progs, temp, fs_filesize);
1239 Con_DPrintf ("%s programs occupy %iK.\n", PRVM_NAME, fs_filesize/1024);
1241 pr_crc = CRC_Block((qbyte *)prog->progs, fs_filesize);
1243 // byte swap the header
1244 for (i = 0;i < (int) sizeof(*prog->progs) / 4;i++)
1245 ((int *)prog->progs)[i] = LittleLong ( ((int *)prog->progs)[i] );
1247 if (prog->progs->version != PROG_VERSION)
1248 PRVM_ERROR ("%s: %s has wrong version number (%i should be %i)", PRVM_NAME, filename, prog->progs->version, PROG_VERSION);
1249 if (prog->progs->crc != prog->crc)
1250 PRVM_ERROR ("%s: %s system vars have been modified, progdefs.h is out of date", PRVM_NAME, filename);
1252 //pr_functions = (dfunction_t *)((qbyte *)progs + progs->ofs_functions);
1253 dfunctions = (dfunction_t *)((qbyte *)prog->progs + prog->progs->ofs_functions);
1254 prog->strings = (char *)prog->progs + prog->progs->ofs_strings;
1255 prog->globaldefs = (ddef_t *)((qbyte *)prog->progs + prog->progs->ofs_globaldefs);
1257 // we need to expand the fielddefs list to include all the engine fields,
1258 // so allocate a new place for it
1259 infielddefs = (ddef_t *)((qbyte *)prog->progs + prog->progs->ofs_fielddefs);
1261 prog->fielddefs = Mem_Alloc(prog->progs_mempool, prog->progs->numfielddefs * sizeof(ddef_t));
1263 prog->statements = (dstatement_t *)((qbyte *)prog->progs + prog->progs->ofs_statements);
1265 // moved edict_size calculation down below field adding code
1267 //pr_global_struct = (globalvars_t *)((qbyte *)progs + progs->ofs_globals);
1268 prog->globals = (float *)((qbyte *)prog->progs + prog->progs->ofs_globals);
1270 // byte swap the lumps
1271 for (i=0 ; i<prog->progs->numstatements ; i++)
1273 prog->statements[i].op = LittleShort(prog->statements[i].op);
1274 prog->statements[i].a = LittleShort(prog->statements[i].a);
1275 prog->statements[i].b = LittleShort(prog->statements[i].b);
1276 prog->statements[i].c = LittleShort(prog->statements[i].c);
1279 prog->functions = Mem_Alloc(prog->progs_mempool, sizeof(mfunction_t) * prog->progs->numfunctions);
1280 for (i = 0;i < prog->progs->numfunctions;i++)
1282 prog->functions[i].first_statement = LittleLong (dfunctions[i].first_statement);
1283 prog->functions[i].parm_start = LittleLong (dfunctions[i].parm_start);
1284 prog->functions[i].s_name = LittleLong (dfunctions[i].s_name);
1285 prog->functions[i].s_file = LittleLong (dfunctions[i].s_file);
1286 prog->functions[i].numparms = LittleLong (dfunctions[i].numparms);
1287 prog->functions[i].locals = LittleLong (dfunctions[i].locals);
1288 memcpy(prog->functions[i].parm_size, dfunctions[i].parm_size, sizeof(dfunctions[i].parm_size));
1291 for (i=0 ; i<prog->progs->numglobaldefs ; i++)
1293 prog->globaldefs[i].type = LittleShort (prog->globaldefs[i].type);
1294 prog->globaldefs[i].ofs = LittleShort (prog->globaldefs[i].ofs);
1295 prog->globaldefs[i].s_name = LittleLong (prog->globaldefs[i].s_name);
1298 // copy the progs fields to the new fields list
1299 for (i = 0;i < prog->progs->numfielddefs;i++)
1301 prog->fielddefs[i].type = LittleShort (infielddefs[i].type);
1302 if (prog->fielddefs[i].type & DEF_SAVEGLOBAL)
1303 PRVM_ERROR ("PRVM_LoadProgs: prog->fielddefs[i].type & DEF_SAVEGLOBAL in %s", PRVM_NAME);
1304 prog->fielddefs[i].ofs = LittleShort (infielddefs[i].ofs);
1305 prog->fielddefs[i].s_name = LittleLong (infielddefs[i].s_name);
1308 /* // append the darkplaces fields
1309 for (i = 0;i < (int) DPFIELDS;i++)
1311 pr_fielddefs[progs->numfielddefs].type = dpfields[i].type;
1312 pr_fielddefs[progs->numfielddefs].ofs = progs->entityfields;
1313 pr_fielddefs[progs->numfielddefs].s_name = PR_SetString(dpfields[i].string);
1314 if (pr_fielddefs[progs->numfielddefs].type == ev_vector)
1315 progs->entityfields += 3;
1317 progs->entityfields++;
1318 progs->numfielddefs++;
1321 // check required functions
1322 for(i=0 ; i < numrequiredfunc ; i++)
1323 if(PRVM_ED_FindFunction(required_func[i]) == 0)
1324 PRVM_ERROR("%s: %s not found in %s\n",PRVM_NAME, required_func[i], filename);
1326 for (i=0 ; i<prog->progs->numglobals ; i++)
1327 ((int *)prog->globals)[i] = LittleLong (((int *)prog->globals)[i]);
1329 // moved edict_size calculation down here, below field adding code
1330 // LordHavoc: this no longer includes the edict_t header
1331 prog->edict_size = prog->progs->entityfields * 4;
1332 prog->edictareasize = prog->edict_size * MAX_EDICTS;
1334 // LordHavoc: bounds check anything static
1335 for (i = 0,st = prog->statements;i < prog->progs->numstatements;i++,st++)
1341 if ((unsigned short) st->a >= prog->progs->numglobals || st->b + i < 0 || st->b + i >= prog->progs->numstatements)
1342 PRVM_ERROR("PRVM_LoadProgs: out of bounds IF/IFNOT (statement %d) in %s\n", i, PRVM_NAME);
1345 if (st->a + i < 0 || st->a + i >= prog->progs->numstatements)
1346 PRVM_ERROR("PRVM_LoadProgs: out of bounds GOTO (statement %d) in %s\n", i, PRVM_NAME);
1348 // global global global
1383 if ((unsigned short) st->a >= prog->progs->numglobals || (unsigned short) st->b >= prog->progs->numglobals || (unsigned short) st->c >= prog->progs->numglobals)
1384 PRVM_ERROR("PRVM_LoadProgs: out of bounds global index (statement %d)\n", i);
1386 // global none global
1392 if ((unsigned short) st->a >= prog->progs->numglobals || (unsigned short) st->c >= prog->progs->numglobals)
1393 PRVM_ERROR("PRVM_LoadProgs: out of bounds global index (statement %d) in %s\n", i, PRVM_NAME);
1409 if ((unsigned short) st->a >= prog->progs->numglobals || (unsigned short) st->b >= prog->progs->numglobals)
1410 PRVM_ERROR("PRVM_LoadProgs: out of bounds global index (statement %d)\n in %s", i, PRVM_NAME);
1424 if ((unsigned short) st->a >= prog->progs->numglobals)
1425 PRVM_ERROR("PRVM_LoadProgs: out of bounds global index (statement %d) in %s\n", i, PRVM_NAME);
1428 PRVM_ERROR("PRVM_LoadProgs: unknown opcode %d at statement %d in %s\n", st->op, i, PRVM_NAME);
1435 prog->loaded = TRUE;
1437 // set flags & ddef_ts in prog
1441 prog->self = PRVM_ED_FindGlobal("self");
1443 if(PRVM_ED_FindGlobal("time"))
1444 prog->flag |= PRVM_GE_TIME;
1446 if(PRVM_ED_FindFieldOffset ("classname"))
1447 prog->flag |= PRVM_FE_CLASSNAME;
1449 if(PRVM_ED_FindFieldOffset ("nextthink") && PRVM_ED_FindFieldOffset("frame") && PRVM_ED_FindFieldOffset("think")
1450 && prog->flag & PRVM_GE_TIME && prog->self)
1451 prog->flag |= PRVM_OP_STATE;
1453 PRVM_GCALL(reset_cmd)();
1460 void PRVM_Fields_f (void)
1462 int i, j, ednum, used, usedamount;
1464 char tempstring[5000], tempstring2[260], *name;
1473 Con_Printf("no progs loaded\n");
1480 Con_Print("prvm_fields <program name>\n");
1485 if(!PRVM_SetProgFromString(Cmd_Argv(1)))
1488 counts = Mem_Alloc(tempmempool, prog->progs->numfielddefs * sizeof(int));
1489 for (ednum = 0;ednum < prog->max_edicts;ednum++)
1491 ed = PRVM_EDICT_NUM(ednum);
1494 for (i = 1;i < prog->progs->numfielddefs;i++)
1496 d = &prog->fielddefs[i];
1497 name = PRVM_GetString(d->s_name);
1498 if (name[strlen(name)-2] == '_')
1499 continue; // skip _x, _y, _z vars
1500 v = (int *)((char *)ed->v + d->ofs*4);
1501 // if the value is still all 0, skip the field
1502 for (j = 0;j < prvm_type_size[d->type & ~DEF_SAVEGLOBAL];j++)
1515 for (i = 0;i < prog->progs->numfielddefs;i++)
1517 d = &prog->fielddefs[i];
1518 name = PRVM_GetString(d->s_name);
1519 if (name[strlen(name)-2] == '_')
1520 continue; // skip _x, _y, _z vars
1521 switch(d->type & ~DEF_SAVEGLOBAL)
1524 strcat(tempstring, "string ");
1527 strcat(tempstring, "entity ");
1530 strcat(tempstring, "function ");
1533 strcat(tempstring, "field ");
1536 strcat(tempstring, "void ");
1539 strcat(tempstring, "float ");
1542 strcat(tempstring, "vector ");
1545 strcat(tempstring, "pointer ");
1548 sprintf (tempstring2, "bad type %i ", d->type & ~DEF_SAVEGLOBAL);
1549 strcat(tempstring, tempstring2);
1552 if (strlen(name) > 256)
1554 strncpy(tempstring2, name, 256);
1555 tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
1556 tempstring2[259] = 0;
1559 strcat(tempstring, name);
1560 for (j = strlen(name);j < 25;j++)
1561 strcat(tempstring, " ");
1562 sprintf(tempstring2, "%5d", counts[i]);
1563 strcat(tempstring, tempstring2);
1564 strcat(tempstring, "\n");
1565 if (strlen(tempstring) >= 4096)
1567 Con_Printf("%s", tempstring);
1573 usedamount += prvm_type_size[d->type & ~DEF_SAVEGLOBAL];
1577 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);
1582 void PRVM_Globals_f (void)
1588 Con_Printf("no progs loaded\n");
1591 if(Cmd_Argc () != 2)
1593 Con_Print ("prvm_globals <program name>\n");
1598 if(!PRVM_SetProgFromString (Cmd_Argv (1)))
1601 Con_Printf("%s :", PRVM_NAME);
1603 for (i = 0;i < prog->progs->numglobaldefs;i++)
1604 Con_Printf("%s\n", PRVM_GetString(pr_globaldefs[i].s_name));
1605 Con_Printf("%i global variables, totalling %i bytes\n", prog->progs->numglobals, prog->progs->numglobals * 4);
1615 void PRVM_Init (void)
1617 Cmd_AddCommand ("prvm_edict", PRVM_ED_PrintEdict_f);
1618 Cmd_AddCommand ("prvm_edicts", PRVM_ED_PrintEdicts_f);
1619 Cmd_AddCommand ("prvm_edictcount", PRVM_ED_Count_f);
1620 Cmd_AddCommand ("prvm_profile", PRVM_Profile_f);
1621 Cmd_AddCommand ("prvm_fields", PRVM_Fields_f);
1622 Cmd_AddCommand ("prvm_globals", PRVM_Globals_f);
1623 // LordHavoc: optional runtime bounds checking (speed drain, but worth it for security, on by default - breaks most QCCX features (used by CRMod and others))
1624 Cvar_RegisterVariable (&prvm_boundscheck);
1625 Cvar_RegisterVariable (&prvm_traceqc);
1635 void PRVM_InitProg(int prognr)
1637 if(prognr < 0 || prognr >= PRVM_MAXPROGS)
1638 Sys_Error("PRVM_InitProg: Invalid program number %i\n",prognr);
1640 prog = &prog_list[prognr];
1642 memset(prog, 0, sizeof(prvm_prog_t));
1644 PRVM_GCALL(init_cmd)();
1647 int PRVM_GetProgNr()
1649 return prog - prog_list;
1652 // LordHavoc: turned PRVM_EDICT_NUM into a #define for speed reasons
1653 prvm_edict_t *PRVM_EDICT_NUM_ERROR(int n, char *filename, int fileline)
1655 PRVM_ERROR ("PRVM_EDICT_NUM: %s: bad number %i (called at %s:%i)", PRVM_NAME, n, filename, fileline);
1660 int NUM_FOR_EDICT_ERROR(edict_t *e)
1662 Host_Error ("NUM_FOR_EDICT: bad pointer %p (world is %p, entity number would be %i)", e, sv.edicts, e - sv.edicts);
1666 int NUM_FOR_EDICT(edict_t *e)
1670 if ((unsigned int)n >= MAX_EDICTS)
1671 Host_Error ("NUM_FOR_EDICT: bad pointer");
1675 //int NoCrash_NUM_FOR_EDICT(edict_t *e)
1677 // return e - sv.edicts;
1680 //#define EDICT_TO_PROG(e) ((qbyte *)(((edict_t *)e)->v) - (qbyte *)(sv.edictsfields))
1681 //#define PROG_TO_EDICT(e) (sv.edicts + ((e) / (progs->entityfields * 4)))
1682 int EDICT_TO_PROG(edict_t *e)
1686 if ((unsigned int)n >= (unsigned int)sv.max_edicts)
1687 Host_Error("EDICT_TO_PROG: invalid edict %8p (number %i compared to world at %8p)\n", e, n, sv.edicts);
1688 return n;// EXPERIMENTAL
1689 //return (qbyte *)e->v - (qbyte *)sv.edictsfields;
1691 edict_t *PROG_TO_EDICT(int n)
1693 if ((unsigned int)n >= (unsigned int)sv.max_edicts)
1694 Host_Error("PROG_TO_EDICT: invalid edict number %i\n", n);
1695 return sv.edicts + n; // EXPERIMENTAL
1696 //return sv.edicts + ((n) / (progs->entityfields * 4));