Decode the message tables (schema b412e6d8) into dialogue lines: each `Message_NNN` sub-record → a DemoMessage with the speaker, portrait (face), voice-clip token, and caption page text-keys. Fields are found by prefix (Character*/Face*/VOICE_*/id-prefixed pages), so the positional / first-record-defines-schema layout doesn't matter. 10,263 lines parse; ~815 name an explicit speaker (the rest are system / continuation lines — left unattributed rather than guessed). Paired with localization::TextIndex the attributed ones read straight out — e.g. KATANA [VOICE_RHIN_000] "Ellen, get back into formation!". The voice-clip token ties each line to its audio bank, closing the loop with the cutscene-voice work. +1 test; example `dialogue` prints speaker + clip + resolved text. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
14 lines
778 B
Rust
14 lines
778 B
Rust
use sylpheed_formats::{game_data, localization::TextIndex, PakArchive};
|
|
fn main(){
|
|
let disc=std::env::var("SYLPHEED_DISC").unwrap();
|
|
let pak=PakArchive::open(format!("{disc}/dat/GP_MAIN_GAME_E.pak")).unwrap();
|
|
let text=TextIndex::build(&pak);
|
|
let msgs=game_data::load_demo_messages(&pak);
|
|
println!("{} dialogue lines total\n", msgs.len());
|
|
for m in msgs.iter().filter(|m|m.character.is_some()&&!m.page_keys.is_empty()).take(8){
|
|
let who=m.character.as_deref().unwrap_or("?").trim_start_matches("Character");
|
|
let line:String=m.page_keys.iter().filter_map(|k|text.get(k)).collect::<Vec<_>>().join(" ");
|
|
println!(" {who:10} [{}] “{}”", m.voice_clip.as_deref().unwrap_or("-"), line.chars().take(64).collect::<String>());
|
|
}
|
|
}
|