paavohtl Claude Opus 4.6 (1M context) commited on
Commit
a9dc351
Β·
1 Parent(s): 463da8a

refactor: replace FFI bridges with direct Rust calls in DDGame constructor

Browse files

Replace 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 = call_gfx_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,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
- let gfx_load_dir_addr = rb(va::GFX_HANDLER_LOAD_DIR);
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() && call_gfx_load_dir(gfx1, gfx_load_dir_addr) != 0 {
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() || call_gfx_load_dir(gfx2, gfx_load_dir_addr) == 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() || call_gfx_load_dir(gfx2, gfx_load_dir_addr) == 0 {
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
- call_usercall_esi(wrapper, FUN_570E20_ADDR);
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 = call_gfx_resource_create(
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 = call_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,8 +1368,7 @@ unsafe fn init_graphics_and_resources(
1368
  layer_ctx as u32, gfx_handler as u32));
1369
  }
1370
 
1371
- // GfxDir__FindEntry: usercall(EAX=name) + 1 stack(gfx_handler), RET 0x4
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 = call_gfx_find_entry(name, gfx_dir);
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)