paavohtl Claude Opus 4.6 (1M context) commited on
Commit
3c72efb
Β·
1 Parent(s): 74b6e34

refactor: clean up outdated comments in ddgame.rs

Browse files

- Simplify verbose vtable calling convention comments to purpose descriptions
- Remove x86 instruction-level "Original:" comments (noise post-porting)
- Remove development breadcrumbs and debug provenance notes
- Condense multi-line comment blocks to concise summaries
- Remove empty else branch and obvious/redundant comments
- Keep TODO for unported complex gradient computation
- Improve doc comment on init_graphics_and_resources

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

crates/openwa-core/src/engine/ddgame.rs CHANGED
@@ -446,7 +446,6 @@ pub unsafe fn ddgame_init_fields(ddgame: *mut DDGame) {
446
  /// # Safety
447
  /// `base` must point to a valid memory region with at least 0x4A4 bytes.
448
  pub unsafe fn ddgame_init_render_indices(base: *mut u8) {
449
- // Zero base+0xC4
450
  *(base.add(0xC4) as *mut u32) = 0;
451
 
452
  // eh_vector_constructor_iterator equivalent:
@@ -510,7 +509,6 @@ pub unsafe fn task_state_machine_init(object: *mut u8, param1: u32, width: u32,
510
  core::ptr::write_bytes(buffer, 0, total_size as usize);
511
  core::ptr::write_bytes(buffer, 0, total_size as usize);
512
 
513
- // Set object fields (DWORD array layout)
514
  let obj = object as *mut u32;
515
  *obj.add(0) = rb(0x6640EC); // vtable
516
  *obj.add(1) = 0; // unused
@@ -556,7 +554,7 @@ pub unsafe fn display_layer_color_init(wrapper: *mut DDGameWrapper) {
556
 
557
  let display = (*wrapper).display as *mut u8;
558
  let vt = *(display as *const *const u32);
559
- // vtable[4] (offset 0x10): thiscall(display, layer, color), RET 0x8
560
  let set_color: unsafe extern "thiscall" fn(*mut u8, i32, i32) =
561
  core::mem::transmute(*vt.add(4));
562
 
@@ -821,7 +819,6 @@ pub unsafe fn gfx_handler_load_dir(handler: *mut u8) -> i32 {
821
  }
822
  }
823
 
824
- // Mark as loaded
825
  *(handler.add(0x194) as *mut u32) = 1;
826
 
827
  1 // success
@@ -958,10 +955,7 @@ pub unsafe fn create_ddgame(
958
 
959
  // ── 6. Sound available + always-1 flags ──
960
  let is_headless = (*game_info).headless_mode != 0;
961
- // Original: sound_available = (headless_mode == 0) β€” set EARLY.
962
- // This enables the loading progress bar, message pump, and sound during
963
- // construction. Previously deferred to avoid message pump crashes, but all
964
- // critical DDGame fields (game_info, display, sound, etc.) are now set.
965
  (*ddgame).sound_available = if is_headless { 0 } else { 1 };
966
  (*ddgame)._field_7efc = 1;
967
 
@@ -993,8 +987,7 @@ pub unsafe fn create_ddgame(
993
 
994
  /// Second half of the constructor: GfxHandler, landscape, sprites, audio, resources.
995
  ///
996
- /// Separated for readability. Will be broken into smaller functions as
997
- /// individual sections are converted to pure Rust.
998
  #[cfg(target_arch = "x86")]
999
  unsafe fn init_graphics_and_resources(
1000
  wrapper: *mut DDGameWrapper,
@@ -1006,7 +999,7 @@ unsafe fn init_graphics_and_resources(
1006
  let ddgame = (*wrapper).ddgame;
1007
  let fopen: unsafe extern "cdecl" fn(*const u8, *const u8) -> *mut u8 =
1008
  core::mem::transmute(rb(va::WA_FOPEN) as usize);
1009
- let gfx_handler_vtable = rb(0x66B280) as u32; // GfxHandler__vtable (from asm: MOV [ESI], 0x66B280)
1010
 
1011
  // ── GfxHandler #1 (primary) ──
1012
  let gfx1 = wa_malloc(0x19C);
@@ -1068,7 +1061,6 @@ unsafe fn init_graphics_and_resources(
1068
 
1069
  // ── GfxHandler #2 (conditional) ──
1070
  let game_version = (*game_info).game_version;
1071
- // Original: (-(gfx_mode != 0) & 0x23) - 2 β†’ gfx_mode ? 33 : -2
1072
  let threshold = if (*wrapper).gfx_mode != 0 { 33 } else { -2i32 };
1073
  if game_version < threshold {
1074
  let c_digit = if game_version > -3 { b'2' } else { b'1' };
@@ -1096,21 +1088,19 @@ unsafe fn init_graphics_and_resources(
1096
  if *(rb(0x88E485) as *const u8) == 0 {
1097
  call_usercall_eax(wrapper, FUN_570A90_ADDR);
1098
  }
1099
- // DDGameWrapper+0x4D0 points to the display object used for palette calls.
1100
- // BUT: FUN_00570A90 or something else may write to wrapper in ways we
1101
- // don't expect. Read via struct field instead of raw offset.
1102
  let disp = (*wrapper).display as *mut u8;
1103
  let gfx_handler = (*wrapper)._field_4c0;
1104
  let vt = *(disp as *const *const u32);
1105
- // vtable[4] (offset 0x10): thiscall + 2 stack params (1, 0xFE), RET 0x8
1106
  let vt_10: unsafe extern "thiscall" fn(*mut u8, i32, i32) =
1107
  core::mem::transmute(*vt.add(4));
1108
  vt_10(disp, 1, 0xFE);
1109
- // vtable[0x1F] (offset 0x7C): thiscall + 5 stack params, RET 0x14
1110
  let vt_7c: unsafe extern "thiscall" fn(*mut u8, i32, i32, i32, *mut u8, u32) =
1111
  core::mem::transmute(*vt.add(0x1F));
1112
  vt_7c(disp, 1, 1, 0, gfx_handler, rb(0x66A3A8));
1113
- // vtable[0x17] (offset 0x5C): thiscall + 2 stack params, RET 0x8
1114
  let vt_5c: unsafe extern "thiscall" fn(*mut u8, i32, i32) =
1115
  core::mem::transmute(*vt.add(0x17));
1116
  vt_5c(disp, 1, -100);
@@ -1146,7 +1136,6 @@ unsafe fn init_graphics_and_resources(
1146
 
1147
  // ── GfxDir color entries DDGame+0x730C..0x732C ──
1148
  if (*wrapper).gfx_mode != 0 {
1149
- // Original: PUSH ESI (=layer_ctx from vtable[5] call), MOV EAX=0x66A3B4, CALL 0x4F6300
1150
  // The layer_ctx is used as the output buffer, not a plain stack alloc.
1151
  let res = gfx_resource_create((*wrapper)._field_4c0, rb(0x66A3B4) as *const u8, layer_ctx);
1152
  if !res.is_null() {
@@ -1168,8 +1157,6 @@ unsafe fn init_graphics_and_resources(
1168
  core::mem::transmute(*rvt.add(3));
1169
  release(res, 1);
1170
  }
1171
- } else {
1172
- // gfx_mode == 0: no color entries to load
1173
  }
1174
 
1175
  // ── Secondary GfxDir object (DDGame+0x2C, conditional) ──
@@ -1196,9 +1183,7 @@ unsafe fn init_graphics_and_resources(
1196
 
1197
  // ── DDGameWrapper field inits ──
1198
  (*wrapper)._field_4d8 = 0;
1199
- // Original: if (display == NULL) iVar4=0 else iVar4=*(byte*)(game_info+0x44C)*0x38+0x7E
1200
- // Ghidra mislabeled game_info as param8 β€” the original reads game_info, not net_game.
1201
- // Our headless display is non-null, so use is_headless as the condition.
1202
  if is_headless {
1203
  (*wrapper)._field_4dc = 0x2AD;
1204
  } else {
@@ -1278,7 +1263,6 @@ unsafe fn init_graphics_and_resources(
1278
  (ddgame as *mut u8).add(0x777C), // param 10
1279
  (ddgame as *mut u8).add(0x7780), // param 11
1280
  );
1281
- // Store landscape pointer
1282
  (*wrapper).landscape = result as *mut PCLandscape;
1283
  (*ddgame).landscape = result as *mut PCLandscape;
1284
  result
@@ -1306,7 +1290,6 @@ unsafe fn init_graphics_and_resources(
1306
  // ── 8Γ— SpriteRegion at DDGame+0x46C..0x488 ──
1307
  // SpriteRegion__Constructor: fastcall(ECX, EDX) + 6 stack(this, p2, p3, p4, p5, p6), RET 0x18
1308
  {
1309
- // Params verified by hooking original (see SpriteRegion param logger).
1310
  // (ddgame_offset, ECX, EDX, p2, p3, p4, p5, p6=gfx_resource)
1311
  // p6 is the GfxResource pointer returned by GfxResource__Create_Maybe.
1312
  let gr = gfx_resource as u32;
@@ -1436,14 +1419,10 @@ unsafe fn init_graphics_and_resources(
1436
  }
1437
 
1438
  // ── DisplayGfx at DDGame+0x138 ──
1439
- // Original: alloc 0x4C, memset 0x2C, PUSH 0x100, MOV ECX=8, MOV EDI=0x1E0,
1440
- // CALL 0x4F6370, MOV [alloc]=0x664144
1441
  {
1442
  let tsm = wa_malloc(0x4C);
1443
  core::ptr::write_bytes(tsm, 0, 0x2C);
1444
  if !tsm.is_null() {
1445
- // Original: TaskStateMachine__Init(ECX=8, EDI=0x1E0, stack=0x100)
1446
- // β†’ task_state_machine_init(object, param1=8, width=0x100, height=0x1E0)
1447
  task_state_machine_init(tsm, 8, 0x100, 0x1E0);
1448
  *(tsm as *mut u32) = rb(0x664144); // Override vtable to DisplayGfx
1449
  }
@@ -1588,7 +1567,6 @@ unsafe fn init_graphics_and_resources(
1588
  b"layer\\layer.spr|layer.spr\0".as_ptr(),
1589
  );
1590
 
1591
- // gradient_image_2 = 0
1592
  (*ddgame).gradient_image_2 = core::ptr::null_mut();
1593
 
1594
  // ── Gradient image (0x030) ──
@@ -1605,10 +1583,8 @@ unsafe fn init_graphics_and_resources(
1605
  call_gfx_find_and_load(land_layer, b"gradient.img\0".as_ptr(), layer3_ctx);
1606
  (*ddgame).gradient_image = gradient;
1607
  } else {
1608
- // Complex gradient computation β€” ~200 lines of color interpolation.
1609
- // For now, skip this path (gradient_image remains null/0).
1610
- // This affects the sky background appearance but not gameplay.
1611
- // Set gradient_image to null (already zero from memset)
1612
  }
1613
 
1614
  // ── Fill image β†’ fill_pixel (0x7338) ──
@@ -1647,10 +1623,7 @@ unsafe fn init_graphics_and_resources(
1647
  call_usercall_ecx(wrapper, LOADING_PROGRESS_TICK_ADDR);
1648
  }
1649
  // ── Gradient image stub (DDGame+0x30) ──
1650
- // The original constructor loads "gradient.img" here and stores the result at DDGame+0x30.
1651
- // CTaskLand__InitLandscape reads DDGame+0x30/+0x34 and calls vtable[4](0, i) for each
1652
- // pixel column. vtable[4] = CTaskOilDrum__ProcessFrame_stub (XOR EAX,EAX; RET 0x8) returns 0.
1653
- // A minimal stub with [6]=0 (zero-width) causes the loop to not execute at all.
1654
  if (*ddgame).gradient_image.is_null() {
1655
  let obj = wa_malloc(0x2C);
1656
  core::ptr::write_bytes(obj, 0, 0x2C);
 
446
  /// # Safety
447
  /// `base` must point to a valid memory region with at least 0x4A4 bytes.
448
  pub unsafe fn ddgame_init_render_indices(base: *mut u8) {
 
449
  *(base.add(0xC4) as *mut u32) = 0;
450
 
451
  // eh_vector_constructor_iterator equivalent:
 
509
  core::ptr::write_bytes(buffer, 0, total_size as usize);
510
  core::ptr::write_bytes(buffer, 0, total_size as usize);
511
 
 
512
  let obj = object as *mut u32;
513
  *obj.add(0) = rb(0x6640EC); // vtable
514
  *obj.add(1) = 0; // unused
 
554
 
555
  let display = (*wrapper).display as *mut u8;
556
  let vt = *(display as *const *const u32);
557
+ // vtable[4]: set layer color
558
  let set_color: unsafe extern "thiscall" fn(*mut u8, i32, i32) =
559
  core::mem::transmute(*vt.add(4));
560
 
 
819
  }
820
  }
821
 
 
822
  *(handler.add(0x194) as *mut u32) = 1;
823
 
824
  1 // success
 
955
 
956
  // ── 6. Sound available + always-1 flags ──
957
  let is_headless = (*game_info).headless_mode != 0;
958
+ // sound_available enables loading progress bar, message pump, and sound during construction.
 
 
 
959
  (*ddgame).sound_available = if is_headless { 0 } else { 1 };
960
  (*ddgame)._field_7efc = 1;
961
 
 
987
 
988
  /// Second half of the constructor: GfxHandler, landscape, sprites, audio, resources.
989
  ///
990
+ /// Second half of the constructor β€” initializes graphics, audio, landscape, and sprites.
 
991
  #[cfg(target_arch = "x86")]
992
  unsafe fn init_graphics_and_resources(
993
  wrapper: *mut DDGameWrapper,
 
999
  let ddgame = (*wrapper).ddgame;
1000
  let fopen: unsafe extern "cdecl" fn(*const u8, *const u8) -> *mut u8 =
1001
  core::mem::transmute(rb(va::WA_FOPEN) as usize);
1002
+ let gfx_handler_vtable = rb(0x66B280) as u32; // GfxHandler vtable
1003
 
1004
  // ── GfxHandler #1 (primary) ──
1005
  let gfx1 = wa_malloc(0x19C);
 
1061
 
1062
  // ── GfxHandler #2 (conditional) ──
1063
  let game_version = (*game_info).game_version;
 
1064
  let threshold = if (*wrapper).gfx_mode != 0 { 33 } else { -2i32 };
1065
  if game_version < threshold {
1066
  let c_digit = if game_version > -3 { b'2' } else { b'1' };
 
1088
  if *(rb(0x88E485) as *const u8) == 0 {
1089
  call_usercall_eax(wrapper, FUN_570A90_ADDR);
1090
  }
1091
+ // Read display (may be modified by FUN_00570A90).
 
 
1092
  let disp = (*wrapper).display as *mut u8;
1093
  let gfx_handler = (*wrapper)._field_4c0;
1094
  let vt = *(disp as *const *const u32);
1095
+ // vtable[4]: set palette range
1096
  let vt_10: unsafe extern "thiscall" fn(*mut u8, i32, i32) =
1097
  core::mem::transmute(*vt.add(4));
1098
  vt_10(disp, 1, 0xFE);
1099
+ // vtable[0x1F]: init palette layer
1100
  let vt_7c: unsafe extern "thiscall" fn(*mut u8, i32, i32, i32, *mut u8, u32) =
1101
  core::mem::transmute(*vt.add(0x1F));
1102
  vt_7c(disp, 1, 1, 0, gfx_handler, rb(0x66A3A8));
1103
+ // vtable[0x17]: set layer visibility
1104
  let vt_5c: unsafe extern "thiscall" fn(*mut u8, i32, i32) =
1105
  core::mem::transmute(*vt.add(0x17));
1106
  vt_5c(disp, 1, -100);
 
1136
 
1137
  // ── GfxDir color entries DDGame+0x730C..0x732C ──
1138
  if (*wrapper).gfx_mode != 0 {
 
1139
  // The layer_ctx is used as the output buffer, not a plain stack alloc.
1140
  let res = gfx_resource_create((*wrapper)._field_4c0, rb(0x66A3B4) as *const u8, layer_ctx);
1141
  if !res.is_null() {
 
1157
  core::mem::transmute(*rvt.add(3));
1158
  release(res, 1);
1159
  }
 
 
1160
  }
1161
 
1162
  // ── Secondary GfxDir object (DDGame+0x2C, conditional) ──
 
1183
 
1184
  // ── DDGameWrapper field inits ──
1185
  (*wrapper)._field_4d8 = 0;
1186
+ // Loading progress total: game_info+0x44C controls team count scaling.
 
 
1187
  if is_headless {
1188
  (*wrapper)._field_4dc = 0x2AD;
1189
  } else {
 
1263
  (ddgame as *mut u8).add(0x777C), // param 10
1264
  (ddgame as *mut u8).add(0x7780), // param 11
1265
  );
 
1266
  (*wrapper).landscape = result as *mut PCLandscape;
1267
  (*ddgame).landscape = result as *mut PCLandscape;
1268
  result
 
1290
  // ── 8Γ— SpriteRegion at DDGame+0x46C..0x488 ──
1291
  // SpriteRegion__Constructor: fastcall(ECX, EDX) + 6 stack(this, p2, p3, p4, p5, p6), RET 0x18
1292
  {
 
1293
  // (ddgame_offset, ECX, EDX, p2, p3, p4, p5, p6=gfx_resource)
1294
  // p6 is the GfxResource pointer returned by GfxResource__Create_Maybe.
1295
  let gr = gfx_resource as u32;
 
1419
  }
1420
 
1421
  // ── DisplayGfx at DDGame+0x138 ──
 
 
1422
  {
1423
  let tsm = wa_malloc(0x4C);
1424
  core::ptr::write_bytes(tsm, 0, 0x2C);
1425
  if !tsm.is_null() {
 
 
1426
  task_state_machine_init(tsm, 8, 0x100, 0x1E0);
1427
  *(tsm as *mut u32) = rb(0x664144); // Override vtable to DisplayGfx
1428
  }
 
1567
  b"layer\\layer.spr|layer.spr\0".as_ptr(),
1568
  );
1569
 
 
1570
  (*ddgame).gradient_image_2 = core::ptr::null_mut();
1571
 
1572
  // ── Gradient image (0x030) ──
 
1583
  call_gfx_find_and_load(land_layer, b"gradient.img\0".as_ptr(), layer3_ctx);
1584
  (*ddgame).gradient_image = gradient;
1585
  } else {
1586
+ // TODO: port complex gradient computation (~200 lines of color interpolation).
1587
+ // Affects sky background appearance. Not yet implemented.
 
 
1588
  }
1589
 
1590
  // ── Fill image β†’ fill_pixel (0x7338) ──
 
1623
  call_usercall_ecx(wrapper, LOADING_PROGRESS_TICK_ADDR);
1624
  }
1625
  // ── Gradient image stub (DDGame+0x30) ──
1626
+ // Minimal stub: [6]=0 (zero-width) so CTaskLand skips the gradient column loop.
 
 
 
1627
  if (*ddgame).gradient_image.is_null() {
1628
  let obj = wa_malloc(0x2C);
1629
  core::ptr::write_bytes(obj, 0, 0x2C);