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,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 sprintf (line, "%s", PRVM_GetString(val->string));
442 for (i = 0;i < (int)sizeof(line) - 2 && *s;)
462 sprintf (line, "%i", PRVM_NUM_FOR_EDICT(PRVM_PROG_TO_EDICT(val->edict)));
465 f = pr_functions + val->function;
466 sprintf (line, "%s", PRVM_GetString(f->s_name));
469 def = PRVM_ED_FieldAtOfs ( val->_int );
470 s = PRVM_GetString(def->s_name);
473 sprintf (line, "void");
476 sprintf (line, "%f", val->_float);
479 sprintf (line, "%f %f %f", val->vector[0], val->vector[1], val->vector[2]);
482 sprintf (line, "bad type %i", type);
493 Returns a string with a description and the contents of a global,
494 padded to 20 field width
497 char *PRVM_GlobalString (int ofs)
503 static char line[128];
505 val = (void *)&prog->globals[ofs];
506 def = PRVM_ED_GlobalAtOfs(ofs);
508 sprintf (line,"%i(?)", ofs);
511 s = PRVM_ValueString (def->type, val);
512 sprintf (line,"%i(%s)%s", ofs, PRVM_GetString(def->s_name), s);
523 char *PRVM_GlobalStringNoContents (int ofs)
527 static char line[128];
529 def = PRVM_ED_GlobalAtOfs(ofs);
531 sprintf (line,"%i(?)", ofs);
533 sprintf (line,"%i(%s)", ofs, PRVM_GetString(def->s_name));
551 // LordHavoc: optimized this to print out much more quickly (tempstring)
552 // LordHavoc: changed to print out every 4096 characters (incase there are a lot of fields to print)
553 void PRVM_ED_Print (prvm_edict_t *ed)
561 char tempstring[8192], tempstring2[260]; // temporary string buffers
565 Con_Printf ("%s: FREE\n",PRVM_NAME);
570 sprintf(tempstring, "\n%s EDICT %i:\n", PRVM_NAME, PRVM_NUM_FOR_EDICT(ed));
571 for (i=1 ; i<prog->progs->numfielddefs ; i++)
573 d = &prog->fielddefs[i];
574 name = PRVM_GetString(d->s_name);
575 if (name[strlen(name)-2] == '_')
576 continue; // skip _x, _y, _z vars
578 v = (int *)((char *)ed->v + d->ofs*4);
580 // if the value is still all 0, skip the field
581 type = d->type & ~DEF_SAVEGLOBAL;
583 for (j=0 ; j<prvm_type_size[type] ; j++)
586 if (j == prvm_type_size[type])
589 if (strlen(name) > 256)
591 strncpy(tempstring2, name, 256);
592 tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
593 tempstring2[259] = 0;
596 strcat(tempstring, name);
597 for (l = strlen(name);l < 14;l++)
598 strcat(tempstring, " ");
599 strcat(tempstring, " ");
601 name = PRVM_ValueString(d->type, (prvm_eval_t *)v);
602 if (strlen(name) > 256)
604 strncpy(tempstring2, name, 256);
605 tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
606 tempstring2[259] = 0;
609 strcat(tempstring, name);
610 strcat(tempstring, "\n");
611 if (strlen(tempstring) >= 4096)
613 Con_Printf("%s", tempstring);
618 Con_Printf("%s", tempstring);
628 void PRVM_ED_Write (qfile_t *f, prvm_edict_t *ed)
636 FS_Printf (f, "{\n");
640 FS_Printf (f, "}\n");
644 for (i=1 ; i<prog->progs->numfielddefs ; i++)
646 d = &prog->fielddefs[i];
647 name = PRVM_GetString(d->s_name);
648 if (name[strlen(name)-2] == '_')
649 continue; // skip _x, _y, _z vars
651 v = (int *)((char *)ed->v + d->ofs*4);
653 // if the value is still all 0, skip the field
654 type = d->type & ~DEF_SAVEGLOBAL;
655 for (j=0 ; j<prvm_type_size[type] ; j++)
658 if (j == prvm_type_size[type])
661 FS_Printf (f,"\"%s\" ",name);
662 FS_Printf (f,"\"%s\"\n", PRVM_UglyValueString(d->type, (prvm_eval_t *)v));
665 FS_Printf (f, "}\n");
668 void PRVM_ED_PrintNum (int ent)
670 PRVM_ED_Print (PRVM_EDICT_NUM(ent));
675 PRVM_ED_PrintEdicts_f
677 For debugging, prints all the entities in the current server
680 void PRVM_ED_PrintEdicts_f (void)
686 Con_Print("prvm_edicts <program name>\n");
691 if(!PRVM_SetProgFromString(Cmd_Argv(1)))
694 Con_Printf ("%s: %i entities\n", PRVM_NAME, prog->num_edicts);
695 for (i=0 ; i<prog->num_edicts ; i++)
696 PRVM_ED_PrintNum (i);
705 For debugging, prints a single edict
708 void PRVM_ED_PrintEdict_f (void)
714 Con_Print("prvm_edict <program name> <edict number>\n");
719 if(!PRVM_SetProgFromString(Cmd_Argv(1)))
722 i = atoi (Cmd_Argv(2));
723 if (i >= prog->num_edicts)
725 Con_Printf("Bad edict number\n");
728 PRVM_ED_PrintNum (i);
740 // 2 possibilities : 1. just displaying the active edict count
741 // 2. making a function pointer [x]
742 void PRVM_ED_Count_f (void)
750 Con_Print("prvm_count <program name>\n");
755 if(!PRVM_SetProgFromString(Cmd_Argv(1)))
758 if(prog->count_edicts)
759 prog->count_edicts();
763 for (i=0 ; i<prog->num_edicts ; i++)
765 ent = PRVM_EDICT_NUM(i);
771 Con_Printf ("num_edicts:%3i\n", sv.num_edicts);
772 Con_Printf ("active :%3i\n", active);
779 ==============================================================================
783 FIXME: need to tag constants, doesn't really work
784 ==============================================================================
792 void PRVM_ED_WriteGlobals (qfile_t *f)
800 for (i=0 ; i<prog->progs->numglobaldefs ; i++)
802 def = &prog->globaldefs[i];
804 if ( !(def->type & DEF_SAVEGLOBAL) )
806 type &= ~DEF_SAVEGLOBAL;
808 if (type != ev_string && type != ev_float && type != ev_entity)
811 name = PRVM_GetString(def->s_name);
812 FS_Printf (f,"\"%s\" ", name);
813 FS_Printf (f,"\"%s\"\n", PRVM_UglyValueString(type, (prvm_eval_t *)&prog->globals[def->ofs]));
823 void PRVM_ED_ParseGlobals (const char *data)
825 char keyname[1024]; // LordHavoc: good idea? bad idea? was 64
831 if (!COM_ParseToken(&data, false))
832 PRVM_ERROR ("PRVM_ED_ParseEntity: EOF without closing brace");
833 if (com_token[0] == '}')
836 strcpy (keyname, com_token);
839 if (!COM_ParseToken(&data, false))
840 PRVM_ERROR ("PRVM_ED_ParseEntity: EOF without closing brace");
842 if (com_token[0] == '}')
843 PRVM_ERROR ("PRVM_ED_ParseEntity: closing brace without data");
845 key = PRVM_ED_FindGlobal (keyname);
848 Con_DPrintf ("'%s' is not a global on %s\n", keyname, PRVM_NAME);
852 if (!PRVM_ED_ParseEpair(NULL, key, com_token))
853 PRVM_ERROR ("PRVM_ED_ParseGlobals: parse error");
857 //============================================================================
865 char *PRVM_ED_NewString (const char *string)
870 l = strlen(string) + 1;
871 new = Mem_Alloc(prog->edictstring_mempool, l);
874 for (i=0 ; i< l ; i++)
876 if (string[i] == '\\' && i < l-1)
879 if (string[i] == 'n')
885 *new_p++ = string[i];
896 Can parse either fields or globals
897 returns false if error
900 qboolean PRVM_ED_ParseEpair(prvm_edict_t *ent, ddef_t *key, const char *s)
908 val = (prvm_eval_t *)((int *)ent->v + key->ofs);
910 val = (prvm_eval_t *)((int *)pr_globals + key->ofs);
911 switch (key->type & ~DEF_SAVEGLOBAL)
914 val->string = PRVM_SetString(ED_NewString(s));
918 while (*s && *s <= ' ')
920 val->_float = atof(s);
924 for (i = 0;i < 3;i++)
926 while (*s && *s <= ' ')
930 val->vector[i] = atof(s);
939 while (*s && *s <= ' ')
942 if (i < 0 || i >= MAX_EDICTS)
943 Con_Printf("PRVM_ED_ParseEpair: ev_entity reference too large (edict %i >= MAX_EDICTS %i) on %s\n", i, MAX_EDICTS, PRVM_NAME);
944 while (i >= prog->max_edicts)
945 PRVM_MEM_IncreaseEdicts();
946 //SV_IncreaseEdicts();
947 // if SV_IncreaseEdicts was called the base pointer needs to be updated
949 val = (prvm_eval_t *)((int *)ent->v + key->ofs);
950 val->edict = PRVM_EDICT_TO_PROG(EDICT_NUM(i));
954 def = PRVM_ED_FindField(s);
957 Con_DPrintf("PRVM_ED_ParseEpair: Can't find field %s on %s\n", s, PRVM_NAME);
960 val->_int = PRVM_G_INT(def->ofs);
964 func = PRVM_ED_FindFunction(s);
967 Con_Printf ("PRVM_ED_ParseEpair: Can't find function %s on %s\n", s, PRVM_NAME);
970 val->function = func - prog->functions;
974 Con_Printf("PRVM_ED_ParseEpair: Unknown key->type %i for key \"%s\" on %s\n", key->type, PR_GetString(key->s_name), PRVM_NAME);
984 Parses an edict out of the given string, returning the new position
985 ed should be a properly initialized empty edict.
986 Used for initial level load and for savegames.
989 const char *PRVM_ED_ParseEdict (const char *data, prvm_edict_t *ent)
1000 if (ent != prog->edicts) // hack
1001 memset (ent->v, 0, prog->progs->entityfields * 4);
1003 // go through all the dictionary pairs
1007 if (!COM_ParseToken(&data, false))
1008 PRVM_ERROR ("PRVM_ED_ParseEntity: EOF without closing brace");
1009 if (com_token[0] == '}')
1012 // anglehack is to allow QuakeEd to write single scalar angles
1013 // and allow them to be turned into vectors. (FIXME...)
1014 if (!strcmp(com_token, "angle"))
1016 strcpy (com_token, "angles");
1022 // FIXME: change light to _light to get rid of this hack
1023 if (!strcmp(com_token, "light"))
1024 strcpy (com_token, "light_lev"); // hack for single light def
1026 strcpy (keyname, com_token);
1028 // another hack to fix heynames with trailing spaces
1029 n = strlen(keyname);
1030 while (n && keyname[n-1] == ' ')
1037 if (!COM_ParseToken(&data, false))
1038 PRVM_ERROR ("PRVM_ED_ParseEntity: EOF without closing brace");
1040 if (com_token[0] == '}')
1041 PRVM_ERROR ("PRVM_ED_ParseEntity: closing brace without data");
1045 // keynames with a leading underscore are used for utility comments,
1046 // and are immediately discarded by quake
1047 if (keyname[0] == '_')
1050 key = PRVM_ED_FindField (keyname);
1053 Con_DPrintf ("%s: '%s' is not a field\n", PRVM_NAME, keyname);
1060 strcpy (temp, com_token);
1061 sprintf (com_token, "0 %s 0", temp);
1064 if (!PRVM_ED_ParseEpair(ent, key, com_token))
1065 PRVM_ERROR ("PRVM_ED_ParseEdict: parse error");
1069 ent->e->free = true;
1077 PRVM_ED_LoadFromFile
1079 The entities are directly placed in the array, rather than allocated with
1080 PRVM_ED_Alloc, because otherwise an error loading the map would have entity
1081 number references out of order.
1083 Creates a server's entity / program execution context by
1084 parsing textual entity definitions out of an ent file.
1086 Used for both fresh maps and savegame loads. A fresh map would also need
1087 to call PRVM_ED_CallSpawnFunctions () to let the objects initialize themselves.
1090 void PRVM_ED_LoadFromFile (const char *data)
1093 int parsed, inhibited, spawned, died;
1103 if(prog->flag & PRVM_GE_TIME)
1104 PRVM_G_FLOAT(PRVM_ED_FindFieldOffset("time")) = prog->time;
1109 // parse the opening brace
1110 if (!COM_ParseToken(&data, false))
1112 if (com_token[0] != '{')
1113 PRVM_ERROR ("PRVM_ED_LoadFromFile: found %s when expecting (%s) {",com_token, PRVM_NAME);
1116 ent = PRVM_EDICT_NUM(0);
1118 ent = PRVM_ED_Alloc ();
1119 data = PRVM_ED_ParseEdict (data, ent);
1122 // remove the entity ?
1123 if(prog->load_edict && !prog->load_edict(ent))
1131 // immediately call spawn function, but only if there is a self global
1133 if(prog->self && prog->flag & PRVM_FE_CLASSNAME)
1135 string_t handle = *(string_t*)&((float*)ent->v)[PRVM_ED_FindFieldOffset("classname")];
1138 Con_Printf ("No classname for:\n");
1139 PRVM_ED_Print (ent);
1144 // look for the spawn function
1145 func = PRVM_ED_FindFunction (PRVM_GetString(handle));
1149 if (developer.integer) // don't confuse non-developers with errors
1151 Con_Printf ("No spawn function for:\n");
1152 PRVM_ED_Print (ent);
1159 PRVM_G_INT(prog->self->ofs) = PRVM_EDICT_TO_PROG(ent);
1160 PRVM_ExecuteProgram (func - prog->functions, "");
1168 Con_DPrintf ("%s: %i entities parsed, %i inhibited, %i spawned (%i removed self, %i stayed)\n", PRVM_NAME, parsed, inhibited, spawned, died, spawned - died);
1173 typedef struct dpfield_s
1180 #define DPFIELDS (sizeof(dpfields) / sizeof(dpfield_t))
1182 dpfield_t dpfields[] =
1193 void PRVM_ResetProg()
1195 mempool_t *t1, *t2, *t3;
1197 t1 = prog->progs_mempool;
1198 t2 = prog->edictstring_mempool;
1199 t3 = prog->edicts_mempool;
1201 Mem_EmptyPool(prog->progs_mempool);
1202 Mem_EmptyPool(prog->edictstring_mempool);
1203 Mem_EmptyPool(prog->edicts_mempool);
1205 memset(prog,0,sizeof(prvm_prog_t));
1208 prog->progs_mempool = t1;
1209 prog->edictstring_mempool = t2;
1210 prog->edicts_mempool = t3;
1212 PRVM_GCALL(reset_cmd);
1220 void PRVM_LoadProgs (const char * filename, int numrequiredfunc, char **required_func)
1224 ddef_t *infielddefs;
1226 dfunction_t *dfunctions;
1228 Mem_EmptyPool(prog->progs_mempool);
1229 Mem_EmptyPool(prog->edictstring_mempool);
1231 temp = FS_LoadFile (filename, false);
1233 PRVM_ERROR ("PRVM_LoadProgs: couldn't load %s for %s", filename, PRVM_NAME);
1235 prog->progs = (dprograms_t *)Mem_Alloc(prog->progs_mempool, fs_filesize);
1237 memcpy(prog->progs, temp, fs_filesize);
1240 Con_DPrintf ("%s programs occupy %iK.\n", PRVM_NAME, fs_filesize/1024);
1242 pr_crc = CRC_Block((qbyte *)prog->progs, fs_filesize);
1244 // byte swap the header
1245 for (i = 0;i < (int) sizeof(*prog->progs) / 4;i++)
1246 ((int *)prog->progs)[i] = LittleLong ( ((int *)prog->progs)[i] );
1248 if (prog->progs->version != PROG_VERSION)
1249 PRVM_ERROR ("%s: %s has wrong version number (%i should be %i)", PRVM_NAME, filename, prog->progs->version, PROG_VERSION);
1250 if (prog->progs->crc != prog->crc)
1251 PRVM_ERROR ("%s: %s system vars have been modified, progdefs.h is out of date", PRVM_NAME, filename);
1253 //pr_functions = (dfunction_t *)((qbyte *)progs + progs->ofs_functions);
1254 dfunctions = (dfunction_t *)((qbyte *)prog->progs + prog->progs->ofs_functions);
1255 prog->strings = (char *)prog->progs + prog->progs->ofs_strings;
1256 prog->globaldefs = (ddef_t *)((qbyte *)prog->progs + prog->progs->ofs_globaldefs);
1258 // we need to expand the fielddefs list to include all the engine fields,
1259 // so allocate a new place for it
1260 infielddefs = (ddef_t *)((qbyte *)prog->progs + prog->progs->ofs_fielddefs);
1262 prog->fielddefs = Mem_Alloc(prog->progs_mempool, prog->progs->numfielddefs * sizeof(ddef_t));
1264 prog->statements = (dstatement_t *)((qbyte *)prog->progs + prog->progs->ofs_statements);
1266 // moved edict_size calculation down below field adding code
1268 //pr_global_struct = (globalvars_t *)((qbyte *)progs + progs->ofs_globals);
1269 prog->globals = (float *)((qbyte *)prog->progs + prog->progs->ofs_globals);
1271 // byte swap the lumps
1272 for (i=0 ; i<prog->progs->numstatements ; i++)
1274 prog->statements[i].op = LittleShort(prog->statements[i].op);
1275 prog->statements[i].a = LittleShort(prog->statements[i].a);
1276 prog->statements[i].b = LittleShort(prog->statements[i].b);
1277 prog->statements[i].c = LittleShort(prog->statements[i].c);
1280 prog->functions = Mem_Alloc(prog->progs_mempool, sizeof(mfunction_t) * prog->progs->numfunctions);
1281 for (i = 0;i < prog->progs->numfunctions;i++)
1283 prog->functions[i].first_statement = LittleLong (dfunctions[i].first_statement);
1284 prog->functions[i].parm_start = LittleLong (dfunctions[i].parm_start);
1285 prog->functions[i].s_name = LittleLong (dfunctions[i].s_name);
1286 prog->functions[i].s_file = LittleLong (dfunctions[i].s_file);
1287 prog->functions[i].numparms = LittleLong (dfunctions[i].numparms);
1288 prog->functions[i].locals = LittleLong (dfunctions[i].locals);
1289 memcpy(prog->functions[i].parm_size, dfunctions[i].parm_size, sizeof(dfunctions[i].parm_size));
1292 for (i=0 ; i<prog->progs->numglobaldefs ; i++)
1294 prog->globaldefs[i].type = LittleShort (prog->globaldefs[i].type);
1295 prog->globaldefs[i].ofs = LittleShort (prog->globaldefs[i].ofs);
1296 prog->globaldefs[i].s_name = LittleLong (prog->globaldefs[i].s_name);
1299 // copy the progs fields to the new fields list
1300 for (i = 0;i < prog->progs->numfielddefs;i++)
1302 prog->fielddefs[i].type = LittleShort (infielddefs[i].type);
1303 if (prog->fielddefs[i].type & DEF_SAVEGLOBAL)
1304 PRVM_ERROR ("PRVM_LoadProgs: prog->fielddefs[i].type & DEF_SAVEGLOBAL in %s", PRVM_NAME);
1305 prog->fielddefs[i].ofs = LittleShort (infielddefs[i].ofs);
1306 prog->fielddefs[i].s_name = LittleLong (infielddefs[i].s_name);
1309 /* // append the darkplaces fields
1310 for (i = 0;i < (int) DPFIELDS;i++)
1312 pr_fielddefs[progs->numfielddefs].type = dpfields[i].type;
1313 pr_fielddefs[progs->numfielddefs].ofs = progs->entityfields;
1314 pr_fielddefs[progs->numfielddefs].s_name = PR_SetString(dpfields[i].string);
1315 if (pr_fielddefs[progs->numfielddefs].type == ev_vector)
1316 progs->entityfields += 3;
1318 progs->entityfields++;
1319 progs->numfielddefs++;
1322 // check required functions
1323 for(i=0 ; i < numrequiredfunc ; i++)
1324 if(PRVM_ED_FindFunction(required_func[i]) == 0)
1325 PRVM_ERROR("%s: %s not found in %s\n",PRVM_NAME, required_func[i], filename);
1327 for (i=0 ; i<prog->progs->numglobals ; i++)
1328 ((int *)prog->globals)[i] = LittleLong (((int *)prog->globals)[i]);
1330 // moved edict_size calculation down here, below field adding code
1331 // LordHavoc: this no longer includes the edict_t header
1332 prog->edict_size = prog->progs->entityfields * 4;
1333 prog->edictareasize = prog->edict_size * MAX_EDICTS;
1335 // LordHavoc: bounds check anything static
1336 for (i = 0,st = prog->statements;i < prog->progs->numstatements;i++,st++)
1342 if ((unsigned short) st->a >= prog->progs->numglobals || st->b + i < 0 || st->b + i >= prog->progs->numstatements)
1343 PRVM_ERROR("PRVM_LoadProgs: out of bounds IF/IFNOT (statement %d) in %s\n", i, PRVM_NAME);
1346 if (st->a + i < 0 || st->a + i >= prog->progs->numstatements)
1347 PRVM_ERROR("PRVM_LoadProgs: out of bounds GOTO (statement %d) in %s\n", i, PRVM_NAME);
1349 // global global global
1384 if ((unsigned short) st->a >= prog->progs->numglobals || (unsigned short) st->b >= prog->progs->numglobals || (unsigned short) st->c >= prog->progs->numglobals)
1385 PRVM_ERROR("PRVM_LoadProgs: out of bounds global index (statement %d)\n", i);
1387 // global none global
1393 if ((unsigned short) st->a >= prog->progs->numglobals || (unsigned short) st->c >= prog->progs->numglobals)
1394 PRVM_ERROR("PRVM_LoadProgs: out of bounds global index (statement %d) in %s\n", i, PRVM_NAME);
1410 if ((unsigned short) st->a >= prog->progs->numglobals || (unsigned short) st->b >= prog->progs->numglobals)
1411 PRVM_ERROR("PRVM_LoadProgs: out of bounds global index (statement %d)\n in %s", i, PRVM_NAME);
1425 if ((unsigned short) st->a >= prog->progs->numglobals)
1426 PRVM_ERROR("PRVM_LoadProgs: out of bounds global index (statement %d) in %s\n", i, PRVM_NAME);
1429 PRVM_ERROR("PRVM_LoadProgs: unknown opcode %d at statement %d in %s\n", st->op, i, PRVM_NAME);
1436 prog->loaded = TRUE;
1438 // set flags & ddef_ts in prog
1442 prog->self = PRVM_ED_FindGlobal("self");
1444 if(PRVM_ED_FindGlobal("time"))
1445 prog->flag |= PRVM_GE_TIME;
1447 if(PRVM_ED_FindFieldOffset ("classname"))
1448 prog->flag |= PRVM_FE_CLASSNAME;
1450 if(PRVM_ED_FindFieldOffset ("nextthink") && PRVM_ED_FindFieldOffset("frame") && PRVM_ED_FindFieldOffset("think")
1451 && prog->flag & PRVM_GE_TIME && prog->self)
1452 prog->flag |= PRVM_OP_STATE;
1454 PRVM_GCALL(reset_cmd)();
1461 void PRVM_Fields_f (void)
1463 int i, j, ednum, used, usedamount;
1465 char tempstring[5000], tempstring2[260], *name;
1474 Con_Printf("no progs loaded\n");
1481 Con_Print("prvm_fields <program name>\n");
1486 if(!PRVM_SetProgFromString(Cmd_Argv(1)))
1489 counts = Mem_Alloc(tempmempool, prog->progs->numfielddefs * sizeof(int));
1490 for (ednum = 0;ednum < prog->max_edicts;ednum++)
1492 ed = PRVM_EDICT_NUM(ednum);
1495 for (i = 1;i < prog->progs->numfielddefs;i++)
1497 d = &prog->fielddefs[i];
1498 name = PRVM_GetString(d->s_name);
1499 if (name[strlen(name)-2] == '_')
1500 continue; // skip _x, _y, _z vars
1501 v = (int *)((char *)ed->v + d->ofs*4);
1502 // if the value is still all 0, skip the field
1503 for (j = 0;j < prvm_type_size[d->type & ~DEF_SAVEGLOBAL];j++)
1516 for (i = 0;i < prog->progs->numfielddefs;i++)
1518 d = &prog->fielddefs[i];
1519 name = PRVM_GetString(d->s_name);
1520 if (name[strlen(name)-2] == '_')
1521 continue; // skip _x, _y, _z vars
1522 switch(d->type & ~DEF_SAVEGLOBAL)
1525 strcat(tempstring, "string ");
1528 strcat(tempstring, "entity ");
1531 strcat(tempstring, "function ");
1534 strcat(tempstring, "field ");
1537 strcat(tempstring, "void ");
1540 strcat(tempstring, "float ");
1543 strcat(tempstring, "vector ");
1546 strcat(tempstring, "pointer ");
1549 sprintf (tempstring2, "bad type %i ", d->type & ~DEF_SAVEGLOBAL);
1550 strcat(tempstring, tempstring2);
1553 if (strlen(name) > 256)
1555 strncpy(tempstring2, name, 256);
1556 tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
1557 tempstring2[259] = 0;
1560 strcat(tempstring, name);
1561 for (j = strlen(name);j < 25;j++)
1562 strcat(tempstring, " ");
1563 sprintf(tempstring2, "%5d", counts[i]);
1564 strcat(tempstring, tempstring2);
1565 strcat(tempstring, "\n");
1566 if (strlen(tempstring) >= 4096)
1568 Con_Printf("%s", tempstring);
1574 usedamount += prvm_type_size[d->type & ~DEF_SAVEGLOBAL];
1578 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);
1583 void PRVM_Globals_f (void)
1589 Con_Printf("no progs loaded\n");
1592 if(Cmd_Argc () != 2)
1594 Con_Print ("prvm_globals <program name>\n");
1599 if(!PRVM_SetProgFromString (Cmd_Argv (1)))
1602 Con_Printf("%s :", PRVM_NAME);
1604 for (i = 0;i < prog->progs->numglobaldefs;i++)
1605 Con_Printf("%s\n", PRVM_GetString(pr_globaldefs[i].s_name));
1606 Con_Printf("%i global variables, totalling %i bytes\n", prog->progs->numglobals, prog->progs->numglobals * 4);
1616 void PRVM_Init (void)
1618 Cmd_AddCommand ("prvm_edict", PRVM_ED_PrintEdict_f);
1619 Cmd_AddCommand ("prvm_edicts", PRVM_ED_PrintEdicts_f);
1620 Cmd_AddCommand ("prvm_edictcount", PRVM_ED_Count_f);
1621 Cmd_AddCommand ("prvm_profile", PRVM_Profile_f);
1622 Cmd_AddCommand ("prvm_fields", PRVM_Fields_f);
1623 Cmd_AddCommand ("prvm_globals", PRVM_Globals_f);
1624 // LordHavoc: optional runtime bounds checking (speed drain, but worth it for security, on by default - breaks most QCCX features (used by CRMod and others))
1625 Cvar_RegisterVariable (&prvm_boundscheck);
1626 Cvar_RegisterVariable (&prvm_traceqc);
1636 void PRVM_InitProg(int prognr)
1638 if(prognr < 0 || prognr >= PRVM_MAXPROGS)
1639 Sys_Error("PRVM_InitProg: Invalid program number %i\n",prognr);
1641 prog = &prog_list[prognr];
1643 memset(prog, 0, sizeof(prvm_prog_t));
1645 PRVM_GCALL(init_cmd)();
1648 int PRVM_GetProgNr()
1650 return prog - prog_list;
1653 // LordHavoc: turned PRVM_EDICT_NUM into a #define for speed reasons
1654 prvm_edict_t *PRVM_EDICT_NUM_ERROR(int n, char *filename, int fileline)
1656 PRVM_ERROR ("PRVM_EDICT_NUM: %s: bad number %i (called at %s:%i)", PRVM_NAME, n, filename, fileline);
1661 int NUM_FOR_EDICT_ERROR(edict_t *e)
1663 Host_Error ("NUM_FOR_EDICT: bad pointer %p (world is %p, entity number would be %i)", e, sv.edicts, e - sv.edicts);
1667 int NUM_FOR_EDICT(edict_t *e)
1671 if ((unsigned int)n >= MAX_EDICTS)
1672 Host_Error ("NUM_FOR_EDICT: bad pointer");
1676 //int NoCrash_NUM_FOR_EDICT(edict_t *e)
1678 // return e - sv.edicts;
1681 //#define EDICT_TO_PROG(e) ((qbyte *)(((edict_t *)e)->v) - (qbyte *)(sv.edictsfields))
1682 //#define PROG_TO_EDICT(e) (sv.edicts + ((e) / (progs->entityfields * 4)))
1683 int EDICT_TO_PROG(edict_t *e)
1687 if ((unsigned int)n >= (unsigned int)sv.max_edicts)
1688 Host_Error("EDICT_TO_PROG: invalid edict %8p (number %i compared to world at %8p)\n", e, n, sv.edicts);
1689 return n;// EXPERIMENTAL
1690 //return (qbyte *)e->v - (qbyte *)sv.edictsfields;
1692 edict_t *PROG_TO_EDICT(int n)
1694 if ((unsigned int)n >= (unsigned int)sv.max_edicts)
1695 Host_Error("PROG_TO_EDICT: invalid edict number %i\n", n);
1696 return sv.edicts + n; // EXPERIMENTAL
1697 //return sv.edicts + ((n) / (progs->entityfields * 4));