Created: 2026-02-08
Status: Complete Investigation
Reference: references/fighter19-dxvk-port/
fighter19 is a production-ready Linux port of C&C Generals Zero Hour with comprehensive compatibility layer. NOT just graphics - provides:
- β Complete CompatLib - WindowsβPOSIX abstraction layer (threads, strings, time, file I/O, etc.)
- β Graphics (DXVK) - DirectX 8 β Vulkan via libdxvk_d3d8.so
- β Windowing (SDL3) - Cross-platform window/input management
β οΈ Audio (OpenAL) - PARTIAL: Sound effects work, music/voices still brokenβ οΈ Video - Has VideoDevice abstraction but status unclear- β D3DX8 Math - Using GLM library (open-source replacement)
GeneralsMD/Code/CompatLib/
βββ Include/
β βββ windows_compat.h β Main include multiplexer
β βββ types_compat.h β Windows types (HRESULT, HANDLE, etc.)
β βββ thread_compat.h β CreateThread β pthread
β βββ string_compat.h β _stricmp, itoa, lstrcat β POSIX
β βββ file_compat.h β _access, _stat β POSIX
β βββ time_compat.h β Windows time funcs
β βββ memory_compat.h β Memory management
β βββ wnd_compat.h β Window/display
β βββ gdi_compat.h β GDI drawing stubs
β βββ keyboard_compat.h β Input
β βββ wchar_compat.h β Unicode strings
β βββ module_compat.h β DLL loading
β βββ d3dx8math.h β D3DMATRIX, D3DVECTOR (GLM-based)
β βββ d3dx8core.h
β βββ [more files]
βββ Source/
βββ d3dx8_compat.cpp
βββ string_compat.cpp
βββ thread_compat.cpp
βββ time_compat.cpp
βββ wchar_compat.cpp
βββ wnd_compat.cpp
βββ module_compat.cpp
βββ [more implementations]
# GeneralsMD/Code/CompatLib/CMakeLists.txt
add_library(CompatLib STATIC ${SOURCE_COMPAT})
target_include_directories(CompatLib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/Include)
target_link_libraries(CompatLib PUBLIC d3d8lib) # DXVK library
# GeneralsMD/Code/CMakeLists.txt
add_subdirectory(CompatLib) # Built first, used by all other modulesthread_compat.h:
typedef pthread_t THREAD_ID;
THREAD_ID GetCurrentThreadId();
void* CreateThread(void *lpSecure, size_t dwStackSize,
start_routine lpStartAddress, void *lpParameter,
unsigned long dwCreationFlags, unsigned long *lpThreadId);
int TerminateThread(void *hThread, unsigned long dwExitCode);string_compat.h:
#define _stricmp strcasecmp
#define _strnicmp strncasecmp
#define _strdup strdup
#define lstrcat strcat
#define lstrcpy strcpy
#define lstrcmpi strcasecmp
extern "C" {
char* itoa(int value, char* str, int base);
char* _strlwr(char* str);
}file_compat.h:
#define _access access
#define _stat statwindows_compat.h:
#ifndef CALLBACK
#define CALLBACK
#endif
#ifndef WINAPI
#define WINAPI
#endif
#define __forceinline __attribute__((always_inline)) inline
static unsigned int GetDoubleClickTime() {
return 500;
}
#include "types_compat.h"
#include "thread_compat.h"
#include "tchar_compat.h"
#include "time_compat.h"
#include "string_compat.h"
#include "keyboard_compat.h"
#include "memory_compat.h"
#include "module_compat.h"
#include "wchar_compat.h"
#include "gdi_compat.h"
#include "wnd_compat.h"
#include "file_compat.h"| Area | Our Approach | fighter19 |
|---|---|---|
| Intrinsics | /Dependencies/Utility/intrin_compat.h |
/CompatLib/windows_compat.h |
| Scope | Math only (_isnan, _int64, etc.) |
Comprehensive (threads, I/O, strings, types) |
| Build | Included in PreRTS.h | Separate static library, linked to all modules |
| Organization | Single file | Multiple specialized headers + CMake lib |
| Thread safety | Not addressed | β Covered (pthread wrapper) |
| File I/O | Not addressed | β Covered (_access, _stat) |
| String funcs | Partial (via intrin_compat) | β Complete (itoa, _strlwr, etc.) |
GameEngineDevice/Source/
βββ OpenALAudioDevice/ β Linux implementation
β βββ OpenALAudioManager.h
β βββ OpenALAudioManager.cpp
βββ MilesAudioDevice/ β Windows implementation
β βββ [Miles wrapper code]
βββ StdDevice/ β Fallback/stub
What's working:
β
"Most sound effects"
What's not working:
β "Music tracks and longer voice lines"
Sound Effects (β working):
- Short, looping sounds
- Weapon fire, explosions, unit voices (short)
- Implemented in OpenALAudioManager
Music/Voices (β not working):
- Longer audio tracks
- Campaign music
- Long voice-overs
- Likely Miles-specific format not yet handled in OpenAL wrapper
Probable reasons:
- Miles Sound System format complexity - Miles has proprietary codecs/formats
- Audio streaming - Long tracks may use streaming, not simple buffers
- Timing/synchronization - Music timing might not match OpenAL implementation
- Miles-specific effects - Audio processing that OpenAL doesn't replicate 1:1
// fighters' approach (use as reference):
// OpenALAudioManager::PlayMusic(const char *filename)
// - Detects file format (WAV, OGG, etc.)
// - If Miles-specific: fall through to Miles backend
// - Else: decode and play via OpenAL
// Our Phase 2 should:
// 1. Copy OpenALAudioDevice structure (proven)
// 2. Extend for music streaming support
// 3. Add format detection/conversion
// 4. May still need Miles for some edge casesGameEngineDevice/Source/VideoDevice/
βββ VideoDevice.h
βββ VideoManager.h
βββ [specific implementations]
Status: Code exists, but README mentions NOTHING about video functionality
- Might work (not mentioned as broken)
- Might be stubbed (not implemented yet)
- README is incomplete on this
Phase 3.1: Research Video
- Determine actual status (working/broken/stubbed)
- Check fighter19 Issues/PRs if available
- Decide: Replace Bink? Use FFmpeg wrapper?
Phase 3.2: Implement Video
- Could use fighter19's VideoDevice wrapper
- Or: Stub for now (game works without videos)
See: docs/WORKDIR/support/phase0-fighter19-analysis.md
Key points:
dx8wrapper.cpp- Thin wrapper that loads libdxvk_d3d8.so- SDL3 for windowing/input
- D3DX8 math via GLM library
GeneralsMD/Code/CompatLib/
βββ Include/d3dx8math.h
βββ Source/d3dx8math.cpp
fighter19 replaced DirectX math library with GLM (open-source):
// d3dx8math.h - Wrapper around GLM
// D3DMATRIX β glm::mat4x4
// D3DVECTOR β glm::vec3/vec4
// D3DQUATERNION β glm::quat
// This allows:
// - Same API as DirectX math
// - Cross-platform (Linux/Windows)
// - No DirectX SDK dependencyWe haven't hit math issues yet because:
- Game logic uses DirectX math sparingly (wrapped in game code)
- Graphics math happens in DXVK (not our code)
- Simulation math is generic (no DirectX dependency)
When Phase 1 graphics integration happens, we may need this.
| Component | Our Phase 1 | fighter19 |
|---|---|---|
| Build system | CMake presets (same) | β |
| Compatibility layer | Minimal (intrin_compat.h) | β Comprehensive (CompatLib) |
| Graphics (DXVK) | Stubs + protects | β Full integration |
| Windowing (SDL3) | Not yet | β Integrated |
| Audio | Not yet | |
| Video | Not yet | |
| Windows builds | Preserved β | β Still work (cross-compile friendly) |
| CI/CD | Building | β GitHub Actions |
- β Continue with our current intrin_compat approach (minimal, focused)
- β Document fighter19 CompatLib as "future enhancement"
- π Begin protecting graphics device headers (our current task)
- Review fighter19's CompatLib structure
- Decide: Adopt wholesale vs. cherry-pick
- Refactor
intrin_compat.hβ Full CompatLib if beneficial - Update CMakeLists.txt for static library linking
- Validate Windows builds still work
- USE fighter19's OpenALAudioDevice directly (don't rewrite)
- Copy source files from
GameEngineDevice/Source/OpenALAudioDevice/ - Extend for music streaming support
- Reference implementation: proven in production
- Investigate actual status (demo if possible)
- Use fighter19's VideoDevice structure as baseline
- Decide: Implement fully or stub for now
- Remaining CompatLib cleanup
- Performance tuning
- Edge case handling
If updating from fighter19 upstream:
GeneralsMD/Code/CompatLib/ β Watch for updates
GeneralsMD/Code/GameEngineDevice/ β Audio/video changes
GeneralsMD/Code/CMakeLists.txt β Build config changes
resources/ β Build resources
Confirmed: README is INCOMPLETE, not necessarily wrong:
- β "Most sound effects" = correct (OpenAL working)
- β "Music tracks and longer voice lines" = correct (not working yet)
- π€ "Video" = MISSING from README (status unknown)
Should update fighter19's README to clarify:
- Audio status (partial, specific formats broken)
- Video status (if implemented, what formats work)
- CompatLib scope (not just graphics)
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Should we use fighter19's component? β
ββββββββββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββ€
β CompatLib (threads/strings/etc) β DEFER to Phase CompatLib β
β Graphics (DXVK wrapper) β BEGIN Phase 1 (now) β
β SDL3 (windowing) β INTEGRATE Phase 1 β
β Audio (OpenAL) β COPY Phase 2 β
β D3DX8 Math (GLM) β COPY Phase 1 (if needed) β
β Video β INVESTIGATE Phase 3 β
ββββββββββββββββββββββββββββββββββββββ΄βββββββββββββββββββββββββββ
- Add fighter19 CompatLib to Phase CompatLib-Migration plan
- Document audio limitations (music/voices)
- Investigate video status (open issue on fighter19?)
- Begin Phase 1: Graphics device header protection
- Commission Phase 2: Audio work (reference fighter19)
- Add CompatLib review to post-Phase 1 checklist
- fighter19 repo:
references/fighter19-dxvk-port/ - Current analysis: This document
- Phase planning:
docs/WORKDIR/phases/ - Build references:
cmake/,CMakePresets.json