Skip to content

Latest commit

 

History

History
145 lines (112 loc) · 4.87 KB

File metadata and controls

145 lines (112 loc) · 4.87 KB

Phase 0: Current DX8 Renderer Architecture Analysis

Created: 2026-02-07 Status: In Progress

Objective

Document the current DirectX 8 rendering architecture in the TheSuperHackers baseline to understand:

  • Where DX8 device creation happens
  • Device lifecycle management
  • Rendering pipeline flow
  • Interface boundaries for abstraction

Research Questions

  1. Where does DX8 initialization occur?

    • Entry point: WinMain.cpp
    • Device creation flow: TBD
    • Window management: TBD
  2. What are the key DX8 interfaces used?

    • IDirect3D8 - Base interface
    • IDirect3DDevice8 - Rendering device
    • Texture/buffer/shader interfaces: TBD
  3. Where is the abstraction boundary?

    • Core game code should NOT call DX8 directly
    • Expected: Abstraction layer in Core/GameEngineDevice/
    • Confirm: fighter19/jmarshall kept core untouched

Investigation Plan

Step 1: Locate Device Creation

  • Search for D3D8 references in codebase
  • Find CreateDevice calls
  • Trace initialization from WinMain

Step 2: Map Device Management

  • Document device creation flow
  • Document reset/present patterns
  • Document shutdown sequence

Step 3: Identify Abstraction Layer

  • Check Core/GameEngineDevice/ structure
  • Look for wrapper classes
  • Confirm game logic isolation

Findings

DX8 Entry Points ✅ FOUND

Initialization Flow:

  1. Entry: DX8Wrapper::Init(void* hwnd, bool lite) (line 272)
  2. D3D8.DLL Loading: Dynamically loads D3D8.DLL via LoadLibrary()
  3. Function Pointer: Obtains Direct3DCreate8 via GetProcAddress()
  4. Interface Creation: D3DInterface = Direct3DCreate8Ptr(D3D_SDK_VERSION)
  5. Device Enumeration: Enumerate_Devices()
  6. Device Creation: Create_Device() (protected method)
  7. Subsystem Init: Do_Onetime_Device_Dependent_Inits() (line 405)

Key Static Members:

static IDirect3D8* D3DInterface;        // Base D3D8 interface
static IDirect3DDevice8* D3DDevice;     // Rendering device
static HINSTANCE D3D8Lib;               // D3D8.DLL handle
static Direct3DCreate8Type Direct3DCreate8Ptr; // Function pointer

Device Lifecycle:

  • Init → Create_Device → Do_Onetime_Device_Dependent_Inits
  • Shutdown → Release_Device → Release D3DInterface

Abstraction Layer Architecture ✅ CONFIRMED

Existing Wrapper: DX8Wrapper class already exists!

  • Location: GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.{h,cpp}
  • Purpose: "Thin insulation layer" for DX8 calls (4510 lines!)
  • Pattern: Static class with global state, not object-oriented abstraction
  • Usage: Game code calls DX8Wrapper:: methods, which call underlying DX8

Key Methods:

  • _Get_D3D_Device8() - Returns IDirect3DDevice8*
  • _Get_D3D8() - Returns IDirect3D8*
  • Begin_Scene(), End_Scene(), Present() - Rendering lifecycle
  • Texture/buffer/shader management
  • Render state caching (reduces redundant DX8 calls)

Game Logic Isolation ✅:

  • Game code uses DX8Wrapper:: interface
  • Core engine in Core/Libraries/Source/WWVegas/ uses wrapper
  • Direct DX8 calls ONLY in dx8wrapper.cpp

Example Usage (from W3DShaderManager.cpp line 2914):

IDirect3D8* d3d8Interface = DX8Wrapper::_Get_D3D8();

Files to Analyze

Primary DX8 Wrapper:

  • GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.h (1476 lines)
  • GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp (4510 lines)

Related Subsystems:

  • dx8caps.{h,cpp} - Capability detection
  • dx8fvf.{h,cpp} - Flexible Vertex Format
  • dx8vertexbuffer.{h,cpp} - Vertex buffer management
  • dx8indexbuffer.{h,cpp} - Index buffer management
  • dx8renderer.{h,cpp} - High-level rendering
  • dx8texman.{h,cpp} - Texture management

Device Management:

  • Core/GameEngineDevice/Source/W3DDevice/ - W3D device layer
  • Core/GameEngineDevice/Include/W3DDevice/ - W3D device headers

Entry Points:

  • GeneralsMD/Code/Main/WinMain.cpp - Application entry
  • Core/GameEngine/Source/ - Game engine initialization

fighter19 vs Our Codebase

Similarities:

  • Both have DX8Wrapper class (same heritage - EA Games source)
  • Both use static interface pattern
  • Both dynamically load D3D8.DLL

Differences (fighter19's DXVK port):

  • fighter19: Loads libdxvk_d3d8.so on Linux instead of D3D8.DLL
  • fighter19: Adds #ifdef BUILD_WITH_DXVK guards
  • fighter19: Adds SDL3 windowing integration
  • Our code: Pure Windows/DX8 (baseline from TheSuperHackers)

Notes

  • This is LEGACY code (20+ years old)
  • Patterns may be unconventional by modern standards
  • Focus on "where to insert abstraction" NOT "how to refactor"
  • Windows compatibility is NON-NEGOTIABLE

Next Steps

  1. Search codebase for DX8 references
  2. Map call flow from WinMain → Device creation
  3. Document existing abstraction (if any)
  4. Compare with fighter19's approach (DXVK wrapper pattern)