refactor: type DisplayGfx hook_vec fields + add destructor addresses
Browse filesRenames the four `object_vector_*` fields at +0x24DF8..+0x24E07 to
`hook_vec_proxy/first/last/end` and documents the underlying MSVC 2005
`std::vector<FramePostProcessHook*>` layout. The proxy field at offset
0 (the iterator-debug `_Container_proxy*`) was previously labelled as
the start pointer, a latent off-by-one. The pointee type is left as
`*mut u8` until the FramePostProcessHook struct lands.
Adds new `define_addresses!` entries to `display/gfx.rs` for the
destructor port:
- DISPLAY_GFX_DESTRUCTOR (0x569CE0, slot 0 thunk)
- DISPLAY_GFX_DESTRUCTOR_IMPL (0x56A010, body)
- DISPLAY_GFX_FREE_LAYER_SPRITE_TABLE (0x56A280)
- DISPLAY_GFX_DISPATCH_FRAME_POST_PROCESS_HOOKS (0x56CDB0)
- TILE_BITMAP_SET_DESTRUCTOR (0x569BC0)
- DISPLAY_BASE_DESTRUCTOR_IMPL (0x522F60, parent dtor)
Re-exported via `mod va`.
Pre-work for porting DisplayGfx::Destructor (slot 0). Note: the plan's
`DD_DISPLAY_VTABLE` constant turned out to be bogus β the destructor's
self-rebind at 0x56A030 writes the most-derived DisplayGfx vtable
(0x66A218), the standard MSVC C++ destructor pattern. There is no
separate "DDDisplay" parent vtable; the Ghidra `DDDisplay_vtable`
label is just the legacy name for `DisplayGfxVtable` itself.
|
@@ -82,6 +82,11 @@ pub mod va {
|
|
| 82 |
};
|
| 83 |
pub use crate::render::display::base::DISPLAY_BASE_VTABLE;
|
| 84 |
pub use crate::render::display::context::{RenderContextVtable, RENDER_CONTEXT_VTABLE};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 85 |
pub use crate::render::display::palette::PALETTE_VTABLE;
|
| 86 |
pub use crate::render::display::vtable::DISPLAY_GFX_VTABLE;
|
| 87 |
pub use crate::task::game_task::SOUND_EMITTER_VTABLE;
|
|
|
|
| 82 |
};
|
| 83 |
pub use crate::render::display::base::DISPLAY_BASE_VTABLE;
|
| 84 |
pub use crate::render::display::context::{RenderContextVtable, RENDER_CONTEXT_VTABLE};
|
| 85 |
+
pub use crate::render::display::gfx::{
|
| 86 |
+
DISPLAY_BASE_DESTRUCTOR_IMPL, DISPLAY_GFX_DESTRUCTOR, DISPLAY_GFX_DESTRUCTOR_IMPL,
|
| 87 |
+
DISPLAY_GFX_DISPATCH_FRAME_POST_PROCESS_HOOKS, DISPLAY_GFX_FREE_LAYER_SPRITE_TABLE,
|
| 88 |
+
TILE_BITMAP_SET_DESTRUCTOR,
|
| 89 |
+
};
|
| 90 |
pub use crate::render::display::palette::PALETTE_VTABLE;
|
| 91 |
pub use crate::render::display::vtable::DISPLAY_GFX_VTABLE;
|
| 92 |
pub use crate::task::game_task::SOUND_EMITTER_VTABLE;
|
|
@@ -3,6 +3,43 @@ use super::vtable::DisplayGfxVtable;
|
|
| 3 |
use crate::bitgrid::{BitGrid, BitGridBaseVtable, DisplayBitGrid};
|
| 4 |
use crate::render::sprite::sprite::{CBitmap, LayerSprite};
|
| 5 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6 |
/// DisplayGfx β full display/graphics subsystem (derived from DisplayBase).
|
| 7 |
///
|
| 8 |
/// Constructor: DisplayGfx__Constructor (0x569C10), stdcall(this) β DisplayGfx*.
|
|
@@ -174,15 +211,29 @@ pub struct DisplayGfx {
|
|
| 174 |
/// 0x24DF4: Blend mode flag. Controls color distance weighting in
|
| 175 |
/// InitDisplayFinal (1 = reduced red weight, else normal).
|
| 176 |
pub blend_mode_flag: u32,
|
| 177 |
-
/// 0x24DF8 - 0x24E07:
|
| 178 |
-
///
|
| 179 |
-
|
| 180 |
-
///
|
| 181 |
-
|
| 182 |
-
///
|
| 183 |
-
|
| 184 |
-
/// 0x24E04:
|
| 185 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 186 |
/// 0x24E08 - 0x24E27: Remaining tail (0x20 bytes)
|
| 187 |
pub _tail: [u8; 0x24E28 - 0x24E08],
|
| 188 |
}
|
|
|
|
| 3 |
use crate::bitgrid::{BitGrid, BitGridBaseVtable, DisplayBitGrid};
|
| 4 |
use crate::render::sprite::sprite::{CBitmap, LayerSprite};
|
| 5 |
|
| 6 |
+
crate::define_addresses! {
|
| 7 |
+
class "DisplayGfx" {
|
| 8 |
+
/// `DisplayGfx::Destructor` (vtable slot 0 thunk, 0x569CE0) β thiscall.
|
| 9 |
+
/// Calls `DestructorImpl` then `_free(this)` if `flags & 1`.
|
| 10 |
+
fn/Thiscall DISPLAY_GFX_DESTRUCTOR = 0x0056_9CE0;
|
| 11 |
+
/// `DisplayGfx::DestructorImpl` (0x56A010) β fastcall(ECX=this).
|
| 12 |
+
/// The actual cleanup body. Wrapped in C++ SEH; rebinds vtable to
|
| 13 |
+
/// the most-derived DisplayGfx vtable (standard MSVC pattern), then
|
| 14 |
+
/// frees layer sprites, tile bitmap set, CBitmap vec, layers, hook
|
| 15 |
+
/// vec, embedded BitGrid, and chains to `DisplayBase::Destructor`.
|
| 16 |
+
fn/Fastcall DISPLAY_GFX_DESTRUCTOR_IMPL = 0x0056_A010;
|
| 17 |
+
/// `DisplayGfx::FreeLayerSpriteTable` (0x56A280) β fastcall(ECX=this).
|
| 18 |
+
/// Iterates `sprite_table[1..0x3FF]` at `+0x3DD4` and frees each
|
| 19 |
+
/// `LayerSprite` + its `frame_array`.
|
| 20 |
+
fn/Fastcall DISPLAY_GFX_FREE_LAYER_SPRITE_TABLE = 0x0056_A280;
|
| 21 |
+
/// `DisplayGfx::DispatchFramePostProcessHooks` (0x56CDB0) β per-frame
|
| 22 |
+
/// poll/dispatch over the FramePostProcessHook* vector at `+0x24DF8`.
|
| 23 |
+
/// Called from `RenderFrame_Maybe` (0x56E06C) which is still bridged.
|
| 24 |
+
fn/Thiscall DISPLAY_GFX_DISPATCH_FRAME_POST_PROCESS_HOOKS = 0x0056_CDB0;
|
| 25 |
+
}
|
| 26 |
+
|
| 27 |
+
class "TileBitmapSet" {
|
| 28 |
+
/// `TileBitmapSet::Destructor` (0x569BC0) β fastcall(ECX=this).
|
| 29 |
+
/// Iterates `bitmap_ptrs[0..count]`, calls `vtable[0](1)` on each,
|
| 30 |
+
/// frees `bitmap_ptrs`.
|
| 31 |
+
fn/Fastcall TILE_BITMAP_SET_DESTRUCTOR = 0x0056_9BC0;
|
| 32 |
+
}
|
| 33 |
+
|
| 34 |
+
class "DisplayBase" {
|
| 35 |
+
/// `DisplayBase::Destructor` (0x522F60) β thiscall(ECX=this).
|
| 36 |
+
/// Parent class destructor; rebinds vtable to DisplayBase
|
| 37 |
+
/// (`0x6645F8`) and tears down sprite cache, palette slots, etc.
|
| 38 |
+
/// Chained from `DisplayGfx::DestructorImpl` as the final step.
|
| 39 |
+
fn/Thiscall DISPLAY_BASE_DESTRUCTOR_IMPL = 0x0052_2F60;
|
| 40 |
+
}
|
| 41 |
+
}
|
| 42 |
+
|
| 43 |
/// DisplayGfx β full display/graphics subsystem (derived from DisplayBase).
|
| 44 |
///
|
| 45 |
/// Constructor: DisplayGfx__Constructor (0x569C10), stdcall(this) β DisplayGfx*.
|
|
|
|
| 211 |
/// 0x24DF4: Blend mode flag. Controls color distance weighting in
|
| 212 |
/// InitDisplayFinal (1 = reduced red weight, else normal).
|
| 213 |
pub blend_mode_flag: u32,
|
| 214 |
+
/// 0x24DF8 - 0x24E07: `std::vector<FramePostProcessHook*>` (16-byte
|
| 215 |
+
/// MSVC 2005 layout with the iterator-debug proxy at offset 0).
|
| 216 |
+
///
|
| 217 |
+
/// ```text
|
| 218 |
+
/// +0x00 (= +0x24DF8) _Myproxy : *const c_void β debug iterator container proxy
|
| 219 |
+
/// +0x04 (= +0x24DFC) _Myfirst : *mut *mut FramePostProcessHook β start
|
| 220 |
+
/// +0x08 (= +0x24E00) _Mylast : *mut *mut FramePostProcessHook β end
|
| 221 |
+
/// +0x0C (= +0x24E04) _Myend : *mut *mut FramePostProcessHook β capacity end
|
| 222 |
+
/// ```
|
| 223 |
+
///
|
| 224 |
+
/// Populated during `DisplayGfx::Init` with the registered post-process
|
| 225 |
+
/// hooks (the only known shipping entry is `ScreenshotHook`, which writes
|
| 226 |
+
/// the rendered frame as a numbered PNG when a screenshot is requested).
|
| 227 |
+
/// Iterated every frame by `DispatchFramePostProcessHooks` (0x56CDB0).
|
| 228 |
+
/// Until the FramePostProcessHook type lands the entry pointer is left
|
| 229 |
+
/// as `*mut u8`.
|
| 230 |
+
pub hook_vec_proxy: *const core::ffi::c_void,
|
| 231 |
+
/// 0x24DFC: hook vec `_Myfirst` β start pointer.
|
| 232 |
+
pub hook_vec_first: *mut *mut u8,
|
| 233 |
+
/// 0x24E00: hook vec `_Mylast` β end pointer.
|
| 234 |
+
pub hook_vec_last: *mut *mut u8,
|
| 235 |
+
/// 0x24E04: hook vec `_Myend` β capacity end pointer.
|
| 236 |
+
pub hook_vec_end: *mut *mut u8,
|
| 237 |
/// 0x24E08 - 0x24E27: Remaining tail (0x20 bytes)
|
| 238 |
pub _tail: [u8; 0x24E28 - 0x24E08],
|
| 239 |
}
|