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.
27 static prvm_prog_t prog_list[PRVM_MAXPROGS];
29 int prvm_type_size[8] = {1,sizeof(string_t)/4,1,3,1,1,sizeof(func_t)/4,sizeof(void *)/4};
31 ddef_t *PRVM_ED_FieldAtOfs(int ofs);
32 qboolean PRVM_ED_ParseEpair(prvm_edict_t *ent, ddef_t *key, const char *s);
34 // LordHavoc: optional runtime bounds checking (speed drain, but worth it for security, on by default - breaks most QCCX features (used by CRMod and others))
35 cvar_t prvm_boundscheck = {0, "prvm_boundscheck", "1"};
36 // LordHavoc: prints every opcode as it executes - warning: this is significant spew
37 cvar_t prvm_traceqc = {0, "prvm_traceqc", "0"};
39 ddef_t *PRVM_ED_FindField (const char *name);
40 mfunction_t *PRVM_ED_FindFunction (const char *name);
42 //============================================================================
54 // reserve space for the null entity aka world
55 // check bound of max_edicts
56 prog->max_edicts = bound(1, prog->max_edicts, prog->limit_edicts);
57 prog->num_edicts = bound(1, prog->num_edicts, prog->max_edicts);
59 // edictprivate_size has to be min as big prvm_edict_private_t
60 prog->edictprivate_size = max(prog->edictprivate_size,(int)sizeof(prvm_edict_private_t));
63 prog->edicts = Mem_Alloc(prog->edicts_mempool,prog->limit_edicts * sizeof(prvm_edict_t));
65 // alloc edict private space
66 prog->edictprivate = Mem_Alloc(prog->edicts_mempool, prog->max_edicts * prog->edictprivate_size);
69 prog->edictsfields = Mem_Alloc(prog->edicts_mempool, prog->max_edicts * prog->edict_size);
72 for(i = 0; i < prog->max_edicts; i++)
74 prog->edicts[i].p.e = (prvm_edict_private_t *)((qbyte *)prog->edictprivate + i * prog->edictprivate_size);
75 prog->edicts[i].v = (void*)((qbyte *)prog->edictsfields + i * prog->edict_size);
81 PRVM_MEM_IncreaseEdicts
84 void PRVM_MEM_IncreaseEdicts()
87 int oldmaxedicts = prog->max_edicts;
88 void *oldedictsfields = prog->edictsfields;
89 void *oldedictprivate = prog->edictprivate;
91 if(prog->max_edicts >= prog->limit_edicts)
94 PRVM_GCALL(begin_increase_edicts)();
97 prog->max_edicts = min(prog->max_edicts + 256, prog->limit_edicts);
99 prog->edictsfields = Mem_Alloc(prog->edicts_mempool, prog->max_edicts * prog->edict_size);
100 prog->edictprivate = Mem_Alloc(prog->edicts_mempool, prog->max_edicts * prog->edictprivate_size);
102 memcpy(prog->edictsfields, oldedictsfields, oldmaxedicts * prog->edict_size);
103 memcpy(prog->edictprivate, oldedictprivate, oldmaxedicts * prog->edictprivate_size);
105 //set e and v pointers
106 for(i = 0; i < prog->max_edicts; i++)
108 prog->edicts[i].p.e = (prvm_edict_private_t *)((qbyte *)prog->edictprivate + i * prog->edictprivate_size);
109 prog->edicts[i].v = (void*)((qbyte *)prog->edictsfields + i * prog->edict_size);
112 PRVM_GCALL(end_increase_edicts)();
114 Mem_Free(oldedictsfields);
115 Mem_Free(oldedictprivate);
118 //============================================================================
121 int PRVM_ED_FindFieldOffset(const char *field)
124 d = PRVM_ED_FindField(field);
130 qboolean PRVM_ProgLoaded(int prognr)
132 if(prognr < 0 || prognr >= PRVM_MAXPROGS)
135 return (prog_list[prognr].loaded ? TRUE : FALSE);
140 PRVM_SetProgFromString
143 // perhaps add a return value when the str doesnt exist
144 qboolean PRVM_SetProgFromString(const char *str)
147 for(; i < PRVM_MAXPROGS ; i++)
148 if(prog_list[i].name && !strcmp(prog_list[i].name,str))
150 if(prog_list[i].loaded)
152 prog = &prog_list[i];
157 Con_Printf("%s not loaded !\n",PRVM_NAME);
162 Con_Printf("Invalid program name %s !\n", str);
171 void PRVM_SetProg(int prognr)
173 if(prognr && prognr < PRVM_MAXPROGS)
175 if(prog_list[prognr].loaded)
176 prog = &prog_list[prognr];
178 PRVM_ERROR("%i(%s) not loaded !\n", prognr, PRVM_NAME);
181 PRVM_ERROR("Invalid program number %i\n", prognr);
188 Sets everything to NULL
191 void PRVM_ED_ClearEdict (prvm_edict_t *e)
194 memset (e->v, 0, prog->progs->entityfields * 4);
195 e->p.e->free = false;
196 // LordHavoc: for consistency set these here
197 num = PRVM_NUM_FOR_EDICT(e) - 1;
199 // AK: Let the init_edict function determine if something needs to be initialized
200 PRVM_GCALL(init_edict)(num);
207 Either finds a free edict, or allocates a new one.
208 Try to avoid reusing an entity that was recently freed, because it
209 can cause the client to think the entity morphed into something else
210 instead of being removed and recreated, which can cause interpolated
211 angles and bad trails.
214 prvm_edict_t *PRVM_ED_Alloc (void)
219 // the client qc dont need maxclients
220 // thus it doesnt need to use svs.maxclients
221 // AK: changed i=svs.maxclients+1
222 // AK: changed so the edict 0 wont spawn -> used as reserved/world entity
223 // although the menu/client has no world
224 for (i = 1;i < prog->num_edicts;i++)
226 e = PRVM_EDICT_NUM(i);
227 // the first couple seconds of server time can involve a lot of
228 // freeing and allocating, so relax the replacement policy
229 if (e->p.e->free && ( e->p.e->freetime < 2 || (*prog->time - e->p.e->freetime) > 0.5 ) )
231 PRVM_ED_ClearEdict (e);
237 PRVM_ERROR ("%s: PRVM_ED_Alloc: no free edicts",PRVM_NAME);
240 if (prog->num_edicts >= prog->max_edicts)
241 PRVM_MEM_IncreaseEdicts();
243 e = PRVM_EDICT_NUM(i);
244 PRVM_ED_ClearEdict (e);
253 Marks the edict as free
254 FIXME: walk all entities and NULL out references to this entity
257 void PRVM_ED_Free (prvm_edict_t *ed)
259 // dont delete the null entity (world)
260 if(PRVM_NUM_FOR_EDICT(ed) == 0)
263 PRVM_GCALL(free_edict)(ed);
265 ed->p.e->free = true;
266 ed->p.e->freetime = *prog->time;
269 //===========================================================================
276 ddef_t *PRVM_ED_GlobalAtOfs (int ofs)
281 for (i=0 ; i<prog->progs->numglobaldefs ; i++)
283 def = &prog->globaldefs[i];
295 ddef_t *PRVM_ED_FieldAtOfs (int ofs)
300 for (i=0 ; i<prog->progs->numfielddefs ; i++)
302 def = &prog->fielddefs[i];
314 ddef_t *PRVM_ED_FindField (const char *name)
319 for (i=0 ; i<prog->progs->numfielddefs ; i++)
321 def = &prog->fielddefs[i];
322 if (!strcmp(PRVM_GetString(def->s_name), name))
333 ddef_t *PRVM_ED_FindGlobal (const char *name)
338 for (i=0 ; i<prog->progs->numglobaldefs ; i++)
340 def = &prog->globaldefs[i];
341 if (!strcmp(PRVM_GetString(def->s_name), name))
353 mfunction_t *PRVM_ED_FindFunction (const char *name)
358 for (i=0 ; i<prog->progs->numfunctions ; i++)
360 func = &prog->functions[i];
361 if (!strcmp(PRVM_GetString(func->s_name), name))
372 Returns a string describing *data in a type specific manner
375 char *PRVM_ValueString (etype_t type, prvm_eval_t *val)
377 static char line[1024]; // LordHavoc: enlarged a bit (was 256)
382 type &= ~DEF_SAVEGLOBAL;
387 strlcpy (line, PRVM_GetString (val->string), sizeof (line));
391 if (n < 0 || n >= MAX_EDICTS)
392 sprintf (line, "entity %i (invalid!)", n);
394 sprintf (line, "entity %i", n);
397 f = prog->functions + val->function;
398 sprintf (line, "%s()", PRVM_GetString(f->s_name));
401 def = PRVM_ED_FieldAtOfs ( val->_int );
402 sprintf (line, ".%s", PRVM_GetString(def->s_name));
405 sprintf (line, "void");
408 // LordHavoc: changed from %5.1f to %10.4f
409 sprintf (line, "%10.4f", val->_float);
412 // LordHavoc: changed from %5.1f to %10.4f
413 sprintf (line, "'%10.4f %10.4f %10.4f'", val->vector[0], val->vector[1], val->vector[2]);
416 sprintf (line, "pointer");
419 sprintf (line, "bad type %i", type);
430 Returns a string describing *data in a type specific manner
431 Easier to parse than PR_ValueString
434 char *PRVM_UglyValueString (etype_t type, prvm_eval_t *val)
436 static char line[4096];
442 type &= ~DEF_SAVEGLOBAL;
447 // Parse the string a bit to turn special characters
448 // (like newline, specifically) into escape codes,
449 // this fixes saving games from various mods
450 s = PRVM_GetString (val->string);
451 for (i = 0;i < (int)sizeof(line) - 2 && *s;)
470 dpsnprintf (line, sizeof (line), "%i", PRVM_NUM_FOR_EDICT(PRVM_PROG_TO_EDICT(val->edict)));
473 f = pr_functions + val->function;
474 strlcpy (line, PRVM_GetString (f->s_name), sizeof (line));
477 def = PRVM_ED_FieldAtOfs ( val->_int );
478 dpsnprintf (line, sizeof (line), ".%s", PRVM_GetString(def->s_name));
481 dpsnprintf (line, sizeof (line), "void");
484 dpsnprintf (line, sizeof (line), "%f", val->_float);
487 dpsnprintf (line, sizeof (line), "%f %f %f", val->vector[0], val->vector[1], val->vector[2]);
490 dpsnprintf (line, sizeof (line), "bad type %i", type);
501 Returns a string with a description and the contents of a global,
502 padded to 20 field width
505 char *PRVM_GlobalString (int ofs)
511 static char line[128];
513 val = (void *)&prog->globals[ofs];
514 def = PRVM_ED_GlobalAtOfs(ofs);
516 sprintf (line,"%i(?)", ofs);
519 s = PRVM_ValueString (def->type, val);
520 sprintf (line,"%i(%s)%s", ofs, PRVM_GetString(def->s_name), s);
531 char *PRVM_GlobalStringNoContents (int ofs)
535 static char line[128];
537 def = PRVM_ED_GlobalAtOfs(ofs);
539 sprintf (line,"%i(?)", ofs);
541 sprintf (line,"%i(%s)", ofs, PRVM_GetString(def->s_name));
559 // LordHavoc: optimized this to print out much more quickly (tempstring)
560 // LordHavoc: changed to print out every 4096 characters (incase there are a lot of fields to print)
561 void PRVM_ED_Print(prvm_edict_t *ed)
569 char tempstring[8192], tempstring2[260]; // temporary string buffers
573 Con_Printf("%s: FREE\n",PRVM_NAME);
578 sprintf(tempstring, "\n%s EDICT %i:\n", PRVM_NAME, PRVM_NUM_FOR_EDICT(ed));
579 for (i=1 ; i<prog->progs->numfielddefs ; i++)
581 d = &prog->fielddefs[i];
582 name = PRVM_GetString(d->s_name);
583 if (name[strlen(name)-2] == '_')
584 continue; // skip _x, _y, _z vars
586 v = (int *)((char *)ed->v + d->ofs*4);
588 // if the value is still all 0, skip the field
589 type = d->type & ~DEF_SAVEGLOBAL;
591 for (j=0 ; j<prvm_type_size[type] ; j++)
594 if (j == prvm_type_size[type])
597 if (strlen(name) > 256)
599 memcpy (tempstring2, name, 256);
600 tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
601 tempstring2[259] = 0;
604 strcat(tempstring, name);
605 for (l = strlen(name);l < 14;l++)
606 strcat(tempstring, " ");
607 strcat(tempstring, " ");
609 name = PRVM_ValueString(d->type, (prvm_eval_t *)v);
610 if (strlen(name) > 256)
612 memcpy (tempstring2, name, 256);
613 tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
614 tempstring2[259] = 0;
617 strcat(tempstring, name);
618 strcat(tempstring, "\n");
619 if (strlen(tempstring) >= 4096)
621 Con_Print(tempstring);
626 Con_Print(tempstring);
636 void PRVM_ED_Write (qfile_t *f, prvm_edict_t *ed)
652 for (i=1 ; i<prog->progs->numfielddefs ; i++)
654 d = &prog->fielddefs[i];
655 name = PRVM_GetString(d->s_name);
656 if (name[strlen(name)-2] == '_')
657 continue; // skip _x, _y, _z vars
659 v = (int *)((char *)ed->v + d->ofs*4);
661 // if the value is still all 0, skip the field
662 type = d->type & ~DEF_SAVEGLOBAL;
663 for (j=0 ; j<prvm_type_size[type] ; j++)
666 if (j == prvm_type_size[type])
669 FS_Printf(f,"\"%s\" ",name);
670 FS_Printf(f,"\"%s\"\n", PRVM_UglyValueString(d->type, (prvm_eval_t *)v));
676 void PRVM_ED_PrintNum (int ent)
678 PRVM_ED_Print(PRVM_EDICT_NUM(ent));
683 PRVM_ED_PrintEdicts_f
685 For debugging, prints all the entities in the current server
688 void PRVM_ED_PrintEdicts_f (void)
694 Con_Print("prvm_edicts <program name>\n");
699 if(!PRVM_SetProgFromString(Cmd_Argv(1)))
702 Con_Printf("%s: %i entities\n", PRVM_NAME, prog->num_edicts);
703 for (i=0 ; i<prog->num_edicts ; i++)
704 PRVM_ED_PrintNum (i);
713 For debugging, prints a single edict
716 void PRVM_ED_PrintEdict_f (void)
722 Con_Print("prvm_edict <program name> <edict number>\n");
727 if(!PRVM_SetProgFromString(Cmd_Argv(1)))
730 i = atoi (Cmd_Argv(2));
731 if (i >= prog->num_edicts)
733 Con_Print("Bad edict number\n");
737 PRVM_ED_PrintNum (i);
749 // 2 possibilities : 1. just displaying the active edict count
750 // 2. making a function pointer [x]
751 void PRVM_ED_Count_f (void)
759 Con_Print("prvm_count <program name>\n");
764 if(!PRVM_SetProgFromString(Cmd_Argv(1)))
767 if(prog->count_edicts)
768 prog->count_edicts();
772 for (i=0 ; i<prog->num_edicts ; i++)
774 ent = PRVM_EDICT_NUM(i);
780 Con_Printf("num_edicts:%3i\n", prog->num_edicts);
781 Con_Printf("active :%3i\n", active);
788 ==============================================================================
792 FIXME: need to tag constants, doesn't really work
793 ==============================================================================
801 void PRVM_ED_WriteGlobals (qfile_t *f)
809 for (i=0 ; i<prog->progs->numglobaldefs ; i++)
811 def = &prog->globaldefs[i];
813 if ( !(def->type & DEF_SAVEGLOBAL) )
815 type &= ~DEF_SAVEGLOBAL;
817 if (type != ev_string && type != ev_float && type != ev_entity)
820 name = PRVM_GetString(def->s_name);
821 FS_Printf(f,"\"%s\" ", name);
822 FS_Printf(f,"\"%s\"\n", PRVM_UglyValueString(type, (prvm_eval_t *)&prog->globals[def->ofs]));
832 void PRVM_ED_ParseGlobals (const char *data)
834 char keyname[1024]; // LordHavoc: good idea? bad idea? was 64
840 if (!COM_ParseToken(&data, false))
841 PRVM_ERROR ("PRVM_ED_ParseEntity: EOF without closing brace");
842 if (com_token[0] == '}')
845 strcpy (keyname, com_token);
848 if (!COM_ParseToken(&data, false))
849 PRVM_ERROR ("PRVM_ED_ParseEntity: EOF without closing brace");
851 if (com_token[0] == '}')
852 PRVM_ERROR ("PRVM_ED_ParseEntity: closing brace without data");
854 key = PRVM_ED_FindGlobal (keyname);
857 Con_DPrintf("'%s' is not a global on %s\n", keyname, PRVM_NAME);
861 if (!PRVM_ED_ParseEpair(NULL, key, com_token))
862 PRVM_ERROR ("PRVM_ED_ParseGlobals: parse error");
866 //============================================================================
874 char *PRVM_ED_NewString (const char *string)
879 l = strlen(string) + 1;
880 new = Mem_Alloc(prog->edictstring_mempool, l);
883 for (i=0 ; i< l ; i++)
885 if (string[i] == '\\' && i < l-1)
888 if (string[i] == 'n')
894 *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 *)prog->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 = 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 Console command to set a field of a specified edict
995 void PRVM_ED_EdictSet_f(void)
1002 Con_Print("prvm_edictset <program name> <edict number> <field> <value>\n");
1007 if(!PRVM_SetProgFromString(Cmd_Argv(1)))
1009 Con_Printf("Wrong program name %s !\n", Cmd_Argv(1));
1013 ed = PRVM_EDICT_NUM(atoi(Cmd_Argv(2)));
1015 if((key = PRVM_ED_FindField(Cmd_Argv(3))) == 0)
1016 Con_Printf("Key %s not found !\n", Cmd_Argv(3));
1018 PRVM_ED_ParseEpair(ed, key, Cmd_Argv(4));
1024 ====================
1027 Parses an edict out of the given string, returning the new position
1028 ed should be a properly initialized empty edict.
1029 Used for initial level load and for savegames.
1030 ====================
1032 const char *PRVM_ED_ParseEdict (const char *data, prvm_edict_t *ent)
1042 // go through all the dictionary pairs
1046 if (!COM_ParseToken(&data, false))
1047 PRVM_ERROR ("PRVM_ED_ParseEntity: EOF without closing brace");
1048 if (com_token[0] == '}')
1051 // anglehack is to allow QuakeEd to write single scalar angles
1052 // and allow them to be turned into vectors. (FIXME...)
1053 if (!strcmp(com_token, "angle"))
1055 strcpy (com_token, "angles");
1061 // FIXME: change light to _light to get rid of this hack
1062 if (!strcmp(com_token, "light"))
1063 strcpy (com_token, "light_lev"); // hack for single light def
1065 strcpy (keyname, com_token);
1067 // another hack to fix keynames with trailing spaces
1068 n = strlen(keyname);
1069 while (n && keyname[n-1] == ' ')
1076 if (!COM_ParseToken(&data, false))
1077 PRVM_ERROR ("PRVM_ED_ParseEntity: EOF without closing brace");
1079 if (com_token[0] == '}')
1080 PRVM_ERROR ("PRVM_ED_ParseEntity: closing brace without data");
1084 // keynames with a leading underscore are used for utility comments,
1085 // and are immediately discarded by quake
1086 if (keyname[0] == '_')
1089 key = PRVM_ED_FindField (keyname);
1092 Con_DPrintf("%s: '%s' is not a field\n", PRVM_NAME, keyname);
1099 strcpy (temp, com_token);
1100 sprintf (com_token, "0 %s 0", temp);
1103 if (!PRVM_ED_ParseEpair(ent, key, com_token))
1104 PRVM_ERROR ("PRVM_ED_ParseEdict: parse error");
1108 ent->p.e->free = true;
1116 PRVM_ED_LoadFromFile
1118 The entities are directly placed in the array, rather than allocated with
1119 PRVM_ED_Alloc, because otherwise an error loading the map would have entity
1120 number references out of order.
1122 Creates a server's entity / program execution context by
1123 parsing textual entity definitions out of an ent file.
1125 Used for both fresh maps and savegame loads. A fresh map would also need
1126 to call PRVM_ED_CallSpawnFunctions () to let the objects initialize themselves.
1129 void PRVM_ED_LoadFromFile (const char *data)
1132 int parsed, inhibited, spawned, died;
1144 // parse the opening brace
1145 if (!COM_ParseToken(&data, false))
1147 if (com_token[0] != '{')
1148 PRVM_ERROR ("PRVM_ED_LoadFromFile: %s: found %s when expecting {", PRVM_NAME, com_token);
1150 // CHANGED: this is not conform to ED_LoadFromFile
1151 if(!prog->num_edicts)
1152 ent = PRVM_EDICT_NUM(0);
1154 ent = PRVM_ED_Alloc();
1157 if (ent != prog->edicts) // hack
1158 memset (ent->v, 0, prog->progs->entityfields * 4);
1160 data = PRVM_ED_ParseEdict (data, ent);
1163 // remove the entity ?
1164 if(prog->load_edict && !prog->load_edict(ent))
1172 // immediately call spawn function, but only if there is a self global and a classname
1174 if(prog->self && prog->flag & PRVM_FE_CLASSNAME)
1176 string_t handle = *(string_t*)&((float*)ent->v)[PRVM_ED_FindFieldOffset("classname")];
1179 Con_Print("No classname for:\n");
1185 // look for the spawn function
1186 func = PRVM_ED_FindFunction (PRVM_GetString(handle));
1190 if (developer.integer) // don't confuse non-developers with errors
1192 Con_Print("No spawn function for:\n");
1200 PRVM_G_INT(prog->self->ofs) = PRVM_EDICT_TO_PROG(ent);
1201 PRVM_ExecuteProgram (func - prog->functions, "");
1209 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);
1214 typedef struct dpfield_s
1221 #define DPFIELDS (sizeof(dpfields) / sizeof(dpfield_t))
1223 dpfield_t dpfields[] =
1234 void PRVM_ResetProg()
1236 /*mempool_t *t1, *t2, *t3;
1238 t1 = prog->progs_mempool;
1239 t2 = prog->edictstring_mempool;
1240 t3 = prog->edicts_mempool;
1242 Mem_EmptyPool(prog->progs_mempool);
1243 Mem_EmptyPool(prog->edictstring_mempool);
1244 Mem_EmptyPool(prog->edicts_mempool);*/
1245 Mem_FreePool(&prog->progs_mempool);
1246 Mem_FreePool(&prog->edictstring_mempool);
1247 Mem_FreePool(&prog->edicts_mempool);
1249 memset(prog,0,sizeof(prvm_prog_t));
1251 /*prog->time = &prog->_time;
1253 prog->progs_mempool = t1;
1254 prog->edictstring_mempool = t2;
1255 prog->edicts_mempool = t3;*/
1257 PRVM_GCALL(reset_cmd)();
1265 void PRVM_LoadProgs (const char * filename, int numrequiredfunc, char **required_func)
1269 ddef_t *infielddefs;
1270 dfunction_t *dfunctions;
1272 Mem_EmptyPool(prog->progs_mempool);
1273 Mem_EmptyPool(prog->edictstring_mempool);
1275 prog->progs = (dprograms_t *)FS_LoadFile (filename, prog->progs_mempool, false);
1276 if (prog->progs == NULL)
1277 PRVM_ERROR ("PRVM_LoadProgs: couldn't load %s for %s", filename, PRVM_NAME);
1279 Con_DPrintf("%s programs occupy %iK.\n", PRVM_NAME, fs_filesize/1024);
1281 pr_crc = CRC_Block((qbyte *)prog->progs, fs_filesize);
1283 // byte swap the header
1284 for (i = 0;i < (int) sizeof(*prog->progs) / 4;i++)
1285 ((int *)prog->progs)[i] = LittleLong ( ((int *)prog->progs)[i] );
1287 if (prog->progs->version != PROG_VERSION)
1288 PRVM_ERROR ("%s: %s has wrong version number (%i should be %i)", PRVM_NAME, filename, prog->progs->version, PROG_VERSION);
1289 if (prog->progs->crc != prog->crc)
1290 PRVM_ERROR ("%s: %s system vars have been modified, progdefs.h is out of date", PRVM_NAME, filename);
1292 //pr_functions = (dfunction_t *)((qbyte *)progs + progs->ofs_functions);
1293 dfunctions = (dfunction_t *)((qbyte *)prog->progs + prog->progs->ofs_functions);
1294 prog->strings = (char *)prog->progs + prog->progs->ofs_strings;
1295 prog->globaldefs = (ddef_t *)((qbyte *)prog->progs + prog->progs->ofs_globaldefs);
1297 // we need to expand the fielddefs list to include all the engine fields,
1298 // so allocate a new place for it
1299 infielddefs = (ddef_t *)((qbyte *)prog->progs + prog->progs->ofs_fielddefs);
1301 prog->fielddefs = Mem_Alloc(prog->progs_mempool, prog->progs->numfielddefs * sizeof(ddef_t));
1303 prog->statements = (dstatement_t *)((qbyte *)prog->progs + prog->progs->ofs_statements);
1305 // moved edict_size calculation down below field adding code
1307 //pr_global_struct = (globalvars_t *)((qbyte *)progs + progs->ofs_globals);
1308 prog->globals = (float *)((qbyte *)prog->progs + prog->progs->ofs_globals);
1310 // byte swap the lumps
1311 for (i=0 ; i<prog->progs->numstatements ; i++)
1313 prog->statements[i].op = LittleShort(prog->statements[i].op);
1314 prog->statements[i].a = LittleShort(prog->statements[i].a);
1315 prog->statements[i].b = LittleShort(prog->statements[i].b);
1316 prog->statements[i].c = LittleShort(prog->statements[i].c);
1319 prog->functions = Mem_Alloc(prog->progs_mempool, sizeof(mfunction_t) * prog->progs->numfunctions);
1320 for (i = 0;i < prog->progs->numfunctions;i++)
1322 prog->functions[i].first_statement = LittleLong (dfunctions[i].first_statement);
1323 prog->functions[i].parm_start = LittleLong (dfunctions[i].parm_start);
1324 prog->functions[i].s_name = LittleLong (dfunctions[i].s_name);
1325 prog->functions[i].s_file = LittleLong (dfunctions[i].s_file);
1326 prog->functions[i].numparms = LittleLong (dfunctions[i].numparms);
1327 prog->functions[i].locals = LittleLong (dfunctions[i].locals);
1328 memcpy(prog->functions[i].parm_size, dfunctions[i].parm_size, sizeof(dfunctions[i].parm_size));
1331 for (i=0 ; i<prog->progs->numglobaldefs ; i++)
1333 prog->globaldefs[i].type = LittleShort (prog->globaldefs[i].type);
1334 prog->globaldefs[i].ofs = LittleShort (prog->globaldefs[i].ofs);
1335 prog->globaldefs[i].s_name = LittleLong (prog->globaldefs[i].s_name);
1338 // copy the progs fields to the new fields list
1339 for (i = 0;i < prog->progs->numfielddefs;i++)
1341 prog->fielddefs[i].type = LittleShort (infielddefs[i].type);
1342 if (prog->fielddefs[i].type & DEF_SAVEGLOBAL)
1343 PRVM_ERROR ("PRVM_LoadProgs: prog->fielddefs[i].type & DEF_SAVEGLOBAL in %s", PRVM_NAME);
1344 prog->fielddefs[i].ofs = LittleShort (infielddefs[i].ofs);
1345 prog->fielddefs[i].s_name = LittleLong (infielddefs[i].s_name);
1348 /* // append the darkplaces fields
1349 for (i = 0;i < (int) DPFIELDS;i++)
1351 pr_fielddefs[progs->numfielddefs].type = dpfields[i].type;
1352 pr_fielddefs[progs->numfielddefs].ofs = progs->entityfields;
1353 pr_fielddefs[progs->numfielddefs].s_name = PR_SetString(dpfields[i].string);
1354 if (pr_fielddefs[progs->numfielddefs].type == ev_vector)
1355 progs->entityfields += 3;
1357 progs->entityfields++;
1358 progs->numfielddefs++;
1361 // check required functions
1362 for(i=0 ; i < numrequiredfunc ; i++)
1363 if(PRVM_ED_FindFunction(required_func[i]) == 0)
1364 PRVM_ERROR("%s: %s not found in %s\n",PRVM_NAME, required_func[i], filename);
1366 for (i=0 ; i<prog->progs->numglobals ; i++)
1367 ((int *)prog->globals)[i] = LittleLong (((int *)prog->globals)[i]);
1369 // moved edict_size calculation down here, below field adding code
1370 // LordHavoc: this no longer includes the edict_t header
1371 prog->edict_size = prog->progs->entityfields * 4;
1372 prog->edictareasize = prog->edict_size * MAX_EDICTS;
1374 // LordHavoc: bounds check anything static
1375 for (i = 0,st = prog->statements;i < prog->progs->numstatements;i++,st++)
1381 if ((unsigned short) st->a >= prog->progs->numglobals || st->b + i < 0 || st->b + i >= prog->progs->numstatements)
1382 PRVM_ERROR("PRVM_LoadProgs: out of bounds IF/IFNOT (statement %d) in %s\n", i, PRVM_NAME);
1385 if (st->a + i < 0 || st->a + i >= prog->progs->numstatements)
1386 PRVM_ERROR("PRVM_LoadProgs: out of bounds GOTO (statement %d) in %s\n", i, PRVM_NAME);
1388 // global global global
1423 if ((unsigned short) st->a >= prog->progs->numglobals || (unsigned short) st->b >= prog->progs->numglobals || (unsigned short) st->c >= prog->progs->numglobals)
1424 PRVM_ERROR("PRVM_LoadProgs: out of bounds global index (statement %d)\n", i);
1426 // global none global
1432 if ((unsigned short) st->a >= prog->progs->numglobals || (unsigned short) st->c >= prog->progs->numglobals)
1433 PRVM_ERROR("PRVM_LoadProgs: out of bounds global index (statement %d) in %s\n", i, PRVM_NAME);
1449 if ((unsigned short) st->a >= prog->progs->numglobals || (unsigned short) st->b >= prog->progs->numglobals)
1450 PRVM_ERROR("PRVM_LoadProgs: out of bounds global index (statement %d)\n in %s", i, PRVM_NAME);
1464 if ((unsigned short) st->a >= prog->progs->numglobals)
1465 PRVM_ERROR("PRVM_LoadProgs: out of bounds global index (statement %d) in %s\n", i, PRVM_NAME);
1468 PRVM_ERROR("PRVM_LoadProgs: unknown opcode %d at statement %d in %s\n", st->op, i, PRVM_NAME);
1475 prog->loaded = TRUE;
1477 // set flags & ddef_ts in prog
1481 prog->self = PRVM_ED_FindGlobal("self");
1483 if( PRVM_ED_FindGlobal("time") && PRVM_ED_FindGlobal("time")->type & ev_float )
1484 prog->time = &PRVM_G_FLOAT(PRVM_ED_FindGlobal("time")->ofs);
1486 if(PRVM_ED_FindField ("chain"))
1487 prog->flag |= PRVM_FE_CHAIN;
1489 if(PRVM_ED_FindField ("classname"))
1490 prog->flag |= PRVM_FE_CLASSNAME;
1492 if(PRVM_ED_FindField ("nextthink") && PRVM_ED_FindField ("frame") && PRVM_ED_FindField ("think")
1493 && prog->flag && prog->self)
1494 prog->flag |= PRVM_OP_STATE;
1496 PRVM_GCALL(reset_cmd)();
1497 PRVM_GCALL(init_cmd)();
1504 void PRVM_Fields_f (void)
1506 int i, j, ednum, used, usedamount;
1508 char tempstring[5000], tempstring2[260], *name;
1517 Con_Print("no progs loaded\n");
1524 Con_Print("prvm_fields <program name>\n");
1529 if(!PRVM_SetProgFromString(Cmd_Argv(1)))
1532 counts = Mem_Alloc(tempmempool, prog->progs->numfielddefs * sizeof(int));
1533 for (ednum = 0;ednum < prog->max_edicts;ednum++)
1535 ed = PRVM_EDICT_NUM(ednum);
1538 for (i = 1;i < prog->progs->numfielddefs;i++)
1540 d = &prog->fielddefs[i];
1541 name = PRVM_GetString(d->s_name);
1542 if (name[strlen(name)-2] == '_')
1543 continue; // skip _x, _y, _z vars
1544 v = (int *)((char *)ed->v + d->ofs*4);
1545 // if the value is still all 0, skip the field
1546 for (j = 0;j < prvm_type_size[d->type & ~DEF_SAVEGLOBAL];j++)
1559 for (i = 0;i < prog->progs->numfielddefs;i++)
1561 d = &prog->fielddefs[i];
1562 name = PRVM_GetString(d->s_name);
1563 if (name[strlen(name)-2] == '_')
1564 continue; // skip _x, _y, _z vars
1565 switch(d->type & ~DEF_SAVEGLOBAL)
1568 strcat(tempstring, "string ");
1571 strcat(tempstring, "entity ");
1574 strcat(tempstring, "function ");
1577 strcat(tempstring, "field ");
1580 strcat(tempstring, "void ");
1583 strcat(tempstring, "float ");
1586 strcat(tempstring, "vector ");
1589 strcat(tempstring, "pointer ");
1592 sprintf (tempstring2, "bad type %i ", d->type & ~DEF_SAVEGLOBAL);
1593 strcat(tempstring, tempstring2);
1596 if (strlen(name) > 256)
1598 memcpy (tempstring2, name, 256);
1599 tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
1600 tempstring2[259] = 0;
1603 strcat(tempstring, name);
1604 for (j = strlen(name);j < 25;j++)
1605 strcat(tempstring, " ");
1606 sprintf(tempstring2, "%5d", counts[i]);
1607 strcat(tempstring, tempstring2);
1608 strcat(tempstring, "\n");
1609 if (strlen(tempstring) >= 4096)
1611 Con_Print(tempstring);
1617 usedamount += prvm_type_size[d->type & ~DEF_SAVEGLOBAL];
1621 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);
1626 void PRVM_Globals_f (void)
1632 Con_Print("no progs loaded\n");
1635 if(Cmd_Argc () != 2)
1637 Con_Print("prvm_globals <program name>\n");
1642 if(!PRVM_SetProgFromString (Cmd_Argv (1)))
1645 Con_Printf("%s :", PRVM_NAME);
1647 for (i = 0;i < prog->progs->numglobaldefs;i++)
1648 Con_Printf("%s\n", PRVM_GetString(prog->globaldefs[i].s_name));
1649 Con_Printf("%i global variables, totalling %i bytes\n", prog->progs->numglobals, prog->progs->numglobals * 4);
1659 void PRVM_Global_f(void)
1662 if( Cmd_Argc() != 3 ) {
1663 Con_Printf( "prvm_global <program name> <global name>\n" );
1668 if( !PRVM_SetProgFromString( Cmd_Argv(1) ) )
1671 global = PRVM_ED_FindGlobal( Cmd_Argv(2) );
1673 Con_Printf( "No global '%s' in %s!\n", Cmd_Argv(2), Cmd_Argv(1) );
1675 Con_Printf( "%s: %s\n", Cmd_Argv(2), PRVM_ValueString( global->type, (prvm_eval_t *) &prog->globals[ global->ofs ] ) );
1684 void PRVM_GlobalSet_f(void)
1687 if( Cmd_Argc() != 4 ) {
1688 Con_Printf( "prvm_globalset <program name> <global name> <value>\n" );
1693 if( !PRVM_SetProgFromString( Cmd_Argv(1) ) )
1696 global = PRVM_ED_FindGlobal( Cmd_Argv(2) );
1698 Con_Printf( "No global '%s' in %s!\n", Cmd_Argv(2), Cmd_Argv(1) );
1700 PRVM_ED_ParseEpair( NULL, global, Cmd_Argv(3) );
1709 void PRVM_Init (void)
1711 Cmd_AddCommand ("prvm_edict", PRVM_ED_PrintEdict_f);
1712 Cmd_AddCommand ("prvm_edicts", PRVM_ED_PrintEdicts_f);
1713 Cmd_AddCommand ("prvm_edictcount", PRVM_ED_Count_f);
1714 Cmd_AddCommand ("prvm_profile", PRVM_Profile_f);
1715 Cmd_AddCommand ("prvm_fields", PRVM_Fields_f);
1716 Cmd_AddCommand ("prvm_globals", PRVM_Globals_f);
1717 Cmd_AddCommand ("prvm_global", PRVM_Global_f);
1718 Cmd_AddCommand ("prvm_globalset", PRVM_GlobalSet_f);
1719 Cmd_AddCommand ("prvm_edictset", PRVM_ED_EdictSet_f);
1720 // LordHavoc: optional runtime bounds checking (speed drain, but worth it for security, on by default - breaks most QCCX features (used by CRMod and others))
1721 Cvar_RegisterVariable (&prvm_boundscheck);
1722 Cvar_RegisterVariable (&prvm_traceqc);
1732 void PRVM_InitProg(int prognr)
1734 if(prognr < 0 || prognr >= PRVM_MAXPROGS)
1735 Sys_Error("PRVM_InitProg: Invalid program number %i\n",prognr);
1737 prog = &prog_list[prognr];
1742 memset(prog, 0, sizeof(prvm_prog_t));
1744 prog->time = &prog->_time;
1747 int PRVM_GetProgNr()
1749 return prog - prog_list;
1752 // LordHavoc: turned PRVM_EDICT_NUM into a #define for speed reasons
1753 prvm_edict_t *PRVM_EDICT_NUM_ERROR(int n, char *filename, int fileline)
1755 PRVM_ERROR ("PRVM_EDICT_NUM: %s: bad number %i (called at %s:%i)", PRVM_NAME, n, filename, fileline);
1759 void PRVM_ProcessError(void)
1762 PRVM_GCALL(error_cmd)();
1766 int NUM_FOR_EDICT_ERROR(edict_t *e)
1768 Host_Error ("NUM_FOR_EDICT: bad pointer %p (world is %p, entity number would be %i)", e, sv.edicts, e - sv.edicts);
1772 int NUM_FOR_EDICT(edict_t *e)
1776 if ((unsigned int)n >= MAX_EDICTS)
1777 Host_Error ("NUM_FOR_EDICT: bad pointer");
1781 //int NoCrash_NUM_FOR_EDICT(edict_t *e)
1783 // return e - sv.edicts;
1786 //#define EDICT_TO_PROG(e) ((qbyte *)(((edict_t *)e)->v) - (qbyte *)(sv.edictsfields))
1787 //#define PROG_TO_EDICT(e) (sv.edicts + ((e) / (progs->entityfields * 4)))
1788 int EDICT_TO_PROG(edict_t *e)
1792 if ((unsigned int)n >= (unsigned int)sv.max_edicts)
1793 Host_Error("EDICT_TO_PROG: invalid edict %8p (number %i compared to world at %8p)\n", e, n, sv.edicts);
1794 return n;// EXPERIMENTAL
1795 //return (qbyte *)e->v - (qbyte *)sv.edictsfields;
1797 edict_t *PROG_TO_EDICT(int n)
1799 if ((unsigned int)n >= (unsigned int)sv.max_edicts)
1800 Host_Error("PROG_TO_EDICT: invalid edict number %i\n", n);
1801 return sv.edicts + n; // EXPERIMENTAL
1802 //return sv.edicts + ((n) / (progs->entityfields * 4));