refactor: name DDGame fields, add CoordEntry struct, unify gfx_color_table
Browse filesReplace raw offset writes with named field access throughout DDGame:
- _landscape_val (*mut u8) β landscape_property (u32)
- _gfx_color_entries + crosshair_line_color + _unknown_7328 +
crosshair_line_style β unified gfx_color_table: [u32; 9]
- sprite_regions write via raw offset β array indexing
- _param_028 β net_game
- Remove underscore prefixes from _field_64d8, _field_72a4,
_field_7ea0, _field_7ef0, _field_7efc, _unknown_7ea4, _unknown_7ef4
- coord_entries β screen_coords: [CoordEntry; 4] with typed x/y fields
- ddgame_init_fields uses named fields instead of raw pointer arithmetic
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
crates/openwa-core/src/engine/ddgame.rs
CHANGED
|
@@ -60,8 +60,8 @@ pub struct DDGame {
|
|
| 60 |
pub landscape: *mut PCLandscape,
|
| 61 |
/// 0x024: GameInfo pointer (passed as param_10 to constructor).
|
| 62 |
pub game_info: *mut GameInfo,
|
| 63 |
-
/// 0x028: param_9
|
| 64 |
-
pub
|
| 65 |
/// 0x02C: Secondary GfxDir object (0x70C bytes, conditional on GfxHandler 1)
|
| 66 |
pub secondary_gfxdir: *mut u8,
|
| 67 |
/// 0x030: Gradient image pointer
|
|
@@ -84,8 +84,9 @@ pub struct DDGame {
|
|
| 84 |
/// 0x384-0x467: Additional sprite/image object slots.
|
| 85 |
/// Same vtable 0x664144 as sprite_cache. ~20 entries populated at runtime.
|
| 86 |
pub sprite_cache_2: [*mut u8; 57],
|
| 87 |
-
/// 0x468: Landscape
|
| 88 |
-
|
|
|
|
| 89 |
/// 0x46C-0x488: 8 SpriteRegion pointers (0x9C bytes each, vtable 0x66B268)
|
| 90 |
/// Created by SpriteRegion__Constructor (0x57DB20).
|
| 91 |
/// Each contains 32 BitGrid sub-objects.
|
|
@@ -177,12 +178,12 @@ pub struct DDGame {
|
|
| 177 |
/// Known landmarks:
|
| 178 |
/// - 0x64D8: cleared by init
|
| 179 |
pub _unknown_4620: [u8; 0x64D8 - 0x4620],
|
| 180 |
-
/// 0x64D8: Cleared by
|
| 181 |
-
pub
|
| 182 |
/// 0x64DC-0x72A3: Unknown
|
| 183 |
pub _unknown_64dc: [u8; 0x72A4 - 0x64DC],
|
| 184 |
-
/// 0x72A4: Cleared by
|
| 185 |
-
pub
|
| 186 |
/// 0x72A8-0x72D7: Unknown
|
| 187 |
pub _unknown_72a8: [u8; 0x72D8 - 0x72A8],
|
| 188 |
|
|
@@ -200,16 +201,12 @@ pub struct DDGame {
|
|
| 200 |
pub _unknown_72f4: [u8; 0x7308 - 0x72F4],
|
| 201 |
/// 0x7308: Sprite/gfx dimension data (passed to GFX_DIR_LOAD_SPRITES).
|
| 202 |
pub gfx_sprite_data: [u8; 0x730C - 0x7308],
|
| 203 |
-
/// 0x730C-
|
| 204 |
-
|
| 205 |
-
|
| 206 |
-
/// 0x7324: Crosshair line color
|
| 207 |
-
///
|
| 208 |
-
pub
|
| 209 |
-
/// 0x7328: Unknown (between crosshair params)
|
| 210 |
-
pub _unknown_7328: [u8; 4],
|
| 211 |
-
/// 0x732C: Crosshair line style param (DrawPolygon param_1).
|
| 212 |
-
pub crosshair_line_style: u32,
|
| 213 |
/// 0x7330-0x7337: Unknown
|
| 214 |
pub _unknown_7330: [u8; 8],
|
| 215 |
/// 0x7338: Fill pixel value
|
|
@@ -288,24 +285,24 @@ pub struct DDGame {
|
|
| 288 |
/// 0x7D84-0x7E9F: Unknown
|
| 289 |
pub _unknown_7d84: [u8; 0x7EA0 - 0x7D84],
|
| 290 |
|
| 291 |
-
/// 0x7EA0:
|
| 292 |
-
pub
|
| 293 |
-
/// 0x7EA4: Unknown
|
| 294 |
-
pub
|
| 295 |
/// 0x7EA8: Turn time limit in seconds (150 = 2:30 default).
|
| 296 |
pub turn_time_limit: u32,
|
| 297 |
/// 0x7EAC-0x7ECF: Unknown
|
| 298 |
pub _unknown_7eac: [u8; 0x7ED0 - 0x7EAC],
|
| 299 |
/// 0x7ED0-0x7EEF: Unknown
|
| 300 |
pub _unknown_7ed0: [u8; 0x7EF0 - 0x7ED0],
|
| 301 |
-
/// 0x7EF0:
|
| 302 |
-
pub
|
| 303 |
-
/// 0x7EF4: Unknown
|
| 304 |
-
pub
|
| 305 |
/// 0x7EF8: Sound available flag (1 when game_info+0xF914 == 0, i.e. not headless).
|
| 306 |
pub sound_available: u32,
|
| 307 |
/// 0x7EFC: Always initialized to 1 in constructor.
|
| 308 |
-
pub
|
| 309 |
|
| 310 |
// === Sound queue (0x7F00-0x8143) ===
|
| 311 |
/// 0x7F00: Sound queue (16 entries, stride 0x24). Appended by PlaySoundGlobal.
|
|
@@ -332,16 +329,16 @@ pub struct DDGame {
|
|
| 332 |
/// - 0x8174: value 0x3FC (1020) at runtime
|
| 333 |
pub _unknown_81cc: [u8; 0x8CBC - 0x81CC],
|
| 334 |
|
| 335 |
-
/// 0x8CBC-
|
| 336 |
-
/// InitFields zeroes
|
| 337 |
/// screen coordinates (e.g. 393.0, 532.0, 960.0, 348.0).
|
| 338 |
-
pub
|
| 339 |
|
| 340 |
/// 0x8CFC-0x984F: Unknown
|
| 341 |
pub _unknown_8cfc: [u8; 0x9850 - 0x8CFC],
|
| 342 |
|
| 343 |
-
/// 0x9850-0x988F: 4
|
| 344 |
-
pub
|
| 345 |
|
| 346 |
/// 0x9890-0x98A3: Flags
|
| 347 |
pub _unknown_9890: [u8; 0x98A4 - 0x9890],
|
|
@@ -392,54 +389,30 @@ const _: () = assert!(core::mem::size_of::<DDGame>() == 0x98B8);
|
|
| 392 |
pub unsafe fn ddgame_init_fields(ddgame: *mut DDGame) {
|
| 393 |
let base = ddgame as *mut u8;
|
| 394 |
|
| 395 |
-
// Zero the stride-0x194 table (10 entries)
|
|
|
|
|
|
|
| 396 |
for &off in &[
|
| 397 |
-
0x379Cusize,
|
| 398 |
-
|
| 399 |
-
0x3AC4,
|
| 400 |
-
0x3C58,
|
| 401 |
-
0x3DEC,
|
| 402 |
-
0x3F80,
|
| 403 |
-
0x4114,
|
| 404 |
-
0x42A8,
|
| 405 |
-
0x443C,
|
| 406 |
-
0x45D0,
|
| 407 |
] {
|
| 408 |
-
*(base.add(off
|
| 409 |
}
|
| 410 |
|
| 411 |
-
|
| 412 |
-
|
| 413 |
|
| 414 |
// InitRenderIndices β original sets ESI = ddgame + 0x72D8 before calling
|
| 415 |
ddgame_init_render_indices(base.add(0x72D8));
|
| 416 |
|
| 417 |
-
// Zero
|
| 418 |
-
for
|
| 419 |
-
|
| 420 |
-
|
| 421 |
-
0x8CCC,
|
| 422 |
-
0x8CD0,
|
| 423 |
-
0x8CDC,
|
| 424 |
-
0x8CE0,
|
| 425 |
-
0x8CEC,
|
| 426 |
-
0x8CF0,
|
| 427 |
-
] {
|
| 428 |
-
*(base.add(off as usize) as *mut u32) = 0;
|
| 429 |
}
|
| 430 |
-
|
| 431 |
-
|
| 432 |
-
|
| 433 |
-
0x9850usize,
|
| 434 |
-
0x9854,
|
| 435 |
-
0x9860,
|
| 436 |
-
0x9864,
|
| 437 |
-
0x9870,
|
| 438 |
-
0x9874,
|
| 439 |
-
0x9880,
|
| 440 |
-
0x9884,
|
| 441 |
-
] {
|
| 442 |
-
*(base.add(off as usize) as *mut u32) = 0;
|
| 443 |
}
|
| 444 |
}
|
| 445 |
|
|
@@ -705,7 +678,7 @@ pub unsafe fn create_ddgame(
|
|
| 705 |
(*ddgame).timer_obj = param7;
|
| 706 |
(*ddgame).network_ecx = network_ecx;
|
| 707 |
(*ddgame).game_info = game_info;
|
| 708 |
-
(*ddgame).
|
| 709 |
|
| 710 |
// Now safe to expose β all fields that concurrent readers check are set.
|
| 711 |
(*wrapper).ddgame = ddgame;
|
|
@@ -717,7 +690,7 @@ pub unsafe fn create_ddgame(
|
|
| 717 |
let is_headless = (*game_info).headless_mode != 0;
|
| 718 |
// sound_available enables loading progress bar, message pump, and sound during construction.
|
| 719 |
(*ddgame).sound_available = if is_headless { 0 } else { 1 };
|
| 720 |
-
(*ddgame).
|
| 721 |
|
| 722 |
// ββ 7. DDGameWrapper+0x48C init ββ
|
| 723 |
(*wrapper).ddgame_secondary = core::ptr::null_mut();
|
|
@@ -898,13 +871,8 @@ unsafe fn init_graphics_and_resources(
|
|
| 898 |
// vtable[4] = get_pixel: thiscall(this, x, y) -> color, RET 0x8.
|
| 899 |
let get_color: unsafe extern "thiscall" fn(*mut u8, u32, u32) -> u32 =
|
| 900 |
core::mem::transmute(*rvt.add(4));
|
| 901 |
-
|
| 902 |
-
|
| 903 |
-
while off < 0x732Du32 {
|
| 904 |
-
let c = get_color(res, idx, 0);
|
| 905 |
-
*((ddgame as *mut u8).add(off as usize) as *mut u32) = c;
|
| 906 |
-
off += 4;
|
| 907 |
-
idx += 1;
|
| 908 |
}
|
| 909 |
// DisplayGfx__vmethod_3: thiscall(this, byte param_2), RET 4.
|
| 910 |
// param_2 & 1 = free the object itself.
|
|
@@ -1019,37 +987,37 @@ unsafe fn init_graphics_and_resources(
|
|
| 1019 |
// ββ 8Γ SpriteRegion at DDGame+0x46C..0x488 ββ
|
| 1020 |
// SpriteRegion__Constructor: fastcall(ECX, EDX) + 6 stack(this, p2, p3, p4, p5, p6), RET 0x18
|
| 1021 |
{
|
| 1022 |
-
// (
|
| 1023 |
// p6 is the GfxResource pointer returned by GfxResource__Create_Maybe.
|
| 1024 |
let gr = gfx_resource as u32;
|
| 1025 |
-
let regions: [(
|
| 1026 |
-
(
|
| 1027 |
-
(
|
| 1028 |
-
(
|
| 1029 |
-
(
|
| 1030 |
-
(
|
| 1031 |
-
(
|
| 1032 |
-
(
|
| 1033 |
-
(
|
| 1034 |
];
|
| 1035 |
|
| 1036 |
-
for &(
|
| 1037 |
let alloc = wa_malloc_zeroed(0x9C);
|
| 1038 |
let result = if !alloc.is_null() {
|
| 1039 |
call_sprite_region_ctor(alloc, ecx, edx, p2, p3, p4, p5, p6)
|
| 1040 |
} else {
|
| 1041 |
core::ptr::null_mut()
|
| 1042 |
};
|
| 1043 |
-
|
| 1044 |
}
|
| 1045 |
}
|
| 1046 |
|
| 1047 |
-
// ββ Landscape
|
| 1048 |
if !landscape.is_null() {
|
| 1049 |
let land_vt = *(landscape as *const *const u32);
|
| 1050 |
let get_val: unsafe extern "thiscall" fn(*mut u8) -> u32 =
|
| 1051 |
core::mem::transmute(*land_vt.add(0xB));
|
| 1052 |
-
|
| 1053 |
}
|
| 1054 |
|
| 1055 |
// NOTE: gfx_resource is NOT released here β arrow SpriteRegions need it.
|
|
@@ -1553,6 +1521,20 @@ pub mod offsets {
|
|
| 1553 |
pub const SOUND_QUEUE_COUNT: usize = 0x8140;
|
| 1554 |
}
|
| 1555 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1556 |
// ============================================================
|
| 1557 |
// Sound queue entry β 16 entries at DDGame + 0x7F00
|
| 1558 |
// ============================================================
|
|
|
|
| 60 |
pub landscape: *mut PCLandscape,
|
| 61 |
/// 0x024: GameInfo pointer (passed as param_10 to constructor).
|
| 62 |
pub game_info: *mut GameInfo,
|
| 63 |
+
/// 0x028: Network game object (param_9 to DDGameWrapper constructor).
|
| 64 |
+
pub net_game: *mut u8,
|
| 65 |
/// 0x02C: Secondary GfxDir object (0x70C bytes, conditional on GfxHandler 1)
|
| 66 |
pub secondary_gfxdir: *mut u8,
|
| 67 |
/// 0x030: Gradient image pointer
|
|
|
|
| 84 |
/// 0x384-0x467: Additional sprite/image object slots.
|
| 85 |
/// Same vtable 0x664144 as sprite_cache. ~20 entries populated at runtime.
|
| 86 |
pub sprite_cache_2: [*mut u8; 57],
|
| 87 |
+
/// 0x468: Landscape property from PCLandscape vtable[0xB] (thiscall getter).
|
| 88 |
+
/// Set during DDGame construction if landscape is non-null.
|
| 89 |
+
pub landscape_property: u32,
|
| 90 |
/// 0x46C-0x488: 8 SpriteRegion pointers (0x9C bytes each, vtable 0x66B268)
|
| 91 |
/// Created by SpriteRegion__Constructor (0x57DB20).
|
| 92 |
/// Each contains 32 BitGrid sub-objects.
|
|
|
|
| 178 |
/// Known landmarks:
|
| 179 |
/// - 0x64D8: cleared by init
|
| 180 |
pub _unknown_4620: [u8; 0x64D8 - 0x4620],
|
| 181 |
+
/// 0x64D8: Cleared by InitFields. Purpose unknown.
|
| 182 |
+
pub init_field_64d8: u32,
|
| 183 |
/// 0x64DC-0x72A3: Unknown
|
| 184 |
pub _unknown_64dc: [u8; 0x72A4 - 0x64DC],
|
| 185 |
+
/// 0x72A4: Cleared by InitFields. Purpose unknown.
|
| 186 |
+
pub init_field_72a4: u32,
|
| 187 |
/// 0x72A8-0x72D7: Unknown
|
| 188 |
pub _unknown_72a8: [u8; 0x72D8 - 0x72A8],
|
| 189 |
|
|
|
|
| 201 |
pub _unknown_72f4: [u8; 0x7308 - 0x72F4],
|
| 202 |
/// 0x7308: Sprite/gfx dimension data (passed to GFX_DIR_LOAD_SPRITES).
|
| 203 |
pub gfx_sprite_data: [u8; 0x730C - 0x7308],
|
| 204 |
+
/// 0x730C-0x732F: GfxDir color table (9 entries).
|
| 205 |
+
/// Populated from colours.img pixel row: `color_table[i] = get_pixel(sprite, i, 0)`.
|
| 206 |
+
/// Known entries:
|
| 207 |
+
/// - [6] (0x7324): Crosshair line color (DrawPolygon param_2)
|
| 208 |
+
/// - [8] (0x732C): Crosshair line style (DrawPolygon param_1)
|
| 209 |
+
pub gfx_color_table: [u32; 9],
|
|
|
|
|
|
|
|
|
|
|
|
|
| 210 |
/// 0x7330-0x7337: Unknown
|
| 211 |
pub _unknown_7330: [u8; 8],
|
| 212 |
/// 0x7338: Fill pixel value
|
|
|
|
| 285 |
/// 0x7D84-0x7E9F: Unknown
|
| 286 |
pub _unknown_7d84: [u8; 0x7EA0 - 0x7D84],
|
| 287 |
|
| 288 |
+
/// 0x7EA0: Flag/counter (value 4 at runtime β likely team count).
|
| 289 |
+
pub field_7ea0: u32,
|
| 290 |
+
/// 0x7EA4: Unknown.
|
| 291 |
+
pub field_7ea4: u32,
|
| 292 |
/// 0x7EA8: Turn time limit in seconds (150 = 2:30 default).
|
| 293 |
pub turn_time_limit: u32,
|
| 294 |
/// 0x7EAC-0x7ECF: Unknown
|
| 295 |
pub _unknown_7eac: [u8; 0x7ED0 - 0x7EAC],
|
| 296 |
/// 0x7ED0-0x7EEF: Unknown
|
| 297 |
pub _unknown_7ed0: [u8; 0x7EF0 - 0x7ED0],
|
| 298 |
+
/// 0x7EF0: Flag (-1 = 0xFFFFFFFF at runtime).
|
| 299 |
+
pub field_7ef0: i32,
|
| 300 |
+
/// 0x7EF4: Unknown.
|
| 301 |
+
pub field_7ef4: u32,
|
| 302 |
/// 0x7EF8: Sound available flag (1 when game_info+0xF914 == 0, i.e. not headless).
|
| 303 |
pub sound_available: u32,
|
| 304 |
/// 0x7EFC: Always initialized to 1 in constructor.
|
| 305 |
+
pub field_7efc: u32,
|
| 306 |
|
| 307 |
// === Sound queue (0x7F00-0x8143) ===
|
| 308 |
/// 0x7F00: Sound queue (16 entries, stride 0x24). Appended by PlaySoundGlobal.
|
|
|
|
| 329 |
/// - 0x8174: value 0x3FC (1020) at runtime
|
| 330 |
pub _unknown_81cc: [u8; 0x8CBC - 0x81CC],
|
| 331 |
|
| 332 |
+
/// 0x8CBC-0x8CFB: 4 coordinate entries (0x10-byte stride).
|
| 333 |
+
/// InitFields zeroes x and y of each. At runtime contains fixed-point
|
| 334 |
/// screen coordinates (e.g. 393.0, 532.0, 960.0, 348.0).
|
| 335 |
+
pub screen_coords: [CoordEntry; 4],
|
| 336 |
|
| 337 |
/// 0x8CFC-0x984F: Unknown
|
| 338 |
pub _unknown_8cfc: [u8; 0x9850 - 0x8CFC],
|
| 339 |
|
| 340 |
+
/// 0x9850-0x988F: 4 coordinate entries (0x10-byte stride, zeroed by InitFields).
|
| 341 |
+
pub screen_coords_2: [CoordEntry; 4],
|
| 342 |
|
| 343 |
/// 0x9890-0x98A3: Flags
|
| 344 |
pub _unknown_9890: [u8; 0x98A4 - 0x9890],
|
|
|
|
| 389 |
pub unsafe fn ddgame_init_fields(ddgame: *mut DDGame) {
|
| 390 |
let base = ddgame as *mut u8;
|
| 391 |
|
| 392 |
+
// Zero the stride-0x194 table (10 entries starting at 0x379C).
|
| 393 |
+
// These offsets are deep in the unknown 0x2E00-0x45EB region and don't
|
| 394 |
+
// have named fields yet β keep as raw offsets for now.
|
| 395 |
for &off in &[
|
| 396 |
+
0x379Cusize, 0x3930, 0x3AC4, 0x3C58, 0x3DEC,
|
| 397 |
+
0x3F80, 0x4114, 0x42A8, 0x443C, 0x45D0,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 398 |
] {
|
| 399 |
+
*(base.add(off) as *mut u32) = 0;
|
| 400 |
}
|
| 401 |
|
| 402 |
+
(*ddgame).init_field_64d8 = 0;
|
| 403 |
+
(*ddgame).init_field_72a4 = 0;
|
| 404 |
|
| 405 |
// InitRenderIndices β original sets ESI = ddgame + 0x72D8 before calling
|
| 406 |
ddgame_init_render_indices(base.add(0x72D8));
|
| 407 |
|
| 408 |
+
// Zero x and y of each screen coordinate entry (4 entries each)
|
| 409 |
+
for entry in &mut (*ddgame).screen_coords {
|
| 410 |
+
entry.x = 0;
|
| 411 |
+
entry.y = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 412 |
}
|
| 413 |
+
for entry in &mut (*ddgame).screen_coords_2 {
|
| 414 |
+
entry.x = 0;
|
| 415 |
+
entry.y = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 416 |
}
|
| 417 |
}
|
| 418 |
|
|
|
|
| 678 |
(*ddgame).timer_obj = param7;
|
| 679 |
(*ddgame).network_ecx = network_ecx;
|
| 680 |
(*ddgame).game_info = game_info;
|
| 681 |
+
(*ddgame).net_game = net_game;
|
| 682 |
|
| 683 |
// Now safe to expose β all fields that concurrent readers check are set.
|
| 684 |
(*wrapper).ddgame = ddgame;
|
|
|
|
| 690 |
let is_headless = (*game_info).headless_mode != 0;
|
| 691 |
// sound_available enables loading progress bar, message pump, and sound during construction.
|
| 692 |
(*ddgame).sound_available = if is_headless { 0 } else { 1 };
|
| 693 |
+
(*ddgame).field_7efc = 1;
|
| 694 |
|
| 695 |
// ββ 7. DDGameWrapper+0x48C init ββ
|
| 696 |
(*wrapper).ddgame_secondary = core::ptr::null_mut();
|
|
|
|
| 871 |
// vtable[4] = get_pixel: thiscall(this, x, y) -> color, RET 0x8.
|
| 872 |
let get_color: unsafe extern "thiscall" fn(*mut u8, u32, u32) -> u32 =
|
| 873 |
core::mem::transmute(*rvt.add(4));
|
| 874 |
+
for i in 0..9u32 {
|
| 875 |
+
(*ddgame).gfx_color_table[i as usize] = get_color(res, i, 0);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 876 |
}
|
| 877 |
// DisplayGfx__vmethod_3: thiscall(this, byte param_2), RET 4.
|
| 878 |
// param_2 & 1 = free the object itself.
|
|
|
|
| 987 |
// ββ 8Γ SpriteRegion at DDGame+0x46C..0x488 ββ
|
| 988 |
// SpriteRegion__Constructor: fastcall(ECX, EDX) + 6 stack(this, p2, p3, p4, p5, p6), RET 0x18
|
| 989 |
{
|
| 990 |
+
// (array_index, ECX, EDX, p2, p3, p4, p5, p6=gfx_resource)
|
| 991 |
// p6 is the GfxResource pointer returned by GfxResource__Create_Maybe.
|
| 992 |
let gr = gfx_resource as u32;
|
| 993 |
+
let regions: [(usize, u32, u32, u32, u32, u32, u32, u32); 8] = [
|
| 994 |
+
(2, 0x37, 0x36, 0x2E, 0x24, 0x41, 0x2D, gr),
|
| 995 |
+
(0, 0x30, 0x0C, 0x2D, 0x07, 0x34, 0x09, gr),
|
| 996 |
+
(1, 0x11, 0x1A, 0x0D, 0x0A, 0x16, 0x13, gr),
|
| 997 |
+
(3, 0x0C, 0x3D, 0x00, 0x20, 0x18, 0x33, gr),
|
| 998 |
+
(4, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, gr),
|
| 999 |
+
(6, 0x1A2, 0x1B, 0x173, 0x09, 0x1D8, 0x03, gr),
|
| 1000 |
+
(7, 0x1EF, 0x26, 0x1E5, 0x07, 0x1F9, 0x16, gr),
|
| 1001 |
+
(5, 0x2D, 0x08, 0x2D, 0x07, 0x2E, 0x07, gr),
|
| 1002 |
];
|
| 1003 |
|
| 1004 |
+
for &(idx, ecx, edx, p2, p3, p4, p5, p6) in ®ions {
|
| 1005 |
let alloc = wa_malloc_zeroed(0x9C);
|
| 1006 |
let result = if !alloc.is_null() {
|
| 1007 |
call_sprite_region_ctor(alloc, ecx, edx, p2, p3, p4, p5, p6)
|
| 1008 |
} else {
|
| 1009 |
core::ptr::null_mut()
|
| 1010 |
};
|
| 1011 |
+
(*ddgame).sprite_regions[idx] = result;
|
| 1012 |
}
|
| 1013 |
}
|
| 1014 |
|
| 1015 |
+
// ββ Landscape property at DDGame+0x468 (PCLandscape vtable[0xB]) ββ
|
| 1016 |
if !landscape.is_null() {
|
| 1017 |
let land_vt = *(landscape as *const *const u32);
|
| 1018 |
let get_val: unsafe extern "thiscall" fn(*mut u8) -> u32 =
|
| 1019 |
core::mem::transmute(*land_vt.add(0xB));
|
| 1020 |
+
(*ddgame).landscape_property = get_val(landscape);
|
| 1021 |
}
|
| 1022 |
|
| 1023 |
// NOTE: gfx_resource is NOT released here β arrow SpriteRegions need it.
|
|
|
|
| 1521 |
pub const SOUND_QUEUE_COUNT: usize = 0x8140;
|
| 1522 |
}
|
| 1523 |
|
| 1524 |
+
/// Coordinate entry used in DDGame screen coordinate tables (stride 0x10).
|
| 1525 |
+
///
|
| 1526 |
+
/// InitFields zeroes x and y; at runtime they contain fixed-point screen
|
| 1527 |
+
/// coordinates used for camera tracking and rendering regions.
|
| 1528 |
+
#[repr(C)]
|
| 1529 |
+
#[derive(Clone, Copy)]
|
| 1530 |
+
pub struct CoordEntry {
|
| 1531 |
+
pub x: i32,
|
| 1532 |
+
pub y: i32,
|
| 1533 |
+
pub _unknown: [u8; 8],
|
| 1534 |
+
}
|
| 1535 |
+
|
| 1536 |
+
const _: () = assert!(core::mem::size_of::<CoordEntry>() == 0x10);
|
| 1537 |
+
|
| 1538 |
// ============================================================
|
| 1539 |
// Sound queue entry β 16 entries at DDGame + 0x7F00
|
| 1540 |
// ============================================================
|
crates/openwa-wormkit/src/replacements/render.rs
CHANGED
|
@@ -542,8 +542,8 @@ unsafe extern "cdecl" fn draw_crosshair_line_impl(task_ptr: u32) {
|
|
| 542 |
}
|
| 543 |
|
| 544 |
// Enqueue polygon line (2 vertices)
|
| 545 |
-
let poly_param_1 = ddgame.
|
| 546 |
-
let poly_param_2 = ddgame.
|
| 547 |
let verts: [[i32; 3]; 2] = [[start_x, start_y, 0], [endpoint_x, endpoint_y, 0]];
|
| 548 |
let total_size = 2 * 0xC + 0x20;
|
| 549 |
if let Some(ptr) = rq.alloc_raw(total_size) {
|
|
|
|
| 542 |
}
|
| 543 |
|
| 544 |
// Enqueue polygon line (2 vertices)
|
| 545 |
+
let poly_param_1 = ddgame.gfx_color_table[8]; // crosshair line style
|
| 546 |
+
let poly_param_2 = ddgame.gfx_color_table[6]; // crosshair line color
|
| 547 |
let verts: [[i32; 3]; 2] = [[start_x, start_y, 0], [endpoint_x, endpoint_y, 0]];
|
| 548 |
let total_size = 2 * 0xC + 0x20;
|
| 549 |
if let Some(ptr) = rq.alloc_raw(total_size) {
|