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.
This commit is contained in:
@@ -190,6 +190,17 @@ impl PakArchive {
|
||||
Ok(Self::from_parts(index, Vec::new())?.entries)
|
||||
}
|
||||
|
||||
/// A raw slice of the concatenated segment data, by absolute offset.
|
||||
///
|
||||
/// Entry windows are **not** wave boundaries in `sound.pak`: a `.slb` wave
|
||||
/// runs to `data_at + declared_size`, which routinely overruns the entry's
|
||||
/// own `comp_size` (see docs/re/structures/slb-data-offset.md). Reading the
|
||||
/// boundary marker therefore needs the flat stream, not the entry slice.
|
||||
/// Returns `None` if the range falls outside the loaded data.
|
||||
pub fn data_at(&self, offset: usize, len: usize) -> Option<&[u8]> {
|
||||
self.data.get(offset..offset.checked_add(len)?)
|
||||
}
|
||||
|
||||
/// All TOC entries, in stored order (ascending `name_hash`).
|
||||
pub fn entries(&self) -> &[PakEntry] {
|
||||
&self.entries
|
||||
|
||||
@@ -219,3 +219,53 @@ fn scan_only_returns_known_offsets() {
|
||||
}
|
||||
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");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user