paavohtl Claude Opus 4.6 commited on
Commit
f572faf
·
1 Parent(s): 6c0f448

refactor: replace raw DDGame pointers with typed *mut DDGame

Browse files

Change CTask.ddgame, DDGameWrapper.ddgame, and PCLandscape.ddgame from
*mut u8 to *mut DDGame. Add named struct fields for crosshair line
params (0x7324/0x732C), fill_pixel (0x7338), and level dimensions
(0x77C0-0x77C8). Remove redundant casts and raw pointer arithmetic
in sound.rs, render.rs, input.rs, and validation.

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

crates/openwa-types/src/ddgame.rs CHANGED
@@ -76,20 +76,44 @@ pub struct DDGame {
76
  pub _unknown_528: [u8; 0x20],
77
  /// 0x548: Weapon panel pointer
78
  pub weapon_panel: *mut u8,
79
- /// 0x54C-0x7EFF: Sparse fields (see offsets module)
80
  ///
81
  /// Known landmarks:
82
  /// - 0x64D8: cleared by init
83
  /// - 0x72A4: cleared by init
84
- /// - 0x730C-0x732C: 9 GfxDir color entries
85
- /// - 0x7338: fill pixel value
86
- /// - 0x77C4: display-related value
87
- /// - 0x7EF8: flag from game_state+0xF914
88
- /// - 0x7EFC: init 1
89
  ///
90
  /// Also includes FUN_00526120 zeroed offsets at stride 0x194:
91
  /// 0x379C, 0x3930, 0x3AC4, 0x3C58, 0x3DEC, 0x3F80, 0x4114, 0x42A8, 0x443C, 0x45D0
92
- pub _unknown_54c: [u8; 0x7F00 - 0x54C],
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
93
 
94
  // === Sound queue (0x7F00-0x8143) ===
95
  /// 0x7F00: Sound queue (16 entries, stride 0x24). Appended by PlaySoundGlobal.
@@ -178,12 +202,6 @@ pub mod offsets {
178
  pub const FIELD_64D8: usize = 0x64D8;
179
  pub const FIELD_72A4: usize = 0x72A4;
180
  pub const GFX_COLOR_ENTRIES: usize = 0x730C;
181
- /// Crosshair line color param (DrawPolygon param_2). Part of GfxDir color entries.
182
- pub const CROSSHAIR_LINE_PARAM_2: usize = 0x7324;
183
- /// Crosshair line style param (DrawPolygon param_1). Part of GfxDir color entries.
184
- pub const CROSSHAIR_LINE_PARAM_1: usize = 0x732C;
185
- pub const FILL_PIXEL: usize = 0x7338;
186
- pub const DISPLAY_77C4: usize = 0x77C4;
187
  pub const FLAG_7EF8: usize = 0x7EF8;
188
  pub const FIELD_7EFC: usize = 0x7EFC;
189
  /// Scale factor used by DrawCrosshairLine (multiplied by 0x140000).
 
76
  pub _unknown_528: [u8; 0x20],
77
  /// 0x548: Weapon panel pointer
78
  pub weapon_panel: *mut u8,
79
+ /// 0x54C-0x7323: Sparse fields (see offsets module)
80
  ///
81
  /// Known landmarks:
82
  /// - 0x64D8: cleared by init
83
  /// - 0x72A4: cleared by init
84
+ /// - 0x730C-0x731C: 5 GfxDir color entries
 
 
 
 
85
  ///
86
  /// Also includes FUN_00526120 zeroed offsets at stride 0x194:
87
  /// 0x379C, 0x3930, 0x3AC4, 0x3C58, 0x3DEC, 0x3F80, 0x4114, 0x42A8, 0x443C, 0x45D0
88
+ pub _unknown_54c: [u8; 0x7324 - 0x54C],
89
+
90
+ /// 0x7324: Crosshair line color param (DrawPolygon param_2).
91
+ /// Part of GfxDir color entries at 0x730C.
92
+ pub crosshair_line_color: u32,
93
+ /// 0x7328: Unknown (between crosshair params)
94
+ pub _unknown_7328: [u8; 4],
95
+ /// 0x732C: Crosshair line style param (DrawPolygon param_1).
96
+ pub crosshair_line_style: u32,
97
+ /// 0x7330-0x7337: Unknown
98
+ pub _unknown_7330: [u8; 8],
99
+ /// 0x7338: Fill pixel value
100
+ pub fill_pixel: u32,
101
+ /// 0x733C-0x77BF: Unknown
102
+ pub _unknown_733c: [u8; 0x77C0 - 0x733C],
103
+
104
+ /// 0x77C0: Level width in pixels (set by PCLandscape constructor).
105
+ pub level_width: u32,
106
+ /// 0x77C4: Level height in pixels (set by PCLandscape constructor).
107
+ pub level_height: u32,
108
+ /// 0x77C8: Total pixels (width × height).
109
+ pub level_total_pixels: u32,
110
+
111
+ /// 0x77CC-0x7EFF: Unknown
112
+ ///
113
+ /// Known landmarks:
114
+ /// - 0x7EF8: flag from game_state+0xF914
115
+ /// - 0x7EFC: init 1
116
+ pub _unknown_77cc: [u8; 0x7F00 - 0x77CC],
117
 
118
  // === Sound queue (0x7F00-0x8143) ===
119
  /// 0x7F00: Sound queue (16 entries, stride 0x24). Appended by PlaySoundGlobal.
 
202
  pub const FIELD_64D8: usize = 0x64D8;
203
  pub const FIELD_72A4: usize = 0x72A4;
204
  pub const GFX_COLOR_ENTRIES: usize = 0x730C;
 
 
 
 
 
 
205
  pub const FLAG_7EF8: usize = 0x7EF8;
206
  pub const FIELD_7EFC: usize = 0x7EFC;
207
  /// Scale factor used by DrawCrosshairLine (multiplied by 0x140000).
crates/openwa-types/src/ddgame_wrapper.rs CHANGED
@@ -1,3 +1,5 @@
 
 
1
  /// DDGameWrapper — large wrapper around DDGame.
2
  ///
3
  /// Created by DDGameWrapper__Constructor (0x56DEF0).
@@ -20,7 +22,7 @@ pub struct DDGameWrapper {
20
  /// 0x004-0x487: Unknown fields
21
  pub _unknown_004: [u8; 0x484],
22
  /// 0x488: Pointer to DDGame allocation (DWORD index 0x122)
23
- pub ddgame: *mut u8,
24
  /// 0x48C: Secondary DDGame struct pointer (0x2C bytes, conditional)
25
  pub ddgame_secondary: *mut u8,
26
  /// 0x490-0x4BF: Unknown
 
1
+ use crate::ddgame::DDGame;
2
+
3
  /// DDGameWrapper — large wrapper around DDGame.
4
  ///
5
  /// Created by DDGameWrapper__Constructor (0x56DEF0).
 
22
  /// 0x004-0x487: Unknown fields
23
  pub _unknown_004: [u8; 0x484],
24
  /// 0x488: Pointer to DDGame allocation (DWORD index 0x122)
25
+ pub ddgame: *mut DDGame,
26
  /// 0x48C: Secondary DDGame struct pointer (0x2C bytes, conditional)
27
  pub ddgame_secondary: *mut u8,
28
  /// 0x490-0x4BF: Unknown
crates/openwa-types/src/landscape.rs CHANGED
@@ -1,3 +1,5 @@
 
 
1
  /// PCLandscape — terrain/landscape subsystem (0xB40 bytes).
2
  ///
3
  /// Created by `PCLandscape__Constructor` (0x57ACB0). Vtable: 0x66B208 (32 slots).
@@ -24,7 +26,7 @@ pub struct PCLandscape {
24
  /// 0x000: Vtable pointer (0x66B208)
25
  pub vtable: *mut u8,
26
  /// 0x004: Parent DDGame pointer (param_1[1])
27
- pub ddgame: *mut u8,
28
  /// 0x008-0x0CB: Pre-rendered crater sprites for 15 explosion sizes.
29
  /// param_1[2..17]: crater image ptrs, param_1[18..33]: secondary ptrs.
30
  /// Indexed by `explosion_size * 15 / 100`.
 
1
+ use crate::ddgame::DDGame;
2
+
3
  /// PCLandscape — terrain/landscape subsystem (0xB40 bytes).
4
  ///
5
  /// Created by `PCLandscape__Constructor` (0x57ACB0). Vtable: 0x66B208 (32 slots).
 
26
  /// 0x000: Vtable pointer (0x66B208)
27
  pub vtable: *mut u8,
28
  /// 0x004: Parent DDGame pointer (param_1[1])
29
+ pub ddgame: *mut DDGame,
30
  /// 0x008-0x0CB: Pre-rendered crater sprites for 15 explosion sizes.
31
  /// param_1[2..17]: crater image ptrs, param_1[18..33]: secondary ptrs.
32
  /// Indexed by `explosion_size * 15 / 100`.
crates/openwa-types/src/task.rs CHANGED
@@ -1,4 +1,5 @@
1
  use crate::class_type::ClassType;
 
2
  use crate::fixed::Fixed;
3
 
4
  /// Base task class in WA's entity hierarchy.
@@ -44,7 +45,7 @@ pub struct CTask {
44
  /// 0x28: 1 if this task owns shared_data (root), 0 if inherited from parent
45
  pub owns_shared_data: u32,
46
  /// 0x2C: DDGame pointer (3rd param to CTask::Constructor, stored at this+0x2C)
47
- pub ddgame: *mut u8,
48
  }
49
 
50
  const _: () = assert!(core::mem::size_of::<CTask>() == 0x30);
 
1
  use crate::class_type::ClassType;
2
+ use crate::ddgame::DDGame;
3
  use crate::fixed::Fixed;
4
 
5
  /// Base task class in WA's entity hierarchy.
 
45
  /// 0x28: 1 if this task owns shared_data (root), 0 if inherited from parent
46
  pub owns_shared_data: u32,
47
  /// 0x2C: DDGame pointer (3rd param to CTask::Constructor, stored at this+0x2C)
48
+ pub ddgame: *mut DDGame,
49
  }
50
 
51
  const _: () = assert!(core::mem::size_of::<CTask>() == 0x30);
crates/openwa-wormkit/src/replacements/input.rs CHANGED
@@ -17,22 +17,23 @@ use crate::log_line;
17
  use openwa_lib::rebase::rb;
18
  use openwa_types::address::va;
19
  use openwa_types::ddgame::DDGame;
 
20
 
21
  /// Trampoline to the original TurnManager_ProcessFrame.
22
  static ORIG_TURN_MANAGER: AtomicU32 = AtomicU32::new(0);
23
 
24
- /// Get the DDGame pointer (session+0xA0 → DDGameWrapper+0x488).
25
  #[inline]
26
  unsafe fn get_ddgame() -> *mut DDGame {
27
  let session = *(rb(va::G_GAME_SESSION) as *const u32);
28
  if session == 0 {
29
  return core::ptr::null_mut();
30
  }
31
- let wrapper = *((session + 0xA0) as *const u32);
32
- if wrapper == 0 {
33
  return core::ptr::null_mut();
34
  }
35
- *((wrapper + 0x488) as *const *mut DDGame)
36
  }
37
 
38
  /// Hook for TurnManager_ProcessFrame (stdcall, 1 param = TurnGame*).
 
17
  use openwa_lib::rebase::rb;
18
  use openwa_types::address::va;
19
  use openwa_types::ddgame::DDGame;
20
+ use openwa_types::ddgame_wrapper::DDGameWrapper;
21
 
22
  /// Trampoline to the original TurnManager_ProcessFrame.
23
  static ORIG_TURN_MANAGER: AtomicU32 = AtomicU32::new(0);
24
 
25
+ /// Get the DDGame pointer (session+0xA0 → DDGameWrapper.ddgame).
26
  #[inline]
27
  unsafe fn get_ddgame() -> *mut DDGame {
28
  let session = *(rb(va::G_GAME_SESSION) as *const u32);
29
  if session == 0 {
30
  return core::ptr::null_mut();
31
  }
32
+ let wrapper_ptr = *((session + 0xA0) as *const *const DDGameWrapper);
33
+ if wrapper_ptr.is_null() {
34
  return core::ptr::null_mut();
35
  }
36
+ (*wrapper_ptr).ddgame
37
  }
38
 
39
  /// Hook for TurnManager_ProcessFrame (stdcall, 1 param = TurnGame*).
crates/openwa-wormkit/src/replacements/render.rs CHANGED
@@ -5,7 +5,6 @@
5
 
6
  use openwa_lib::rebase::rb;
7
  use openwa_types::address::va;
8
- use openwa_types::ddgame::{offsets as dg, DDGame};
9
  use openwa_types::render::*;
10
  use openwa_types::task::{BungeeTrailTask, WeaponAimTask};
11
 
@@ -380,7 +379,7 @@ unsafe extern "stdcall" fn draw_bungee_trail_impl(
380
  return;
381
  }
382
 
383
- let ddgame = &*(task.base.ddgame as *const DDGame);
384
  let rq = &mut *ddgame.render_queue;
385
 
386
  let seg_data = task.segment_data;
@@ -504,7 +503,7 @@ unsafe extern "cdecl" fn draw_crosshair_line_impl(task_ptr: u32) {
504
  return;
505
  }
506
 
507
- let ddgame = &*(gt.base.ddgame as *const DDGame);
508
  let rq = &mut *ddgame.render_queue;
509
 
510
  let start_x = gt.pos_x.0;
@@ -554,9 +553,8 @@ unsafe extern "cdecl" fn draw_crosshair_line_impl(task_ptr: u32) {
554
  }
555
 
556
  // Enqueue polygon line (2 vertices)
557
- let ddgame_ptr = ddgame as *const DDGame as *const u8;
558
- let poly_param_1 = *(ddgame_ptr.add(dg::CROSSHAIR_LINE_PARAM_1) as *const u32);
559
- let poly_param_2 = *(ddgame_ptr.add(dg::CROSSHAIR_LINE_PARAM_2) as *const u32);
560
  let verts: [[i32; 3]; 2] = [
561
  [start_x, start_y, 0],
562
  [endpoint_x, endpoint_y, 0],
 
5
 
6
  use openwa_lib::rebase::rb;
7
  use openwa_types::address::va;
 
8
  use openwa_types::render::*;
9
  use openwa_types::task::{BungeeTrailTask, WeaponAimTask};
10
 
 
379
  return;
380
  }
381
 
382
+ let ddgame = &*task.base.ddgame;
383
  let rq = &mut *ddgame.render_queue;
384
 
385
  let seg_data = task.segment_data;
 
503
  return;
504
  }
505
 
506
+ let ddgame = &*gt.base.ddgame;
507
  let rq = &mut *ddgame.render_queue;
508
 
509
  let start_x = gt.pos_x.0;
 
553
  }
554
 
555
  // Enqueue polygon line (2 vertices)
556
+ let poly_param_1 = ddgame.crosshair_line_style;
557
+ let poly_param_2 = ddgame.crosshair_line_color;
 
558
  let verts: [[i32; 3]; 2] = [
559
  [start_x, start_y, 0],
560
  [endpoint_x, endpoint_y, 0],
crates/openwa-wormkit/src/replacements/sound.rs CHANGED
@@ -80,7 +80,7 @@ unsafe extern "thiscall" fn hook_play_sound_global(
80
  }
81
 
82
  let task = &*(this as *const CGameTask);
83
- queue_sound(task.base.ddgame as *mut DDGame, sound_id, flags, volume, pitch).is_some() as u32
84
  }
85
 
86
  // ============================================================
@@ -110,7 +110,7 @@ unsafe extern "cdecl" fn play_sound_local_impl(
110
  }
111
 
112
  let gt = &*(task as *const CGameTask);
113
- let ddgame = gt.base.ddgame as *mut DDGame;
114
  let entry = match queue_sound(ddgame, sound_id, flags, volume, pitch) {
115
  Some(e) => e,
116
  None => return 0,
 
80
  }
81
 
82
  let task = &*(this as *const CGameTask);
83
+ queue_sound(task.base.ddgame, sound_id, flags, volume, pitch).is_some() as u32
84
  }
85
 
86
  // ============================================================
 
110
  }
111
 
112
  let gt = &*(task as *const CGameTask);
113
+ let ddgame = gt.base.ddgame;
114
  let entry = match queue_sound(ddgame, sound_id, flags, volume, pitch) {
115
  Some(e) => e,
116
  None => return 0,
crates/openwa-wormkit/src/validation/mod.rs CHANGED
@@ -617,7 +617,7 @@ fn dump_landscape() {
617
  let _ = log_validation(&format!(" vtable: 0x{:08X} (expected 0x{:08X}) {}",
618
  land.vtable as u32, expected_vt, if vt_ok { "OK" } else { "MISMATCH" }));
619
 
620
- let _ = log_validation(&format!(" ddgame: 0x{:08X}", land.ddgame as u32));
621
  let _ = log_validation(&format!(" _unknown_900: 0x{:08X}", land._unknown_900 as u32));
622
  let _ = log_validation(&format!(" collision_bitmap: 0x{:08X}", land.collision_bitmap as u32));
623
  let _ = log_validation(&format!(" initialized: {}", land.initialized));
@@ -671,13 +671,10 @@ fn dump_landscape() {
671
  let _ = log_validation(&format!(" level_dir_path: {:?}", level_path));
672
  let _ = log_validation(&format!(" theme_dir_path: {:?}", theme_path));
673
 
674
- let ddgame_ptr = land.ddgame as u32;
675
- if ddgame_ptr != 0 {
676
- let level_w = read_u32(ddgame_ptr + 0x77C0);
677
- let level_h = read_u32(ddgame_ptr + 0x77C4);
678
- let level_total = read_u32(ddgame_ptr + 0x77C8);
679
  let _ = log_validation(&format!(" DDGame level dims: {}x{} (total={})",
680
- level_w, level_h, level_total));
681
  }
682
 
683
  let _ = log_validation(" Vtable slots:");
 
617
  let _ = log_validation(&format!(" vtable: 0x{:08X} (expected 0x{:08X}) {}",
618
  land.vtable as u32, expected_vt, if vt_ok { "OK" } else { "MISMATCH" }));
619
 
620
+ let _ = log_validation(&format!(" ddgame: 0x{:08X}", land.ddgame as usize));
621
  let _ = log_validation(&format!(" _unknown_900: 0x{:08X}", land._unknown_900 as u32));
622
  let _ = log_validation(&format!(" collision_bitmap: 0x{:08X}", land.collision_bitmap as u32));
623
  let _ = log_validation(&format!(" initialized: {}", land.initialized));
 
671
  let _ = log_validation(&format!(" level_dir_path: {:?}", level_path));
672
  let _ = log_validation(&format!(" theme_dir_path: {:?}", theme_path));
673
 
674
+ if !land.ddgame.is_null() {
675
+ let dg = &*land.ddgame;
 
 
 
676
  let _ = log_validation(&format!(" DDGame level dims: {}x{} (total={})",
677
+ dg.level_width, dg.level_height, dg.level_total_pixels));
678
  }
679
 
680
  let _ = log_validation(" Vtable slots:");