}
static int picelements[6] = {0, 1, 2, 0, 2, 3};
-void DrawQ_Pic(float x, float y, char *picname, float width, float height, float red, float green, float blue, float alpha, int flags)
+void DrawQ_Pic(float x, float y, const char *picname, float width, float height, float red, float green, float blue, float alpha, int flags)
{
DrawQ_SuperPic(x,y,picname,width,height,0,0,red,green,blue,alpha,1,0,red,green,blue,alpha,0,1,red,green,blue,alpha,1,1,red,green,blue,alpha,flags);
}
DrawQ_SuperPic(x,y,NULL,w,h,0,0,red,green,blue,alpha,1,0,red,green,blue,alpha,0,1,red,green,blue,alpha,1,1,red,green,blue,alpha,flags);
}
-void DrawQ_SuperPic(float x, float y, char *picname, float width, float height, float s1, float t1, float r1, float g1, float b1, float a1, float s2, float t2, float r2, float g2, float b2, float a2, float s3, float t3, float r3, float g3, float b3, float a3, float s4, float t4, float r4, float g4, float b4, float a4, int flags)
+void DrawQ_SuperPic(float x, float y, const char *picname, float width, float height, float s1, float t1, float r1, float g1, float b1, float a1, float s2, float t2, float r2, float g2, float b2, float a2, float s3, float t3, float r3, float g3, float b3, float a3, float s4, float t4, float r4, float g4, float b4, float a4, int flags)
{
float floats[36];
cachepic_t *pic;
}
drawqueuemesh_t;
-enum drawqueue_drawflag_e {
+enum drawqueue_drawflag_e {
DRAWFLAG_NORMAL,
DRAWFLAG_ADDITIVE,
DRAWFLAG_MODULATE,
// clear the draw queue
void DrawQ_Clear(void);
// draw an image
-void DrawQ_Pic(float x, float y, char *picname, float width, float height, float red, float green, float blue, float alpha, int flags);
+void DrawQ_Pic(float x, float y, const char *picname, float width, float height, float red, float green, float blue, float alpha, int flags);
// draw a text string
void DrawQ_String(float x, float y, const char *string, int maxlen, float scalex, float scaley, float red, float green, float blue, float alpha, int flags);
// draw a filled rectangle
void DrawQ_Fill(float x, float y, float w, float h, float red, float green, float blue, float alpha, int flags);
// draw a very fancy pic (per corner texcoord/color control), the order is tl, tr, bl, br
-void DrawQ_SuperPic(float x, float y, char *picname, float width, float height, float s1, float t1, float r1, float g1, float b1, float a1, float s2, float t2, float r2, float g2, float b2, float a2, float s3, float t3, float r3, float g3, float b3, float a3, float s4, float t4, float r4, float g4, float b4, float a4, int flags);
+void DrawQ_SuperPic(float x, float y, const char *picname, float width, float height, float s1, float t1, float r1, float g1, float b1, float a1, float s2, float t2, float r2, float g2, float b2, float a2, float s3, float t3, float r3, float g3, float b3, float a3, float s4, float t4, float r4, float g4, float b4, float a4, int flags);
// draw a triangle mesh
void DrawQ_Mesh(drawqueuemesh_t *mesh, int flags);
// set the clipping area
return true;
}
-static clvideo_t* OpenVideo( clvideo_t *video, char *filename, char *name, int owner )
+static clvideo_t* OpenVideo( clvideo_t *video, const char *filename, const char *name, int owner )
{
strncpy( video->filename, filename, MAX_QPATH );
video->ownertag = owner;
return video;
}
-clvideo_t* CL_OpenVideo( char *filename, char *name, int owner )
+clvideo_t* CL_OpenVideo( const char *filename, const char *name, int owner )
{
clvideo_t *video;
return OpenVideo( video, filename, name, owner );
}
-clvideo_t* CL_GetVideo( char *name )
+clvideo_t* CL_GetVideo( const char *name )
{
int i;
clvideo_t *video;
cachepic_t cpif;
// if a video is suspended, it is automatically paused (else we'd still have to process the frames)
-
+
// used to determine whether the video's resources should be freed or not
- double lasttime;
+ double lasttime;
// when lasttime - realtime > THRESHOLD, all but the stream is freed
- qboolean suspended;
+ qboolean suspended;
char filename[MAX_QPATH];
} clvideo_t;
-clvideo_t* CL_OpenVideo( char *filename, char *name, int owner );
-clvideo_t* CL_GetVideo( char *name );
+clvideo_t* CL_OpenVideo( const char *filename, const char *name, int owner );
+clvideo_t* CL_GetVideo( const char *name );
void CL_SetVideoState( clvideo_t *video, clvideostate_t state );
void CL_RestartVideo( clvideo_t *video );
0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
};
-unsigned short CRC_Block(qbyte *data, int size)
+unsigned short CRC_Block(const qbyte *data, int size)
{
unsigned short crc = CRC_INIT_VALUE;
while (size--)
void Com_HexDumpToConsole(const qbyte *data, int size);
-unsigned short CRC_Block(qbyte *data, int size);
+unsigned short CRC_Block(const qbyte *data, int size);
//============================================================================
cachepic_t;
void Draw_Init (void);
-cachepic_t *Draw_CachePic (char *path, qboolean persistent);
+cachepic_t *Draw_CachePic (const char *path, qboolean persistent);
// create or update a pic's image
-cachepic_t *Draw_NewPic(char *picname, int width, int height, int alpha, qbyte *pixels);
+cachepic_t *Draw_NewPic(const char *picname, int width, int height, int alpha, qbyte *pixels);
// free the texture memory used by a pic
-void Draw_FreePic(char *picname);
+void Draw_FreePic(const char *picname);
void R_DrawQueue(void);
================
*/
// FIXME: move this to client somehow
-cachepic_t *Draw_CachePic (char *path, qboolean persistent)
+cachepic_t *Draw_CachePic (const char *path, qboolean persistent)
{
int i, crc, hashkey;
cachepic_t *pic;
return pic;
}
-cachepic_t *Draw_NewPic(char *picname, int width, int height, int alpha, qbyte *pixels)
+cachepic_t *Draw_NewPic(const char *picname, int width, int height, int alpha, qbyte *pixels)
{
int crc, hashkey;
cachepic_t *pic;
return pic;
}
-void Draw_FreePic(char *picname)
+void Draw_FreePic(const char *picname)
{
int crc;
int hashkey;
}
// remove leaving player from scoreboard
- //host_client->edict->v->netname = PR_SetString(host_client->name);
+ //host_client->edict->v->netname = PR_SetEngineString(host_client->name);
//if ((val = GETEDICTFIELDVALUE(host_client->edict, eval_clientcolors)))
// val->_float = 0;
//host_client->edict->v->frags = 0;
// write the light styles
for (i=0 ; i<MAX_LIGHTSTYLES ; i++)
{
- if (sv.lightstyles[i])
+ if (sv.lightstyles[i][0])
FS_Printf(f, "%s\n", sv.lightstyles[i]);
else
FS_Print(f,"m\n");
{
// light style
COM_ParseToken(&t, false);
- sv.lightstyles[i] = PR_Alloc(strlen(com_token)+1);
- strcpy(sv.lightstyles[i], com_token);
+ strlcpy(sv.lightstyles[i], com_token, sizeof(sv.lightstyles[i]));
}
// load the edicts out of the savegame file
// point the string back at updateclient->name to keep it safe
strlcpy (host_client->name, newName, sizeof (host_client->name));
- host_client->edict->v->netname = PR_SetString(host_client->name);
+ host_client->edict->v->netname = PR_SetEngineString(host_client->name);
if (strcmp(host_client->old_name, host_client->name))
{
if (host_client->spawned)
// point the string back at updateclient->name to keep it safe
strlcpy (host_client->playermodel, newPath, sizeof (host_client->playermodel));
if( eval_playermodel )
- GETEDICTFIELDVALUE(host_client->edict, eval_playermodel)->string = PR_SetString(host_client->playermodel);
+ GETEDICTFIELDVALUE(host_client->edict, eval_playermodel)->string = PR_SetEngineString(host_client->playermodel);
if (strcmp(host_client->old_model, host_client->playermodel))
{
if (host_client->spawned)
// point the string back at updateclient->name to keep it safe
strlcpy (host_client->playerskin, newPath, sizeof (host_client->playerskin));
if( eval_playerskin )
- GETEDICTFIELDVALUE(host_client->edict, eval_playerskin)->string = PR_SetString(host_client->playerskin);
+ GETEDICTFIELDVALUE(host_client->edict, eval_playerskin)->string = PR_SetEngineString(host_client->playerskin);
if (strcmp(host_client->old_skin, host_client->playerskin))
{
if (host_client->spawned)
#define NUMKEYS 5
-void M_FindKeysForCommand (char *command, int *keys)
+void M_FindKeysForCommand (const char *command, int *keys)
{
int count;
int j;
"NEXUIZ_PLAYERSKIN "
;
-qboolean checkextension(char *name)
+qboolean checkextension(const char *name)
{
int len;
char *e, *start;
if (e->e->free)
PF_WARNING("setmodel: can not modify free entity\n");
i = SV_ModelIndex(G_STRING(OFS_PARM1), 1);
- e->v->model = PR_SetString(sv.model_precache[i]);
+ e->v->model = PR_SetEngineString(sv.model_precache[i]);
e->v->modelindex = i;
mod = sv.models[i];
*/
void PF_ambientsound (void)
{
- char *samp;
+ const char *samp;
float *pos;
float vol, attenuation;
int soundnum, large;
*/
void PF_sound (void)
{
- char *sample;
+ const char *sample;
int channel;
edict_t *entity;
int volume;
void PF_stuffcmd (void)
{
int entnum;
- char *str;
+ const char *str;
client_t *old;
entnum = G_EDICTNUM(OFS_PARM0);
sprintf(s, "%i", (int)v);
else
sprintf(s, "%f", v);
- G_INT(OFS_RETURN) = PR_SetString(s);
+ G_INT(OFS_RETURN) = PR_SetEngineString(s);
}
void PF_fabs (void)
char *s;
s = PR_GetTempString();
sprintf (s, "'%5.1f %5.1f %5.1f'", G_VECTOR(OFS_PARM0)[0], G_VECTOR(OFS_PARM0)[1], G_VECTOR(OFS_PARM0)[2]);
- G_INT(OFS_RETURN) = PR_SetString(s);
+ G_INT(OFS_RETURN) = PR_SetEngineString(s);
}
void PF_etos (void)
char *s;
s = PR_GetTempString();
sprintf (s, "entity %i", G_EDICTNUM(OFS_PARM0));
- G_INT(OFS_RETURN) = PR_SetString(s);
+ G_INT(OFS_RETURN) = PR_SetEngineString(s);
}
void PF_Spawn (void)
{
int e;
int f;
- char *s, *t;
+ const char *s, *t;
edict_t *ed;
e = G_EDICTNUM(OFS_PARM0);
{
int i;
int f;
- char *s, *t;
+ const char *s, *t;
edict_t *ent, *chain;
chain = (edict_t *)sv.edicts;
RETURN_EDICT(chain);
}
-void PR_CheckEmptyString (char *s)
-{
- if (s[0] <= ' ')
- PF_ERROR("Bad string");
-}
-
void PF_precache_file (void)
{ // precache_file is only used to copy files with qcc, it does nothing
G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
void PF_lightstyle (void)
{
int style;
- char *val;
+ const char *val;
client_t *client;
int j;
val = G_STRING(OFS_PARM1);
// change the string in sv
- sv.lightstyles[style] = val;
+ strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
// send message to all clients on this server
if (sv.state != ss_active)
*/
void PF_changelevel (void)
{
- char *s;
+ const char *s;
// make sure we don't issue two changelevels
if (svs.changelevel_issued)
void PF_registercvar (void)
{
- char *name, *value;
+ const char *name, *value;
name = G_STRING(OFS_PARM0);
value = G_STRING(OFS_PARM1);
G_FLOAT(OFS_RETURN) = 0;
void PF_effect (void)
{
int i;
- char *s;
+ const char *s;
s = G_STRING(OFS_PARM1);
if (!s || !s[0])
PF_WARNING("effect: no model specified\n");
G_INT(OFS_RETURN) = 0;
if (!(surface = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1))))
return;
- G_INT(OFS_RETURN) = PR_SetString(surface->texture->name);
+ G_INT(OFS_RETURN) = PR_SetEngineString(surface->texture->name);
}
//PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
void PF_getsurfacenearpoint(void)
void PF_fopen(void)
{
int filenum, mode;
- char *modestring, *filename;
+ const char *modestring, *filename;
for (filenum = 0;filenum < MAX_PRFILES;filenum++)
if (pr_files[filenum] == NULL)
break;
if (developer.integer)
Con_Printf("fgets: %s\n", string);
if (c >= 0 || end)
- G_INT(OFS_RETURN) = PR_SetString(string);
+ G_INT(OFS_RETURN) = PR_SetEngineString(string);
else
G_INT(OFS_RETURN) = 0;
}
//float(string s) strlen = #114; // returns how many characters are in a string
void PF_strlen(void)
{
- char *s;
+ const char *s;
s = G_STRING(OFS_PARM0);
if (s)
G_FLOAT(OFS_RETURN) = strlen(s);
{
char *s = PR_GetTempString();
PF_VarString(0, s, STRINGTEMP_LENGTH);
- G_INT(OFS_RETURN) = PR_SetString(s);
+ G_INT(OFS_RETURN) = PR_SetEngineString(s);
}
//string(string s, float start, float length) substring = #116; // returns a section of a string as a tempstring
void PF_substring(void)
{
int i, start, length;
- char *s, *string = PR_GetTempString();
+ const char *s;
+ char *string = PR_GetTempString();
s = G_STRING(OFS_PARM0);
start = G_FLOAT(OFS_PARM1);
length = G_FLOAT(OFS_PARM2);
for (i = 0;i < STRINGTEMP_LENGTH - 1 && *s && i < length;i++, s++)
string[i] = *s;
string[i] = 0;
- G_INT(OFS_RETURN) = PR_SetString(string);
+ G_INT(OFS_RETURN) = PR_SetEngineString(string);
}
//vector(string s) stov = #117; // returns vector value from a string
//string(string s) strzone = #118; // makes a copy of a string into the string zone and returns it, this is often used to keep around a tempstring for longer periods of time (tempstrings are replaced often)
void PF_strzone(void)
{
- char *in, *out;
+ const char *in;
+ char *out;
in = G_STRING(OFS_PARM0);
- out = PR_Alloc(strlen(in) + 1);
+ out = PR_AllocString(strlen(in) + 1);
strcpy(out, in);
- G_INT(OFS_RETURN) = PR_SetString(out);
+ G_INT(OFS_RETURN) = PR_SetQCString(out);
}
//void(string s) strunzone = #119; // removes a copy of a string from the string zone (you can not use that string again or it may crash!!!)
void PF_strunzone(void)
{
- PR_Free(G_STRING(OFS_PARM0));
+ PR_FreeString((char *)G_STRING(OFS_PARM0));
}
//void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
{
int token_num = G_FLOAT(OFS_PARM0);
if (token_num >= 0 && token_num < num_tokens)
- G_INT(OFS_RETURN) = PR_SetString(tokens[token_num]);
+ G_INT(OFS_RETURN) = PR_SetEngineString(tokens[token_num]);
else
- G_INT(OFS_RETURN) = PR_SetString("");
+ G_INT(OFS_RETURN) = PR_SetEngineString(NULL);
}
//void(entity e, entity tagentity, string tagname) setattachment = #443; // attachs e to a tag on tagentity (note: use "" to attach to entity origin/angles instead of a tag)
{
edict_t *e = G_EDICT(OFS_PARM0);
edict_t *tagentity = G_EDICT(OFS_PARM1);
- char *tagname = G_STRING(OFS_PARM2);
+ const char *tagname = G_STRING(OFS_PARM2);
eval_t *v;
int modelindex;
model_t *model;
/////////////////////////////////////////
// DP_MD3_TAGINFO extension coded by VorteX
-int SV_GetTagIndex (edict_t *e, char *tagname)
+int SV_GetTagIndex (edict_t *e, const char *tagname)
{
int i;
model_t *model;
void PF_gettagindex (void)
{
edict_t *ent = G_EDICT(OFS_PARM0);
- char *tag_name = G_STRING(OFS_PARM1);
+ const char *tag_name = G_STRING(OFS_PARM1);
int modelindex, tag_index;
if (ent == sv.edicts)
void PF_search_begin(void)
{
int handle;
- char *pattern;
+ const char *pattern;
int caseinsens, quiet;
pattern = G_STRING(OFS_PARM0);
-
- PR_CheckEmptyString(pattern);
+ if (!pattern || pattern[0] <= ' ')
+ PF_ERROR("PF_search_begin: Bad string");
caseinsens = G_FLOAT(OFS_PARM1);
quiet = G_FLOAT(OFS_PARM2);
tmp = PR_GetTempString();
strcpy(tmp, pr_fssearchlist[handle]->filenames[filenum]);
- G_INT(OFS_RETURN) = PR_SetString(tmp);
+ G_INT(OFS_RETURN) = PR_SetEngineString(tmp);
}
void PF_cvar_string (void)
{
- char *str;
+ const char *str;
cvar_t *var;
char *tmp;
strcpy(tmp, var->string);
}
else
- tmp = "";
- G_INT(OFS_RETURN) = PR_SetString(tmp);
+ tmp = NULL;
+ G_INT(OFS_RETURN) = PR_SetEngineString(tmp);
}
//void(entity clent) dropclient (DP_SV_DROPCLIENT)
dprograms_t *progs;
mfunction_t *pr_functions;
char *pr_strings;
+int pr_stringssize;
ddef_t *pr_fielddefs;
ddef_t *pr_globaldefs;
dstatement_t *pr_statements;
int pr_edict_size; // in bytes
int pr_edictareasize; // LordHavoc: in bytes
+int pr_maxknownstrings;
+int pr_numknownstrings;
+const char **pr_knownstrings;
+
unsigned short pr_crc;
mempool_t *serverprogs_mempool;
// set netname/clientcolors back to client values so that
// DP_SV_CLIENTNAME and DPV_SV_CLIENTCOLORS will not immediately
// reset them
- e->v->netname = PR_SetString(svs.clients[num].name);
+ e->v->netname = PR_SetEngineString(svs.clients[num].name);
if ((val = GETEDICTFIELDVALUE(e, eval_clientcolors)))
val->_float = svs.clients[num].colors;
// NEXUIZ_PLAYERMODEL and NEXUIZ_PLAYERSKIN
if( eval_playermodel )
- GETEDICTFIELDVALUE(host_client->edict, eval_playermodel)->string = PR_SetString(svs.clients[num].playermodel);
+ GETEDICTFIELDVALUE(host_client->edict, eval_playermodel)->string = PR_SetEngineString(svs.clients[num].playermodel);
if( eval_playerskin )
- GETEDICTFIELDVALUE(host_client->edict, eval_playerskin)->string = PR_SetString(svs.clients[num].playerskin);
+ GETEDICTFIELDVALUE(host_client->edict, eval_playerskin)->string = PR_SetEngineString(svs.clients[num].playerskin);
}
}
{
static char line[4096];
int i;
- char *s;
+ const char *s;
ddef_t *def;
mfunction_t *f;
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");
{
ddef_t *def;
int i;
- char *name;
+ const char *name;
int type;
FS_Print(f,"{\n");
//============================================================================
-/*
-=============
-ED_NewString
-=============
-*/
-char *ED_NewString (const char *string)
-{
- char *new, *new_p;
- int i,l;
-
- l = strlen(string) + 1;
- new = PR_Alloc(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 if (string[i] == 'r')
- *new_p++ = '\r';
- else
- *new_p++ = '\\';
- }
- else
- *new_p++ = string[i];
- }
-
- return new;
-}
-
-
/*
=============
ED_ParseEval
*/
qboolean ED_ParseEpair(edict_t *ent, ddef_t *key, const char *s)
{
- int i;
+ int i, l;
+ char *new_p;
ddef_t *def;
eval_t *val;
mfunction_t *func;
switch (key->type & ~DEF_SAVEGLOBAL)
{
case ev_string:
- val->string = PR_SetString(ED_NewString(s));
+ l = strlen(s) + 1;
+ new_p = PR_AllocString(l);
+ val->string = PR_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:
//pr_functions = (dfunction_t *)((qbyte *)progs + progs->ofs_functions);
dfunctions = (dfunction_t *)((qbyte *)progs + progs->ofs_functions);
+
pr_strings = (char *)progs + progs->ofs_strings;
+ pr_stringssize = 0;
+ for (i = 0;i < progs->numstrings;i++)
+ {
+ if (progs->ofs_strings + pr_stringssize >= fs_filesize)
+ Host_Error ("progs.dat strings go past end of file\n");
+ pr_stringssize += strlen (pr_strings + pr_stringssize) + 1;
+ }
+ pr_numknownstrings = 0;
+ pr_maxknownstrings = 0;
+ pr_knownstrings = NULL;
+
pr_globaldefs = (ddef_t *)((qbyte *)progs + 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
{
int i, j, ednum, used, usedamount;
int *counts;
- char tempstring[5000], tempstring2[260], *name;
+ const char *name;
+ char tempstring[5000], tempstring2[260];
edict_t *ed;
ddef_t *d;
int *v;
}
*/
+const char *PR_GetString(int num)
+{
+ if (num >= 0 && num < pr_stringssize)
+ return pr_strings + num;
+ else if (num < 0 && num >= -pr_numknownstrings)
+ {
+ num = -1 - num;
+ if (!pr_knownstrings[num])
+ Host_Error("PR_GetString: attempt to get string that is already freed\n");
+ return pr_knownstrings[num];
+ }
+ else
+ {
+ Host_Error("PR_GetString: invalid string offset %i\n", num);
+ return "";
+ }
+}
+
+int PR_SetQCString(const char *s)
+{
+ int i;
+ if (!s)
+ return 0;
+ if (s >= pr_strings && s <= pr_strings + pr_stringssize)
+ return s - pr_strings;
+ for (i = 0;i < pr_numknownstrings;i++)
+ if (pr_knownstrings[i] == s)
+ return -1 - i;
+ Host_Error("PR_SetQCString: unknown string\n");
+ return -1 - i;
+}
+
+int PR_SetEngineString(const char *s)
+{
+ int i;
+ if (!s)
+ return 0;
+ if (s >= pr_strings && s <= pr_strings + pr_stringssize)
+ Host_Error("PR_SetEngineString: s in pr_strings area\n");
+ for (i = 0;i < pr_numknownstrings;i++)
+ if (pr_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 < pr_numknownstrings;i++)
+ if (!pr_knownstrings[i])
+ break;
+ if (i >= pr_numknownstrings)
+ {
+ if (i >= pr_maxknownstrings)
+ {
+ const char **oldstrings = pr_knownstrings;
+ pr_maxknownstrings += 128;
+ pr_knownstrings = PR_Alloc(pr_maxknownstrings * sizeof(char *));
+ if (pr_numknownstrings)
+ memcpy(pr_knownstrings, oldstrings, pr_numknownstrings * sizeof(char *));
+ }
+ pr_numknownstrings++;
+ }
+ pr_knownstrings[i] = s;
+ return -1 - i;
+}
+
+char *PR_AllocString(int bufferlength)
+{
+ int i;
+ if (!bufferlength)
+ return 0;
+ for (i = 0;i < pr_numknownstrings;i++)
+ if (!pr_knownstrings[i])
+ break;
+ if (i >= pr_numknownstrings)
+ {
+ if (i >= pr_maxknownstrings)
+ {
+ const char **oldstrings = pr_knownstrings;
+ pr_maxknownstrings += 128;
+ pr_knownstrings = PR_Alloc(pr_maxknownstrings * sizeof(char *));
+ if (pr_numknownstrings)
+ memcpy(pr_knownstrings, oldstrings, pr_numknownstrings * sizeof(char *));
+ }
+ pr_numknownstrings++;
+ }
+ return (char *)(pr_knownstrings[i] = PR_Alloc(bufferlength));
+}
+
+void PR_FreeString(char *s)
+{
+ int i;
+ if (!s)
+ Host_Error("PR_FreeString: attempt to free a NULL string\n");
+ if (s >= pr_strings && s <= pr_strings + pr_stringssize)
+ Host_Error("PR_FreeString: attempt to free a constant string\n");
+ for (i = 0;i < pr_numknownstrings;i++)
+ if (pr_knownstrings[i] == s)
+ break;
+ if (i == pr_numknownstrings)
+ Host_Error("PR_FreeString: attempt to free a non-existent or already freed string\n");
+ PR_Free((char *)pr_knownstrings[i]);
+ pr_knownstrings[i] = NULL;
+}
+
extern dprograms_t *progs;
extern mfunction_t *pr_functions;
extern char *pr_strings;
+extern int pr_stringssize;
extern ddef_t *pr_globaldefs;
extern ddef_t *pr_fielddefs;
extern dstatement_t *pr_statements;
extern int pr_edict_size; // in bytes
extern int pr_edictareasize; // LordHavoc: for bounds checking
+extern int pr_maxknownstrings;
+extern int pr_numknownstrings;
+extern const char **pr_knownstrings;
+
//============================================================================
void PR_Init (void);
void ED_Free (edict_t *ed);
void ED_ClearEdict (edict_t *e);
-char *ED_NewString (const char *string);
-// returns a copy of the string allocated from the server's string heap
-
void ED_Print(edict_t *ed);
void ED_Write (qfile_t *f, edict_t *ed);
const char *ED_ParseEdict (const char *data, edict_t *ent);
void ED_PrintEdicts (void);
void ED_PrintNum (int ent);
-#define PR_GetString(num) (pr_strings + num)
-#define PR_SetString(s) ((s) != NULL ? (int) (s - pr_strings) : 0)
+const char *PR_GetString(int num);
+int PR_SetQCString(const char *s);
+int PR_SetEngineString(const char *s);
+char *PR_AllocString(int bufferlength);
+void PR_FreeString(char *s);
#endif
dprograms_t *progs;
mfunction_t *functions;
char *strings;
+ int stringssize;
ddef_t *fielddefs;
ddef_t *globaldefs;
dstatement_t *statements;
int edict_size; // in bytes
int edictareasize; // LordHavoc: in bytes (for bound checking)
+ int maxknownstrings;
+ int numknownstrings;
+ const char **knownstrings;
+
// all memory allocations related to this vm_prog (code, edicts, strings)
mempool_t *progs_mempool;
void PRVM_ExecuteProgram (func_t fnum, const char *errormessage);
void PRVM_LoadProgs (const char *filename, int numrequiredfunc, char **required_func);
+#define PRVM_Alloc(buffersize) _PRVM_Alloc(buffersize, __FILE__, __LINE__)
+#define PRVM_Free(buffer) _PRVM_Free(buffer, __FILE__, __LINE__)
+#define PRVM_FreeAll() _PRVM_FreeAll(__FILE__, __LINE__)
+void *_PRVM_Alloc (size_t buffersize, const char *filename, int fileline);
+void _PRVM_Free (void *buffer, const char *filename, int fileline);
+void _PRVM_FreeAll (const char *filename, int fileline);
+
void PRVM_Profile_f (void);
void PRVM_PrintState(void);
void PRVM_ED_Free (prvm_edict_t *ed);
void PRVM_ED_ClearEdict (prvm_edict_t *e);
-char *PRVM_ED_NewString (const char *string);
-// returns a copy of the string allocated from the server's string heap
-
void PRVM_ED_Print(prvm_edict_t *ed);
void PRVM_ED_Write (qfile_t *f, prvm_edict_t *ed);
const char *PRVM_ED_ParseEdict (const char *data, prvm_edict_t *ent);
void PRVM_ED_PrintEdicts_f (void);
void PRVM_ED_PrintNum (int ent);
-#define PRVM_GetString(num) (prog->strings + num)
-#define PRVM_SetString(s) ((s) != NULL ? (int) (s - prog->strings) : 0)
+const char *PRVM_GetString(int num);
+int PRVM_SetQCString(const char *s);
+int PRVM_SetEngineString(const char *s);
+char *PRVM_AllocString(int bufferlength);
+void PRVM_FreeString(char *s);
//============================================================================
#define VM_RETURN_EDICT(e) (((int *)prog->globals)[OFS_RETURN] = PRVM_EDICT_TO_PROG(e))
-#define VM_STRINGS_MEMPOOL vm_strings_mempool[PRVM_GetProgNr()]
-
#define e10 0,0,0,0,0,0,0,0,0,0
#define e100 e10,e10,e10,e10,e10,e10,e10,e10,e10,e10
#define e1000 e100,e100,e100,e100,e100,e100,e100,e100,e100,e100
//============================================================================
// Common
-// string zone mempool
-mempool_t *vm_strings_mempool[PRVM_MAXPROGS];
-
// temp string handling
// LordHavoc: added this to semi-fix the problem of using many ftos calls in a print
#define VM_STRINGTEMP_BUFFERS 16
return s;
}
-void VM_CheckEmptyString (char *s)
+void VM_CheckEmptyString (const char *s)
{
if (s[0] <= ' ')
PRVM_ERROR ("%s: Bad string", PRVM_NAME);
*/
// kind of helper function
-static qboolean checkextension(char *name)
+static qboolean checkextension(const char *name)
{
int len;
char *e, *start;
*/
void VM_localsound(void)
{
- char *s;
+ const char *s;
VM_SAFEPARMCOUNT(1,VM_localsound);
*/
void VM_str_cvar(void)
{
- char *out, *name;
+ char *out;
+ const char *name;
const char *cvar_string;
VM_SAFEPARMCOUNT(1,VM_str_cvar);
strcpy(out, cvar_string);
- PRVM_G_INT(OFS_RETURN) = PRVM_SetString(out);
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(out);
}
/*
sprintf(s, "%i", (int)v);
else
sprintf(s, "%f", v);
- PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(s);
}
/*
s = VM_GetTempString();
sprintf (s, "'%5.1f %5.1f %5.1f'", PRVM_G_VECTOR(OFS_PARM0)[0], PRVM_G_VECTOR(OFS_PARM0)[1], PRVM_G_VECTOR(OFS_PARM0)[2]);
- PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(s);
}
/*
s = VM_GetTempString();
sprintf (s, "entity %i", PRVM_G_EDICTNUM(OFS_PARM0));
- PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(s);
}
/*
{
int e;
int f;
- char *s, *t;
+ const char *s, *t;
prvm_edict_t *ed;
VM_SAFEPARMCOUNT(3,VM_find);
int i;
int f;
int chain_of;
- char *s, *t;
+ const char *s, *t;
prvm_edict_t *ent, *chain;
VM_SAFEPARMCOUNT(2,VM_findchain);
*/
void VM_precache_sound (void)
{
- char *s;
+ const char *s;
VM_SAFEPARMCOUNT(1, VM_precache_sound);
*/
void VM_changelevel (void)
{
- char *s;
+ const char *s;
VM_SAFEPARMCOUNT(1, VM_changelevel);
return;
svs.changelevel_issued = true;
- s = G_STRING(OFS_PARM0);
+ s = PRVM_G_STRING(OFS_PARM0);
Cbuf_AddText (va("changelevel %s\n",s));
}
*/
void VM_registercvar (void)
{
- char *name, *value;
+ const char *name, *value;
int flags;
VM_SAFEPARMCOUNT(3,VM_registercvar);
void VM_fopen(void)
{
int filenum, mode;
- char *modestring, *filename;
+ const char *modestring, *filename;
VM_SAFEPARMCOUNT(2,VM_fopen);
if (developer.integer >= 3)
Con_Printf("fgets: %s: %s\n", PRVM_NAME, string);
if (c >= 0 || end)
- PRVM_G_INT(OFS_RETURN) = PRVM_SetString(string);
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(string);
else
PRVM_G_INT(OFS_RETURN) = 0;
}
//float(string s) strlen = #114; // returns how many characters are in a string
void VM_strlen(void)
{
- char *s;
+ const char *s;
VM_SAFEPARMCOUNT(1,VM_strlen);
s = VM_GetTempString();
VM_VarString(0, s, VM_STRINGTEMP_LENGTH);
- PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(s);
}
/*
void VM_substring(void)
{
int i, start, length;
- char *s, *string;
+ const char *s;
+ char *string;
VM_SAFEPARMCOUNT(3,VM_substring);
for (i = 0;i < VM_STRINGTEMP_LENGTH - 1 && *s && i < length;i++, s++)
string[i] = *s;
string[i] = 0;
- PRVM_G_INT(OFS_RETURN) = PRVM_SetString(string);
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(string);
}
/*
//string(string s) strzone = #118; // makes a copy of a string into the string zone and returns it, this is often used to keep around a tempstring for longer periods of time (tempstrings are replaced often)
void VM_strzone(void)
{
- char *in, *out;
+ const char *in;
+ char *out;
VM_SAFEPARMCOUNT(1,VM_strzone);
in = PRVM_G_STRING(OFS_PARM0);
- out = Mem_Alloc(VM_STRINGS_MEMPOOL, strlen(in) + 1);
+ out = PRVM_AllocString(strlen(in) + 1);
strcpy(out, in);
- PRVM_G_INT(OFS_RETURN) = PRVM_SetString(out);
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetQCString(out);
}
/*
//void(string s) strunzone = #119; // removes a copy of a string from the string zone (you can not use that string again or it may crash!!!)
void VM_strunzone(void)
{
- char *str;
VM_SAFEPARMCOUNT(1,VM_strunzone);
-
- str = PRVM_G_STRING(OFS_PARM0);
- if( !str )
- PRVM_ERROR( "VM_strunzone: s%: Null string passed!", PRVM_NAME );
- if( developer.integer && !Mem_IsAllocated( VM_STRINGS_MEMPOOL, str ) )
- PRVM_ERROR( "VM_strunzone: Zone string already freed in %s!", PRVM_NAME );
- else
- Mem_Free( str );
+ PRVM_FreeString((char *)PRVM_G_STRING(OFS_PARM0));
}
/*
static int max_tokens, num_tokens = 0;
void VM_tokenize (void)
{
- const char *p;
- char *str;
+ const char *p, *str;
VM_SAFEPARMCOUNT(1,VM_tokenize);
token_num = PRVM_G_FLOAT(OFS_PARM0);
if (token_num >= 0 && token_num < num_tokens)
- PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tokens[token_num]);
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(tokens[token_num]);
else
- PRVM_G_INT(OFS_RETURN) = PRVM_SetString("");
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(NULL);
}
/*
*/
void VM_loadfromfile(void)
{
- char *filename;
+ const char *filename;
qbyte *data;
VM_SAFEPARMCOUNT(1,VM_loadfromfile);
void VM_search_begin(void)
{
int handle;
- char *pattern;
+ const char *pattern;
int caseinsens, quiet;
VM_SAFEPARMCOUNT(3, VM_search_begin);
tmp = VM_GetTempString();
strcpy(tmp, VM_SEARCHLIST[handle]->filenames[filenum]);
- PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tmp);
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(tmp);
}
/*
tmp[0] = (unsigned char) PRVM_G_FLOAT(OFS_PARM0);
tmp[1] = 0;
- PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tmp);
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(tmp);
}
//=============================================================================
*/
void VM_precache_pic(void)
{
- char *s;
+ const char *s;
VM_SAFEPARMCOUNT(1, VM_precache_pic);
// AK Draw_CachePic is supposed to always return a valid pointer
if( Draw_CachePic(s, false)->tex == r_texture_notexture )
- PRVM_G_INT(OFS_RETURN) = PRVM_SetString("");
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(NULL);
}
/*
*/
void VM_freepic(void)
{
- char *s;
+ const char *s;
VM_SAFEPARMCOUNT(1,VM_freepic);
void VM_drawstring(void)
{
float *pos,*scale,*rgb;
- char *string;
+ const char *string;
int flag;
VM_SAFEPARMCOUNT(6,VM_drawstring);
*/
void VM_drawpic(void)
{
- char *pic;
+ const char *pic;
float *size, *pos, *rgb;
int flag;
*/
void VM_getimagesize(void)
{
- char *p;
+ const char *p;
cachepic_t *pic;
VM_SAFEPARMCOUNT(1,VM_getimagesize);
*/
void VM_cin_open( void )
{
- char *file;
- char *name;
+ const char *file;
+ const char *name;
VM_SAFEPARMCOUNT( 2, VM_cin_open );
*/
void VM_cin_close( void )
{
- char *name;
+ const char *name;
VM_SAFEPARMCOUNT( 1, VM_cin_close );
*/
void VM_cin_setstate( void )
{
- char *name;
+ const char *name;
clvideostate_t state;
clvideo_t *video;
*/
void VM_cin_getstate( void )
{
- char *name;
+ const char *name;
clvideo_t *video;
VM_SAFEPARMCOUNT( 1, VM_cin_getstate );
*/
void VM_cin_restart( void )
{
- char *name;
+ const char *name;
clvideo_t *video;
VM_SAFEPARMCOUNT( 1, VM_cin_restart );
*/
void VM_altstr_count( void )
{
- char *altstr, *pos;
+ const char *altstr, *pos;
int count;
VM_SAFEPARMCOUNT( 1, VM_altstr_count );
void VM_altstr_prepare( void )
{
char *outstr, *out;
- char *instr, *in;
+ const char *instr, *in;
int size;
VM_SAFEPARMCOUNT( 1, VM_altstr_prepare );
*out = *in;
*out = 0;
- PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( outstr );
+ PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( outstr );
}
/*
*/
void VM_altstr_get( void )
{
- char *altstr, *pos, *outstr, *out;
+ const char *altstr, *pos;
+ char *outstr, *out;
int count, size;
VM_SAFEPARMCOUNT( 2, VM_altstr_get );
count--;
if( !*pos ) {
- PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( "" );
+ PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( NULL );
return;
}
*out = *pos;
*out = 0;
- PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( outstr );
+ PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( outstr );
}
/*
void VM_altstr_set( void )
{
int num;
- char *altstr, *str;
- char *in;
+ const char *altstr, *str;
+ const char *in;
char *outstr, *out;
VM_SAFEPARMCOUNT( 3, VM_altstr_set );
num--;
if( !in ) {
- PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( "" );
+ PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( NULL );
return;
}
// copy set in
break;
if( !in ) {
- PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( "" );
+ PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( NULL );
return;
}
strcpy( out, in );
- PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( outstr );
+ PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( outstr );
}
/*
void VM_altstr_ins(void)
{
int num;
- char *setstr;
- char *set;
- char *instr;
- char *in;
+ const char *setstr;
+ const char *set;
+ const char *instr;
+ const char *in;
char *outstr;
char *out;
for( ; *set ; *out++ = *set++ );
strcpy( out, in );
- PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( outstr );
+ PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( outstr );
}
void VM_Cmd_Init(void)
{
// only init the stuff for the current prog
- VM_STRINGS_MEMPOOL = Mem_AllocPool(va("vm_stringsmempool[%s]",PRVM_NAME), 0, NULL);
VM_Files_Init();
VM_Search_Init();
}
void VM_Cmd_Reset(void)
{
- //Mem_EmptyPool(VM_STRINGS_MEMPOOL);
- if( developer.integer >= 2 && VM_STRINGS_MEMPOOL ) {
- memheader_t *header;
- int i;
-
- for( i = 0, header = VM_STRINGS_MEMPOOL->chain ; header ; header = header->next, i++ )
- Con_DPrintf( "Leaked string %i (size: %i): %.*s\n", i, header->size, header->size, ((char*)header) + sizeof( memheader_t ) );
- }
-
- Mem_FreePool(&VM_STRINGS_MEMPOOL);
CL_PurgeOwner( MENUOWNER );
VM_Search_Reset();
VM_Files_CloseAll();
void VM_M_callfunction(void)
{
mfunction_t *func;
- char *s;
+ const char *s;
if(prog->argc == 0)
PRVM_ERROR("VM_M_callfunction: 1 parameter is required !\n");
void VM_M_isfunction(void)
{
mfunction_t *func;
- char *s;
+ const char *s;
VM_SAFEPARMCOUNT(1, VM_M_isfunction);
strcpy(tmp, Key_KeynumToString(keynum));
- PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tmp);
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(tmp);
}
/*
*/
void VM_M_stringtokeynum( void )
{
- char *str;
+ const char *str;
VM_SAFEPARMCOUNT( 1, VM_M_keynumtostring );
str = PRVM_G_STRING( OFS_PARM0 );
*/
#define NUMKEYS 5 // TODO: merge the constant in keys.c with this one somewhen
-void M_FindKeysForCommand(char *command, int *keys);
+void M_FindKeysForCommand(const char *command, int *keys);
void VM_M_findkeysforcommand(void)
{
- char *cmd, *ret;
+ const char *cmd;
+ char *ret;
int keys[NUMKEYS];
int i;
for(i = 0; i < NUMKEYS; i++)
ret = strcat(ret, va(" \'%i\'", keys[i]));
- PRVM_G_INT(OFS_RETURN) = PRVM_SetString(ret);
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(ret);
}
/*
*/
void VM_M_setserverlistmaskstring( void )
{
- char *str;
+ const char *str;
int masknr;
serverlist_mask_t *mask;
int field;
cache = serverlist_viewlist[hostnr];
switch( (int) PRVM_G_FLOAT(OFS_PARM0) ) {
case SLIF_CNAME:
- PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( cache->info.cname );
+ PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( cache->info.cname );
break;
case SLIF_NAME:
- PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( cache->info.name );
+ PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( cache->info.name );
break;
case SLIF_GAME:
- PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( cache->info.game );
+ PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( cache->info.game );
break;
case SLIF_MOD:
- PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( cache->info.mod );
+ PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( cache->info.mod );
break;
case SLIF_MAP:
- PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( cache->info.map );
+ PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( cache->info.map );
break;
// TODO remove this again
case 1024:
- PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( cache->line1 );
+ PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( cache->line1 );
break;
case 1025:
- PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( cache->line2 );
+ PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( cache->line2 );
break;
default:
Con_Print("VM_M_getserverliststring: bad field number passed!\n");
*/
void VM_M_getserverlistindexforkey( void )
{
- char *key;
+ const char *key;
VM_SAFEPARMCOUNT( 1, VM_M_getserverlistindexforkey );
key = PRVM_G_STRING( OFS_PARM0 );
{
static char line[4096];
int i;
- char *s;
+ const char *s;
ddef_t *def;
mfunction_t *f;
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");
{
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->progs_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:
void PRVM_ResetProg()
{
- /*mempool_t *t1;
-
- t1 = prog->progs_mempool;
-
- Mem_EmptyPool(prog->progs_mempool);*/
Mem_FreePool(&prog->progs_mempool);
-
memset(prog,0,sizeof(prvm_prog_t));
-
- /*prog->time = &prog->_time;
-
- prog->progs_mempool = t1;*/
-
PRVM_GCALL(reset_cmd)();
}
//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
{
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;
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(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(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;
+}
+
// LordHavoc: precaches are now MAX_QPATH rather than a pointer
// updated by SV_SoundIndex
char sound_precache[MAX_SOUNDS][MAX_QPATH];
- char *lightstyles[MAX_LIGHTSTYLES];
+ char lightstyles[MAX_LIGHTSTYLES][64];
int num_edicts;
int max_edicts;
// small edict_t structures which just contain pointers
void SV_StartParticle (vec3_t org, vec3_t dir, int color, int count);
void SV_StartEffect (vec3_t org, int modelindex, int startframe, int framecount, int framerate);
-void SV_StartSound (edict_t *entity, int channel, char *sample, int volume, float attenuation);
+void SV_StartSound (edict_t *entity, int channel, const char *sample, int volume, float attenuation);
void SV_ConnectClient (int clientnum, netconn_t *netconnection);
void SV_DropClient (qboolean crash);
// 0 = fail if not precached,
// 1 = warn if not found and precache if possible
// 2 = precache
-int SV_ModelIndex(char *s, int precachemode);
-int SV_SoundIndex(char *s, int precachemode);
+int SV_ModelIndex(const char *s, int precachemode);
+int SV_SoundIndex(const char *s, int precachemode);
void SV_SetIdealPitch (void);
==================
*/
-void SV_StartSound (edict_t *entity, int channel, char *sample, int volume, float attenuation)
+void SV_StartSound (edict_t *entity, int channel, const char *sample, int volume, float attenuation)
{
int sound_num, field_mask, i, ent;
int i, j;
client_t *client;
eval_t *val;
- char *name;
- char *model;
- char *skin;
+ const char *name;
+ const char *model;
+ const char *skin;
// check for changes to be sent over the reliable streams
for (i = 0, host_client = svs.clients;i < svs.maxclients;i++, host_client++)
name = "";
// always point the string back at host_client->name to keep it safe
strlcpy (host_client->name, name, sizeof (host_client->name));
- host_client->edict->v->netname = PR_SetString(host_client->name);
+ host_client->edict->v->netname = PR_SetEngineString(host_client->name);
if (strcmp(host_client->old_name, host_client->name))
{
if (host_client->spawned)
model = "";
// always point the string back at host_client->name to keep it safe
strlcpy (host_client->playermodel, model, sizeof (host_client->playermodel));
- GETEDICTFIELDVALUE(host_client->edict, eval_playermodel)->string = PR_SetString(host_client->playermodel);
+ GETEDICTFIELDVALUE(host_client->edict, eval_playermodel)->string = PR_SetEngineString(host_client->playermodel);
}
// NEXUIZ_PLAYERSKIN
skin = "";
// always point the string back at host_client->name to keep it safe
strlcpy (host_client->playerskin, skin, sizeof (host_client->playerskin));
- GETEDICTFIELDVALUE(host_client->edict, eval_playerskin)->string = PR_SetString(host_client->playerskin);
+ GETEDICTFIELDVALUE(host_client->edict, eval_playerskin)->string = PR_SetEngineString(host_client->playerskin);
}
// frags
================
*/
-int SV_ModelIndex(char *s, int precachemode)
+int SV_ModelIndex(const char *s, int precachemode)
{
int i, limit = (sv.protocol == PROTOCOL_QUAKE ? 256 : MAX_MODELS);
char filename[MAX_QPATH];
================
*/
-int SV_SoundIndex(char *s, int precachemode)
+int SV_SoundIndex(const char *s, int precachemode)
{
int i, limit = (sv.protocol == PROTOCOL_QUAKE ? 256 : MAX_SOUNDS);
char filename[MAX_QPATH];
ent = EDICT_NUM(0);
memset (ent->v, 0, progs->entityfields * 4);
ent->e->free = false;
- ent->v->model = PR_SetString(sv.modelname);
+ ent->v->model = PR_SetEngineString(sv.modelname);
ent->v->modelindex = 1; // world model
ent->v->solid = SOLID_BSP;
ent->v->movetype = MOVETYPE_PUSH;
else
pr_global_struct->deathmatch = deathmatch.integer;
- pr_global_struct->mapname = PR_SetString(sv.name);
+ pr_global_struct->mapname = PR_SetEngineString(sv.name);
// serverflags are for cross level information (sigils)
pr_global_struct->serverflags = svs.serverflags;
Cmd_ExecuteString (s, src_client);
else if (SV_ParseClientCommandQC)
{
- G_INT(OFS_PARM0) = PR_SetString(s);
+ G_INT(OFS_PARM0) = PR_SetEngineString(s);
pr_global_struct->self = EDICT_TO_PROG(host_client->edict);
PR_ExecuteProgram ((func_t)(SV_ParseClientCommandQC - pr_functions), "QC function SV_ParseClientCommand is missing");
}
Can safely be performed in place.
==================
*/
-static void W_CleanupName (char *in, char *out)
+static void W_CleanupName (const char *in, char *out)
{
int i;
int c;
out[i] = 0;
}
-void *W_GetLumpName(char *name)
+void *W_GetLumpName(const char *name)
{
int i;
lumpinfo_t *lump;
extern lumpinfo_t *wad_lumps;
extern qbyte *wad_base;
-void *W_GetLumpName (char *name);
+void *W_GetLumpName (const char *name);
// LordHavoc: added alternate texture WAD2/WAD3 system for easier loading of HalfLife texture wads