This branch predates CI on `main`. `cargo fmt --all` only; no behaviour. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
114 lines
4.8 KiB
Rust
114 lines
4.8 KiB
Rust
//! Every record reachable from an element — leaf **and** `focus_link` — plus a
|
|
//! disc-wide census of how many elements have more than one.
|
|
//!
|
|
//! ⚠️ WHY. I claimed `ptbtn00f`'s peak alpha of 80 was undeclared, having read
|
|
//! `ptbtn00.rat` (the leaf, flat 255) and stopped. The pulse is in
|
|
//! `ptbtn00f.rat`, the focus record. `focus_link` was already parsed and
|
|
//! `ui_layout.rs` already documented it: the format was known and I did not
|
|
//! consult it. An absence claim is only as good as its enumeration, so this
|
|
//! enumerates rather than asking the reader to remember.
|
|
//!
|
|
//! cargo run -p sylpheed-formats --example element_records -- GP_TITLE ptbtn00
|
|
//! cargo run -p sylpheed-formats --example element_records -- --census
|
|
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 argv: Vec<String> = std::env::args().skip(1).collect();
|
|
|
|
if argv.iter().any(|a| a == "--census") {
|
|
let (mut els, mut linked, mut screens_with) = (0usize, 0usize, 0usize);
|
|
let mut paks: Vec<_> = std::fs::read_dir(root.join("dat"))
|
|
.expect("dat")
|
|
.filter_map(|e| e.ok())
|
|
.map(|e| e.path())
|
|
.filter(|p| p.extension().map(|x| x == "pak").unwrap_or(false))
|
|
.collect();
|
|
paks.sort();
|
|
for p in &paks {
|
|
let Ok(ar) = PakArchive::open(p) else {
|
|
continue;
|
|
};
|
|
for ent in ar.entries() {
|
|
let Ok(by) = ar.read(ent) else { continue };
|
|
let Some(b) = ui_layout::parse_build(&by) else {
|
|
continue;
|
|
};
|
|
let n = b.elements.iter().filter(|e| e.focus_link.is_some()).count();
|
|
els += b.elements.len();
|
|
linked += n;
|
|
if n > 0 {
|
|
screens_with += 1
|
|
}
|
|
}
|
|
}
|
|
println!("elements disc-wide : {els}");
|
|
println!(
|
|
"with a focus_link record : {linked} ({:.1}%)",
|
|
100.0 * linked as f64 / els as f64
|
|
);
|
|
println!("builds containing at least 1: {screens_with}");
|
|
println!("\nEach of those carries a SECOND record whose keyframes are invisible");
|
|
println!("to anyone who looks up the leaf by name and stops.");
|
|
return;
|
|
}
|
|
|
|
let pak = argv.first().cloned().unwrap_or_else(|| "GP_TITLE".into());
|
|
let want = argv.get(1).cloned();
|
|
let ar = PakArchive::open(root.join(format!("dat/{pak}.pak"))).expect("pak");
|
|
for (i, ent) in ar.entries().iter().enumerate() {
|
|
let Ok(by) = ar.read(ent) else { continue };
|
|
let Some(b) = ui_layout::parse_build(&by) else {
|
|
continue;
|
|
};
|
|
for el in &b.elements {
|
|
if let Some(w) = &want {
|
|
if !el.name.starts_with(w.as_str()) {
|
|
continue;
|
|
}
|
|
}
|
|
if el.focus_link.is_none() && want.is_none() {
|
|
continue;
|
|
}
|
|
println!("entry {i}: {}", el.name);
|
|
let stem = el.name.trim_end_matches(".rat");
|
|
for (tag, rec) in [
|
|
("leaf", format!("{stem}.rat")),
|
|
("focus", el.focus_link.clone().unwrap_or_default()),
|
|
] {
|
|
if rec.is_empty() {
|
|
continue;
|
|
}
|
|
match b.records.get(rec.as_str()) {
|
|
Some(&(lo, ls)) => {
|
|
let bytes = &by[lo..(lo + ls).min(by.len())];
|
|
let loop_u = ui_layout::loop_length_units(bytes);
|
|
let kf: Vec<String> = ui_layout::parse_build(bytes)
|
|
.map(|lb| {
|
|
lb.elements
|
|
.iter()
|
|
.map(|e| {
|
|
format!(
|
|
"{} [{} keys, peak a{}]",
|
|
e.name,
|
|
e.keyframes.len(),
|
|
e.keyframes
|
|
.iter()
|
|
.map(|k| k.fade >> 24)
|
|
.max()
|
|
.unwrap_or(0)
|
|
)
|
|
})
|
|
.collect()
|
|
})
|
|
.unwrap_or_default();
|
|
println!(" {tag:<6} {rec:<20} loop {:?} {}", loop_u, kf.join(", "));
|
|
}
|
|
None => println!(" {tag:<6} {rec:<20} (no such record)"),
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|