use sylpheed_formats::{ratc, idxd::IdxdObject, PakArchive}; use std::collections::BTreeMap; fn main(){ let disc=std::env::var("SYLPHEED_DISC").unwrap(); // 1. RATC child-type census across the big RATC paks let mut childtypes:BTreeMap=BTreeMap::new(); let mut ratc_unparsed=0u64; for pk in ["GP_READY_ROOM","GP_MOVIE_THEATER","GP_DIALOG","GP_DEBRIEFING_PILOTLOG","GP_TITLE","GP_BUNK"]{ let Ok(arc)=PakArchive::open(format!("{disc}/dat/{pk}.pak")) else{continue}; for e in arc.entries(){ let Ok(b)=arc.read(e) else{continue}; if !ratc::is_ratc(&b){continue;} match ratc::parse(&b){ Some(kids)=> for k in kids{ let ext=k.name.rsplit('.').next().unwrap_or("?").to_lowercase(); *childtypes.entry(ext).or_default()+=1; }, None=>ratc_unparsed+=1, } } } println!("=== RATC child-type census (big RATC paks) ==="); let mut cv:Vec<_>=childtypes.into_iter().collect(); cv.sort_by_key(|x|std::cmp::Reverse(x.1)); for (e,c) in &cv{ println!(" .{e:8} ×{c}"); } println!(" (RATC bundles that failed to parse: {ratc_unparsed})"); // 2. The 00000002 mystery format (GP_MAIN_GAME_E) let arc=PakArchive::open(format!("{disc}/dat/GP_MAIN_GAME_E.pak")).unwrap(); for e in arc.entries(){ let Ok(b)=arc.read(e) else{continue}; if b.len()>=4 && b[0..4]==[0,0,0,2]{ let hx:String=b[..48.min(b.len())].iter().map(|x|format!("{x:02x}")).collect::>().join(" "); let asc:String=b[..64.min(b.len())].iter().map(|&x|if(0x20..0x7f).contains(&x){x as char}else{'.'}).collect(); println!("\n=== 00000002 format sample ({}B) ===\n{hx}\n{asc}",b.len()); break; } } // 3. Sample the top undecoded IDXD schemas: first tokens (guess semantics) println!("\n=== top undecoded IDXD schemas — sample tokens (semantic hints) ==="); let targets:[u32;6]=[0xb412e6d8,0x026379ab,0x43faa517,0x3c5b0549,0x6ab4825a,0x0426e81d]; for want in targets{ let mut shown=false; for e in arc.entries(){ if shown{break;} let Ok(b)=arc.read(e) else{continue}; if b.len()<12 || &b[0..4]!=b"IDXD"{continue;} let s=u32::from_be_bytes([b[8],b[9],b[10],b[11]]); if s!=want{continue;} if let Ok(o)=IdxdObject::parse(&b){ let t=o.tokens(); let sample:Vec=t.iter().take(14).map(|s|{let s=s.chars().take(18).collect::();s}).collect(); println!(" {want:08x}: {sample:?}"); shown=true; } } if !shown{ println!(" {want:08x}: (parse failed / not found)"); } } }