refactor: add DDDisplayVtable, replace inline vtable dispatch
Browse filesCreate DDDisplayVtable (38 slots) with typed methods for the 5 slots
used in the DDGame constructor:
- set_layer_color (slot 4)
- set_active_layer (slot 5)
- set_layer_visibility (slot 23)
- load_sprite (slot 31)
- load_sprite_by_layer (slot 37)
Methods take *mut DDDisplay (not &self) to avoid UB from creating
mutable pointers from shared references.
Replaces ~15 inline transmute + vtable[N] patterns with typed calls
like DDDisplay::set_layer_color(disp, 1, 0xFE).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
crates/openwa-core/src/display/dd_display.rs
CHANGED
|
@@ -1,16 +1,151 @@
|
|
| 1 |
/// DDDisplay β display/rendering subsystem.
|
| 2 |
///
|
| 3 |
/// Constructor: DDDisplay__Init (0x569D00).
|
| 4 |
-
/// Vtable: 0x66A218.
|
| 5 |
/// Destructor: FUN_00569CE0.
|
| 6 |
///
|
| 7 |
/// Manages display mode, dimensions, palette, and HWND.
|
| 8 |
/// Contains DrawTextOnBitmap (thiscall) and ConstructTextbox methods.
|
| 9 |
/// The OpenGL context (HDC, HGLRC) is also stored here when GL mode is active.
|
| 10 |
///
|
| 11 |
-
/// OPAQUE:
|
| 12 |
#[repr(C)]
|
| 13 |
pub struct DDDisplay {
|
| 14 |
/// 0x000: Vtable pointer (0x66A218)
|
| 15 |
-
pub vtable: *
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 16 |
}
|
|
|
|
| 1 |
/// DDDisplay β display/rendering subsystem.
|
| 2 |
///
|
| 3 |
/// Constructor: DDDisplay__Init (0x569D00).
|
| 4 |
+
/// Vtable: 0x66A218 (38 known slots).
|
| 5 |
/// Destructor: FUN_00569CE0.
|
| 6 |
///
|
| 7 |
/// Manages display mode, dimensions, palette, and HWND.
|
| 8 |
/// Contains DrawTextOnBitmap (thiscall) and ConstructTextbox methods.
|
| 9 |
/// The OpenGL context (HDC, HGLRC) is also stored here when GL mode is active.
|
| 10 |
///
|
| 11 |
+
/// OPAQUE: Full struct size not yet determined. Only vtable pointer defined.
|
| 12 |
#[repr(C)]
|
| 13 |
pub struct DDDisplay {
|
| 14 |
/// 0x000: Vtable pointer (0x66A218)
|
| 15 |
+
pub vtable: *const DDDisplayVtable,
|
| 16 |
+
}
|
| 17 |
+
|
| 18 |
+
/// DDDisplay vtable (0x66A218, 38 slots).
|
| 19 |
+
///
|
| 20 |
+
/// Only actively-used slots have typed signatures. Unknown slots are `usize`.
|
| 21 |
+
/// Follows the DSSoundVtable pattern: all slots defined, unknowns as stubs.
|
| 22 |
+
#[repr(C)]
|
| 23 |
+
pub struct DDDisplayVtable {
|
| 24 |
+
/// Slot 0: destructor
|
| 25 |
+
pub _slot_00: usize,
|
| 26 |
+
/// Slot 1
|
| 27 |
+
pub _slot_01: usize,
|
| 28 |
+
/// Slot 2
|
| 29 |
+
pub _slot_02: usize,
|
| 30 |
+
/// Slot 3
|
| 31 |
+
pub _slot_03: usize,
|
| 32 |
+
/// Slot 4: set layer color β thiscall(this, layer, color)
|
| 33 |
+
pub set_layer_color: unsafe extern "thiscall" fn(*mut DDDisplay, i32, i32),
|
| 34 |
+
/// Slot 5: set active layer β thiscall(this, layer) -> layer context ptr
|
| 35 |
+
pub set_active_layer: unsafe extern "thiscall" fn(*mut DDDisplay, i32) -> *mut u8,
|
| 36 |
+
/// Slot 6
|
| 37 |
+
pub _slot_06: usize,
|
| 38 |
+
/// Slot 7
|
| 39 |
+
pub _slot_07: usize,
|
| 40 |
+
/// Slot 8
|
| 41 |
+
pub _slot_08: usize,
|
| 42 |
+
/// Slot 9
|
| 43 |
+
pub _slot_09: usize,
|
| 44 |
+
/// Slot 10
|
| 45 |
+
pub _slot_10: usize,
|
| 46 |
+
/// Slot 11
|
| 47 |
+
pub _slot_11: usize,
|
| 48 |
+
/// Slot 12
|
| 49 |
+
pub _slot_12: usize,
|
| 50 |
+
/// Slot 13
|
| 51 |
+
pub _slot_13: usize,
|
| 52 |
+
/// Slot 14
|
| 53 |
+
pub _slot_14: usize,
|
| 54 |
+
/// Slot 15
|
| 55 |
+
pub _slot_15: usize,
|
| 56 |
+
/// Slot 16
|
| 57 |
+
pub _slot_16: usize,
|
| 58 |
+
/// Slot 17
|
| 59 |
+
pub _slot_17: usize,
|
| 60 |
+
/// Slot 18
|
| 61 |
+
pub _slot_18: usize,
|
| 62 |
+
/// Slot 19
|
| 63 |
+
pub _slot_19: usize,
|
| 64 |
+
/// Slot 20
|
| 65 |
+
pub _slot_20: usize,
|
| 66 |
+
/// Slot 21
|
| 67 |
+
pub _slot_21: usize,
|
| 68 |
+
/// Slot 22
|
| 69 |
+
pub _slot_22: usize,
|
| 70 |
+
/// Slot 23 (0x5C): set layer visibility β thiscall(this, layer, value)
|
| 71 |
+
pub set_layer_visibility: unsafe extern "thiscall" fn(*mut DDDisplay, i32, i32),
|
| 72 |
+
/// Slot 24
|
| 73 |
+
pub _slot_24: usize,
|
| 74 |
+
/// Slot 25
|
| 75 |
+
pub _slot_25: usize,
|
| 76 |
+
/// Slot 26
|
| 77 |
+
pub _slot_26: usize,
|
| 78 |
+
/// Slot 27
|
| 79 |
+
pub _slot_27: usize,
|
| 80 |
+
/// Slot 28
|
| 81 |
+
pub _slot_28: usize,
|
| 82 |
+
/// Slot 29
|
| 83 |
+
pub _slot_29: usize,
|
| 84 |
+
/// Slot 30
|
| 85 |
+
pub _slot_30: usize,
|
| 86 |
+
/// Slot 31 (0x7C): load sprite with flag β thiscall(this, layer, id, flag, gfx, name), RET 0x14
|
| 87 |
+
pub load_sprite:
|
| 88 |
+
unsafe extern "thiscall" fn(*mut DDDisplay, u32, u32, u32, *mut u8, *const u8) -> i32,
|
| 89 |
+
/// Slot 32
|
| 90 |
+
pub _slot_32: usize,
|
| 91 |
+
/// Slot 33
|
| 92 |
+
pub _slot_33: usize,
|
| 93 |
+
/// Slot 34
|
| 94 |
+
pub _slot_34: usize,
|
| 95 |
+
/// Slot 35
|
| 96 |
+
pub _slot_35: usize,
|
| 97 |
+
/// Slot 36
|
| 98 |
+
pub _slot_36: usize,
|
| 99 |
+
/// Slot 37 (0x94): load sprite by layer β thiscall(this, layer, id, gfx, name), RET 0x10
|
| 100 |
+
pub load_sprite_by_layer:
|
| 101 |
+
unsafe extern "thiscall" fn(*mut DDDisplay, u32, u32, *mut u8, *const u8) -> i32,
|
| 102 |
+
}
|
| 103 |
+
|
| 104 |
+
const _: () = assert!(core::mem::size_of::<DDDisplayVtable>() == 38 * 4);
|
| 105 |
+
|
| 106 |
+
/// Typed wrappers for DDDisplay vtable calls.
|
| 107 |
+
/// All take `*mut DDDisplay` since thiscall passes `this` as mutable.
|
| 108 |
+
impl DDDisplay {
|
| 109 |
+
/// Vtable slot 5: set active display layer, returns layer context pointer.
|
| 110 |
+
#[inline]
|
| 111 |
+
pub unsafe fn set_active_layer(this: *mut Self, layer: i32) -> *mut u8 {
|
| 112 |
+
((*(*this).vtable).set_active_layer)(this, layer)
|
| 113 |
+
}
|
| 114 |
+
|
| 115 |
+
/// Vtable slot 4: set color for a display layer.
|
| 116 |
+
#[inline]
|
| 117 |
+
pub unsafe fn set_layer_color(this: *mut Self, layer: i32, color: i32) {
|
| 118 |
+
((*(*this).vtable).set_layer_color)(this, layer, color)
|
| 119 |
+
}
|
| 120 |
+
|
| 121 |
+
/// Vtable slot 23: set layer visibility.
|
| 122 |
+
#[inline]
|
| 123 |
+
pub unsafe fn set_layer_visibility(this: *mut Self, layer: i32, value: i32) {
|
| 124 |
+
((*(*this).vtable).set_layer_visibility)(this, layer, value)
|
| 125 |
+
}
|
| 126 |
+
|
| 127 |
+
/// Vtable slot 37: load sprite into a layer by name.
|
| 128 |
+
#[inline]
|
| 129 |
+
pub unsafe fn load_sprite_by_layer(
|
| 130 |
+
this: *mut Self,
|
| 131 |
+
layer: u32,
|
| 132 |
+
id: u32,
|
| 133 |
+
gfx: *mut u8,
|
| 134 |
+
name: *const u8,
|
| 135 |
+
) -> i32 {
|
| 136 |
+
((*(*this).vtable).load_sprite_by_layer)(this, layer, id, gfx, name)
|
| 137 |
+
}
|
| 138 |
+
|
| 139 |
+
/// Vtable slot 31: load sprite with flag.
|
| 140 |
+
#[inline]
|
| 141 |
+
pub unsafe fn load_sprite(
|
| 142 |
+
this: *mut Self,
|
| 143 |
+
layer: u32,
|
| 144 |
+
id: u32,
|
| 145 |
+
flag: u32,
|
| 146 |
+
gfx: *mut u8,
|
| 147 |
+
name: *const u8,
|
| 148 |
+
) -> i32 {
|
| 149 |
+
((*(*this).vtable).load_sprite)(this, layer, id, flag, gfx, name)
|
| 150 |
+
}
|
| 151 |
}
|
crates/openwa-core/src/engine/ddgame.rs
CHANGED
|
@@ -526,15 +526,10 @@ pub unsafe fn display_layer_color_init(wrapper: *mut DDGameWrapper) {
|
|
| 526 |
5 + 0x69 // = 0x6E
|
| 527 |
};
|
| 528 |
|
| 529 |
-
let display = (*wrapper).display
|
| 530 |
-
|
| 531 |
-
|
| 532 |
-
|
| 533 |
-
core::mem::transmute(*vt.add(4));
|
| 534 |
-
|
| 535 |
-
set_color(display, 1, layer1_color);
|
| 536 |
-
set_color(display, 2, 0x20);
|
| 537 |
-
set_color(display, 3, 0x70);
|
| 538 |
}
|
| 539 |
|
| 540 |
/// Initialize runtime addresses for the constructor bridges.
|
|
@@ -844,22 +839,18 @@ unsafe fn init_graphics_and_resources(
|
|
| 844 |
if *(rb(va::G_DISPLAY_MODE_FLAG) as *const u8) == 0 {
|
| 845 |
call_usercall_eax(wrapper, FUN_570A90_ADDR);
|
| 846 |
}
|
| 847 |
-
|
| 848 |
-
let disp = (*wrapper).display as *mut u8;
|
| 849 |
let gfx_handler = (*wrapper)._field_4c0;
|
| 850 |
-
|
| 851 |
-
|
| 852 |
-
|
| 853 |
-
|
| 854 |
-
|
| 855 |
-
|
| 856 |
-
|
| 857 |
-
|
| 858 |
-
|
| 859 |
-
|
| 860 |
-
let vt_5c: unsafe extern "thiscall" fn(*mut u8, i32, i32) =
|
| 861 |
-
core::mem::transmute(*vt.add(0x17));
|
| 862 |
-
vt_5c(disp, 1, -100);
|
| 863 |
|
| 864 |
// Palette slot range init
|
| 865 |
let palette_range_ptr = *(disp.add(0x3120) as *const *mut i16);
|
|
@@ -883,12 +874,7 @@ unsafe fn init_graphics_and_resources(
|
|
| 883 |
// ββ Display vtable slot 5 (offset 0x14) ββ
|
| 884 |
// Original: CALL EAX (vtable[5]), saves return value in ESI for use as
|
| 885 |
// the `output` parameter in the color-entries GfxResource__Create call below.
|
| 886 |
-
let layer_ctx =
|
| 887 |
-
let vt = *((*ddgame).display as *const *const u32);
|
| 888 |
-
let f: unsafe extern "thiscall" fn(*mut DDDisplay, i32) -> *mut u8 =
|
| 889 |
-
core::mem::transmute(*vt.add(5));
|
| 890 |
-
f((*ddgame).display, 1)
|
| 891 |
-
};
|
| 892 |
|
| 893 |
// ββ GfxDir color entries DDGame+0x730C..0x732C ββ
|
| 894 |
if (*wrapper).gfx_mode != 0 {
|
|
@@ -1076,11 +1062,7 @@ unsafe fn init_graphics_and_resources(
|
|
| 1076 |
name_buf[5] = b'0' + (i / 10) as u8;
|
| 1077 |
name_buf[6] = b'0' + (i % 10) as u8;
|
| 1078 |
|
| 1079 |
-
|
| 1080 |
-
let disp_vt = *((*ddgame).display as *const *const u32);
|
| 1081 |
-
let set_layer: unsafe extern "thiscall" fn(*mut DDDisplay, i32) -> *mut u8 =
|
| 1082 |
-
core::mem::transmute(*disp_vt.add(5));
|
| 1083 |
-
let layer_ctx = set_layer((*ddgame).display, 1);
|
| 1084 |
|
| 1085 |
let entry = gfx_dir_find_entry(name_buf.as_ptr(), gfx_handler);
|
| 1086 |
|
|
@@ -1267,37 +1249,16 @@ unsafe fn init_graphics_and_resources(
|
|
| 1267 |
0x2F4,
|
| 1268 |
);
|
| 1269 |
|
| 1270 |
-
|
| 1271 |
-
|
| 1272 |
-
let set_layer: unsafe extern "thiscall" fn(*mut DDDisplay, i32) -> *mut u8 =
|
| 1273 |
-
core::mem::transmute(*disp_vt.add(5));
|
| 1274 |
-
let _layer3_ctx = set_layer((*ddgame).display, 3);
|
| 1275 |
|
| 1276 |
-
// Load back.spr and debris.spr (conditional)
|
| 1277 |
-
let disp_obj = (*wrapper).display as *mut u8;
|
| 1278 |
-
let disp_obj_vt = *(disp_obj as *const *const u32);
|
| 1279 |
-
// Check if gfx_mode high byte is set (original: uStack_123c._3_1_ != '\0')
|
| 1280 |
if (*wrapper).gfx_mode != 0 {
|
| 1281 |
-
|
| 1282 |
-
|
| 1283 |
-
load_spr_94(disp_obj, 3, 0x26D, land_layer, b"back.spr\0".as_ptr());
|
| 1284 |
-
|
| 1285 |
-
let load_spr_7c: unsafe extern "thiscall" fn(
|
| 1286 |
-
*mut u8,
|
| 1287 |
-
u32,
|
| 1288 |
-
u32,
|
| 1289 |
-
u32,
|
| 1290 |
-
*mut u8,
|
| 1291 |
-
*const u8,
|
| 1292 |
-
) = core::mem::transmute(*disp_obj_vt.add(0x7C / 4));
|
| 1293 |
-
load_spr_7c(disp_obj, 3, 0x26E, 0, land_layer, b"debris.spr\0".as_ptr());
|
| 1294 |
}
|
| 1295 |
|
| 1296 |
-
|
| 1297 |
-
|
| 1298 |
-
core::mem::transmute(*disp_obj_vt.add(0x94 / 4));
|
| 1299 |
-
load_spr_94(
|
| 1300 |
-
disp_obj,
|
| 1301 |
2,
|
| 1302 |
0x26C,
|
| 1303 |
water_layer,
|
|
@@ -1307,11 +1268,8 @@ unsafe fn init_graphics_and_resources(
|
|
| 1307 |
(*ddgame).gradient_image_2 = core::ptr::null_mut();
|
| 1308 |
|
| 1309 |
// ββ Gradient image (0x030) ββ
|
| 1310 |
-
// The gradient is loaded from "gradient.img" via GfxDir.
|
| 1311 |
-
// Simple path: height <= 0x60 AND level_height == 0x2B8
|
| 1312 |
let level_height = (*ddgame).level_height as i32;
|
| 1313 |
-
|
| 1314 |
-
let layer3_ctx = set_layer((*ddgame).display, 3);
|
| 1315 |
let s_var1 = *(layer3_ctx.add(0x606) as *const i16);
|
| 1316 |
|
| 1317 |
if s_var1 < 0x61 && level_height == 0x2B8 {
|
|
@@ -1325,7 +1283,7 @@ unsafe fn init_graphics_and_resources(
|
|
| 1325 |
|
| 1326 |
// ββ Fill image β fill_pixel (0x7338) ββ
|
| 1327 |
{
|
| 1328 |
-
let layer2_ctx =
|
| 1329 |
// In the original, fill.img uses piStack_126c which the decompiler
|
| 1330 |
// shows was set from piVar3 (water_layer from landscape+0xB38).
|
| 1331 |
let fill_sprite =
|
|
@@ -1380,15 +1338,12 @@ unsafe fn init_graphics_and_resources(
|
|
| 1380 |
call_usercall_eax(wrapper, FUN_570A90_ADDR);
|
| 1381 |
}
|
| 1382 |
|
| 1383 |
-
// ββ Final display layer visibility
|
| 1384 |
{
|
| 1385 |
-
let disp = (*wrapper).display
|
| 1386 |
-
|
| 1387 |
-
|
| 1388 |
-
|
| 1389 |
-
set_vis(disp, 1, 0);
|
| 1390 |
-
set_vis(disp, 2, 0);
|
| 1391 |
-
set_vis(disp, 3, 1);
|
| 1392 |
}
|
| 1393 |
|
| 1394 |
let _ = crate::log::log_line("[DDGame] init_graphics_and_resources DONE");
|
|
|
|
| 526 |
5 + 0x69 // = 0x6E
|
| 527 |
};
|
| 528 |
|
| 529 |
+
let display = (*wrapper).display;
|
| 530 |
+
DDDisplay::set_layer_color(display, 1, layer1_color);
|
| 531 |
+
DDDisplay::set_layer_color(display, 2, 0x20);
|
| 532 |
+
DDDisplay::set_layer_color(display, 3, 0x70);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 533 |
}
|
| 534 |
|
| 535 |
/// Initialize runtime addresses for the constructor bridges.
|
|
|
|
| 839 |
if *(rb(va::G_DISPLAY_MODE_FLAG) as *const u8) == 0 {
|
| 840 |
call_usercall_eax(wrapper, FUN_570A90_ADDR);
|
| 841 |
}
|
| 842 |
+
let disp = (*wrapper).display;
|
|
|
|
| 843 |
let gfx_handler = (*wrapper)._field_4c0;
|
| 844 |
+
DDDisplay::set_layer_color(disp, 1, 0xFE);
|
| 845 |
+
DDDisplay::load_sprite(
|
| 846 |
+
disp,
|
| 847 |
+
1,
|
| 848 |
+
1,
|
| 849 |
+
0,
|
| 850 |
+
gfx_handler,
|
| 851 |
+
rb(va::STR_CDROM_SPR) as *const u8,
|
| 852 |
+
);
|
| 853 |
+
DDDisplay::set_layer_visibility(disp, 1, -100);
|
|
|
|
|
|
|
|
|
|
| 854 |
|
| 855 |
// Palette slot range init
|
| 856 |
let palette_range_ptr = *(disp.add(0x3120) as *const *mut i16);
|
|
|
|
| 874 |
// ββ Display vtable slot 5 (offset 0x14) ββ
|
| 875 |
// Original: CALL EAX (vtable[5]), saves return value in ESI for use as
|
| 876 |
// the `output` parameter in the color-entries GfxResource__Create call below.
|
| 877 |
+
let layer_ctx = DDDisplay::set_active_layer((*ddgame).display, 1);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 878 |
|
| 879 |
// ββ GfxDir color entries DDGame+0x730C..0x732C ββ
|
| 880 |
if (*wrapper).gfx_mode != 0 {
|
|
|
|
| 1062 |
name_buf[5] = b'0' + (i / 10) as u8;
|
| 1063 |
name_buf[6] = b'0' + (i % 10) as u8;
|
| 1064 |
|
| 1065 |
+
let layer_ctx = DDDisplay::set_active_layer((*ddgame).display, 1);
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1066 |
|
| 1067 |
let entry = gfx_dir_find_entry(name_buf.as_ptr(), gfx_handler);
|
| 1068 |
|
|
|
|
| 1249 |
0x2F4,
|
| 1250 |
);
|
| 1251 |
|
| 1252 |
+
let disp = (*wrapper).display;
|
| 1253 |
+
DDDisplay::set_active_layer(disp, 3);
|
|
|
|
|
|
|
|
|
|
| 1254 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1255 |
if (*wrapper).gfx_mode != 0 {
|
| 1256 |
+
DDDisplay::load_sprite_by_layer(disp, 3, 0x26D, land_layer, b"back.spr\0".as_ptr());
|
| 1257 |
+
DDDisplay::load_sprite(disp, 3, 0x26E, 0, land_layer, b"debris.spr\0".as_ptr());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1258 |
}
|
| 1259 |
|
| 1260 |
+
DDDisplay::load_sprite_by_layer(
|
| 1261 |
+
disp,
|
|
|
|
|
|
|
|
|
|
| 1262 |
2,
|
| 1263 |
0x26C,
|
| 1264 |
water_layer,
|
|
|
|
| 1268 |
(*ddgame).gradient_image_2 = core::ptr::null_mut();
|
| 1269 |
|
| 1270 |
// ββ Gradient image (0x030) ββ
|
|
|
|
|
|
|
| 1271 |
let level_height = (*ddgame).level_height as i32;
|
| 1272 |
+
let layer3_ctx = DDDisplay::set_active_layer(disp, 3);
|
|
|
|
| 1273 |
let s_var1 = *(layer3_ctx.add(0x606) as *const i16);
|
| 1274 |
|
| 1275 |
if s_var1 < 0x61 && level_height == 0x2B8 {
|
|
|
|
| 1283 |
|
| 1284 |
// ββ Fill image β fill_pixel (0x7338) ββ
|
| 1285 |
{
|
| 1286 |
+
let layer2_ctx = DDDisplay::set_active_layer((*ddgame).display, 2);
|
| 1287 |
// In the original, fill.img uses piStack_126c which the decompiler
|
| 1288 |
// shows was set from piVar3 (water_layer from landscape+0xB38).
|
| 1289 |
let fill_sprite =
|
|
|
|
| 1338 |
call_usercall_eax(wrapper, FUN_570A90_ADDR);
|
| 1339 |
}
|
| 1340 |
|
| 1341 |
+
// ββ Final display layer visibility ββ
|
| 1342 |
{
|
| 1343 |
+
let disp = (*wrapper).display;
|
| 1344 |
+
DDDisplay::set_layer_visibility(disp, 1, 0);
|
| 1345 |
+
DDDisplay::set_layer_visibility(disp, 2, 0);
|
| 1346 |
+
DDDisplay::set_layer_visibility(disp, 3, 1);
|
|
|
|
|
|
|
|
|
|
| 1347 |
}
|
| 1348 |
|
| 1349 |
let _ = crate::log::log_line("[DDGame] init_graphics_and_resources DONE");
|