sylpheed-port reconciled the population gap exactly and I reproduced it: filtering max_t > 0 gives 1781 records and 92.3 %, their figures precisely. Same numerator, 1643, both ways. My stated explanation was wrong. I said the scan requires a timed keyframe; it does not, because .max() returns Some(0) rather than None for records whose keyframes are all at time 0, so 1530 records where the question has no content stayed in my denominator and counted as failures by construction. The conclusion is untouched -- +0x04 is 0 % under either denominator. Records their diagnosis of why it stayed invisible: the numerator agreed to the unit, so a shared 1643 read as agreement and neither of us looked there. And both halves needed a qualifier neither carried -- 92.3 % is of the records where the question is meaningful, not of nested records. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
69 lines
3.1 KiB
Rust
69 lines
3.1 KiB
Rust
//! Does the `+0x08` falsifier actually identify `+0x08`?
|
|
//!
|
|
//! `ui-record-loop-length.md` (mine) rests on: an animation cannot restart before
|
|
//! its own last pose, so a wrong reading should produce violations, and none exist
|
|
//! in 1 781 records. `sylpheed-port` re-ran it at the neighbouring offsets and
|
|
//! reports the falsifier ACCEPTS `+0x04` too — meaning it does not discriminate,
|
|
//! and the real evidence is the exactness statistic I called a formality.
|
|
//!
|
|
//! This checks that from my own reader before I correct the page.
|
|
//!
|
|
//! cargo run -p sylpheed-formats --example loop_length_offset_discriminates
|
|
use sylpheed_formats::{pak::PakArchive, ui_layout};
|
|
use std::path::PathBuf;
|
|
|
|
fn be32(b: &[u8], o: usize) -> Option<u32> {
|
|
(b.len() >= o + 4).then(|| u32::from_be_bytes([b[o], b[o + 1], b[o + 2], b[o + 3]]))
|
|
}
|
|
|
|
fn main() {
|
|
let root = PathBuf::from(std::env::var("SYLPHEED_DISC").expect("SYLPHEED_DISC"));
|
|
let dat = root.join("dat");
|
|
let mut paks: Vec<_> = std::fs::read_dir(&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();
|
|
// offset -> (records, violations where word < max_t, exact matches)
|
|
let mut stat = [(0usize, 0usize, 0usize); 3];
|
|
let offsets = [0x04usize, 0x08, 0x0c];
|
|
for p in &paks {
|
|
let Ok(ar) = PakArchive::open(p) else { continue };
|
|
for e in ar.entries() {
|
|
let Ok(by) = ar.read(e) else { continue };
|
|
let Some(b) = ui_layout::parse_build(&by) else { continue };
|
|
for (_, (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 };
|
|
let max_t = leaf
|
|
.elements
|
|
.iter()
|
|
.flat_map(|el| el.keyframes.iter().filter_map(|k| k.time))
|
|
.max();
|
|
let Some(max_t) = max_t else { continue };
|
|
// sylpheed-port's reconciliation: max_t == 0 makes "does the word
|
|
// equal the largest keyframe time?" vacuous, and those records were
|
|
// silently in my denominator. Filter them and the counts must meet.
|
|
if std::env::var("MEANINGFUL_ONLY").is_ok() && max_t == 0 { continue }
|
|
for (i, o) in offsets.iter().enumerate() {
|
|
if let Some(w) = be32(rec, *o) {
|
|
stat[i].0 += 1;
|
|
if w < max_t { stat[i].1 += 1 }
|
|
if w == max_t { stat[i].2 += 1 }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
println!("{:>8} {:>9} {:>12} {:>14}", "offset", "records", "violations", "exact == max_t");
|
|
for (i, o) in offsets.iter().enumerate() {
|
|
let (n, v, x) = stat[i];
|
|
println!(" +0x{o:02X} {n:>9} {v:>12} ({:>5.1}%) {x:>8} ({:>5.1}%)",
|
|
100.0 * v as f64 / n.max(1) as f64, 100.0 * x as f64 / n.max(1) as f64);
|
|
}
|
|
}
|