Skip to content

Latest commit

Β 

History

History
390 lines (305 loc) Β· 11.7 KB

File metadata and controls

390 lines (305 loc) Β· 11.7 KB

Phase 0: Complete fighter19 DXVK Port Analysis

Created: 2026-02-08
Status: Complete Investigation
Reference: references/fighter19-dxvk-port/


Executive Summary

fighter19 is a production-ready Linux port of C&C Generals Zero Hour with comprehensive compatibility layer. NOT just graphics - provides:

  1. βœ… Complete CompatLib - Windowsβ†’POSIX abstraction layer (threads, strings, time, file I/O, etc.)
  2. βœ… Graphics (DXVK) - DirectX 8 β†’ Vulkan via libdxvk_d3d8.so
  3. βœ… Windowing (SDL3) - Cross-platform window/input management
  4. ⚠️ Audio (OpenAL) - PARTIAL: Sound effects work, music/voices still broken
  5. ⚠️ Video - Has VideoDevice abstraction but status unclear
  6. βœ… D3DX8 Math - Using GLM library (open-source replacement)

1. CompatLib - The Missing Piece

Location

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]

Build Integration

# 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 modules

Key Implementation Examples

thread_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 stat

windows_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"

Our Current vs fighter19's Approach

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.)

2. Audio Subsystem - PARTIAL (not "broken")

Architecture

GameEngineDevice/Source/
β”œβ”€β”€ OpenALAudioDevice/      ← Linux implementation
β”‚   β”œβ”€β”€ OpenALAudioManager.h
β”‚   └── OpenALAudioManager.cpp
β”œβ”€β”€ MilesAudioDevice/       ← Windows implementation
β”‚   └── [Miles wrapper code]
└── StdDevice/              ← Fallback/stub

Status (from README)

What's working:
βœ… "Most sound effects"  

What's not working:
❌ "Music tracks and longer voice lines"

Analysis

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

Why Partially Broken?

Probable reasons:

  1. Miles Sound System format complexity - Miles has proprietary codecs/formats
  2. Audio streaming - Long tracks may use streaming, not simple buffers
  3. Timing/synchronization - Music timing might not match OpenAL implementation
  4. Miles-specific effects - Audio processing that OpenAL doesn't replicate 1:1

Phase 2 Strategy

// 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 cases

3. Video Playback - ABSTRACTED (status unknown)

Structure

GameEngineDevice/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 Consideration

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)

4. Graphics (DXVK) - Complete

βœ… Fully Documented Previously

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

5. D3DX8 Math Library - GLM-Based

Location

GeneralsMD/Code/CompatLib/
β”œβ”€β”€ Include/d3dx8math.h
└── Source/d3dx8math.cpp

Implementation Strategy

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 dependency

Our Situation

We haven't hit math issues yet because:

  1. Game logic uses DirectX math sparingly (wrapped in game code)
  2. Graphics math happens in DXVK (not our code)
  3. Simulation math is generic (no DirectX dependency)

When Phase 1 graphics integration happens, we may need this.


6. Comparison: Our approach vs fighter19

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 ⚠️ Partial (OpenAL)
Video Not yet ⚠️ Stubbed/unknown
Windows builds Preserved βœ… βœ… Still work (cross-compile friendly)
CI/CD Building βœ… GitHub Actions

7. Recommended Absorption Strategy

Phase 1 (Current - Graphics)

  • βœ… Continue with our current intrin_compat approach (minimal, focused)
  • βœ… Document fighter19 CompatLib as "future enhancement"
  • πŸ”„ Begin protecting graphics device headers (our current task)

Phase CompatLib-Migration (NEW - Between Phase 1 and 2)

  • 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

Phase 2 (Audio - Next)

  • 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

Phase 3 (Video - Future)

  • Investigate actual status (demo if possible)
  • Use fighter19's VideoDevice structure as baseline
  • Decide: Implement fully or stub for now

Phase 4+ (Polish)

  • Remaining CompatLib cleanup
  • Performance tuning
  • Edge case handling

8. Key Files to Monitor

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

9. README.md Status

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)

10. Decision Matrix for Our Implementation

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 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      β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Action Items

  • 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

References

  • fighter19 repo: references/fighter19-dxvk-port/
  • Current analysis: This document
  • Phase planning: docs/WORKDIR/phases/
  • Build references: cmake/, CMakePresets.json