Browse Source

Transplanted improved QuakeC string handling over from QuakeSpasm, as well as a few other improvements to the script interpreter (including a massive bump to the Zone memory size). This now allows the entire game to run properly in 64-bit mode! :D

console
Nico de Poel 5 years ago
parent
commit
e8f97ce8e8
  1. 10
      engine/code/host_cmd.c
  2. 16
      engine/code/pr_cmds.c
  3. 149
      engine/code/pr_edict.c
  4. 16
      engine/code/pr_exec.c
  5. 11
      engine/code/progs.h
  6. 18
      engine/code/sv_main.c
  7. 4
      engine/code/sv_phys.c
  8. 40
      engine/code/zone.c
  9. 1
      engine/code/zone.h

10
engine/code/host_cmd.c

@ -946,7 +946,7 @@ void Host_Name_f (void)
if (Q_strcmp(host_client->name, newName) != 0)
Con_Printf ("%s renamed to %s\n", host_client->name, newName);
Q_strcpy (host_client->name, newName);
host_client->edict->v.netname = host_client->name - pr_strings;
host_client->edict->v.netname = PR_SetEngineString(host_client->name);
// send notification to all clients
@ -1240,11 +1240,11 @@ void Host_Pause_f (void)
if (sv.paused)
{
SV_BroadcastPrintf ("%s paused the game\n", pr_strings + sv_player->v.netname);
SV_BroadcastPrintf ("%s paused the game\n", PR_GetString(sv_player->v.netname));
}
else
{
SV_BroadcastPrintf ("%s unpaused the game\n",pr_strings + sv_player->v.netname);
SV_BroadcastPrintf ("%s unpaused the game\n", PR_GetString(sv_player->v.netname));
}
// send notification to all clients
@ -1318,7 +1318,7 @@ void Host_Spawn_f (void)
memset (&ent->v, 0, progs->entityfields * 4);
ent->v.colormap = NUM_FOR_EDICT(ent);
ent->v.team = (host_client->colors & 15) + 1;
ent->v.netname = host_client->name - pr_strings;
ent->v.netname = PR_SetEngineString(host_client->name);
// copy spawn parms out of the client_t
@ -1685,7 +1685,7 @@ edict_t *FindViewthing (void)
for (i=0 ; i<sv.num_edicts ; i++)
{
e = EDICT_NUM(i);
if ( !strcmp (pr_strings + e->v.classname, "viewthing") )
if ( !strcmp (PR_GetString(e->v.classname), "viewthing") )
return e;
}
Con_Printf ("No viewthing on map\n");

16
engine/code/pr_cmds.c

@ -60,8 +60,8 @@ void PF_error (void)
edict_t *ed;
s = PF_VarString(0);
Con_Printf ("======SERVER ERROR in %s:\n%s\n"
,pr_strings + pr_xfunction->s_name,s);
Con_Printf ("======SERVER ERROR in %s:\n%s\n",
PR_GetString(pr_xfunction->s_name), s);
ed = PROG_TO_EDICT(pr_global_struct->self);
ED_Print (ed);
@ -84,8 +84,8 @@ void PF_objerror (void)
edict_t *ed;
s = PF_VarString(0);
Con_Printf ("======OBJECT ERROR in %s:\n%s\n"
,pr_strings + pr_xfunction->s_name,s);
Con_Printf ("======OBJECT ERROR in %s:\n%s\n",
PR_GetString(pr_xfunction->s_name), s);
ed = PROG_TO_EDICT(pr_global_struct->self);
ED_Print (ed);
ED_Free (ed);
@ -250,7 +250,7 @@ void PF_setmodel (void)
PR_RunError ("no precache: %s\n", m);
e->v.model = m - pr_strings;
e->v.model = PR_SetEngineString(*check);
e->v.modelindex = i; //SV_ModelIndex (m);
mod = sv.models[ (int)e->v.modelindex]; // Mod_ForName (m, true);
@ -937,7 +937,7 @@ void PF_ftos (void)
// jkrige - FTOS fix
}
G_INT(OFS_RETURN) = pr_string_temp - pr_strings;
G_INT(OFS_RETURN) = PR_SetEngineString(pr_string_temp);
}
void PF_fabs (void)
@ -950,7 +950,7 @@ void PF_fabs (void)
void PF_vtos (void)
{
sprintf (pr_string_temp, "'%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_string_temp - pr_strings;
G_INT(OFS_RETURN) = PR_SetEngineString(pr_string_temp);
}
#ifdef QUAKE2
@ -1596,7 +1596,7 @@ void PF_makestatic (void)
MSG_WriteByte (&sv.signon,svc_spawnstatic);
MSG_WriteByte (&sv.signon, SV_ModelIndex(pr_strings + ent->v.model));
MSG_WriteByte (&sv.signon, SV_ModelIndex(PR_GetString(ent->v.model)));
MSG_WriteByte (&sv.signon, ent->v.frame);
MSG_WriteByte (&sv.signon, ent->v.colormap);

149
engine/code/pr_edict.c

@ -23,7 +23,13 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
dprograms_t *progs;
dfunction_t *pr_functions;
char *pr_strings;
static char *pr_strings;
static int pr_stringssize;
static char **pr_knownstrings;
static int pr_maxknownstrings;
static int pr_numknownstrings;
ddef_t *pr_fielddefs;
ddef_t *pr_globaldefs;
dstatement_t *pr_statements;
@ -191,7 +197,7 @@ ddef_t *ED_FindField (char *name)
for (i=0 ; i<progs->numfielddefs ; i++)
{
def = &pr_fielddefs[i];
if (!strcmp(pr_strings + def->s_name,name) )
if (!strcmp(PR_GetString(def->s_name), name) )
return def;
}
return NULL;
@ -211,7 +217,7 @@ ddef_t *ED_FindGlobal (char *name)
for (i=0 ; i<progs->numglobaldefs ; i++)
{
def = &pr_globaldefs[i];
if (!strcmp(pr_strings + def->s_name,name) )
if (!strcmp(PR_GetString(def->s_name), name) )
return def;
}
return NULL;
@ -231,7 +237,7 @@ dfunction_t *ED_FindFunction (char *name)
for (i=0 ; i<progs->numfunctions ; i++)
{
func = &pr_functions[i];
if (!strcmp(pr_strings + func->s_name,name) )
if (!strcmp(PR_GetString(func->s_name), name) )
return func;
}
return NULL;
@ -288,18 +294,18 @@ char *PR_ValueString (etype_t type, eval_t *val)
switch (type)
{
case ev_string:
sprintf (line, "%s", pr_strings + val->string);
sprintf (line, "%s", PR_GetString(val->string));
break;
case ev_entity:
sprintf (line, "entity %i", NUM_FOR_EDICT(PROG_TO_EDICT(val->edict)) );
break;
case ev_function:
f = pr_functions + val->function;
sprintf (line, "%s()", pr_strings + f->s_name);
sprintf (line, "%s()", PR_GetString(f->s_name));
break;
case ev_field:
def = ED_FieldAtOfs ( val->_int );
sprintf (line, ".%s", pr_strings + def->s_name);
sprintf (line, ".%s", PR_GetString(def->s_name));
break;
case ev_void:
sprintf (line, "void");
@ -340,18 +346,18 @@ char *PR_UglyValueString (etype_t type, eval_t *val)
switch (type)
{
case ev_string:
sprintf (line, "%s", pr_strings + val->string);
sprintf (line, "%s", PR_GetString(val->string));
break;
case ev_entity:
sprintf (line, "%i", NUM_FOR_EDICT(PROG_TO_EDICT(val->edict)));
break;
case ev_function:
f = pr_functions + val->function;
sprintf (line, "%s", pr_strings + f->s_name);
sprintf (line, "%s", PR_GetString(f->s_name));
break;
case ev_field:
def = ED_FieldAtOfs ( val->_int );
sprintf (line, "%s", pr_strings + def->s_name);
sprintf (line, "%s", PR_GetString(def->s_name));
break;
case ev_void:
sprintf (line, "void");
@ -393,7 +399,7 @@ char *PR_GlobalString (int ofs)
else
{
s = PR_ValueString (def->type, val);
sprintf (line,"%i(%s)%s", ofs, pr_strings + def->s_name, s);
sprintf (line,"%i(%s)%s", ofs, PR_GetString(def->s_name), s);
}
i = strlen(line);
@ -414,7 +420,7 @@ char *PR_GlobalStringNoContents (int ofs)
if (!def)
sprintf (line,"%i(???)", ofs);
else
sprintf (line,"%i(%s)", ofs, pr_strings + def->s_name);
sprintf (line,"%i(%s)", ofs, PR_GetString(def->s_name));
i = strlen(line);
for ( ; i<20 ; i++)
@ -451,7 +457,7 @@ void ED_Print (edict_t *ed)
for (i=1 ; i<progs->numfielddefs ; i++)
{
d = &pr_fielddefs[i];
name = pr_strings + d->s_name;
name = PR_GetString(d->s_name);
if (name[strlen(name)-2] == '_')
continue; // skip _x, _y, _z vars
@ -501,7 +507,7 @@ void ED_Write (FILE *f, edict_t *ed)
for (i=1 ; i<progs->numfielddefs ; i++)
{
d = &pr_fielddefs[i];
name = pr_strings + d->s_name;
name = PR_GetString(d->s_name);
if (name[strlen(name)-2] == '_')
continue; // skip _x, _y, _z vars
@ -634,7 +640,7 @@ void ED_WriteGlobals (FILE *f)
&& type != ev_entity)
continue;
name = pr_strings + def->s_name;
name = PR_GetString(def->s_name);
fprintf (f,"\"%s\" ", name);
fprintf (f,"\"%s\"\n", PR_UglyValueString(type, (eval_t *)&pr_globals[def->ofs]));
}
@ -690,14 +696,14 @@ void ED_ParseGlobals (char *data)
ED_NewString
=============
*/
char *ED_NewString (char *string)
string_t ED_NewString (char *string)
{
char *new, *new_p;
char *new_p;
int i,l;
string_t num;
l = strlen(string) + 1;
new = Hunk_Alloc (l);
new_p = new;
num = PR_AllocString(l, &new_p);
for (i=0 ; i< l ; i++)
{
@ -713,7 +719,7 @@ char *ED_NewString (char *string)
*new_p++ = string[i];
}
return new;
return num;
}
@ -739,7 +745,7 @@ qboolean ED_ParseEpair (void *base, ddef_t *key, char *s)
switch (key->type & ~DEF_SAVEGLOBAL)
{
case ev_string:
*(string_t *)d = ED_NewString (s) - pr_strings;
*(string_t *)d = ED_NewString (s);
break;
case ev_float:
@ -965,7 +971,7 @@ void ED_LoadFromFile (char *data)
}
// look for the spawn function
func = ED_FindFunction ( pr_strings + ent->v.classname );
func = ED_FindFunction ( PR_GetString(ent->v.classname) );
if (!func)
{
@ -1017,6 +1023,15 @@ void PR_LoadProgs (void)
pr_functions = (dfunction_t *)((byte *)progs + progs->ofs_functions);
pr_strings = (char *)progs + progs->ofs_strings;
// initialize the strings
pr_numknownstrings = 0;
pr_maxknownstrings = 0;
pr_stringssize = progs->numstrings;
if (pr_knownstrings) Z_Free((void *)pr_knownstrings);
pr_knownstrings = NULL;
PR_SetEngineString("");
pr_globaldefs = (ddef_t *)((byte *)progs + progs->ofs_globaldefs);
pr_fielddefs = (ddef_t *)((byte *)progs + progs->ofs_fielddefs);
pr_statements = (dstatement_t *)((byte *)progs + progs->ofs_statements);
@ -1025,6 +1040,11 @@ void PR_LoadProgs (void)
pr_globals = (float *)pr_global_struct;
pr_edict_size = progs->entityfields * 4 + sizeof (edict_t) - sizeof(entvars_t);
// Round off to next highest whole word address
// this ensures that pointers in the engine data area are always properly aligned
pr_edict_size += sizeof(void *) - 1;
pr_edict_size &= ~(sizeof(void *) - 1);
// byte swap the lumps
for (i=0 ; i<progs->numstatements ; i++)
@ -1110,3 +1130,88 @@ int NUM_FOR_EDICT(edict_t *e)
Sys_Error ("NUM_FOR_EDICT: bad pointer");
return b;
}
// ===============
// String handling
// ===============
#define PR_STRING_ALLOCSLOTS 256
static void PR_AllocStringSlots(void)
{
pr_maxknownstrings += PR_STRING_ALLOCSLOTS;
Con_DPrintf("PR_AllocStringSlots: realloc'ing for %d slots\n", pr_maxknownstrings);
pr_knownstrings = (char **)Z_Realloc((void *)pr_knownstrings, pr_maxknownstrings * sizeof(char *));
}
char *PR_GetString(int num)
{
if (num >= 0 && num < pr_stringssize)
return pr_strings + num;
else if (num < 0 && num >= -pr_numknownstrings)
{
if (!pr_knownstrings[-1 - num])
{
Host_Error("PR_GetString: attempt to get a non-existent string %d\n", num);
return "";
}
return pr_knownstrings[-1 - num];
}
else
{
Host_Error("PR_GetString: invalid string offset %d\n", num);
return "";
}
}
int PR_SetEngineString(char *s)
{
int i;
if (!s)
return 0;
if (s >= pr_strings && s <= pr_strings + pr_stringssize - 2)
return (int)(s - pr_strings);
for (i = 0; i < pr_numknownstrings; i++)
{
if (pr_knownstrings[i] == s)
return -1 - i;
}
if (i >= pr_maxknownstrings)
PR_AllocStringSlots();
pr_numknownstrings++;
pr_knownstrings[i] = s;
return -1 - i;
}
int PR_AllocString(int size, char **ptr)
{
int i;
if (!size)
return 0;
for (i = 0; i < pr_numknownstrings; i++)
{
if (!pr_knownstrings[i])
break;
}
if (i >= pr_maxknownstrings)
PR_AllocStringSlots();
pr_numknownstrings++;
pr_knownstrings[i] = (char *)Hunk_AllocName(size, "string");
if (ptr)
*ptr = (char *)pr_knownstrings[i];
return -1 - i;
}

16
engine/code/pr_exec.c

@ -213,7 +213,7 @@ void PR_StackTrace (void)
Con_Printf ("<NO FUNCTION>\n");
}
else
Con_Printf ("%12s : %s\n", pr_strings + f->s_file, pr_strings + f->s_name);
Con_Printf ("%12s : %s\n", PR_GetString(f->s_file), PR_GetString(f->s_name));
}
}
@ -248,7 +248,7 @@ void PR_Profile_f (void)
if (best)
{
if (num < 10)
Con_Printf ("%7i %s\n", best->profile, pr_strings+best->s_name);
Con_Printf ("%7i %s\n", best->profile, PR_GetString(best->s_name));
num++;
best->profile = 0;
}
@ -397,9 +397,9 @@ while (1)
s++; // next statement
st = &pr_statements[s];
a = (eval_t *)&pr_globals[st->a];
b = (eval_t *)&pr_globals[st->b];
c = (eval_t *)&pr_globals[st->c];
a = (eval_t *)&pr_globals[(unsigned short)st->a];
b = (eval_t *)&pr_globals[(unsigned short)st->b];
c = (eval_t *)&pr_globals[(unsigned short)st->c];
if (!--runaway)
PR_RunError ("runaway loop error");
@ -488,7 +488,7 @@ while (1)
c->_float = !a->vector[0] && !a->vector[1] && !a->vector[2];
break;
case OP_NOT_S:
c->_float = !a->string || !pr_strings[a->string];
c->_float = !a->string || !*PR_GetString(a->string);
break;
case OP_NOT_FNC:
c->_float = !a->function;
@ -506,7 +506,7 @@ while (1)
(a->vector[2] == b->vector[2]);
break;
case OP_EQ_S:
c->_float = !strcmp(pr_strings+a->string,pr_strings+b->string);
c->_float = !strcmp(PR_GetString(a->string), PR_GetString(b->string));
break;
case OP_EQ_E:
c->_float = a->_int == b->_int;
@ -525,7 +525,7 @@ while (1)
(a->vector[2] != b->vector[2]);
break;
case OP_NE_S:
c->_float = strcmp(pr_strings+a->string,pr_strings+b->string);
c->_float = strcmp(PR_GetString(a->string), PR_GetString(b->string));
break;
case OP_NE_E:
c->_float = a->_int != b->_int;

11
engine/code/progs.h

@ -52,7 +52,6 @@ typedef struct edict_s
extern dprograms_t *progs;
extern dfunction_t *pr_functions;
extern char *pr_strings;
extern ddef_t *pr_globaldefs;
extern ddef_t *pr_fielddefs;
extern dstatement_t *pr_statements;
@ -68,12 +67,16 @@ void PR_Init (void);
void PR_ExecuteProgram (func_t fnum);
void PR_LoadProgs (void);
char *PR_GetString (int num);
int PR_SetEngineString (char *s);
int PR_AllocString (int bufferlength, char **ptr);
void PR_Profile_f (void);
edict_t *ED_Alloc (void);
void ED_Free (edict_t *ed);
char *ED_NewString (char *string);
string_t ED_NewString (char *string);
// returns a copy of the string allocated from the server's string heap
void ED_Print (edict_t *ed);
@ -103,13 +106,13 @@ int NUM_FOR_EDICT(edict_t *e);
#define G_EDICT(o) ((edict_t *)((byte *)sv.edicts+ *(int *)&pr_globals[o]))
#define G_EDICTNUM(o) NUM_FOR_EDICT(G_EDICT(o))
#define G_VECTOR(o) (&pr_globals[o])
#define G_STRING(o) (pr_strings + *(string_t *)&pr_globals[o])
#define G_STRING(o) (PR_GetString(*(string_t *)&pr_globals[o]))
#define G_FUNCTION(o) (*(func_t *)&pr_globals[o])
#define E_FLOAT(e,o) (((float*)&e->v)[o])
#define E_INT(e,o) (*(int *)&((float*)&e->v)[o])
#define E_VECTOR(e,o) (&((float*)&e->v)[o])
#define E_STRING(e,o) (pr_strings + *(string_t *)&((float*)&e->v)[o])
#define E_STRING(e,o) (PR_GetString(*(string_t *)&((float*)&e->v)[o]))
extern int type_size[8];

18
engine/code/sv_main.c

@ -214,7 +214,7 @@ void SV_SendServerinfo (client_t *client)
else
MSG_WriteByte (&client->message, GAME_COOP);
sprintf (message, pr_strings+sv.edicts->v.message);
sprintf (message, PR_GetString(sv.edicts->v.message));
MSG_WriteString (&client->message,message);
@ -466,7 +466,7 @@ void SV_WriteEntitiesToClient (edict_t *clent, sizebuf_t *msg)
if (ent != clent) // clent is ALLWAYS sent
{
// ignore ents without visible models
if (!ent->v.modelindex || !pr_strings[ent->v.model])
if (!ent->v.modelindex || !PR_GetString(ent->v.model)[0])
continue;
for (i=0 ; i < ent->num_leafs ; i++)
@ -701,7 +701,7 @@ void SV_WriteClientdataToMessage (edict_t *ent, sizebuf_t *msg)
if (bits & SU_ARMOR)
MSG_WriteByte (msg, ent->v.armorvalue);
if (bits & SU_WEAPON)
MSG_WriteByte (msg, SV_ModelIndex(pr_strings+ent->v.weaponmodel));
MSG_WriteByte (msg, SV_ModelIndex(PR_GetString(ent->v.weaponmodel)));
MSG_WriteShort (msg, ent->v.health);
MSG_WriteByte (msg, ent->v.currentammo);
@ -968,7 +968,7 @@ void SV_CreateBaseline (void)
{
svent->baseline.colormap = 0;
svent->baseline.modelindex =
SV_ModelIndex(pr_strings + svent->v.model);
SV_ModelIndex(PR_GetString(svent->v.model));
}
//
@ -1062,6 +1062,7 @@ void SV_SpawnServer (char *server, char *startspot)
void SV_SpawnServer (char *server)
#endif
{
static char dummy[8] = { 0,0,0,0,0,0,0,0 };
edict_t *ent;
int i;
@ -1168,9 +1169,8 @@ void SV_SpawnServer (char *server)
//
SV_ClearWorld ();
sv.sound_precache[0] = pr_strings;
sv.model_precache[0] = pr_strings;
sv.sound_precache[0] = dummy;
sv.model_precache[0] = dummy;
sv.model_precache[1] = sv.modelname;
for (i=1 ; i<sv.worldmodel->numsubmodels ; i++)
{
@ -1184,7 +1184,7 @@ void SV_SpawnServer (char *server)
ent = EDICT_NUM(0);
memset (&ent->v, 0, progs->entityfields * 4);
ent->free = false;
ent->v.model = sv.worldmodel->name - pr_strings;
ent->v.model = PR_SetEngineString(sv.worldmodel->name);
ent->v.modelindex = 1; // world model
ent->v.solid = SOLID_BSP;
ent->v.movetype = MOVETYPE_PUSH;
@ -1194,7 +1194,7 @@ void SV_SpawnServer (char *server)
else
pr_global_struct->deathmatch = deathmatch.value;
pr_global_struct->mapname = sv.name - pr_strings;
pr_global_struct->mapname = PR_SetEngineString(sv.name);
#ifdef QUAKE2
pr_global_struct->startspot = sv.startspot - pr_strings;
#endif

4
engine/code/sv_phys.c

@ -99,13 +99,13 @@ void SV_CheckVelocity (edict_t *ent)
{
if (IS_NAN(ent->v.velocity[i]))
{
Con_Printf ("Got a NaN velocity on %s\n", pr_strings + ent->v.classname);
Con_Printf ("Got a NaN velocity on %s\n", PR_GetString(ent->v.classname));
ent->v.velocity[i] = 0;
}
if (IS_NAN(ent->v.origin[i]))
{
Con_Printf ("Got a NaN origin on %s\n", pr_strings + ent->v.classname);
Con_Printf ("Got a NaN origin on %s\n", PR_GetString(ent->v.classname));
ent->v.origin[i] = 0;
}

40
engine/code/zone.c

@ -21,7 +21,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "quakedef.h"
#define DYNAMIC_SIZE 0xc000
#define DYNAMIC_SIZE (4 * 1024 * 1024) // was 0xc000 (too small for 64-bit)
#define ZONEID 0x1d4a11
#define MINFRAGMENT 64
@ -143,7 +143,7 @@ void *Z_Malloc (int size)
{
void *buf;
Z_CheckHeap (); // DEBUG
Z_CheckHeap (); // DEBUG
buf = Z_TagMalloc (size, 1);
if (!buf)
Sys_Error ("Z_Malloc: failed on allocation of %i bytes",size);
@ -210,6 +210,42 @@ void *Z_TagMalloc (int size, int tag)
return (void *) ((byte *)base + sizeof(memblock_t));
}
/*
========================
Z_Realloc
========================
*/
void *Z_Realloc(void *ptr, int size)
{
int old_size;
void *old_ptr;
memblock_t *block;
if (!ptr)
return Z_Malloc(size);
block = (memblock_t *)((byte *)ptr - sizeof(memblock_t));
if (block->id != ZONEID)
Sys_Error("Z_Realloc: realloced a pointer without ZONEID");
if (block->tag == 0)
Sys_Error("Z_Realloc: realloced a freed pointer");
old_size = block->size;
old_size -= (4 + (int)sizeof(memblock_t)); /* see Z_TagMalloc() */
old_ptr = ptr;
Z_Free(ptr);
ptr = Z_TagMalloc(size, 1);
if (!ptr)
Sys_Error("Z_Realloc: failed on allocation of %i bytes", size);
if (ptr != old_ptr)
memmove(ptr, old_ptr, min(old_size, size));
if (old_size < size)
memset((byte *)ptr + old_size, 0, size - old_size);
return ptr;
}
/*
========================

1
engine/code/zone.h

@ -88,6 +88,7 @@ void Memory_Init (void *buf, int size);
void Z_Free (void *ptr);
void *Z_Malloc (int size); // returns 0 filled memory
void *Z_TagMalloc (int size, int tag);
void *Z_Realloc (void *ptr, int size);
void Z_DumpHeap (void);
void Z_CheckHeap (void);

Loading…
Cancel
Save