refactor: name DDGame fields, replace pointer arithmetic with struct access
Browse filesDDGame struct:
- Add gfx_sprite_data field at +0x7308 (was raw offset)
- Add level_width_raw/level_height_raw at +0x777C/+0x7780 (PCLandscape output)
Replace pointer arithmetic with typed access:
- ddgame.add(0x7308) β ddgame.gfx_sprite_data.as_mut_ptr()
- ddgame.add(0x777C/0x7780) β &ddgame.level_width_raw / level_height_raw
- game_info.add(0x44C) β game_info.speech_team_count
- landscape.add(0xB34/0xB38) β landscape.level_gfx_handler / water_gfx_handler
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
crates/openwa-core/src/engine/ddgame.rs
CHANGED
|
@@ -198,8 +198,10 @@ pub struct DDGame {
|
|
| 198 |
pub rng_state_1: u32,
|
| 199 |
/// 0x72F0: RNG state word 2 (changes every frame).
|
| 200 |
pub rng_state_2: u32,
|
| 201 |
-
/// 0x72F4-
|
| 202 |
-
pub _unknown_72f4: [u8;
|
|
|
|
|
|
|
| 203 |
/// 0x730C-0x731C: 5 GfxDir color entries
|
| 204 |
pub _gfx_color_entries: [u8; 0x7324 - 0x730C],
|
| 205 |
|
|
@@ -251,8 +253,14 @@ pub struct DDGame {
|
|
| 251 |
pub _unknown_76f0: [u8; 0x7718 - 0x76F0],
|
| 252 |
/// 0x7718-0x7757: Team index mapping table 3 (similar pattern, slightly different end).
|
| 253 |
pub team_index_map_3: [u8; 0x7758 - 0x7718],
|
| 254 |
-
/// 0x7758-
|
| 255 |
-
pub _unknown_7758: [u8;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 256 |
|
| 257 |
/// 0x779C: Level bound min X (Fixed-point, negative = off-screen left).
|
| 258 |
pub level_bound_min_x: i32,
|
|
@@ -831,7 +839,7 @@ unsafe fn init_graphics_and_resources(
|
|
| 831 |
core::mem::transmute(rb(va::GFX_HANDLER_LOAD_SPRITES) as usize);
|
| 832 |
f(
|
| 833 |
wrapper,
|
| 834 |
-
(
|
| 835 |
(*game_info).display_flags,
|
| 836 |
0,
|
| 837 |
);
|
|
@@ -839,12 +847,12 @@ unsafe fn init_graphics_and_resources(
|
|
| 839 |
|
| 840 |
// ββ DDGameWrapper field inits ββ
|
| 841 |
(*wrapper)._field_4d8 = 0;
|
| 842 |
-
// Loading progress total:
|
| 843 |
if is_headless {
|
| 844 |
(*wrapper)._field_4dc = 0x2AD;
|
| 845 |
} else {
|
| 846 |
-
let
|
| 847 |
-
(*wrapper)._field_4dc =
|
| 848 |
}
|
| 849 |
(*wrapper)._field_4e0 = 0xFFFFFF9C; // -100
|
| 850 |
(*wrapper).speech_name_count = 0;
|
|
@@ -903,7 +911,7 @@ unsafe fn init_graphics_and_resources(
|
|
| 903 |
*mut u8,
|
| 904 |
*mut u8, // 8=stack local, 9=coord output
|
| 905 |
*mut u8,
|
| 906 |
-
*mut u8, // 10=&ddgame
|
| 907 |
) -> *mut u8 = core::mem::transmute(rb(va::PC_LANDSCAPE_CONSTRUCTOR) as usize);
|
| 908 |
|
| 909 |
let result = pc_ctor(
|
|
@@ -916,8 +924,8 @@ unsafe fn init_graphics_and_resources(
|
|
| 916 |
(*wrapper).gfx_mode, // param 7
|
| 917 |
stack_local_8, // param 8
|
| 918 |
landscape_coords_buf, // param 9
|
| 919 |
-
(ddgame as *mut
|
| 920 |
-
(ddgame as *mut
|
| 921 |
);
|
| 922 |
(*wrapper).landscape = result as *mut PCLandscape;
|
| 923 |
(*ddgame).landscape = result as *mut PCLandscape;
|
|
@@ -1140,9 +1148,9 @@ unsafe fn init_graphics_and_resources(
|
|
| 1140 |
// DDNetGameWrapper__LoadResourceList: thiscall(ECX=wrapper) +
|
| 1141 |
// 5 stack params (layer, gfx_handler, base_path, data_table, table_size)
|
| 1142 |
{
|
| 1143 |
-
let landscape_ptr = (*wrapper).landscape
|
| 1144 |
-
let water_layer =
|
| 1145 |
-
let land_layer =
|
| 1146 |
let gfx_handler = (*wrapper)._field_4c0;
|
| 1147 |
|
| 1148 |
let wrapper_vt = *(wrapper as *const *const u32);
|
|
|
|
| 198 |
pub rng_state_1: u32,
|
| 199 |
/// 0x72F0: RNG state word 2 (changes every frame).
|
| 200 |
pub rng_state_2: u32,
|
| 201 |
+
/// 0x72F4-0x7307: Unknown
|
| 202 |
+
pub _unknown_72f4: [u8; 0x7308 - 0x72F4],
|
| 203 |
+
/// 0x7308: Sprite/gfx dimension data (passed to GFX_HANDLER_LOAD_SPRITES).
|
| 204 |
+
pub gfx_sprite_data: [u8; 0x730C - 0x7308],
|
| 205 |
/// 0x730C-0x731C: 5 GfxDir color entries
|
| 206 |
pub _gfx_color_entries: [u8; 0x7324 - 0x730C],
|
| 207 |
|
|
|
|
| 253 |
pub _unknown_76f0: [u8; 0x7718 - 0x76F0],
|
| 254 |
/// 0x7718-0x7757: Team index mapping table 3 (similar pattern, slightly different end).
|
| 255 |
pub team_index_map_3: [u8; 0x7758 - 0x7718],
|
| 256 |
+
/// 0x7758-0x777B: Unknown
|
| 257 |
+
pub _unknown_7758: [u8; 0x777C - 0x7758],
|
| 258 |
+
/// 0x777C: Level width output (written by PCLandscape constructor param 10).
|
| 259 |
+
pub level_width_raw: u32,
|
| 260 |
+
/// 0x7780: Level height output (written by PCLandscape constructor param 11).
|
| 261 |
+
pub level_height_raw: u32,
|
| 262 |
+
/// 0x7784-0x779B: Unknown
|
| 263 |
+
pub _unknown_7784: [u8; 0x779C - 0x7784],
|
| 264 |
|
| 265 |
/// 0x779C: Level bound min X (Fixed-point, negative = off-screen left).
|
| 266 |
pub level_bound_min_x: i32,
|
|
|
|
| 839 |
core::mem::transmute(rb(va::GFX_HANDLER_LOAD_SPRITES) as usize);
|
| 840 |
f(
|
| 841 |
wrapper,
|
| 842 |
+
(*ddgame).gfx_sprite_data.as_mut_ptr(),
|
| 843 |
(*game_info).display_flags,
|
| 844 |
0,
|
| 845 |
);
|
|
|
|
| 847 |
|
| 848 |
// ββ DDGameWrapper field inits ββ
|
| 849 |
(*wrapper)._field_4d8 = 0;
|
| 850 |
+
// Loading progress total: speech_team_count controls team count scaling.
|
| 851 |
if is_headless {
|
| 852 |
(*wrapper)._field_4dc = 0x2AD;
|
| 853 |
} else {
|
| 854 |
+
let team_count = (*game_info).speech_team_count as u32;
|
| 855 |
+
(*wrapper)._field_4dc = team_count * 0x38 + 0x7E + 0x2AD;
|
| 856 |
}
|
| 857 |
(*wrapper)._field_4e0 = 0xFFFFFF9C; // -100
|
| 858 |
(*wrapper).speech_name_count = 0;
|
|
|
|
| 911 |
*mut u8,
|
| 912 |
*mut u8, // 8=stack local, 9=coord output
|
| 913 |
*mut u8,
|
| 914 |
+
*mut u8, // 10=&ddgame.level_width_raw, 11=&ddgame.level_height_raw
|
| 915 |
) -> *mut u8 = core::mem::transmute(rb(va::PC_LANDSCAPE_CONSTRUCTOR) as usize);
|
| 916 |
|
| 917 |
let result = pc_ctor(
|
|
|
|
| 924 |
(*wrapper).gfx_mode, // param 7
|
| 925 |
stack_local_8, // param 8
|
| 926 |
landscape_coords_buf, // param 9
|
| 927 |
+
&mut (*ddgame).level_width_raw as *mut u32 as *mut u8,
|
| 928 |
+
&mut (*ddgame).level_height_raw as *mut u32 as *mut u8,
|
| 929 |
);
|
| 930 |
(*wrapper).landscape = result as *mut PCLandscape;
|
| 931 |
(*ddgame).landscape = result as *mut PCLandscape;
|
|
|
|
| 1148 |
// DDNetGameWrapper__LoadResourceList: thiscall(ECX=wrapper) +
|
| 1149 |
// 5 stack params (layer, gfx_handler, base_path, data_table, table_size)
|
| 1150 |
{
|
| 1151 |
+
let landscape_ptr = (*wrapper).landscape;
|
| 1152 |
+
let water_layer = (*landscape_ptr).water_gfx_handler;
|
| 1153 |
+
let land_layer = (*landscape_ptr).level_gfx_handler;
|
| 1154 |
let gfx_handler = (*wrapper)._field_4c0;
|
| 1155 |
|
| 1156 |
let wrapper_vt = *(wrapper as *const *const u32);
|