re: the primitive colour census -- and it refutes 38 of my own 80 forced verdicts
A disc-wide census of the ARGB that keyless elements carry. Every full-screen *eff00* PRIMITIVE is pure black at its various alphas (ff000000, 7f000000, 40000000, b2000000, cc000000, d4000000, 00000000). Black at alpha a over content is exactly an alpha-over dim or fade, and an additive black quad would be a no-op nobody would author -- so this narrows the open blend question a long way. The only non-black primitive on the disc is pbafc.prm, RGB 00e8e0 cyan at alphas up to ff, and it is 844x600, NOT full-screen, so it sits outside forced_backdrop's geometry guard. It is now the sole additive candidate. The census also refutes my own argument for nearly half its verdicts. Of the 80 forced-first instances only 42 are .prm; 38 are .tbm carrying fade ffffffff. A SOLID white quad at alpha 255 painted first would make the screen white, and no screen is white -- so a .tbm is a white modulation on a texture, and element alpha does not establish its coverage. That is the .t32 error one file extension further out. I guarded that with el.sprite.is_some(), which fixed the symptom and not the cause: an element's alpha is not its texture's opacity, and only an untextured primitive makes the two the same fact. So 42 verdicts stay decoded and 38 drop to inferred -- still almost certainly right, since all are named *base*, all are full-screen, and pfbase.tbm's first position is measured in the running game, but that is a name-and-role argument which this page elsewhere calls the weaker kind. The code is deliberately unchanged. Restricting forced_backdrop to .prm would send eleven screens' backgrounds back to u32::MAX -- last -- which is the blank-screen bug the rule was written to fix. Downgrading the status is honest; reverting the position would be wrong. The 42/38 split is pinned by a test so anyone tightening the rule sees what it costs. Separately, on the port's black_hold_units ask: four more no-input boots yielded one usable log, which armed late and missed the publisher splash, so the sample is still two runs spanning 3 and 4 frames. Their 6.5-9.2 range stands. And a reason it may not be resolvable this way: the draw log DROPS frame numbers -- in the 3-frame run, frames 121 and 124 are absent entirely, so "frames with no sprite" and "span of frame numbers" are different quantities. Their statistical correction is taken: at n=3 the sample SD (3.893) is the estimator, not the population SD (3.179), making my run 1.88 sigma from the corpus mean rather than 2.31. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QsEPXWVaEpyfudtR6re1Pd
This commit is contained in:
37
crates/sylpheed-formats/examples/prm_colour_census.rs
Normal file
37
crates/sylpheed-formats/examples/prm_colour_census.rs
Normal file
@@ -0,0 +1,37 @@
|
||||
//! What COLOUR is a primitive, and does any of them only make sense additively?
|
||||
//!
|
||||
//! `ui-prm-primitives.md` leaves blend mode open, and `forced_backdrop` assumes
|
||||
//! straight alpha-over. A quad whose ARGB would tint the whole screen a colour no
|
||||
//! screen shows is evidence against alpha-over for that quad.
|
||||
use sylpheed_formats::{pak, ratc, ui_layout};
|
||||
use std::collections::BTreeMap;
|
||||
fn main(){
|
||||
let root=std::env::var("SYLPHEED_DISC").unwrap_or_else(|_|"/disc".into());
|
||||
let mut paks:Vec<_>=std::fs::read_dir(format!("{root}/dat")).expect("dat/")
|
||||
.flatten().map(|e|e.path())
|
||||
.filter(|p|p.extension().and_then(|s|s.to_str())==Some("pak")).collect();
|
||||
paks.sort();
|
||||
let mut m:BTreeMap<String,BTreeMap<String,usize>>=BTreeMap::new();
|
||||
for p in &paks {
|
||||
let Ok(ar)=pak::PakArchive::open(p) else { continue };
|
||||
for e in ar.entries() {
|
||||
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 el in &b.elements {
|
||||
if el.sprite.is_some() { continue }
|
||||
for k in &el.keyframes {
|
||||
*m.entry(el.name.clone()).or_default()
|
||||
.entry(format!("{:08x}", k.fade)).or_default()+=1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
println!("{:>26} fade ARGB values (count)", "keyless element");
|
||||
for (n,v) in &m {
|
||||
let tot:usize=v.values().sum();
|
||||
if tot<4 { continue }
|
||||
let s:Vec<String>=v.iter().map(|(k,c)|format!("{k}x{c}")).collect();
|
||||
println!(" {n:>24} {}", s.join(" "));
|
||||
}
|
||||
}
|
||||
@@ -147,7 +147,7 @@ fn forced_backdrops_are_full_screen_and_plentiful() {
|
||||
.filter(|p| p.extension().and_then(|s| s.to_str()) == Some("pak"))
|
||||
.collect();
|
||||
paks.sort();
|
||||
let mut forced = 0usize;
|
||||
let (mut forced, mut prm, mut tbm) = (0usize, 0usize, 0usize);
|
||||
for p in &paks {
|
||||
let Ok(ar) = PakArchive::open(p) else { continue };
|
||||
for e in ar.entries() {
|
||||
@@ -161,6 +161,8 @@ fn forced_backdrops_are_full_screen_and_plentiful() {
|
||||
continue;
|
||||
}
|
||||
forced += 1;
|
||||
if element.name.ends_with(".prm") { prm += 1 }
|
||||
else if element.name.ends_with(".tbm") { tbm += 1 }
|
||||
// 🔴 Untextured only. This assertion caught the rule's real
|
||||
// limit: applied to `.t32` sprites it claimed 22 of them must
|
||||
// sort first, against their own layer keys — a sprite's element
|
||||
@@ -181,4 +183,15 @@ fn forced_backdrops_are_full_screen_and_plentiful() {
|
||||
}
|
||||
assert!(forced > 50, "expected a real population, got {forced}");
|
||||
eprintln!("{forced} keyless primitives have their position forced to first");
|
||||
|
||||
// 🔴 Pin the split, so anyone tightening this rule sees what it would cost.
|
||||
// Only the `.prm` half is DECODED: a solid colour quad's fade IS its pixel, so
|
||||
// opacity and coverage are the same fact. Every `.tbm` in the set carries fade
|
||||
// `ffffffff` — a white SOLID quad painted first would make the screen white, so
|
||||
// they are textured, and element alpha does not establish their coverage.
|
||||
// Their verdicts are kept because restricting to `.prm` would send eleven
|
||||
// screens' backgrounds back to last, which is the bug this rule fixed.
|
||||
assert!(prm >= 40 && tbm >= 30,
|
||||
"expected roughly 42 .prm / 38 .tbm forced instances, got {prm} / {tbm} — \
|
||||
if this moved, re-read the self-refutation section of ui-forced-backdrop.md");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user