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_Printf("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_Printf("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_Printf("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 and a classname
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);*/
1210 Mem_FreePool(&prog->progs_mempool);
1211 Mem_FreePool(&prog->edictstring_mempool);
1212 Mem_FreePool(&prog->edicts_mempool);
1214 memset(prog,0,sizeof(prvm_prog_t));
1216 /*prog->time = &prog->_time;
1218 prog->progs_mempool = t1;
1219 prog->edictstring_mempool = t2;
1220 prog->edicts_mempool = t3;*/
1222 PRVM_GCALL(reset_cmd)();
1230 void PRVM_LoadProgs (const char * filename, int numrequiredfunc, char **required_func)
1234 ddef_t *infielddefs;
1236 dfunction_t *dfunctions;
1238 Mem_EmptyPool(prog->progs_mempool);
1239 Mem_EmptyPool(prog->edictstring_mempool);
1241 temp = FS_LoadFile (filename, false);
1243 PRVM_ERROR ("PRVM_LoadProgs: couldn't load %s for %s", filename, PRVM_NAME);
1245 prog->progs = (dprograms_t *)Mem_Alloc(prog->progs_mempool, fs_filesize);
1247 memcpy(prog->progs, temp, fs_filesize);
1250 Con_DPrintf ("%s programs occupy %iK.\n", PRVM_NAME, fs_filesize/1024);
1252 pr_crc = CRC_Block((qbyte *)prog->progs, fs_filesize);
1254 // byte swap the header
1255 for (i = 0;i < (int) sizeof(*prog->progs) / 4;i++)
1256 ((int *)prog->progs)[i] = LittleLong ( ((int *)prog->progs)[i] );
1258 if (prog->progs->version != PROG_VERSION)
1259 PRVM_ERROR ("%s: %s has wrong version number (%i should be %i)", PRVM_NAME, filename, prog->progs->version, PROG_VERSION);
1260 if (prog->progs->crc != prog->crc)
1261 PRVM_ERROR ("%s: %s system vars have been modified, progdefs.h is out of date", PRVM_NAME, filename);
1263 //pr_functions = (dfunction_t *)((qbyte *)progs + progs->ofs_functions);
1264 dfunctions = (dfunction_t *)((qbyte *)prog->progs + prog->progs->ofs_functions);
1265 prog->strings = (char *)prog->progs + prog->progs->ofs_strings;
1266 prog->globaldefs = (ddef_t *)((qbyte *)prog->progs + prog->progs->ofs_globaldefs);
1268 // we need to expand the fielddefs list to include all the engine fields,
1269 // so allocate a new place for it
1270 infielddefs = (ddef_t *)((qbyte *)prog->progs + prog->progs->ofs_fielddefs);
1272 prog->fielddefs = Mem_Alloc(prog->progs_mempool, prog->progs->numfielddefs * sizeof(ddef_t));
1274 prog->statements = (dstatement_t *)((qbyte *)prog->progs + prog->progs->ofs_statements);
1276 // moved edict_size calculation down below field adding code
1278 //pr_global_struct = (globalvars_t *)((qbyte *)progs + progs->ofs_globals);
1279 prog->globals = (float *)((qbyte *)prog->progs + prog->progs->ofs_globals);
1281 // byte swap the lumps
1282 for (i=0 ; i<prog->progs->numstatements ; i++)
1284 prog->statements[i].op = LittleShort(prog->statements[i].op);
1285 prog->statements[i].a = LittleShort(prog->statements[i].a);
1286 prog->statements[i].b = LittleShort(prog->statements[i].b);
1287 prog->statements[i].c = LittleShort(prog->statements[i].c);
1290 prog->functions = Mem_Alloc(prog->progs_mempool, sizeof(mfunction_t) * prog->progs->numfunctions);
1291 for (i = 0;i < prog->progs->numfunctions;i++)
1293 prog->functions[i].first_statement = LittleLong (dfunctions[i].first_statement);
1294 prog->functions[i].parm_start = LittleLong (dfunctions[i].parm_start);
1295 prog->functions[i].s_name = LittleLong (dfunctions[i].s_name);
1296 prog->functions[i].s_file = LittleLong (dfunctions[i].s_file);
1297 prog->functions[i].numparms = LittleLong (dfunctions[i].numparms);
1298 prog->functions[i].locals = LittleLong (dfunctions[i].locals);
1299 memcpy(prog->functions[i].parm_size, dfunctions[i].parm_size, sizeof(dfunctions[i].parm_size));
1302 for (i=0 ; i<prog->progs->numglobaldefs ; i++)
1304 prog->globaldefs[i].type = LittleShort (prog->globaldefs[i].type);
1305 prog->globaldefs[i].ofs = LittleShort (prog->globaldefs[i].ofs);
1306 prog->globaldefs[i].s_name = LittleLong (prog->globaldefs[i].s_name);
1309 // copy the progs fields to the new fields list
1310 for (i = 0;i < prog->progs->numfielddefs;i++)
1312 prog->fielddefs[i].type = LittleShort (infielddefs[i].type);
1313 if (prog->fielddefs[i].type & DEF_SAVEGLOBAL)
1314 PRVM_ERROR ("PRVM_LoadProgs: prog->fielddefs[i].type & DEF_SAVEGLOBAL in %s", PRVM_NAME);
1315 prog->fielddefs[i].ofs = LittleShort (infielddefs[i].ofs);
1316 prog->fielddefs[i].s_name = LittleLong (infielddefs[i].s_name);
1319 /* // append the darkplaces fields
1320 for (i = 0;i < (int) DPFIELDS;i++)
1322 pr_fielddefs[progs->numfielddefs].type = dpfields[i].type;
1323 pr_fielddefs[progs->numfielddefs].ofs = progs->entityfields;
1324 pr_fielddefs[progs->numfielddefs].s_name = PR_SetString(dpfields[i].string);
1325 if (pr_fielddefs[progs->numfielddefs].type == ev_vector)
1326 progs->entityfields += 3;
1328 progs->entityfields++;
1329 progs->numfielddefs++;
1332 // check required functions
1333 for(i=0 ; i < numrequiredfunc ; i++)
1334 if(PRVM_ED_FindFunction(required_func[i]) == 0)
1335 PRVM_ERROR("%s: %s not found in %s\n",PRVM_NAME, required_func[i], filename);
1337 for (i=0 ; i<prog->progs->numglobals ; i++)
1338 ((int *)prog->globals)[i] = LittleLong (((int *)prog->globals)[i]);
1340 // moved edict_size calculation down here, below field adding code
1341 // LordHavoc: this no longer includes the edict_t header
1342 prog->edict_size = prog->progs->entityfields * 4;
1343 prog->edictareasize = prog->edict_size * MAX_EDICTS;
1345 // LordHavoc: bounds check anything static
1346 for (i = 0,st = prog->statements;i < prog->progs->numstatements;i++,st++)
1352 if ((unsigned short) st->a >= prog->progs->numglobals || st->b + i < 0 || st->b + i >= prog->progs->numstatements)
1353 PRVM_ERROR("PRVM_LoadProgs: out of bounds IF/IFNOT (statement %d) in %s\n", i, PRVM_NAME);
1356 if (st->a + i < 0 || st->a + i >= prog->progs->numstatements)
1357 PRVM_ERROR("PRVM_LoadProgs: out of bounds GOTO (statement %d) in %s\n", i, PRVM_NAME);
1359 // global global global
1394 if ((unsigned short) st->a >= prog->progs->numglobals || (unsigned short) st->b >= prog->progs->numglobals || (unsigned short) st->c >= prog->progs->numglobals)
1395 PRVM_ERROR("PRVM_LoadProgs: out of bounds global index (statement %d)\n", i);
1397 // global none global
1403 if ((unsigned short) st->a >= prog->progs->numglobals || (unsigned short) st->c >= prog->progs->numglobals)
1404 PRVM_ERROR("PRVM_LoadProgs: out of bounds global index (statement %d) in %s\n", i, PRVM_NAME);
1420 if ((unsigned short) st->a >= prog->progs->numglobals || (unsigned short) st->b >= prog->progs->numglobals)
1421 PRVM_ERROR("PRVM_LoadProgs: out of bounds global index (statement %d)\n in %s", i, PRVM_NAME);
1435 if ((unsigned short) st->a >= prog->progs->numglobals)
1436 PRVM_ERROR("PRVM_LoadProgs: out of bounds global index (statement %d) in %s\n", i, PRVM_NAME);
1439 PRVM_ERROR("PRVM_LoadProgs: unknown opcode %d at statement %d in %s\n", st->op, i, PRVM_NAME);
1446 prog->loaded = TRUE;
1448 // set flags & ddef_ts in prog
1452 prog->self = PRVM_ED_FindGlobal("self");
1454 if(PRVM_ED_FindGlobal("time"))
1455 prog->time = &PRVM_G_FLOAT(PRVM_ED_FindGlobal("time")->ofs);
1457 if(PRVM_ED_FindField ("chain"))
1458 prog->flag |= PRVM_FE_CHAIN;
1460 if(PRVM_ED_FindField ("classname"))
1461 prog->flag |= PRVM_FE_CLASSNAME;
1463 if(PRVM_ED_FindField ("nextthink") && PRVM_ED_FindField ("frame") && PRVM_ED_FindField ("think")
1464 && prog->flag && prog->self)
1465 prog->flag |= PRVM_OP_STATE;
1467 PRVM_GCALL(reset_cmd)();
1468 PRVM_GCALL(init_cmd)();
1475 void PRVM_Fields_f (void)
1477 int i, j, ednum, used, usedamount;
1479 char tempstring[5000], tempstring2[260], *name;
1488 Con_Printf("no progs loaded\n");
1495 Con_Printf("prvm_fields <program name>\n");
1500 if(!PRVM_SetProgFromString(Cmd_Argv(1)))
1503 counts = Mem_Alloc(tempmempool, prog->progs->numfielddefs * sizeof(int));
1504 for (ednum = 0;ednum < prog->max_edicts;ednum++)
1506 ed = PRVM_EDICT_NUM(ednum);
1509 for (i = 1;i < prog->progs->numfielddefs;i++)
1511 d = &prog->fielddefs[i];
1512 name = PRVM_GetString(d->s_name);
1513 if (name[strlen(name)-2] == '_')
1514 continue; // skip _x, _y, _z vars
1515 v = (int *)((char *)ed->v + d->ofs*4);
1516 // if the value is still all 0, skip the field
1517 for (j = 0;j < prvm_type_size[d->type & ~DEF_SAVEGLOBAL];j++)
1530 for (i = 0;i < prog->progs->numfielddefs;i++)
1532 d = &prog->fielddefs[i];
1533 name = PRVM_GetString(d->s_name);
1534 if (name[strlen(name)-2] == '_')
1535 continue; // skip _x, _y, _z vars
1536 switch(d->type & ~DEF_SAVEGLOBAL)
1539 strcat(tempstring, "string ");
1542 strcat(tempstring, "entity ");
1545 strcat(tempstring, "function ");
1548 strcat(tempstring, "field ");
1551 strcat(tempstring, "void ");
1554 strcat(tempstring, "float ");
1557 strcat(tempstring, "vector ");
1560 strcat(tempstring, "pointer ");
1563 sprintf (tempstring2, "bad type %i ", d->type & ~DEF_SAVEGLOBAL);
1564 strcat(tempstring, tempstring2);
1567 if (strlen(name) > 256)
1569 strncpy(tempstring2, name, 256);
1570 tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
1571 tempstring2[259] = 0;
1574 strcat(tempstring, name);
1575 for (j = strlen(name);j < 25;j++)
1576 strcat(tempstring, " ");
1577 sprintf(tempstring2, "%5d", counts[i]);
1578 strcat(tempstring, tempstring2);
1579 strcat(tempstring, "\n");
1580 if (strlen(tempstring) >= 4096)
1582 Con_Printf("%s", tempstring);
1588 usedamount += prvm_type_size[d->type & ~DEF_SAVEGLOBAL];
1592 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);
1597 void PRVM_Globals_f (void)
1603 Con_Printf("no progs loaded\n");
1606 if(Cmd_Argc () != 2)
1608 Con_Printf("prvm_globals <program name>\n");
1613 if(!PRVM_SetProgFromString (Cmd_Argv (1)))
1616 Con_Printf("%s :", PRVM_NAME);
1618 for (i = 0;i < prog->progs->numglobaldefs;i++)
1619 Con_Printf("%s\n", PRVM_GetString(prog->globaldefs[i].s_name));
1620 Con_Printf("%i global variables, totalling %i bytes\n", prog->progs->numglobals, prog->progs->numglobals * 4);
1630 void PRVM_Init (void)
1632 Cmd_AddCommand ("prvm_edict", PRVM_ED_PrintEdict_f);
1633 Cmd_AddCommand ("prvm_edicts", PRVM_ED_PrintEdicts_f);
1634 Cmd_AddCommand ("prvm_edictcount", PRVM_ED_Count_f);
1635 Cmd_AddCommand ("prvm_profile", PRVM_Profile_f);
1636 Cmd_AddCommand ("prvm_fields", PRVM_Fields_f);
1637 Cmd_AddCommand ("prvm_globals", PRVM_Globals_f);
1638 // LordHavoc: optional runtime bounds checking (speed drain, but worth it for security, on by default - breaks most QCCX features (used by CRMod and others))
1639 Cvar_RegisterVariable (&prvm_boundscheck);
1640 Cvar_RegisterVariable (&prvm_traceqc);
1650 void PRVM_InitProg(int prognr)
1652 if(prognr < 0 || prognr >= PRVM_MAXPROGS)
1653 Sys_Error("PRVM_InitProg: Invalid program number %i\n",prognr);
1655 prog = &prog_list[prognr];
1660 memset(prog, 0, sizeof(prvm_prog_t));
1662 prog->time = &prog->_time;
1665 int PRVM_GetProgNr()
1667 return prog - prog_list;
1670 // LordHavoc: turned PRVM_EDICT_NUM into a #define for speed reasons
1671 prvm_edict_t *PRVM_EDICT_NUM_ERROR(int n, char *filename, int fileline)
1673 PRVM_ERROR ("PRVM_EDICT_NUM: %s: bad number %i (called at %s:%i)", PRVM_NAME, n, filename, fileline);
1677 void PRVM_ProcessError(void)
1680 PRVM_GCALL(error_cmd)();
1684 int NUM_FOR_EDICT_ERROR(edict_t *e)
1686 Host_Error ("NUM_FOR_EDICT: bad pointer %p (world is %p, entity number would be %i)", e, sv.edicts, e - sv.edicts);
1690 int NUM_FOR_EDICT(edict_t *e)
1694 if ((unsigned int)n >= MAX_EDICTS)
1695 Host_Error ("NUM_FOR_EDICT: bad pointer");
1699 //int NoCrash_NUM_FOR_EDICT(edict_t *e)
1701 // return e - sv.edicts;
1704 //#define EDICT_TO_PROG(e) ((qbyte *)(((edict_t *)e)->v) - (qbyte *)(sv.edictsfields))
1705 //#define PROG_TO_EDICT(e) (sv.edicts + ((e) / (progs->entityfields * 4)))
1706 int EDICT_TO_PROG(edict_t *e)
1710 if ((unsigned int)n >= (unsigned int)sv.max_edicts)
1711 Host_Error("EDICT_TO_PROG: invalid edict %8p (number %i compared to world at %8p)\n", e, n, sv.edicts);
1712 return n;// EXPERIMENTAL
1713 //return (qbyte *)e->v - (qbyte *)sv.edictsfields;
1715 edict_t *PROG_TO_EDICT(int n)
1717 if ((unsigned int)n >= (unsigned int)sv.max_edicts)
1718 Host_Error("PROG_TO_EDICT: invalid edict number %i\n", n);
1719 return sv.edicts + n; // EXPERIMENTAL
1720 //return sv.edicts + ((n) / (progs->entityfields * 4));