Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-// AK new vm
+// AK new vm
#include "quakedef.h"
#include "progsvm.h"
// reserve space for the null entity aka world
// check bound of max_edicts
prog->max_edicts = bound(1, prog->max_edicts, prog->limit_edicts);
- prog->num_edicts = bound(1, prog->num_edicts, prog->max_edicts);
+ prog->num_edicts = bound(1, prog->num_edicts, prog->max_edicts);
// edictprivate_size has to be min as big prvm_edict_private_t
- prog->edictprivate_size = max(prog->edictprivate_size,(int)sizeof(prvm_edict_private_t));
+ prog->edictprivate_size = max(prog->edictprivate_size,(int)sizeof(prvm_edict_private_t));
// alloc edicts
- prog->edicts = Mem_Alloc(prog->edicts_mempool,prog->limit_edicts * sizeof(prvm_edict_t));
-
+ prog->edicts = Mem_Alloc(prog->progs_mempool,prog->limit_edicts * sizeof(prvm_edict_t));
+
// alloc edict private space
- prog->edictprivate = Mem_Alloc(prog->edicts_mempool, prog->max_edicts * prog->edictprivate_size);
-
+ prog->edictprivate = Mem_Alloc(prog->progs_mempool, prog->max_edicts * prog->edictprivate_size);
+
// alloc edict fields
- prog->edictsfields = Mem_Alloc(prog->edicts_mempool, prog->max_edicts * prog->edict_size);
+ prog->edictsfields = Mem_Alloc(prog->progs_mempool, prog->max_edicts * prog->edict_size);
// set edict pointers
for(i = 0; i < prog->max_edicts; i++)
void PRVM_MEM_IncreaseEdicts()
{
int i;
- int oldmaxedicts = prog->max_edicts;
+ int oldmaxedicts = prog->max_edicts;
void *oldedictsfields = prog->edictsfields;
void *oldedictprivate = prog->edictprivate;
-
+
if(prog->max_edicts >= prog->limit_edicts)
return;
-
+
PRVM_GCALL(begin_increase_edicts)();
// increase edicts
prog->max_edicts = min(prog->max_edicts + 256, prog->limit_edicts);
- prog->edictsfields = Mem_Alloc(prog->edicts_mempool, prog->max_edicts * prog->edict_size);
- prog->edictprivate = Mem_Alloc(prog->edicts_mempool, prog->max_edicts * prog->edictprivate_size);
+ prog->edictsfields = Mem_Alloc(prog->progs_mempool, prog->max_edicts * prog->edict_size);
+ prog->edictprivate = Mem_Alloc(prog->progs_mempool, prog->max_edicts * prog->edictprivate_size);
memcpy(prog->edictsfields, oldedictsfields, oldmaxedicts * prog->edict_size);
memcpy(prog->edictprivate, oldedictprivate, oldmaxedicts * prog->edictprivate_size);
void PRVM_SetProg(int prognr)
{
if(prognr && prognr < PRVM_MAXPROGS)
- {
+ {
if(prog_list[prognr].loaded)
prog = &prog_list[prognr];
else
num = PRVM_NUM_FOR_EDICT(e) - 1;
// AK: Let the init_edict function determine if something needs to be initialized
- PRVM_GCALL(init_edict)(num);
+ PRVM_GCALL(init_edict)(num);
}
/*
{
static char line[4096];
int i;
- char *s;
+ const char *s;
ddef_t *def;
mfunction_t *f;
-
+
type &= ~DEF_SAVEGLOBAL;
-
+
switch (type)
{
case ev_string:
line[i] = '\0';
break;
case ev_entity:
- snprintf (line, sizeof (line), "%i", PRVM_NUM_FOR_EDICT(PRVM_PROG_TO_EDICT(val->edict)));
+ dpsnprintf (line, sizeof (line), "%i", PRVM_NUM_FOR_EDICT(PRVM_PROG_TO_EDICT(val->edict)));
break;
case ev_function:
f = pr_functions + val->function;
break;
case ev_field:
def = PRVM_ED_FieldAtOfs ( val->_int );
- snprintf (line, sizeof (line), ".%s", PRVM_GetString(def->s_name));
+ dpsnprintf (line, sizeof (line), ".%s", PRVM_GetString(def->s_name));
break;
case ev_void:
- snprintf (line, sizeof (line), "void");
+ dpsnprintf (line, sizeof (line), "void");
break;
case ev_float:
- snprintf (line, sizeof (line), "%f", val->_float);
+ dpsnprintf (line, sizeof (line), "%f", val->_float);
break;
case ev_vector:
- snprintf (line, sizeof (line), "%f %f %f", val->vector[0], val->vector[1], val->vector[2]);
+ dpsnprintf (line, sizeof (line), "%f %f %f", val->vector[0], val->vector[1], val->vector[2]);
break;
default:
- snprintf (line, sizeof (line), "bad type %i", type);
+ dpsnprintf (line, sizeof (line), "bad type %i", type);
break;
}
-
+
return line;
}
ddef_t *d;
int *v;
int i, j;
- char *name;
+ const char *name;
int type;
char tempstring[8192], tempstring2[260]; // temporary string buffers
ddef_t *d;
int *v;
int i, j;
- char *name;
+ const char *name;
int type;
FS_Print(f, "{\n");
Con_Print("prvm_edicts <program name>\n");
return;
}
-
+
PRVM_Begin;
if(!PRVM_SetProgFromString(Cmd_Argv(1)))
return;
continue;
active++;
}
-
+
Con_Printf("num_edicts:%3i\n", prog->num_edicts);
Con_Printf("active :%3i\n", active);
}
{
ddef_t *def;
int i;
- char *name;
+ const char *name;
int type;
FS_Print(f,"{\n");
//============================================================================
-/*
-=============
-PRVM_ED_NewString
-=============
-*/
-char *PRVM_ED_NewString (const char *string)
-{
- char *new, *new_p;
- int i,l;
-
- l = strlen(string) + 1;
- new = Mem_Alloc(prog->edictstring_mempool, l);
- new_p = new;
-
- for (i=0 ; i< l ; i++)
- {
- if (string[i] == '\\' && i < l-1)
- {
- i++;
- if (string[i] == 'n')
- *new_p++ = '\n';
- else
- *new_p++ = '\\';
- }
- else
- *new_p++ = string[i];
- }
-
- return new;
-}
-
/*
=============
PRVM_ED_ParseEval
*/
qboolean PRVM_ED_ParseEpair(prvm_edict_t *ent, ddef_t *key, const char *s)
{
- int i;
+ int i, l;
+ char *new_p;
ddef_t *def;
prvm_eval_t *val;
mfunction_t *func;
switch (key->type & ~DEF_SAVEGLOBAL)
{
case ev_string:
- val->string = PRVM_SetString(PRVM_ED_NewString(s));
+ l = strlen(s) + 1;
+ new_p = PRVM_AllocString(l);
+ val->string = PRVM_SetQCString(new_p);
+ for (i = 0;i < l;i++)
+ {
+ if (s[i] == '\\' && i < l-1)
+ {
+ i++;
+ if (s[i] == 'n')
+ *new_p++ = '\n';
+ else if (s[i] == 'r')
+ *new_p++ = '\r';
+ else
+ *new_p++ = s[i];
+ }
+ else
+ *new_p++ = s[i];
+ }
break;
case ev_float:
PRVM_ERROR ("PRVM_ED_LoadFromFile: %s: found %s when expecting {", PRVM_NAME, com_token);
// CHANGED: this is not conform to ED_LoadFromFile
- if(!prog->num_edicts)
+ if(!prog->num_edicts)
ent = PRVM_EDICT_NUM(0);
- else
+ else
ent = PRVM_ED_Alloc();
// clear it
PRVM_ED_Free (ent);
continue;
}
-
+
// look for the spawn function
func = PRVM_ED_FindFunction (PRVM_GetString(handle));
-
+
if (!func)
{
if (developer.integer) // don't confuse non-developers with errors
PRVM_ED_Free (ent);
continue;
}
-
+
// self = ent
PRVM_G_INT(prog->self->ofs) = PRVM_EDICT_TO_PROG(ent);
PRVM_ExecuteProgram (func - prog->functions, "");
}
-
+
spawned++;
if (ent->p.e->free)
died++;
}
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);
-}
+}
// not used
/*
void PRVM_ResetProg()
{
- /*mempool_t *t1, *t2, *t3;
-
- t1 = prog->progs_mempool;
- t2 = prog->edictstring_mempool;
- t3 = prog->edicts_mempool;
-
- Mem_EmptyPool(prog->progs_mempool);
- Mem_EmptyPool(prog->edictstring_mempool);
- Mem_EmptyPool(prog->edicts_mempool);*/
Mem_FreePool(&prog->progs_mempool);
- Mem_FreePool(&prog->edictstring_mempool);
- Mem_FreePool(&prog->edicts_mempool);
-
memset(prog,0,sizeof(prvm_prog_t));
-
- /*prog->time = &prog->_time;
-
- prog->progs_mempool = t1;
- prog->edictstring_mempool = t2;
- prog->edicts_mempool = t3;*/
-
PRVM_GCALL(reset_cmd)();
}
dfunction_t *dfunctions;
Mem_EmptyPool(prog->progs_mempool);
- Mem_EmptyPool(prog->edictstring_mempool);
prog->progs = (dprograms_t *)FS_LoadFile (filename, prog->progs_mempool, false);
if (prog->progs == NULL)
//pr_functions = (dfunction_t *)((qbyte *)progs + progs->ofs_functions);
dfunctions = (dfunction_t *)((qbyte *)prog->progs + prog->progs->ofs_functions);
+
prog->strings = (char *)prog->progs + prog->progs->ofs_strings;
+ prog->stringssize = 0;
+ for (i = 0;i < prog->progs->numstrings;i++)
+ {
+ if (prog->progs->ofs_strings + prog->stringssize >= fs_filesize)
+ PRVM_ERROR ("%s: %s strings go past end of file\n", PRVM_NAME, filename);
+ prog->stringssize += strlen (prog->strings + prog->stringssize) + 1;
+ }
+ prog->numknownstrings = 0;
+ prog->maxknownstrings = 0;
+ prog->knownstrings = NULL;
+
prog->globaldefs = (ddef_t *)((qbyte *)prog->progs + prog->progs->ofs_globaldefs);
// we need to expand the fielddefs list to include all the engine fields,
{
pr_fielddefs[progs->numfielddefs].type = dpfields[i].type;
pr_fielddefs[progs->numfielddefs].ofs = progs->entityfields;
- pr_fielddefs[progs->numfielddefs].s_name = PR_SetString(dpfields[i].string);
+ pr_fielddefs[progs->numfielddefs].s_name = PR_SetEngineString(dpfields[i].string);
if (pr_fielddefs[progs->numfielddefs].type == ev_vector)
progs->entityfields += 3;
else
PRVM_Init_Exec();
prog->loaded = TRUE;
-
+
// set flags & ddef_ts in prog
-
+
prog->flag = 0;
-
+
prog->self = PRVM_ED_FindGlobal("self");
if( PRVM_ED_FindGlobal("time") && PRVM_ED_FindGlobal("time")->type & ev_float )
prog->flag |= PRVM_FE_CHAIN;
if(PRVM_ED_FindField ("classname"))
- prog->flag |= PRVM_FE_CLASSNAME;
+ prog->flag |= PRVM_FE_CLASSNAME;
- if(PRVM_ED_FindField ("nextthink") && PRVM_ED_FindField ("frame") && PRVM_ED_FindField ("think")
- && prog->flag && prog->self)
+ if(PRVM_ED_FindField ("nextthink") && PRVM_ED_FindField ("frame") && PRVM_ED_FindField ("think")
+ && prog->flag && prog->self)
prog->flag |= PRVM_OP_STATE;
-
+
PRVM_GCALL(reset_cmd)();
PRVM_GCALL(init_cmd)();
{
int i, j, ednum, used, usedamount;
int *counts;
- char tempstring[5000], tempstring2[260], *name;
+ char tempstring[5000], tempstring2[260];
+ const char *name;
prvm_edict_t *ed;
ddef_t *d;
int *v;
if( !global )
Con_Printf( "No global '%s' in %s!\n", Cmd_Argv(2), Cmd_Argv(1) );
else
- Con_Printf( "%s: %s\n", Cmd_Argv(2), PRVM_ValueString( global->type, (prvm_eval_t *) &prog->globals[ global->ofs ] ) );
+ Con_Printf( "%s: %s\n", Cmd_Argv(2), PRVM_ValueString( global->type, (prvm_eval_t *) &prog->globals[ global->ofs ] ) );
PRVM_End;
}
global = PRVM_ED_FindGlobal( Cmd_Argv(2) );
if( !global )
Con_Printf( "No global '%s' in %s!\n", Cmd_Argv(2), Cmd_Argv(1) );
- else
+ else
PRVM_ED_ParseEpair( NULL, global, Cmd_Argv(3) );
PRVM_End;
}
return prog - prog_list;
}
+void *_PRVM_Alloc(size_t buffersize, const char *filename, int fileline)
+{
+ return _Mem_Alloc(prog->progs_mempool, buffersize, filename, fileline);
+}
+
+void _PRVM_Free(void *buffer, const char *filename, int fileline)
+{
+ _Mem_Free(buffer, filename, fileline);
+}
+
+void _PRVM_FreeAll(const char *filename, int fileline)
+{
+ prog->progs = NULL;
+ prog->fielddefs = NULL;
+ prog->functions = NULL;
+ _Mem_EmptyPool(prog->progs_mempool, filename, fileline);
+}
+
// LordHavoc: turned PRVM_EDICT_NUM into a #define for speed reasons
prvm_edict_t *PRVM_EDICT_NUM_ERROR(int n, char *filename, int fileline)
{
}
*/
+
+const char *PRVM_GetString(int num)
+{
+ if (num >= 0 && num < prog->stringssize)
+ return prog->strings + num;
+ else if (num < 0 && num >= -prog->numknownstrings)
+ {
+ num = -1 - num;
+ if (!prog->knownstrings[num])
+ Host_Error("PRVM_GetString: attempt to get string that is already freed\n");
+ return prog->knownstrings[num];
+ }
+ else
+ {
+ Host_Error("PRVM_GetString: invalid string offset %i\n", num);
+ return "";
+ }
+}
+
+int PRVM_SetQCString(const char *s)
+{
+ int i;
+ if (!s)
+ return 0;
+ if (s >= prog->strings && s <= prog->strings + prog->stringssize)
+ return s - prog->strings;
+ for (i = 0;i < prog->numknownstrings;i++)
+ if (prog->knownstrings[i] == s)
+ return -1 - i;
+ Host_Error("PRVM_SetQCString: unknown string\n");
+ return -1 - i;
+}
+
+int PRVM_SetEngineString(const char *s)
+{
+ int i;
+ if (!s)
+ return 0;
+ if (s >= prog->strings && s <= prog->strings + prog->stringssize)
+ Host_Error("PRVM_SetEngineString: s in prog->strings area\n");
+ for (i = 0;i < prog->numknownstrings;i++)
+ if (prog->knownstrings[i] == s)
+ return -1 - i;
+ // new unknown engine string
+ if (developer.integer >= 3)
+ Con_Printf("new engine string %p\n", s);
+ for (i = 0;i < prog->numknownstrings;i++)
+ if (!prog->knownstrings[i])
+ break;
+ if (i >= prog->numknownstrings)
+ {
+ if (i >= prog->maxknownstrings)
+ {
+ const char **oldstrings = prog->knownstrings;
+ prog->maxknownstrings += 128;
+ prog->knownstrings = PRVM_Alloc(prog->maxknownstrings * sizeof(char *));
+ if (prog->numknownstrings)
+ memcpy((char **)prog->knownstrings, oldstrings, prog->numknownstrings * sizeof(char *));
+ }
+ prog->numknownstrings++;
+ }
+ prog->knownstrings[i] = s;
+ return -1 - i;
+}
+
+char *PRVM_AllocString(int bufferlength)
+{
+ int i;
+ if (!bufferlength)
+ return 0;
+ for (i = 0;i < prog->numknownstrings;i++)
+ if (!prog->knownstrings[i])
+ break;
+ if (i >= prog->numknownstrings)
+ {
+ if (i >= prog->maxknownstrings)
+ {
+ const char **oldstrings = prog->knownstrings;
+ prog->maxknownstrings += 128;
+ prog->knownstrings = PRVM_Alloc(prog->maxknownstrings * sizeof(char *));
+ if (prog->numknownstrings)
+ memcpy((char **)prog->knownstrings, oldstrings, prog->numknownstrings * sizeof(char *));
+ }
+ prog->numknownstrings++;
+ }
+ return (char *)(prog->knownstrings[i] = PRVM_Alloc(bufferlength));
+}
+
+void PRVM_FreeString(char *s)
+{
+ int i;
+ if (!s)
+ Host_Error("PRVM_FreeString: attempt to free a NULL string\n");
+ if (s >= prog->strings && s <= prog->strings + prog->stringssize)
+ Host_Error("PRVM_FreeString: attempt to free a constant string\n");
+ for (i = 0;i < prog->numknownstrings;i++)
+ if (prog->knownstrings[i] == s)
+ break;
+ if (i == prog->numknownstrings)
+ Host_Error("PRVM_FreeString: attempt to free a non-existent or already freed string\n");
+ PRVM_Free((char *)prog->knownstrings[i]);
+ prog->knownstrings[i] = NULL;
+}
+