refactor: DDDisplayWrapper vtable uses extern "fastcall" instead of inline asm
Browse filesThe "MFC result-return convention" (ECX=this, EDX=result_buf_ptr) is
actually __fastcall with an explicit FastcallResult parameter. This
eliminates all inline asm (call_method/call_method_1) and lets the
compiler generate correct calling code via the bind macro.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
crates/openwa-core/src/display/dd_display.rs
CHANGED
|
@@ -294,7 +294,7 @@ pub unsafe extern "thiscall" fn get_dimensions(
|
|
| 294 |
*out_h = (*gfx).base.display_height;
|
| 295 |
}
|
| 296 |
|
| 297 |
-
use super::display_wrapper::DDDisplayWrapper;
|
| 298 |
use crate::address::va;
|
| 299 |
use crate::rebase::rb;
|
| 300 |
|
|
@@ -322,5 +322,6 @@ pub unsafe extern "thiscall" fn flush_render(this: *mut DDDisplay) {
|
|
| 322 |
}
|
| 323 |
|
| 324 |
// get_renderer_surface β renderer Flip
|
| 325 |
-
|
|
|
|
| 326 |
}
|
|
|
|
| 294 |
*out_h = (*gfx).base.display_height;
|
| 295 |
}
|
| 296 |
|
| 297 |
+
use super::display_wrapper::{DDDisplayWrapper, FastcallResult};
|
| 298 |
use crate::address::va;
|
| 299 |
use crate::rebase::rb;
|
| 300 |
|
|
|
|
| 322 |
}
|
| 323 |
|
| 324 |
// get_renderer_surface β renderer Flip
|
| 325 |
+
let mut buf = FastcallResult::default();
|
| 326 |
+
DDDisplayWrapper::get_renderer_surface_raw(wrapper, &mut buf);
|
| 327 |
}
|
crates/openwa-core/src/display/display_wrapper.rs
CHANGED
|
@@ -4,28 +4,46 @@
|
|
| 4 |
crate::define_addresses! {
|
| 5 |
class "CWormsApp" {
|
| 6 |
/// CWormsApp__FlipSurface β dispatches to renderer backend vtable[1]
|
| 7 |
-
fn/
|
| 8 |
/// ConstructFrameBuffer β allocates software framebuffer, inits renderer
|
| 9 |
-
fn/
|
| 10 |
/// CWormsApp__ReleaseFrameBuffer
|
| 11 |
-
fn/
|
| 12 |
/// CWormsApp__FillRect β lock surface, memset rows, unlock
|
| 13 |
-
fn/
|
| 14 |
/// CWormsApp__BlitToFrameBuffer β optimized blit from surface to framebuffer
|
| 15 |
-
fn/
|
| 16 |
/// CWormsApp__DrawLandscape β blit with clipping and transparency
|
| 17 |
-
fn/
|
| 18 |
/// ClearFrameBuffer β memset(framebuffer, 0, w*h)
|
| 19 |
fn CWORMSAPP_CLEAR_FRAME_BUFFER = 0x005A_23F0;
|
| 20 |
}
|
| 21 |
}
|
| 22 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 23 |
/// DDDisplayWrapper vtable (0x662EC8, 25 slots).
|
| 24 |
///
|
| 25 |
/// Many slots are thin thunks that forward to the renderer backend
|
| 26 |
/// via `*(this+0x18)->vtable[N]`. Others manage the software framebuffer
|
| 27 |
/// or perform blitting directly.
|
| 28 |
///
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 29 |
/// ## Slot categories
|
| 30 |
///
|
| 31 |
/// - **Renderer thunks** (0, 2, 4, 5, 8, 10, 11): Forward to backend
|
|
@@ -37,90 +55,191 @@ crate::define_addresses! {
|
|
| 37 |
pub struct DDDisplayWrapperVtable {
|
| 38 |
/// renderer thunk -> backend vtable[0] (init/create) (0x4E3420, RET 0x8)
|
| 39 |
#[slot(0)]
|
| 40 |
-
pub renderer_init:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 41 |
/// flip/present β dispatches to renderer backend vtable[1] (0x5A2700)
|
| 42 |
#[slot(1)]
|
| 43 |
-
pub flip_surface:
|
|
|
|
|
|
|
|
|
|
| 44 |
/// renderer thunk -> backend vtable[2] (reset state) (0x4E3440)
|
| 45 |
#[slot(2)]
|
| 46 |
-
pub renderer_reset:
|
|
|
|
|
|
|
|
|
|
| 47 |
/// get framebuffer dimensions β reads G_FRAME_BUFFER_WIDTH/HEIGHT (0x5A2660, RET 0x4)
|
| 48 |
#[slot(3)]
|
| 49 |
-
pub get_framebuffer_dims:
|
|
|
|
|
|
|
|
|
|
|
|
|
| 50 |
/// renderer thunk -> backend vtable[4] (enum display modes) (0x4E3460, RET 0x8)
|
| 51 |
#[slot(4)]
|
| 52 |
-
pub renderer_enum_modes:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 53 |
/// renderer thunk -> backend vtable[5] (tail jump) (0x4E3480)
|
| 54 |
#[slot(5)]
|
| 55 |
-
pub renderer_slot5:
|
|
|
|
|
|
|
|
|
|
| 56 |
/// construct framebuffer β wa_malloc(w*h), init renderer (0x5A2430, RET 0x8)
|
| 57 |
#[slot(6)]
|
| 58 |
-
pub construct_frame_buffer:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 59 |
/// release framebuffer β calls renderer teardown, frees buffer (0x5A24A0)
|
| 60 |
#[slot(7)]
|
| 61 |
-
pub release_frame_buffer:
|
|
|
|
|
|
|
|
|
|
|
|
|
| 62 |
/// renderer thunk -> backend vtable[8] (0x5A24F0)
|
| 63 |
#[slot(8)]
|
| 64 |
-
pub renderer_slot8:
|
|
|
|
|
|
|
|
|
|
| 65 |
/// lock framebuffer for pixel access (0x5A2530)
|
| 66 |
///
|
| 67 |
/// Returns framebuffer pointer and stride for direct pixel manipulation.
|
| 68 |
#[slot(9)]
|
| 69 |
-
pub lock_framebuffer:
|
| 70 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 71 |
/// renderer thunk -> backend vtable[10] (0x5A2510)
|
| 72 |
#[slot(10)]
|
| 73 |
-
pub renderer_restore_dims:
|
|
|
|
|
|
|
|
|
|
| 74 |
/// renderer thunk -> backend vtable[11] (restore surface) (0x5A25A0)
|
| 75 |
#[slot(11)]
|
| 76 |
-
pub renderer_restore_surface:
|
|
|
|
|
|
|
|
|
|
| 77 |
/// allocate error/result object (0x5A2720, RET 0x4)
|
| 78 |
#[slot(12)]
|
| 79 |
-
pub alloc_error_result:
|
|
|
|
|
|
|
|
|
|
|
|
|
| 80 |
/// get renderer surface pointer (0x5A26C0)
|
| 81 |
///
|
| 82 |
/// Queries `renderer->vtable[12]` with G_FRAME_BUFFER_PTR.
|
| 83 |
#[slot(13)]
|
| 84 |
-
pub get_renderer_surface:
|
|
|
|
|
|
|
|
|
|
| 85 |
/// stub β returns 0 (CGameTask__vt18, 0x545780)
|
| 86 |
#[slot(14)]
|
| 87 |
-
pub stub_ret_zero:
|
|
|
|
|
|
|
|
|
|
| 88 |
/// lock surface for reading β returns framebuffer ptr + width (0x5A2690, RET 0x8)
|
| 89 |
#[slot(15)]
|
| 90 |
-
pub lock_surface_read:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 91 |
/// unlock surface (0x5A2C10, RET 0x4)
|
| 92 |
///
|
| 93 |
/// No-op for software framebuffer β just returns success code.
|
| 94 |
#[slot(16)]
|
| 95 |
-
pub unlock_surface_read:
|
|
|
|
|
|
|
|
|
|
|
|
|
| 96 |
/// lock surface for writing (0x5A2690 β same fn as slot 15, RET 0x8)
|
| 97 |
#[slot(17)]
|
| 98 |
-
pub lock_surface_write:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 99 |
/// unlock surface after writing (0x5A2C10 β same fn as slot 16, RET 0x4)
|
| 100 |
#[slot(18)]
|
| 101 |
-
pub unlock_surface_write:
|
|
|
|
|
|
|
|
|
|
|
|
|
| 102 |
/// fill rectangle β lock, memset rows, unlock (0x5A25C0)
|
| 103 |
///
|
| 104 |
/// Params: x, y, width, height, fill_value.
|
| 105 |
#[slot(19)]
|
| 106 |
-
pub fill_rect:
|
| 107 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 108 |
/// clear framebuffer β memset(ptr, 0, w*h) (0x5A23F0)
|
| 109 |
#[slot(20)]
|
| 110 |
-
pub clear_frame_buffer:
|
|
|
|
|
|
|
|
|
|
| 111 |
/// trampoline to slot 20 via vtable dispatch (0x5A2420)
|
| 112 |
#[slot(21)]
|
| 113 |
-
pub clear_frame_buffer_indirect:
|
|
|
|
|
|
|
|
|
|
| 114 |
/// allocate surface object β wa_malloc(0x14) (0x5A2760)
|
| 115 |
#[slot(22)]
|
| 116 |
-
pub alloc_surface:
|
|
|
|
|
|
|
|
|
|
| 117 |
/// draw landscape β blit with clipping and optional color-key transparency (0x5A2790)
|
| 118 |
#[slot(23)]
|
| 119 |
-
pub draw_landscape:
|
| 120 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 121 |
/// blit surface to framebuffer β optimized copy with stride alignment (0x5A2A40)
|
| 122 |
#[slot(24)]
|
| 123 |
-
pub blit_to_frame_buffer:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 124 |
}
|
| 125 |
|
| 126 |
/// DDDisplayWrapper struct β CWormsApp rendering dispatch subobject.
|
|
@@ -139,57 +258,7 @@ pub struct DDDisplayWrapper {
|
|
| 139 |
|
| 140 |
const _: () = assert!(core::mem::size_of::<DDDisplayWrapper>() == 0x1C);
|
| 141 |
|
| 142 |
-
// Generate calling wrappers: DDDisplayWrapper::
|
| 143 |
-
//
|
| 144 |
-
//
|
| 145 |
-
// (ECX=this, EDX=result_buf_ptr). Use call_wrapper_method() instead.
|
| 146 |
bind_DDDisplayWrapperVtable!(DDDisplayWrapper, vtable);
|
| 147 |
-
|
| 148 |
-
impl DDDisplayWrapper {
|
| 149 |
-
/// Call a DDDisplayWrapper vtable method by slot index.
|
| 150 |
-
///
|
| 151 |
-
/// DDDisplayWrapper methods use an MFC result-return convention:
|
| 152 |
-
/// ECX = this, EDX = pointer to caller-allocated result buffer.
|
| 153 |
-
/// The result is discarded by most callers.
|
| 154 |
-
///
|
| 155 |
-
/// # Safety
|
| 156 |
-
/// `this` must be a valid DDDisplayWrapper pointer with an initialized vtable.
|
| 157 |
-
#[inline]
|
| 158 |
-
pub unsafe fn call_method(this: *mut DDDisplayWrapper, slot: usize) {
|
| 159 |
-
let vtable = (*this).vtable as *const u32;
|
| 160 |
-
let func: u32 = *vtable.add(slot);
|
| 161 |
-
let mut result_buf: [u32; 2] = [0; 2];
|
| 162 |
-
core::arch::asm!(
|
| 163 |
-
"call {func}",
|
| 164 |
-
func = in(reg) func,
|
| 165 |
-
in("ecx") this,
|
| 166 |
-
inout("edx") result_buf.as_mut_ptr() => _,
|
| 167 |
-
out("eax") _,
|
| 168 |
-
clobber_abi("C"),
|
| 169 |
-
);
|
| 170 |
-
}
|
| 171 |
-
|
| 172 |
-
/// Call a DDDisplayWrapper vtable method with one stack parameter.
|
| 173 |
-
///
|
| 174 |
-
/// Same MFC convention as `call_method`, with an additional stack argument
|
| 175 |
-
/// pushed before the call (callee cleans via RET N).
|
| 176 |
-
///
|
| 177 |
-
/// # Safety
|
| 178 |
-
/// `this` must be a valid DDDisplayWrapper pointer with an initialized vtable.
|
| 179 |
-
#[inline]
|
| 180 |
-
pub unsafe fn call_method_1(this: *mut DDDisplayWrapper, slot: usize, param: u32) {
|
| 181 |
-
let vtable = (*this).vtable as *const u32;
|
| 182 |
-
let func: u32 = *vtable.add(slot);
|
| 183 |
-
let mut result_buf: [u32; 2] = [0; 2];
|
| 184 |
-
core::arch::asm!(
|
| 185 |
-
"push {param}",
|
| 186 |
-
"call {func}",
|
| 187 |
-
param = in(reg) param,
|
| 188 |
-
func = in(reg) func,
|
| 189 |
-
in("ecx") this,
|
| 190 |
-
inout("edx") result_buf.as_mut_ptr() => _,
|
| 191 |
-
out("eax") _,
|
| 192 |
-
clobber_abi("C"),
|
| 193 |
-
);
|
| 194 |
-
}
|
| 195 |
-
}
|
|
|
|
| 4 |
crate::define_addresses! {
|
| 5 |
class "CWormsApp" {
|
| 6 |
/// CWormsApp__FlipSurface β dispatches to renderer backend vtable[1]
|
| 7 |
+
fn/Fastcall CWORMSAPP_FLIP_SURFACE = 0x005A_2700;
|
| 8 |
/// ConstructFrameBuffer β allocates software framebuffer, inits renderer
|
| 9 |
+
fn/Fastcall CONSTRUCT_FRAME_BUFFER_THISCALL = 0x005A_2430;
|
| 10 |
/// CWormsApp__ReleaseFrameBuffer
|
| 11 |
+
fn/Fastcall CWORMSAPP_RELEASE_FRAME_BUFFER = 0x005A_24A0;
|
| 12 |
/// CWormsApp__FillRect β lock surface, memset rows, unlock
|
| 13 |
+
fn/Fastcall CWORMSAPP_FILL_RECT = 0x005A_25C0;
|
| 14 |
/// CWormsApp__BlitToFrameBuffer β optimized blit from surface to framebuffer
|
| 15 |
+
fn/Fastcall CWORMSAPP_BLIT_TO_FRAME_BUFFER = 0x005A_2A40;
|
| 16 |
/// CWormsApp__DrawLandscape β blit with clipping and transparency
|
| 17 |
+
fn/Fastcall CWORMSAPP_DRAW_LANDSCAPE = 0x005A_2790;
|
| 18 |
/// ClearFrameBuffer β memset(framebuffer, 0, w*h)
|
| 19 |
fn CWORMSAPP_CLEAR_FRAME_BUFFER = 0x005A_23F0;
|
| 20 |
}
|
| 21 |
}
|
| 22 |
|
| 23 |
+
/// Result buffer for DDDisplayWrapper and CompatRenderer vtable calls.
|
| 24 |
+
///
|
| 25 |
+
/// These classes use `__fastcall` convention: ECX = this, EDX = result buffer pointer.
|
| 26 |
+
/// The callee writes a result (typically an HRESULT or pointer) into `value` and
|
| 27 |
+
/// returns `EDX` in `EAX`. Most callers allocate this on the stack and ignore the result.
|
| 28 |
+
#[repr(C)]
|
| 29 |
+
#[derive(Clone, Copy, Default)]
|
| 30 |
+
pub struct FastcallResult {
|
| 31 |
+
pub value: u32,
|
| 32 |
+
_pad: u32,
|
| 33 |
+
}
|
| 34 |
+
|
| 35 |
/// DDDisplayWrapper vtable (0x662EC8, 25 slots).
|
| 36 |
///
|
| 37 |
/// Many slots are thin thunks that forward to the renderer backend
|
| 38 |
/// via `*(this+0x18)->vtable[N]`. Others manage the software framebuffer
|
| 39 |
/// or perform blitting directly.
|
| 40 |
///
|
| 41 |
+
/// ## Calling convention
|
| 42 |
+
///
|
| 43 |
+
/// All methods use `__fastcall`: ECX = this, EDX = `*mut FastcallResult` (caller-allocated
|
| 44 |
+
/// 8-byte result buffer). Remaining parameters are on the stack, callee-cleaned.
|
| 45 |
+
/// Most callers ignore the result value.
|
| 46 |
+
///
|
| 47 |
/// ## Slot categories
|
| 48 |
///
|
| 49 |
/// - **Renderer thunks** (0, 2, 4, 5, 8, 10, 11): Forward to backend
|
|
|
|
| 55 |
pub struct DDDisplayWrapperVtable {
|
| 56 |
/// renderer thunk -> backend vtable[0] (init/create) (0x4E3420, RET 0x8)
|
| 57 |
#[slot(0)]
|
| 58 |
+
pub renderer_init: unsafe extern "fastcall" fn(
|
| 59 |
+
this: *mut DDDisplayWrapper,
|
| 60 |
+
result: *mut FastcallResult,
|
| 61 |
+
p2: u32,
|
| 62 |
+
p3: u32,
|
| 63 |
+
) -> *mut FastcallResult,
|
| 64 |
/// flip/present β dispatches to renderer backend vtable[1] (0x5A2700)
|
| 65 |
#[slot(1)]
|
| 66 |
+
pub flip_surface: unsafe extern "fastcall" fn(
|
| 67 |
+
this: *mut DDDisplayWrapper,
|
| 68 |
+
result: *mut FastcallResult,
|
| 69 |
+
) -> *mut FastcallResult,
|
| 70 |
/// renderer thunk -> backend vtable[2] (reset state) (0x4E3440)
|
| 71 |
#[slot(2)]
|
| 72 |
+
pub renderer_reset: unsafe extern "fastcall" fn(
|
| 73 |
+
this: *mut DDDisplayWrapper,
|
| 74 |
+
result: *mut FastcallResult,
|
| 75 |
+
) -> *mut FastcallResult,
|
| 76 |
/// get framebuffer dimensions β reads G_FRAME_BUFFER_WIDTH/HEIGHT (0x5A2660, RET 0x4)
|
| 77 |
#[slot(3)]
|
| 78 |
+
pub get_framebuffer_dims: unsafe extern "fastcall" fn(
|
| 79 |
+
this: *mut DDDisplayWrapper,
|
| 80 |
+
result: *mut FastcallResult,
|
| 81 |
+
out: *mut u32,
|
| 82 |
+
) -> *mut FastcallResult,
|
| 83 |
/// renderer thunk -> backend vtable[4] (enum display modes) (0x4E3460, RET 0x8)
|
| 84 |
#[slot(4)]
|
| 85 |
+
pub renderer_enum_modes: unsafe extern "fastcall" fn(
|
| 86 |
+
this: *mut DDDisplayWrapper,
|
| 87 |
+
result: *mut FastcallResult,
|
| 88 |
+
p2: u32,
|
| 89 |
+
p3: u32,
|
| 90 |
+
) -> *mut FastcallResult,
|
| 91 |
/// renderer thunk -> backend vtable[5] (tail jump) (0x4E3480)
|
| 92 |
#[slot(5)]
|
| 93 |
+
pub renderer_slot5: unsafe extern "fastcall" fn(
|
| 94 |
+
this: *mut DDDisplayWrapper,
|
| 95 |
+
result: *mut FastcallResult,
|
| 96 |
+
) -> *mut FastcallResult,
|
| 97 |
/// construct framebuffer β wa_malloc(w*h), init renderer (0x5A2430, RET 0x8)
|
| 98 |
#[slot(6)]
|
| 99 |
+
pub construct_frame_buffer: unsafe extern "fastcall" fn(
|
| 100 |
+
this: *mut DDDisplayWrapper,
|
| 101 |
+
result: *mut FastcallResult,
|
| 102 |
+
width: i32,
|
| 103 |
+
height: i32,
|
| 104 |
+
) -> *mut FastcallResult,
|
| 105 |
/// release framebuffer β calls renderer teardown, frees buffer (0x5A24A0)
|
| 106 |
#[slot(7)]
|
| 107 |
+
pub release_frame_buffer: unsafe extern "fastcall" fn(
|
| 108 |
+
this: *mut DDDisplayWrapper,
|
| 109 |
+
result: *mut FastcallResult,
|
| 110 |
+
p2: i32,
|
| 111 |
+
) -> *mut FastcallResult,
|
| 112 |
/// renderer thunk -> backend vtable[8] (0x5A24F0)
|
| 113 |
#[slot(8)]
|
| 114 |
+
pub renderer_slot8: unsafe extern "fastcall" fn(
|
| 115 |
+
this: *mut DDDisplayWrapper,
|
| 116 |
+
result: *mut FastcallResult,
|
| 117 |
+
) -> *mut FastcallResult,
|
| 118 |
/// lock framebuffer for pixel access (0x5A2530)
|
| 119 |
///
|
| 120 |
/// Returns framebuffer pointer and stride for direct pixel manipulation.
|
| 121 |
#[slot(9)]
|
| 122 |
+
pub lock_framebuffer: unsafe extern "fastcall" fn(
|
| 123 |
+
this: *mut DDDisplayWrapper,
|
| 124 |
+
result: *mut FastcallResult,
|
| 125 |
+
p2: u32,
|
| 126 |
+
p3: u32,
|
| 127 |
+
p4: u32,
|
| 128 |
+
p5: u32,
|
| 129 |
+
) -> *mut FastcallResult,
|
| 130 |
/// renderer thunk -> backend vtable[10] (0x5A2510)
|
| 131 |
#[slot(10)]
|
| 132 |
+
pub renderer_restore_dims: unsafe extern "fastcall" fn(
|
| 133 |
+
this: *mut DDDisplayWrapper,
|
| 134 |
+
result: *mut FastcallResult,
|
| 135 |
+
) -> *mut FastcallResult,
|
| 136 |
/// renderer thunk -> backend vtable[11] (restore surface) (0x5A25A0)
|
| 137 |
#[slot(11)]
|
| 138 |
+
pub renderer_restore_surface: unsafe extern "fastcall" fn(
|
| 139 |
+
this: *mut DDDisplayWrapper,
|
| 140 |
+
result: *mut FastcallResult,
|
| 141 |
+
) -> *mut FastcallResult,
|
| 142 |
/// allocate error/result object (0x5A2720, RET 0x4)
|
| 143 |
#[slot(12)]
|
| 144 |
+
pub alloc_error_result: unsafe extern "fastcall" fn(
|
| 145 |
+
this: *mut DDDisplayWrapper,
|
| 146 |
+
result: *mut FastcallResult,
|
| 147 |
+
p2: u32,
|
| 148 |
+
) -> *mut FastcallResult,
|
| 149 |
/// get renderer surface pointer (0x5A26C0)
|
| 150 |
///
|
| 151 |
/// Queries `renderer->vtable[12]` with G_FRAME_BUFFER_PTR.
|
| 152 |
#[slot(13)]
|
| 153 |
+
pub get_renderer_surface: unsafe extern "fastcall" fn(
|
| 154 |
+
this: *mut DDDisplayWrapper,
|
| 155 |
+
result: *mut FastcallResult,
|
| 156 |
+
) -> *mut FastcallResult,
|
| 157 |
/// stub β returns 0 (CGameTask__vt18, 0x545780)
|
| 158 |
#[slot(14)]
|
| 159 |
+
pub stub_ret_zero: unsafe extern "fastcall" fn(
|
| 160 |
+
this: *mut DDDisplayWrapper,
|
| 161 |
+
result: *mut FastcallResult,
|
| 162 |
+
) -> *mut FastcallResult,
|
| 163 |
/// lock surface for reading β returns framebuffer ptr + width (0x5A2690, RET 0x8)
|
| 164 |
#[slot(15)]
|
| 165 |
+
pub lock_surface_read: unsafe extern "fastcall" fn(
|
| 166 |
+
this: *mut DDDisplayWrapper,
|
| 167 |
+
result: *mut FastcallResult,
|
| 168 |
+
p2: u32,
|
| 169 |
+
p3: u32,
|
| 170 |
+
) -> *mut FastcallResult,
|
| 171 |
/// unlock surface (0x5A2C10, RET 0x4)
|
| 172 |
///
|
| 173 |
/// No-op for software framebuffer β just returns success code.
|
| 174 |
#[slot(16)]
|
| 175 |
+
pub unlock_surface_read: unsafe extern "fastcall" fn(
|
| 176 |
+
this: *mut DDDisplayWrapper,
|
| 177 |
+
result: *mut FastcallResult,
|
| 178 |
+
p2: u32,
|
| 179 |
+
) -> *mut FastcallResult,
|
| 180 |
/// lock surface for writing (0x5A2690 β same fn as slot 15, RET 0x8)
|
| 181 |
#[slot(17)]
|
| 182 |
+
pub lock_surface_write: unsafe extern "fastcall" fn(
|
| 183 |
+
this: *mut DDDisplayWrapper,
|
| 184 |
+
result: *mut FastcallResult,
|
| 185 |
+
p2: u32,
|
| 186 |
+
p3: u32,
|
| 187 |
+
) -> *mut FastcallResult,
|
| 188 |
/// unlock surface after writing (0x5A2C10 β same fn as slot 16, RET 0x4)
|
| 189 |
#[slot(18)]
|
| 190 |
+
pub unlock_surface_write: unsafe extern "fastcall" fn(
|
| 191 |
+
this: *mut DDDisplayWrapper,
|
| 192 |
+
result: *mut FastcallResult,
|
| 193 |
+
p2: u32,
|
| 194 |
+
) -> *mut FastcallResult,
|
| 195 |
/// fill rectangle β lock, memset rows, unlock (0x5A25C0)
|
| 196 |
///
|
| 197 |
/// Params: x, y, width, height, fill_value.
|
| 198 |
#[slot(19)]
|
| 199 |
+
pub fill_rect: unsafe extern "fastcall" fn(
|
| 200 |
+
this: *mut DDDisplayWrapper,
|
| 201 |
+
result: *mut FastcallResult,
|
| 202 |
+
x: i32,
|
| 203 |
+
y: i32,
|
| 204 |
+
width: i32,
|
| 205 |
+
height: i32,
|
| 206 |
+
fill_value: u32,
|
| 207 |
+
) -> *mut FastcallResult,
|
| 208 |
/// clear framebuffer β memset(ptr, 0, w*h) (0x5A23F0)
|
| 209 |
#[slot(20)]
|
| 210 |
+
pub clear_frame_buffer: unsafe extern "fastcall" fn(
|
| 211 |
+
this: *mut DDDisplayWrapper,
|
| 212 |
+
result: *mut FastcallResult,
|
| 213 |
+
) -> *mut FastcallResult,
|
| 214 |
/// trampoline to slot 20 via vtable dispatch (0x5A2420)
|
| 215 |
#[slot(21)]
|
| 216 |
+
pub clear_frame_buffer_indirect: unsafe extern "fastcall" fn(
|
| 217 |
+
this: *mut DDDisplayWrapper,
|
| 218 |
+
result: *mut FastcallResult,
|
| 219 |
+
) -> *mut FastcallResult,
|
| 220 |
/// allocate surface object β wa_malloc(0x14) (0x5A2760)
|
| 221 |
#[slot(22)]
|
| 222 |
+
pub alloc_surface: unsafe extern "fastcall" fn(
|
| 223 |
+
this: *mut DDDisplayWrapper,
|
| 224 |
+
result: *mut FastcallResult,
|
| 225 |
+
) -> *mut FastcallResult,
|
| 226 |
/// draw landscape β blit with clipping and optional color-key transparency (0x5A2790)
|
| 227 |
#[slot(23)]
|
| 228 |
+
pub draw_landscape: unsafe extern "fastcall" fn(
|
| 229 |
+
this: *mut DDDisplayWrapper,
|
| 230 |
+
result: *mut FastcallResult,
|
| 231 |
+
surface: *mut u8,
|
| 232 |
+
y_offset: i32,
|
| 233 |
+
flags: u32,
|
| 234 |
+
) -> *mut FastcallResult,
|
| 235 |
/// blit surface to framebuffer β optimized copy with stride alignment (0x5A2A40)
|
| 236 |
#[slot(24)]
|
| 237 |
+
pub blit_to_frame_buffer: unsafe extern "fastcall" fn(
|
| 238 |
+
this: *mut DDDisplayWrapper,
|
| 239 |
+
result: *mut FastcallResult,
|
| 240 |
+
surface: *mut u8,
|
| 241 |
+
y_offset: i32,
|
| 242 |
+
) -> *mut FastcallResult,
|
| 243 |
}
|
| 244 |
|
| 245 |
/// DDDisplayWrapper struct β CWormsApp rendering dispatch subobject.
|
|
|
|
| 258 |
|
| 259 |
const _: () = assert!(core::mem::size_of::<DDDisplayWrapper>() == 0x1C);
|
| 260 |
|
| 261 |
+
// Generate calling wrappers: DDDisplayWrapper::get_renderer_surface_raw(), etc.
|
| 262 |
+
// Use the `_raw` variants to avoid LLVM noalias miscompilation.
|
| 263 |
+
// Callers must pass a `&mut FastcallResult` buffer (allocated on the stack).
|
|
|
|
| 264 |
bind_DDDisplayWrapperVtable!(DDDisplayWrapper, vtable);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
crates/openwa-core/src/display/mod.rs
CHANGED
|
@@ -15,7 +15,7 @@ pub use bitgrid::{
|
|
| 15 |
};
|
| 16 |
pub use compat_renderer::CompatRenderer;
|
| 17 |
pub use dd_display::DDDisplay;
|
| 18 |
-
pub use display_wrapper::DDDisplayWrapper;
|
| 19 |
pub use gfx::DisplayGfx;
|
| 20 |
pub use opengl::OpenGLState;
|
| 21 |
pub use palette::{Palette, PaletteVtable};
|
|
|
|
| 15 |
};
|
| 16 |
pub use compat_renderer::CompatRenderer;
|
| 17 |
pub use dd_display::DDDisplay;
|
| 18 |
+
pub use display_wrapper::{DDDisplayWrapper, FastcallResult};
|
| 19 |
pub use gfx::DisplayGfx;
|
| 20 |
pub use opengl::OpenGLState;
|
| 21 |
pub use palette::{Palette, PaletteVtable};
|