Play-test finding 4, answered as a mechanism and from the disc, so it generalises instead of describing one boot. ui-splash-draw-pass.md excluded a post-process from GPU state and closed with "that softness is in the texture or in which quads are drawn, not in a pass", leaving the two unseparated. It is both, and they are one fact: each logo ships a second texture that IS the blur -- the same artwork outset by exactly 10 px per side, concentric to <=1.5 px, drawn as its own alpha-over quad. Three results, each with its control: * The capture's eight anonymous quads are NAMED from the disc. Predicting each NDC rect from declared position + decoded sprite size matches all eight bijectively; every match <=0.0061, every runner-up >=0.0272, a 4.5-8.9x margin. That margin is the control -- eight similar boxes would match anything. * REFUTES splash-quad-timeline.txt's "the same three rects scaled slightly larger" (my own earlier wording). The x and y scale factors differ by up to 0.28; a uniform scale cannot do that, a fixed 10-px border can. The conclusion it supported (draw all six quads) stands; the model was wrong, and the wrong model tells a port to scale a sprite. * The T8aD blend bit tested OUT of sample on entries 10/11, which were not in its 35-row fit and are the screens under complaint. Pre-registered additive=false for all eight against 0 additive draws in 1048; held 8/8, with the control still reporting 9 additive on entry 6. Also resolves a REFUTED.md 🟡 <our-reader> in the reader's favour: the prediction is ours and the target is the oracle, so the agreement is evidence about the reader rather than a claim resting on it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Jc4pciRArGHfxGGhEbwp5t
76 lines
3.6 KiB
Rust
76 lines
3.6 KiB
Rust
//! Out-of-sample test of the `T8aD +0x04` blend bit on the **boot splashes**.
|
|
//!
|
|
//! `ui-blend-mode-decoded.md` established the field on 35 elements over three
|
|
//! screens (GP_TITLE entries 2, 4, 5, 6). The two splashes -- entries 10 and 11 --
|
|
//! were NOT in that sample, and they are the screens the 2026-09-01 play-test
|
|
//! says are wrong.
|
|
//!
|
|
//! The oracle for these two screens is `data/splash-draw-pass-census.txt`: over
|
|
//! **1048 draws of frames 4..226**, covering both splashes end to end, the only
|
|
//! blend states submitted are `0x00010001` (the clear) and `0x07010701`
|
|
//! (source-over). Additive, `0x01010101`, appears **zero** times.
|
|
//!
|
|
//! PRE-REGISTERED PREDICTION, written before reading the disc: if the bit is the
|
|
//! blend selector and it generalises off its training screens, then every sprite
|
|
//! in entries 10 and 11 must report `additive = false`. Any `true` is a
|
|
//! discrepancy the field has to answer for.
|
|
//!
|
|
//! cargo run --release -p sylpheed-formats --example splash_blend_check
|
|
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 ar = PakArchive::open(root.join("dat/GP_TITLE.pak")).expect("GP_TITLE");
|
|
|
|
let mut additive = 0usize;
|
|
let mut alpha_over = 0usize;
|
|
let mut no_header = 0usize;
|
|
|
|
for entry in [10usize, 11] {
|
|
let by = ar.read(&ar.entries()[entry]).expect("entry");
|
|
let Some(b) = ui_layout::parse_build(&by) else {
|
|
println!("entry {entry}: not a build");
|
|
continue;
|
|
};
|
|
println!("\n## GP_TITLE entry {entry} -- {} elements, {} sprites",
|
|
b.elements.len(), b.sprites.len());
|
|
|
|
// Every sprite the bundle carries, not only those a top-level element
|
|
// names: a focused variant is reached through `focus_link` and would
|
|
// otherwise be invisible to this check.
|
|
let mut names: Vec<&String> = b.sprites.keys().collect();
|
|
names.sort();
|
|
for n in names {
|
|
match ui_layout::blend_additive_by_name(&b, &by, n) {
|
|
Some(true) => { additive += 1;
|
|
println!(" {n:<26} word04=0x{:08X} ADDITIVE",
|
|
ui_layout::header_word_04_by_name(&b, &by, n).unwrap()); }
|
|
Some(false) => { alpha_over += 1;
|
|
println!(" {n:<26} word04=0x{:08X} alpha-over",
|
|
ui_layout::header_word_04_by_name(&b, &by, n).unwrap()); }
|
|
None => { no_header += 1; println!(" {n:<26} (no T8aD header)"); }
|
|
}
|
|
}
|
|
}
|
|
|
|
println!("\nadditive={additive} alpha-over={alpha_over} no-header={no_header}");
|
|
println!("oracle (splash-draw-pass-census.txt, 1048 draws): additive draws = 0");
|
|
if additive == 0 {
|
|
println!("PREDICTION HELD -- the bit agrees with the capture on both splashes");
|
|
} else {
|
|
println!("PREDICTION FAILED -- {additive} sprite(s) claim additive, \
|
|
the capture submits none");
|
|
}
|
|
|
|
// Control: this harness must be able to REPORT additive, or "additive=0"
|
|
// is a property of the harness and not of the splashes. Entry 6 is a screen
|
|
// the oracle measures as mixed.
|
|
let by6 = ar.read(&ar.entries()[6]).expect("entry 6");
|
|
let b6 = ui_layout::parse_build(&by6).expect("build 6");
|
|
let c_add = b6.sprites.keys()
|
|
.filter(|n| ui_layout::blend_additive_by_name(&b6, &by6, n) == Some(true)).count();
|
|
println!("control -- entry 6 through the SAME code path reports additive={c_add} \
|
|
(must be > 0): {}", if c_add > 0 { "PASS" } else { "FAIL" });
|
|
}
|