From 8a23010abb9f569883bf03276fc57c1f1550fa04 Mon Sep 17 00:00:00 2001 From: Daniel Gibson Date: Tue, 19 Mar 2024 00:47:28 +0100 Subject: [PATCH] Add information about dhewm3 build to savegames like the dhewm3 version and the OS and architecture of the dhewm3 version that created the savegame. Also added an internalSavegameVersion so be independent of BUILD_NUMBER fixes #344 --- d3xp/Game_local.cpp | 41 +++++++++++++++++++++++++++++++++++++++ d3xp/Game_local.h | 1 + d3xp/gamesys/SaveGame.cpp | 1 + d3xp/gamesys/SaveGame.h | 15 ++++++++++++++ game/Game_local.cpp | 41 +++++++++++++++++++++++++++++++++++++++ game/Game_local.h | 1 + game/gamesys/SaveGame.cpp | 1 + game/gamesys/SaveGame.h | 15 ++++++++++++++ 8 files changed, 116 insertions(+) diff --git a/d3xp/Game_local.cpp b/d3xp/Game_local.cpp index dc09037..87fb4ab 100644 --- a/d3xp/Game_local.cpp +++ b/d3xp/Game_local.cpp @@ -26,6 +26,7 @@ If you have questions concerning this license or the applicable additional terms =========================================================================== */ +#include "sys/Stub_SDL_endian.h" #include "sys/platform.h" #include "idlib/LangDict.h" #include "idlib/Timer.h" @@ -33,6 +34,7 @@ If you have questions concerning this license or the applicable additional terms #include "framework/BuildVersion.h" #include "framework/DeclEntityDef.h" #include "framework/FileSystem.h" +#include "framework/Licensee.h" #include "renderer/ModelManager.h" #include "gamesys/SysCvar.h" @@ -503,6 +505,15 @@ void idGameLocal::SaveGame( idFile *f ) { savegame.WriteBuildNumber( BUILD_NUMBER ); + // DG: add some more information to savegame to make future quirks easier + savegame.WriteInt( INTERNAL_SAVEGAME_VERSION ); // to be independent of BUILD_NUMBER + savegame.WriteString( D3_OSTYPE ); // operating system - from CMake + savegame.WriteString( D3_ARCH ); // CPU architecture (e.g. "x86" or "x86_64") - from CMake + savegame.WriteString( ENGINE_VERSION ); + savegame.WriteShort( (short)sizeof(void*) ); // tells us if it's from a 32bit (4) or 64bit system (8) + savegame.WriteShort( SDL_BYTEORDER ) ; // SDL_LIL_ENDIAN or SDL_BIG_ENDIAN + // DG end + // go through all entities and threads and add them to the object list for( i = 0; i < MAX_GENTITIES; i++ ) { ent = entities[i]; @@ -1358,6 +1369,36 @@ bool idGameLocal::InitFromSaveGame( const char *mapName, idRenderWorld *renderWo savegame.ReadBuildNumber(); + // DG: I enhanced the information in savegames a bit for dhewm3 1.5.1 + // for which I bumped th BUILD_NUMBER to 1305 + if( savegame.GetBuildNumber() >= 1305 ) + { + savegame.ReadInternalSavegameVersion(); + if( savegame.GetInternalSavegameVersion() > INTERNAL_SAVEGAME_VERSION ) { + Warning( "Savegame from newer dhewm3 version, don't know how to load! (its version is %d, only up to %d supported)", + savegame.GetInternalSavegameVersion(), INTERNAL_SAVEGAME_VERSION ); + return false; + } + idStr osType; + idStr cpuArch; + idStr engineVersion; + short ptrSize = 0; + short byteorder = 0; + savegame.ReadString( osType ); // operating system the savegame was crated on (written from D3_OSTYPE) + savegame.ReadString( cpuArch ); // written from D3_ARCH (which is set in CMake), like "x86" or "x86_64" + savegame.ReadString( engineVersion ); // written from ENGINE_VERSION + savegame.ReadShort( ptrSize ); // sizeof(void*) of system that created the savegame, 4 on 32bit systems, 8 on 64bit systems + savegame.ReadShort( byteorder ); // SDL_LIL_ENDIAN or SDL_BIG_ENDIAN + + Printf( "Savegame was created by %s on %s %s. BuildNumber was %d, savegameversion %d\n", + engineVersion.c_str(), osType.c_str(), cpuArch.c_str(), savegame.GetBuildNumber(), + savegame.GetInternalSavegameVersion() ); + + // right now I have no further use for this information, but in the future + // it can be used for quirks for (then-) old savegames + } + // DG end + // Create the list of all objects in the game savegame.CreateObjects(); diff --git a/d3xp/Game_local.h b/d3xp/Game_local.h index cb229cd..acd4fff 100644 --- a/d3xp/Game_local.h +++ b/d3xp/Game_local.h @@ -512,6 +512,7 @@ public: private: const static int INITIAL_SPAWN_COUNT = 1; + const static int INTERNAL_SAVEGAME_VERSION = 1; // DG: added this for >= 1305 savegames idStr mapFileName; // name of the map, empty string if no map loaded idMapFile * mapFile; // will be NULL during the game unless in-game editing is used diff --git a/d3xp/gamesys/SaveGame.cpp b/d3xp/gamesys/SaveGame.cpp index 1207263..ce31cf0 100644 --- a/d3xp/gamesys/SaveGame.cpp +++ b/d3xp/gamesys/SaveGame.cpp @@ -786,6 +786,7 @@ idRestoreGame::RestoreGame */ idRestoreGame::idRestoreGame( idFile *savefile ) { file = savefile; + internalSavegameVersion = 0; } /* diff --git a/d3xp/gamesys/SaveGame.h b/d3xp/gamesys/SaveGame.h index 4b0927f..b781659 100644 --- a/d3xp/gamesys/SaveGame.h +++ b/d3xp/gamesys/SaveGame.h @@ -158,8 +158,23 @@ public: // Used to retrieve the saved game buildNumber from within class Restore methods int GetBuildNumber( void ); + // DG: added these methods, internalSavegameVersion makes us independent of the global BUILD_NUMBER + void ReadInternalSavegameVersion( void ) + { + ReadInt( internalSavegameVersion ); + } + + // if it's 0, this is from a GetBuildNumber() < 1305 savegame + // otherwise, compare it to idGameLocal::INTERNAL_SAVEGAME_VERSION + int GetInternalSavegameVersion( void ) const + { + return internalSavegameVersion; + } + // DG end + private: int buildNumber; + int internalSavegameVersion; // DG added this idFile * file; diff --git a/game/Game_local.cpp b/game/Game_local.cpp index 78c089b..a051629 100644 --- a/game/Game_local.cpp +++ b/game/Game_local.cpp @@ -26,6 +26,7 @@ If you have questions concerning this license or the applicable additional terms =========================================================================== */ +#include "sys/Stub_SDL_endian.h" #include "sys/platform.h" #include "idlib/LangDict.h" #include "idlib/Timer.h" @@ -33,6 +34,7 @@ If you have questions concerning this license or the applicable additional terms #include "framework/BuildVersion.h" #include "framework/DeclEntityDef.h" #include "framework/FileSystem.h" +#include "framework/Licensee.h" #include "renderer/ModelManager.h" #include "gamesys/SysCvar.h" @@ -430,6 +432,15 @@ void idGameLocal::SaveGame( idFile *f ) { savegame.WriteBuildNumber( BUILD_NUMBER ); + // DG: add some more information to savegame to make future quirks easier + savegame.WriteInt( INTERNAL_SAVEGAME_VERSION ); // to be independent of BUILD_NUMBER + savegame.WriteString( D3_OSTYPE ); // operating system - from CMake + savegame.WriteString( D3_ARCH ); // CPU architecture (e.g. "x86" or "x86_64") - from CMake + savegame.WriteString( ENGINE_VERSION ); + savegame.WriteShort( (short)sizeof(void*) ); // tells us if it's from a 32bit (4) or 64bit system (8) + savegame.WriteShort( SDL_BYTEORDER ) ; // SDL_LIL_ENDIAN or SDL_BIG_ENDIAN + // DG end + // go through all entities and threads and add them to the object list for( i = 0; i < MAX_GENTITIES; i++ ) { ent = entities[i]; @@ -1232,6 +1243,36 @@ bool idGameLocal::InitFromSaveGame( const char *mapName, idRenderWorld *renderWo savegame.ReadBuildNumber(); + // DG: I enhanced the information in savegames a bit for dhewm3 1.5.1 + // for which I bumped th BUILD_NUMBER to 1305 + if( savegame.GetBuildNumber() >= 1305 ) + { + savegame.ReadInternalSavegameVersion(); + if( savegame.GetInternalSavegameVersion() > INTERNAL_SAVEGAME_VERSION ) { + Warning( "Savegame from newer dhewm3 version, don't know how to load! (its version is %d, only up to %d supported)", + savegame.GetInternalSavegameVersion(), INTERNAL_SAVEGAME_VERSION ); + return false; + } + idStr osType; + idStr cpuArch; + idStr engineVersion; + short ptrSize = 0; + short byteorder = 0; + savegame.ReadString( osType ); // operating system the savegame was crated on (written from D3_OSTYPE) + savegame.ReadString( cpuArch ); // written from D3_ARCH (which is set in CMake), like "x86" or "x86_64" + savegame.ReadString( engineVersion ); // written from ENGINE_VERSION + savegame.ReadShort( ptrSize ); // sizeof(void*) of system that created the savegame, 4 on 32bit systems, 8 on 64bit systems + savegame.ReadShort( byteorder ); // SDL_LIL_ENDIAN or SDL_BIG_ENDIAN + + Printf( "Savegame was created by %s on %s %s. BuildNumber was %d, savegameversion %d\n", + engineVersion.c_str(), osType.c_str(), cpuArch.c_str(), savegame.GetBuildNumber(), + savegame.GetInternalSavegameVersion() ); + + // right now I have no further use for this information, but in the future + // it can be used for quirks for (then-) old savegames + } + // DG end + // Create the list of all objects in the game savegame.CreateObjects(); diff --git a/game/Game_local.h b/game/Game_local.h index 377aaec..34ee489 100644 --- a/game/Game_local.h +++ b/game/Game_local.h @@ -454,6 +454,7 @@ public: private: const static int INITIAL_SPAWN_COUNT = 1; + const static int INTERNAL_SAVEGAME_VERSION = 1; // DG: added this for >= 1305 savegames idStr mapFileName; // name of the map, empty string if no map loaded idMapFile * mapFile; // will be NULL during the game unless in-game editing is used diff --git a/game/gamesys/SaveGame.cpp b/game/gamesys/SaveGame.cpp index 40e1969..158f5ab 100644 --- a/game/gamesys/SaveGame.cpp +++ b/game/gamesys/SaveGame.cpp @@ -781,6 +781,7 @@ idRestoreGame::RestoreGame */ idRestoreGame::idRestoreGame( idFile *savefile ) { file = savefile; + internalSavegameVersion = 0; } /* diff --git a/game/gamesys/SaveGame.h b/game/gamesys/SaveGame.h index 4b0927f..b781659 100644 --- a/game/gamesys/SaveGame.h +++ b/game/gamesys/SaveGame.h @@ -158,8 +158,23 @@ public: // Used to retrieve the saved game buildNumber from within class Restore methods int GetBuildNumber( void ); + // DG: added these methods, internalSavegameVersion makes us independent of the global BUILD_NUMBER + void ReadInternalSavegameVersion( void ) + { + ReadInt( internalSavegameVersion ); + } + + // if it's 0, this is from a GetBuildNumber() < 1305 savegame + // otherwise, compare it to idGameLocal::INTERNAL_SAVEGAME_VERSION + int GetInternalSavegameVersion( void ) const + { + return internalSavegameVersion; + } + // DG end + private: int buildNumber; + int internalSavegameVersion; // DG added this idFile * file;