feat: port DDDisplay::GetDimensions to Rust, hook via vtable_replace
Browse filesFirst DDDisplay vtable method ported to Rust. Reads display_width/height
from DisplayBase and writes to output pointers. Hooked via vtable_replace
on slot 1 of the DDDisplay vtable (0x66A218).
FlushRender (slot 26) attempted but reverted — DDDisplayWrapper methods
use a non-standard fastcall convention (EDX = result pointer) that the
thiscall bind wrappers can't handle. Documented for future work.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
crates/openwa-core/src/display/dd_display.rs
CHANGED
|
@@ -270,3 +270,33 @@ pub struct DDDisplayVtable {
|
|
| 270 |
|
| 271 |
// Generate calling wrappers: DDDisplay::set_layer_color(), etc.
|
| 272 |
bind_DDDisplayVtable!(DDDisplay, vtable);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 270 |
|
| 271 |
// Generate calling wrappers: DDDisplay::set_layer_color(), etc.
|
| 272 |
bind_DDDisplayVtable!(DDDisplay, vtable);
|
| 273 |
+
|
| 274 |
+
// =========================================================================
|
| 275 |
+
// Ported DDDisplay vtable methods
|
| 276 |
+
// =========================================================================
|
| 277 |
+
|
| 278 |
+
use super::gfx::DisplayGfx;
|
| 279 |
+
|
| 280 |
+
/// Port of DDDisplay::GetDimensions (vtable slot 1, 0x56A460).
|
| 281 |
+
///
|
| 282 |
+
/// Reads display_width/display_height from DisplayBase and writes them
|
| 283 |
+
/// to the output pointers.
|
| 284 |
+
///
|
| 285 |
+
/// # Safety
|
| 286 |
+
/// `this` must be a valid `*mut DDDisplay` (actually a `*mut DisplayGfx`).
|
| 287 |
+
pub unsafe extern "thiscall" fn get_dimensions(
|
| 288 |
+
this: *mut DDDisplay,
|
| 289 |
+
out_w: *mut u32,
|
| 290 |
+
out_h: *mut u32,
|
| 291 |
+
) {
|
| 292 |
+
let gfx = this as *mut DisplayGfx;
|
| 293 |
+
*out_w = (*gfx).base.display_width;
|
| 294 |
+
*out_h = (*gfx).base.display_height;
|
| 295 |
+
}
|
| 296 |
+
|
| 297 |
+
// FlushRender (vtable slot 26, 0x56A580) — NOT YET PORTED.
|
| 298 |
+
//
|
| 299 |
+
// Calls DDDisplayWrapper::unlock_surface_write and ::get_renderer_surface,
|
| 300 |
+
// which use a non-standard fastcall convention (EDX = result pointer, not
|
| 301 |
+
// standard thiscall). Needs a naked asm bridge or corrected vtable typing
|
| 302 |
+
// for the DDDisplayWrapper methods before this can be ported.
|
crates/openwa-dll/src/replacements/display.rs
CHANGED
|
@@ -7,9 +7,11 @@
|
|
| 7 |
|
| 8 |
use crate::log_line;
|
| 9 |
use openwa_core::address::va;
|
|
|
|
| 10 |
use openwa_core::display::{DisplayBase, SpriteBufferCtrl, SpriteCacheWrapper};
|
| 11 |
use openwa_core::rebase::rb;
|
| 12 |
use openwa_core::vtable::patch_vtable;
|
|
|
|
| 13 |
use openwa_core::wa_alloc::wa_free;
|
| 14 |
|
| 15 |
/// The _purecall function address (calls abort).
|
|
@@ -76,6 +78,12 @@ pub fn install() -> Result<(), String> {
|
|
| 76 |
*vt = headless_destructor as *const () as u32;
|
| 77 |
let _ = log_line("[Display] Headless: patched slot 0 (destructor) → Rust");
|
| 78 |
})?;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 79 |
}
|
| 80 |
|
| 81 |
Ok(())
|
|
|
|
| 7 |
|
| 8 |
use crate::log_line;
|
| 9 |
use openwa_core::address::va;
|
| 10 |
+
use openwa_core::display::dd_display::{self, DDDisplayVtable};
|
| 11 |
use openwa_core::display::{DisplayBase, SpriteBufferCtrl, SpriteCacheWrapper};
|
| 12 |
use openwa_core::rebase::rb;
|
| 13 |
use openwa_core::vtable::patch_vtable;
|
| 14 |
+
use openwa_core::vtable_replace;
|
| 15 |
use openwa_core::wa_alloc::wa_free;
|
| 16 |
|
| 17 |
/// The _purecall function address (calls abort).
|
|
|
|
| 78 |
*vt = headless_destructor as *const () as u32;
|
| 79 |
let _ = log_line("[Display] Headless: patched slot 0 (destructor) → Rust");
|
| 80 |
})?;
|
| 81 |
+
|
| 82 |
+
// Patch DDDisplay vtable (0x66A218): replace ported methods with Rust.
|
| 83 |
+
vtable_replace!(DDDisplayVtable, va::DD_DISPLAY_VTABLE, {
|
| 84 |
+
get_dimensions => dd_display::get_dimensions,
|
| 85 |
+
})?;
|
| 86 |
+
let _ = log_line("[Display] DDDisplay: patched get_dimensions → Rust");
|
| 87 |
}
|
| 88 |
|
| 89 |
Ok(())
|