From 528e324ba4ab68cc03e66c52957ddca457912328 Mon Sep 17 00:00:00 2001 From: Helmut Buhler Date: Sat, 25 Oct 2025 18:32:58 +0200 Subject: [PATCH 1/4] Add startup messagebox --- .../GameEngine/Source/Common/System/Debug.cpp | 2 +- GeneralsMD/Code/Main/WinMain.cpp | 27 +++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/Core/GameEngine/Source/Common/System/Debug.cpp b/Core/GameEngine/Source/Common/System/Debug.cpp index 55dcdcd65f..530f48e7a9 100644 --- a/Core/GameEngine/Source/Common/System/Debug.cpp +++ b/Core/GameEngine/Source/Common/System/Debug.cpp @@ -104,7 +104,7 @@ extern const char *gAppPrefix; /// So WB can have a different log file name. // TheSuperHackers @info Must not use static RAII types when set in DebugInit, // because DebugInit can be called during static module initialization before the main function is called. #ifdef DEBUG_LOGGING -static FILE *theLogFile = NULL; +FILE *theLogFile = NULL; static char theLogFileName[ _MAX_PATH ]; static char theLogFileNamePrev[ _MAX_PATH ]; #endif diff --git a/GeneralsMD/Code/Main/WinMain.cpp b/GeneralsMD/Code/Main/WinMain.cpp index e23d4e4b44..5374743bb7 100644 --- a/GeneralsMD/Code/Main/WinMain.cpp +++ b/GeneralsMD/Code/Main/WinMain.cpp @@ -48,6 +48,7 @@ #include "Common/GameEngine.h" #include "Common/GameSounds.h" #include "Common/Debug.h" +#include "Common/CRCDebug.h" #include "Common/GameMemory.h" #include "Common/StackDump.h" #include "Common/MessageStream.h" @@ -854,6 +855,32 @@ Int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, CommandLine::parseCommandLineForStartup(); + if(!TheGlobalData->m_headless) + { +#if defined(DEBUG_LOGGING) && defined(DEBUG_CRC) + extern FILE *theLogFile; + if (theLogFile == NULL || NET_CRC_INTERVAL != 1) + { + MessageBoxW(NULL, L"This is a special build of the game that helps debugging mismatches.\n" + L"This version requires write permission on the game folder. To fix this, you can start the game as admin or copy the game folder into a user folder and run the game from there.", + L"Super Hackers Build", MB_ICONERROR); + return 1; + } + + MessageBoxW(NULL, L"This is a special build of the game that helps debugging mismatches.\n\n" + L"Some info about this:\n" + L" - This version might run a bit slower.\n" + L" - If a mismatch occurs, a log file 00000000.txt appears next to the replay. The devs will need both the replay and the log file.\n" + L" - This version is still compatible with the 1.04 retail game. But to debug mismatches with this, the devs will need the replays and log files of two players who got a mismatch with each other.\n" + L"\nThanks for testing!", + L"Super Hackers Build", 0); +#else + MessageBoxW(NULL, L"You downloaded the wrong exe!", + L"Super Hackers Build", MB_ICONERROR); + return 1; +#endif + } + // register windows class and create application window if(!TheGlobalData->m_headless && initializeAppWindows(hInstance, nCmdShow, TheGlobalData->m_windowed) == false) return exitcode; From e009c99f2b5833fd7670429b4ea5b2604936b51a Mon Sep 17 00:00:00 2001 From: Helmut Buhler Date: Sat, 25 Oct 2025 21:09:50 +0200 Subject: [PATCH 2/4] Enable crc logging and object crc logging by default. Disable assert messageboxes. --- GeneralsMD/Code/GameEngine/Source/Common/CommandLine.cpp | 4 ++-- GeneralsMD/Code/GameEngine/Source/Common/GlobalData.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/GeneralsMD/Code/GameEngine/Source/Common/CommandLine.cpp b/GeneralsMD/Code/GameEngine/Source/Common/CommandLine.cpp index 19678a6744..469da6ed7f 100644 --- a/GeneralsMD/Code/GameEngine/Source/Common/CommandLine.cpp +++ b/GeneralsMD/Code/GameEngine/Source/Common/CommandLine.cpp @@ -44,7 +44,7 @@ Bool TheDebugIgnoreSyncErrors = FALSE; extern Int DX8Wrapper_PreserveFPU; #ifdef DEBUG_CRC -Int TheCRCFirstFrameToLog = -1; +Int TheCRCFirstFrameToLog = 0;//-1; UnsignedInt TheCRCLastFrameToLog = 0xffffffff; Bool g_keepCRCSaves = FALSE; Bool g_saveDebugCRCPerFrame = FALSE; @@ -53,7 +53,7 @@ Bool g_crcModuleDataFromLogic = FALSE; Bool g_crcModuleDataFromClient = FALSE; Bool g_verifyClientCRC = FALSE; // verify that GameLogic CRC doesn't change from client Bool g_clientDeepCRC = FALSE; -Bool g_logObjectCRCs = FALSE; +Bool g_logObjectCRCs = TRUE;//FALSE; #endif #if defined(RTS_DEBUG) diff --git a/GeneralsMD/Code/GameEngine/Source/Common/GlobalData.cpp b/GeneralsMD/Code/GameEngine/Source/Common/GlobalData.cpp index 264a0ddab8..6e5cbbbcbe 100644 --- a/GeneralsMD/Code/GameEngine/Source/Common/GlobalData.cpp +++ b/GeneralsMD/Code/GameEngine/Source/Common/GlobalData.cpp @@ -603,7 +603,7 @@ GlobalData::GlobalData() #endif #ifdef DEBUG_CRASHING - m_debugIgnoreAsserts = FALSE; + m_debugIgnoreAsserts = TRUE; #endif #ifdef DEBUG_STACKTRACE From 8e89eebb1983a893d55805ad9758f6fad9ba86d7 Mon Sep 17 00:00:00 2001 From: Helmut Buhler Date: Sat, 25 Oct 2025 21:11:22 +0200 Subject: [PATCH 3/4] Copy log to replay folder when mismatch happens --- .../GameEngine/Source/Common/Recorder.cpp | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/GeneralsMD/Code/GameEngine/Source/Common/Recorder.cpp b/GeneralsMD/Code/GameEngine/Source/Common/Recorder.cpp index b59813da06..d82beee0d3 100644 --- a/GeneralsMD/Code/GameEngine/Source/Common/Recorder.cpp +++ b/GeneralsMD/Code/GameEngine/Source/Common/Recorder.cpp @@ -198,10 +198,10 @@ void RecorderClass::logCRCMismatch( void ) m_file->seek(fileSize, File::seekMode::START); DEBUG_ASSERTCRASH(res == fileSize, ("Could not seek to end of file!")); + m_wasDesync = TRUE; #if defined(RTS_DEBUG) if (TheGlobalData->m_saveStats) { - m_wasDesync = TRUE; unsigned long bufSize = MAX_COMPUTERNAME_LENGTH + 1; char computerName[MAX_COMPUTERNAME_LENGTH + 1]; if (!GetComputerName(computerName, &bufSize)) @@ -350,6 +350,18 @@ void RecorderClass::cleanUpReplayFile( void ) #endif // DEBUG_LOGGING } #endif +#ifdef DEBUG_LOGGING + const char* logFileName = DebugGetLogFileName(); + if (logFileName[0] == '\0') + return; + + AsciiString targetFilepath = getReplayDir(); + targetFilepath.concat(getLastReplayFileName()); + targetFilepath.concat(".txt"); + + DEBUG_LOG(("Copy log to replayfolder to %s", targetFilepath.str())); + CopyFile(logFileName, targetFilepath.str(), FALSE); +#endif // DEBUG_LOGGING } /** @@ -553,6 +565,14 @@ void RecorderClass::startRecording(GameDifficulty diff, Int originalGameMode, In // We have to make sure the replay dir exists. TheFileSystem->createDirectory(filepath); +#ifdef DEBUG_LOGGING + // Delete old logfile next to replay + m_fileName = getReplayDir(); + m_fileName.concat(getLastReplayFileName()); + m_fileName.concat(".txt"); + DeleteFileA(m_fileName.str()); +#endif + m_fileName = getLastReplayFileName(); m_fileName.concat(getReplayExtention()); filepath.concat(m_fileName); From 47e49267d37ac58225de8defea476ad901cfbb00 Mon Sep 17 00:00:00 2001 From: Helmut Buhler Date: Sun, 26 Oct 2025 17:23:33 +0100 Subject: [PATCH 4/4] Add extra condition to #if --- GeneralsMD/Code/Main/WinMain.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GeneralsMD/Code/Main/WinMain.cpp b/GeneralsMD/Code/Main/WinMain.cpp index 5374743bb7..6450c7a784 100644 --- a/GeneralsMD/Code/Main/WinMain.cpp +++ b/GeneralsMD/Code/Main/WinMain.cpp @@ -857,7 +857,7 @@ Int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, if(!TheGlobalData->m_headless) { -#if defined(DEBUG_LOGGING) && defined(DEBUG_CRC) +#if defined(DEBUG_LOGGING) && defined(DEBUG_CRC) && (defined(_MSC_VER) && _MSC_VER < 1300) && RETAIL_COMPATIBLE_CRC extern FILE *theLogFile; if (theLogFile == NULL || NET_CRC_INTERVAL != 1) {