From 6227f9f7fdbad022d73d78086c155081aefc052f Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 21 Jul 2020 21:32:38 +0200 Subject: [PATCH] - optimizations for better savegame performance. --- source/blood/src/loadsave.cpp | 2 +- source/core/menu/savegamemanager.cpp | 2 +- source/core/quotemgr.h | 17 ------ source/core/quotes.cpp | 11 +--- source/core/savegamehelp.cpp | 2 +- source/exhumed/src/save.cpp | 1 - source/games/duke/src/actors_r.cpp | 6 +-- source/games/duke/src/gameexec.cpp | 6 +-- source/games/duke/src/global.cpp | 2 +- source/games/duke/src/global.h | 2 +- source/games/duke/src/player.cpp | 6 +-- source/games/duke/src/premap.cpp | 2 +- source/games/duke/src/savegame.cpp | 79 ++++++++++++++++++++-------- source/games/duke/src/sectors_r.cpp | 10 ++-- source/games/duke/src/types.h | 1 + source/sw/src/mfile.h | 5 -- source/sw/src/save.cpp | 5 +- 17 files changed, 79 insertions(+), 80 deletions(-) diff --git a/source/blood/src/loadsave.cpp b/source/blood/src/loadsave.cpp index 58210a1bf..c55ba0e07 100644 --- a/source/blood/src/loadsave.cpp +++ b/source/blood/src/loadsave.cpp @@ -614,7 +614,7 @@ bool GameInterface::SaveGame(FSaveGameNode* node) } LoadSave::hSFile = NULL; - return FinishSavegameWrite(); + return 1; } class MyLoadSave : public LoadSave diff --git a/source/core/menu/savegamemanager.cpp b/source/core/menu/savegamemanager.cpp index 87e951fe6..98992f0e6 100644 --- a/source/core/menu/savegamemanager.cpp +++ b/source/core/menu/savegamemanager.cpp @@ -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; diff --git a/source/core/quotemgr.h b/source/core/quotemgr.h index f6dc8af7a..b387cc9ec 100644 --- a/source/core/quotemgr.h +++ b/source/core/quotemgr.h @@ -17,45 +17,28 @@ class FSerializer; class Quotes { FString quotes[MAXQUOTES]; - FString exquotes[MAXQUOTES]; void MakeStringLabel(FString "e); 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); diff --git a/source/core/quotes.cpp b/source/core/quotes.cpp index 3a6d438e5..c70c2b0ac 100644 --- a/source/core/quotes.cpp +++ b/source/core/quotes.cpp @@ -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; diff --git a/source/core/savegamehelp.cpp b/source/core/savegamehelp.cpp index 45ecec0dc..0dfbdb2a4 100644 --- a/source/core/savegamehelp.cpp +++ b/source/core/savegamehelp.cpp @@ -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 //============================================================================= // diff --git a/source/exhumed/src/save.cpp b/source/exhumed/src/save.cpp index 30275cb86..ceb06359c 100644 --- a/source/exhumed/src/save.cpp +++ b/source/exhumed/src/save.cpp @@ -42,7 +42,6 @@ bool GameInterface::SaveGame(FSaveGameNode* sv) { for (auto sgh : sghelpers) sgh->Save(); SaveTextureState(); - FinishSavegameWrite(); return 1; // CHECKME } diff --git a/source/games/duke/src/actors_r.cpp b/source/games/duke/src/actors_r.cpp index c0d79ec8f..ddcfec339 100644 --- a/source/games/duke/src/actors_r.cpp +++ b/source/games/duke/src/actors_r.cpp @@ -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; } diff --git a/source/games/duke/src/gameexec.cpp b/source/games/duke/src/gameexec.cpp index 221bb92e1..02e62518c 100644 --- a/source/games/duke/src/gameexec.cpp +++ b/source/games/duke/src/gameexec.cpp @@ -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; diff --git a/source/games/duke/src/global.cpp b/source/games/duke/src/global.cpp index 844bb0599..c922c2976 100644 --- a/source/games/duke/src/global.cpp +++ b/source/games/duke/src/global.cpp @@ -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; diff --git a/source/games/duke/src/global.h b/source/games/duke/src/global.h index d32647ed3..0d3577f36 100644 --- a/source/games/duke/src/global.h +++ b/source/games/duke/src/global.h @@ -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; diff --git a/source/games/duke/src/player.cpp b/source/games/duke/src/player.cpp index 8b4ed12b4..e6676f7c6 100644 --- a/source/games/duke/src/player.cpp +++ b/source/games/duke/src/player.cpp @@ -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); } } diff --git a/source/games/duke/src/premap.cpp b/source/games/duke/src/premap.cpp index 363093f98..85284c3bf 100644 --- a/source/games/duke/src/premap.cpp +++ b/source/games/duke/src/premap.cpp @@ -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)); diff --git a/source/games/duke/src/savegame.cpp b/source/games/duke/src/savegame.cpp index 9c4cdee95..55c2a390d 100644 --- a/source/games/duke/src/savegame.cpp +++ b/source/games/duke/src/savegame.cpp @@ -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) diff --git a/source/games/duke/src/sectors_r.cpp b/source/games/duke/src/sectors_r.cpp index 214a43720..d7be602e7 100644 --- a/source/games/duke/src/sectors_r.cpp +++ b/source/games/duke/src/sectors_r.cpp @@ -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); diff --git a/source/games/duke/src/types.h b/source/games/duke/src/types.h index ed5fe4c89..ad6764bd8 100644 --- a/source/games/duke/src/types.h +++ b/source/games/duke/src/types.h @@ -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; diff --git a/source/sw/src/mfile.h b/source/sw/src/mfile.h index bd7e91af2..8f30762e6 100644 --- a/source/sw/src/mfile.h +++ b/source/sw/src/mfile.h @@ -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(); diff --git a/source/sw/src/save.cpp b/source/sw/src/save.cpp index f31b7d10d..ef0fb741a 100644 --- a/source/sw/src/save.cpp +++ b/source/sw/src/save.cpp @@ -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; }