- optimizations for better savegame performance.

This commit is contained in:
Christoph Oelckers 2020-07-21 21:32:38 +02:00
parent 1869a7930e
commit 6227f9f7fd
17 changed files with 79 additions and 80 deletions

View file

@ -614,7 +614,7 @@ bool GameInterface::SaveGame(FSaveGameNode* node)
}
LoadSave::hSFile = NULL;
return FinishSavegameWrite();
return 1;
}
class MyLoadSave : public LoadSave

View file

@ -75,7 +75,7 @@ void FSavegameManager::SaveGame(FSaveGameNode* node, bool ok4q, bool forceq)
{
if (OpenSaveGameForWrite(node->Filename, node->SaveTitle))
{
if (gi->SaveGame(node))
if (gi->SaveGame(node) && FinishSavegameWrite())
{
FString fn = node->Filename;
FString desc = node->SaveTitle;

View file

@ -17,45 +17,28 @@ class FSerializer;
class Quotes
{
FString quotes[MAXQUOTES];
FString exquotes[MAXQUOTES];
void MakeStringLabel(FString &quote);
public:
void InitializeQuote(int num, const char *text, bool fromscript = false);
void InitializeExQuote(int num, const char *text, bool fromscript = false);
const char *GetQuote(int num)
{
return GStrings.localize(quotes[num]);
}
const char *GetExQuote(int num)
{
return GStrings.localize(exquotes[num]);
}
const char *GetRawQuote(int num)
{
return quotes[num];
}
const char *GetRawExQuote(int num)
{
return exquotes[num];
}
void CopyQuote(int dst, int src)
{
quotes[dst] = quotes[src];
}
void CopyExQuote(int dst, int src)
{
quotes[dst] = exquotes[src];
}
void AppendQuote(int dst, int src, int len = -1);
void FormatQuote(int dst, const char* fmt, ...);
void Substitute(int num, const char* text, const char* replc);

View file

@ -56,15 +56,6 @@ void Quotes::InitializeQuote(int num, const char *text, bool fromscript)
}
}
void Quotes::InitializeExQuote(int num, const char *text, bool fromscript)
{
exquotes[num] = text;
if (fromscript) // means this is the initial setup from the source data.
{
MakeStringLabel(quotes[num]);
}
}
void Quotes::AppendQuote(int dst, int src, int len)
{
// This needs to apply the localization because the combined string is not localizable anymore.
@ -89,6 +80,7 @@ void Quotes::Substitute(int dst, const char* text, const char* replc)
void Quotes::Serialize(FSerializer &arc)
{
#if 0 // not needed without EDuke's extensions.
// This only saves the regular quotes. The ExQuotes array is immutable once initialized.
if (arc.BeginObject("quotes"))
{
@ -101,6 +93,7 @@ void Quotes::Serialize(FSerializer &arc)
}
arc.EndObject();
}
#endif
}
Quotes quoteMgr;

View file

@ -162,7 +162,7 @@ void FinishSavegameRead()
savereader = nullptr;
}
CVAR(Bool, save_formatted, true, 0) // should be set to false once the conversion is done
CVAR(Bool, save_formatted, false, 0) // should be set to false once the conversion is done
//=============================================================================
//

View file

@ -42,7 +42,6 @@ bool GameInterface::SaveGame(FSaveGameNode* sv)
{
for (auto sgh : sghelpers) sgh->Save();
SaveTextureState();
FinishSavegameWrite();
return 1; // CHECKME
}

View file

@ -4432,17 +4432,17 @@ static int fallspecial(int g_i, int g_p)
addspritetodelete(g_i);
return 0;
}
if (g_sp->picnum != APLAYER && (badguy(g_sp) || g_sp->picnum == HEN || g_sp->picnum == COW || g_sp->picnum == PIG || g_sp->picnum == DOGRUN || g_sp->picnum == RABBIT) && (!isRRRA() || spriteextra[g_i] < 128))
if (g_sp->picnum != APLAYER && (badguy(g_sp) || g_sp->picnum == HEN || g_sp->picnum == COW || g_sp->picnum == PIG || g_sp->picnum == DOGRUN || g_sp->picnum == RABBIT) && (!isRRRA() || hittype[g_i].spriteextra < 128))
{
g_sp->z = hittype[g_i].floorz - FOURSLEIGHT;
g_sp->zvel = 8000;
g_sp->extra = 0;
spriteextra[g_i]++;
hittype[g_i].spriteextra++;
sphit = 1;
}
else if (g_sp->picnum != APLAYER)
{
if (!spriteextra[g_i])
if (!hittype[g_i].spriteextra)
addspritetodelete(g_i);
return 0;
}

View file

@ -567,10 +567,10 @@ int ParseState::parse(void)
break;
case concmd_iftipcow:
case concmd_ifhittruck: // both have the same code.
if (spriteextra[g_i] == 1) // TRANSITIONAL 'filler' no longer exists
if (hittype[g_i].spriteextra == 1) //
{
j = 1;
spriteextra[g_i]++;
hittype[g_i].spriteextra++;
}
else
j = 0;
@ -631,7 +631,7 @@ int ParseState::parse(void)
insptr++;
if (isRR())
{
if (spriteextra[g_i] < 1 || spriteextra[g_i] == 128)
if (hittype[g_i].spriteextra < 1 || hittype[g_i].spriteextra == 128)
{
if (actorfella(g_i))
ps[g_p].actors_killed += *insptr;

View file

@ -75,7 +75,7 @@ ClockTicks ototalclock;
// Variables that must be saved
uint8_t spriteextra[MAXSPRITES], sectorextra[MAXSECTORS]; // move these back into the base structs!
uint8_t sectorextra[MAXSECTORS]; // move these back into the base structs!
int rtsplaying;
int tempwallptr;

View file

@ -60,7 +60,7 @@ extern int screenpeek;
extern ClockTicks ototalclock;
// Variables that must be saved
extern uint8_t spriteextra[MAXSPRITES], sectorextra[MAXSECTORS]; // these hold fields that were formerly in sprite and sector. Move these back into the base structs!
extern uint8_t sectorextra[MAXSECTORS]; // these hold fields that were formerly in sprite and sector. Move these back into the base structs!
extern int rtsplaying;
extern int tempwallptr;

View file

@ -588,13 +588,11 @@ void playerisdead(int snum, int psectlotag, int fz, int cz)
auto pname = &ud.user_name[p->frag_ps][0];
if (snum == screenpeek)
{
quoteMgr.InitializeQuote(QUOTE_RESERVED, "Killed by %s", pname);
FTA(QUOTE_RESERVED, p);
Printf(PRINT_NOTIFY, "Killed by %s", pname);
}
else
{
quoteMgr.InitializeQuote(QUOTE_RESERVED2, "Killed %s", pname);
FTA(QUOTE_RESERVED2, p);
Printf(PRINT_NOTIFY, "Killed %s", pname);
}
}

View file

@ -697,7 +697,7 @@ void prelevel_common(int g)
resetprestat(0, g);
numclouds = 0;
memset(spriteextra, 0, sizeof(spriteextra));
memset(hittype, 0, sizeof(hittype));
memset(sectorextra, 0, sizeof(sectorextra));
memset(shadedsector, 0, sizeof(shadedsector));
memset(geosectorwarp, -1, sizeof(geosectorwarp));

View file

@ -75,7 +75,6 @@ static void recreateinterpolations()
}
FSerializer& Serialize(FSerializer& arc, const char* keyname, animwalltype& w, animwalltype* def)
{
if (arc.BeginObject(keyname))
@ -303,25 +302,26 @@ FSerializer& Serialize(FSerializer& arc, const char* keyname, weaponhit& w, weap
{
if (arc.BeginObject(keyname))
{
arc("cgg", w.cgg)
("picnum", w.picnum)
("ang", w.ang)
("extra", w.extra)
("owner", w.owner)
("movflag", w.movflag)
("tempang", w.tempang)
("actorstayput", w.actorstayput)
("dispicnum", w.dispicnum)
("timetosleep", w.timetosleep)
("floorz", w.floorz)
("ceilingz", w.ceilingz)
("lastvx", w.lastvx)
("lastvy", w.lastvy)
("bposx", w.bposx)
("bposy", w.bposy)
("bposz", w.bposz)
("aflags", w.aflags)
.Array("temp_data", w.temp_data, 6)
arc("cgg", w.cgg, def->cgg)
("spriteextra", w.spriteextra, def->spriteextra)
("picnum", w.picnum, def->picnum)
("ang", w.ang, def->ang)
("extra", w.extra, def->extra)
("owner", w.owner, def->owner)
("movflag", w.movflag, def->movflag)
("tempang", w.tempang, def->tempang)
("actorstayput", w.actorstayput, def->actorstayput)
("dispicnum", w.dispicnum, def->dispicnum)
("timetosleep", w.timetosleep, def->timetosleep)
("floorz", w.floorz, def->floorz)
("ceilingz", w.ceilingz, def->ceilingz)
("lastvx", w.lastvx, def->lastvx)
("lastvy", w.lastvy, def->lastvy)
("bposx", w.bposx, def->bposx)
("bposy", w.bposy, def->bposy)
("bposz", w.bposz, def->bposz)
("aflags", w.aflags, def->aflags)
.Array("temp_data", w.temp_data, def->temp_data, 6)
.EndObject();
}
return arc;
@ -332,8 +332,8 @@ void GameInterface::SerializeGameState(FSerializer& arc)
{
if (arc.isReading())
{
memset(hittype, 0, sizeof(hittype));
memset(sectorextra, 0, sizeof(sectorextra));
memset(spriteextra, 0, sizeof(spriteextra));
memset(shadedsector, 0, sizeof(shadedsector));
memset(geosectorwarp, -1, sizeof(geosectorwarp));
memset(geosectorwarp2, -1, sizeof(geosectorwarp2));
@ -344,6 +344,41 @@ void GameInterface::SerializeGameState(FSerializer& arc)
{
arc("multimode", ud.multimode);
if (ud.multimode > 1) arc.Array("frags", &frags[0][0], MAXPLAYERS * MAXPLAYERS);
// Here we must only save the used entries, otherwise the savegame would get too large.
weaponhit def = {};
if (arc.isWriting())
{
if (arc.BeginArray("weaponhit"))
{
// Save this in a way that's easy to read out again. RapidJSON sucks at iterating over objects. :(
for (int i = 0; i < MAXSPRITES; i++)
{
if (sprite[i].statnum != MAXSTATUS)
{
arc(nullptr, i);
arc(nullptr, hittype[i], def);
}
}
}
arc.EndArray();
}
else
{
if (arc.BeginArray("weaponhit"))
{
auto s = arc.ArraySize()/2;
for (unsigned i = 0; i < s; i++)
{
int ii;
arc(nullptr, ii);
arc(nullptr, hittype[ii], def);
}
arc.EndArray();
}
}
arc("skill", ud.player_skill)
("from_bonus", ud.from_bonus)
@ -360,8 +395,6 @@ void GameInterface::SerializeGameState(FSerializer& arc)
("marker", ud.marker)
("ffire", ud.ffire)
.Array("spriteextra", spriteextra, MAXSPRITES)
.Array("weaponhit", hittype, MAXSPRITES)
.Array("sectorextra", sectorextra, numsectors)
("rtsplaying", rtsplaying)
("tempwallptr", tempwallptr)

View file

@ -1081,8 +1081,8 @@ void checkhitwall_r(int spr, int dawallnum, int x, int y, int z, int atwith)
if (s->lotag == 6)
{
for (j = 0; j < 16; j++) RANDOMSCRAP(s, -1);
spriteextra[jj]++; // TRANSITIONAL move to sprite or actor
if (spriteextra[jj] == 25)
hittype[jj].spriteextra++;
if (hittype[jj].spriteextra == 25)
{
startwall = sector[s->sectnum].wallptr;
endwall = startwall + sector[s->sectnum].wallnum;
@ -2576,7 +2576,7 @@ void checksectors_r(int snum)
case TOUGHGAL:
return;
case COW:
spriteextra[neartagsprite] = 1; // TRANSITIONAL move to sprite or actor
hittype[neartagsprite].spriteextra = 1;
return;
}
}
@ -2739,7 +2739,7 @@ void checksectors_r(int snum)
operatesectors(neartagsector, p->i);
else
{
if (spriteextra[neartagsprite] > 3) // TRANSITIONAL move to sprite or actor
if (hittype[neartagsprite].spriteextra > 3)
spritesound(99, p->i);
else
spritesound(419, p->i);
@ -2760,7 +2760,7 @@ void checksectors_r(int snum)
operatesectors(sprite[p->i].sectnum, p->i);
else
{
if (spriteextra[neartagsprite] > 3) // TRANSITIONAL move to sprite or actor
if (hittype[neartagsprite].spriteextra > 3)
spritesound(99, p->i);
else
spritesound(419, p->i);

View file

@ -19,6 +19,7 @@ struct STATUSBARTYPE
struct weaponhit
{
uint8_t cgg;
uint8_t spriteextra; // moved here for easier maintenance. This was originally a hacked in field in the sprite structure called 'filler'.
short picnum, ang, extra, owner, movflag;
short tempang, actorstayput, dispicnum;
short timetosleep;

View file

@ -43,11 +43,6 @@ inline size_t MWRITE(void* buf, size_t size, size_t nelem, FileWriter* handle)
return handle->Write(buf, size * nelem) / size;
}
inline void MCLOSE_WRITE(FileWriter* handle)
{
FinishSavegameWrite();
}
inline void MCLOSE_READ(FileReader* handle)
{
handle->Close();

View file

@ -670,10 +670,7 @@ bool GameInterface::SaveGame(FSaveGameNode *sv)
MWRITE(BossSpriteNum, sizeof(BossSpriteNum), 1, fil);
//MWRITE(&Zombies, sizeof(Zombies), 1, fil);
if (!saveisshot)
return FinishSavegameWrite();
return false;
return !saveisshot;
}