style: cargo fmt, add automatic cargo fmt hook
Browse filesCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- .claude/settings.json +14 -1
- crates/openwa-config/src/lib.rs +6 -8
- crates/openwa-core/src/address.rs +4 -5
- crates/openwa-core/src/audio/music.rs +39 -53
- crates/openwa-core/src/audio/sound_id.rs +0 -1
- crates/openwa-core/src/audio/speech_ops.rs +51 -50
- crates/openwa-core/src/lib.rs +1 -1
- crates/openwa-core/src/task/cloud.rs +0 -1
- crates/openwa-launcher/src/main.rs +0 -1
- crates/openwa-test-runner/src/main.rs +1 -4
- crates/openwa-wormkit/src/replacements/speech.rs +1 -1
.claude/settings.json
CHANGED
|
@@ -4,5 +4,18 @@
|
|
| 4 |
"Bash(target/i686-pc-windows-msvc/release/openwa-debug resume:*)",
|
| 5 |
"Bash(taskkill /f /im WA.exe)"
|
| 6 |
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7 |
}
|
| 8 |
-
}
|
|
|
|
| 4 |
"Bash(target/i686-pc-windows-msvc/release/openwa-debug resume:*)",
|
| 5 |
"Bash(taskkill /f /im WA.exe)"
|
| 6 |
]
|
| 7 |
+
},
|
| 8 |
+
"hooks": {
|
| 9 |
+
"PostToolUse": [
|
| 10 |
+
{
|
| 11 |
+
"matcher": "Write|Edit|MultiEdit",
|
| 12 |
+
"hooks": [
|
| 13 |
+
{
|
| 14 |
+
"type": "command",
|
| 15 |
+
"command": "cd \"$CLAUDE_TOOL_INPUT_FILE_PATH\" && cargo fmt 2>/dev/null || cargo fmt --manifest-path \"$(git rev-parse --show-toplevel)/Cargo.toml\" 2>/dev/null || true"
|
| 16 |
+
}
|
| 17 |
+
]
|
| 18 |
+
}
|
| 19 |
+
]
|
| 20 |
}
|
| 21 |
+
}
|
crates/openwa-config/src/lib.rs
CHANGED
|
@@ -28,7 +28,11 @@ fn from_env() -> Option<PathBuf> {
|
|
| 28 |
let val = std::env::var_os("OPENWA_WA_PATH")?;
|
| 29 |
let path = PathBuf::from(val);
|
| 30 |
// Accept either a WA.exe path or a directory.
|
| 31 |
-
if path
|
|
|
|
|
|
|
|
|
|
|
|
|
| 32 |
path.parent().map(|p| p.to_path_buf())
|
| 33 |
} else {
|
| 34 |
Some(path)
|
|
@@ -50,13 +54,7 @@ fn from_registry() -> Option<PathBuf> {
|
|
| 50 |
fn read_registry_sz(key: &[u8], value: &[u8], buf: &mut [u8]) -> Option<usize> {
|
| 51 |
unsafe {
|
| 52 |
let mut hkey: HKEY = std::ptr::null_mut();
|
| 53 |
-
let status = RegOpenKeyExA(
|
| 54 |
-
HKEY_CURRENT_USER,
|
| 55 |
-
key.as_ptr(),
|
| 56 |
-
0,
|
| 57 |
-
KEY_READ,
|
| 58 |
-
&mut hkey,
|
| 59 |
-
);
|
| 60 |
if status != 0 {
|
| 61 |
return None;
|
| 62 |
}
|
|
|
|
| 28 |
let val = std::env::var_os("OPENWA_WA_PATH")?;
|
| 29 |
let path = PathBuf::from(val);
|
| 30 |
// Accept either a WA.exe path or a directory.
|
| 31 |
+
if path
|
| 32 |
+
.extension()
|
| 33 |
+
.map(|e| e.eq_ignore_ascii_case("exe"))
|
| 34 |
+
.unwrap_or(false)
|
| 35 |
+
{
|
| 36 |
path.parent().map(|p| p.to_path_buf())
|
| 37 |
} else {
|
| 38 |
Some(path)
|
|
|
|
| 54 |
fn read_registry_sz(key: &[u8], value: &[u8], buf: &mut [u8]) -> Option<usize> {
|
| 55 |
unsafe {
|
| 56 |
let mut hkey: HKEY = std::ptr::null_mut();
|
| 57 |
+
let status = RegOpenKeyExA(HKEY_CURRENT_USER, key.as_ptr(), 0, KEY_READ, &mut hkey);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 58 |
if status != 0 {
|
| 59 |
return None;
|
| 60 |
}
|
crates/openwa-core/src/address.rs
CHANGED
|
@@ -65,11 +65,10 @@ pub mod va {
|
|
| 65 |
// Re-exported from audio modules
|
| 66 |
pub use crate::audio::dssound::DS_SOUND_VTABLE;
|
| 67 |
pub use crate::audio::music::{
|
| 68 |
-
MUSIC_CONSTRUCTOR, MUSIC_DESTRUCTOR, MUSIC_PLAY_TRACK, MUSIC_VOLUME_DB_TABLE,
|
| 69 |
-
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
STREAMING_AUDIO_TIMER_CALLBACK,
|
| 73 |
};
|
| 74 |
pub use crate::display::base::DISPLAY_BASE_VTABLE;
|
| 75 |
pub use crate::display::dd_display::DD_DISPLAY_VTABLE;
|
|
|
|
| 65 |
// Re-exported from audio modules
|
| 66 |
pub use crate::audio::dssound::DS_SOUND_VTABLE;
|
| 67 |
pub use crate::audio::music::{
|
| 68 |
+
MUSIC_CONSTRUCTOR, MUSIC_DESTRUCTOR, MUSIC_PLAY_TRACK, MUSIC_VOLUME_DB_TABLE, MUSIC_VTABLE,
|
| 69 |
+
STREAMING_AUDIO_FILL_AND_START, STREAMING_AUDIO_INIT, STREAMING_AUDIO_INIT_PLAYBACK,
|
| 70 |
+
STREAMING_AUDIO_OPEN, STREAMING_AUDIO_OPEN_WAV, STREAMING_AUDIO_READ_CHUNK,
|
| 71 |
+
STREAMING_AUDIO_RESET, STREAMING_AUDIO_STOP, STREAMING_AUDIO_TIMER_CALLBACK,
|
|
|
|
| 72 |
};
|
| 73 |
pub use crate::display::base::DISPLAY_BASE_VTABLE;
|
| 74 |
pub use crate::display::dd_display::DD_DISPLAY_VTABLE;
|
crates/openwa-core/src/audio/music.rs
CHANGED
|
@@ -212,19 +212,19 @@ pub struct MusicVtable {
|
|
| 212 |
/// Track ID to WAV filename mapping (from PlayTrack switch at 0x58BD20).
|
| 213 |
/// Track IDs 1-13 map to these filenames.
|
| 214 |
pub const MUSIC_TRACKS: [&str; 13] = [
|
| 215 |
-
"ingame-01-generic.wav",
|
| 216 |
-
"ingame-02-cavern.wav",
|
| 217 |
-
"ingame-03-jungle.wav",
|
| 218 |
-
"ingame-04-battlezone.wav",
|
| 219 |
-
"ingame-05-forest.wav",
|
| 220 |
"ingame-06-weird-alien-plan.wav", // 6
|
| 221 |
-
"ingame-07-outerspace.wav",
|
| 222 |
-
"ingame-08-desert.wav",
|
| 223 |
-
"ingame-09-hell.wav",
|
| 224 |
-
"ingame-10-mech-workshop.wav",
|
| 225 |
-
"ingame-11-rain&surf.wav",
|
| 226 |
-
"suddendeath2-loop.wav",
|
| 227 |
-
"suddendeath1-loop.wav",
|
| 228 |
];
|
| 229 |
|
| 230 |
/// Streaming audio flags.
|
|
@@ -250,12 +250,11 @@ pub mod streaming_flags {
|
|
| 250 |
/// Copied from WA.exe .rdata at 0x6AF960.
|
| 251 |
/// Index 0 = -10000 cB (silence), index 64 = 0 cB (full volume).
|
| 252 |
const MUSIC_VOLUME_DB: [i32; 65] = [
|
| 253 |
-
-10000, -6644, -5644, -5059, -4644, -4322, -4059, -3837, -3644, -3473, -3322,
|
| 254 |
-
-
|
| 255 |
-
-
|
| 256 |
-
-
|
| 257 |
-
-
|
| 258 |
-
-862, -837, -811, -787, -762, -737, -714, -690, -667, 0,
|
| 259 |
];
|
| 260 |
|
| 261 |
// ============================================================
|
|
@@ -265,9 +264,7 @@ const MUSIC_VOLUME_DB: [i32; 65] = [
|
|
| 265 |
use std::io::{Read, Seek, SeekFrom};
|
| 266 |
use std::sync::atomic::{AtomicU32, Ordering};
|
| 267 |
|
| 268 |
-
use windows::Win32::Media::Audio::DirectSound::{
|
| 269 |
-
IDirectSound, IDirectSoundBuffer, DSBUFFERDESC,
|
| 270 |
-
};
|
| 271 |
use windows::Win32::Media::Audio::{WAVEFORMATEX, WAVE_FORMAT_PCM};
|
| 272 |
|
| 273 |
/// Global pointer to the active StreamingAudio for the timer callback.
|
|
@@ -294,7 +291,11 @@ impl StreamingAudio {
|
|
| 294 |
pub fn init(&mut self) {
|
| 295 |
// Zero everything except keep the struct's memory layout intact
|
| 296 |
unsafe {
|
| 297 |
-
core::ptr::write_bytes(
|
|
|
|
|
|
|
|
|
|
|
|
|
| 298 |
}
|
| 299 |
}
|
| 300 |
|
|
@@ -303,12 +304,7 @@ impl StreamingAudio {
|
|
| 303 |
/// `flags` is a combination of `streaming_flags` constants.
|
| 304 |
/// `path` is the absolute path to the WAV file.
|
| 305 |
/// `ds` is the IDirectSound instance for buffer creation.
|
| 306 |
-
pub unsafe fn open(
|
| 307 |
-
&mut self,
|
| 308 |
-
path: &str,
|
| 309 |
-
flags: u32,
|
| 310 |
-
ds: Ptr32,
|
| 311 |
-
) -> bool {
|
| 312 |
// If already initialized, stop first
|
| 313 |
if self.is_initialized != 0 {
|
| 314 |
self.stop();
|
|
@@ -380,7 +376,8 @@ impl StreamingAudio {
|
|
| 380 |
Ok(r) => r,
|
| 381 |
Err(e) => {
|
| 382 |
let _ = crate::log::log_line(&format!(
|
| 383 |
-
"[Music] init_playback: failed to open \"{}\": {}",
|
|
|
|
| 384 |
));
|
| 385 |
return false;
|
| 386 |
}
|
|
@@ -423,8 +420,8 @@ impl StreamingAudio {
|
|
| 423 |
// Compute buffer size matching original float arithmetic (constant at 0x679760 = 1000.0):
|
| 424 |
// per_tick = round(timer_delay_ms * avg_bytes_per_sec / 1000.0)
|
| 425 |
// ds_buffer_size = per_tick * buffer_segments
|
| 426 |
-
let per_tick =
|
| 427 |
-
.round() as u32;
|
| 428 |
let buffer_bytes = per_tick * self.buffer_segments;
|
| 429 |
self.ds_buffer_size = buffer_bytes;
|
| 430 |
|
|
@@ -522,9 +519,10 @@ impl StreamingAudio {
|
|
| 522 |
}
|
| 523 |
|
| 524 |
// Read from WAV file into buffer
|
| 525 |
-
let bytes_read = self.read_file_data(
|
| 526 |
-
|
| 527 |
-
|
|
|
|
| 528 |
|
| 529 |
// Zero-fill remainder if we didn't fill the whole buffer
|
| 530 |
if (bytes_read as u32) < len1 {
|
|
@@ -597,7 +595,6 @@ impl StreamingAudio {
|
|
| 597 |
self.bytes_played_snapshot = 0;
|
| 598 |
}
|
| 599 |
|
| 600 |
-
|
| 601 |
/// Close the WAV file handle.
|
| 602 |
unsafe fn close_file(&mut self) {
|
| 603 |
if self.file_handle != 0 {
|
|
@@ -754,11 +751,7 @@ impl StreamingAudio {
|
|
| 754 |
}
|
| 755 |
} else {
|
| 756 |
// End of file: zero-fill remainder
|
| 757 |
-
core::ptr::write_bytes(
|
| 758 |
-
(ptr1 as *mut u8).add(read),
|
| 759 |
-
0,
|
| 760 |
-
len1 as usize - read,
|
| 761 |
-
);
|
| 762 |
total_written += len1;
|
| 763 |
}
|
| 764 |
} else {
|
|
@@ -786,11 +779,7 @@ impl StreamingAudio {
|
|
| 786 |
);
|
| 787 |
}
|
| 788 |
} else {
|
| 789 |
-
core::ptr::write_bytes(
|
| 790 |
-
(ptr2 as *mut u8).add(read),
|
| 791 |
-
0,
|
| 792 |
-
len2 as usize - read,
|
| 793 |
-
);
|
| 794 |
total_written += len2;
|
| 795 |
}
|
| 796 |
} else {
|
|
@@ -850,11 +839,7 @@ impl Music {
|
|
| 850 |
///
|
| 851 |
/// `ds` is the IDirectSound instance (from DSSound).
|
| 852 |
/// `base_path` is the music directory path (e.g. "DATA\\Music").
|
| 853 |
-
pub unsafe fn init(
|
| 854 |
-
this: *mut Music,
|
| 855 |
-
ds: Ptr32,
|
| 856 |
-
base_path: &str,
|
| 857 |
-
) {
|
| 858 |
// Zero the streaming sub-object
|
| 859 |
(*this).streaming.init();
|
| 860 |
|
|
@@ -898,7 +883,9 @@ impl Music {
|
|
| 898 |
flags |= streaming_flags::LOOP;
|
| 899 |
}
|
| 900 |
|
| 901 |
-
let _ = (*this)
|
|
|
|
|
|
|
| 902 |
}
|
| 903 |
|
| 904 |
/// Start a specific music track (looping). Port of vtable[1] at 0x58BE70.
|
|
@@ -938,8 +925,7 @@ impl Music {
|
|
| 938 |
if (*this).streaming.is_playing() {
|
| 939 |
return;
|
| 940 |
}
|
| 941 |
-
(*this).current_track_index =
|
| 942 |
-
((*this).current_track_index + 1) % (*this).playlist_count;
|
| 943 |
let track_id = (*this).playlist[(*this).current_track_index as usize];
|
| 944 |
Music::play_track(this, track_id, false);
|
| 945 |
}
|
|
|
|
| 212 |
/// Track ID to WAV filename mapping (from PlayTrack switch at 0x58BD20).
|
| 213 |
/// Track IDs 1-13 map to these filenames.
|
| 214 |
pub const MUSIC_TRACKS: [&str; 13] = [
|
| 215 |
+
"ingame-01-generic.wav", // 1
|
| 216 |
+
"ingame-02-cavern.wav", // 2
|
| 217 |
+
"ingame-03-jungle.wav", // 3
|
| 218 |
+
"ingame-04-battlezone.wav", // 4
|
| 219 |
+
"ingame-05-forest.wav", // 5
|
| 220 |
"ingame-06-weird-alien-plan.wav", // 6
|
| 221 |
+
"ingame-07-outerspace.wav", // 7
|
| 222 |
+
"ingame-08-desert.wav", // 8
|
| 223 |
+
"ingame-09-hell.wav", // 9
|
| 224 |
+
"ingame-10-mech-workshop.wav", // 10
|
| 225 |
+
"ingame-11-rain&surf.wav", // 11
|
| 226 |
+
"suddendeath2-loop.wav", // 12
|
| 227 |
+
"suddendeath1-loop.wav", // 13
|
| 228 |
];
|
| 229 |
|
| 230 |
/// Streaming audio flags.
|
|
|
|
| 250 |
/// Copied from WA.exe .rdata at 0x6AF960.
|
| 251 |
/// Index 0 = -10000 cB (silence), index 64 = 0 cB (full volume).
|
| 252 |
const MUSIC_VOLUME_DB: [i32; 65] = [
|
| 253 |
+
-10000, -6644, -5644, -5059, -4644, -4322, -4059, -3837, -3644, -3473, -3322, -3185, -3059,
|
| 254 |
+
-2943, -2837, -2737, -2644, -2557, -2474, -2396, -2322, -2251, -2184, -2119, -2059, -2000,
|
| 255 |
+
-1943, -1889, -1837, -1787, -1737, -1690, -1644, -1600, -1557, -1515, -1474, -1434, -1396,
|
| 256 |
+
-1358, -1322, -1286, -1251, -1217, -1184, -1151, -1119, -1088, -1059, -1028, -1000, -971, -943,
|
| 257 |
+
-915, -889, -862, -837, -811, -787, -762, -737, -714, -690, -667, 0,
|
|
|
|
| 258 |
];
|
| 259 |
|
| 260 |
// ============================================================
|
|
|
|
| 264 |
use std::io::{Read, Seek, SeekFrom};
|
| 265 |
use std::sync::atomic::{AtomicU32, Ordering};
|
| 266 |
|
| 267 |
+
use windows::Win32::Media::Audio::DirectSound::{IDirectSound, IDirectSoundBuffer, DSBUFFERDESC};
|
|
|
|
|
|
|
| 268 |
use windows::Win32::Media::Audio::{WAVEFORMATEX, WAVE_FORMAT_PCM};
|
| 269 |
|
| 270 |
/// Global pointer to the active StreamingAudio for the timer callback.
|
|
|
|
| 291 |
pub fn init(&mut self) {
|
| 292 |
// Zero everything except keep the struct's memory layout intact
|
| 293 |
unsafe {
|
| 294 |
+
core::ptr::write_bytes(
|
| 295 |
+
self as *mut Self as *mut u8,
|
| 296 |
+
0,
|
| 297 |
+
core::mem::size_of::<Self>(),
|
| 298 |
+
);
|
| 299 |
}
|
| 300 |
}
|
| 301 |
|
|
|
|
| 304 |
/// `flags` is a combination of `streaming_flags` constants.
|
| 305 |
/// `path` is the absolute path to the WAV file.
|
| 306 |
/// `ds` is the IDirectSound instance for buffer creation.
|
| 307 |
+
pub unsafe fn open(&mut self, path: &str, flags: u32, ds: Ptr32) -> bool {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 308 |
// If already initialized, stop first
|
| 309 |
if self.is_initialized != 0 {
|
| 310 |
self.stop();
|
|
|
|
| 376 |
Ok(r) => r,
|
| 377 |
Err(e) => {
|
| 378 |
let _ = crate::log::log_line(&format!(
|
| 379 |
+
"[Music] init_playback: failed to open \"{}\": {}",
|
| 380 |
+
path_str, e
|
| 381 |
));
|
| 382 |
return false;
|
| 383 |
}
|
|
|
|
| 420 |
// Compute buffer size matching original float arithmetic (constant at 0x679760 = 1000.0):
|
| 421 |
// per_tick = round(timer_delay_ms * avg_bytes_per_sec / 1000.0)
|
| 422 |
// ds_buffer_size = per_tick * buffer_segments
|
| 423 |
+
let per_tick =
|
| 424 |
+
(self.timer_delay_ms as f64 * avg_bytes_per_sec as f64 / 1000.0).round() as u32;
|
| 425 |
let buffer_bytes = per_tick * self.buffer_segments;
|
| 426 |
self.ds_buffer_size = buffer_bytes;
|
| 427 |
|
|
|
|
| 519 |
}
|
| 520 |
|
| 521 |
// Read from WAV file into buffer
|
| 522 |
+
let bytes_read = self.read_file_data(core::slice::from_raw_parts_mut(
|
| 523 |
+
ptr1 as *mut u8,
|
| 524 |
+
len1 as usize,
|
| 525 |
+
));
|
| 526 |
|
| 527 |
// Zero-fill remainder if we didn't fill the whole buffer
|
| 528 |
if (bytes_read as u32) < len1 {
|
|
|
|
| 595 |
self.bytes_played_snapshot = 0;
|
| 596 |
}
|
| 597 |
|
|
|
|
| 598 |
/// Close the WAV file handle.
|
| 599 |
unsafe fn close_file(&mut self) {
|
| 600 |
if self.file_handle != 0 {
|
|
|
|
| 751 |
}
|
| 752 |
} else {
|
| 753 |
// End of file: zero-fill remainder
|
| 754 |
+
core::ptr::write_bytes((ptr1 as *mut u8).add(read), 0, len1 as usize - read);
|
|
|
|
|
|
|
|
|
|
|
|
|
| 755 |
total_written += len1;
|
| 756 |
}
|
| 757 |
} else {
|
|
|
|
| 779 |
);
|
| 780 |
}
|
| 781 |
} else {
|
| 782 |
+
core::ptr::write_bytes((ptr2 as *mut u8).add(read), 0, len2 as usize - read);
|
|
|
|
|
|
|
|
|
|
|
|
|
| 783 |
total_written += len2;
|
| 784 |
}
|
| 785 |
} else {
|
|
|
|
| 839 |
///
|
| 840 |
/// `ds` is the IDirectSound instance (from DSSound).
|
| 841 |
/// `base_path` is the music directory path (e.g. "DATA\\Music").
|
| 842 |
+
pub unsafe fn init(this: *mut Music, ds: Ptr32, base_path: &str) {
|
|
|
|
|
|
|
|
|
|
|
|
|
| 843 |
// Zero the streaming sub-object
|
| 844 |
(*this).streaming.init();
|
| 845 |
|
|
|
|
| 883 |
flags |= streaming_flags::LOOP;
|
| 884 |
}
|
| 885 |
|
| 886 |
+
let _ = (*this)
|
| 887 |
+
.streaming
|
| 888 |
+
.open(&full_path, flags, (*this).direct_sound);
|
| 889 |
}
|
| 890 |
|
| 891 |
/// Start a specific music track (looping). Port of vtable[1] at 0x58BE70.
|
|
|
|
| 925 |
if (*this).streaming.is_playing() {
|
| 926 |
return;
|
| 927 |
}
|
| 928 |
+
(*this).current_track_index = ((*this).current_track_index + 1) % (*this).playlist_count;
|
|
|
|
| 929 |
let track_id = (*this).playlist[(*this).current_track_index as usize];
|
| 930 |
Music::play_track(this, track_id, false);
|
| 931 |
}
|
crates/openwa-core/src/audio/sound_id.rs
CHANGED
|
@@ -36,4 +36,3 @@ impl SoundId {
|
|
| 36 |
Self(self.0 & 0xFFFE_FFFF)
|
| 37 |
}
|
| 38 |
}
|
| 39 |
-
|
|
|
|
| 36 |
Self(self.0 & 0xFFFE_FFFF)
|
| 37 |
}
|
| 38 |
}
|
|
|
crates/openwa-core/src/audio/speech_ops.rs
CHANGED
|
@@ -36,55 +36,55 @@ const MAX_PATH: usize = 260;
|
|
| 36 |
/// Used for fanfare WAV file paths (e.g. "user\Fanfare\Finland.wav").
|
| 37 |
/// Note: "Leichtenstein" is WA's original misspelling β must match for file lookup.
|
| 38 |
const TEAM_CONFIG_NAMES: [&str; 49] = [
|
| 39 |
-
"UK",
|
| 40 |
-
"Argentina",
|
| 41 |
-
"Australia",
|
| 42 |
-
"Austria",
|
| 43 |
-
"Belgium",
|
| 44 |
-
"Brazil",
|
| 45 |
-
"Canada",
|
| 46 |
-
"Croatia",
|
| 47 |
-
"Simple",
|
| 48 |
-
"Cyprus",
|
| 49 |
-
"Simple",
|
| 50 |
-
"Denmark",
|
| 51 |
-
"Finland",
|
| 52 |
-
"France",
|
| 53 |
-
"Simple",
|
| 54 |
-
"Germany",
|
| 55 |
-
"Greece",
|
| 56 |
-
"Simple",
|
| 57 |
-
"Hungary",
|
| 58 |
-
"Iceland",
|
| 59 |
-
"India",
|
| 60 |
-
"Simple",
|
| 61 |
-
"Psycho Laugh",
|
| 62 |
-
"Psycho Laugh",
|
| 63 |
-
"Ireland",
|
| 64 |
-
"Israel",
|
| 65 |
-
"Italy",
|
| 66 |
-
"Japan",
|
| 67 |
-
"Leichtenstein",
|
| 68 |
-
"Luxembourg",
|
| 69 |
-
"Simple",
|
| 70 |
-
"Malta",
|
| 71 |
-
"Mexico",
|
| 72 |
-
"Morocco",
|
| 73 |
-
"Netherlands",
|
| 74 |
-
"New Zealand",
|
| 75 |
-
"Norway",
|
| 76 |
-
"Poland",
|
| 77 |
-
"Portugal",
|
| 78 |
-
"Simple",
|
| 79 |
-
"Romania",
|
| 80 |
-
"Russia",
|
| 81 |
-
"Singapore",
|
| 82 |
-
"South Africa",
|
| 83 |
-
"Spain",
|
| 84 |
-
"Sweden",
|
| 85 |
-
"Switzerland",
|
| 86 |
-
"Turkey",
|
| 87 |
-
"USA",
|
| 88 |
];
|
| 89 |
|
| 90 |
/// Look up a team config name by team_type (1-49). Returns "Simple" for out-of-range.
|
|
@@ -291,7 +291,8 @@ pub unsafe fn load_speech_wav(
|
|
| 291 |
}
|
| 292 |
|
| 293 |
let slot_idx = count as u32 + SpeechSlotTable::BUFFER_OFFSET;
|
| 294 |
-
let result =
|
|
|
|
| 295 |
|
| 296 |
if result != 0 {
|
| 297 |
slot_table.set(team_index as usize, line_id, slot_idx);
|
|
|
|
| 36 |
/// Used for fanfare WAV file paths (e.g. "user\Fanfare\Finland.wav").
|
| 37 |
/// Note: "Leichtenstein" is WA's original misspelling β must match for file lookup.
|
| 38 |
const TEAM_CONFIG_NAMES: [&str; 49] = [
|
| 39 |
+
"UK", // 0
|
| 40 |
+
"Argentina", // 1
|
| 41 |
+
"Australia", // 2
|
| 42 |
+
"Austria", // 3
|
| 43 |
+
"Belgium", // 4
|
| 44 |
+
"Brazil", // 5
|
| 45 |
+
"Canada", // 6
|
| 46 |
+
"Croatia", // 7
|
| 47 |
+
"Simple", // 8
|
| 48 |
+
"Cyprus", // 9
|
| 49 |
+
"Simple", // 10
|
| 50 |
+
"Denmark", // 11
|
| 51 |
+
"Finland", // 12
|
| 52 |
+
"France", // 13
|
| 53 |
+
"Simple", // 14
|
| 54 |
+
"Germany", // 15
|
| 55 |
+
"Greece", // 16
|
| 56 |
+
"Simple", // 17
|
| 57 |
+
"Hungary", // 18
|
| 58 |
+
"Iceland", // 19
|
| 59 |
+
"India", // 20
|
| 60 |
+
"Simple", // 21
|
| 61 |
+
"Psycho Laugh", // 22
|
| 62 |
+
"Psycho Laugh", // 23
|
| 63 |
+
"Ireland", // 24
|
| 64 |
+
"Israel", // 25
|
| 65 |
+
"Italy", // 26
|
| 66 |
+
"Japan", // 27
|
| 67 |
+
"Leichtenstein", // 28
|
| 68 |
+
"Luxembourg", // 29
|
| 69 |
+
"Simple", // 30
|
| 70 |
+
"Malta", // 31
|
| 71 |
+
"Mexico", // 32
|
| 72 |
+
"Morocco", // 33
|
| 73 |
+
"Netherlands", // 34
|
| 74 |
+
"New Zealand", // 35
|
| 75 |
+
"Norway", // 36
|
| 76 |
+
"Poland", // 37
|
| 77 |
+
"Portugal", // 38
|
| 78 |
+
"Simple", // 39
|
| 79 |
+
"Romania", // 40
|
| 80 |
+
"Russia", // 41
|
| 81 |
+
"Singapore", // 42
|
| 82 |
+
"South Africa", // 43
|
| 83 |
+
"Spain", // 44
|
| 84 |
+
"Sweden", // 45
|
| 85 |
+
"Switzerland", // 46
|
| 86 |
+
"Turkey", // 47
|
| 87 |
+
"USA", // 48
|
| 88 |
];
|
| 89 |
|
| 90 |
/// Look up a team config name by team_type (1-49). Returns "Simple" for out-of-range.
|
|
|
|
| 291 |
}
|
| 292 |
|
| 293 |
let slot_idx = count as u32 + SpeechSlotTable::BUFFER_OFFSET;
|
| 294 |
+
let result =
|
| 295 |
+
crate::audio::dssound::load_wav(wrapper.sound, slot_idx as i32, full_path as *const u8);
|
| 296 |
|
| 297 |
if result != 0 {
|
| 298 |
slot_table.set(team_index as usize, line_id, slot_idx);
|
crates/openwa-core/src/lib.rs
CHANGED
|
@@ -43,10 +43,10 @@ pub mod log;
|
|
| 43 |
pub mod mem;
|
| 44 |
pub mod rebase;
|
| 45 |
pub mod registry;
|
|
|
|
| 46 |
pub mod snapshot;
|
| 47 |
pub mod task;
|
| 48 |
pub mod vtable;
|
| 49 |
pub mod wa;
|
| 50 |
-
pub mod rng;
|
| 51 |
pub mod wa_alloc;
|
| 52 |
pub mod wa_call;
|
|
|
|
| 43 |
pub mod mem;
|
| 44 |
pub mod rebase;
|
| 45 |
pub mod registry;
|
| 46 |
+
pub mod rng;
|
| 47 |
pub mod snapshot;
|
| 48 |
pub mod task;
|
| 49 |
pub mod vtable;
|
| 50 |
pub mod wa;
|
|
|
|
| 51 |
pub mod wa_alloc;
|
| 52 |
pub mod wa_call;
|
crates/openwa-core/src/task/cloud.rs
CHANGED
|
@@ -254,4 +254,3 @@ impl CTaskCloud {
|
|
| 254 |
}
|
| 255 |
}
|
| 256 |
}
|
| 257 |
-
|
|
|
|
| 254 |
}
|
| 255 |
}
|
| 256 |
}
|
|
|
crates/openwa-launcher/src/main.rs
CHANGED
|
@@ -294,4 +294,3 @@ fn path_to_cstring(p: &Path) -> Result<CString, String> {
|
|
| 294 |
)
|
| 295 |
.map_err(|e| format!("path contains nul byte: {e}"))
|
| 296 |
}
|
| 297 |
-
|
|
|
|
| 294 |
)
|
| 295 |
.map_err(|e| format!("path contains nul byte: {e}"))
|
| 296 |
}
|
|
|
crates/openwa-test-runner/src/main.rs
CHANGED
|
@@ -24,7 +24,6 @@ const TIMEOUT_SECS: u64 = 120;
|
|
| 24 |
const REPLAYS_DIR: &str = "testdata/replays";
|
| 25 |
const RUNS_DIR: &str = "testdata/runs";
|
| 26 |
|
| 27 |
-
|
| 28 |
// βββ Types ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 29 |
|
| 30 |
struct TestCase {
|
|
@@ -698,9 +697,7 @@ fn parse_headful_args(argv: &[String]) -> HeadfulArgs {
|
|
| 698 |
"--timeout" | "-t" => {
|
| 699 |
i += 1;
|
| 700 |
if i < argv.len() {
|
| 701 |
-
args.timeout_secs = argv[i]
|
| 702 |
-
.parse()
|
| 703 |
-
.unwrap_or(DEFAULT_HEADFUL_TIMEOUT_SECS);
|
| 704 |
}
|
| 705 |
}
|
| 706 |
s if !s.starts_with('-') && args.filter_or_replay.is_none() => {
|
|
|
|
| 24 |
const REPLAYS_DIR: &str = "testdata/replays";
|
| 25 |
const RUNS_DIR: &str = "testdata/runs";
|
| 26 |
|
|
|
|
| 27 |
// βββ Types ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 28 |
|
| 29 |
struct TestCase {
|
|
|
|
| 697 |
"--timeout" | "-t" => {
|
| 698 |
i += 1;
|
| 699 |
if i < argv.len() {
|
| 700 |
+
args.timeout_secs = argv[i].parse().unwrap_or(DEFAULT_HEADFUL_TIMEOUT_SECS);
|
|
|
|
|
|
|
| 701 |
}
|
| 702 |
}
|
| 703 |
s if !s.starts_with('-') && args.filter_or_replay.is_none() => {
|
crates/openwa-wormkit/src/replacements/speech.rs
CHANGED
|
@@ -16,8 +16,8 @@
|
|
| 16 |
use std::ffi::{c_char, CStr};
|
| 17 |
|
| 18 |
use openwa_core::address::va;
|
| 19 |
-
use openwa_core::audio::{speech_ops, wav_player};
|
| 20 |
use openwa_core::audio::wav_player::WavPlayer;
|
|
|
|
| 21 |
use openwa_core::engine::DDGameWrapper;
|
| 22 |
use openwa_core::rebase::rb;
|
| 23 |
|
|
|
|
| 16 |
use std::ffi::{c_char, CStr};
|
| 17 |
|
| 18 |
use openwa_core::address::va;
|
|
|
|
| 19 |
use openwa_core::audio::wav_player::WavPlayer;
|
| 20 |
+
use openwa_core::audio::{speech_ops, wav_player};
|
| 21 |
use openwa_core::engine::DDGameWrapper;
|
| 22 |
use openwa_core::rebase::rb;
|
| 23 |
|