paavohtl Claude Opus 4.6 (1M context) commited on
Commit
dfe2f8e
Β·
1 Parent(s): 93f1a62

debug: fix PCLandscape param order, defer sound_available, add logging

Browse files

- Swap params 4/5 in PCLandscape__Constructor call (game_info+0xDAAC
before wrapper, matching original push order)
- Defer sound_available=1 to end of constructor (prevents message pump
in DDGame__LoadWeaponSprites from triggering during construction)
- Add diagnostic logging for PCLandscape crash investigation
- Crash still occurs inside PCLandscape β€” likely remaining param
issues with stack-local output pointers (ESP+0x47 and ESP+0x64
from original's 4KB stack frame)

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

crates/openwa-core/src/engine/ddgame.rs CHANGED
@@ -468,7 +468,12 @@ pub unsafe fn create_ddgame(
468
 
469
  // ── 6. Sound available + always-1 flags ──
470
  let is_headless = *(game_info as *const u8).add(0xF914).cast::<i32>() != 0;
471
- (*ddgame).sound_available = if is_headless { 0 } else { 1 };
 
 
 
 
 
472
  (*ddgame)._field_7efc = 1;
473
 
474
  // ── 7. DDGameWrapper+0x48C init ──
@@ -495,6 +500,10 @@ pub unsafe fn create_ddgame(
495
  // ── 10. GfxHandler, landscape, sprites, audio, resources ──
496
  init_graphics_and_resources(wrapper, game_info, net_game, display, is_headless);
497
 
 
 
 
 
498
  let _ = crate::log::log_line("[DDGame] create_ddgame complete");
499
  ddgame
500
  }
@@ -697,7 +706,8 @@ unsafe fn init_graphics_and_resources(
697
  let f: unsafe extern "stdcall" fn(*mut DDGameWrapper) =
698
  core::mem::transmute(rb(va::DSSOUND_LOAD_EFFECT_WAVS) as usize);
699
  f(wrapper);
700
- // DSSound_LoadAllSpeechBanks: usercall(ESI=wrapper)
 
701
  call_usercall_esi(wrapper, LOAD_SPEECH_BANKS_ADDR);
702
  let _ = crate::log::log_line("[DDGame] audio: done");
703
  // Allocate ActiveSoundTable (0x608 bytes)
@@ -728,6 +738,7 @@ unsafe fn init_graphics_and_resources(
728
  "[DDGame] GfxResource returned: 0x{:08X}", gfx_resource as u32));
729
  }
730
 
 
731
  // ── PCLandscape (alloc 0xB44, stdcall 11 params) ──
732
  let landscape = {
733
  let alloc = wa_malloc(0xB44);
@@ -739,9 +750,9 @@ unsafe fn init_graphics_and_resources(
739
 
740
  let pc_ctor: unsafe extern "stdcall" fn(
741
  *mut u8, *mut DDGame, *mut u8, // this, ddgame, gfx_resource
742
- *mut DDGameWrapper, *const u8, // wrapper, game_info+0xDAAC
743
  *mut u8, u32, // &landscape_byte, gfx_mode
744
- *mut [i32; 2], *mut i32, // outputs: coords, more coords
745
  *mut u8, *mut u8, // &ddgame+0x777C, &ddgame+0x7780
746
  ) -> *mut u8 = core::mem::transmute(rb(va::PC_LANDSCAPE_CONSTRUCTOR) as usize);
747
 
@@ -750,15 +761,17 @@ unsafe fn init_graphics_and_resources(
750
  alloc,
751
  ddgame,
752
  gfx_resource,
753
- wrapper,
754
- gi.add(0xDAAC),
755
  &mut landscape_byte as *mut u8,
756
  (*wrapper).gfx_mode,
 
757
  &mut landscape_coords as *mut [i32; 2],
758
- landscape_coords.as_mut_ptr(), // placeholder for extra output
759
  (ddgame as *mut u8).add(0x777C),
760
  (ddgame as *mut u8).add(0x7780),
761
  );
 
 
762
  // Store landscape pointer
763
  (*wrapper).landscape = result as *mut PCLandscape;
764
  (*ddgame).landscape = result as *mut PCLandscape;
 
468
 
469
  // ── 6. Sound available + always-1 flags ──
470
  let is_headless = *(game_info as *const u8).add(0xF914).cast::<i32>() != 0;
471
+ // Defer sound_available β€” keep at 0 during construction.
472
+ // DDGame__LoadWeaponSprites checks this flag; when set, it calls
473
+ // FUN_572E30 which pumps PeekMessage/DispatchMessage. That can
474
+ // trigger game task code that reads uninitialized DDGame fields.
475
+ // Set to final value at the end of init_graphics_and_resources.
476
+ (*ddgame).sound_available = 0;
477
  (*ddgame)._field_7efc = 1;
478
 
479
  // ── 7. DDGameWrapper+0x48C init ──
 
500
  // ── 10. GfxHandler, landscape, sprites, audio, resources ──
501
  init_graphics_and_resources(wrapper, game_info, net_game, display, is_headless);
502
 
503
+ // Now set sound_available to its real value β€” construction is complete,
504
+ // so the message pump in DDGame__LoadWeaponSprites is safe.
505
+ (*ddgame).sound_available = if is_headless { 0 } else { 1 };
506
+
507
  let _ = crate::log::log_line("[DDGame] create_ddgame complete");
508
  ddgame
509
  }
 
706
  let f: unsafe extern "stdcall" fn(*mut DDGameWrapper) =
707
  core::mem::transmute(rb(va::DSSOUND_LOAD_EFFECT_WAVS) as usize);
708
  f(wrapper);
709
+ // DSSound_LoadAllSpeechBanks: the original is hooked to our Rust
710
+ // replacement (speech.rs), so the usercall bridge calls our code.
711
  call_usercall_esi(wrapper, LOAD_SPEECH_BANKS_ADDR);
712
  let _ = crate::log::log_line("[DDGame] audio: done");
713
  // Allocate ActiveSoundTable (0x608 bytes)
 
738
  "[DDGame] GfxResource returned: 0x{:08X}", gfx_resource as u32));
739
  }
740
 
741
+ let _ = crate::log::log_line("[DDGame] calling PCLandscape ctor");
742
  // ── PCLandscape (alloc 0xB44, stdcall 11 params) ──
743
  let landscape = {
744
  let alloc = wa_malloc(0xB44);
 
750
 
751
  let pc_ctor: unsafe extern "stdcall" fn(
752
  *mut u8, *mut DDGame, *mut u8, // this, ddgame, gfx_resource
753
+ *const u8, *mut DDGameWrapper, // game_info+0xDAAC, wrapper
754
  *mut u8, u32, // &landscape_byte, gfx_mode
755
+ *mut u8, *mut [i32; 2], // stack local, coord output
756
  *mut u8, *mut u8, // &ddgame+0x777C, &ddgame+0x7780
757
  ) -> *mut u8 = core::mem::transmute(rb(va::PC_LANDSCAPE_CONSTRUCTOR) as usize);
758
 
 
761
  alloc,
762
  ddgame,
763
  gfx_resource,
764
+ gi.add(0xDAAC), // param 4
765
+ wrapper, // param 5
766
  &mut landscape_byte as *mut u8,
767
  (*wrapper).gfx_mode,
768
+ &mut landscape_byte as *mut u8, // param 8 (stack local)
769
  &mut landscape_coords as *mut [i32; 2],
 
770
  (ddgame as *mut u8).add(0x777C),
771
  (ddgame as *mut u8).add(0x7780),
772
  );
773
+ let _ = crate::log::log_line(&format!(
774
+ "[DDGame] PCLandscape returned: 0x{:08X}", result as u32));
775
  // Store landscape pointer
776
  (*wrapper).landscape = result as *mut PCLandscape;
777
  (*ddgame).landscape = result as *mut PCLandscape;