sync: merge TheSuperHackers main and fix macOS build regressions#93
Conversation
…ants on save game load (TheSuperHackers#2508)
… plants on save game load (TheSuperHackers#2509)
…ing audio length script conditions in headless mode (TheSuperHackers#2313)
…ackers#2546) This adds two new meta events: DEMO_BEGIN_ADJUST_DEFAULTPITCH, DEMO_END_ADJUST_DEFAULTPITCH, which are default mapped to CTRL + MK_COMMA
…antly on save load (TheSuperHackers#2591)
- merges 13 upstream commits including bugfixes for INI parsing, camera, pathfinder, energy, audio, money, input, projectiles - Key change: dx8wrapper and dx8caps moved to Core/Libraries/Source/WWVegas/WW3D2 - Conflict resolution: * Accepted DX8 file deletions from Generals/ game dir (files now in Core) * Kept GeneralsX INI parser approach: merged plus-sign handling + Apple std::strtod support * Kept GeneralsX camera/UI implementation (aspect-ratio-aware, sorted starting cash) * Preserved PCH conditional pattern for Windows (disabled on Linux) - Preserved cross-platform architecture (SDL3, DXVK, OpenAL) - All conflict markers resolved, ready for validation
Resolve post-sync macOS build failures after integrating TheSuperHackers upstream changes. - align SDL3GameEngine pure-virtual factory signatures in Generals and GeneralsMD - migrate Generals WW3D2 sorting renderer to unified RenderStateStruct fields - release all vertex streams in sorting state cleanup path - update April 2026 dev diary with sync and validation notes This restores successful Generals base macOS build while preserving the cross-platform architecture.
There was a problem hiding this comment.
Pull request overview
Upstream sync from TheSuperHackers/main into GeneralsX, with conflict resolutions to preserve the SDL3 + DXVK + OpenAL cross-platform stack and fix post-merge build regressions (notably factory interface changes, WW3D2 unification, and several gameplay/input/camera fixes).
Changes:
- Aligned
GameEnginefactory interfaces (headless/dummy-aware signatures) and updated implementations/call sites. - Unified WW3D2 DX8 wrapper/caps into
Core/and adjusted WW3D2 build files accordingly. - Integrated upstream fixes across INI parsing, camera/view behavior, input/mouse wheel handling, save/load/xfer versioning, and renderer state cleanup.
Reviewed changes
Copilot reviewed 55 out of 60 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| scripts/tooling/cpp/maintenance/unify_move_files.py | Adds helper to unify/move WW3D2 DX8 wrapper/caps into Core via script. |
| docs/DEV_BLOG/2026-04-DIARY.md | Dev diary entry documenting upstream sync + validation notes. |
| GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/CMakeLists.txt | Stops compiling dx8wrapper/dx8caps in ZH game-local WW3D2; keeps Win32-only PCH include. |
| GeneralsMD/Code/GameEngineDevice/Source/SDL3GameEngine.cpp | Updates SDL3 factory signatures for radar/audio (but has headless + fallback issues). |
| GeneralsMD/Code/GameEngineDevice/Include/Win32Device/Common/Win32GameEngine.h | Updates Win32 factory signatures and returns dummy implementations when dummy==true. |
| GeneralsMD/Code/GameEngineDevice/Include/SDL3GameEngine.h | Updates SDL3 factory method declarations to match new pure-virtual signatures. |
| GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp | Switches token fetching to throwing getNextToken(...) for stricter INI parsing. |
| GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Upgrade/PowerPlantUpgrade.cpp | Avoids adding power bonus for disabled objects on load. |
| GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/OCLUpdate.cpp | Switches to throwing getNextToken(...) in parser. |
| GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AutoDepositUpdate.cpp | Switches to throwing getNextToken(...) in parser. |
| GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp | Moves team restoration later in xfer load after disabled-data transfer. |
| GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Behavior/OverchargeBehavior.cpp | Avoids adding power bonus when object is disabled on load. |
| GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Behavior/DumbProjectileBehavior.cpp | Adds xfer versioning for mid-flight save/load + recalculates flight path on load. |
| GeneralsMD/Code/GameEngine/Source/GameClient/MessageStream/WindowXlat.cpp | Treats mouse wheel argument as Real (touchpad fractional support). |
| GeneralsMD/Code/GameEngine/Source/GameClient/MessageStream/MetaEvent.cpp | Adds meta bindings for debug “adjust default pitch” actions. |
| GeneralsMD/Code/GameEngine/Source/GameClient/MessageStream/LookAtXlat.cpp | Implements debug default-pitch adjustment mode + uses Real wheel delta. |
| GeneralsMD/Code/GameEngine/Source/Common/RTS/Energy.cpp | Adds debug assert to prevent adding power bonus to disabled power plants. |
| GeneralsMD/Code/GameEngine/Source/Common/MessageStream.cpp | Adds missing string labels for new meta commands. |
| GeneralsMD/Code/GameEngine/Source/Common/GameEngine.cpp | Routes radar/audio init through new create*(Bool dummy) factories. |
| GeneralsMD/Code/GameEngine/Include/GameClient/LookAtXlat.h | Adds state for default-pitch adjustment mode. |
| GeneralsMD/Code/GameEngine/Include/Common/MessageStream.h | Updates mouse wheel arg doc to Real; adds new meta message enums. |
| GeneralsMD/Code/GameEngine/Include/Common/GameEngine.h | Updates pure-virtual factory signatures for radar/audio to take Bool dummy. |
| Generals/Code/Libraries/Source/WWVegas/WW3D2/sortingrenderer.cpp | Updates to unified RenderStateStruct fields + releases all vertex streams. |
| Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.h | Removes local dx8wrapper header (moved/unified into Core layout). |
| Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8caps.h | Removes local dx8caps header (moved/unified into Core layout). |
| Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8caps.cpp | Removes local dx8caps source (moved/unified into Core layout). |
| Generals/Code/Libraries/Source/WWVegas/WW3D2/CMakeLists.txt | Stops compiling dx8wrapper/dx8caps in Generals game-local WW3D2; adjusts PCH include quoting. |
| Generals/Code/GameEngineDevice/Source/SDL3GameEngine.cpp | Updates SDL3 factory signatures for radar/audio (but has headless + fallback issues). |
| Generals/Code/GameEngineDevice/Include/Win32Device/Common/Win32GameEngine.h | Updates Win32 factory signatures and dummy-return logic for headless. |
| Generals/Code/GameEngineDevice/Include/SDL3GameEngine.h | Updates SDL3 factory declarations to match new pure-virtual signatures. |
| Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp | Switches token fetching to throwing getNextToken(...). |
| Generals/Code/GameEngine/Source/GameLogic/Object/Upgrade/PowerPlantUpgrade.cpp | Avoids adding power bonus for disabled objects on load. |
| Generals/Code/GameEngine/Source/GameLogic/Object/Update/AutoDepositUpdate.cpp | Switches to throwing getNextToken(...) in parser. |
| Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp | Moves team restoration later in xfer load after disabled-data transfer. |
| Generals/Code/GameEngine/Source/GameLogic/Object/Behavior/OverchargeBehavior.cpp | Avoids adding power bonus when object is disabled on load. |
| Generals/Code/GameEngine/Source/GameLogic/Object/Behavior/DumbProjectileBehavior.cpp | Adds xfer versioning for mid-flight save/load + recalculates flight path on load. |
| Generals/Code/GameEngine/Source/GameClient/MessageStream/WindowXlat.cpp | Treats mouse wheel argument as Real. |
| Generals/Code/GameEngine/Source/GameClient/MessageStream/MetaEvent.cpp | Adds meta bindings for debug “adjust default pitch” actions. |
| Generals/Code/GameEngine/Source/GameClient/MessageStream/LookAtXlat.cpp | Implements debug default-pitch adjustment mode + uses Real wheel delta. |
| Generals/Code/GameEngine/Source/Common/RTS/Energy.cpp | Adds debug assert to prevent adding power bonus to disabled power plants. |
| Generals/Code/GameEngine/Source/Common/MessageStream.cpp | Adds missing string labels for new meta commands. |
| Generals/Code/GameEngine/Source/Common/GameEngine.cpp | Routes radar/audio init through new create*(Bool dummy) factories. |
| Generals/Code/GameEngine/Include/GameClient/LookAtXlat.h | Adds state for default-pitch adjustment mode. |
| Generals/Code/GameEngine/Include/Common/MessageStream.h | Updates mouse wheel arg doc to Real; adds new meta message enums. |
| Generals/Code/GameEngine/Include/Common/GameEngine.h | Updates pure-virtual factory signatures for radar/audio to take Bool dummy. |
| Core/Libraries/Source/WWVegas/WW3D2/dx8caps.h | Adds unified dx8caps header under Core WW3D2. |
| Core/Libraries/Source/WWVegas/WW3D2/dx8caps.cpp | Adds unified dx8caps implementation under Core WW3D2. |
| Core/Libraries/Source/WWVegas/WW3D2/CMakeLists.txt | Enables building dx8wrapper/dx8caps from Core WW3D2 sources. |
| Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DView.cpp | Camera math/constraints updates; adds default pitch setter; clamps adjustment factor. |
| Core/GameEngineDevice/Include/W3DDevice/GameClient/W3DView.h | Updates signatures for camera constraint helper + adds setDefaultPitch override. |
| Core/GameEngineDevice/Include/MilesAudioDevice/MilesAudioManager.h | Adds MilesAudioManagerDummy for headless mode while preserving file-length behavior. |
| Core/GameEngine/Source/GameLogic/AI/AIPathfind.cpp | Fixes CRC computation while keeping retail-compatible behavior behind macro. |
| Core/GameEngine/Source/GameClient/View.cpp | Initializes defaults from GlobalData; clamps pitch; adds setDefaultPitch. |
| Core/GameEngine/Source/GameClient/Input/Mouse.cpp | Emits wheel delta as Real to preserve fractional touchpad input. |
| Core/GameEngine/Source/Common/INI/INI.cpp | Updates numeric scan logic for +-prefixed tokens + Apple float parsing (currently broken for integers). |
| Core/GameEngine/Include/GameClient/View.h | Adds default pitch/yaw constants + exposes default angle/pitch getters and user actions. |
| Core/GameEngine/Include/Common/GameAudio.h | Removes AudioManagerDummy (now relying on alternative dummy strategy). |
Comments suppressed due to low confidence (3)
Core/GameEngine/Source/Common/INI/INI.cpp:1714
scanTypeno longer compiles for non-floating-point types: the integer-parsing path referencesecandresultbut they are never declared (thestd::from_charscall /resultdefinition were removed when adding the leading+handling). Please restore the integer parsing branch (e.g., declarestd::conditional_t<...> result+auto [ptr, ec] = std::from_chars(...)) and keep the existing+prefix stripping + error handling consistent with the float branch.
template <typename Type>
Type scanType(std::string_view token)
{
DEBUG_ASSERTCRASH(!token.empty(), ("token is not expected to be empty"));
// Unlike sscanf, std::from_chars cannot parse "+".
// Consume the plus symbol to accommodate custom ini files that have numbers prefixed with a plus.
if (!token.empty() && token[0] == '+')
{
token.remove_prefix(1);
}
if constexpr (std::is_floating_point_v<Type>)
{
// GeneralsX @bugfix BenderAI 07/04/2026 Apple SDKs in our deployment target do not expose std::from_chars for floats.
#if defined(__APPLE__)
const std::string tokenString(token);
char *end = nullptr;
const double result = std::strtod(tokenString.c_str(), &end);
if (end == tokenString.c_str())
{
throw INI_INVALID_DATA;
}
return static_cast<Type>(result);
#else
Type result{};
const auto [ptr, ec] = std::from_chars(token.data(), token.data() + token.size(), result);
if (ec != std::errc{})
{
throw INI_INVALID_DATA;
}
return result;
#endif
}
// TheSuperHackers @info std::from_chars cannot parse "-1" as uint32 so the result needs to be int64 for integers.
if (ec != std::errc{})
{
throw INI_INVALID_DATA;
}
return static_cast<Type>(result);
}
Generals/Code/GameEngineDevice/Source/SDL3GameEngine.cpp:544
SDL3GameEngine::createAudioManager(Bool)falls back toAudioManagerDummy, butAudioManagerDummywas removed fromCore/GameEngine/Include/Common/GameAudio.hin this PR. This will fail to compile whenSAGE_USE_OPENALis not defined. Please update the fallback to a currently-available dummy implementation (e.g.,MilesAudioManagerDummyon Windows, or a new cross-platform stub) and/or make the factory honor thedummy/headless flag.
GeneralsMD/Code/GameEngineDevice/Source/SDL3GameEngine.cpp:562- In the
#elsebranch (whenSAGE_USE_OPENALis not defined),createAudioManager(Bool)callsGameEngine::createAudioManager()with no arguments. After this sync,GameEngine::createAudioManageris a pure-virtual that takesBool dummy, so this fallback should not compile and cannot work at runtime. Please replace this with a real dummy/stubAudioManagerinstance (and/or delegate to a helper that matches the new signature).
| // GeneralsX @bugfix Copilot 15/04/2026 Match upstream GameEngine pure-virtual signature after sync. | ||
| Radar *SDL3GameEngine::createRadar(Bool dummy) | ||
| { | ||
| (void)dummy; | ||
| fprintf(stderr, "INFO: SDL3GameEngine::createRadar() -> W3DRadar\n"); | ||
| return NEW W3DRadar; | ||
| } |
There was a problem hiding this comment.
createRadar(Bool dummy) ignores the dummy (headless) flag and always instantiates W3DRadar. Since GameEngine::init() now passes TheGlobalData->m_headless into createRadar(...), headless mode will still allocate the full radar subsystem. Please honor dummy here (e.g., return RadarDummy when dummy is true) to match the updated factory contract.
| // GeneralsX @bugfix Copilot 15/04/2026 Match upstream GameEngine pure-virtual signature after sync. | ||
| Radar *SDL3GameEngine::createRadar(Bool dummy) | ||
| { | ||
| (void)dummy; | ||
| fprintf(stderr, "INFO: SDL3GameEngine::createRadar() -> W3DRadar\n"); | ||
| return NEW W3DRadar; | ||
| } |
There was a problem hiding this comment.
createRadar(Bool dummy) ignores the dummy (headless) flag and always instantiates W3DRadar. Since GameEngine::init() now passes TheGlobalData->m_headless into createRadar(...), headless mode will still allocate the full radar subsystem. Please honor dummy here (e.g., return RadarDummy when dummy is true) to match the updated factory contract.
Restore the integer from_chars declarations in INI::scanType after upstream sync conflict resolution. The missing declarations left ec/result out of scope for non-floating-point instantiations, breaking Linux and Flatpak builds for Generals and GeneralsMD. Manual build validated successfully after this fix.
Summary
This PR performs a full upstream sync from
TheSuperHackers/mainintoGeneralsXand resolves merge/build regressions while preserving the cross-platform architecture.Upstream sync scope
Conflict resolution highlights
+numeric token compatibility from upstreamRenderStateStructfields and release all vertex streamsValidation performed
macos-vulkan)Risk areas for review
Notes