Finishes #16 in the three places its earlier remedies missed. `tests/`: the last four local `disc_root()` copies now use `tests/common`, and with them goes the one real hardcoded fallback — `ui_keyframe_record_disc.rs` fell back to an absolute path on one machine, which made `unset SYLPHEED_DISC` a no-op there. Control: with the corpus absent that suite now finishes in 0.00s instead of 57.55s, so it skips rather than finding a disc of its own. `examples/`: seventeen examples defaulted to `/disc`, the mount point inside the CI container. Redundant there — `docker/ci/run` sets `SYLPHEED_DISC=/disc` — and wrong everywhere else, where a missing corpus turned into a file-not-found against a path that has never existed on the host. They now name the variable to set, like the other hundred examples already did. `docker/ci/run`: mount `$SYLPHEED_RES3D` and `$SYLPHEED_ISO` alongside the disc. Only the disc was mounted, so an in-container run sat out the res3d and iso suites while looking like a full one — the defect this issue is about, in the runner itself. Measured in the container on this desktop with all three corpora present: 45 suites / 377 passed / 0 failed / 14 ignored, and `sylpheed-corpus-report.txt` now reports PRESENT for all three rather than for the disc alone. Refs #16. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
69 lines
3.0 KiB
Rust
69 lines
3.0 KiB
Rust
//! Do any screens THIS PORT SHIPS carry a record that declares a cycle while all
|
|
//! its poses sit at t = 0?
|
|
//!
|
|
//! The substantive finding from the denominator thread: 1 530 nested records
|
|
//! disc-wide are timed with every pose at t = 0 and still declare a nonzero
|
|
//! `+0x08`. A static record that declares a cycle length is a real thing, not a
|
|
//! counting artefact — so the question for the port is whether it holds one of
|
|
//! those still while the disc says it cycles.
|
|
//!
|
|
//! Scoped to `GP_TITLE`, because that is the archive the port exports.
|
|
use sylpheed_formats::{pak, ratc, ui_layout};
|
|
|
|
fn main() {
|
|
let root =
|
|
std::env::var("SYLPHEED_DISC").expect("set SYLPHEED_DISC to the extracted disc root");
|
|
let ar = pak::PakArchive::open(format!("{root}/dat/GP_TITLE.pak")).expect("GP_TITLE.pak");
|
|
let (mut total, mut hits, mut multipose) = (0usize, 0usize, 0usize);
|
|
for (i, e) in ar.entries().iter().enumerate() {
|
|
let Ok(by) = ar.read(e) else { continue };
|
|
if !ratc::is_ratc(&by) {
|
|
continue;
|
|
}
|
|
let Some(b) = ui_layout::parse_build(&by) else {
|
|
continue;
|
|
};
|
|
for (name, &(o, s)) in &b.records {
|
|
if o + 12 > by.len() || o + s > by.len() || &by[o..o + 4] != b"RATC" {
|
|
continue;
|
|
}
|
|
let Some(lb) = ui_layout::parse_build(&by[o..o + s]) else {
|
|
continue;
|
|
};
|
|
let maxt = lb
|
|
.elements
|
|
.iter()
|
|
.flat_map(|el| el.keyframes.iter().filter_map(|k| k.time))
|
|
.max()
|
|
.unwrap_or(0);
|
|
let len = ui_layout::loop_length_units(&by[o..o + s]).unwrap_or(0);
|
|
total += 1;
|
|
if maxt == 0 && len > 0 {
|
|
hits += 1;
|
|
// A cycle can only produce motion if there is more than one pose
|
|
// to move between. All-at-t=0 with a single keyframe per element
|
|
// is visually inert however it is played.
|
|
let kf: usize = lb.elements.iter().map(|el| el.keyframes.len()).sum();
|
|
let multi = lb
|
|
.elements
|
|
.iter()
|
|
.filter(|el| el.keyframes.len() > 1)
|
|
.count();
|
|
if multi > 0 {
|
|
multipose += 1
|
|
}
|
|
println!(
|
|
" entry {i:>2} {name:<16} {len}-unit cycle, {kf} keyframe(s) \
|
|
across {} element(s), {multi} with >1 pose",
|
|
lb.elements.len()
|
|
);
|
|
}
|
|
}
|
|
}
|
|
println!("\n {total} nested record(s) in GP_TITLE; {hits} declare a cycle while static.");
|
|
println!(" Of those, {multipose} have an element with MORE THAN ONE pose -- the only");
|
|
println!(" ones where looping could differ visibly from holding. A record whose");
|
|
println!(" elements each carry a single pose renders identically either way, so a");
|
|
println!(" declared cycle there is inert rather than a defect.");
|
|
}
|