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
This commit is contained in:
46
crates/sylpheed-formats/examples/blend_prediction_splash.rs
Normal file
46
crates/sylpheed-formats/examples/blend_prediction_splash.rs
Normal file
@@ -0,0 +1,46 @@
|
||||
//! 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!();
|
||||
}
|
||||
}
|
||||
152
crates/sylpheed-formats/examples/blend_vs_t8ad_bit.rs
Normal file
152
crates/sylpheed-formats/examples/blend_vs_t8ad_bit.rs
Normal file
@@ -0,0 +1,152 @@
|
||||
//! Does `T8aD +0x04` bit `0x02` predict the blend the GAME uses?
|
||||
//!
|
||||
//! ⚠️ **`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** — it is a claim about our renderer, and the corpus's own rule
|
||||
//! says so. Since it was written, the blend has been measured off the GPU per
|
||||
//! draw on three screens (`structures/ui-blend-mode-measured.md`), so the claim
|
||||
//! can now be tested against the oracle instead of against a render.
|
||||
//!
|
||||
//! The labels below are **not** from a render. Every one is a
|
||||
//! `RB_BLENDCONTROL0` value read out of the guest command stream and attributed
|
||||
//! to an element by quad size:
|
||||
//! `data/ui-blend-mode-measured.txt`, `data/ui-blend-title-and-replication.txt`,
|
||||
//! `data/ui-blend-extras-complete.txt`.
|
||||
//!
|
||||
//! cargo run -p sylpheed-formats --example blend_vs_t8ad_bit
|
||||
use sylpheed_formats::{pak::PakArchive, ui_layout};
|
||||
use std::collections::BTreeMap;
|
||||
use std::path::PathBuf;
|
||||
|
||||
/// (build entry, sprite, measured additive?) — the oracle's verdicts, verbatim.
|
||||
const MEASURED: &[(usize, &str, bool)] = &[
|
||||
// --- GP_TITLE entry 4 + 2, the live title -------------------------------
|
||||
(4, "ptbase2.t32", false),
|
||||
(4, "ptlogo1.t32", false),
|
||||
(4, "ptlogo2.t32", false),
|
||||
(4, "ptlogo_tm.t32", false),
|
||||
(4, "ptcopyright.t32", false),
|
||||
(4, "ptlogo_back2.t32", false),
|
||||
(4, "ptlogo_back2eff.t32", false),
|
||||
(2, "ptbtn00.t32", false),
|
||||
(2, "ptbtn00f.t32", true),
|
||||
// --- entry 5, the main menu ---------------------------------------------
|
||||
(5, "ptbase.t32", false),
|
||||
(5, "ptmsg.t32", false),
|
||||
(5, "ptbtn01f.t32", false),
|
||||
(5, "ptbtneff01.t32", false),
|
||||
(5, "pteff10.t32", true),
|
||||
(5, "pteff12.t32", true),
|
||||
(5, "ptframe1.t32", true),
|
||||
(5, "ptframe2.t32", true),
|
||||
(5, "pteff03.t32", true), // the rotated sweep strips, via ptloop01/02
|
||||
(5, "pteff03a.t32", true),
|
||||
// --- entry 6, EXTRAS ------------------------------------------------------
|
||||
(6, "ptbase.t32", false),
|
||||
(6, "ptmsg2.t32", false),
|
||||
(6, "pttitle.t32", false),
|
||||
(6, "ptbtn11f.t32", false),
|
||||
(6, "ptbtn12.t32", false),
|
||||
(6, "ptbtn13.t32", false),
|
||||
(6, "ptbtneff02.t32", false),
|
||||
(6, "pteff10.t32", true),
|
||||
(6, "pteff20.t32", true),
|
||||
(6, "pteff21.t32", true),
|
||||
(6, "pteff22.t32", true),
|
||||
(6, "pteff23.t32", true),
|
||||
(6, "ptframe3.t32", true),
|
||||
(6, "ptframe4.t32", true),
|
||||
(6, "pteff03.t32", true),
|
||||
(6, "pteff03a.t32", true),
|
||||
];
|
||||
|
||||
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 hdr: BTreeMap<(usize, String), u32> = BTreeMap::new();
|
||||
for e in [2usize, 4, 5, 6] {
|
||||
let by = ar.read(&ar.entries()[e]).expect("entry");
|
||||
let b = ui_layout::parse_build(&by).expect("build");
|
||||
for (n, &(off, size)) in &b.sprites {
|
||||
let s = &by[off..(off + size).min(by.len())];
|
||||
if s.len() < 8 || &s[0..4] != b"T8aD" { continue }
|
||||
hdr.insert((e, n.clone()), u32::from_be_bytes([s[4], s[5], s[6], s[7]]));
|
||||
}
|
||||
}
|
||||
println!("{:<10} {:<22} {:<10} {:>10} {}", "entry", "sprite", "+0x04", "bit 0x02", "measured blend");
|
||||
let (mut tp, mut tn, mut fp, mut fnn, mut missing) = (0, 0, 0, 0, 0);
|
||||
for &(e, n, additive) in MEASURED {
|
||||
let Some(&w) = hdr.get(&(e, n.to_string())) else {
|
||||
println!("{e:<10} {n:<22} {:<10} {:>10} {}", "MISSING", "-",
|
||||
if additive { "ADDITIVE" } else { "alpha-over" });
|
||||
missing += 1;
|
||||
continue;
|
||||
};
|
||||
let bit = w & 0x02 != 0;
|
||||
match (bit, additive) {
|
||||
(true, true) => tp += 1,
|
||||
(false, false) => tn += 1,
|
||||
(true, false) => fp += 1,
|
||||
(false, true) => fnn += 1,
|
||||
}
|
||||
println!("{e:<10} {n:<22} {:08X} {:>10} {}{}", w, bit,
|
||||
if additive { "ADDITIVE" } else { "alpha-over" },
|
||||
if bit == additive { "" } else { " <== DISAGREES" });
|
||||
}
|
||||
println!("\nbit set & additive {tp}");
|
||||
println!("bit clear & alpha-over {tn}");
|
||||
println!("bit set & alpha-over {fp} <- false positives");
|
||||
println!("bit clear & additive {fnn} <- false negatives");
|
||||
println!("sprite not found {missing}");
|
||||
println!("\n{}", if fp == 0 && fnn == 0 && missing == 0 {
|
||||
"PERFECT PARTITION on every element whose blend was measured."
|
||||
} else {
|
||||
"THE BIT DOES NOT PREDICT THE MEASURED BLEND."
|
||||
});
|
||||
|
||||
// ── THE CONTROL THAT MATTERS ────────────────────────────────────────────
|
||||
// A perfect partition is worthless if half the header partitions equally
|
||||
// well: then the sample is too small to single out a field, and picking
|
||||
// `+0x04` bit 0x02 out of the tie is the same mistake as picking `+0x08`
|
||||
// 0x8050 was. So: how many OTHER bits of the first 12 header words separate
|
||||
// the same 35 elements without error?
|
||||
let mut rivals: Vec<String> = Vec::new();
|
||||
let mut words: BTreeMap<(usize, String), Vec<u32>> = BTreeMap::new();
|
||||
for e in [2usize, 4, 5, 6] {
|
||||
let by = ar.read(&ar.entries()[e]).expect("entry");
|
||||
let b = ui_layout::parse_build(&by).expect("build");
|
||||
for (n, &(off, size)) in &b.sprites {
|
||||
let s = &by[off..(off + size).min(by.len())];
|
||||
if s.len() < 48 || &s[0..4] != b"T8aD" { continue }
|
||||
words.insert((e, n.clone()), (0..12)
|
||||
.map(|k| u32::from_be_bytes([s[k*4], s[k*4+1], s[k*4+2], s[k*4+3]]))
|
||||
.collect());
|
||||
}
|
||||
}
|
||||
for w in 0..12 {
|
||||
for bit in 0..32 {
|
||||
let mut ok = true;
|
||||
let mut set_seen = false;
|
||||
let mut clear_seen = false;
|
||||
for &(e, n, additive) in MEASURED {
|
||||
let Some(v) = words.get(&(e, n.to_string())) else { ok = false; break };
|
||||
let on = (v[w] >> bit) & 1 == 1;
|
||||
if on { set_seen = true } else { clear_seen = true }
|
||||
if on != additive { ok = false; break }
|
||||
}
|
||||
// A constant bit trivially "agrees" with nothing; require both sides.
|
||||
if ok && set_seen && clear_seen {
|
||||
rivals.push(format!("+0x{:02X} bit {bit} (0x{:X})", w * 4, 1u32 << bit));
|
||||
}
|
||||
}
|
||||
}
|
||||
println!("\nRIVAL FIELDS — other bits of the first 12 header words that separate");
|
||||
println!("the same 35 elements with zero errors: {}", rivals.len());
|
||||
for r in &rivals { println!(" {r}"); }
|
||||
if rivals.len() == 1 {
|
||||
println!(" -> the sample singles out ONE field. Nothing else in the header does it.");
|
||||
} else {
|
||||
println!(" -> the sample does NOT single out a field; {} candidates tie.", rivals.len());
|
||||
}
|
||||
}
|
||||
@@ -38,15 +38,18 @@ fn census(name: &str, img: &t8ad::T8adImage) {
|
||||
|
||||
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 argv: Vec<String> = std::env::args().skip(1).collect();
|
||||
let pak = argv.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");
|
||||
// Builds default to the two the port ships and can be overridden, so the
|
||||
// same census serves the title (4) and the `PRESS (A)` plate (2).
|
||||
let args: Vec<usize> = std::env::args().skip(1).filter_map(|a| a.parse().ok()).collect();
|
||||
let args: Vec<usize> = argv.iter().filter_map(|a| a.parse().ok()).collect();
|
||||
let builds: Vec<usize> = if args.is_empty() { vec![5, 6] } else { args };
|
||||
for build in builds {
|
||||
let by = ar.read(&ar.entries()[build]).expect("entry");
|
||||
let b = ui_layout::parse_build(&by).expect("build");
|
||||
println!("=== GP_TITLE build {build} ===");
|
||||
let Ok(by) = ar.read(&ar.entries()[build]) else { continue };
|
||||
let Some(b) = ui_layout::parse_build(&by) else { continue };
|
||||
println!("=== {pak} build {build} ===");
|
||||
let mut names: Vec<&String> = b.sprites.keys().collect();
|
||||
names.sort();
|
||||
for n in names {
|
||||
|
||||
@@ -11,12 +11,15 @@ 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");
|
||||
let builds: Vec<usize> = std::env::args().skip(1).filter_map(|a| a.parse().ok()).collect();
|
||||
let argv: Vec<String> = std::env::args().skip(1).collect();
|
||||
let pak = argv.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> = argv.iter().filter_map(|a| a.parse().ok()).collect();
|
||||
for build in if builds.is_empty() { vec![5usize, 6] } else { builds } {
|
||||
let by = ar.read(&ar.entries()[build]).expect("entry");
|
||||
let b = ui_layout::parse_build(&by).expect("build");
|
||||
println!("=== GP_TITLE entry {build} ===");
|
||||
let Ok(by) = ar.read(&ar.entries()[build]) else { continue };
|
||||
let Some(b) = ui_layout::parse_build(&by) else { continue };
|
||||
println!("=== {pak} entry {build} ===");
|
||||
println!("{:<22} {:>10} {:>7} {:>7} {:>12} {}", "element", "pivot(w,h)", "sx%", "sy%", "drawn px", "at 1x/2x of pivot*2");
|
||||
for e in &b.elements {
|
||||
let k = match e.rest() { Some(k) => k, None => continue };
|
||||
|
||||
36
docs/re/data/blend-bit-prediction-gp-options.txt
Normal file
36
docs/re/data/blend-bit-prediction-gp-options.txt
Normal file
@@ -0,0 +1,36 @@
|
||||
# PREDICTION, written and committed BEFORE the capture that tests it. 2026-08-31.
|
||||
#
|
||||
# blend_vs_t8ad_bit finds 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 it. That is a fit to three screens of one
|
||||
# archive.
|
||||
#
|
||||
# GP_OPTIONS has never been captured, is a different archive with an entirely
|
||||
# different element set, and is a screen the port ships. Its prediction is MIXED,
|
||||
# which is what makes it a test rather than a formality: 3 elements ADDITIVE,
|
||||
# 595 alpha-over.
|
||||
#
|
||||
# FALSIFIED IF: po_menu_eff01/02/03 draw alpha-over, or any other GP_OPTIONS
|
||||
# element 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.)
|
||||
|
||||
=== the ADDITIVE predictions in GP_OPTIONS ===
|
||||
po_menu_eff01.t32 +0x04 = 00008832 bit 0x02 SET PREDICT ADDITIVE
|
||||
po_menu_eff02.t32 +0x04 = 00008832 bit 0x02 SET PREDICT ADDITIVE
|
||||
po_menu_eff03.t32 +0x04 = 00008832 bit 0x02 SET PREDICT ADDITIVE
|
||||
|
||||
=== counts ===
|
||||
elements predicted ADDITIVE: 6
|
||||
elements predicted alpha-over: 592
|
||||
|
||||
=== the developer splash, for completeness (both alpha-over) ===
|
||||
=== GP_TITLE entry 10 ===
|
||||
palogo_sqex.t32 +0x04 = 00008830 bit 0x02 clear PREDICT alpha-over
|
||||
palogo_sqex_eff.t32 +0x04 = 00008830 bit 0x02 clear PREDICT alpha-over
|
||||
|
||||
=== GP_TITLE entry 13 ===
|
||||
palogo_sqex.t32 +0x04 = 00008830 bit 0x02 clear PREDICT alpha-over
|
||||
palogo_sqex_eff.t32 +0x04 = 00008830 bit 0x02 clear PREDICT alpha-over
|
||||
|
||||
67
docs/re/data/blend-bit-vs-oracle.txt
Normal file
67
docs/re/data/blend-bit-vs-oracle.txt
Normal file
@@ -0,0 +1,67 @@
|
||||
# T8aD +0x04 bit 0x02 vs the blend the GAME uses -- 35 elements, 3 screens.
|
||||
# 2026-08-31. cargo run -p sylpheed-formats --example blend_vs_t8ad_bit
|
||||
#
|
||||
# ⚠️ 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 is a claim about OUR RENDERER, which the
|
||||
# corpus's own rule says is a hypothesis under test. The blend has since been
|
||||
# measured off the GPU, so the claim can be tested against the oracle instead.
|
||||
#
|
||||
# Every label below is an RB_BLENDCONTROL0 value read out of the guest command
|
||||
# stream and attributed to an element by quad size -- see
|
||||
# data/ui-blend-mode-measured.txt, data/ui-blend-title-and-replication.txt and
|
||||
# data/ui-blend-extras-complete.txt.
|
||||
#
|
||||
# The pair that no confound survives: ptbtn00 = 0x0110 and ptbtn00f = 0x0112, the
|
||||
# PRESS (A) plate and its own highlight, same screen, same draw order, differing
|
||||
# in exactly this bit -- and the game draws one alpha-over and the other additive.
|
||||
|
||||
entry sprite +0x04 bit 0x02 measured blend
|
||||
4 ptbase2.t32 00008830 false alpha-over
|
||||
4 ptlogo1.t32 00008830 false alpha-over
|
||||
4 ptlogo2.t32 00008830 false alpha-over
|
||||
4 ptlogo_tm.t32 00008830 false alpha-over
|
||||
4 ptcopyright.t32 00008830 false alpha-over
|
||||
4 ptlogo_back2.t32 00008830 false alpha-over
|
||||
4 ptlogo_back2eff.t32 00008830 false alpha-over
|
||||
2 ptbtn00.t32 00000110 false alpha-over
|
||||
2 ptbtn00f.t32 00000112 true ADDITIVE
|
||||
5 ptbase.t32 00008830 false alpha-over
|
||||
5 ptmsg.t32 00008830 false alpha-over
|
||||
5 ptbtn01f.t32 00008130 false alpha-over
|
||||
5 ptbtneff01.t32 00008130 false alpha-over
|
||||
5 pteff10.t32 00008832 true ADDITIVE
|
||||
5 pteff12.t32 00008832 true ADDITIVE
|
||||
5 ptframe1.t32 00008832 true ADDITIVE
|
||||
5 ptframe2.t32 00008832 true ADDITIVE
|
||||
5 pteff03.t32 00008832 true ADDITIVE
|
||||
5 pteff03a.t32 00008832 true ADDITIVE
|
||||
6 ptbase.t32 00008830 false alpha-over
|
||||
6 ptmsg2.t32 00008830 false alpha-over
|
||||
6 pttitle.t32 00008830 false alpha-over
|
||||
6 ptbtn11f.t32 00008130 false alpha-over
|
||||
6 ptbtn12.t32 00008130 false alpha-over
|
||||
6 ptbtn13.t32 00008130 false alpha-over
|
||||
6 ptbtneff02.t32 00008130 false alpha-over
|
||||
6 pteff10.t32 00008832 true ADDITIVE
|
||||
6 pteff20.t32 00008832 true ADDITIVE
|
||||
6 pteff21.t32 00008832 true ADDITIVE
|
||||
6 pteff22.t32 00008832 true ADDITIVE
|
||||
6 pteff23.t32 00008832 true ADDITIVE
|
||||
6 ptframe3.t32 00008832 true ADDITIVE
|
||||
6 ptframe4.t32 00008832 true ADDITIVE
|
||||
6 pteff03.t32 00008832 true ADDITIVE
|
||||
6 pteff03a.t32 00008832 true ADDITIVE
|
||||
|
||||
bit set & additive 16
|
||||
bit clear & alpha-over 19
|
||||
bit set & alpha-over 0 <- false positives
|
||||
bit clear & additive 0 <- false negatives
|
||||
sprite not found 0
|
||||
|
||||
PERFECT PARTITION on every element whose blend was measured.
|
||||
|
||||
RIVAL FIELDS — other bits of the first 12 header words that separate
|
||||
the same 35 elements with zero errors: 1
|
||||
+0x04 bit 1 (0x2)
|
||||
-> the sample singles out ONE field. Nothing else in the header does it.
|
||||
@@ -45,7 +45,7 @@ def blend_name(raw):
|
||||
return "%s+%s" % (FACTOR.get(src, src), FACTOR.get(dst, dst))
|
||||
|
||||
|
||||
def candidates(builds):
|
||||
def candidates(builds, pak="GP_TITLE"):
|
||||
"""Every size a UI draw could legitimately have, with a label and a basis.
|
||||
|
||||
Two bases, because neither alone names every element:
|
||||
@@ -67,7 +67,7 @@ def candidates(builds):
|
||||
def run(example):
|
||||
return subprocess.run(
|
||||
["cargo", "run", "--release", "-q", "-p", "sylpheed-formats",
|
||||
"--example", example, "--"] + [str(b) for b in builds],
|
||||
"--example", example, "--", pak] + [str(b) for b in builds],
|
||||
capture_output=True, text=True, cwd="/work", env=env).stdout
|
||||
out = []
|
||||
for line in run("rest_scale_of").splitlines():
|
||||
@@ -87,7 +87,8 @@ def main():
|
||||
path = sys.argv[1]
|
||||
spec = sys.argv[sys.argv.index("--build") + 1] if "--build" in sys.argv else "5"
|
||||
builds = [int(b) for b in spec.split(",")]
|
||||
cands = candidates(builds)
|
||||
pak = sys.argv[sys.argv.index("--pak") + 1] if "--pak" in sys.argv else "GP_TITLE"
|
||||
cands = candidates(builds, pak)
|
||||
lines = open(path).read().splitlines()
|
||||
rows = []
|
||||
for i, line in enumerate(lines):
|
||||
|
||||
Reference in New Issue
Block a user