This repository has been archived on 2026-09-16. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
Syplheed-Reborn/crates/sylpheed-formats/tests/slb_leading_segment_disc.rs
Sylpheed RE agent 0a0a0333dd slb: guard the wave-boundary identity with a test, and expose data_at
A wave runs to data_at + declared_size, and there is seek magic exactly there
whose little-endian packet count at +12 times 2048 equals the declared size --
7620/7620 disc-wide. That is the decoder-independent boundary and the thing that
proves the declared sizes honest, so it should not be able to regress silently.

The boundary routinely lies outside the entry's own comp_size window, so reading
it needs the flat segment stream rather than the entry slice; PakArchive gains a
small data_at(offset, len) accessor for that.

Test walks a bounded slice to stay fast -- 792 banks in this run, all holding.
8 disc tests pass.
2026-08-26 05:33:01 +00:00

272 lines
11 KiB
Rust

//! The `.slb` leading segment — recovered, and scoped.
//!
//! `VOICE_D_453` used to decode to 0.14 s because its line lives in a headerless
//! packet stream *before* the first `RIFF`, and the decoder started at the
//! `RIFF`. The banks that looked fine were the ones whose leading segment is
//! silence. One rule, two outcomes.
use std::path::{Path, PathBuf};
use sylpheed_formats::{slb, PakArchive};
fn disc_root() -> Option<PathBuf> {
if let Ok(p) = std::env::var("SYLPHEED_DISC") {
let p = PathBuf::from(p);
if p.join("dat").is_dir() {
return Some(p);
}
}
let default = Path::new(
"/home/fabi/RE - Project Sylpheed/Project Sylpheed - Arc of Deception (USA, Europe) (En,Ja)",
);
default.join("dat").is_dir().then(|| default.to_path_buf())
}
macro_rules! skip_without_disc {
($root:ident) => {
let Some($root) = disc_root() else {
eprintln!("SKIP: set SYLPHEED_DISC");
return;
};
};
}
fn bank(root: &Path, n: u32) -> Vec<u8> {
let snd = PakArchive::open(root.join("dat/sound.pak")).expect("sound.pak");
let path = format!("eng\\etc\\VOICE_D_{n}.slb");
let entry = snd.find_by_name(&path).expect("bank present");
snd.read(entry).expect("read")
}
/// The boundary is arithmetic and has no tunable: the first `RIFF` sits at
/// exactly `HEADERLESS_DATA_OFFSET + n*XMA1_PACKET` in every resupply bank.
#[test]
fn leading_segment_is_a_whole_number_of_packets() {
skip_without_disc!(root);
for (n, packets) in [(450u32, 8usize), (451, 1), (452, 7), (453, 22), (454, 29)] {
let b = bank(&root, n);
let ri = b.windows(4).position(|w| w == b"RIFF").expect("has a RIFF");
assert!(ri > slb::HEADERLESS_DATA_OFFSET, "VOICE_D_{n}");
let lead = ri - slb::HEADERLESS_DATA_OFFSET;
assert_eq!(lead % slb::XMA1_PACKET, 0, "VOICE_D_{n} not a whole packet count");
assert_eq!(lead / slb::XMA1_PACKET, packets, "VOICE_D_{n} packet count");
}
}
/// The two banks whose line lives in the leading segment now yield it.
#[test]
fn broken_banks_recover_their_line() {
skip_without_disc!(root);
// (bank, sub-waves expected, payload of the leading one)
for (n, waves, lead_len) in [(453u32, 2usize, 45116usize), (454, 2, 59452)] {
let riffs = slb::to_xma_riffs(&bank(&root, n));
assert_eq!(riffs.len(), waves, "VOICE_D_{n} sub-wave count");
assert_eq!(riffs[0].len(), lead_len, "VOICE_D_{n} leading segment");
// It must be the LARGER part: that is the whole point.
assert!(
riffs[0].len() > riffs[1].len() * 5,
"VOICE_D_{n}: leading segment should dominate"
);
}
}
/// `VOICE_D_451`'s leading region is all zeros — the guard must skip it, so the
/// rule cannot prepend silence to a bank that does not need it.
#[test]
fn all_zero_leading_region_is_skipped() {
skip_without_disc!(root);
let b = bank(&root, 451);
let ri = b.windows(4).position(|w| w == b"RIFF").unwrap();
assert!(
b[slb::HEADERLESS_DATA_OFFSET..ri].iter().all(|x| *x == 0),
"expected an all-zero leading region"
);
// Two sub-waves, both from the RIFF section — no synthesised third.
assert_eq!(slb::to_xma_riffs(&b).len(), 2);
}
fn bank_named(root: &Path, path: &str) -> Vec<u8> {
let snd = PakArchive::open(root.join("dat/sound.pak")).expect("sound.pak");
let entry = snd.find_by_name(path).unwrap_or_else(|| panic!("{path} present"));
snd.read(entry).expect("read")
}
/// `HEADERLESS_DATA_OFFSET` is the `<lang>\etc\` case, not the format.
///
/// The leading stream is a whole number of packets ending at the first `RIFF`,
/// so its start is `first_riff % XMA1_PACKET`. Disc-wide that takes four values
/// and only 1392 matches the old constant — assuming it elsewhere starts the
/// decode mid-packet. See docs/re/structures/slb-data-offset.md.
#[test]
fn leading_data_offset_is_derived_not_assumed() {
skip_without_disc!(root);
// (bank, expected derived offset). The `etc` banks must still land on the
// old constant — that is the no-regression half of the test.
for (path, want) in [
("eng\\etc\\VOICE_D_452.slb", 1392usize),
("eng\\etc\\VOICE_D_453.slb", 1392),
("eng\\Voice\\VOICE_TCAF_592.slb", 1468),
("jpn\\Voice\\VOICE_TCAF_592.slb", 1728),
("jpn\\etc\\VOICE_D_452.slb", 1600),
] {
let b = bank_named(&root, path);
let ri = b.windows(4).position(|w| w == b"RIFF").expect("has a RIFF");
let got = slb::leading_data_offset(ri);
assert_eq!(got, want, "{path}: derived offset");
assert_eq!(
(ri - got) % slb::XMA1_PACKET,
0,
"{path}: leading stream is not a whole packet count"
);
assert!(
got == slb::HEADERLESS_DATA_OFFSET || got > slb::HEADERLESS_DATA_OFFSET,
"{path}: offsets below the old constant are unexplained"
);
}
}
/// The banks the old constant mis-decoded now carry a leading sub-wave, and the
/// ones it decoded correctly are untouched.
#[test]
fn derived_offset_recovers_voice_banks_without_regressing_etc() {
skip_without_disc!(root);
for path in ["eng\\Voice\\VOICE_TCAF_592.slb", "jpn\\Voice\\VOICE_TCAF_592.slb"] {
let b = bank_named(&root, path);
let ri = b.windows(4).position(|w| w == b"RIFF").expect("has a RIFF");
// Under the old constant this leading region was not a whole packet
// count, so `to_xma_riffs` emitted no leading sub-wave at all.
assert_ne!(
(ri - slb::HEADERLESS_DATA_OFFSET) % slb::XMA1_PACKET,
0,
"{path}: expected the OLD constant to mis-align here"
);
let riffs = slb::to_xma_riffs(&b);
assert!(
riffs.len() >= 2,
"{path}: expected a leading sub-wave plus at least one RIFF, got {}",
riffs.len()
);
}
// Control: an `etc` bank still produces what it did before.
let b = bank_named(&root, "eng\\etc\\VOICE_D_452.slb");
assert_eq!(slb::leading_data_offset(
b.windows(4).position(|w| w == b"RIFF").unwrap()),
slb::HEADERLESS_DATA_OFFSET);
}
/// The scan agrees with the truth wherever the truth is knowable.
///
/// A bank carrying a `RIFF` has its offset *forced* to `first_riff % 2048`, so
/// those banks are a labelled set for a rule meant to serve the ones without a
/// `RIFF`. Over the whole labelled set the scan is right 99.6 % of the time and
/// its only failures are ties. This test walks a slice of it.
#[test]
fn scan_data_offset_agrees_with_the_riff_derived_answer() {
skip_without_disc!(root);
let snd = PakArchive::open(root.join("dat/sound.pak")).expect("sound.pak");
let mut checked = 0usize;
let mut agreed = 0usize;
for lang in ["eng", "jpn"] {
for (dir, lo, hi) in [("Voice", 1u32, 120u32), ("etc", 1, 120)] {
for n in lo..hi {
let path = format!("{lang}\\{dir}\\VOICE_TCAF_{n:03}.slb");
let Some(entry) = snd.find_by_name(&path) else { continue };
let Ok(b) = snd.read(entry) else { continue };
let Some(ri) = b.windows(4).position(|w| w == b"RIFF") else { continue };
if ri <= slb::HEADERLESS_DATA_OFFSET {
continue;
}
if !b[slb::HEADERLESS_DATA_OFFSET..ri].iter().any(|v| *v != 0) {
continue;
}
checked += 1;
if slb::scan_data_offset(&b) == slb::leading_data_offset(ri) {
agreed += 1;
}
}
}
}
assert!(checked >= 20, "expected a usable labelled set, got {checked}");
// The whole-disc rate is 99.62%; allow a little slack for a small slice.
let rate = agreed as f64 / checked as f64;
assert!(
rate >= 0.95,
"scan agreed on {agreed}/{checked} ({:.1}%), expected >=95%",
rate * 100.0
);
}
/// Every offset the scan can return is one of the four seen on disc.
#[test]
fn scan_only_returns_known_offsets() {
skip_without_disc!(root);
let snd = PakArchive::open(root.join("dat/sound.pak")).expect("sound.pak");
let mut seen = 0usize;
for n in 1u32..200 {
for path in [
format!("eng\\Voice\\VOICE_ADAN_{n:03}.slb"),
format!("jpn\\Voice\\VOICE_ADAN_{n:03}.slb"),
] {
let Some(entry) = snd.find_by_name(&path) else { continue };
let Ok(b) = snd.read(entry) else { continue };
let got = slb::scan_data_offset(&b);
assert!(
slb::DATA_OFFSET_CANDIDATES.contains(&got),
"{path}: scan returned {got}, not a known offset"
);
seen += 1;
}
}
assert!(seen >= 20, "expected banks to test, saw {seen}");
}
/// A wave's boundary is exact: `seek` magic sits at `data_at + declared_size`.
///
/// Established 2026-08-26 (docs/re/structures/slb-data-offset.md). Every
/// `RIFF`-bearing entry on the disc satisfies it — **7 620/7 620** in the full
/// sweep — and the `seek` chunk's little-endian packet count at `+12` times
/// 2048 equals the declared size. This is the decoder-independent boundary, and
/// it is what proves the declared sizes honest rather than over-stated.
///
/// The test walks a bounded slice so it stays fast; the identity is disc-wide.
#[test]
fn a_waves_declared_size_is_confirmed_by_the_next_seek() {
skip_without_disc!(root);
let snd = PakArchive::open(root.join("dat/sound.pak")).expect("sound.pak");
let mut checked = 0usize;
for n in 1u32..400 {
for path in [
format!("eng\\etc\\VOICE_D_{n}.slb"),
format!("eng\\Voice\\VOICE_TCAF_{n:03}.slb"),
format!("jpn\\Voice\\VOICE_ADAN_{n:03}.slb"),
] {
let Some(entry) = snd.find_by_name(&path) else { continue };
let Ok(b) = snd.read(entry) else { continue };
let Some(ri) = b.windows(4).position(|w| w == b"RIFF") else { continue };
let Some(rel) = b[ri..].windows(4).position(|w| w == b"data") else { continue };
let di = ri + rel;
let Some(sz) = b.get(di + 4..di + 8) else { continue };
let declared = u32::from_le_bytes(sz.try_into().unwrap()) as usize;
// The boundary lies outside this entry's own TOC window whenever the
// declared size overruns it, which is the common case — so read from
// the archive's flat data rather than from the entry slice.
let probe = entry.offset as usize + di + 8 + declared;
let Some(tag) = snd.data_at(probe, 16) else { continue };
assert_eq!(
&tag[0..4],
b"seek",
"{path}: expected `seek` at data_at+declared ({probe})"
);
let packets = u32::from_le_bytes(tag[12..16].try_into().unwrap()) as usize;
assert_eq!(
packets * slb::XMA1_PACKET,
declared,
"{path}: seek packet count x 2048 != declared data size"
);
checked += 1;
}
}
assert!(checked >= 30, "expected banks to check, got {checked}");
eprintln!("wave-boundary identity held for {checked} banks");
}