feat: port DDDisplay draw_line, draw_line_clipped, draw_pixel_strip
Browse filesdraw_line (slot 13) and draw_line_clipped (slot 14) apply Fixed-point
camera offset and delegate to BitGrid line-drawing routines at 0x4F7A60
and 0x4F7500 (both stdcall). draw_pixel_strip (slot 15) iterates
count+1 pixels along a Fixed-point vector using put_pixel_clipped.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
crates/openwa-core/src/address.rs
CHANGED
|
@@ -73,7 +73,8 @@ pub mod va {
|
|
| 73 |
pub use crate::display::base::DISPLAY_BASE_VTABLE;
|
| 74 |
pub use crate::display::bitgrid::{
|
| 75 |
BitGridBaseVtable, BitGridCollisionVtable, BitGridDisplayVtable, BIT_GRID_BASE_VTABLE,
|
| 76 |
-
BIT_GRID_COLLISION_VTABLE, BIT_GRID_DISPLAY_VTABLE, BIT_GRID_INIT,
|
|
|
|
| 77 |
};
|
| 78 |
pub use crate::display::compat_renderer::{
|
| 79 |
CompatRendererVtable, COMPAT_RENDERER_VTABLE, DDRAW8_RENDERER_VTABLE,
|
|
|
|
| 73 |
pub use crate::display::base::DISPLAY_BASE_VTABLE;
|
| 74 |
pub use crate::display::bitgrid::{
|
| 75 |
BitGridBaseVtable, BitGridCollisionVtable, BitGridDisplayVtable, BIT_GRID_BASE_VTABLE,
|
| 76 |
+
BIT_GRID_COLLISION_VTABLE, BIT_GRID_DISPLAY_VTABLE, BIT_GRID_INIT, DRAW_LINE_CLIPPED,
|
| 77 |
+
DRAW_LINE_TWO_COLOR,
|
| 78 |
};
|
| 79 |
pub use crate::display::compat_renderer::{
|
| 80 |
CompatRendererVtable, COMPAT_RENDERER_VTABLE, DDRAW8_RENDERER_VTABLE,
|
crates/openwa-core/src/display/bitgrid.rs
CHANGED
|
@@ -44,6 +44,10 @@ crate::define_addresses! {
|
|
| 44 |
class "BitGrid" {
|
| 45 |
/// BitGrid::init (0x4F6370) — allocates buffer, sets base vtable
|
| 46 |
fn BIT_GRID_INIT = 0x004F_6370;
|
|
|
|
|
|
|
|
|
|
|
|
|
| 47 |
}
|
| 48 |
}
|
| 49 |
|
|
|
|
| 44 |
class "BitGrid" {
|
| 45 |
/// BitGrid::init (0x4F6370) — allocates buffer, sets base vtable
|
| 46 |
fn BIT_GRID_INIT = 0x004F_6370;
|
| 47 |
+
/// Clipped line draw on 8bpp BitGrid (0x4F7500)
|
| 48 |
+
fn DRAW_LINE_CLIPPED = 0x004F_7500;
|
| 49 |
+
/// Two-color line draw on 8bpp BitGrid (0x4F7A60)
|
| 50 |
+
fn DRAW_LINE_TWO_COLOR = 0x004F_7A60;
|
| 51 |
}
|
| 52 |
}
|
| 53 |
|
crates/openwa-core/src/display/dd_display.rs
CHANGED
|
@@ -640,3 +640,105 @@ pub unsafe extern "thiscall" fn draw_crosshair(
|
|
| 640 |
DisplayBitGrid::put_pixel_clipped_raw(layer, cx, cy + 1, fg);
|
| 641 |
DisplayBitGrid::put_pixel_clipped_raw(layer, cx + 1, cy + 1, fg);
|
| 642 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 640 |
DisplayBitGrid::put_pixel_clipped_raw(layer, cx, cy + 1, fg);
|
| 641 |
DisplayBitGrid::put_pixel_clipped_raw(layer, cx + 1, cy + 1, fg);
|
| 642 |
}
|
| 643 |
+
|
| 644 |
+
/// Port of DDDisplay::DrawLine (vtable slot 13, 0x56BDB0).
|
| 645 |
+
///
|
| 646 |
+
/// Draws a two-color line. Fixed-point coordinates with camera offset
|
| 647 |
+
/// applied as `camera * 0x10000 + coord`. Delegates to the BitGrid
|
| 648 |
+
/// line-drawing routine at 0x4F7A60.
|
| 649 |
+
///
|
| 650 |
+
/// # Safety
|
| 651 |
+
/// `this` must be a valid `*mut DDDisplay` (actually a `*mut DisplayGfx`).
|
| 652 |
+
pub unsafe extern "thiscall" fn draw_line(
|
| 653 |
+
this: *mut DDDisplay,
|
| 654 |
+
x1: Fixed,
|
| 655 |
+
y1: Fixed,
|
| 656 |
+
x2: Fixed,
|
| 657 |
+
y2: Fixed,
|
| 658 |
+
color1: u32,
|
| 659 |
+
color2: u32,
|
| 660 |
+
) {
|
| 661 |
+
let gfx = this as *mut DisplayGfx;
|
| 662 |
+
let cam_x = Fixed::from_int((*gfx).camera_x);
|
| 663 |
+
let cam_y = Fixed::from_int((*gfx).camera_y);
|
| 664 |
+
|
| 665 |
+
acquire_render_lock(gfx);
|
| 666 |
+
|
| 667 |
+
let draw: unsafe extern "stdcall" fn(*mut DisplayBitGrid, i32, i32, i32, i32, u32, u32) =
|
| 668 |
+
core::mem::transmute(rb(va::DRAW_LINE_TWO_COLOR) as usize);
|
| 669 |
+
draw(
|
| 670 |
+
(*gfx).layer_0,
|
| 671 |
+
(x1 + cam_x).to_raw(),
|
| 672 |
+
(y1 + cam_y).to_raw(),
|
| 673 |
+
(x2 + cam_x).to_raw(),
|
| 674 |
+
(y2 + cam_y).to_raw(),
|
| 675 |
+
color1,
|
| 676 |
+
color2,
|
| 677 |
+
);
|
| 678 |
+
}
|
| 679 |
+
|
| 680 |
+
/// Port of DDDisplay::DrawLineClipped (vtable slot 14, 0x56BD50).
|
| 681 |
+
///
|
| 682 |
+
/// Draws a single-color clipped line. Fixed-point coordinates with camera
|
| 683 |
+
/// offset. Delegates to the BitGrid clipped line routine at 0x4F7500.
|
| 684 |
+
///
|
| 685 |
+
/// # Safety
|
| 686 |
+
/// `this` must be a valid `*mut DDDisplay` (actually a `*mut DisplayGfx`).
|
| 687 |
+
pub unsafe extern "thiscall" fn draw_line_clipped(
|
| 688 |
+
this: *mut DDDisplay,
|
| 689 |
+
x1: Fixed,
|
| 690 |
+
y1: Fixed,
|
| 691 |
+
x2: Fixed,
|
| 692 |
+
y2: Fixed,
|
| 693 |
+
color: u32,
|
| 694 |
+
) {
|
| 695 |
+
let gfx = this as *mut DisplayGfx;
|
| 696 |
+
let cam_x = Fixed::from_int((*gfx).camera_x);
|
| 697 |
+
let cam_y = Fixed::from_int((*gfx).camera_y);
|
| 698 |
+
|
| 699 |
+
acquire_render_lock(gfx);
|
| 700 |
+
|
| 701 |
+
let draw: unsafe extern "stdcall" fn(*mut DisplayBitGrid, i32, i32, i32, i32, u32) =
|
| 702 |
+
core::mem::transmute(rb(va::DRAW_LINE_CLIPPED) as usize);
|
| 703 |
+
draw(
|
| 704 |
+
(*gfx).layer_0,
|
| 705 |
+
(x1 + cam_x).to_raw(),
|
| 706 |
+
(y1 + cam_y).to_raw(),
|
| 707 |
+
(x2 + cam_x).to_raw(),
|
| 708 |
+
(y2 + cam_y).to_raw(),
|
| 709 |
+
color,
|
| 710 |
+
);
|
| 711 |
+
}
|
| 712 |
+
|
| 713 |
+
/// Port of DDDisplay::DrawPixelStrip (vtable slot 15, 0x56BE10).
|
| 714 |
+
///
|
| 715 |
+
/// Draws `count + 1` pixels starting at (x, y), stepping by (dx, dy) each
|
| 716 |
+
/// iteration. All coordinates are Fixed-point. Camera applied as
|
| 717 |
+
/// `camera * 0x10000 + coord`.
|
| 718 |
+
///
|
| 719 |
+
/// # Safety
|
| 720 |
+
/// `this` must be a valid `*mut DDDisplay` (actually a `*mut DisplayGfx`).
|
| 721 |
+
pub unsafe extern "thiscall" fn draw_pixel_strip(
|
| 722 |
+
this: *mut DDDisplay,
|
| 723 |
+
x: Fixed,
|
| 724 |
+
y: Fixed,
|
| 725 |
+
dx: Fixed,
|
| 726 |
+
dy: Fixed,
|
| 727 |
+
count: i32,
|
| 728 |
+
color: u32,
|
| 729 |
+
) {
|
| 730 |
+
let gfx = this as *mut DisplayGfx;
|
| 731 |
+
let mut cx = Fixed::from_int((*gfx).camera_x) + x;
|
| 732 |
+
let mut cy = Fixed::from_int((*gfx).camera_y) + y;
|
| 733 |
+
|
| 734 |
+
acquire_render_lock(gfx);
|
| 735 |
+
|
| 736 |
+
let layer = (*gfx).layer_0;
|
| 737 |
+
if count >= 0 {
|
| 738 |
+
for _ in 0..=count {
|
| 739 |
+
DisplayBitGrid::put_pixel_clipped_raw(layer, cx.to_int(), cy.to_int(), color as u8);
|
| 740 |
+
cx += dx;
|
| 741 |
+
cy += dy;
|
| 742 |
+
}
|
| 743 |
+
}
|
| 744 |
+
}
|
crates/openwa-dll/src/replacements/display.rs
CHANGED
|
@@ -82,6 +82,9 @@ pub fn install() -> Result<(), String> {
|
|
| 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 |
draw_crosshair => dd_display::draw_crosshair,
|
| 86 |
draw_outlined_pixel => dd_display::draw_outlined_pixel,
|
| 87 |
fill_rect => dd_display::fill_rect,
|
|
@@ -89,7 +92,7 @@ pub fn install() -> Result<(), String> {
|
|
| 89 |
set_camera_offset => dd_display::set_camera_offset,
|
| 90 |
set_clip_rect => dd_display::set_clip_rect,
|
| 91 |
})?;
|
| 92 |
-
let _ = log_line("[Display] DDDisplay: patched
|
| 93 |
}
|
| 94 |
|
| 95 |
Ok(())
|
|
|
|
| 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 |
+
draw_line => dd_display::draw_line,
|
| 86 |
+
draw_line_clipped => dd_display::draw_line_clipped,
|
| 87 |
+
draw_pixel_strip => dd_display::draw_pixel_strip,
|
| 88 |
draw_crosshair => dd_display::draw_crosshair,
|
| 89 |
draw_outlined_pixel => dd_display::draw_outlined_pixel,
|
| 90 |
fill_rect => dd_display::fill_rect,
|
|
|
|
| 92 |
set_camera_offset => dd_display::set_camera_offset,
|
| 93 |
set_clip_rect => dd_display::set_clip_rect,
|
| 94 |
})?;
|
| 95 |
+
let _ = log_line("[Display] DDDisplay: patched 10 methods → Rust");
|
| 96 |
}
|
| 97 |
|
| 98 |
Ok(())
|