Skip to content

Conversation

@BasharShehab
Copy link

Overview

This PR completes the Linux x86-64 Vulkan port of GeneralsXZH with all linker errors resolved. The game now compiles and links successfully, producing a 179MB executable. However, this is only for the build. Many functions are only stubs and placeholders.

DISCLAIMER

  • I'm a junior developer and this is the first time I work with c/c++, so please let me know if I did a bad job or if anything needs fixing. I'm willing to learn and help further to get this game running on Linux.

Status

  • Build Status: Compiles and links successfully on Linux x86-64
  • Executable Generated: /build/linux/GeneralsMD/GeneralsXZH (179MB)
  • ⚠️ Runtime Testing: Not yet performed (needs asset setup)

Changes Summary (149 files)

Core Graphics & Math

  • D3DX8 math compatibility layer (vectors, matrices, transforms)
  • DirectX type stubs for Vulkan backend

Type System & Compatibility

  • __int64int64_t migrations
  • ByteSignedByte type fixes because of conflict with Byte definition in used libraries like zlib
  • STL compatibility (WWMath::Min/Maxstd::min/std::max)

Platform Abstraction

  • Full RegistryClass stub implementation (non-Windows)
  • glibc 2.40+ compatibility fixes
  • GameSpy SDK duplicate symbol removal

Build System

  • Fixed linker dependencies and library ordering
  • Updated CMake configuration for Linux builds

Known Limitations

  • Not tested at runtime - executable exists but hasn't been run yet
  • Commit history is messy - everything was added in 1 or 2 commits, as I was fixing build errors one by one.
  • Game assets required - needs .big files from retail game to test properly. Will report back if I manage to launch the game.

How to Test

cmake --preset linux
cmake --build build/linux --target GeneralsXZH -j 4

Phase 54: Comprehensive Linux x86-64 compatibility fixes for GeneralsXZH.

## D3DX8 Math Compatibility (d3dx8_vulkan_math_compat.h)
- Add D3DXVECTOR3(x,y,z) and D3DXVECTOR4(x,y,z,w) constructors
- Add D3DXMATRIX 16-float constructor for matrix initialization
- Add D3DXVec4Dot() and D3DXVec4Transform() functions
- Re-enable BezierSegment.cpp/h with cross-platform D3DX8 math

## Type System Migrations
- Replace __int64 with int64_t across ~30 files (Win64 compatibility)
- Replace Byte with SignedByte in locomotor/physics code
- Fix signed/unsigned comparison warnings

## STL Compatibility
- Migrate WWMath::Min/Max to std::min/std::max (~40 files)
- Comment out conflicting min/max templates in wwmath.h
- Add <algorithm> includes where needed

## Registry Stubs (phase43_registry_stubs.cpp)
- Implement full RegistryClass interface matching registry.h
- Add Exists(), Get_Int(), Set_Int(), Get_String(), Set_String()
- Add Get_Binary(), Set_Binary(), Delete_Value(), Delete_Key()
- Return sensible defaults for non-Windows platforms

## WW3D Wrapper (vulkan_ww3d_wrapper.cpp)
- Fix WW3D::Render() signature: SceneClass*, CameraClass*
- Fix WW3D::Flush() signature: RenderInfoClass&
- Add TextureFilterClass stubs: Apply(), Set_Default_Min/Mag_Filter()
- Add missing WW3D namespace functions

## glibc 2.40+ Compatibility (stringex.h)
- Add conditional declarations for wcslcpy/wcslcat
- Prevent conflicts with glibc's new wchar.h definitions
- Use __GLIBC_PREREQ macro for version detection

## GameSpy SDK Fixes
- Remove duplicate globals from phase43_5_gamespy_globals.cpp
- Variables moved: TheGameSpyGame, TheGameSpyInfo, GameSpyColor,
  parseWebpageURLDefinition, and 10+ other duplicates
- Add cmake/gamespy.cmake patches for min/max conflicts

## Build System Updates
- Fix OpenAL linking order in CMakeLists.txt
- Update library dependencies for Linux builds
- Add proper include paths for cross-platform headers

## Header Reorganization
- Rename debug.h to debug_renamed.h (conflict resolution)
- Add CrossPlatformOSDisplay.cpp for display abstraction
- Update include guards and paths

Build verified: 179MB ELF x86-64 executable generated successfully.

Refs: Phase 54 - Linux Vulkan Port
This commit fixes critical issues preventing the game from loading INI files
and other assets from .big archives on Linux.

## Root Cause
.big archive files created on Windows store internal paths with backslash
separators (e.g., 'Data\INI\Default\GameData.ini'). The Linux build was
using GET_PATH_SEPARATOR() which returns '/' on Linux, causing path
tokenization failures throughout the archive system.

## Key Fixes

### New Macro: GET_BIG_FILE_SEPARATOR()
- Added to Dependencies/Utility/Utility/compat.h
- Always returns "\\" regardless of platform
- Used consistently for all .big file internal path operations

### BIG File Header Parsing (StdBIGFileSystem.cpp, Win32BIGFileSystem.cpp)
- Fixed path/filename splitting to use backslash instead of platform separator
- Files now correctly split: path='Data\INI\Default\' + filename='GameData.ini'

### Archive Directory Tree (ArchiveFile.cpp)
- Fixed getFileListInDirectory() to use GET_BIG_FILE_SEPARATOR()
- Fixed getArchivedFileInfo() path normalization
- Added null-terminator fix for normalized path buffer (was causing garbage
  bytes in file lookup keys)
- Added lowercase conversion for filename keys in addFile()

### Archive File System (ArchiveFileSystem.cpp)
- Fixed loadIntoDirectoryTree() to use backslash separators
- Fixed getArchivedDirectoryInfo() path normalization
- Consistent use of GET_BIG_FILE_SEPARATOR() for all tokenization

### StdBIGFile.cpp
- Added path normalization (forward slash to backslash) before file lookup

## Debug Build Support
- Added linux-debug preset to CMakePresets.json for -O0 builds
- Fixed linker errors for debug mode:
  - Added ApplicationHInstance definition for non-Windows
  - Added CComModuleStub for ATL _Module compatibility
  - Added -fPIC flags for position-independent code
  - Added WW3D static member definitions in Vulkan wrapper

## Other Fixes
- Fixed GET_PATH_SEPARATOR() character extraction in multiple files
- Updated scripts for dynamic path discovery (check_compat_includes.fish,
  add_compat_includes.py)

## Result
INI files and other assets now load correctly from .big archives on Linux.
87+ files confirmed opening successfully during game initialization.

Refs: Cross-platform VFS compatibility for Linux port
…g VertexMaterialClass in Vulkan wrapper

CRITICAL FIX: Terrain initialization crash on all platforms using Vulkan backend

## Problem Analysis

When creating TerrainVisual on Linux (Vulkan backend), game crashed in W3DBridgeBuffer::allocateBridgeBuffers()
with segmentation fault during VertexMaterialClass::Get_Preset() call. Root cause chain:

1. ww3d.cpp excluded from CMakeLists.txt - Vulkan wrapper provides stub implementations
2. Vulkan wrapper's WW3D::Init() was incomplete - returned immediately without initialization
3. VertexMaterialClass::Init() never called - left static Presets[] array uninitialized (all NULL)
4. W3DBridgeBuffer tried to access Presets[PRELIT_DIFFUSE]->Add_Ref() on NULL pointer → SIGSEGV

## Solution Implementation

### File: Core/Libraries/Source/Graphics/Vulkan/vulkan_ww3d_wrapper.cpp

1. **Moved VertexMaterialClass definition before WW3D namespace** (lines 37-50)
   - Placed full class definition with Init()/Shutdown() static methods
   - Allows Vulkan wrapper to call initialization during WW3D::Init()
   - Removed duplicate definition at end of file

2. **Enhanced WW3D::Init()** (lines 85-102)
   - Added call to VertexMaterialClass::Init() with debug logging
   - Debug output: `[Vulkan WW3D Wrapper] Calling VertexMaterialClass::Init()`
   - Critical for terrain rendering - presets must be initialized before any render objects created
   - Uses fprintf(stderr) + fflush(stderr) for immediate visibility

3. **Enhanced WW3D::Shutdown()** (lines 104-117)
   - Added call to VertexMaterialClass::Shutdown() with debug logging
   - Ensures proper cleanup when graphics subsystem shuts down

4. **Code formatting cleanup**
   - Normalized indentation from mixed 4/8-space to consistent 2-space (Vulkan wrapper style)
   - No functional changes to other stub functions

### File: GeneralsMD/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DBridgeBuffer.cpp

1. **Added comprehensive debug logging to W3DBridgeBuffer::allocateBridgeBuffers()** (lines 773-788)
   - Logs: buffer creation, material preset retrieval, pointer values
   - Output example: `[W3DBridgeBuffer::allocateBridgeBuffers] m_vertexMaterial=0x559e5e04a2c0`
   - Validates VertexMaterialClass presets are properly initialized

2. **Constructor debug logging** (lines 748-751)
   - Added entry/exit logging for constructor flow tracking
   - Shows allocateBridgeBuffers() call sequence

3. **Code formatting improvements**
   - Fixed pointer declaration spacing: `DX8IndexBufferClass *` → `DX8IndexBufferClass*`
   - Normalized spacing around operators: `a+b` → `a + b`, `if(x)` → `if (x)`
   - Fixed alignment in parameter lists (100+ instances)
   - Applied consistent indentation throughout

### File: GeneralsMD/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DTerrainVisual.cpp

1. **Constructor/Initialization debug logging** (lines 161, 219-222, 219-222)
   - Added entry/exit markers for W3DTerrainVisual::init()
   - Logs: TerrainVisual parent init, HeightMapRenderObjClass creation
   - Traces initialization order and object pointers

2. **Code formatting standardization**
   - Fixed seismic simulation code indentation (entire TestSeismicFilter class)
   - Normalized spacing in method signatures: `void init( void )` → `void init(void)`
   - Fixed pointer declaration style throughout (150+ instances)
   - Aligned complex parameter lists and conditional blocks

## Verification

**Build Result**: ✅ SUCCESS (linux-debug configuration)
- Compiled: Core graphics_drivers.a library
- Compiled: GeneralsXZH executable

**Deployment Result**: ✅ SUCCESS
- Binary deployed to ~/GeneralsX/GeneralsMD/GeneralsXZH

**Test Result**: ✅ SUCCESS - No SIGSEGV
Debug output showed:
[Vulkan WW3D Wrapper] Calling VertexMaterialClass::Init()
[Vulkan WW3D Wrapper] VertexMaterialClass::Init() completed
[W3DBridgeBuffer::allocateBridgeBuffers] m_vertexMaterial=0x559e5e04a2c0
[W3DTerrainVisual::init] HeightMapRenderObjClass created: 0x559e5df66668
[W3DTerrainVisual::init] HeightMapRenderObjClass setup done
- Game initialized past TerrainVisual without crash
- Progression blocked at graphics driver stage (separate Phase 39/50 issue)

## Initialization Order (Fixed)
GameClient::init()
↓
TheDisplay->init() [W3DDisplay::init]
↓
WW3D::Init() [Vulkan wrapper] ← NOW CALLS:
↓
VertexMaterialClass::Init() ← FIXED
↓
createTerrainVisual()
↓
W3DTerrainVisual::init()
↓
NEW_REF(HeightMapRenderObjClass)
↓
W3DBridgeBuffer::allocateBridgeBuffers() ← NOW SUCCEEDS

## Impact

- **Fixes SIGSEGV on Linux/Vulkan for all terrain-dependent maps**
- **Enables further graphics subsystem initialization**
- **Maintains compatibility with DirectX/Windows path (unaffected)**
- **Applies to both GeneralsXZH (primary) and GeneralsX (secondary) targets**
- **Debug logging essential for Phase 39+ graphics driver development**

## Files Changed

- Core/Libraries/Source/Graphics/Vulkan/vulkan_ww3d_wrapper.cpp
- GeneralsMD/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DBridgeBuffer.cpp
- GeneralsMD/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DTerrainVisual.cpp

## Phase Reference

- Phase 5-6: TerrainVisual crash investigation and fix
- Phase 28.4: Texture loading (fixed in this cycle)
- Phase 39.x: Graphics driver initialization (next blocker)
- Remove macOS-only ifdef guard around SDL_Vulkan_CreateSurface() call
  in VulkanSwapchain::Create(), making surface creation cross-platform
- Add Linux-specific instance extension query using
  SDL_Vulkan_GetInstanceExtensions() to dynamically request the correct
  surface extensions (X11/Wayland) based on SDL's window system
- Remove dead VK_USE_PLATFORM_XCB_KHR code path now handled by SDL query
- Add NULL window handle validation and improved debug logging

The graphics driver now initializes successfully on Linux:
- Vulkan instance, physical device, and logical device created
- Swapchain created with 4 images at 800x600
- SetGraphicsDriver() registers driver globally
- 69+ vertex/index buffers created for terrain rendering
- Textures loading correctly

This fixes the SIGSEGV crash caused by GetGraphicsDriver() returning
NULL when buffer classes tried to use the uninitialized driver.
…ig files) from using / to using \\ again (paths inside .big files are hardcoded). Will implement a way to standardize this later.
…idMemPass() returns true/false accourding to available memory.
…an integration

This commit enables Linux gameplay by fixing critical cross-platform issues:

SYSTEM DETECTION FIXES:
- Fix memory detection: Use sysconf(_SC_PHYS_PAGES * _SC_PAGE_SIZE) on Unix/Linux
  instead of Windows-only GlobalMemoryStatusEx in cpudetect.cpp
- Fix CPU frequency detection: Use CPUDetectClass::Get_Processor_Speed() on all
  platforms in W3DShaderManager.cpp (was hardcoded to 0 on non-Windows)
- Enable RTS_HAS_FFMPEG by default in cmake/config-build.cmake

WINDOW VISIBILITY FIXES:
- Add explicit SDL_ShowWindow(), SDL_RaiseWindow(), SDL_SetInputFocus() calls
  after window creation in WinMain.cpp and W3DDisplay.cpp
- Fix SDL_CreateWindow() parameter order (add x, y coordinates)

WW3D RENDERING PIPELINE INTEGRATION:
- Re-enable ww3d.cpp (WW3D class) instead of vulkan_ww3d_wrapper.cpp (namespace)
- ww3d.cpp uses DX8Wrapper_Stubs.cpp which provides proper Vulkan bridge
- Remove vulkan_ww3d_wrapper.cpp from build to avoid multiple definition errors
- Keep FastAllocator.cpp in build (incorrectly excluded for USE_VULKAN)

RESULT: Game now compiles on Linux and displays visible window. didMemPass()
correctly returns true, rendering pipeline connected via DX8Wrapper_Stubs.

Files modified:
- cmake/config-build.cmake: FFmpeg default ON
- Core/Libraries/Source/WWVegas/WWLib/cpudetect.cpp: sysconf-based memory detection
- Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DShaderManager.cpp:
  Cross-platform CPU/memory detection
- Core/Libraries/Source/WWVegas/WW3D2/win32_sdl_api_compat.cpp: SDL parameter fix
- GeneralsMD/Code/Main/WinMain.cpp: Window visibility calls
- GeneralsMD/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DDisplay.cpp:
  SDL2 include, window visibility, debug logging
- Core/Libraries/Source/Graphics/CMakeLists.txt: vulkan_ww3d_wrapper.cpp removed
- Core/Libraries/Source/WWVegas/WW3D2/CMakeLists.txt: ww3d.cpp re-enabled
- Core/Libraries/Source/WWVegas/WWLib/CMakeLists.txt: FastAllocator.cpp kept

Refs: Phase 54 - Linux Vulkan Rendering Pipeline
@BasharShehab
Copy link
Author

I also realised that I commited some random files because my cpp formatter changed the files formatting and I didn't notice. Feel free to not include these files.

@BasharShehab
Copy link
Author

I'm unsure why the loading screen and main menu are not showing, but the game now compiles on Linux and plays the EA logo and sizzle with ffmpeg, skippable by hitting ESC. Will keep investigating to understand how to land into game UI.

…s. Now we finally have the loading screen and the main menu rendering, although with some glitches.
@BasharShehab
Copy link
Author

titlescreen with loading progress bar rendering now, and we fade into the main menu successfully, although there are still some weird texture glitches. Will keep working on it.

@BasharShehab
Copy link
Author

Screenshot_20251207_203142

If anyone has a clue about these glitches, please let me know. I also suspect it has to do with fonts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant