diff --git a/quakespasm/Quake/pr_edict.c b/quakespasm/Quake/pr_edict.c index d5d8b2d7..32ea36d6 100644 --- a/quakespasm/Quake/pr_edict.c +++ b/quakespasm/Quake/pr_edict.c @@ -35,7 +35,6 @@ int type_size[8] = { }; static ddef_t *ED_FieldAtOfs (int ofs); -qboolean ED_ParseEpair (void *base, ddef_t *key, const char *s); cvar_t nomonsters = {"nomonsters", "0", CVAR_NONE}; cvar_t gamecfg = {"gamecfg", "0", CVAR_NONE}; @@ -575,7 +574,7 @@ static void ED_PrintEdict_f (void) else if (Cmd_Argc() < 4) Con_Printf("Edict %u.%s==%s\n", i, PR_GetString(def->s_name), PR_UglyValueString(def->type&~DEF_SAVEGLOBAL, (eval_t *)((char *)&EDICT_NUM(i)->v + def->ofs*4))); else - ED_ParseEpair((void *)&EDICT_NUM(i)->v, def, Cmd_Argv(3)); + ED_ParseEpair((void *)&EDICT_NUM(i)->v, def, Cmd_Argv(3), false); } } @@ -698,7 +697,7 @@ const char *ED_ParseGlobals (const char *data) continue; } - if (!ED_ParseEpair ((void *)qcvm->globals, key, com_token)) + if (!ED_ParseEpair ((void *)qcvm->globals, key, com_token, false)) Host_Error ("ED_ParseGlobals: parse error"); } return data; @@ -737,7 +736,37 @@ static string_t ED_NewString (const char *string) return num; } +static void ED_RezoneString (string_t *ref, const char *str) +{ + char *buf; + size_t len = strlen(str)+1; + size_t id; + if (*ref) + { //if the reference is already a zoned string then free it first. + id = -1-*ref; + if (id < qcvm->knownzonesize && (qcvm->knownzone[id>>3] & (1u<<(id&7)))) + { //okay, it was zoned. + qcvm->knownzone[id>>3] &= ~(1u<<(id&7)); + buf = (char*)PR_GetString(*ref); + PR_ClearEngineString(*ref); + Z_Free(buf); + } +// else +// Con_Warning("ED_RezoneString: string wasn't strzoned\n"); //warnings would trigger from the default cvar value that autocvars are initialised with + } + + buf = Z_Malloc(len); + memcpy(buf, str, len); + id = -1-(*ref = PR_SetEngineString(buf)); + //make sure its flagged as zoned so we can clean up properly after. + if (id >= qcvm->knownzonesize) + { + qcvm->knownzonesize = (id+32)&~7; + qcvm->knownzone = Z_Realloc(qcvm->knownzone, (qcvm->knownzonesize+7)>>3); + } + qcvm->knownzone[id>>3] |= 1u<<(id&7); +} /* ============= @@ -747,7 +776,7 @@ Can parse either fields or globals returns false if error ============= */ -qboolean ED_ParseEpair (void *base, ddef_t *key, const char *s) +qboolean ED_ParseEpair (void *base, ddef_t *key, const char *s, qboolean zoned) { int i; char string[128]; @@ -762,7 +791,10 @@ qboolean ED_ParseEpair (void *base, ddef_t *key, const char *s) switch (key->type & ~DEF_SAVEGLOBAL) { case ev_string: - *(string_t *)d = ED_NewString(s); + if (zoned) //zoned version allows us to change the strings more freely + ED_RezoneString((string_t *)d, s); + else + *(string_t *)d = ED_NewString(s); break; case ev_float: @@ -960,7 +992,7 @@ const char *ED_ParseEdict (const char *data, edict_t *ent) sprintf (com_token, "0 %s 0", temp); } - if (!ED_ParseEpair ((void *)&ent->v, key, com_token)) + if (!ED_ParseEpair ((void *)&ent->v, key, com_token, false)) Host_Error ("ED_ParseEdict: parse error"); } diff --git a/quakespasm/Quake/pr_ext.c b/quakespasm/Quake/pr_ext.c index fe036fa9..41581ae6 100644 --- a/quakespasm/Quake/pr_ext.c +++ b/quakespasm/Quake/pr_ext.c @@ -492,7 +492,7 @@ static void PF_strzone(void) if (id >= qcvm->knownzonesize) { qcvm->knownzonesize = (id+32)&~7; - qcvm->knownzone = Z_Realloc(qcvm->knownzone, qcvm->knownzonesize>>3); + qcvm->knownzone = Z_Realloc(qcvm->knownzone, (qcvm->knownzonesize+7)>>3); } qcvm->knownzone[id>>3] |= 1u<<(id&7); @@ -3809,7 +3809,7 @@ static void PF_putentfldstr(void) edict_t *ent = G_EDICT(OFS_PARM1); const char *value = G_STRING(OFS_PARM2); if (fldidx < (unsigned int)qcvm->progs->numfielddefs) - G_FLOAT(OFS_RETURN) = ED_ParseEpair ((void *)&ent->v, qcvm->fielddefs+fldidx, value); + G_FLOAT(OFS_RETURN) = ED_ParseEpair ((void *)&ent->v, qcvm->fielddefs+fldidx, value, true); else G_FLOAT(OFS_RETURN) = false; } @@ -6645,33 +6645,31 @@ void PR_AutoCvarChanged(cvar_t *var) glob = ED_FindGlobal(n); if (glob) { - if (!ED_ParseEpair ((void *)qcvm->globals, glob, var->string)) + if (!ED_ParseEpair ((void *)qcvm->globals, glob, var->string, true)) Con_Warning("EXT: Unable to configure %s\n", n); } PR_SwitchQCVM(NULL); } if (cl.qcvm.globals) { - PR_SwitchQCVM(NULL); PR_SwitchQCVM(&cl.qcvm); n = va("autocvar_%s", var->name); glob = ED_FindGlobal(n); if (glob) { - if (!ED_ParseEpair ((void *)qcvm->globals, glob, var->string)) + if (!ED_ParseEpair ((void *)qcvm->globals, glob, var->string, true)) Con_Warning("EXT: Unable to configure %s\n", n); } PR_SwitchQCVM(NULL); } if (cls.menu_qcvm.globals) { - PR_SwitchQCVM(NULL); PR_SwitchQCVM(&cls.menu_qcvm); n = va("autocvar_%s", var->name); glob = ED_FindGlobal(n); if (glob) { - if (!ED_ParseEpair ((void *)qcvm->globals, glob, var->string)) + if (!ED_ParseEpair ((void *)qcvm->globals, glob, var->string, true)) Con_Warning("EXT: Unable to configure %s\n", n); } PR_SwitchQCVM(NULL); @@ -6806,7 +6804,7 @@ void PR_EnableExtensions(ddef_t *pr_globaldefs) if (!var) continue; //name conflicts with a command? - if (!ED_ParseEpair ((void *)qcvm->globals, &pr_globaldefs[i], var->string)) + if (!ED_ParseEpair ((void *)qcvm->globals, &pr_globaldefs[i], var->string, true)) Con_Warning("EXT: Unable to configure %s\n", n); var->flags |= CVAR_AUTOCVAR; } diff --git a/quakespasm/Quake/progs.h b/quakespasm/Quake/progs.h index d7f18d5a..d3a3fdad 100644 --- a/quakespasm/Quake/progs.h +++ b/quakespasm/Quake/progs.h @@ -84,7 +84,7 @@ int SV_Precache_Sound(const char *s); void PR_spawnfunc_misc_model(edict_t *self); //from pr_edict, for pr_ext. reflection is messy. -qboolean ED_ParseEpair (void *base, ddef_t *key, const char *s); +qboolean ED_ParseEpair (void *base, ddef_t *key, const char *s, qboolean zoned); const char *PR_UglyValueString (int type, eval_t *val); ddef_t *ED_FindField (const char *name); ddef_t *ED_FindGlobal (const char *name); diff --git a/quakespasm/Quake/zone.c b/quakespasm/Quake/zone.c index 9ab8cfe2..d6e02e29 100644 --- a/quakespasm/Quake/zone.c +++ b/quakespasm/Quake/zone.c @@ -76,7 +76,8 @@ void Z_Free (void *ptr) memblock_t *block, *other; if (!ptr) - Sys_Error ("Z_Free: NULL pointer"); + return; //ignore this like libc would +// Sys_Error ("Z_Free: NULL pointer"); block = (memblock_t *) ( (byte *)ptr - sizeof(memblock_t)); if (block->id != ZONEID)