fix: correct HUD/sprite init addresses, fix display byte-read bug
Browse filesCritical fixes:
- HUD_LoadWeaponSprites: was 0x524070 (wrong), now 0x53D0E0 (correct)
with stdcall(ddgame, wrapper_4c4), RET 0x8
- Two DisplayGfx init calls: were using DISPLAYGFX_CTOR (0x569C10),
now use 0x5706D0 and 0x5703E0 (stdcall(wrapper), RET 0x4)
- Fix display byte-read bug in sprite resource section (same pattern
as earlier: *(wrapper as u8).add(0x4D0) reads byte not pointer)
- Re-enable loading tick calls
Headful mode: game starts, 119 validations pass.
Headless mode: still crashes β under investigation.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
crates/openwa-core/src/engine/ddgame.rs
CHANGED
|
@@ -962,9 +962,8 @@ unsafe fn init_graphics_and_resources(
|
|
| 962 |
}
|
| 963 |
|
| 964 |
// ββ Loading tick (FUN_005717A0 Γ2): usercall(ECX=wrapper) ββ
|
| 965 |
-
|
| 966 |
-
|
| 967 |
-
// call_usercall_ecx(wrapper, LOAD_WEAPON_SPRITES_ADDR);
|
| 968 |
|
| 969 |
// ββ Sprite resource loading via DDGameWrapper vtable[0] ββ
|
| 970 |
// DDNetGameWrapper__LoadResourceList: thiscall(ECX=wrapper) +
|
|
@@ -1015,7 +1014,7 @@ unsafe fn init_graphics_and_resources(
|
|
| 1015 |
let _layer3_ctx = set_layer((*ddgame).display, 3);
|
| 1016 |
|
| 1017 |
// Load back.spr and debris.spr (conditional)
|
| 1018 |
-
let disp_obj =
|
| 1019 |
let disp_obj_vt = *(disp_obj as *const *const u32);
|
| 1020 |
// Check if gfx_mode high byte is set (original: uStack_123c._3_1_ != '\0')
|
| 1021 |
if (*wrapper).gfx_mode != 0 {
|
|
@@ -1077,19 +1076,24 @@ unsafe fn init_graphics_and_resources(
|
|
| 1077 |
}
|
| 1078 |
}
|
| 1079 |
|
| 1080 |
-
// ββ
|
|
|
|
| 1081 |
{
|
| 1082 |
-
let hud_load: unsafe extern "stdcall" fn(
|
| 1083 |
-
core::mem::transmute(rb(
|
| 1084 |
-
hud_load(ddgame
|
| 1085 |
}
|
| 1086 |
|
| 1087 |
-
// ββ Two
|
|
|
|
|
|
|
| 1088 |
{
|
| 1089 |
-
let
|
| 1090 |
-
core::mem::transmute(rb(
|
| 1091 |
-
|
| 1092 |
-
|
|
|
|
|
|
|
| 1093 |
}
|
| 1094 |
|
| 1095 |
// ββ Close primary GfxHandler ββ
|
|
|
|
| 962 |
}
|
| 963 |
|
| 964 |
// ββ Loading tick (FUN_005717A0 Γ2): usercall(ECX=wrapper) ββ
|
| 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) +
|
|
|
|
| 1014 |
let _layer3_ctx = set_layer((*ddgame).display, 3);
|
| 1015 |
|
| 1016 |
// Load back.spr and debris.spr (conditional)
|
| 1017 |
+
let disp_obj = (*wrapper).display as *mut u8;
|
| 1018 |
let disp_obj_vt = *(disp_obj as *const *const u32);
|
| 1019 |
// Check if gfx_mode high byte is set (original: uStack_123c._3_1_ != '\0')
|
| 1020 |
if (*wrapper).gfx_mode != 0 {
|
|
|
|
| 1076 |
}
|
| 1077 |
}
|
| 1078 |
|
| 1079 |
+
// ββ HUD_LoadWeaponSprites (0x53D0E0) ββ
|
| 1080 |
+
// stdcall(ddgame, wrapper_4c4), verified from asm: PUSH ECX([EBP+0x4C4]), PUSH EDX(ddgame)
|
| 1081 |
{
|
| 1082 |
+
let hud_load: unsafe extern "stdcall" fn(*mut DDGame, *mut u8) =
|
| 1083 |
+
core::mem::transmute(rb(0x53D0E0) as usize);
|
| 1084 |
+
hud_load(ddgame, (*wrapper)._field_4c4);
|
| 1085 |
}
|
| 1086 |
|
| 1087 |
+
// ββ Two sprite init calls ββ
|
| 1088 |
+
// PUSH EBP(wrapper); CALL 0x5706D0 β stdcall(wrapper)
|
| 1089 |
+
// PUSH EBP(wrapper); CALL 0x5703E0 β stdcall(wrapper)
|
| 1090 |
{
|
| 1091 |
+
let f1: unsafe extern "stdcall" fn(*mut DDGameWrapper) =
|
| 1092 |
+
core::mem::transmute(rb(0x5706D0) as usize);
|
| 1093 |
+
f1(wrapper);
|
| 1094 |
+
let f2: unsafe extern "stdcall" fn(*mut DDGameWrapper) =
|
| 1095 |
+
core::mem::transmute(rb(0x5703E0) as usize);
|
| 1096 |
+
f2(wrapper);
|
| 1097 |
}
|
| 1098 |
|
| 1099 |
// ββ Close primary GfxHandler ββ
|
crates/openwa-wormkit/src/replacements/game_session.rs
CHANGED
|
@@ -159,9 +159,11 @@ pub(crate) unsafe fn construct_ddgame_wrapper(
|
|
| 159 |
}
|
| 160 |
|
| 161 |
// Initialize DDGame's game-state fields.
|
|
|
|
| 162 |
let init_state: unsafe extern "stdcall" fn(*mut DDGameWrapper) =
|
| 163 |
core::mem::transmute(rb(va::DDGAME_INIT_GAME_STATE) as usize);
|
| 164 |
init_state(this);
|
|
|
|
| 165 |
|
| 166 |
let ddgame = (*this).ddgame;
|
| 167 |
let _ = log_line(&format!(
|
|
|
|
| 159 |
}
|
| 160 |
|
| 161 |
// Initialize DDGame's game-state fields.
|
| 162 |
+
let _ = log_line("[GameSession] calling InitGameState");
|
| 163 |
let init_state: unsafe extern "stdcall" fn(*mut DDGameWrapper) =
|
| 164 |
core::mem::transmute(rb(va::DDGAME_INIT_GAME_STATE) as usize);
|
| 165 |
init_state(this);
|
| 166 |
+
let _ = log_line("[GameSession] InitGameState done");
|
| 167 |
|
| 168 |
let ddgame = (*this).ddgame;
|
| 169 |
let _ = log_line(&format!(
|