Project Sylpheed stores its UI/story text in IXUD entries as UTF-16LE, interleaved `text, key` (a prose string immediately followed by the identifier that names it). TextIndex::build(pak) scans a language pak's IXUD entries and indexes every pair — 8457 English keys from GP_MAIN_GAME_E: objectives, hints, lose conditions, character names, and cutscene dialogue. This makes the whole game read in English: the 16-mission campaign (Repel the surprise attack → Shoot down Margras → the Prometheus Driver finale), each mission's briefing, and the named cast (Katana, Raymond, Ellen, Crichton, …) all resolve. API: get / objectives / lose_conditions / hints / character_name. 3 tests. Examples: campaign / dossier print the readable campaign + cast. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
25 lines
1.3 KiB
Rust
25 lines
1.3 KiB
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 mut stages=game_data::load_stages(&pak);
|
||
stages.retain(|s|s.id.starts_with('S') && s.id.len()==3 && s.id[1..].parse::<u32>().map(|n|n<=16).unwrap_or(false));
|
||
stages.sort_by(|a,b|a.id.cmp(&b.id));
|
||
println!("═══ CAMPAIGN (S01–S16) ═══");
|
||
for s in &stages{
|
||
let obj=text.objectives(&s.id,1);
|
||
println!("\n{} · {}", s.id, s.location.as_deref().unwrap_or("?"));
|
||
for o in obj.iter().take(2){ println!(" ▸ {o}"); }
|
||
}
|
||
// roster with real names
|
||
let mut chars=game_data::load_characters(&pak);
|
||
chars.retain(|c|c.faction.as_deref()==Some("TCAF") && c.unique==Some(true) && c.faces.len()>=4);
|
||
println!("\n═══ PRINCIPAL CAST (TCAF, named) ═══");
|
||
for c in &chars{
|
||
let id=c.id.as_deref().unwrap_or("");
|
||
let name=text.character_name(id.trim_start_matches("Character")).or_else(||c.name_key.as_deref().and_then(|k|text.get(k))).unwrap_or("?");
|
||
println!(" {name:12} ({} portraits) [{}]", c.faces.len(), id.trim_start_matches("Character"));
|
||
}
|
||
}
|