paavohtl Claude Opus 4.6 commited on
Commit
ed63829
Β·
1 Parent(s): e454eb7

Add DDGame engine architecture structs and subsystem types

Browse files

Define DDGame (0x98B8), DDGameWrapper, PCLandscape, DSSound, and
OpenGLState repr(C) structs with compile-time size assertions.
Add 9 subsystem vtable addresses to address.rs. Document the
engine initialization chain and update memory map with DDGame layout.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

crates/openwa-types/src/address.rs CHANGED
@@ -26,6 +26,24 @@ pub mod va {
26
  pub const CGAMETASK_VTABLE: u32 = 0x0066_41F8;
27
  /// CGameTask secondary vtable (at object offset 0xE8)
28
  pub const CGAMETASK_VTABLE2: u32 = 0x0066_9CF8;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
 
30
  // === CTask vtable methods (at CTask__vtable) ===
31
 
 
26
  pub const CGAMETASK_VTABLE: u32 = 0x0066_41F8;
27
  /// CGameTask secondary vtable (at object offset 0xE8)
28
  pub const CGAMETASK_VTABLE2: u32 = 0x0066_9CF8;
29
+ /// DDGameWrapper vtable
30
+ pub const DDGAME_WRAPPER_VTABLE: u32 = 0x0066_A30C;
31
+ /// GfxHandler vtable (0x19C-byte objects)
32
+ pub const GFX_HANDLER_VTABLE: u32 = 0x0066_B280;
33
+ /// DisplayGfx vtable
34
+ pub const DISPLAY_GFX_VTABLE: u32 = 0x0066_4144;
35
+ /// PCLandscape vtable
36
+ pub const PC_LANDSCAPE_VTABLE: u32 = 0x0066_B208;
37
+ /// LandscapeShader vtable
38
+ pub const LANDSCAPE_SHADER_VTABLE: u32 = 0x0066_B1DC;
39
+ /// DSSound vtable
40
+ pub const DS_SOUND_VTABLE: u32 = 0x0066_AF20;
41
+ /// TaskStateMachine vtable
42
+ pub const TASK_STATE_MACHINE_VTABLE: u32 = 0x0066_4118;
43
+ /// OpenGLCPU vtable (0x48-byte object)
44
+ pub const OPENGL_CPU_VTABLE: u32 = 0x0067_74C0;
45
+ /// WaterEffect vtable (0xBC-byte object)
46
+ pub const WATER_EFFECT_VTABLE: u32 = 0x0066_B268;
47
 
48
  // === CTask vtable methods (at CTask__vtable) ===
49
 
crates/openwa-types/src/ddgame.rs ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ use crate::task::Ptr32;
2
+
3
+ /// DDGame β€” the main game engine object.
4
+ ///
5
+ /// This is a massive ~39KB struct (0x98B8 bytes) that owns all major subsystems:
6
+ /// display, landscape, sound, graphics handlers, and task state machines.
7
+ ///
8
+ /// Allocated in DDGame__Constructor (0x56E220).
9
+ /// Vtable set via DDGameWrapper at 0x66A30C.
10
+ ///
11
+ /// PARTIAL: Only landmark offsets are defined. The vast majority of fields
12
+ /// are unknown. Use the offset constants below for field access.
13
+ ///
14
+ /// Note: Ghidra decompiles DDGame constructor with DWORD-indexed offsets
15
+ /// (param_2[0x122] etc.), but these are byte offsets in the struct below.
16
+ /// Conversion: dword_index * 4 = byte_offset.
17
+ #[repr(C)]
18
+ pub struct DDGame {
19
+ /// 0x0000-0x0023: Header region
20
+ pub _header: [u8; 0x24],
21
+ /// 0x0024: Game state pointer
22
+ pub game_state: Ptr32,
23
+ /// 0x0028: Unknown parameter from constructor
24
+ pub _param_28: Ptr32,
25
+ /// 0x002C-0x11AF: Unknown fields
26
+ pub _unknown_002c: [u8; 0x1184],
27
+ /// 0x11B0-0x11BF: Task objects region (5 state machine pointers)
28
+ /// Ghidra: param[0x46C..0x47C] (dword-indexed)
29
+ pub task_ptrs: [Ptr32; 5],
30
+ /// 0x11C4-0x1217: Unknown
31
+ pub _unknown_11c4: [u8; 0x54],
32
+ /// 0x1218-0x1223: Game global / WormKit-known offsets area
33
+ /// Note: WormKit documents DDGame+0x488 as game_global, but that's
34
+ /// relative to the DDGame ptr held in DDGameWrapper[0x122].
35
+ /// Since DDGameWrapper[0x122] points to THIS struct at offset 0,
36
+ /// these WormKit offsets map directly.
37
+ pub _unknown_1218: [u8; 0x270],
38
+ /// 0x1488-0x3547: Unknown fields
39
+ pub _unknown_1488: [u8; 0x20C0],
40
+ /// 0x3548: Display mode pointer
41
+ pub display_mode: Ptr32,
42
+ /// 0x354C: Display width
43
+ pub display_width: u32,
44
+ /// 0x3550: Display param (init 0)
45
+ pub _display_3550: u32,
46
+ /// 0x3554: Display param (init 0)
47
+ pub _display_3554: u32,
48
+ /// 0x3558-0x355F: Unknown
49
+ pub _unknown_3558: [u8; 8],
50
+ /// 0x3560: Display center X (width / 2)
51
+ pub display_center_x: u32,
52
+ /// 0x3564: Display center Y (height / 2)
53
+ pub display_center_y: u32,
54
+ /// 0x3568-0x3577: Unknown
55
+ pub _unknown_3568: [u8; 0x10],
56
+ /// 0x3578: Window handle (HWND)
57
+ pub hwnd: Ptr32,
58
+ /// 0x357C-0x358C: Unknown
59
+ pub _unknown_357c: [u8; 0x11],
60
+ /// 0x358D-0x398C: Palette entries (0x100 * 4 = 1024 bytes)
61
+ pub palette: [u8; 0x400],
62
+ /// 0x398D-0x3D8F: Unknown display fields
63
+ pub _unknown_398d: [u8; 0x403],
64
+ /// 0x3D90: Graphics constant (init 0x100)
65
+ pub _gfx_3d90: u32,
66
+ /// 0x3D94: Graphics constant (init 0xFFFFFFFF)
67
+ pub _gfx_3d94: u32,
68
+ /// 0x3D98: Graphics object pointers (4 entries)
69
+ pub gfx_objects: [Ptr32; 4],
70
+ /// 0x3DA8-0x98B7: Remaining fields
71
+ pub _unknown_3da8: [u8; 0x5B10],
72
+ }
73
+
74
+ const _: () = assert!(core::mem::size_of::<DDGame>() == 0x98B8);
75
+
76
+ /// Well-known byte offsets into DDGame, for use with raw pointer access.
77
+ ///
78
+ /// These are sourced from WormKit, wkJellyWorm, and Ghidra decompilation.
79
+ /// WormKit documents offsets relative to DDGameWrapper[0x122] which points
80
+ /// to the DDGame allocation.
81
+ pub mod offsets {
82
+ /// Game state pointer
83
+ pub const GAME_STATE: usize = 0x0024;
84
+
85
+ /// Task state machine pointers (5 entries, each Ptr32)
86
+ pub const TASK_PTRS: usize = 0x11B0;
87
+
88
+ /// Display mode pointer
89
+ pub const DISPLAY_MODE: usize = 0x3548;
90
+ /// Display width
91
+ pub const DISPLAY_WIDTH: usize = 0x354C;
92
+ /// Display center X
93
+ pub const DISPLAY_CENTER_X: usize = 0x3560;
94
+ /// Display center Y
95
+ pub const DISPLAY_CENTER_Y: usize = 0x3564;
96
+ /// Window handle (HWND)
97
+ pub const HWND: usize = 0x3578;
98
+ /// Palette start (0x400 bytes)
99
+ pub const PALETTE: usize = 0x358D;
100
+
101
+ /// Graphics object pointers (from DDDisplay__Init)
102
+ pub const GFX_OBJECTS: usize = 0x3D98;
103
+ }
crates/openwa-types/src/ddgame_wrapper.rs ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ use crate::task::Ptr32;
2
+
3
+ /// DDGameWrapper β€” thin wrapper around DDGame.
4
+ ///
5
+ /// This is the top-level object created by DDGameWrapper__Constructor (0x56DEF0).
6
+ /// It holds a pointer to the DDGame allocation and graphics handler references.
7
+ ///
8
+ /// Vtable: 0x66A30C
9
+ ///
10
+ /// Note: Ghidra shows DWORD-indexed offsets (param_1[0x122] etc.).
11
+ /// Byte offset = dword_index * 4.
12
+ ///
13
+ /// PARTIAL: Only confirmed fields from the constructor are defined.
14
+ #[repr(C)]
15
+ pub struct DDGameWrapper {
16
+ /// 0x000: Vtable pointer (0x66A30C)
17
+ pub vtable: Ptr32,
18
+ /// 0x004-0x487: Unknown fields
19
+ pub _unknown_004: [u8; 0x484],
20
+ /// 0x488: Pointer to DDGame allocation
21
+ pub ddgame: Ptr32,
22
+ /// 0x48C: Secondary DDGame struct pointer (0x2C bytes, conditional)
23
+ pub ddgame_secondary: Ptr32,
24
+ /// 0x490-0x4BF: Unknown
25
+ pub _unknown_490: [u8; 0x30],
26
+ /// 0x4C0: Graphics handler 0 pointer (0x19C bytes, vtable 0x66B280)
27
+ pub gfx_handler_0: Ptr32,
28
+ /// 0x4C4: Graphics handler 1 pointer (optional)
29
+ pub gfx_handler_1: Ptr32,
30
+ /// 0x4C8: Graphics mode flag
31
+ pub gfx_mode: u32,
32
+ /// 0x4CC: PCLandscape object pointer
33
+ pub landscape: Ptr32,
34
+ /// 0x4D0: Constructor param_2
35
+ pub _param_4d0: u32,
36
+ /// 0x4D4: Constructor param_3
37
+ pub _param_4d4: u32,
38
+ /// 0x4D8-end: Unknown trailing fields
39
+ /// Size uncertain β€” DDGameWrapper total size not yet determined
40
+ pub _unknown_4d8: [u8; 0x28],
41
+ }
42
+
43
+ // DDGameWrapper total size is uncertain. This is a minimum based on known fields.
44
+ // Remove or update this assertion when the true size is determined.
45
+ const _: () = assert!(core::mem::size_of::<DDGameWrapper>() == 0x500);
crates/openwa-types/src/dssound.rs ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ use crate::fixed::Fixed;
2
+ use crate::task::Ptr32;
3
+
4
+ /// DSSound β€” DirectSound audio subsystem.
5
+ ///
6
+ /// Created by DSSound__Constructor (0x573D50).
7
+ /// Vtable: 0x66AF20
8
+ ///
9
+ /// Manages sound playback through DirectSound.
10
+ /// Has 500 sound channel slots and a master volume control.
11
+ ///
12
+ /// PARTIAL: Only constructor-confirmed fields.
13
+ /// Ghidra uses DWORD-indexed offsets.
14
+ #[repr(C)]
15
+ pub struct DSSound {
16
+ /// 0x000: Vtable pointer (0x66AF20)
17
+ pub vtable: Ptr32,
18
+ /// 0x004: Unknown
19
+ pub _unknown_004: [u8; 4],
20
+ /// 0x008: Init field (set to 0)
21
+ pub _field_008: u32,
22
+ /// 0x00C: Init field (set to 0)
23
+ pub _field_00c: u32,
24
+ /// 0x010: Init field (set to 0)
25
+ pub _field_010: u32,
26
+ /// 0x014-0x8A3: Unknown fields
27
+ pub _unknown_014: [u8; 0x890],
28
+ /// 0x8A4: Master volume (Fixed, init 0x10000 = 1.0)
29
+ pub volume: Fixed,
30
+ /// 0x8A8-0xBB3: Unknown (includes 500-entry channel slot table)
31
+ pub _unknown_8a8: [u8; 0x30C],
32
+ /// 0xBB4: Status flag 1 (init 1)
33
+ pub status_1: u32,
34
+ /// 0xBB8: Status flag 2 (init 1)
35
+ pub status_2: u32,
36
+ /// 0xBBC: Status flag 3 (init 0)
37
+ pub status_3: u32,
38
+ /// 0xBC0-end: Unknown trailing fields
39
+ pub _unknown_bc0: [u8; 0x10],
40
+ }
41
+
42
+ // Total size uncertain β€” this is an estimate based on constructor analysis.
43
+ // The 500 dword channel table starts around offset 0xD4+ but exact layout unclear.
44
+ const _: () = assert!(core::mem::size_of::<DSSound>() == 0xBD0);
crates/openwa-types/src/landscape.rs ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ use crate::task::Ptr32;
2
+
3
+ /// PCLandscape β€” terrain/landscape subsystem.
4
+ ///
5
+ /// Created by PCLandscape__Constructor (0x57ACB0).
6
+ /// Vtable: 0x66B208
7
+ ///
8
+ /// Manages terrain data, water effects, and level graphics.
9
+ /// Loads Water.dir and Level.dir from `data\Gfx\`.
10
+ /// Allocates a 384KB (0x60000) terrain buffer.
11
+ ///
12
+ /// PARTIAL: Only constructor-confirmed fields are defined.
13
+ /// Ghidra uses DWORD-indexed offsets (param_1[0x240] etc.).
14
+ /// Byte offset = dword_index * 4.
15
+ #[repr(C)]
16
+ pub struct PCLandscape {
17
+ /// 0x000: Vtable pointer (0x66B208)
18
+ pub vtable: Ptr32,
19
+ /// 0x004: Parent DDGame pointer
20
+ pub ddgame: Ptr32,
21
+ /// 0x008-0x0C7: Unknown
22
+ pub _unknown_008: [u8; 0xC0],
23
+ /// 0x0C8: Water effect object pointer (0xBC bytes, vtable 0x66B268)
24
+ pub water_effect: Ptr32,
25
+ /// 0x0CC-0x8E7: Unknown fields (terrain metadata, dimensions, etc.)
26
+ pub _unknown_0cc: [u8; 0x81C],
27
+ /// 0x8E8: Terrain buffer pointer (0x60000 bytes allocated)
28
+ pub terrain_buffer: Ptr32,
29
+ /// 0x8EC-0x8EF: Buffer size (0x60000)
30
+ pub _terrain_size: [u8; 4],
31
+ /// 0x8F0-0x90F: Unknown
32
+ pub _unknown_8f0: [u8; 0x20],
33
+ /// 0x910-0x913: Terrain handler pointer
34
+ pub terrain_handler: Ptr32,
35
+ /// 0x914: Initialized flag (set to 1)
36
+ pub initialized: u32,
37
+ /// 0x918-0x92F: Terrain directory path pointers
38
+ pub _dir_paths: [u8; 0x18],
39
+ /// 0x930: Splash buffer pointer (0x4C bytes)
40
+ pub splash_buffer: Ptr32,
41
+ /// 0x934: Terrain data pointer
42
+ pub terrain_data: Ptr32,
43
+ /// 0x938: Palette pointer
44
+ pub palette: Ptr32,
45
+ /// 0x93C: Shader object pointer (vtable 0x66B1DC)
46
+ pub shader: Ptr32,
47
+ /// 0x940-0x947: Surface texture buffer pointers
48
+ pub surface_textures: [Ptr32; 2],
49
+ /// 0x948-0x94B: Unknown
50
+ pub _unknown_948: [u8; 4],
51
+ /// 0x94C-0xB33: Unknown
52
+ pub _unknown_94c: [u8; 0x1E8],
53
+ /// 0xB34: Water .dir file handle
54
+ pub water_dir_handle: Ptr32,
55
+ /// 0xB38: Level .dir file handle
56
+ pub level_dir_handle: Ptr32,
57
+ /// 0xB3C-0xB3F: Trailing padding
58
+ pub _unknown_b3c: [u8; 4],
59
+ }
60
+
61
+ const _: () = assert!(core::mem::size_of::<PCLandscape>() == 0xB40);
crates/openwa-types/src/lib.rs CHANGED
@@ -5,4 +5,9 @@ pub mod sound;
5
  pub mod sprite;
6
  pub mod fixed;
7
  pub mod task;
 
 
 
 
 
8
  pub mod address;
 
5
  pub mod sprite;
6
  pub mod fixed;
7
  pub mod task;
8
+ pub mod ddgame;
9
+ pub mod ddgame_wrapper;
10
+ pub mod landscape;
11
+ pub mod dssound;
12
+ pub mod opengl;
13
  pub mod address;
crates/openwa-types/src/opengl.rs ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ use crate::task::Ptr32;
2
+
3
+ /// OpenGLState β€” CPU-side OpenGL state object.
4
+ ///
5
+ /// Created by OpenGLCPU__Constructor (0x5A0850).
6
+ /// Vtable: 0x6774C0
7
+ ///
8
+ /// Small object (0x48 bytes) holding OpenGL rendering state.
9
+ /// The actual OpenGL context (HDC, HGLRC) is stored in DDDisplay
10
+ /// fields during OpenGL__Init (0x59F000).
11
+ #[repr(C)]
12
+ pub struct OpenGLState {
13
+ /// 0x00: Vtable pointer (0x6774C0)
14
+ pub vtable: Ptr32,
15
+ /// 0x04-0x0F: Unknown
16
+ pub _unknown_04: [u8; 0x0C],
17
+ /// 0x10: Width
18
+ pub width: u32,
19
+ /// 0x14: Unknown (init 0)
20
+ pub _field_14: u32,
21
+ /// 0x18-0x23: Unknown (init 0)
22
+ pub _unknown_18: [u8; 0x0C],
23
+ /// 0x24: Height
24
+ pub height: u32,
25
+ /// 0x28-0x3F: Unknown
26
+ pub _unknown_28: [u8; 0x18],
27
+ /// 0x40: Unknown (init 0)
28
+ pub _field_40: u32,
29
+ /// 0x44: Unknown (init 0)
30
+ pub _field_44: u32,
31
+ }
32
+
33
+ const _: () = assert!(core::mem::size_of::<OpenGLState>() == 0x48);
docs/re-notes/engine-init.md ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Engine Initialization Chain
2
+
3
+ ## Overview
4
+
5
+ WA.exe initializes the engine through a chain of constructor calls that build
6
+ the DDGame monolith and its subsystems. The top-level entry is
7
+ `ConstructDDGameWrapper` which allocates DDGame and wires up all subsystems.
8
+
9
+ ## Call Chain
10
+
11
+ ```
12
+ WinMain / CRT startup (0x5D8B6C)
13
+ └─ ConstructDDGameWrapper (0x56DEF0)
14
+ β”œβ”€ Allocates DDGameWrapper (vtable 0x66A30C)
15
+ β”œβ”€ DDGame__Constructor (0x56E220)
16
+ β”‚ β”œβ”€ Allocates 0x98B8 bytes for DDGame
17
+ β”‚ β”œβ”€ DDDisplay__Init (0x569D00)
18
+ β”‚ β”‚ └─ Sets display mode, dimensions, palette, HWND
19
+ β”‚ β”œβ”€ GfxHandler x2 (vtable 0x66B280, 0x19C bytes each)
20
+ β”‚ β”œβ”€ Task state machines x5 (vtable 0x664118)
21
+ β”‚ └─ Game state pointer at DDGame+0x24
22
+ β”œβ”€ PCLandscape__Constructor (0x57ACB0)
23
+ β”‚ β”œβ”€ vtable 0x66B208, parent = DDGame
24
+ β”‚ β”œβ”€ Allocates terrain buffer (0x60000 bytes) at +0x8E8
25
+ β”‚ β”œβ”€ Creates WaterEffect object (vtable 0x66B268) at +0xC8
26
+ β”‚ β”œβ”€ Creates LandscapeShader (vtable 0x66B1DC) at +0x93C
27
+ β”‚ └─ Loads Water.dir, Level.dir from data\Gfx\
28
+ β”œβ”€ DSSound__Constructor (0x573D50)
29
+ β”‚ β”œβ”€ vtable 0x66AF20
30
+ β”‚ β”œβ”€ Master volume = Fixed(0x10000) = 1.0 at +0x8A4
31
+ β”‚ └─ 500 sound channel slots
32
+ └─ OpenGLCPU__Constructor (0x5A0850) [conditional]
33
+ β”œβ”€ vtable 0x6774C0, 0x48 bytes
34
+ β”œβ”€ Width at +0x10, Height at +0x24
35
+ └─ OpenGL__Init (0x59F000) stores HDC/HGLRC in DDDisplay
36
+ ```
37
+
38
+ ## DDGameWrapper Layout
39
+
40
+ DDGameWrapper is a thin wrapper (~0x500 bytes) around DDGame:
41
+
42
+ | Offset | Field | Notes |
43
+ |--------|--------------------|------------------------------------|
44
+ | 0x000 | vtable | 0x66A30C |
45
+ | 0x488 | DDGame ptr | Allocated 0x98B8-byte object |
46
+ | 0x48C | DDGame secondary | Optional 0x2C-byte struct |
47
+ | 0x4C0 | GfxHandler 0 | 0x19C bytes, vtable 0x66B280 |
48
+ | 0x4C4 | GfxHandler 1 | Optional |
49
+ | 0x4C8 | GfxMode | Graphics mode flag |
50
+ | 0x4CC | PCLandscape | Pointer to landscape subsystem |
51
+
52
+ ## DDGame Key Offsets
53
+
54
+ DDGame is a ~39KB (0x98B8 bytes) monolithic object. Known landmark fields:
55
+
56
+ | Offset | Field | Notes |
57
+ |--------|--------------------|------------------------------------|
58
+ | 0x0024 | game_state | Global game state pointer |
59
+ | 0x0028 | param | Constructor parameter |
60
+ | 0x11B0 | task_ptrs[5] | 5 task state machine pointers |
61
+ | 0x3548 | display_mode | Display mode pointer |
62
+ | 0x354C | display_width | Screen width |
63
+ | 0x3560 | display_center_x | Screen center X |
64
+ | 0x3564 | display_center_y | Screen center Y |
65
+ | 0x3578 | hwnd | Window handle |
66
+ | 0x358D | palette | 256-color palette (0x400 bytes) |
67
+ | 0x3D98 | gfx_objects[4] | Graphics object pointers |
68
+
69
+ ## Ghidra Offset Convention
70
+
71
+ Ghidra's decompiler shows DWORD-indexed offsets for struct access:
72
+ - `param_1[0x122]` β†’ byte offset 0x122 * 4 = **0x488**
73
+ - `param_1[0x133]` β†’ byte offset 0x133 * 4 = **0x4CC**
74
+ - Always multiply DWORD index by 4 to get the true byte offset.
docs/re-notes/memory-map.md CHANGED
@@ -21,14 +21,48 @@
21
 
22
  ## DDGame structure access
23
 
24
- The main game state is accessed through the DDGame pointer:
25
- - DDGame obtained via `ConstructDDGameWrapper` (0x56DEF0) parameter
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
  - DDGame+0x08 β†’ TurnGame object
27
  - DDGame+0x488 β†’ Game global state
28
  - DDGame+0x4CC β†’ PC_Landscape
29
  - DDGame+0x510 β†’ Weapon table
30
  - DDGame+0x548 β†’ Weapon panel
31
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
  ## Fixed-point convention
33
 
34
  All coordinates, velocities, and physics values use 16.16 fixed-point:
 
21
 
22
  ## DDGame structure access
23
 
24
+ The main game state is a 0x98B8-byte (39KB) monolithic object allocated by
25
+ `DDGame__Constructor` (0x56E220). It is wrapped by DDGameWrapper (0x56DEF0).
26
+
27
+ ### DDGameWrapper offsets (from wrapper base)
28
+ - +0x488 β†’ DDGame pointer (the allocated 0x98B8-byte object)
29
+ - +0x4C0 β†’ GfxHandler 0 (vtable 0x66B280)
30
+ - +0x4CC β†’ PCLandscape pointer
31
+
32
+ ### DDGame offsets (from DDGame base)
33
+ - +0x0024 β†’ Game state pointer
34
+ - +0x0028 β†’ Constructor param
35
+ - +0x11B0 β†’ Task state machine pointers (5 entries)
36
+ - +0x3548 β†’ Display mode
37
+ - +0x354C β†’ Display width
38
+ - +0x3560 β†’ Display center X
39
+ - +0x3564 β†’ Display center Y
40
+ - +0x3578 β†’ HWND
41
+ - +0x358D β†’ Palette (0x400 bytes)
42
+ - +0x3D98 β†’ Gfx object pointers (4 entries)
43
+
44
+ ### WormKit-convention offsets (DWORD-indexed)
45
+ These offsets are from the DDGameWrapper base, as used by WormKit mods:
46
  - DDGame+0x08 β†’ TurnGame object
47
  - DDGame+0x488 β†’ Game global state
48
  - DDGame+0x4CC β†’ PC_Landscape
49
  - DDGame+0x510 β†’ Weapon table
50
  - DDGame+0x548 β†’ Weapon panel
51
 
52
+ ## Subsystem vtables
53
+
54
+ | Address | Object | Size | Notes |
55
+ |------------|-----------------|--------|---------------------------|
56
+ | 0x66A30C | DDGameWrapper | ~0x500 | Top-level wrapper |
57
+ | 0x66B280 | GfxHandler | 0x19C | 2 instances |
58
+ | 0x664144 | DisplayGfx | β€” | |
59
+ | 0x66B208 | PCLandscape | 0xB40 | Terrain, water, level |
60
+ | 0x66B1DC | LandscapeShader | β€” | Used by PCLandscape |
61
+ | 0x66B268 | WaterEffect | 0xBC | Created by PCLandscape |
62
+ | 0x66AF20 | DSSound | ~0xBD0 | DirectSound, 500 channels |
63
+ | 0x664118 | TaskStateMachine| β€” | 5 instances in DDGame |
64
+ | 0x6774C0 | OpenGLCPU | 0x48 | Optional, conditional |
65
+
66
  ## Fixed-point convention
67
 
68
  All coordinates, velocities, and physics values use 16.16 fixed-point: