feat: port DSSound_LoadEffectWAVs to Rust, rename DDGame__LoadFonts
Browse filesPort DSSound_LoadEffectWAVs (0x5714B0) to pure Rust β iterates the SFX
name table at 0x6AF378, builds "data\wav\Effects\{name}.wav" paths, and
calls the already-ported DSSound::load_wav for each entry. Removes the
last WA bridge call from the audio init path in ddgame_constructor.
Rename DDGAME_INIT_SOUND_PATHS to DDGAME_LOAD_FONTS β the function at
0x570F30 loads .fnt font resources, not sound paths.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
crates/openwa-core/src/address.rs
CHANGED
|
@@ -97,8 +97,8 @@ pub mod va {
|
|
| 97 |
fn/Usercall DDGAME_INIT_RENDER_INDICES = 0x0052_6080;
|
| 98 |
/// DDGame__InitVersionFlags β stdcall(ddgame_wrapper)
|
| 99 |
fn/Stdcall DDGAME_INIT_VERSION_FLAGS = 0x0052_5BE0;
|
| 100 |
-
///
|
| 101 |
-
fn
|
| 102 |
/// DDGame__LoadHudAndWeaponSprites
|
| 103 |
fn/Thiscall DDGAME_LOAD_HUD_AND_WEAPON_SPRITES = 0x0053_D0E0;
|
| 104 |
/// DDGame__InitPaletteGradientSprites
|
|
|
|
| 97 |
fn/Usercall DDGAME_INIT_RENDER_INDICES = 0x0052_6080;
|
| 98 |
/// DDGame__InitVersionFlags β stdcall(ddgame_wrapper)
|
| 99 |
fn/Stdcall DDGAME_INIT_VERSION_FLAGS = 0x0052_5BE0;
|
| 100 |
+
/// DDGame__LoadFonts β loads .fnt font resources into the display.
|
| 101 |
+
fn DDGAME_LOAD_FONTS = 0x0057_0F30;
|
| 102 |
/// DDGame__LoadHudAndWeaponSprites
|
| 103 |
fn/Thiscall DDGAME_LOAD_HUD_AND_WEAPON_SPRITES = 0x0053_D0E0;
|
| 104 |
/// DDGame__InitPaletteGradientSprites
|
crates/openwa-core/src/engine/ddgame_constructor.rs
CHANGED
|
@@ -153,7 +153,7 @@ pub fn init_constructor_addrs() {
|
|
| 153 |
unsafe {
|
| 154 |
SPRITE_REGION_CTOR_ADDR = rb(va::SPRITE_REGION_CONSTRUCTOR);
|
| 155 |
FUN_570A90_ADDR = rb(va::FUN_570A90);
|
| 156 |
-
FUN_570F30_ADDR = rb(va::
|
| 157 |
LOAD_SPEECH_BANKS_ADDR = rb(va::DSSOUND_LOAD_ALL_SPEECH_BANKS);
|
| 158 |
LOADING_PROGRESS_TICK_ADDR = rb(va::DDGAME_WRAPPER_LOADING_PROGRESS_TICK);
|
| 159 |
GFX_LOAD_SPRITES_ADDR = rb(va::GFX_DIR_LOAD_SPRITES);
|
|
@@ -203,12 +203,48 @@ unsafe extern "C" fn wa_load_sprites(
|
|
| 203 |
|
| 204 |
static mut GFX_LOAD_SPRITES_ADDR: u32 = 0;
|
| 205 |
|
| 206 |
-
/// DSSound_LoadEffectWAVs (
|
| 207 |
-
|
| 208 |
-
|
| 209 |
-
|
| 210 |
-
|
| 211 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 212 |
}
|
| 213 |
|
| 214 |
/// PCLandscape__Constructor (0x57ACB0): construct landscape object (0xB44 bytes, 11 params).
|
|
@@ -591,10 +627,10 @@ unsafe fn init_graphics_and_resources(
|
|
| 591 |
|
| 592 |
// ββ Audio init (non-headless + sound available) ββ
|
| 593 |
if !is_headless {
|
| 594 |
-
// FUN_570F30:
|
| 595 |
call_usercall_esi(wrapper, FUN_570F30_ADDR);
|
| 596 |
if !(*ddgame).sound.is_null() {
|
| 597 |
-
|
| 598 |
// DSSound_LoadAllSpeechBanks: the original is hooked to our Rust
|
| 599 |
// replacement (speech.rs), so the usercall bridge calls our code.
|
| 600 |
call_usercall_esi(wrapper, LOAD_SPEECH_BANKS_ADDR);
|
|
|
|
| 153 |
unsafe {
|
| 154 |
SPRITE_REGION_CTOR_ADDR = rb(va::SPRITE_REGION_CONSTRUCTOR);
|
| 155 |
FUN_570A90_ADDR = rb(va::FUN_570A90);
|
| 156 |
+
FUN_570F30_ADDR = rb(va::DDGAME_LOAD_FONTS);
|
| 157 |
LOAD_SPEECH_BANKS_ADDR = rb(va::DSSOUND_LOAD_ALL_SPEECH_BANKS);
|
| 158 |
LOADING_PROGRESS_TICK_ADDR = rb(va::DDGAME_WRAPPER_LOADING_PROGRESS_TICK);
|
| 159 |
GFX_LOAD_SPRITES_ADDR = rb(va::GFX_DIR_LOAD_SPRITES);
|
|
|
|
| 203 |
|
| 204 |
static mut GFX_LOAD_SPRITES_ADDR: u32 = 0;
|
| 205 |
|
| 206 |
+
/// Port of DSSound_LoadEffectWAVs (0x5714B0).
|
| 207 |
+
///
|
| 208 |
+
/// Iterates the sound effect name table at 0x6AF378 (pairs of [slot_id, name_ptr],
|
| 209 |
+
/// null-terminated). For each entry, builds "data\wav\Effects\{name}.wav" and calls
|
| 210 |
+
/// DSSound::load_wav (vtable slot 12, already Rust).
|
| 211 |
+
unsafe fn load_effect_wavs(wrapper: *mut DDGameWrapper) {
|
| 212 |
+
use std::ffi::CStr;
|
| 213 |
+
|
| 214 |
+
/// Sound effect name table entry: (slot_id, name_ptr).
|
| 215 |
+
#[repr(C)]
|
| 216 |
+
struct SfxEntry {
|
| 217 |
+
slot_id: i32,
|
| 218 |
+
name_ptr: *const std::ffi::c_char,
|
| 219 |
+
}
|
| 220 |
+
|
| 221 |
+
let table = rb(0x006A_F378) as *const SfxEntry;
|
| 222 |
+
let sound = (*wrapper).sound;
|
| 223 |
+
if sound.is_null() {
|
| 224 |
+
return;
|
| 225 |
+
}
|
| 226 |
+
let sound_vt = &*(*sound).vtable;
|
| 227 |
+
|
| 228 |
+
let mut i = 0;
|
| 229 |
+
loop {
|
| 230 |
+
let entry = &*table.add(i);
|
| 231 |
+
if entry.name_ptr.is_null() {
|
| 232 |
+
break;
|
| 233 |
+
}
|
| 234 |
+
if entry.slot_id == 0 {
|
| 235 |
+
break;
|
| 236 |
+
}
|
| 237 |
+
|
| 238 |
+
let name = CStr::from_ptr(entry.name_ptr).to_str().unwrap_or("");
|
| 239 |
+
let path = format!("data\\wav\\Effects\\{}.wav\0", name);
|
| 240 |
+
|
| 241 |
+
(sound_vt.load_wav)(sound, entry.slot_id, path.as_ptr());
|
| 242 |
+
|
| 243 |
+
// Update loading progress bar
|
| 244 |
+
call_usercall_ecx(wrapper, LOADING_PROGRESS_TICK_ADDR);
|
| 245 |
+
|
| 246 |
+
i += 1;
|
| 247 |
+
}
|
| 248 |
}
|
| 249 |
|
| 250 |
/// PCLandscape__Constructor (0x57ACB0): construct landscape object (0xB44 bytes, 11 params).
|
|
|
|
| 627 |
|
| 628 |
// ββ Audio init (non-headless + sound available) ββ
|
| 629 |
if !is_headless {
|
| 630 |
+
// FUN_570F30: font loading (usercall ESI=wrapper) β NOT audio related
|
| 631 |
call_usercall_esi(wrapper, FUN_570F30_ADDR);
|
| 632 |
if !(*ddgame).sound.is_null() {
|
| 633 |
+
load_effect_wavs(wrapper);
|
| 634 |
// DSSound_LoadAllSpeechBanks: the original is hooked to our Rust
|
| 635 |
// replacement (speech.rs), so the usercall bridge calls our code.
|
| 636 |
call_usercall_esi(wrapper, LOAD_SPEECH_BANKS_ADDR);
|