use sylpheed_formats::{idxd::IdxdObject, PakArchive}; fn main(){ let disc=std::env::var("SYLPHEED_DISC").unwrap(); let arc=PakArchive::open(format!("{disc}/dat/GP_MAIN_GAME_E.pak")).unwrap(); // 1. All stages: BackGroundID + phases + stage tag (from EnumUnit_SNN) println!("=== STAGES (StageResource 3c9ae32e) ==="); let mut rows=vec![]; for e in arc.entries(){ let Ok(b)=arc.read(e) else{continue}; let Ok(o)=IdxdObject::parse(&b) else{continue}; if o.schema_hash!=0x3c9ae32e {continue;} let t=o.tokens(); let bg=o.get_raw("BackGroundID").unwrap_or("?").to_string(); let stage=t.iter().find_map(|s|s.strip_prefix("EnumUnit_").map(|x|x.trim_end_matches(".tbl").to_string())).unwrap_or("?".into()); let phases=t.iter().filter(|s|s.starts_with("Phase_")).count(); let unitgrp=t.iter().any(|s|s.starts_with("UnitGroup_")); let route=t.iter().any(|s|s.starts_with("Route_")); let formation=t.iter().any(|s|s.starts_with("FormationSet_")); rows.push((stage,bg,phases,unitgrp,route,formation)); } rows.sort(); for (s,bg,p,ug,rt,fm) in &rows{ println!(" {s:8} location={bg:14} phases={p} [squadrons:{} route:{} formations:{}]", if *ug{"Y"}else{"·"},if *rt{"Y"}else{"·"},if *fm{"Y"}else{"·"}); } // 2. Parse objectives table into (stage,phase) -> key counts println!("\n=== OBJECTIVES (033b5b7e) — per stage/phase key groups ==="); for e in arc.entries(){ let Ok(b)=arc.read(e) else{continue}; let Ok(o)=IdxdObject::parse(&b) else{continue}; if o.schema_hash!=0x033b5b7e {continue;} let t=o.tokens(); let mut groups:std::collections::BTreeMap=Default::default(); for tok in t{ if let Some(p)=tok.find("_Objective_").or_else(||tok.find("_Lose_")).or_else(||tok.find("_Hint_")){ let key=&tok[..p]; *groups.entry(key.trim_start_matches(|c:char|!c.is_ascii_alphabetic()).into()).or_default()+=1; } } let stages:std::collections::BTreeSet=groups.keys().filter_map(|k|k.get(..3).map(|s|s.to_string())).collect(); println!(" covers {} stages: {:?}", stages.len(), stages); println!(" sample S01_P1 group counts: {:?}", groups.iter().filter(|(k,_)|k.starts_with("S01_P1")).collect::>()); break; } // 3. Resolve objective TEXT: search all pak entries for the key "S01_P1_Objective_00" as an ID with English text println!("\n=== OBJECTIVE TEXT resolution probe ==="); for e in arc.entries(){ let Ok(b)=arc.read(e) else{continue}; let Ok(o)=IdxdObject::parse(&b) else{continue}; let t=o.tokens(); if let Some(i)=t.iter().position(|s|s=="S01_P1_Objective_00"){ let lo=i.saturating_sub(1); let hi=(i+3).min(t.len()); println!(" schema {:08x}: ...{:?}...", o.schema_hash, &t[lo..hi]); } } }