File size: 15,244 Bytes
88857ea 547a858 368f9b1 547a858 368f9b1 547a858 368f9b1 547a858 368f9b1 547a858 368f9b1 547a858 368f9b1 547a858 88857ea 368f9b1 88857ea 547a858 368f9b1 547a858 88857ea 547a858 368f9b1 88857ea 368f9b1 547a858 368f9b1 88857ea 368f9b1 547a858 368f9b1 88857ea 368f9b1 547a858 368f9b1 88857ea 368f9b1 547a858 368f9b1 88857ea 368f9b1 547a858 368f9b1 88857ea 368f9b1 547a858 368f9b1 88857ea 368f9b1 547a858 368f9b1 88857ea 368f9b1 547a858 368f9b1 88857ea 368f9b1 547a858 368f9b1 88857ea 368f9b1 547a858 368f9b1 88857ea 368f9b1 547a858 368f9b1 88857ea 368f9b1 547a858 368f9b1 88857ea 368f9b1 547a858 368f9b1 88857ea 368f9b1 547a858 368f9b1 88857ea 368f9b1 bdd7b6b 547a858 368f9b1 88857ea 368f9b1 bdd7b6b 368f9b1 547a858 368f9b1 88857ea 368f9b1 547a858 bdd7b6b 547a858 368f9b1 88857ea 368f9b1 1b3fdc4 bdd7b6b 368f9b1 547a858 1b3fdc4 547a858 368f9b1 88857ea 368f9b1 1b3fdc4 368f9b1 547a858 368f9b1 88857ea 368f9b1 547a858 368f9b1 88857ea 368f9b1 547a858 368f9b1 88857ea 368f9b1 547a858 368f9b1 88857ea 368f9b1 48dff37 547a858 368f9b1 88857ea 368f9b1 48dff37 368f9b1 547a858 368f9b1 88857ea 368f9b1 547a858 88857ea 547a858 88857ea 547a858 88857ea 547a858 88857ea 547a858 88857ea 547a858 88857ea 368f9b1 88857ea 48dff37 c2c2c15 1b3fdc4 48dff37 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 | // RenderContext β CWormsApp rendering dispatch subobject.
// Manages the software framebuffer and dispatches rendering calls to the active
// renderer backend (CompatRenderer, OpenGLCPU, or DDraw).
crate::define_addresses! {
class "CWormsApp" {
/// CWormsApp__FlipSurface β dispatches to renderer backend vtable[1]
fn/Fastcall CWORMSAPP_FLIP_SURFACE = 0x005A_2700;
/// ConstructFrameBuffer β allocates software framebuffer, inits renderer
fn/Fastcall CONSTRUCT_FRAME_BUFFER_THISCALL = 0x005A_2430;
/// CWormsApp__ReleaseFrameBuffer
fn/Fastcall CWORMSAPP_RELEASE_FRAME_BUFFER = 0x005A_24A0;
/// CWormsApp__FillRect β lock surface, memset rows, unlock
fn/Fastcall CWORMSAPP_FILL_RECT = 0x005A_25C0;
/// CWormsApp__BlitToFrameBuffer β optimized blit from surface to framebuffer
fn/Fastcall CWORMSAPP_BLIT_TO_FRAME_BUFFER = 0x005A_2A40;
/// CWormsApp__DrawLandscape β blit with clipping and transparency
fn/Fastcall CWORMSAPP_DRAW_LANDSCAPE = 0x005A_2790;
/// ClearFrameBuffer β memset(framebuffer, 0, w*h)
fn CWORMSAPP_CLEAR_FRAME_BUFFER = 0x005A_23F0;
}
}
/// Result buffer for RenderContext and CompatRenderer `__fastcall` vtable calls.
///
/// These classes use `__fastcall` convention: ECX = this, EDX = result buffer pointer.
/// The callee writes a result (typically an HRESULT or pointer) into `value` and
/// returns `EDX` in `EAX`. Most callers allocate this on the stack and ignore the result.
#[repr(C)]
#[derive(Clone, Copy, Default)]
pub struct FastcallResult {
pub value: u32,
_pad: u32,
}
/// RenderContext vtable (0x662EC8, 25 slots).
///
/// Many slots are thin thunks that forward to the renderer backend
/// via `*(this+0x18)->vtable[N]`. Others manage the software framebuffer
/// or perform blitting directly.
///
/// ## Calling convention
///
/// All methods use `__fastcall`: ECX = this, EDX = `*mut FastcallResult` (caller-allocated
/// 8-byte result buffer). Remaining parameters are on the stack, callee-cleaned.
/// Most callers ignore the result value.
///
/// ## Slot categories
///
/// - **Renderer thunks** (0, 2, 4, 5, 8, 10, 11): Forward to backend
/// - **Framebuffer management** (3, 6, 7, 9, 15/17, 16/18, 20): Manage G_FRAME_BUFFER_*
/// - **Blitting** (19, 23, 24): FillRect, DrawLandscape, BlitToFrameBuffer
/// - **Surface management** (12, 13, 22): Renderer queries and surface allocation
/// - **Stub** (14): Returns 0
#[openwa_core::vtable(size = 25, va = 0x0066_2EC8, class = "RenderContext")]
pub struct RenderContextVtable {
/// renderer thunk -> backend vtable[0] (init/create) (0x4E3420, RET 0x8)
#[slot(0)]
pub renderer_init: unsafe extern "fastcall" fn(
this: *mut RenderContext,
result: *mut FastcallResult,
p2: u32,
p3: u32,
) -> *mut FastcallResult,
/// flip/present β dispatches to renderer backend vtable[1] (0x5A2700)
#[slot(1)]
pub flip_surface: unsafe extern "fastcall" fn(
this: *mut RenderContext,
result: *mut FastcallResult,
) -> *mut FastcallResult,
/// renderer thunk -> backend vtable[2] (reset state) (0x4E3440)
#[slot(2)]
pub renderer_reset: unsafe extern "fastcall" fn(
this: *mut RenderContext,
result: *mut FastcallResult,
) -> *mut FastcallResult,
/// get framebuffer dimensions β reads G_FRAME_BUFFER_WIDTH/HEIGHT (0x5A2660, RET 0x4)
#[slot(3)]
pub get_framebuffer_dims: unsafe extern "fastcall" fn(
this: *mut RenderContext,
result: *mut FastcallResult,
out: *mut u32,
) -> *mut FastcallResult,
/// renderer thunk -> backend vtable[4] (enum display modes) (0x4E3460, RET 0x8)
#[slot(4)]
pub renderer_enum_modes: unsafe extern "fastcall" fn(
this: *mut RenderContext,
result: *mut FastcallResult,
p2: u32,
p3: u32,
) -> *mut FastcallResult,
/// renderer thunk -> backend vtable[5] (tail jump) (0x4E3480)
#[slot(5)]
pub renderer_slot5: unsafe extern "fastcall" fn(
this: *mut RenderContext,
result: *mut FastcallResult,
) -> *mut FastcallResult,
/// construct framebuffer β wa_malloc(w*h), init renderer (0x5A2430, RET 0x8)
#[slot(6)]
pub construct_frame_buffer: unsafe extern "fastcall" fn(
this: *mut RenderContext,
result: *mut FastcallResult,
width: i32,
height: i32,
) -> *mut FastcallResult,
/// release framebuffer β calls renderer teardown, frees buffer (0x5A24A0)
#[slot(7)]
pub release_frame_buffer: unsafe extern "fastcall" fn(
this: *mut RenderContext,
result: *mut FastcallResult,
p2: i32,
) -> *mut FastcallResult,
/// renderer thunk -> backend vtable[8] (0x5A24F0)
#[slot(8)]
pub renderer_slot8: unsafe extern "fastcall" fn(
this: *mut RenderContext,
result: *mut FastcallResult,
) -> *mut FastcallResult,
/// lock framebuffer for pixel access (0x5A2530)
///
/// Returns framebuffer pointer and stride for direct pixel manipulation.
#[slot(9)]
pub lock_framebuffer: unsafe extern "fastcall" fn(
this: *mut RenderContext,
result: *mut FastcallResult,
p2: u32,
p3: u32,
p4: u32,
p5: u32,
) -> *mut FastcallResult,
/// renderer thunk -> backend vtable[10] (0x5A2510)
#[slot(10)]
pub renderer_restore_dims: unsafe extern "fastcall" fn(
this: *mut RenderContext,
result: *mut FastcallResult,
) -> *mut FastcallResult,
/// renderer thunk -> backend vtable[11] (restore surface) (0x5A25A0)
#[slot(11)]
pub renderer_restore_surface: unsafe extern "fastcall" fn(
this: *mut RenderContext,
result: *mut FastcallResult,
) -> *mut FastcallResult,
/// allocate error/result object (0x5A2720, RET 0x4)
#[slot(12)]
pub alloc_error_result: unsafe extern "fastcall" fn(
this: *mut RenderContext,
result: *mut FastcallResult,
p2: u32,
) -> *mut FastcallResult,
/// get renderer surface pointer (0x5A26C0)
///
/// Queries `renderer->vtable[12]` with G_FRAME_BUFFER_PTR.
#[slot(13)]
pub get_renderer_surface: unsafe extern "fastcall" fn(
this: *mut RenderContext,
result: *mut FastcallResult,
) -> *mut FastcallResult,
/// stub β returns 0 (CGameTask__vt18, 0x545780)
#[slot(14)]
pub stub_ret_zero: unsafe extern "fastcall" fn(
this: *mut RenderContext,
result: *mut FastcallResult,
) -> *mut FastcallResult,
/// lock surface for reading (0x5A2690, RET 0x8)
///
/// Writes framebuffer pointer to `*out_data` and stride to `*out_stride`.
#[slot(15)]
pub lock_surface_read: unsafe extern "fastcall" fn(
this: *mut RenderContext,
result: *mut FastcallResult,
out_data: *mut u32,
out_stride: *mut u32,
) -> *mut FastcallResult,
/// unlock surface (0x5A2C10, RET 0x4)
///
/// No-op for software framebuffer β just returns success code.
#[slot(16)]
pub unlock_surface_read: unsafe extern "fastcall" fn(
this: *mut RenderContext,
result: *mut FastcallResult,
p2: u32,
) -> *mut FastcallResult,
/// lock surface for writing (0x5A2690 β same fn as slot 15, RET 0x8)
///
/// Writes framebuffer pointer to `*out_data` and stride to `*out_stride`.
#[slot(17)]
pub lock_surface_write: unsafe extern "fastcall" fn(
this: *mut RenderContext,
result: *mut FastcallResult,
out_data: *mut *mut u8,
out_stride: *mut u32,
) -> *mut FastcallResult,
/// unlock surface after writing (0x5A2C10 β same fn as slot 16, RET 0x4)
///
/// `data` is the framebuffer pointer previously returned from
/// `lock_surface_write`. The original ignores it; we still pass it
/// through for fidelity.
#[slot(18)]
pub unlock_surface_write: unsafe extern "fastcall" fn(
this: *mut RenderContext,
result: *mut FastcallResult,
data: *mut u8,
) -> *mut FastcallResult,
/// fill rectangle β lock, memset rows, unlock (0x5A25C0)
///
/// Params: x, y, width, height, fill_value.
#[slot(19)]
pub fill_rect: unsafe extern "fastcall" fn(
this: *mut RenderContext,
result: *mut FastcallResult,
x: i32,
y: i32,
width: i32,
height: i32,
fill_value: u32,
) -> *mut FastcallResult,
/// clear framebuffer β memset(ptr, 0, w*h) (0x5A23F0)
#[slot(20)]
pub clear_frame_buffer: unsafe extern "fastcall" fn(
this: *mut RenderContext,
result: *mut FastcallResult,
) -> *mut FastcallResult,
/// trampoline to slot 20 via vtable dispatch (0x5A2420)
#[slot(21)]
pub clear_frame_buffer_indirect: unsafe extern "fastcall" fn(
this: *mut RenderContext,
result: *mut FastcallResult,
) -> *mut FastcallResult,
/// allocate surface object β wa_malloc(0x14) (0x5A2760)
#[slot(22)]
pub alloc_surface: unsafe extern "fastcall" fn(
this: *mut RenderContext,
result: *mut FastcallResult,
) -> *mut FastcallResult,
/// draw landscape β blit a `Surface` to the framebuffer with optional
/// color-key transparency (0x5A2790).
///
/// 8 stack args (verified by RET 0x20 at 0x5a2cba):
/// - `surface`: source `Surface*` (its vtable's slot 17 = lock-write,
/// slot 18 = unlock are dispatched internally to read pixel data)
/// - `dst_x`/`dst_y`: framebuffer destination top-left
/// - `src_x`/`src_y`: rect origin within the surface to copy from
/// - `width`/`height`: rect size
/// - `flags`: bit 1 (`0x2`) = use color-key transparency (skip pixels
/// equal to the surface's color-key); bit 0 (`0x1`) is set by the
/// caller in `BlitBitmapClipped` and is reserved/ignored by the
/// blit loop here.
///
/// Used by `DisplayGfx::DrawTiledBitmap` (slot 11) and
/// `DisplayGfx::DrawTiledTerrain` (slot 22) via the `CBitmap` blit
/// helper at `FUN_00403c60`.
#[slot(23)]
pub draw_landscape: unsafe extern "fastcall" fn(
this: *mut RenderContext,
result: *mut FastcallResult,
surface: *mut u8,
dst_x: i32,
dst_y: i32,
src_x: i32,
src_y: i32,
width: i32,
height: i32,
flags: u32,
) -> *mut FastcallResult,
/// blit surface to framebuffer β optimized copy with stride alignment (0x5A2A40)
#[slot(24)]
pub blit_to_frame_buffer: unsafe extern "fastcall" fn(
this: *mut RenderContext,
result: *mut FastcallResult,
surface: *mut u8,
y_offset: i32,
) -> *mut FastcallResult,
}
/// RenderContext β CWormsApp rendering dispatch subobject.
///
/// Stored as a global pointer at 0x79D6D4 (g_RenderContext).
/// The full object layout is part of CWormsApp; only key fields are mapped here.
#[repr(C)]
pub struct RenderContext {
/// 0x00: Vtable pointer (0x662EC8)
pub vtable: *const RenderContextVtable,
/// 0x04-0x17: Unknown (part of CWormsApp layout)
pub _unknown_04: [u8; 0x14],
/// 0x18: Pointer to renderer backend (CompatRenderer, OpenGLCPU, or DDraw object)
pub renderer_backend: *mut u8,
}
const _: () = assert!(core::mem::size_of::<RenderContext>() == 0x1C);
// Generate calling wrappers: RenderContext::get_renderer_surface_raw(), etc.
// Use the `_raw` variants to avoid LLVM noalias miscompilation.
// Callers must pass a `&mut FastcallResult` buffer (allocated on the stack).
bind_RenderContextVtable!(RenderContext, vtable);
// ---------------------------------------------------------------------------
// Surface β DDraw/D3D/OpenGL surface object created by alloc_surface (slot 22)
// ---------------------------------------------------------------------------
/// Vtable for `Surface` objects allocated by `RenderContext::alloc_surface`
/// (slot 22). This is the rendering-backend surface interface β different
/// backends (CompatRenderer / OpenGLCPU / DDraw) implement different vtables
/// at the same slot positions.
///
/// Slots typed here are the ones used by `DisplayGfx::DrawTiledBitmap`
/// (slot 11) and `LoadSpriteByName` (which already uses raw transmutes).
/// The remaining slots are unmapped β extend as needed.
///
/// All slots are `__fastcall(this, *FastcallResult, ...args)`. The
/// `FastcallResult.value` field receives a non-zero failure code on
/// `init_surface` failure (slot 11 retries with bpp=4 if bpp=8 fails).
#[openwa_core::vtable(size = 8, class = "Surface")]
pub struct SurfaceVtable {
/// lock surface for direct pixel access (slot 3).
///
/// Writes the locked surface base pointer to `*out_data` and the row
/// stride (bytes between rows) to `*out_stride`.
#[slot(3)]
pub lock_surface: unsafe extern "fastcall" fn(
this: *mut Surface,
result: *mut FastcallResult,
out_data: *mut *mut u8,
out_stride: *mut i32,
) -> *mut FastcallResult,
/// unlock surface after editing (slot 4).
///
/// `addr` is the surface base pointer previously obtained from
/// `lock_surface`'s `out_data`.
#[slot(4)]
pub unlock_surface: unsafe extern "fastcall" fn(
this: *mut Surface,
result: *mut FastcallResult,
addr: *mut u8,
) -> *mut FastcallResult,
/// init/recreate surface storage (slot 5).
///
/// `(width, height, bpp)`. Returns 0 in `*result.value` on success;
/// non-zero on failure.
#[slot(5)]
pub init_surface: unsafe extern "fastcall" fn(
this: *mut Surface,
result: *mut FastcallResult,
width: i32,
height: i32,
bpp: i32,
) -> *mut FastcallResult,
/// release surface backing storage (slot 6).
///
/// Pure fastcall β no stack args. Writes a result code into
/// `*result.value` (which most callers ignore). Called from the
/// `DisplayGfx` destructor's CBitmap-vec teardown loop on every
/// non-null `CBitmap.surface` before the bitmap itself is freed.
#[slot(6)]
pub release: unsafe extern "fastcall" fn(
this: *mut Surface,
result: *mut FastcallResult,
) -> *mut FastcallResult,
/// set color-key (transparency) (slot 7).
///
/// Used by `load_sprite_by_name` after `init_surface` to enable
/// transparency on the freshly-allocated frame surface (color key
/// `0`, flag `0x10`). The result code is unused by all known callers.
#[slot(7)]
pub set_color_key: unsafe extern "fastcall" fn(
this: *mut Surface,
result: *mut FastcallResult,
color_key: u32,
flags: u32,
) -> *mut FastcallResult,
}
/// Backend-specific surface object created by
/// `RenderContext::alloc_surface` (slot 22). Layout beyond the vtable
/// pointer is opaque (varies by backend); we only access it through the
/// `SurfaceVtable` slots.
#[repr(C)]
pub struct Surface {
/// 0x00: vtable pointer (one of several backend vtables)
pub vtable: *const SurfaceVtable,
}
bind_SurfaceVtable!(Surface, vtable);
|