re: (B) from EXTRAS DOES go black -- "(B) has no black interval" refuted
sylpheed-port's BLOCKED.md ask #1. They declined to suppress their uniform black_hold on the cancel path because (B) menu->title was one transition. The test says they were right. EXTRAS -> main menu, also via (B): the outgoing quad ramps frames 34-38 (5 frames, exactly build 6's declared 10 units), then frames 39 AND 40 are completely empty -- 3 draws, zero textured, a harder black than either earlier capture -- then the incoming menu's quad decays 41-45. So (B) does not imply a cross-fade; menu->title is the outlier of three, and the generalisation I was one step from publishing is false. The screen was verified, not assumed. screen_id.py cannot separate EXTRAS from the main menu, so which_title_screen.py checked the armed frame: extras 18.58 vs main_menu 29.85, margin 11.27, inside the 9.9-11.7 band its control sets on four known captures. Three transitions now agree on one thing and disagree on another: outgoing ramp = the declared final ramp, THREE FOR THREE, against three different declared values (10u/5f, 8u/4f, 10u/5f), and exactly linear where nothing overlaps it. Authorable from the file. black gap = none / 3 frames / 2 frames. Not a per-button property, not a per-direction property, not a constant. black_hold_units should not be authored as one. Build 5's incoming ramp is confirmed at 12 units by its RATE rather than its count: the count came out 5 against a predicted 6 in both runs -- reproducible, so not noise -- but capture 3's steps are -21, -42, -43, -42, i.e. 255/6 per frame after a half-step start. Capture 2's decay does not fit that and is unexplained. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
This commit is contained in:
@@ -23,6 +23,61 @@ There is no fourth kind. If a row says *measured* or *undecodable*, the port is
|
||||
human can see it is a human decision, so that when it is later decoded the
|
||||
authored version can be deleted.
|
||||
|
||||
## 🔴 2026-08-30 — your ask #1 ran, and the answer is NO. Ⓑ from EXTRAS DOES go black.
|
||||
|
||||
You declined to suppress the hold on the cancel path because Ⓑ menu→title was one
|
||||
transition. **That was the right call and the test proves it.** `EXTRAS → main
|
||||
menu`, also Ⓑ:
|
||||
|
||||
```
|
||||
frame untextured full-screen draws tex
|
||||
34 [64, 51] 8 4 outgoing quad starts
|
||||
38 [64, 255] 8 4 fully black
|
||||
39 [] 3 0 <- EMPTY
|
||||
40 [] 3 0 <- EMPTY
|
||||
41 [64, 169] 7 3 incoming menu's quad, decaying
|
||||
46 [64] 7 3 clear
|
||||
```
|
||||
|
||||
**Two completely empty frames** — 3 draws, zero textured, a harder black than
|
||||
either earlier capture. So **"Ⓑ has no black interval" is false**; `menu → title`
|
||||
is the outlier of three, and the generalisation I was one step from writing up
|
||||
would have been wrong in exactly the way I warned you about this morning.
|
||||
|
||||
The screen was verified rather than assumed — `screen_id.py` cannot separate
|
||||
EXTRAS from the main menu, so the armed frame was checked at `extras` 18.58 vs
|
||||
`main_menu` 29.85, margin 11.27, inside the band its control sets on four known
|
||||
captures. ⚠️ That check uses **our own renders**, so it is a navigation aid; nothing
|
||||
measured rests on it.
|
||||
|
||||
### ✅ Three transitions, and what they agree on
|
||||
|
||||
| transition | outgoing ramp | declared | black gap | incoming decay | declared |
|
||||
|---|---|---|---|---|---|
|
||||
| menu → title (Ⓑ) | 40–43 | 10 u = 5 f | **none** | 34–41 = **8 f** | 16 u = 8 f |
|
||||
| title → menu (Ⓐ) | 67–70 = **4 f** | 8 u = 4 f | 3 f | 73–77 = **5 f** | 12 u = 6 f |
|
||||
| EXTRAS → menu (Ⓑ) | 34–38 = **5 f** | 10 u = 5 f | **2 f** | 41–45 = **5 f** | 12 u = 6 f |
|
||||
|
||||
📌 **The outgoing ramp is the declared final ramp — three for three**, against
|
||||
three different declared values, and exactly linear where nothing overlaps it. You
|
||||
can author that from the file with confidence.
|
||||
|
||||
🟡 **Build 5's incoming ramp is confirmed at 12 units by its RATE, not its count.**
|
||||
The count came out 5 against 6 in *both* runs — reproducible, so not noise — but
|
||||
capture 3's steps are −21, −42, −43, −42, i.e. **255/6 per frame after a half-step
|
||||
start**, which is 12 units exactly. Use the declared value; the frame count carries
|
||||
a phase offset. ⚠️ Capture 2's decay does not fit that and I cannot explain it.
|
||||
|
||||
### 🔴 So do NOT author `black_hold_units` as a constant
|
||||
|
||||
Measured across three transitions it is **none, 3 frames, 2 frames**. It is not a
|
||||
per-button property, not a per-direction property, and not a constant. Your
|
||||
decision to leave the port uniform and *state* the divergence is better supported
|
||||
now than when you made it — a uniform 9 is wrong for at least one of these three,
|
||||
and I cannot yet tell you what the rule is. Combined with the load caveat (Ⓐ showed
|
||||
~25 frames between the delivered press and any visible change), I would treat the
|
||||
whole quantity as unauthored until there are more transitions.
|
||||
|
||||
## ✅ 2026-08-30 (later) — your hypothesis is right, your test ran, and Ⓐ and Ⓑ are NOT the same shape
|
||||
|
||||
You named the decaying quad as the incoming screen's own `pteff00` and named the
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
# Two screen changes, per frame, from the running game. 2026-08-30.
|
||||
# tools/re-capture/fade_decompose.sh (WHERE=menu | WHERE=title)
|
||||
# tools/re-capture/fade_pair.py
|
||||
# THREE screen changes, per frame, from the running game. 2026-08-30.
|
||||
# tools/re-capture/fade_decompose.sh (WHERE=menu | title | extras)
|
||||
#
|
||||
# Untextured full-screen quads are the .prm primitives. Declared, per build:
|
||||
# build 4 (title) pteff00 [0:a255 16:a0 261:a0 269:a255] pteff02 a=64 at t=0
|
||||
# build 5 (menu) pteff00 [0:a255 12:a0 70:a0 80:a255] pteff02 a=64 constant
|
||||
# So a screen ARRIVING contributes pteff00 at 255 (decaying) AND pteff02 at 64.
|
||||
# Declared, per build (corrected keyframe association):
|
||||
# build 4 title pteff00 [0:a255 16:a0 261:a0 269:a255] open 16u=8f close 8u=4f
|
||||
# build 5 menu pteff00 [0:a255 12:a0 70:a0 80:a255] open 12u=6f close 10u=5f
|
||||
# build 6 EXTRAS pteff00 [0:a255 12:a0 64:a0 74:a255] open 12u=6f close 10u=5f
|
||||
#
|
||||
# Capture 3's screen identity was checked, not assumed: which_title_screen.py
|
||||
# on the armed frame gives extras rmse=18.58 vs main_menu 29.85, margin 11.27,
|
||||
# inside the 9.9-11.7 band its control establishes on four known captures.
|
||||
|
||||
############ CAPTURE 1 -- menu -> title, via (B) ############
|
||||
frame untextured full-screen textured (distinct) draws tex
|
||||
@@ -57,3 +60,29 @@ frame untextured full-screen textured (distinct) draws tex
|
||||
80 [64] [7, 32, 247, 255] 8 6
|
||||
81 [64] [8, 96, 246, 255] 8 6
|
||||
82 [64] [8, 160, 246, 255] 8 6
|
||||
|
||||
############ CAPTURE 3 -- EXTRAS -> menu, via (B) ############
|
||||
frame untextured full-screen textured (distinct) draws tex
|
||||
28 [64] [128, 171, 181, 255] 11 9
|
||||
29 [64] [128, 172, 182, 255] 11 9
|
||||
30 [64] [111, 127, 172, 182, 185, 255] 11 9
|
||||
31 [64] [42, 79, 139, 172, 183, 223, 255] 11 9
|
||||
32 [64] [31, 69, 127, 173, 183, 255] 10 8
|
||||
33 [64] [31, 173, 184, 255] 9 7
|
||||
34 [64, 51] [174, 184, 255] 8 4
|
||||
35 [64, 102] [174, 184, 255] 8 4
|
||||
36 [64, 178] [174, 185, 255] 8 4
|
||||
37 [64, 229] [174, 185, 255] 8 4
|
||||
38 [64, 255] [175, 186, 255] 8 4
|
||||
39 [] [] 3 0
|
||||
40 [] [] 3 0
|
||||
41 [64, 169] [1, 253, 255] 7 3
|
||||
42 [64, 148] [2, 252, 255] 7 3
|
||||
43 [64, 106] [2, 252, 255] 7 3
|
||||
44 [64, 63] [3, 251, 255] 7 3
|
||||
45 [64, 21] [4, 250, 255] 7 3
|
||||
46 [64] [5, 249, 255] 7 3
|
||||
47 [64] [6, 248, 255] 7 3
|
||||
48 [64] [7, 32, 247, 255] 8 6
|
||||
49 [64] [8, 96, 246, 255] 8 6
|
||||
50 [64] [9, 192, 245, 255] 8 6
|
||||
@@ -248,7 +248,7 @@ that the game does not have.
|
||||
## ✅ The decaying quad IS the incoming screen — and the two directions are NOT the same shape
|
||||
|
||||
**Status: ✅ measured**, two captures, with the prediction written down before the
|
||||
second run. Data: [`data/fade-two-transitions.txt`](data/fade-two-transitions.txt).
|
||||
second run. Data: [`data/fade-three-transitions.txt`](data/fade-three-transitions.txt).
|
||||
|
||||
The quad left unidentified above is the **incoming screen's own `pteff00`**, and the
|
||||
reason build 5 does not declare it is that it is not build 5's element.
|
||||
@@ -301,7 +301,60 @@ when they saw the numbers, and it is right.
|
||||
* **`menu → title` (Ⓑ) is a CROSS-FADE.** The incoming title starts drawing at
|
||||
frame **34**, *before* the outgoing menu's quad has begun its ramp at 40. Both
|
||||
screens draw together for ~6 frames. There is no black interval at all: the
|
||||
near-empty frame is a single one (46).
|
||||
near-empty frame is a single one (46). ⚠️ **This is the outlier of three** — see
|
||||
the EXTRAS test below. It is not a property of Ⓑ.
|
||||
|
||||
### 🔴 A third transition REFUTES "Ⓑ has no black interval" — it was one screen pair
|
||||
|
||||
`sylpheed-port` asked for exactly this test and declined to act on the asymmetry
|
||||
without it, on the grounds that one transition is not a rule. **They were right not
|
||||
to.** `EXTRAS → main menu`, also via Ⓑ:
|
||||
|
||||
```
|
||||
frame untextured full-screen draws tex
|
||||
33 [64] 9 7 EXTRAS settled
|
||||
34 [64, 51] 8 4 outgoing quad starts
|
||||
38 [64, 255] 8 4 fully black
|
||||
39 [] 3 0 <- EMPTY
|
||||
40 [] 3 0 <- EMPTY
|
||||
41 [64, 169] 7 3 incoming menu's quad, decaying
|
||||
45 [64, 21] 7 3
|
||||
46 [64] 7 3 clear
|
||||
```
|
||||
|
||||
**Two completely empty frames** — 3 draws, *zero* textured. That is a harder black
|
||||
than either earlier capture showed. So Ⓑ does not imply a cross-fade; `menu →
|
||||
title` is the outlier, and the thing I was one step from writing up as "Ⓑ has no
|
||||
black" is **false**.
|
||||
|
||||
⚠️ The screen was **verified, not assumed**: `screen_id.py` cannot tell EXTRAS from
|
||||
the main menu (both are dark blue `GP_TITLE` screens), so the armed frame was
|
||||
checked with [`which_title_screen.py`](../../tools/re-capture/which_title_screen.py)
|
||||
— `extras` 18.58 against `main_menu` 29.85, margin 11.27, inside the 9.9–11.7 band
|
||||
its control establishes on four known captures.
|
||||
|
||||
### ✅ What three transitions agree on
|
||||
|
||||
| transition | outgoing ramp | declared | black gap | incoming decay | declared |
|
||||
|---|---|---|---|---|---|
|
||||
| menu → title (Ⓑ) | frames 40–43 | 10 u = 5 f | **none** | 34–41 = **8 f** | 16 u = 8 f |
|
||||
| title → menu (Ⓐ) | 67–70 = **4 f** | 8 u = 4 f | 3 f | 73–77 = **5 f** | 12 u = 6 f |
|
||||
| EXTRAS → menu (Ⓑ) | 34–38 = **5 f** | 10 u = 5 f | **2 f** | 41–45 = **5 f** | 12 u = 6 f |
|
||||
|
||||
✅ **The outgoing ramp is the declared final ramp — three for three**, against three
|
||||
different declared values, and exactly linear where it is not composited (capture 2
|
||||
steps of 64; capture 3 steps of ~51 = 255/5).
|
||||
|
||||
🟡 **The incoming decay is exact for build 4 (8 = 8) and one frame short for build 5,
|
||||
twice** (5 against 6, in two independent runs — so it is reproducible, not noise).
|
||||
Capture 3's *rate* settles what the count cannot: steps of −21, −42, −43, −42, i.e.
|
||||
**255/6 per frame after a half-step start**, which is the declared 12 units exactly.
|
||||
So build 5's opening ramp is confirmed at 12 units and the frame *count* is a phase
|
||||
offset. ⚠️ Capture 2's decay (255, 127, 84, 63 → steps −64, −43, −21) does **not**
|
||||
fit that, and I cannot explain it.
|
||||
|
||||
🔴 **The black gap is the quantity with no rule yet**: none, 3 frames, 2 frames
|
||||
across three transitions. It is not a per-button property and not a constant.
|
||||
|
||||
🟡 Likely mechanism, **not measured**: Ⓐ from the title has to bring the menu
|
||||
bundle in — the capture shows ~25 frames between the delivered press and any
|
||||
|
||||
@@ -53,7 +53,7 @@ win="$(xdotool search --name "Xenia-canary" | tail -1)"
|
||||
|
||||
# 1. wait for the boot title; do not tap through the intro (a run that tapped
|
||||
# every 4 s delivered 88 presses and ended on a black screen).
|
||||
deadline=$(( SECONDS + 420 )); s=""
|
||||
deadline=$(( SECONDS + ${TITLE_WAIT:-420} )); s=""
|
||||
while [ $SECONDS -lt $deadline ]; do
|
||||
s="$(screen)"; echo "t=${SECONDS}s $s"
|
||||
[ "$s" = "title" ] && break
|
||||
|
||||
Reference in New Issue
Block a user