fix: re-enable all end sections with correct conventions
Browse filesAll constructor sections now enabled:
- HUD_LoadWeaponSprites: stdcall(ddgame, wrapper_4c4), RET 0x8
- Sprite init calls: stdcall(wrapper), RET 0x4
- GfxHandler close: thiscall vtable[3](1)
- Display finalization: stdcall(display)
- Layer visibility: thiscall vtable[0x17](layer, visible)
Headful: PASSES (119 validations)
Headless: still crashes at 0x525B82 (headless display stub issue)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
crates/openwa-core/src/engine/ddgame.rs
CHANGED
|
@@ -1076,18 +1076,61 @@ unsafe fn init_graphics_and_resources(
|
|
| 1076 |
}
|
| 1077 |
}
|
| 1078 |
|
| 1079 |
-
//
|
| 1080 |
-
//
|
| 1081 |
-
//
|
| 1082 |
-
//
|
| 1083 |
-
//
|
| 1084 |
-
//
|
| 1085 |
-
//
|
| 1086 |
-
//
|
| 1087 |
-
//
|
| 1088 |
-
//
|
| 1089 |
-
//
|
| 1090 |
-
//
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1091 |
|
| 1092 |
// GfxHandler close, display finalization, layer visibility:
|
| 1093 |
// Temporarily disabled to test stability.
|
|
|
|
| 1076 |
}
|
| 1077 |
}
|
| 1078 |
|
| 1079 |
+
// ββ HUD_LoadWeaponSprites (0x53D0E0) ββ
|
| 1080 |
+
// thiscall(ECX=ddgame, stack=wrapper_4c4), RET 0x8 (cleans 2: this implicit + 1 stack)
|
| 1081 |
+
// Wait β RET 0x8 means 2 stack params cleaned. For thiscall with ECX, that's 2 stack params.
|
| 1082 |
+
// The asm: PUSH ECX(=wrapper_4c4), PUSH EDX(=ddgame), CALL.
|
| 1083 |
+
// So it's stdcall(ddgame, wrapper_4c4) actually β ECX is NOT the this pointer!
|
| 1084 |
+
// The decompiler labeled it thiscall but the push sequence shows two stack params.
|
| 1085 |
+
// Let me pass wrapper as thiscall ECX and wrapper_4c4 as stack:
|
| 1086 |
+
// Actually: PUSH ECX([EBP+0x4C4]), PUSH EDX([EBP+0x488]=ddgame).
|
| 1087 |
+
// CALL 0x53D0E0. So ECX = gfx_handler_4c4, pushed FIRST. EDX = ddgame, pushed SECOND.
|
| 1088 |
+
// For stdcall: param_1=EDX(ddgame, pushed last), param_2=ECX(wrapper_4c4, pushed first).
|
| 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 "stdcall" fn(*mut DDGame, *mut u8) =
|
| 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
|
| 1100 |
+
{
|
| 1101 |
+
let f1: unsafe extern "stdcall" fn(*mut DDGameWrapper) =
|
| 1102 |
+
core::mem::transmute(rb(0x5706D0) as usize);
|
| 1103 |
+
f1(wrapper);
|
| 1104 |
+
let f2: unsafe extern "stdcall" fn(*mut DDGameWrapper) =
|
| 1105 |
+
core::mem::transmute(rb(0x5703E0) as usize);
|
| 1106 |
+
f2(wrapper);
|
| 1107 |
+
}
|
| 1108 |
+
|
| 1109 |
+
// ββ Close primary GfxHandler ββ
|
| 1110 |
+
if !(*wrapper)._field_4c0.is_null() {
|
| 1111 |
+
let gfx_vt = *((*wrapper)._field_4c0 as *const *const u32);
|
| 1112 |
+
let close: unsafe extern "thiscall" fn(*mut u8, u32) =
|
| 1113 |
+
core::mem::transmute(*gfx_vt.add(3));
|
| 1114 |
+
close((*wrapper)._field_4c0, 1);
|
| 1115 |
+
}
|
| 1116 |
+
|
| 1117 |
+
// ββ Display finalization (non-headless) ββ
|
| 1118 |
+
if !is_headless {
|
| 1119 |
+
let init_display_final: unsafe extern "stdcall" fn(*mut u8) =
|
| 1120 |
+
core::mem::transmute(rb(va::DDGAME_INIT_DISPLAY_FINAL) as usize);
|
| 1121 |
+
init_display_final(disp_obj);
|
| 1122 |
+
}
|
| 1123 |
+
if *(rb(0x88E485) as *const u8) == 0 {
|
| 1124 |
+
call_usercall_eax(wrapper, FUN_570A90_ADDR);
|
| 1125 |
+
}
|
| 1126 |
+
|
| 1127 |
+
// Display layer visibility: display->vtable[0x17](layer, visible)
|
| 1128 |
+
let disp_obj_vt = *(disp_obj as *const *const u32);
|
| 1129 |
+
let set_vis: unsafe extern "thiscall" fn(*mut u8, i32, i32) -> *mut u8 =
|
| 1130 |
+
core::mem::transmute(*disp_obj_vt.add(0x17));
|
| 1131 |
+
set_vis(disp_obj, 1, 0);
|
| 1132 |
+
set_vis(disp_obj, 2, 0);
|
| 1133 |
+
set_vis(disp_obj, 3, 1);
|
| 1134 |
|
| 1135 |
// GfxHandler close, display finalization, layer visibility:
|
| 1136 |
// Temporarily disabled to test stability.
|