paavohtl's picture
Claude Opus 4.6 (1M context)
refactor: migrate all render queue commands to typed RenderMessage enum
12a0785
Raw History Blame Contribute Delete
10.2 kB
//! RenderQueue enqueue hooks and the per-frame dispatcher bridge.
use openwa_core::address::va;
use openwa_core::bitgrid::DisplayBitGrid;
use openwa_core::fixed::Fixed;
use openwa_core::render::display::vtable::TiledBitmapSource;
use openwa_core::render::display::DisplayGfx;
use openwa_core::render::message::RenderMessage;
use openwa_core::render::queue::RenderQueue;
use openwa_core::render::queue_dispatch::{render_drawing_queue, ClipContext};
use openwa_core::render::SpriteOp;
use openwa_core::task::{BungeeTrailTask, WeaponAimTask};
use crate::hook::{self, usercall_trampoline};
// EnqueueTiledBitmap (0x541D60)
usercall_trampoline!(fn trampoline_enqueue_tiled_bitmap; impl_fn = enqueue_tiled_bitmap_impl;
reg = eax; stack_params = 3; ret_bytes = "0xC");
unsafe extern "cdecl" fn enqueue_tiled_bitmap_impl(
queue: *mut RenderQueue,
y: Fixed,
source: *const TiledBitmapSource,
flags: u32,
) {
let _ = (*queue).push_typed(
0x1B_0000,
RenderMessage::TiledBitmap {
x: Fixed(0xFF00_0000u32 as i32),
y,
source,
flags: flags as u8,
},
);
}
// DrawLineStrip (0x541DD0) — variable-size: vertex data via alloc_aux
usercall_trampoline!(fn trampoline_draw_line_strip; impl_fn = draw_line_strip_impl;
regs = [eax, edi]; stack_params = 2; ret_bytes = "0x8");
unsafe extern "cdecl" fn draw_line_strip_impl(
queue: *mut RenderQueue,
count: u32,
vertices: *const [i32; 3],
color: u32,
) {
let rq = &mut *queue;
let byte_len = count as usize * core::mem::size_of::<[i32; 3]>();
if let Some(vert_ptr) = rq.alloc_aux(byte_len) {
core::ptr::copy_nonoverlapping(vertices as *const u8, vert_ptr, byte_len);
let _ = rq.push_typed(
0xE_0000,
RenderMessage::LineStrip {
count,
color,
vertices: vert_ptr as *const [i32; 3],
},
);
}
}
// DrawPolygon (0x541E50) — variable-size: vertex data via alloc_aux
usercall_trampoline!(fn trampoline_draw_polygon; impl_fn = draw_polygon_impl;
regs = [ecx, esi]; stack_params = 3; ret_bytes = "0xC");
unsafe extern "cdecl" fn draw_polygon_impl(
queue: *mut RenderQueue,
count: u32,
vertices: *const [i32; 3],
color1: u32,
color2: u32,
) {
let rq = &mut *queue;
let byte_len = count as usize * core::mem::size_of::<[i32; 3]>();
if let Some(vert_ptr) = rq.alloc_aux(byte_len) {
core::ptr::copy_nonoverlapping(vertices as *const u8, vert_ptr, byte_len);
let _ = rq.push_typed(
0xE_0000,
RenderMessage::Polygon {
count,
color1,
color2,
vertices: vert_ptr as *const [i32; 3],
},
);
}
}
// DrawCrosshair (0x541ED0)
usercall_trampoline!(fn trampoline_draw_crosshair; impl_fn = draw_crosshair_impl;
reg = ecx; stack_params = 5; ret_bytes = "0x14");
unsafe extern "cdecl" fn draw_crosshair_impl(
queue: *mut RenderQueue,
layer: u32,
x: Fixed,
y: Fixed,
color_fg: u32,
color_bg: u32,
) {
let _ = (*queue).push_typed(
layer,
RenderMessage::Crosshair {
color_fg,
color_bg,
x,
y,
},
);
}
// DrawRect (0x541F40)
usercall_trampoline!(fn trampoline_draw_rect; impl_fn = draw_rect_impl;
regs = [ecx, edx]; stack_params = 6; ret_bytes = "0x18");
unsafe extern "cdecl" fn draw_rect_impl(
queue: *mut RenderQueue,
y_clip: Fixed,
layer: u32,
x1: Fixed,
y1: Fixed,
x2: Fixed,
y2: Fixed,
color: u32,
) {
let _ = (*queue).push_typed(
layer,
RenderMessage::FillRect {
color,
x1: x1.floor(),
y1: y1.floor(),
x2: x2.floor(),
y2: y2.floor(),
ref_z: y_clip.floor().0,
},
);
}
// DrawSpriteGlobal (0x541FE0)
usercall_trampoline!(fn trampoline_draw_sprite_global; impl_fn = draw_sprite_global_impl;
regs = [eax, ecx]; stack_params = 4; ret_bytes = "0x10");
unsafe extern "cdecl" fn draw_sprite_global_impl(
y_pos: Fixed,
queue: *mut RenderQueue,
layer: u32,
x_pos: Fixed,
sprite: SpriteOp,
frame: u32,
) {
let _ = (*queue).push_typed(
layer,
RenderMessage::Sprite {
local: false,
x: x_pos.floor(),
y: y_pos.floor(),
sprite,
palette: frame,
},
);
}
// DrawSpriteLocal (0x542060)
usercall_trampoline!(fn trampoline_draw_sprite_local; impl_fn = draw_sprite_local_impl;
regs = [eax, ecx]; stack_params = 4; ret_bytes = "0x10");
unsafe extern "cdecl" fn draw_sprite_local_impl(
y_pos: Fixed,
queue: *mut RenderQueue,
layer: u32,
x_pos: Fixed,
sprite: SpriteOp,
frame: u32,
) {
let _ = (*queue).push_typed(
layer,
RenderMessage::Sprite {
local: true,
x: x_pos.floor(),
y: y_pos.floor(),
sprite,
palette: frame,
},
);
}
// DrawSpriteOffset (0x5420E0)
usercall_trampoline!(fn trampoline_draw_sprite_offset; impl_fn = draw_sprite_offset_impl;
regs = [ecx, edx]; stack_params = 6; ret_bytes = "0x18");
unsafe extern "cdecl" fn draw_sprite_offset_impl(
queue: *mut RenderQueue,
y_clip: Fixed,
layer: u32,
x_pos: Fixed,
y_pos: Fixed,
flags: u32,
sprite: SpriteOp,
palette: u32,
) {
let _ = (*queue).push_typed(
layer,
RenderMessage::SpriteOffset {
flags,
x: x_pos.floor(),
y: y_pos.floor(),
ref_z_2: y_clip.floor().0,
sprite,
palette,
},
);
}
// DrawBitmapGlobal (0x542170)
usercall_trampoline!(fn trampoline_draw_bitmap_global; impl_fn = draw_bitmap_global_impl;
regs = [ecx, edx]; stack_params = 7; ret_bytes = "0x1C");
unsafe extern "cdecl" fn draw_bitmap_global_impl(
queue: *mut RenderQueue,
y_pos: Fixed,
layer: u32,
x_pos: Fixed,
bitmap: *mut DisplayBitGrid,
src_y: i32,
src_w: i32,
src_h: i32,
flags: u32,
) {
let _ = (*queue).push_typed(
layer,
RenderMessage::BitmapGlobal {
x: x_pos.floor(),
y: y_pos.floor(),
bitmap,
src_y,
src_w,
src_h,
flags,
},
);
}
// DrawTextboxLocal (0x542200)
usercall_trampoline!(fn trampoline_draw_textbox_local; impl_fn = draw_textbox_local_impl;
regs = [ecx, edx]; stack_params = 6; ret_bytes = "0x18");
unsafe extern "cdecl" fn draw_textbox_local_impl(
q: *mut RenderQueue,
y_pos: Fixed,
layer: u32,
x_pos: Fixed,
bitmap: *mut DisplayBitGrid,
src_w: i32,
src_h: i32,
flags: u32,
) {
let _ = (*q).push_typed(
layer,
RenderMessage::TextboxLocal {
x: x_pos.floor(),
y: y_pos.floor(),
bitmap,
src_w,
src_h,
flags,
},
);
}
// DrawBungeeTrail (0x500720)
unsafe extern "stdcall" fn draw_bungee_trail_impl(
task: *const BungeeTrailTask,
style: u32,
fill: u32,
) {
openwa_core::render::bungee_trail::draw_bungee_trail(task, style, fill);
}
// DrawCrosshairLine (0x5197D0)
usercall_trampoline!(fn trampoline_draw_crosshair_line; impl_fn = draw_crosshair_line_impl;
reg = edi);
unsafe extern "cdecl" fn draw_crosshair_line_impl(task: *const WeaponAimTask) {
openwa_core::render::crosshair_line::draw_crosshair_line(task);
}
// RenderDrawingQueue (0x542350)
usercall_trampoline!(fn trampoline_render_drawing_queue;
impl_fn = render_drawing_queue_impl;
reg = eax; stack_params = 2; ret_bytes = "0x8");
unsafe extern "cdecl" fn render_drawing_queue_impl(
rq: *mut RenderQueue,
display: *mut DisplayGfx,
clip: *mut ClipContext,
) {
render_drawing_queue(rq, display, clip);
}
pub fn install() -> Result<(), String> {
unsafe {
let _ = hook::install(
"EnqueueTiledBitmap",
va::RQ_ENQUEUE_TILED_BITMAP,
trampoline_enqueue_tiled_bitmap as *const (),
)?;
let _ = hook::install(
"DrawLineStrip",
va::RQ_DRAW_LINE_STRIP,
trampoline_draw_line_strip as *const (),
)?;
let _ = hook::install(
"DrawPolygon",
va::RQ_DRAW_POLYGON,
trampoline_draw_polygon as *const (),
)?;
let _ = hook::install(
"DrawCrosshair",
va::RQ_DRAW_CROSSHAIR,
trampoline_draw_crosshair as *const (),
)?;
let _ = hook::install(
"DrawRect",
va::RQ_DRAW_RECT,
trampoline_draw_rect as *const (),
)?;
let _ = hook::install(
"DrawSpriteGlobal",
va::RQ_DRAW_SPRITE_GLOBAL,
trampoline_draw_sprite_global as *const (),
)?;
let _ = hook::install(
"DrawSpriteLocal",
va::RQ_DRAW_SPRITE_LOCAL,
trampoline_draw_sprite_local as *const (),
)?;
let _ = hook::install(
"DrawSpriteOffset",
va::RQ_DRAW_SPRITE_OFFSET,
trampoline_draw_sprite_offset as *const (),
)?;
let _ = hook::install(
"DrawBitmapGlobal",
va::RQ_DRAW_BITMAP_GLOBAL,
trampoline_draw_bitmap_global as *const (),
)?;
let _ = hook::install(
"DrawTextboxLocal",
va::RQ_DRAW_TEXTBOX_LOCAL,
trampoline_draw_textbox_local as *const (),
)?;
let _ = hook::install(
"DrawBungeeTrail",
va::DRAW_BUNGEE_TRAIL,
draw_bungee_trail_impl as *const (),
)?;
let _ = hook::install(
"DrawCrosshairLine",
va::DRAW_CROSSHAIR_LINE,
trampoline_draw_crosshair_line as *const (),
)?;
let _ = hook::install(
"RenderDrawingQueue",
va::RQ_RENDER_DRAWING_QUEUE,
trampoline_render_drawing_queue as *const (),
)?;
}
Ok(())
}