From e8f97ce8e8e39076b2a5a2b615a816a7d8005a02 Mon Sep 17 00:00:00 2001 From: Nico de Poel Date: Tue, 6 Apr 2021 23:29:43 +0200 Subject: [PATCH] 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 --- engine/code/host_cmd.c | 10 +-- engine/code/pr_cmds.c | 16 ++--- engine/code/pr_edict.c | 149 +++++++++++++++++++++++++++++++++++------ engine/code/pr_exec.c | 16 ++--- engine/code/progs.h | 11 +-- engine/code/sv_main.c | 18 ++--- engine/code/sv_phys.c | 4 +- engine/code/zone.c | 40 ++++++++++- engine/code/zone.h | 1 + 9 files changed, 205 insertions(+), 60 deletions(-) diff --git a/engine/code/host_cmd.c b/engine/code/host_cmd.c index 485321b..d1e55fa 100644 --- a/engine/code/host_cmd.c +++ b/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 ; iv.classname, "viewthing") ) + if ( !strcmp (PR_GetString(e->v.classname), "viewthing") ) return e; } Con_Printf ("No viewthing on map\n"); diff --git a/engine/code/pr_cmds.c b/engine/code/pr_cmds.c index 79fd011..71d9ce0 100644 --- a/engine/code/pr_cmds.c +++ b/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); diff --git a/engine/code/pr_edict.c b/engine/code/pr_edict.c index 2a5292a..c27d403 100644 --- a/engine/code/pr_edict.c +++ b/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 ; inumfielddefs ; 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 ; inumglobaldefs ; 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 ; inumfunctions ; 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 ; inumfielddefs ; 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 ; inumfielddefs ; 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 ; inumstatements ; 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; +} \ No newline at end of file diff --git a/engine/code/pr_exec.c b/engine/code/pr_exec.c index 62b9480..6e3ada8 100644 --- a/engine/code/pr_exec.c +++ b/engine/code/pr_exec.c @@ -213,7 +213,7 @@ void PR_StackTrace (void) Con_Printf ("\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; diff --git a/engine/code/progs.h b/engine/code/progs.h index 6d3aa8a..16693e1 100644 --- a/engine/code/progs.h +++ b/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]; diff --git a/engine/code/sv_main.c b/engine/code/sv_main.c index 6fcd4ed..ea2599a 100644 --- a/engine/code/sv_main.c +++ b/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 ; inumsubmodels ; 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 diff --git a/engine/code/sv_phys.c b/engine/code/sv_phys.c index 647276d..8f163fa 100644 --- a/engine/code/sv_phys.c +++ b/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; } diff --git a/engine/code/zone.c b/engine/code/zone.c index e30d7f8..61b45f9 100644 --- a/engine/code/zone.c +++ b/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; +} /* ======================== diff --git a/engine/code/zone.h b/engine/code/zone.h index 7655ad9..0c4dffd 100644 --- a/engine/code/zone.h +++ b/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);