paavohtl Claude Opus 4.6 (1M context) commited on
Commit
bec7314
Β·
1 Parent(s): 7b6533e

refactor: name DDGame fields, add CoordEntry struct, unify gfx_color_table

Browse files

Replace 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 _param_028: *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,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-derived value
88
- pub _landscape_val: *mut u8,
 
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 init.
181
- pub _field_64d8: u32,
182
  /// 0x64DC-0x72A3: Unknown
183
  pub _unknown_64dc: [u8; 0x72A4 - 0x64DC],
184
- /// 0x72A4: Cleared by init.
185
- pub _field_72a4: u32,
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-0x731C: 5 GfxDir color entries
204
- pub _gfx_color_entries: [u8; 0x7324 - 0x730C],
205
-
206
- /// 0x7324: Crosshair line color param (DrawPolygon param_2).
207
- /// Part of GfxDir color entries at 0x730C.
208
- pub crosshair_line_color: u32,
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: Unknown flag/counter (value 4 at runtime β€” team count?)
292
- pub _field_7ea0: u32,
293
- /// 0x7EA4: Unknown
294
- pub _unknown_7ea4: u32,
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: Unknown flag (-1 = 0xFFFFFFFF at runtime)
302
- pub _field_7ef0: i32,
303
- /// 0x7EF4: Unknown
304
- pub _unknown_7ef4: u32,
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 _field_7efc: u32,
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-0x8CF8: 4Γ— coordinate entries (0x10-byte stride).
336
- /// InitFields zeroes +0 and +4 of each. At runtime contains fixed-point
337
  /// screen coordinates (e.g. 393.0, 532.0, 960.0, 348.0).
338
- pub coord_entries_8cbc: [u8; 0x8CFC - 0x8CBC],
339
 
340
  /// 0x8CFC-0x984F: Unknown
341
  pub _unknown_8cfc: [u8; 0x9850 - 0x8CFC],
342
 
343
- /// 0x9850-0x988F: 4Γ— coordinate entries (0x10-byte stride, zeroed by InitFields).
344
- pub coord_entries_9850: [u8; 0x9890 - 0x9850],
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
- 0x3930,
399
- 0x3AC4,
400
- 0x3C58,
401
- 0x3DEC,
402
- 0x3F80,
403
- 0x4114,
404
- 0x42A8,
405
- 0x443C,
406
- 0x45D0,
407
  ] {
408
- *(base.add(off as usize) as *mut u32) = 0;
409
  }
410
 
411
- *(base.add(0x64D8) as *mut u32) = 0;
412
- *(base.add(0x72A4) as *mut u32) = 0;
413
 
414
  // InitRenderIndices β€” original sets ESI = ddgame + 0x72D8 before calling
415
  ddgame_init_render_indices(base.add(0x72D8));
416
 
417
- // Zero 8 fields at 0x8Cxx
418
- for &off in &[
419
- 0x8CBCusize,
420
- 0x8CC0,
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
- // Zero 8 fields at 0x98xx
432
- for &off in &[
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)._param_028 = net_game;
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)._field_7efc = 1;
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
- let mut off = 0x730Cu32;
902
- let mut idx = 0u32;
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
- // (ddgame_offset, ECX, EDX, p2, p3, p4, p5, p6=gfx_resource)
1023
  // p6 is the GfxResource pointer returned by GfxResource__Create_Maybe.
1024
  let gr = gfx_resource as u32;
1025
- let regions: [(u32, u32, u32, u32, u32, u32, u32, u32); 8] = [
1026
- (0x474, 0x37, 0x36, 0x2E, 0x24, 0x41, 0x2D, gr),
1027
- (0x46C, 0x30, 0x0C, 0x2D, 0x07, 0x34, 0x09, gr),
1028
- (0x470, 0x11, 0x1A, 0x0D, 0x0A, 0x16, 0x13, gr),
1029
- (0x478, 0x0C, 0x3D, 0x00, 0x20, 0x18, 0x33, gr),
1030
- (0x47C, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, gr),
1031
- (0x484, 0x1A2, 0x1B, 0x173, 0x09, 0x1D8, 0x03, gr),
1032
- (0x488, 0x1EF, 0x26, 0x1E5, 0x07, 0x1F9, 0x16, gr),
1033
- (0x480, 0x2D, 0x08, 0x2D, 0x07, 0x2E, 0x07, gr),
1034
  ];
1035
 
1036
- for &(offset, ecx, edx, p2, p3, p4, p5, p6) in &regions {
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
- *((ddgame as *mut u8).add(offset as usize) as *mut *mut u8) = result;
1044
  }
1045
  }
1046
 
1047
- // ── Landscape-derived value at DDGame+0x468 ──
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
- *((ddgame as *mut u8).add(0x468) as *mut u32) = get_val(landscape);
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 &regions {
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.crosshair_line_style;
546
- let poly_param_2 = ddgame.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) {
 
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) {