//! Do `GP_TITLE` records that declare a cycle while sitting at t = 0 actually move? //! //! A static record still declares a cycle length, so a nonzero `+0x08` against a //! largest keyframe time of 0 is a real disagreement. `sylpheed-port` turned that //! into a check on the screens they ship: 20 such records in GP_TITLE, and none //! with any element carrying more than one pose — so the declared cycle is //! visually inert and holding them still is correct. //! //! This re-derives it. If any record had a multi-pose element, the port would be //! holding something the disc says animates. //! //! cargo run -p sylpheed-formats --example static_cycle_inert use std::path::PathBuf; use sylpheed_formats::{pak::PakArchive, ui_layout}; fn main() { let root = PathBuf::from(std::env::var("SYLPHEED_DISC").expect("SYLPHEED_DISC")); let ar = PakArchive::open(root.join("dat/GP_TITLE.pak")).expect("GP_TITLE"); let (mut total, mut static_cycle, mut multipose) = (0usize, 0usize, 0usize); for e in ar.entries() { let Ok(by) = ar.read(e) else { continue }; let Some(b) = ui_layout::parse_build(&by) else { continue; }; for (name, (off, size)) in &b.records { let rec = &by[*off..(*off + *size).min(by.len())]; if rec.len() < 0x10 || &rec[0..4] != b"RATC" { continue; } let Some(leaf) = ui_layout::parse_build(rec) else { continue; }; total += 1; let times: Vec = leaf .elements .iter() .flat_map(|el| el.keyframes.iter().filter_map(|k| k.time)) .collect(); let cycle = ui_layout::loop_length_units(rec).unwrap_or(0); if times.is_empty() || times.iter().max() != Some(&0) || cycle == 0 { continue; } static_cycle += 1; let worst = leaf .elements .iter() .map(|el| el.keyframes.len()) .max() .unwrap_or(0); if worst > 1 { multipose += 1; println!( " 🔴 {name} declares {cycle} units and has an element with {worst} poses" ); } else if name.starts_with("ptbtn1") { println!(" {name:16} declares {cycle} units, max poses/element {worst}"); } } } println!("\nnested records in GP_TITLE : {total}"); println!("declaring a cycle with every pose at t == 0 : {static_cycle}"); println!("...of those, any element with MORE THAN ONE pose : {multipose}"); }