From b54c8ec9e9c7116a84bc28f3a1e23fcb3b2f6bce Mon Sep 17 00:00:00 2001 From: Bobby Battista Date: Sat, 7 Mar 2026 09:16:36 -0600 Subject: [PATCH 1/2] bugfix(savegame): Guard GameLogic xfer version bump with RETAIL_COMPATIBLE_XFER_SAVE --- .../Source/GameLogic/System/GameLogic.cpp | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp index 1d671f180f..3b7e73dfb8 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp @@ -4804,14 +4804,18 @@ void GameLogic::prepareLogicForObjectLoad() * 5: Added xfering the BuildAssistant's sell list. * 9: Added m_rankPointsToAddAtGameStart, or else on a load game, your RestartGame button will forget your exp * 10: xfer m_superweaponRestriction - * 11: TheSuperHackers @tweak Save objects in reverse order so they load in correct order + * 11: TheSuperHackers @fix Save objects in reverse order so they load in correct order */ // ------------------------------------------------------------------------------------------------ void GameLogic::xfer( Xfer *xfer ) { // version +#if RETAIL_COMPATIBLE_XFER_SAVE + const XferVersion currentVersion = 10; +#else const XferVersion currentVersion = 11; +#endif XferVersion version = currentVersion; xfer->xferVersion( &version, currentVersion ); @@ -4844,13 +4848,17 @@ void GameLogic::xfer( Xfer *xfer ) ObjectTOCEntry *tocEntry; if( xfer->getXferMode() == XFER_SAVE ) { - // TheSuperHackers @fix bobtista 27/01/2026 Save objects in reverse order (newest first) +#if !RETAIL_COMPATIBLE_XFER_SAVE + // TheSuperHackers @fix bobtista 07/03/2026 Save objects in reverse order (newest first) // so they load in the correct order (oldest objects at head of list). Object *lastObj = nullptr; for( obj = getFirstObject(); obj; obj = obj->getNextObject() ) lastObj = obj; for( obj = lastObj; obj; obj = obj->getPrevObject() ) +#else + for( obj = getFirstObject(); obj; obj = obj->getNextObject() ) +#endif { // get the object TOC entry for this template @@ -4933,9 +4941,9 @@ void GameLogic::xfer( Xfer *xfer ) } - // TheSuperHackers @fix bobtista 27/01/2026 Reverse object list for old saves. - // Old saves stored objects oldest-first, which results in reversed order when loaded - // since objects are prepended during creation. Version 11+ saves in reverse order. + // TheSuperHackers @fix bobtista 07/03/2026 Reverse object list after load. + // Objects are prepended during creation, which reverses the saved order. + // Version 11+ saves in reverse order so they load in the correct order. if ( version <= 10 ) { Object *prev = nullptr; From 805d1937607587696bf32fbfd880b679a9e350f9 Mon Sep 17 00:00:00 2001 From: Bobby Battista Date: Sat, 7 Mar 2026 09:16:39 -0600 Subject: [PATCH 2/2] bugfix(savegame): Guard GameLogic xfer version bump with RETAIL_COMPATIBLE_XFER_SAVE --- .../Source/GameLogic/System/GameLogic.cpp | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/Generals/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp b/Generals/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp index d14956a990..666ec5eb83 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp @@ -4244,14 +4244,18 @@ void GameLogic::prepareLogicForObjectLoad() * this version breaks compatibility with previous versions. (CBD) * 5: Added xfering the BuildAssistant's sell list. * 9: Added m_rankPointsToAddAtGameStart, or else on a load game, your RestartGame button will forget your exp - * 10: TheSuperHackers @tweak Save objects in reverse order so they load in correct order. Reverse object list for old saves. + * 10: TheSuperHackers @fix Save objects in reverse order so they load in correct order */ // ------------------------------------------------------------------------------------------------ void GameLogic::xfer( Xfer *xfer ) { // version +#if RETAIL_COMPATIBLE_XFER_SAVE + const XferVersion currentVersion = 9; +#else const XferVersion currentVersion = 10; +#endif XferVersion version = currentVersion; xfer->xferVersion( &version, currentVersion ); @@ -4284,14 +4288,17 @@ void GameLogic::xfer( Xfer *xfer ) ObjectTOCEntry *tocEntry; if( xfer->getXferMode() == XFER_SAVE ) { - - // TheSuperHackers @fix bobtista 27/01/2026 Save objects in reverse order (newest first) +#if !RETAIL_COMPATIBLE_XFER_SAVE + // TheSuperHackers @fix bobtista 07/03/2026 Save objects in reverse order (newest first) // so they load in the correct order (oldest objects at head of list). Object *lastObj = nullptr; for( obj = getFirstObject(); obj; obj = obj->getNextObject() ) lastObj = obj; for( obj = lastObj; obj; obj = obj->getPrevObject() ) +#else + for( obj = getFirstObject(); obj; obj = obj->getNextObject() ) +#endif { // get the object TOC entry for this template @@ -4374,9 +4381,9 @@ void GameLogic::xfer( Xfer *xfer ) } - // TheSuperHackers @fix bobtista 27/01/2026 Reverse object list for old saves. - // Old saves stored objects oldest-first, which results in reversed order when loaded - // since objects are prepended during creation. Version 10+ saves in reverse order. + // TheSuperHackers @fix bobtista 07/03/2026 Reverse object list after load. + // Objects are prepended during creation, which reverses the saved order. + // Version 10+ saves in reverse order so they load in the correct order. if ( version <= 9 ) { Object *prev = nullptr;