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 // reserve space for the null entity aka world
54 // check bound of max_edicts
55 prog->max_edicts = bound(1, prog->max_edicts, prog->limit_edicts);
56 prog->num_edicts = bound(1, prog->num_edicts, prog->max_edicts);
58 // edictprivate_size has to be min as big prvm_edict_private_t
59 prog->edictprivate_size = max(prog->edictprivate_size,(int)sizeof(prvm_edict_private_t));
62 prog->edicts = Mem_Alloc(prog->edicts_mempool,prog->limit_edicts * sizeof(prvm_edict_t));
64 // alloc edict private space
65 prog->edictprivate = Mem_Alloc(prog->edicts_mempool, prog->max_edicts * prog->edictprivate_size);
68 prog->edictsfields = Mem_Alloc(prog->edicts_mempool, prog->max_edicts * prog->edict_size);
71 for(i = 0; i < prog->max_edicts; i++)
73 prog->edicts[i].e = (prvm_edict_private_t *)((qbyte *)prog->edictprivate + i * prog->edictprivate_size);
74 prog->edicts[i].v = (void*)((qbyte *)prog->edictsfields + i * prog->edict_size);
80 PRVM_MEM_IncreaseEdicts
83 void PRVM_MEM_IncreaseEdicts()
86 int oldmaxedicts = prog->max_edicts;
87 void *oldedictsfields = prog->edictsfields;
88 void *oldedictprivate = prog->edictprivate;
90 if(prog->max_edicts >= prog->limit_edicts)
93 PRVM_GCALL(begin_increase_edicts)();
96 prog->max_edicts = min(prog->max_edicts + 256, prog->limit_edicts);
98 prog->edictsfields = Mem_Alloc(prog->edicts_mempool, prog->max_edicts * prog->edict_size);
99 prog->edictprivate = Mem_Alloc(prog->edicts_mempool, prog->max_edicts * prog->edictprivate_size);
101 memcpy(prog->edictsfields, oldedictsfields, oldmaxedicts * prog->edict_size);
102 memcpy(prog->edictprivate, oldedictprivate, oldmaxedicts * prog->edictprivate_size);
104 //set e and v pointers
105 for(i = 0; i < prog->max_edicts; i++)
107 prog->edicts[i].e = (prvm_edict_private_t *)((qbyte *)prog->edictprivate + i * prog->edictprivate_size);
108 prog->edicts[i].v = (void*)((qbyte *)prog->edictsfields + i * prog->edict_size);
111 PRVM_GCALL(end_increase_edicts)();
113 Mem_Free(oldedictsfields);
114 Mem_Free(oldedictprivate);
117 //============================================================================
120 int PRVM_ED_FindFieldOffset(const char *field)
123 d = PRVM_ED_FindField(field);
129 qboolean PRVM_ProgLoaded(int prognr)
131 if(prognr < 0 || prognr >= PRVM_MAXPROGS)
134 return (prog_list[prognr].loaded ? TRUE : FALSE);
139 PRVM_SetProgFromString
142 // perhaps add a return value when the str doesnt exist
143 qboolean PRVM_SetProgFromString(const char *str)
146 for(; i < PRVM_MAXPROGS ; i++)
147 if(prog_list[i].name && !strcmp(prog_list[i].name,str))
149 if(prog_list[i].loaded)
151 prog = &prog_list[i];
156 Con_Printf("%s not loaded !\n",PRVM_NAME);
161 Con_Printf("Invalid program name %s !\n", str);
170 void PRVM_SetProg(int prognr)
172 if(prognr && prognr < PRVM_MAXPROGS)
174 if(prog_list[prognr].loaded)
175 prog = &prog_list[prognr];
177 PRVM_ERROR("%i(%s) not loaded !\n", prognr, PRVM_NAME);
180 PRVM_ERROR("Invalid program number %i\n", prognr);
187 Sets everything to NULL
190 void PRVM_ED_ClearEdict (prvm_edict_t *e)
193 memset (e->v, 0, prog->progs->entityfields * 4);
195 // LordHavoc: for consistency set these here
196 num = PRVM_NUM_FOR_EDICT(e) - 1;
198 // AK: Let the init_edict function determine if something needs to be initialized
199 PRVM_GCALL(init_edict)(num);
206 Either finds a free edict, or allocates a new one.
207 Try to avoid reusing an entity that was recently freed, because it
208 can cause the client to think the entity morphed into something else
209 instead of being removed and recreated, which can cause interpolated
210 angles and bad trails.
213 prvm_edict_t *PRVM_ED_Alloc (void)
218 // the client qc dont need maxclients
219 // thus it doesnt need to use svs.maxclients
220 // AK: changed i=svs.maxclients+1
221 // AK: changed so the edict 0 wont spawn -> used as reserved/world entity
222 // although the menu/client has no world
223 for (i = 1;i < prog->num_edicts;i++)
225 e = PRVM_EDICT_NUM(i);
226 // the first couple seconds of server time can involve a lot of
227 // freeing and allocating, so relax the replacement policy
228 if (e->e->free && ( e->e->freetime < 2 || (*prog->time - e->e->freetime) > 0.5 ) )
230 PRVM_ED_ClearEdict (e);
236 PRVM_ERROR ("%s: PRVM_ED_Alloc: no free edicts",PRVM_NAME);
239 if (prog->num_edicts >= prog->max_edicts)
240 PRVM_MEM_IncreaseEdicts();
242 e = PRVM_EDICT_NUM(i);
243 PRVM_ED_ClearEdict (e);
252 Marks the edict as free
253 FIXME: walk all entities and NULL out references to this entity
256 void PRVM_ED_Free (prvm_edict_t *ed)
258 // dont delete the null entity (world)
259 if(PRVM_NUM_FOR_EDICT(ed) == 0)
262 PRVM_GCALL(free_edict)(ed);
265 ed->e->freetime = *prog->time;
268 //===========================================================================
275 ddef_t *PRVM_ED_GlobalAtOfs (int ofs)
280 for (i=0 ; i<prog->progs->numglobaldefs ; i++)
282 def = &prog->globaldefs[i];
294 ddef_t *PRVM_ED_FieldAtOfs (int ofs)
299 for (i=0 ; i<prog->progs->numfielddefs ; i++)
301 def = &prog->fielddefs[i];
313 ddef_t *PRVM_ED_FindField (const char *name)
318 for (i=0 ; i<prog->progs->numfielddefs ; i++)
320 def = &prog->fielddefs[i];
321 if (!strcmp(PRVM_GetString(def->s_name), name))
332 ddef_t *PRVM_ED_FindGlobal (const char *name)
337 for (i=0 ; i<prog->progs->numglobaldefs ; i++)
339 def = &prog->globaldefs[i];
340 if (!strcmp(PRVM_GetString(def->s_name), name))
352 mfunction_t *PRVM_ED_FindFunction (const char *name)
357 for (i=0 ; i<prog->progs->numfunctions ; i++)
359 func = &prog->functions[i];
360 if (!strcmp(PRVM_GetString(func->s_name), name))
371 Returns a string describing *data in a type specific manner
374 char *PRVM_ValueString (etype_t type, prvm_eval_t *val)
376 static char line[1024]; // LordHavoc: enlarged a bit (was 256)
381 type &= ~DEF_SAVEGLOBAL;
386 sprintf (line, "%s", PRVM_GetString(val->string));
390 if (n < 0 || n >= MAX_EDICTS)
391 sprintf (line, "entity %i (invalid!)", n);
393 sprintf (line, "entity %i", n);
396 f = prog->functions + val->function;
397 sprintf (line, "%s()", PRVM_GetString(f->s_name));
400 def = PRVM_ED_FieldAtOfs ( val->_int );
401 sprintf (line, ".%s", PRVM_GetString(def->s_name));
404 sprintf (line, "void");
407 // LordHavoc: changed from %5.1f to %10.4f
408 sprintf (line, "%10.4f", val->_float);
411 // LordHavoc: changed from %5.1f to %10.4f
412 sprintf (line, "'%10.4f %10.4f %10.4f'", val->vector[0], val->vector[1], val->vector[2]);
415 sprintf (line, "pointer");
418 sprintf (line, "bad type %i", type);
429 Returns a string describing *data in a type specific manner
430 Easier to parse than PR_ValueString
433 char *PRVM_UglyValueString (etype_t type, prvm_eval_t *val)
435 static char line[4096];
441 type &= ~DEF_SAVEGLOBAL;
446 // Parse the string a bit to turn special characters
447 // (like newline, specifically) into escape codes,
448 // this fixes saving games from various mods
449 s = PRVM_GetString (val->string);
450 for (i = 0;i < (int)sizeof(line) - 2 && *s;)
469 snprintf (line, sizeof (line), "%i", PRVM_NUM_FOR_EDICT(PRVM_PROG_TO_EDICT(val->edict)));
472 f = pr_functions + val->function;
473 snprintf (line, sizeof (line), "%s", PRVM_GetString(f->s_name));
476 def = PRVM_ED_FieldAtOfs ( val->_int );
477 snprintf (line, sizeof (line), ".%s", PRVM_GetString(def->s_name));
480 snprintf (line, sizeof (line), "void");
483 snprintf (line, sizeof (line), "%f", val->_float);
486 snprintf (line, sizeof (line), "%f %f %f", val->vector[0], val->vector[1], val->vector[2]);
489 snprintf (line, sizeof (line), "bad type %i", type);
500 Returns a string with a description and the contents of a global,
501 padded to 20 field width
504 char *PRVM_GlobalString (int ofs)
510 static char line[128];
512 val = (void *)&prog->globals[ofs];
513 def = PRVM_ED_GlobalAtOfs(ofs);
515 sprintf (line,"%i(?)", ofs);
518 s = PRVM_ValueString (def->type, val);
519 sprintf (line,"%i(%s)%s", ofs, PRVM_GetString(def->s_name), s);
530 char *PRVM_GlobalStringNoContents (int ofs)
534 static char line[128];
536 def = PRVM_ED_GlobalAtOfs(ofs);
538 sprintf (line,"%i(?)", ofs);
540 sprintf (line,"%i(%s)", ofs, PRVM_GetString(def->s_name));
558 // LordHavoc: optimized this to print out much more quickly (tempstring)
559 // LordHavoc: changed to print out every 4096 characters (incase there are a lot of fields to print)
560 void PRVM_ED_Print (prvm_edict_t *ed)
568 char tempstring[8192], tempstring2[260]; // temporary string buffers
572 Con_Printf ("%s: FREE\n",PRVM_NAME);
577 sprintf(tempstring, "\n%s EDICT %i:\n", PRVM_NAME, PRVM_NUM_FOR_EDICT(ed));
578 for (i=1 ; i<prog->progs->numfielddefs ; i++)
580 d = &prog->fielddefs[i];
581 name = PRVM_GetString(d->s_name);
582 if (name[strlen(name)-2] == '_')
583 continue; // skip _x, _y, _z vars
585 v = (int *)((char *)ed->v + d->ofs*4);
587 // if the value is still all 0, skip the field
588 type = d->type & ~DEF_SAVEGLOBAL;
590 for (j=0 ; j<prvm_type_size[type] ; j++)
593 if (j == prvm_type_size[type])
596 if (strlen(name) > 256)
598 strncpy(tempstring2, name, 256);
599 tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
600 tempstring2[259] = 0;
603 strcat(tempstring, name);
604 for (l = strlen(name);l < 14;l++)
605 strcat(tempstring, " ");
606 strcat(tempstring, " ");
608 name = PRVM_ValueString(d->type, (prvm_eval_t *)v);
609 if (strlen(name) > 256)
611 strncpy(tempstring2, name, 256);
612 tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
613 tempstring2[259] = 0;
616 strcat(tempstring, name);
617 strcat(tempstring, "\n");
618 if (strlen(tempstring) >= 4096)
620 Con_Printf("%s", tempstring);
625 Con_Printf("%s", tempstring);
635 void PRVM_ED_Write (qfile_t *f, prvm_edict_t *ed)
643 FS_Printf (f, "{\n");
647 FS_Printf (f, "}\n");
651 for (i=1 ; i<prog->progs->numfielddefs ; i++)
653 d = &prog->fielddefs[i];
654 name = PRVM_GetString(d->s_name);
655 if (name[strlen(name)-2] == '_')
656 continue; // skip _x, _y, _z vars
658 v = (int *)((char *)ed->v + d->ofs*4);
660 // if the value is still all 0, skip the field
661 type = d->type & ~DEF_SAVEGLOBAL;
662 for (j=0 ; j<prvm_type_size[type] ; j++)
665 if (j == prvm_type_size[type])
668 FS_Printf (f,"\"%s\" ",name);
669 FS_Printf (f,"\"%s\"\n", PRVM_UglyValueString(d->type, (prvm_eval_t *)v));
672 FS_Printf (f, "}\n");
675 void PRVM_ED_PrintNum (int ent)
677 PRVM_ED_Print (PRVM_EDICT_NUM(ent));
682 PRVM_ED_PrintEdicts_f
684 For debugging, prints all the entities in the current server
687 void PRVM_ED_PrintEdicts_f (void)
693 Con_Print("prvm_edicts <program name>\n");
698 if(!PRVM_SetProgFromString(Cmd_Argv(1)))
701 Con_Printf ("%s: %i entities\n", PRVM_NAME, prog->num_edicts);
702 for (i=0 ; i<prog->num_edicts ; i++)
703 PRVM_ED_PrintNum (i);
712 For debugging, prints a single edict
715 void PRVM_ED_PrintEdict_f (void)
721 Con_Print("prvm_edict <program name> <edict number>\n");
726 if(!PRVM_SetProgFromString(Cmd_Argv(1)))
729 i = atoi (Cmd_Argv(2));
730 if (i >= prog->num_edicts)
732 Con_Printf("Bad edict number\n");
736 PRVM_ED_PrintNum (i);
748 // 2 possibilities : 1. just displaying the active edict count
749 // 2. making a function pointer [x]
750 void PRVM_ED_Count_f (void)
758 Con_Print("prvm_count <program name>\n");
763 if(!PRVM_SetProgFromString(Cmd_Argv(1)))
766 if(prog->count_edicts)
767 prog->count_edicts();
771 for (i=0 ; i<prog->num_edicts ; i++)
773 ent = PRVM_EDICT_NUM(i);
779 Con_Printf ("num_edicts:%3i\n", prog->num_edicts);
780 Con_Printf ("active :%3i\n", active);
787 ==============================================================================
791 FIXME: need to tag constants, doesn't really work
792 ==============================================================================
800 void PRVM_ED_WriteGlobals (qfile_t *f)
808 for (i=0 ; i<prog->progs->numglobaldefs ; i++)
810 def = &prog->globaldefs[i];
812 if ( !(def->type & DEF_SAVEGLOBAL) )
814 type &= ~DEF_SAVEGLOBAL;
816 if (type != ev_string && type != ev_float && type != ev_entity)
819 name = PRVM_GetString(def->s_name);
820 FS_Printf (f,"\"%s\" ", name);
821 FS_Printf (f,"\"%s\"\n", PRVM_UglyValueString(type, (prvm_eval_t *)&prog->globals[def->ofs]));
831 void PRVM_ED_ParseGlobals (const char *data)
833 char keyname[1024]; // LordHavoc: good idea? bad idea? was 64
839 if (!COM_ParseToken(&data, false))
840 PRVM_ERROR ("PRVM_ED_ParseEntity: EOF without closing brace");
841 if (com_token[0] == '}')
844 strcpy (keyname, com_token);
847 if (!COM_ParseToken(&data, false))
848 PRVM_ERROR ("PRVM_ED_ParseEntity: EOF without closing brace");
850 if (com_token[0] == '}')
851 PRVM_ERROR ("PRVM_ED_ParseEntity: closing brace without data");
853 key = PRVM_ED_FindGlobal (keyname);
856 Con_DPrintf ("'%s' is not a global on %s\n", keyname, PRVM_NAME);
860 if (!PRVM_ED_ParseEpair(NULL, key, com_token))
861 PRVM_ERROR ("PRVM_ED_ParseGlobals: parse error");
865 //============================================================================
873 char *PRVM_ED_NewString (const char *string)
878 l = strlen(string) + 1;
879 new = Mem_Alloc(prog->edictstring_mempool, l);
882 for (i=0 ; i< l ; i++)
884 if (string[i] == '\\' && i < l-1)
887 if (string[i] == 'n')
893 *new_p++ = string[i];
904 Can parse either fields or globals
905 returns false if error
908 qboolean PRVM_ED_ParseEpair(prvm_edict_t *ent, ddef_t *key, const char *s)
916 val = (prvm_eval_t *)((int *)ent->v + key->ofs);
918 val = (prvm_eval_t *)((int *)pr_globals + key->ofs);
919 switch (key->type & ~DEF_SAVEGLOBAL)
922 val->string = PRVM_SetString(PRVM_ED_NewString(s));
926 while (*s && *s <= ' ')
928 val->_float = atof(s);
932 for (i = 0;i < 3;i++)
934 while (*s && *s <= ' ')
938 val->vector[i] = atof(s);
947 while (*s && *s <= ' ')
950 if (i < 0 || i >= MAX_EDICTS)
951 Con_Printf("PRVM_ED_ParseEpair: ev_entity reference too large (edict %i >= MAX_EDICTS %i) on %s\n", i, MAX_EDICTS, PRVM_NAME);
952 while (i >= prog->max_edicts)
953 PRVM_MEM_IncreaseEdicts();
954 //SV_IncreaseEdicts();
955 // if SV_IncreaseEdicts was called the base pointer needs to be updated
957 val = (prvm_eval_t *)((int *)ent->v + key->ofs);
958 val->edict = PRVM_EDICT_TO_PROG(EDICT_NUM(i));
962 def = PRVM_ED_FindField(s);
965 Con_DPrintf("PRVM_ED_ParseEpair: Can't find field %s in %s\n", s, PRVM_NAME);
968 val->_int = PRVM_G_INT(def->ofs);
972 func = PRVM_ED_FindFunction(s);
975 Con_Printf ("PRVM_ED_ParseEpair: Can't find function %s in %s\n", s, PRVM_NAME);
978 val->function = func - prog->functions;
982 Con_Printf("PRVM_ED_ParseEpair: Unknown key->type %i for key \"%s\" on %s\n", key->type, PR_GetString(key->s_name), PRVM_NAME);
992 Parses an edict out of the given string, returning the new position
993 ed should be a properly initialized empty edict.
994 Used for initial level load and for savegames.
997 const char *PRVM_ED_ParseEdict (const char *data, prvm_edict_t *ent)
1008 if (ent != prog->edicts) // hack
1009 memset (ent->v, 0, prog->progs->entityfields * 4);
1011 // go through all the dictionary pairs
1015 if (!COM_ParseToken(&data, false))
1016 PRVM_ERROR ("PRVM_ED_ParseEntity: EOF without closing brace");
1017 if (com_token[0] == '}')
1020 // anglehack is to allow QuakeEd to write single scalar angles
1021 // and allow them to be turned into vectors. (FIXME...)
1022 if (!strcmp(com_token, "angle"))
1024 strcpy (com_token, "angles");
1030 // FIXME: change light to _light to get rid of this hack
1031 if (!strcmp(com_token, "light"))
1032 strcpy (com_token, "light_lev"); // hack for single light def
1034 strcpy (keyname, com_token);
1036 // another hack to fix keynames with trailing spaces
1037 n = strlen(keyname);
1038 while (n && keyname[n-1] == ' ')
1045 if (!COM_ParseToken(&data, false))
1046 PRVM_ERROR ("PRVM_ED_ParseEntity: EOF without closing brace");
1048 if (com_token[0] == '}')
1049 PRVM_ERROR ("PRVM_ED_ParseEntity: closing brace without data");
1053 // keynames with a leading underscore are used for utility comments,
1054 // and are immediately discarded by quake
1055 if (keyname[0] == '_')
1058 key = PRVM_ED_FindField (keyname);
1061 Con_DPrintf ("%s: '%s' is not a field\n", PRVM_NAME, keyname);
1068 strcpy (temp, com_token);
1069 sprintf (com_token, "0 %s 0", temp);
1072 if (!PRVM_ED_ParseEpair(ent, key, com_token))
1073 PRVM_ERROR ("PRVM_ED_ParseEdict: parse error");
1077 ent->e->free = true;
1085 PRVM_ED_LoadFromFile
1087 The entities are directly placed in the array, rather than allocated with
1088 PRVM_ED_Alloc, because otherwise an error loading the map would have entity
1089 number references out of order.
1091 Creates a server's entity / program execution context by
1092 parsing textual entity definitions out of an ent file.
1094 Used for both fresh maps and savegame loads. A fresh map would also need
1095 to call PRVM_ED_CallSpawnFunctions () to let the objects initialize themselves.
1098 void PRVM_ED_LoadFromFile (const char *data)
1101 int parsed, inhibited, spawned, died;
1113 // parse the opening brace
1114 if (!COM_ParseToken(&data, false))
1116 if (com_token[0] != '{')
1117 PRVM_ERROR ("PRVM_ED_LoadFromFile: %s: found %s when expecting {", PRVM_NAME, com_token);
1119 // CHANGED: this is not conform to ED_LoadFromFile
1120 if(!prog->num_edicts)
1121 ent = PRVM_EDICT_NUM(0);
1123 ent = PRVM_ED_Alloc();
1125 data = PRVM_ED_ParseEdict (data, ent);
1128 // remove the entity ?
1129 if(prog->load_edict && !prog->load_edict(ent))
1137 // immediately call spawn function, but only if there is a self global
1139 if(prog->self && prog->flag & PRVM_FE_CLASSNAME)
1141 string_t handle = *(string_t*)&((float*)ent->v)[PRVM_ED_FindFieldOffset("classname")];
1144 Con_Printf ("No classname for:\n");
1145 PRVM_ED_Print (ent);
1150 // look for the spawn function
1151 func = PRVM_ED_FindFunction (PRVM_GetString(handle));
1155 if (developer.integer) // don't confuse non-developers with errors
1157 Con_Printf ("No spawn function for:\n");
1158 PRVM_ED_Print (ent);
1165 PRVM_G_INT(prog->self->ofs) = PRVM_EDICT_TO_PROG(ent);
1166 PRVM_ExecuteProgram (func - prog->functions, "");
1174 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);
1179 typedef struct dpfield_s
1186 #define DPFIELDS (sizeof(dpfields) / sizeof(dpfield_t))
1188 dpfield_t dpfields[] =
1199 void PRVM_ResetProg()
1201 mempool_t *t1, *t2, *t3;
1203 t1 = prog->progs_mempool;
1204 t2 = prog->edictstring_mempool;
1205 t3 = prog->edicts_mempool;
1207 Mem_EmptyPool(prog->progs_mempool);
1208 Mem_EmptyPool(prog->edictstring_mempool);
1209 Mem_EmptyPool(prog->edicts_mempool);
1211 memset(prog,0,sizeof(prvm_prog_t));
1213 prog->time = &prog->_time;
1215 prog->progs_mempool = t1;
1216 prog->edictstring_mempool = t2;
1217 prog->edicts_mempool = t3;
1219 PRVM_GCALL(reset_cmd)();
1227 void PRVM_LoadProgs (const char * filename, int numrequiredfunc, char **required_func)
1231 ddef_t *infielddefs;
1233 dfunction_t *dfunctions;
1235 Mem_EmptyPool(prog->progs_mempool);
1236 Mem_EmptyPool(prog->edictstring_mempool);
1238 temp = FS_LoadFile (filename, false);
1240 PRVM_ERROR ("PRVM_LoadProgs: couldn't load %s for %s", filename, PRVM_NAME);
1242 prog->progs = (dprograms_t *)Mem_Alloc(prog->progs_mempool, fs_filesize);
1244 memcpy(prog->progs, temp, fs_filesize);
1247 Con_DPrintf ("%s programs occupy %iK.\n", PRVM_NAME, fs_filesize/1024);
1249 pr_crc = CRC_Block((qbyte *)prog->progs, fs_filesize);
1251 // byte swap the header
1252 for (i = 0;i < (int) sizeof(*prog->progs) / 4;i++)
1253 ((int *)prog->progs)[i] = LittleLong ( ((int *)prog->progs)[i] );
1255 if (prog->progs->version != PROG_VERSION)
1256 PRVM_ERROR ("%s: %s has wrong version number (%i should be %i)", PRVM_NAME, filename, prog->progs->version, PROG_VERSION);
1257 if (prog->progs->crc != prog->crc)
1258 PRVM_ERROR ("%s: %s system vars have been modified, progdefs.h is out of date", PRVM_NAME, filename);
1260 //pr_functions = (dfunction_t *)((qbyte *)progs + progs->ofs_functions);
1261 dfunctions = (dfunction_t *)((qbyte *)prog->progs + prog->progs->ofs_functions);
1262 prog->strings = (char *)prog->progs + prog->progs->ofs_strings;
1263 prog->globaldefs = (ddef_t *)((qbyte *)prog->progs + prog->progs->ofs_globaldefs);
1265 // we need to expand the fielddefs list to include all the engine fields,
1266 // so allocate a new place for it
1267 infielddefs = (ddef_t *)((qbyte *)prog->progs + prog->progs->ofs_fielddefs);
1269 prog->fielddefs = Mem_Alloc(prog->progs_mempool, prog->progs->numfielddefs * sizeof(ddef_t));
1271 prog->statements = (dstatement_t *)((qbyte *)prog->progs + prog->progs->ofs_statements);
1273 // moved edict_size calculation down below field adding code
1275 //pr_global_struct = (globalvars_t *)((qbyte *)progs + progs->ofs_globals);
1276 prog->globals = (float *)((qbyte *)prog->progs + prog->progs->ofs_globals);
1278 // byte swap the lumps
1279 for (i=0 ; i<prog->progs->numstatements ; i++)
1281 prog->statements[i].op = LittleShort(prog->statements[i].op);
1282 prog->statements[i].a = LittleShort(prog->statements[i].a);
1283 prog->statements[i].b = LittleShort(prog->statements[i].b);
1284 prog->statements[i].c = LittleShort(prog->statements[i].c);
1287 prog->functions = Mem_Alloc(prog->progs_mempool, sizeof(mfunction_t) * prog->progs->numfunctions);
1288 for (i = 0;i < prog->progs->numfunctions;i++)
1290 prog->functions[i].first_statement = LittleLong (dfunctions[i].first_statement);
1291 prog->functions[i].parm_start = LittleLong (dfunctions[i].parm_start);
1292 prog->functions[i].s_name = LittleLong (dfunctions[i].s_name);
1293 prog->functions[i].s_file = LittleLong (dfunctions[i].s_file);
1294 prog->functions[i].numparms = LittleLong (dfunctions[i].numparms);
1295 prog->functions[i].locals = LittleLong (dfunctions[i].locals);
1296 memcpy(prog->functions[i].parm_size, dfunctions[i].parm_size, sizeof(dfunctions[i].parm_size));
1299 for (i=0 ; i<prog->progs->numglobaldefs ; i++)
1301 prog->globaldefs[i].type = LittleShort (prog->globaldefs[i].type);
1302 prog->globaldefs[i].ofs = LittleShort (prog->globaldefs[i].ofs);
1303 prog->globaldefs[i].s_name = LittleLong (prog->globaldefs[i].s_name);
1306 // copy the progs fields to the new fields list
1307 for (i = 0;i < prog->progs->numfielddefs;i++)
1309 prog->fielddefs[i].type = LittleShort (infielddefs[i].type);
1310 if (prog->fielddefs[i].type & DEF_SAVEGLOBAL)
1311 PRVM_ERROR ("PRVM_LoadProgs: prog->fielddefs[i].type & DEF_SAVEGLOBAL in %s", PRVM_NAME);
1312 prog->fielddefs[i].ofs = LittleShort (infielddefs[i].ofs);
1313 prog->fielddefs[i].s_name = LittleLong (infielddefs[i].s_name);
1316 /* // append the darkplaces fields
1317 for (i = 0;i < (int) DPFIELDS;i++)
1319 pr_fielddefs[progs->numfielddefs].type = dpfields[i].type;
1320 pr_fielddefs[progs->numfielddefs].ofs = progs->entityfields;
1321 pr_fielddefs[progs->numfielddefs].s_name = PR_SetString(dpfields[i].string);
1322 if (pr_fielddefs[progs->numfielddefs].type == ev_vector)
1323 progs->entityfields += 3;
1325 progs->entityfields++;
1326 progs->numfielddefs++;
1329 // check required functions
1330 for(i=0 ; i < numrequiredfunc ; i++)
1331 if(PRVM_ED_FindFunction(required_func[i]) == 0)
1332 PRVM_ERROR("%s: %s not found in %s\n",PRVM_NAME, required_func[i], filename);
1334 for (i=0 ; i<prog->progs->numglobals ; i++)
1335 ((int *)prog->globals)[i] = LittleLong (((int *)prog->globals)[i]);
1337 // moved edict_size calculation down here, below field adding code
1338 // LordHavoc: this no longer includes the edict_t header
1339 prog->edict_size = prog->progs->entityfields * 4;
1340 prog->edictareasize = prog->edict_size * MAX_EDICTS;
1342 // LordHavoc: bounds check anything static
1343 for (i = 0,st = prog->statements;i < prog->progs->numstatements;i++,st++)
1349 if ((unsigned short) st->a >= prog->progs->numglobals || st->b + i < 0 || st->b + i >= prog->progs->numstatements)
1350 PRVM_ERROR("PRVM_LoadProgs: out of bounds IF/IFNOT (statement %d) in %s\n", i, PRVM_NAME);
1353 if (st->a + i < 0 || st->a + i >= prog->progs->numstatements)
1354 PRVM_ERROR("PRVM_LoadProgs: out of bounds GOTO (statement %d) in %s\n", i, PRVM_NAME);
1356 // global global global
1391 if ((unsigned short) st->a >= prog->progs->numglobals || (unsigned short) st->b >= prog->progs->numglobals || (unsigned short) st->c >= prog->progs->numglobals)
1392 PRVM_ERROR("PRVM_LoadProgs: out of bounds global index (statement %d)\n", i);
1394 // global none global
1400 if ((unsigned short) st->a >= prog->progs->numglobals || (unsigned short) st->c >= prog->progs->numglobals)
1401 PRVM_ERROR("PRVM_LoadProgs: out of bounds global index (statement %d) in %s\n", i, PRVM_NAME);
1417 if ((unsigned short) st->a >= prog->progs->numglobals || (unsigned short) st->b >= prog->progs->numglobals)
1418 PRVM_ERROR("PRVM_LoadProgs: out of bounds global index (statement %d)\n in %s", i, PRVM_NAME);
1432 if ((unsigned short) st->a >= prog->progs->numglobals)
1433 PRVM_ERROR("PRVM_LoadProgs: out of bounds global index (statement %d) in %s\n", i, PRVM_NAME);
1436 PRVM_ERROR("PRVM_LoadProgs: unknown opcode %d at statement %d in %s\n", st->op, i, PRVM_NAME);
1443 prog->loaded = TRUE;
1445 // set flags & ddef_ts in prog
1449 prog->self = PRVM_ED_FindGlobal("self");
1451 if(PRVM_ED_FindGlobal("time"))
1452 prog->time = &PRVM_G_FLOAT(PRVM_ED_FindGlobal("time")->ofs);
1454 if(PRVM_ED_FindField ("chain"))
1455 prog->flag |= PRVM_FE_CHAIN;
1457 if(PRVM_ED_FindField ("classname"))
1458 prog->flag |= PRVM_FE_CLASSNAME;
1460 if(PRVM_ED_FindField ("nextthink") && PRVM_ED_FindField ("frame") && PRVM_ED_FindField ("think")
1461 && prog->flag && prog->self)
1462 prog->flag |= PRVM_OP_STATE;
1464 PRVM_GCALL(reset_cmd)();
1471 void PRVM_Fields_f (void)
1473 int i, j, ednum, used, usedamount;
1475 char tempstring[5000], tempstring2[260], *name;
1484 Con_Printf("no progs loaded\n");
1491 Con_Print("prvm_fields <program name>\n");
1496 if(!PRVM_SetProgFromString(Cmd_Argv(1)))
1499 counts = Mem_Alloc(tempmempool, prog->progs->numfielddefs * sizeof(int));
1500 for (ednum = 0;ednum < prog->max_edicts;ednum++)
1502 ed = PRVM_EDICT_NUM(ednum);
1505 for (i = 1;i < prog->progs->numfielddefs;i++)
1507 d = &prog->fielddefs[i];
1508 name = PRVM_GetString(d->s_name);
1509 if (name[strlen(name)-2] == '_')
1510 continue; // skip _x, _y, _z vars
1511 v = (int *)((char *)ed->v + d->ofs*4);
1512 // if the value is still all 0, skip the field
1513 for (j = 0;j < prvm_type_size[d->type & ~DEF_SAVEGLOBAL];j++)
1526 for (i = 0;i < prog->progs->numfielddefs;i++)
1528 d = &prog->fielddefs[i];
1529 name = PRVM_GetString(d->s_name);
1530 if (name[strlen(name)-2] == '_')
1531 continue; // skip _x, _y, _z vars
1532 switch(d->type & ~DEF_SAVEGLOBAL)
1535 strcat(tempstring, "string ");
1538 strcat(tempstring, "entity ");
1541 strcat(tempstring, "function ");
1544 strcat(tempstring, "field ");
1547 strcat(tempstring, "void ");
1550 strcat(tempstring, "float ");
1553 strcat(tempstring, "vector ");
1556 strcat(tempstring, "pointer ");
1559 sprintf (tempstring2, "bad type %i ", d->type & ~DEF_SAVEGLOBAL);
1560 strcat(tempstring, tempstring2);
1563 if (strlen(name) > 256)
1565 strncpy(tempstring2, name, 256);
1566 tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
1567 tempstring2[259] = 0;
1570 strcat(tempstring, name);
1571 for (j = strlen(name);j < 25;j++)
1572 strcat(tempstring, " ");
1573 sprintf(tempstring2, "%5d", counts[i]);
1574 strcat(tempstring, tempstring2);
1575 strcat(tempstring, "\n");
1576 if (strlen(tempstring) >= 4096)
1578 Con_Printf("%s", tempstring);
1584 usedamount += prvm_type_size[d->type & ~DEF_SAVEGLOBAL];
1588 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);
1593 void PRVM_Globals_f (void)
1599 Con_Printf("no progs loaded\n");
1602 if(Cmd_Argc () != 2)
1604 Con_Print ("prvm_globals <program name>\n");
1609 if(!PRVM_SetProgFromString (Cmd_Argv (1)))
1612 Con_Printf("%s :", PRVM_NAME);
1614 for (i = 0;i < prog->progs->numglobaldefs;i++)
1615 Con_Printf("%s\n", PRVM_GetString(prog->globaldefs[i].s_name));
1616 Con_Printf("%i global variables, totalling %i bytes\n", prog->progs->numglobals, prog->progs->numglobals * 4);
1626 void PRVM_Init (void)
1628 Cmd_AddCommand ("prvm_edict", PRVM_ED_PrintEdict_f);
1629 Cmd_AddCommand ("prvm_edicts", PRVM_ED_PrintEdicts_f);
1630 Cmd_AddCommand ("prvm_edictcount", PRVM_ED_Count_f);
1631 Cmd_AddCommand ("prvm_profile", PRVM_Profile_f);
1632 Cmd_AddCommand ("prvm_fields", PRVM_Fields_f);
1633 Cmd_AddCommand ("prvm_globals", PRVM_Globals_f);
1634 // LordHavoc: optional runtime bounds checking (speed drain, but worth it for security, on by default - breaks most QCCX features (used by CRMod and others))
1635 Cvar_RegisterVariable (&prvm_boundscheck);
1636 Cvar_RegisterVariable (&prvm_traceqc);
1646 void PRVM_InitProg(int prognr)
1648 if(prognr < 0 || prognr >= PRVM_MAXPROGS)
1649 Sys_Error("PRVM_InitProg: Invalid program number %i\n",prognr);
1651 prog = &prog_list[prognr];
1653 memset(prog, 0, sizeof(prvm_prog_t));
1655 prog->time = &prog->_time;
1657 PRVM_GCALL(init_cmd)();
1660 int PRVM_GetProgNr()
1662 return prog - prog_list;
1665 // LordHavoc: turned PRVM_EDICT_NUM into a #define for speed reasons
1666 prvm_edict_t *PRVM_EDICT_NUM_ERROR(int n, char *filename, int fileline)
1668 PRVM_ERROR ("PRVM_EDICT_NUM: %s: bad number %i (called at %s:%i)", PRVM_NAME, n, filename, fileline);
1672 void PRVM_ProcessError(void)
1675 PRVM_GCALL(error_cmd)();
1679 int NUM_FOR_EDICT_ERROR(edict_t *e)
1681 Host_Error ("NUM_FOR_EDICT: bad pointer %p (world is %p, entity number would be %i)", e, sv.edicts, e - sv.edicts);
1685 int NUM_FOR_EDICT(edict_t *e)
1689 if ((unsigned int)n >= MAX_EDICTS)
1690 Host_Error ("NUM_FOR_EDICT: bad pointer");
1694 //int NoCrash_NUM_FOR_EDICT(edict_t *e)
1696 // return e - sv.edicts;
1699 //#define EDICT_TO_PROG(e) ((qbyte *)(((edict_t *)e)->v) - (qbyte *)(sv.edictsfields))
1700 //#define PROG_TO_EDICT(e) (sv.edicts + ((e) / (progs->entityfields * 4)))
1701 int EDICT_TO_PROG(edict_t *e)
1705 if ((unsigned int)n >= (unsigned int)sv.max_edicts)
1706 Host_Error("EDICT_TO_PROG: invalid edict %8p (number %i compared to world at %8p)\n", e, n, sv.edicts);
1707 return n;// EXPERIMENTAL
1708 //return (qbyte *)e->v - (qbyte *)sv.edictsfields;
1710 edict_t *PROG_TO_EDICT(int n)
1712 if ((unsigned int)n >= (unsigned int)sv.max_edicts)
1713 Host_Error("PROG_TO_EDICT: invalid edict number %i\n", n);
1714 return sv.edicts + n; // EXPERIMENTAL
1715 //return sv.edicts + ((n) / (progs->entityfields * 4));