The port measures four elements as rendering too dark against the capture -- ptframe1/2 on the main menu, ptframe3/4 on EXTRAS -- with the shortfall correlating +0.77/+0.80 with the BACKGROUND and only +0.24 with the element's own contribution. That is the signature of a blend that scales what is already there. It asked whether the disc selects one. Three examples, one negative, wider than the one I gave last iteration: * frame_alpha_census -- every T8aD sprite on builds 5 and 6 by alpha. It REFUTES the port's own sharpener: 'neither frame has a single fully-opaque pixel, against ptbase's 99.1 %' is true, and pteff10 (max alpha 130, 100 % partial, no opaque pixel) is measured by the port as NEARLY EXACT. So being wholly semi-transparent is not what makes the frames special. * frame_vs_accurate_words -- all 12 T8aD header words for both screens, plus a per-BIT sweep of +0x04 and +0x08. NO word and NO bit puts the four frames on one side and pteff10 on the other. It also kills my own remaining candidate a second time: +0x08 = 0x8050 is shared with pteff21/22/23 on EXTRAS. * frame_keyframe_unknowns -- the keyframe record's fade, tint, rotation and its two unexplained signed words. unknown_4 and unknown_8 are ZERO on every keyframe of both screens, so they carry nothing here; no frame takes a value of any field that another element does not. Reach: the 60-byte declaration entry, the T8aD header word-wise and bit-wise, and the keyframe record. Four elements, two screens. Not the executable's draw path, which is the next commit. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
47 lines
2.6 KiB
Rust
47 lines
2.6 KiB
Rust
//! The keyframe record's two unexplained words (`+4`, `+8`) and the fade/tint —
|
|
//! do any of them separate the four elements the port measures as rendering too
|
|
//! dark (`ptframe1`/`2`, `ptframe3`/`4`) from the ones it measures as accurate?
|
|
//!
|
|
//! The T8aD header does not: no word and no bit of `+0x04`/`+0x08` puts the four
|
|
//! frames on one side and `pteff10` (max alpha 130, wholly semi-transparent, and
|
|
//! rendered nearly exact) on the other. The keyframe is the other place a
|
|
//! per-element draw mode could live.
|
|
//!
|
|
//! cargo run -p sylpheed-formats --example frame_keyframe_unknowns
|
|
use sylpheed_formats::{pak::PakArchive, ui_layout};
|
|
use std::path::PathBuf;
|
|
|
|
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");
|
|
println!("{:<22} {:>5} {:>3} {:>10} {:>10} {:>8} {:>8} {:>8}",
|
|
"element", "build", "kf", "unknown_4", "unknown_8", "fade", "tint", "rot");
|
|
let mut frame_sets: Vec<(String, i32, i32, u32, u32, i32)> = Vec::new();
|
|
let mut other_sets: Vec<(String, i32, i32, u32, u32, i32)> = Vec::new();
|
|
for build in [5usize, 6] {
|
|
let by = ar.read(&ar.entries()[build]).expect("entry");
|
|
let b = ui_layout::parse_build(&by).expect("build");
|
|
for e in &b.elements {
|
|
for (i, k) in e.keyframes.iter().enumerate() {
|
|
println!("{:<22} {build:>5} {i:>3} {:>10} {:>10} {:08X} {:08X} {:>8}",
|
|
e.name, k.unknown_4, k.unknown_8, k.fade, k.tint, k.rotation_deg);
|
|
let row = (e.name.clone(), k.unknown_4, k.unknown_8, k.fade, k.tint, k.rotation_deg);
|
|
if e.name.contains("frame") { frame_sets.push(row) } else { other_sets.push(row) }
|
|
}
|
|
}
|
|
}
|
|
println!("\nframe keyframes: {} other keyframes: {}", frame_sets.len(), other_sets.len());
|
|
for (label, get) in [
|
|
("unknown_4", 0usize), ("unknown_8", 1), ("fade", 2), ("tint", 3), ("rotation", 4),
|
|
] {
|
|
let val = |r: &(String, i32, i32, u32, u32, i32)| -> i64 {
|
|
match get { 0 => r.1 as i64, 1 => r.2 as i64, 2 => r.3 as i64, 3 => r.4 as i64, _ => r.5 as i64 }
|
|
};
|
|
let fv: std::collections::BTreeSet<i64> = frame_sets.iter().map(val).collect();
|
|
let ov: std::collections::BTreeSet<i64> = other_sets.iter().map(val).collect();
|
|
let only_frames: Vec<&i64> = fv.iter().filter(|v| !ov.contains(v)).collect();
|
|
println!("{label:<10} frames take {:?} others take {} distinct values; frame-only values: {:?}",
|
|
fv, ov.len(), only_frames);
|
|
}
|
|
}
|