It also has a special feature: it manages to bust many engines gamedir change (FitzQuake 0.85, Quakespasm, JoeQuake, Mark V, Qrack no doubt).
Here is how to create the problem: Start engine like normal (game = id1). Load E1M1, which will precache nail boxes and such.
Type "game zendar; map zendar" or "gamedir zendar; map zendar" in the console.
If you are lucky, the engine being used detects something afoul and you'll get a warning message or error. Other engines, it just crashes. It looks like old cache data for nail boxes, shellboxes and such is being used when the new ones are entirely different and this causes some invalid values in lightmap sizing to be used.
This is the code that Quake normal uses to clear mod data, and works without gamedir changes pretty reliably.
Code: Select all
/*
================
Host_ClearMemory
This clears all the memory used by both the client and server, but does
not reinitialize anything.
================
*/
void Host_ClearMemory (void)
{
Con_DPrintf ("Clearing memory\n");
Mod_ClearAll (); // <------------------------------------ Clear the models
Hunk_FreeToLowMark (host_hunklevel);
cls.signon = 0;
memset (&sv, 0, sizeof(sv));
memset (&cl, 0, sizeof(cl));
}
Code: Select all
/*
===================
Mod_ClearAll
===================
*/
void Mod_ClearAll (void)
{
int i;
qmodel_t *mod;
for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++)
if (mod->type != mod_alias)
{
mod->needload = true;
TexMgr_FreeTexturesForOwner (mod); //johnfitz // <----- Baker: FitzQuake-derived engines have this
}
}
I made a function that handles this thoroughly that can be used for a gamedir change:
Code: Select all
/*
===================
Mod_ClearAll_Compact
===================
*/
void Mod_ClearAll_Compact (void)
{
size_t bufsize = sizeof(qmodel_t) * MAX_MOD_KNOWN;
qmodel_t* new_mod_known = calloc (sizeof(qmodel_t), MAX_MOD_KNOWN );
int i, newcount = 0;
qmodel_t *mod;
for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++)
{
if (mod->type != mod_alias)
{
mod->needload = true;
TexMgr_FreeTexturesForOwner (mod); //johnfitz
}
else
{
qmodel_t *old_mod = &mod_known[i];
qmodel_t *new_mod = &new_mod_known[newcount];
// Transfer it
memcpy (new_mod, old_mod, sizeof(qmodel_t));
newcount ++;
}
}
memset (mod_known, 0, sizeof(mod_known));
memcpy (mod_known, new_mod_known, sizeof(mod_known));
mod_numknown = newcount;
free (new_mod_known);
}
Code: Select all
//clear out and reload appropriate data
Cache_Flush ();
Mod_ClearAll_Compact (); // <------------ Baker, formerly just a Mod_ClearAll