refactor: replace FFI bridges with direct Rust calls in DDGame constructor
Browse filesReplace call_gfx_load_dir, call_gfx_find_entry, call_gfx_resource_create,
and call_usercall_esi(FUN_570E20) with their ported Rust equivalents
(gfx_handler_load_dir, gfx_dir_find_entry, gfx_resource_create,
display_layer_color_init). These functions are now hooked and verified,
so the DDGame constructor can call them directly without naked asm bridges.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
crates/openwa-core/src/engine/ddgame.rs
CHANGED
|
@@ -812,7 +812,7 @@ pub unsafe fn gfx_resource_create(
|
|
| 812 |
output: *mut u8,
|
| 813 |
) -> *mut u8 {
|
| 814 |
// 1. Try FindEntry β cached load β DisplayGfx wrap
|
| 815 |
-
let entry =
|
| 816 |
if !entry.is_null() {
|
| 817 |
// gfx_handler->vtable[2](entry->field_4) β cached load
|
| 818 |
let vt = *(gfx_handler as *const *const u32);
|
|
@@ -1010,7 +1010,7 @@ unsafe fn init_graphics_and_resources(
|
|
| 1010 |
let ddgame = (*wrapper).ddgame;
|
| 1011 |
let fopen: unsafe extern "cdecl" fn(*const u8, *const u8) -> *mut u8 =
|
| 1012 |
core::mem::transmute(rb(va::WA_FOPEN) as usize);
|
| 1013 |
-
|
| 1014 |
let gfx_handler_vtable = rb(0x66B280) as u32; // GfxHandler__vtable (from asm: MOV [ESI], 0x66B280)
|
| 1015 |
|
| 1016 |
// ββ GfxHandler #1 (primary) ββ
|
|
@@ -1039,7 +1039,7 @@ unsafe fn init_graphics_and_resources(
|
|
| 1039 |
for (i, path) in paths.iter().enumerate() {
|
| 1040 |
let fp = fopen(path.as_ptr(), b"rb\0".as_ptr());
|
| 1041 |
*(gfx1.add(0x198) as *mut *mut u8) = fp;
|
| 1042 |
-
if !fp.is_null() &&
|
| 1043 |
gfx_loaded_idx = i as u32;
|
| 1044 |
break;
|
| 1045 |
}
|
|
@@ -1067,10 +1067,10 @@ unsafe fn init_graphics_and_resources(
|
|
| 1067 |
|
| 1068 |
let fp = fopen(gfx_c_path.as_ptr(), b"rb\0".as_ptr());
|
| 1069 |
*(gfx2.add(0x198) as *mut *mut u8) = fp;
|
| 1070 |
-
if fp.is_null() ||
|
| 1071 |
let fp2 = fopen(b"data\\Gfx\\Gfx.dir\0".as_ptr(), b"rb\0".as_ptr());
|
| 1072 |
*(gfx2.add(0x198) as *mut *mut u8) = fp2;
|
| 1073 |
-
if fp2.is_null() ||
|
| 1074 |
panic!("DDGame: couldn't open secondary Gfx.dir");
|
| 1075 |
}
|
| 1076 |
}
|
|
@@ -1117,7 +1117,7 @@ unsafe fn init_graphics_and_resources(
|
|
| 1117 |
|
| 1118 |
// ββ FUN_00570E20: usercall(ESI=wrapper), plain RET ββ
|
| 1119 |
// Runs for all modes β headless vtable[4] is 0x5231E0 (same as headful).
|
| 1120 |
-
|
| 1121 |
|
| 1122 |
// ββ Display vtable slot 5 (offset 0x14) ββ
|
| 1123 |
{
|
|
@@ -1132,7 +1132,7 @@ unsafe fn init_graphics_and_resources(
|
|
| 1132 |
if (*wrapper).gfx_mode != 0 {
|
| 1133 |
// GfxResource__Create: usercall(ECX=gfx_handler, EAX=0x66A3B4) + 1 stack, RET 0x4
|
| 1134 |
// In original: PUSH ESI(display_layer?), MOV EAX=0x66A3B4, CALL 0x4F6300
|
| 1135 |
-
let res =
|
| 1136 |
(*wrapper)._field_4c0, rb(0x66A3B4) as *const u8, core::ptr::null_mut(),
|
| 1137 |
);
|
| 1138 |
if !res.is_null() {
|
|
@@ -1222,7 +1222,7 @@ unsafe fn init_graphics_and_resources(
|
|
| 1222 |
core::ptr::write_bytes(out_buf, 0, 0x900);
|
| 1223 |
// return moved to before color entries
|
| 1224 |
let _ = crate::log::log_line("[DDGame] calling GfxResource_Create");
|
| 1225 |
-
gfx_resource =
|
| 1226 |
let _ = crate::log::log_line(&format!("[DDGame] GfxResource=0x{:08X}", gfx_resource as u32));
|
| 1227 |
}
|
| 1228 |
}
|
|
@@ -1368,8 +1368,7 @@ unsafe fn init_graphics_and_resources(
|
|
| 1368 |
layer_ctx as u32, gfx_handler as u32));
|
| 1369 |
}
|
| 1370 |
|
| 1371 |
-
|
| 1372 |
-
let entry = call_gfx_find_entry(name_buf.as_ptr(), gfx_handler);
|
| 1373 |
if i == 0 {
|
| 1374 |
let _ = crate::log::log_line(&format!(
|
| 1375 |
"[DDGame] arrow[0]: entry=0x{:08X}", entry as u32));
|
|
@@ -1610,7 +1609,7 @@ unsafe fn call_gfx_find_and_load(
|
|
| 1610 |
name: *const u8,
|
| 1611 |
display_ctx: *mut u8,
|
| 1612 |
) -> *mut u8 {
|
| 1613 |
-
let entry =
|
| 1614 |
|
| 1615 |
if !entry.is_null() {
|
| 1616 |
// Try cached load: gfx_dir->vtable[2](entry->field_4)
|
|
|
|
| 812 |
output: *mut u8,
|
| 813 |
) -> *mut u8 {
|
| 814 |
// 1. Try FindEntry β cached load β DisplayGfx wrap
|
| 815 |
+
let entry = gfx_dir_find_entry(name, gfx_handler);
|
| 816 |
if !entry.is_null() {
|
| 817 |
// gfx_handler->vtable[2](entry->field_4) β cached load
|
| 818 |
let vt = *(gfx_handler as *const *const u32);
|
|
|
|
| 1010 |
let ddgame = (*wrapper).ddgame;
|
| 1011 |
let fopen: unsafe extern "cdecl" fn(*const u8, *const u8) -> *mut u8 =
|
| 1012 |
core::mem::transmute(rb(va::WA_FOPEN) as usize);
|
| 1013 |
+
// gfx_load_dir_addr removed β using direct Rust gfx_handler_load_dir() now
|
| 1014 |
let gfx_handler_vtable = rb(0x66B280) as u32; // GfxHandler__vtable (from asm: MOV [ESI], 0x66B280)
|
| 1015 |
|
| 1016 |
// ββ GfxHandler #1 (primary) ββ
|
|
|
|
| 1039 |
for (i, path) in paths.iter().enumerate() {
|
| 1040 |
let fp = fopen(path.as_ptr(), b"rb\0".as_ptr());
|
| 1041 |
*(gfx1.add(0x198) as *mut *mut u8) = fp;
|
| 1042 |
+
if !fp.is_null() && gfx_handler_load_dir(gfx1) != 0 {
|
| 1043 |
gfx_loaded_idx = i as u32;
|
| 1044 |
break;
|
| 1045 |
}
|
|
|
|
| 1067 |
|
| 1068 |
let fp = fopen(gfx_c_path.as_ptr(), b"rb\0".as_ptr());
|
| 1069 |
*(gfx2.add(0x198) as *mut *mut u8) = fp;
|
| 1070 |
+
if fp.is_null() || gfx_handler_load_dir(gfx2) == 0 {
|
| 1071 |
let fp2 = fopen(b"data\\Gfx\\Gfx.dir\0".as_ptr(), b"rb\0".as_ptr());
|
| 1072 |
*(gfx2.add(0x198) as *mut *mut u8) = fp2;
|
| 1073 |
+
if fp2.is_null() || gfx_handler_load_dir(gfx2) == 0 {
|
| 1074 |
panic!("DDGame: couldn't open secondary Gfx.dir");
|
| 1075 |
}
|
| 1076 |
}
|
|
|
|
| 1117 |
|
| 1118 |
// ββ FUN_00570E20: usercall(ESI=wrapper), plain RET ββ
|
| 1119 |
// Runs for all modes β headless vtable[4] is 0x5231E0 (same as headful).
|
| 1120 |
+
display_layer_color_init(wrapper);
|
| 1121 |
|
| 1122 |
// ββ Display vtable slot 5 (offset 0x14) ββ
|
| 1123 |
{
|
|
|
|
| 1132 |
if (*wrapper).gfx_mode != 0 {
|
| 1133 |
// GfxResource__Create: usercall(ECX=gfx_handler, EAX=0x66A3B4) + 1 stack, RET 0x4
|
| 1134 |
// In original: PUSH ESI(display_layer?), MOV EAX=0x66A3B4, CALL 0x4F6300
|
| 1135 |
+
let res = gfx_resource_create(
|
| 1136 |
(*wrapper)._field_4c0, rb(0x66A3B4) as *const u8, core::ptr::null_mut(),
|
| 1137 |
);
|
| 1138 |
if !res.is_null() {
|
|
|
|
| 1222 |
core::ptr::write_bytes(out_buf, 0, 0x900);
|
| 1223 |
// return moved to before color entries
|
| 1224 |
let _ = crate::log::log_line("[DDGame] calling GfxResource_Create");
|
| 1225 |
+
gfx_resource = gfx_resource_create(gfx_handler, rb(0x66A3C0) as *const u8, out_buf);
|
| 1226 |
let _ = crate::log::log_line(&format!("[DDGame] GfxResource=0x{:08X}", gfx_resource as u32));
|
| 1227 |
}
|
| 1228 |
}
|
|
|
|
| 1368 |
layer_ctx as u32, gfx_handler as u32));
|
| 1369 |
}
|
| 1370 |
|
| 1371 |
+
let entry = gfx_dir_find_entry(name_buf.as_ptr(), gfx_handler);
|
|
|
|
| 1372 |
if i == 0 {
|
| 1373 |
let _ = crate::log::log_line(&format!(
|
| 1374 |
"[DDGame] arrow[0]: entry=0x{:08X}", entry as u32));
|
|
|
|
| 1609 |
name: *const u8,
|
| 1610 |
display_ctx: *mut u8,
|
| 1611 |
) -> *mut u8 {
|
| 1612 |
+
let entry = gfx_dir_find_entry(name, gfx_dir);
|
| 1613 |
|
| 1614 |
if !entry.is_null() {
|
| 1615 |
// Try cached load: gfx_dir->vtable[2](entry->field_4)
|