build_caption_text generalises the key parser from MSG_DEMO_* to all eight
families. The shapes are uniform and each family is 100% consistent with its
own: seven use MSG_<FAM>_<id>_<page>_<line>, and VOICE alone inserts a family
letter before the id.
ids lines
build_demo_text 134 537
build_caption_text 3721 8074
The DEMO family comes out identical through both readers -- 537 lines either
way -- which is the control that generalising changed nothing that already
worked. Pinned by tests/caption_families_disc.rs, along with VOICE ids keeping
their family letter.
But this does NOT close the gap, and the write-up says so: 8074 against the
44579 text-bearing fields the record-level scan counts is about 18%.
The reason is the same lesson this session already learned once.
build_caption_text pairs a value with the key that happens to follow it in the
raw UTF-16 token stream -- the adjacency heuristic that was wrong for IDXD and
is wrong here for the same reason. ixud.rs has no record/field reader at all.
The IXUD record table IS decoded and verified disc-wide (1104/1104 objects,
628165/628165 fields reproducing their key) and was simply never wired into
the crate.
Next step recorded: give ixud.rs an IdxdObject-shaped reader and read captions
as fields rather than adjacent tokens. The decode exists; only the plumbing is
missing.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PMRJjbxLqZtsb5Vb7KunPE
39 lines
1.4 KiB
Rust
39 lines
1.4 KiB
Rust
//! How many caption lines does `build_caption_text` actually recover?
|
|
use std::collections::BTreeMap;
|
|
use sylpheed_formats::{movie_subtitle, PakArchive};
|
|
|
|
fn main() {
|
|
let disc = std::env::var("SYLPHEED_DISC").expect("set SYLPHEED_DISC");
|
|
let pak = PakArchive::open(format!("{disc}/dat/GP_MAIN_GAME_E.pak")).expect("pak");
|
|
let all = movie_subtitle::build_caption_text(&pak);
|
|
let demo = movie_subtitle::build_demo_text(&pak);
|
|
|
|
let mut per: BTreeMap<&str, (usize, usize)> = BTreeMap::new();
|
|
for (id, lines) in &all {
|
|
let fam = id.split('_').next().unwrap();
|
|
let e = per.entry(fam).or_default();
|
|
e.0 += 1;
|
|
e.1 += lines.len();
|
|
}
|
|
println!("{:<8} {:>8} {:>9}", "family", "ids", "lines");
|
|
let (mut ids, mut lines) = (0, 0);
|
|
for (fam, (i, l)) in &per {
|
|
println!("{fam:<8} {i:>8} {l:>9}");
|
|
ids += i;
|
|
lines += l;
|
|
}
|
|
println!("{:<8} {:>8} {:>9}", "TOTAL", ids, lines);
|
|
println!(
|
|
"\nbuild_demo_text alone: {} ids, {} lines",
|
|
demo.len(),
|
|
demo.values().map(|v| v.len()).sum::<usize>()
|
|
);
|
|
// The DEMO family must come out identical either way — that is the control.
|
|
let demo_via_all: usize = all
|
|
.iter()
|
|
.filter(|(k, _)| k.starts_with("DEMO_"))
|
|
.map(|(_, v)| v.len())
|
|
.sum();
|
|
println!("DEMO via build_caption_text: {demo_via_all} lines");
|
|
}
|