Created: 2026-02-07
Status: In Progress
Reference: references/fighter19-dxvk-port/
Understand fighter19's DXVK integration approach and confirm the hypothesis:
- Abstraction layer created, core code untouched
- DXVK translates DX8→Vulkan at runtime
- SDL3 replaces Win32 windowing
- Platform-specific code isolated
fighter19 did NOT modify core game logic. Instead, created wrapper/abstraction layers to intercept DX8 calls and translate to DXVK/SDL3.
If true, we can follow the same pattern for Zero Hour.
-
Where is the DXVK wrapper layer?
- Expected:
Core/GameEngineDevice/modifications - Check for DXVK header includes
- Check for compile-time switches (
#ifdef BUILD_WITH_DXVK)
- Expected:
-
How is SDL3 integrated?
- Window creation replacement
- Input handling
- Event loop modifications
-
What files were changed?
- List all modified files
- Categorize: Platform layer vs Core logic
- Zero Hour applicability notes
-
How is platform selection handled?
- Compile flags
- CMake presets
- Runtime detection
- Use
cognitionai/deepwikito query fighter19 repo - Ask: "Where is the DXVK wrapper implemented?"
- Ask: "How is SDL3 integrated without touching core code?"
- Ask: "What files were modified for Linux port?"
- Document wrapper architecture
- Identify DX8→DXVK translation points
- Check for existing abstraction interfaces
- Document window creation changes
- Document input handling changes
- Identify Win32 replacement patterns
- Confirm: Both Generals and Zero Hour covered
- List potential gotchas
- Document differences (if any)
Abstraction Pattern: DX8Wrapper class (thin insulation layer)
- Location:
GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp/h - Approach: Intercepts DirectX 8 calls WITHOUT modifying core game logic
- Runtime Loading: Dynamically loads
libdxvk_d3d8.soon Linux - Function:
DX8Wrapper::Init()loads DXVK, obtainsDirect3DCreate8pointer - Design: Direct wrapping (not high-level abstraction), preserves DX8 API surface
Key Files Modified:
CMakeLists.txt- Fetch DXVK libraryGeneralsMD/Code/CMakeLists.txt- Include DXVK headers, install runtime dependenciesGeneralsMD/Code/GameEngine/CMakeLists.txt- Add DXVK include directoriesGeneralsMD/Code/CompatLib/CMakeLists.txt- Defined3d8libinterface, link DXVKdx8wrapper.cpp/h- Implement wrapper class with dynamic loadingSDL3Main.cpp- SetDXVK_WSI_DRIVER="SDL3", load Vulkan library
Build System: FetchContent_Declare downloads dxvk-native-2.6 from GitHub
Abstraction Pattern: Inheritance-based abstraction
- Base Classes:
Mouse,Keyboard,GameEngine(abstract interfaces) - SDL3 Implementations:
SDL3Mouse,SDL3Keyboard,SDL3GameEngine(concrete) - Location:
GameEngineDevice/SDL3Device/subdirectories - Core Isolation: Game logic interacts with abstract interfaces ONLY
Key Components:
SDL3GameEngine::initializeAppWindows()- Creates SDL3 window viaSDL_CreateWindowSDL3GameEngine::serviceWindowsOS()- Polls events viaSDL_PollEvent, dispatches to input handlersSDL3Mouse::addSDLEvent()- Buffers SDL3 mouse eventsSDL3Mouse::getMouseEvent()- Translates to internalMouseIOformatSDL3Keyboard::addSDLEvent()- Buffers SDL3 keyboard eventsSDL3Keyboard::getKey()- Translates SDL keycodes toKeyDefTypewnd_compat.cpp- Win32 API compatibility layer (e.g.,SetWindowPos→ SDL3)
Compilation: SAGE_USE_SDL3 flag controls SDL3 vs Win32 device backend
Build System:
CMakeLists.txt- DXVK fetchingGeneralsMD/Code/CMakeLists.txt- DXVK headers/runtimeGameEngineDevice/CMakeLists.txt- Conditional SDL3 compilation
Graphics Layer:
Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp/h- DXVK wrapper
Windowing/Input Layer:
GameEngineDevice/SDL3Device/*- SDL3 implementationsCompatLib/wnd_compat.cpp- Win32→SDL3 translationMain/SDL3Main.cpp- Entry point, DXVK/SDL3 initialization
CMake Options (CMakeLists.txt):
SAGE_USE_DX8- Use DirectX 8 (Windows, default ON)SAGE_USE_SDL3- Use SDL3 windowing (Linux, OFF by default)SAGE_USE_OPENAL- Use OpenAL audio (conditional on FFMPEG)SAGE_USE_MILES- Use Miles Sound System (default ON)
Dependency Fetching:
if(SAGE_USE_DX8)
# Windows: Fetch min-dx8-sdk from GitHub
else()
# Linux: Fetch DXVK Native v2.6 from doitsujin/dxvk releases
FetchContent_Declare(
dxvk
URL https://github.com/doitsujin/dxvk/releases/download/v2.6/dxvk-native-2.6-steamrt-sniper.tar.gz
)
endif()CMakePresets.json - Key Presets:
-
linux64-deploy(PRIMARY LINUX TARGET):- Generator: Ninja
- Build Type: RelWithDebInfo
- vcpkg triplet:
x64-linux-dynamic - Sets:
SAGE_USE_SDL3: ON(enables SDL3) - Sets:
SAGE_USE_OPENAL: ON(OpenAL audio) - Sets:
SAGE_USE_FFMPEG: ON(video codec)
-
win32-deploy(Windows baseline):- Generator: Visual Studio 17 2022
- Architecture: Win32
- Uses DX8 + Miles (default)
-
linux64-testing(Debug variant):- Same as deploy but Debug build type
- Includes test building
Platform Definitions:
- Windows:
-D_WINDOWS -DWINVER=0x400 -D_WIN32_WINNT=0x0400 - Linux:
-D_LINUX -D_UNIX - macOS:
-D_MACOSX -D_UNIX
Based on generalsx.instructions.md, expected pattern:
// Core/GameEngineDevice/Include/w3dgraphicsdevice.h
#ifdef BUILD_WITH_DXVK
#include "dxvk_adapter.h"
#else
#include <d3d8.h>
#endifThis keeps Windows DX8 path intact while enabling Linux DXVK path.
- Verified: fighter19 port FULLY covers Zero Hour
SAGE_BUILD_ZEROHOURoption in CMakeLists.txtGeneralsMD/directory contains Zero Hour code- All DXVK/SDL3 changes apply to both Generals and Zero Hour
- Confirmed: Expansion-specific rendering handled correctly
- Same
dx8wrapper.cppfor both games - No Zero Hour-only DX8 usage identified
- Same
- Assessment: Direct port to our Zero Hour codebase is viable
File: GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp (line ~297)
// BEFORE (our code):
D3D8Lib = LoadLibrary("D3D8.DLL");
// AFTER (add ifdef):
#ifdef _WIN32
D3D8Lib = LoadLibrary("D3D8.DLL");
#else
D3D8Lib = LoadLibrary("libdxvk_d3d8.so");
#endifThat's the ONLY change to dx8wrapper.cpp! ✅
Entry Point:
GeneralsMD/Code/Main/SDL3Main.cpp- Replaces WinMain for Linux- Sets
DXVK_WSI_DRIVER=SDL3environment variable - Loads Vulkan library
- Creates window with
SDL_WINDOW_VULKANflag
- Sets
Device Layer (new directory: GameEngineDevice/SDL3Device/):
SDL3GameEngine.{h,cpp}- ExtendsGameEnginebase classSDL3Mouse.{h,cpp}- ExtendsMousebase classSDL3Keyboard.{h,cpp}- ExtendsKeyboardbase classSDL3CDManager.{h,cpp}- CD handling (stub on Linux)SDL3IMEManager.{h,cpp}- Input Method EditorSDL3OSDisplay.{h,cpp}- Display management
CMakeLists.txt:
- Add
SAGE_USE_SDL3option - Add DXVK FetchContent (when NOT
SAGE_USE_DX8) - Conditional compilation of SDL3Device sources
CMakePresets.json:
- Add
linux64-deploypreset withSAGE_USE_SDL3: ON - Set vcpkg triplet to
x64-linux-dynamic
fighter19 uses BOTH Miles (Windows) AND OpenAL (Linux) via conditional compilation:
SAGE_USE_MILES- Windows defaultSAGE_USE_OPENAL- Linux option (requires adaptation from jmarshall)
- fighter19 has WORKING graphics on Linux (native ELF) ✅
- Audio backend switchable (Miles vs OpenAL) ✅
- Zero Hour fully supported ✅
- This is our PRIMARY reference for graphics layer ✅
- Complexity: Lower than expected - dx8wrapper.cpp needs ONE ifdef change!
- Query fighter19 repo via DeepWiki
- Confirm abstraction layer approach
- Document wrapper pattern
- List all changed files with analysis