Files
Sylpheed/crates/sylpheed-formats/examples/blend_prediction_splash.rs
sylph-decoder bbd85e9202 re: T8aD +0x04 bit 0x02 predicts the MEASURED blend, 35/35 -- and a prediction to test it
REFUTED.md kills this claim: 'T8aD +0x04 bit 0x02 selects an additive blend ->
mine, and refuted. Blending those sprites additively worsens every measure
against the capture.' That refutation rests entirely on our renderer, which the
corpus's own rule calls a hypothesis under test. The blend is now measured off
the GPU, so the claim can be tested against the oracle.

35 elements over three screens, every label an RB_BLENDCONTROL0 value read from
the command stream: 16 bit-set and additive, 19 bit-clear and alpha-over, zero
false positives, zero false negatives.

The control that makes it a decode rather than a coincidence: of every bit of
the first 12 header words, EXACTLY ONE separates those 35 elements without
error. Nothing ties with it. A perfect partition on a small sample is worthless
if half the header partitions equally well, which is the mistake +0x08 = 0x8050
was.

And the pair no confound survives: ptbtn00 = 0x0110, ptbtn00f = 0x0112 -- the
PRESS (A) plate and its own highlight, same screen, differing in exactly this
bit, drawn alpha-over and additive respectively.

Committed alongside is a PREDICTION for GP_OPTIONS, written before the capture
that tests it: a different archive, a different element set, and a MIXED
prediction -- po_menu_eff01/02/03 additive, 592 elements alpha-over. Falsified
if those three draw alpha-over or anything else draws additive. The developer
splash was considered first and rejected as a test: both its elements predict
alpha-over, so it can fail but cannot discriminate.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
2026-08-31 07:06:07 +00:00

47 lines
2.4 KiB
Rust

//! A PREDICTION, written before the capture that tests it.
//!
//! `blend_vs_t8ad_bit` finds that `T8aD +0x04` bit `0x02` separates additive from
//! alpha-over on all 35 elements whose blend has been measured off the GPU, and
//! that no other bit of the 48-byte header does. That is a fit to three screens.
//!
//! The developer splash (`GP_TITLE` entries 10 and 13) has **never been captured**
//! and is one of the five screens the port ships. This prints what the bit says
//! its elements should be, so the capture can falsify it rather than confirm it.
//!
//! Takes an archive and a build list, so the prediction can be written for any
//! screen -- including one in a DIFFERENT pak, which is the sharper test: the
//! splash predicts alpha-over for both its elements and so can only fail, never
//! discriminate, while a screen with a predicted MIX can do both.
//!
//! cargo run -p sylpheed-formats --example blend_prediction_splash
//! cargo run -p sylpheed-formats --example blend_prediction_splash -- GP_OPTIONS 0 1 2
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 args: Vec<String> = std::env::args().skip(1).collect();
let pak = args.iter().find(|a| a.parse::<usize>().is_err())
.cloned().unwrap_or_else(|| "GP_TITLE".to_string());
let ar = PakArchive::open(root.join(format!("dat/{pak}.pak"))).expect("pak");
let builds: Vec<usize> = args.iter().filter_map(|a| a.parse().ok()).collect();
let builds = if builds.is_empty() { (0..ar.entries().len()).collect() } else { builds };
for e in builds {
let Ok(by) = ar.read(&ar.entries()[e]) else { continue };
let Some(b) = ui_layout::parse_build(&by) else { continue };
println!("=== {pak} entry {e} ===");
let mut names: Vec<&String> = b.sprites.keys().collect();
names.sort();
for n in names {
let (off, size) = b.sprites[n];
let s = &by[off..(off + size).min(by.len())];
if s.len() < 8 || &s[0..4] != b"T8aD" { continue }
let w = u32::from_be_bytes([s[4], s[5], s[6], s[7]]);
println!("{n:<26} +0x04 = {w:08X} bit 0x02 {} PREDICT {}",
if w & 2 != 0 { "SET " } else { "clear" },
if w & 2 != 0 { "ADDITIVE" } else { "alpha-over" });
}
println!();
}
}