This branch predates CI on `main`. `cargo fmt --all` only; no behaviour. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
72 lines
3.0 KiB
Rust
72 lines
3.0 KiB
Rust
//! How do a parent record's alpha ramp and its nested `.rat` leaf's compose?
|
|
//!
|
|
//! The port emits both but will not draw the leaf without knowing the rule --
|
|
//! rightly, since drawing on a guess trades a visible 1.82 % error for an
|
|
//! invisible wrong one. There is an oracle for this: the GPU draw capture
|
|
//! records **vertex colours**, and on the title's `ptloop` draw they are
|
|
//! `C3FFFFFF` and `B6FFFFFF` -- alpha **195** and **182**, not 255. So the game's
|
|
//! composed alpha is observable, and a candidate rule either predicts those two
|
|
//! numbers or does not.
|
|
//!
|
|
//! cargo run -p sylpheed-formats --example leaf_alpha_compose -- <GP_TITLE.pak>
|
|
use sylpheed_formats::{pak, ui_layout};
|
|
|
|
fn alpha_of(kf: &ui_layout::Keyframe) -> u32 {
|
|
// The keyframe block's +0 is an ARGB fade colour; alpha is its high byte.
|
|
kf.fade >> 24
|
|
}
|
|
|
|
fn main() {
|
|
let path = std::env::args().nth(1).expect("usage: <pak>");
|
|
let ar = pak::PakArchive::open(&path).expect("open");
|
|
let e = &ar.entries()[4]; // GP_TITLE entry 4 = the English title
|
|
let bytes = ar.read(e).expect("read");
|
|
let build = ui_layout::parse_build(&bytes).expect("build");
|
|
|
|
for name in ["ptloop01.rat", "ptloop02.rat"] {
|
|
println!("\n=== {name} ===");
|
|
if let Some(el) = build.elements.iter().find(|x| x.name == name) {
|
|
println!(" PARENT keyframes (t, alpha, scale, rot, x,y):");
|
|
for k in &el.keyframes {
|
|
println!(
|
|
" t={:<5} a={:<4} scale=({},{}) rot={:<5} ({},{})",
|
|
k.time.map(|t| t as i64).unwrap_or(-1),
|
|
alpha_of(k),
|
|
k.scale_x,
|
|
k.scale_y,
|
|
k.rotation_deg,
|
|
k.x,
|
|
k.y
|
|
);
|
|
}
|
|
}
|
|
match build.records.get(name) {
|
|
Some(&(off, size)) => {
|
|
let leaf = &bytes[off..off + size];
|
|
match ui_layout::parse_build(leaf) {
|
|
Some(lb) => {
|
|
for le in &lb.elements {
|
|
println!(" LEAF element {:?}:", le.name);
|
|
for k in &le.keyframes {
|
|
println!(
|
|
" t={:<5} a={:<4} scale=({},{}) rot={:<5} ({},{})",
|
|
k.time.map(|t| t as i64).unwrap_or(-1),
|
|
alpha_of(k),
|
|
k.scale_x,
|
|
k.scale_y,
|
|
k.rotation_deg,
|
|
k.x,
|
|
k.y
|
|
);
|
|
}
|
|
}
|
|
}
|
|
None => println!(" leaf did not parse"),
|
|
}
|
|
}
|
|
None => println!(" no leaf record"),
|
|
}
|
|
}
|
|
println!("\nOBSERVED in the draw capture: quad A alpha 195 (0xC3), quad B alpha 182 (0xB6)");
|
|
}
|