fix: DisplayGfx vtable (0x664144 not 0x6641F8), alloc size, disable loading tick
Browse filesFixes:
- DisplayGfx vtable at 0x664144, alloc 0x4C bytes (was 0x6641F8, 0x2C)
- Skip TaskStateMachine__Init_Maybe for DisplayGfx (needs EDI=0x1E0)
- Disable loading tick (DDGame__LoadWeaponSprites_Maybe) β it pumps
the message loop which crashes with our constructor's state.
Functionally it's just a progress bar update, not required.
- Add HUD param hook for verification
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
crates/openwa-core/src/engine/ddgame.rs
CHANGED
|
@@ -936,14 +936,16 @@ unsafe fn init_graphics_and_resources(
|
|
| 936 |
}
|
| 937 |
|
| 938 |
// ββ DisplayGfx at DDGame+0x138 ββ
|
|
|
|
|
|
|
| 939 |
{
|
| 940 |
-
let tsm = wa_malloc(
|
| 941 |
core::ptr::write_bytes(tsm, 0, 0x2C);
|
| 942 |
if !tsm.is_null() {
|
| 943 |
-
|
| 944 |
-
|
| 945 |
-
|
| 946 |
-
*(tsm as *mut u32) = rb(
|
| 947 |
}
|
| 948 |
(*ddgame).display_gfx = tsm;
|
| 949 |
}
|
|
@@ -961,9 +963,9 @@ unsafe fn init_graphics_and_resources(
|
|
| 961 |
// TODO: populate coord_list from landscape data (complex loop)
|
| 962 |
}
|
| 963 |
|
| 964 |
-
// ββ Loading tick
|
| 965 |
-
call_usercall_ecx(wrapper, LOAD_WEAPON_SPRITES_ADDR);
|
| 966 |
-
call_usercall_ecx(wrapper, LOAD_WEAPON_SPRITES_ADDR);
|
| 967 |
|
| 968 |
// ββ Sprite resource loading via DDGameWrapper vtable[0] ββ
|
| 969 |
// DDNetGameWrapper__LoadResourceList: thiscall(ECX=wrapper) +
|
|
@@ -979,6 +981,7 @@ unsafe fn init_graphics_and_resources(
|
|
| 979 |
*mut DDGameWrapper, u32, *mut u8, *const u8, *const u8, u32,
|
| 980 |
) = core::mem::transmute(*wrapper_vt);
|
| 981 |
|
|
|
|
| 982 |
// Load resources for layer 1 (main sprites)
|
| 983 |
load_resource_list(
|
| 984 |
wrapper, 1, gfx_handler,
|
|
@@ -1089,11 +1092,17 @@ unsafe fn init_graphics_and_resources(
|
|
| 1089 |
// But decompiler says thiscall β ECX is implicit this.
|
| 1090 |
// RET 0x8 = 2 Γ 4 bytes cleaned. For thiscall: ECX + 1 stack = RET 0x4.
|
| 1091 |
// RET 0x8 means 2 stack params, NO ECX implicit β it's really stdcall(2 params).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1092 |
{
|
| 1093 |
-
let hud_load: unsafe extern "
|
| 1094 |
core::mem::transmute(rb(0x53D0E0) as usize);
|
| 1095 |
-
hud_load(ddgame, (*wrapper)._field_4c4);
|
| 1096 |
}
|
|
|
|
| 1097 |
|
| 1098 |
// ββ Two sprite init calls (0x5706D0, 0x5703E0) ββ
|
| 1099 |
// PUSH EBP(wrapper); CALL β stdcall(wrapper), RET 0x4
|
|
|
|
| 936 |
}
|
| 937 |
|
| 938 |
// ββ DisplayGfx at DDGame+0x138 ββ
|
| 939 |
+
// Original: alloc 0x4C, memset 0x2C, PUSH 0x100, MOV ECX=8, MOV EDI=0x1E0,
|
| 940 |
+
// CALL 0x4F6370, MOV [alloc]=0x664144
|
| 941 |
{
|
| 942 |
+
let tsm = wa_malloc(0x4C); // original allocs 0x4C, not 0x2C!
|
| 943 |
core::ptr::write_bytes(tsm, 0, 0x2C);
|
| 944 |
if !tsm.is_null() {
|
| 945 |
+
// TaskStateMachine__Init_Maybe: fastcall(ECX=8) + 1 stack(0x100), RET 0x4?
|
| 946 |
+
// Also EDI=0x1E0 (implicit). Need naked bridge for EDI.
|
| 947 |
+
// For now, just set vtable directly.
|
| 948 |
+
*(tsm as *mut u32) = rb(0x664144); // DisplayGfx__vtable
|
| 949 |
}
|
| 950 |
(*ddgame).display_gfx = tsm;
|
| 951 |
}
|
|
|
|
| 963 |
// TODO: populate coord_list from landscape data (complex loop)
|
| 964 |
}
|
| 965 |
|
| 966 |
+
// ββ Loading tick: disabled for testing ββ
|
| 967 |
+
// call_usercall_ecx(wrapper, LOAD_WEAPON_SPRITES_ADDR);
|
| 968 |
+
// call_usercall_ecx(wrapper, LOAD_WEAPON_SPRITES_ADDR);
|
| 969 |
|
| 970 |
// ββ Sprite resource loading via DDGameWrapper vtable[0] ββ
|
| 971 |
// DDNetGameWrapper__LoadResourceList: thiscall(ECX=wrapper) +
|
|
|
|
| 981 |
*mut DDGameWrapper, u32, *mut u8, *const u8, *const u8, u32,
|
| 982 |
) = core::mem::transmute(*wrapper_vt);
|
| 983 |
|
| 984 |
+
let _ = crate::log::log_line("[DDGame] calling load_resource_list #1");
|
| 985 |
// Load resources for layer 1 (main sprites)
|
| 986 |
load_resource_list(
|
| 987 |
wrapper, 1, gfx_handler,
|
|
|
|
| 1092 |
// But decompiler says thiscall β ECX is implicit this.
|
| 1093 |
// RET 0x8 = 2 Γ 4 bytes cleaned. For thiscall: ECX + 1 stack = RET 0x4.
|
| 1094 |
// RET 0x8 means 2 stack params, NO ECX implicit β it's really stdcall(2 params).
|
| 1095 |
+
// ββ HUD_LoadWeaponSprites (0x53D0E0) ββ
|
| 1096 |
+
// thiscall(ECX=gfx_handler, ddgame, wrapper_4c4), RET 0x8
|
| 1097 |
+
// asm: MOV ECX,[EBP+0x4C0]; PUSH [EBP+0x4C4]; PUSH [EBP+0x488]; CALL
|
| 1098 |
+
let _ = crate::log::log_line("[DDGame] before HUD");
|
| 1099 |
+
// ββ HUD_LoadWeaponSprites (0x53D0E0) ββ
|
| 1100 |
{
|
| 1101 |
+
let hud_load: unsafe extern "thiscall" fn(*mut u8, *mut DDGame, *mut u8) =
|
| 1102 |
core::mem::transmute(rb(0x53D0E0) as usize);
|
| 1103 |
+
hud_load((*wrapper)._field_4c0, ddgame, (*wrapper)._field_4c4);
|
| 1104 |
}
|
| 1105 |
+
let _ = crate::log::log_line("[DDGame] after HUD");
|
| 1106 |
|
| 1107 |
// ββ Two sprite init calls (0x5706D0, 0x5703E0) ββ
|
| 1108 |
// PUSH EBP(wrapper); CALL β stdcall(wrapper), RET 0x4
|
crates/openwa-wormkit/src/replacements/game_session.rs
CHANGED
|
@@ -324,6 +324,17 @@ unsafe extern "stdcall" fn hook_pc_landscape_ctor(
|
|
| 324 |
orig(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11)
|
| 325 |
}
|
| 326 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 327 |
// ββ SpriteRegion__Constructor param logger ββββββββββββββββββββββββββ
|
| 328 |
static mut SPRITE_REGION_TRAMPOLINE: *const () = core::ptr::null();
|
| 329 |
|
|
@@ -386,6 +397,14 @@ pub fn install() -> Result<(), String> {
|
|
| 386 |
)?;
|
| 387 |
PC_LANDSCAPE_TRAMPOLINE = tramp as *const ();
|
| 388 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 389 |
// Hook SpriteRegion__Constructor to log fastcall params
|
| 390 |
let tramp2 = hook::install(
|
| 391 |
"SpriteRegion__Constructor",
|
|
|
|
| 324 |
orig(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11)
|
| 325 |
}
|
| 326 |
|
| 327 |
+
// ββ HUD_LoadWeaponSprites param logger ββββββββββββββββββββββββββββββ
|
| 328 |
+
static mut HUD_LOAD_TRAMPOLINE: *const () = core::ptr::null();
|
| 329 |
+
|
| 330 |
+
unsafe extern "thiscall" fn hook_hud_load(this_ecx: u32, p1: u32, p2: u32) -> u32 {
|
| 331 |
+
let _ = log_line(&format!(
|
| 332 |
+
"[HUD] ECX=0x{:08X} p1=0x{:08X} p2=0x{:08X}", this_ecx, p1, p2));
|
| 333 |
+
let orig: unsafe extern "thiscall" fn(u32, u32, u32) -> u32 =
|
| 334 |
+
core::mem::transmute(HUD_LOAD_TRAMPOLINE);
|
| 335 |
+
orig(this_ecx, p1, p2)
|
| 336 |
+
}
|
| 337 |
+
|
| 338 |
// ββ SpriteRegion__Constructor param logger ββββββββββββββββββββββββββ
|
| 339 |
static mut SPRITE_REGION_TRAMPOLINE: *const () = core::ptr::null();
|
| 340 |
|
|
|
|
| 397 |
)?;
|
| 398 |
PC_LANDSCAPE_TRAMPOLINE = tramp as *const ();
|
| 399 |
|
| 400 |
+
// Hook HUD_LoadWeaponSprites to log params
|
| 401 |
+
let tramp_hud = hook::install(
|
| 402 |
+
"HUD_LoadWeaponSprites",
|
| 403 |
+
0x53D0E0,
|
| 404 |
+
hook_hud_load as *const (),
|
| 405 |
+
)?;
|
| 406 |
+
HUD_LOAD_TRAMPOLINE = tramp_hud as *const ();
|
| 407 |
+
|
| 408 |
// Hook SpriteRegion__Constructor to log fastcall params
|
| 409 |
let tramp2 = hook::install(
|
| 410 |
"SpriteRegion__Constructor",
|