port: draw the measured additive blend -- main_menu 13.21 -> 10.67
The Decoder logged RB_BLENDCONTROL0 per draw in Canary on both screens. 0x01010101 is src=ONE dst=ONE, additive. That makes the blend a transcription rather than my proposal, and they withdrew the "any blend you choose is authored" instruction explicitly. Their control is what licenses the change: one pixel shader, 0xE59B2B3DA4AA9008, runs with BOTH blend states on the main menu -- 12 additive draws and 18 alpha-over. The frames and ptbase share a shader; only the blend register differs. authored/rendering.json gains additive_elements per screen. Every id is a measured draw and the reach is written beside it. verify-capture: main_menu 13.21 -> 10.67 (0.06 % -> 0.02 %), extras 13.38 -> 11.43, main menu with ptbtn04 focused 13.82 -> 11.36. Per element, ptframe1 22.72 -> 4.17 and ptframe2 13.09 -> 3.32. Neutrality control, free with the table: publisher_logo 2.17 and developer_logos 3.05 are unchanged to the digit. Those are the screens whose metric is absolute and they carry no additive element, so the rewrite that routed every draw through RenderingServer canvas items did not change the picture. The improvement is the blend, not the plumbing. RenderingServer rather than child Node2Ds because boot.gd calls view.queue_redraw() from nine places and none reaches a child node -- bands would paint the previous pose, which under --script=wait is a plausible wrong capture rather than an error. Runs are recomputed per frame: the additive elements are consecutive on both measured screens, and that is an accident of those two screens. And the change first ran with the material left at its default MIX, moving ptframe1 from 22.72 to 22.69. Nothing errored and a 0.03 move is a plausible negative result. It was caught only because the measurement predicted a large move. Not done: ptframe4 is now the worst element on EXTRAS at 16.19x the frame mean and additive would plainly help it. It is not in the measured table, so it is not in the file. Filed in BLOCKED.md with pteff21/22/23, which are also in no captured draw. Refuted, mine: "neither frame has a fully-opaque pixel" was true and was not the discriminator -- pteff10 has max alpha 130, no opaque pixel, and measures nearly exact. The direction survived; the reason for it did not.
This commit is contained in:
@@ -147,6 +147,38 @@ HANDOFF.
|
||||
| ~~P1–P7 — the keyframe record layout~~ | ~~adopt the corrected pose/time pairing~~ | — | ✅ **ADOPTED 2026-08-29 by pinning `formats-pin-2026-08-29c`.** This row was wrong twice: it said the change *"cannot be taken yet"* and that it *"reaches the port only when that branch lands on `main`"*. **It arrives when the tag is pinned**, which is what MISSION §2's tagging rule exists for. ⚠️ And the knob I tested first, `SYLPHEED_KF_TIME_SHIFT`, is a **retired partial fix** that left pose 0 untimed — the real correction is the tagged crate's default, with the old reading behind `SYLPHEED_KF_TIME_LEGACY=1`. **The blast radius was far smaller than this row predicted**: under the correction *every pose is timed* (866 keyframes, 0 untimed), so `pose_at`'s synthetic-exit branch became dead code rather than wrong code and nothing needed re-deriving. Oracle: `publisher_logo` 1.00 %→**0.75 %**, `developer_logos` 0.39 %→**0.33 %**, `extras`' differing region collapsing from 736×525 to **398×295 at the sweep position**. 🔴 Open cost: `sylpheed-cli` builds from the workspace crate, so `verify-screen` compares two decoder eras until the tag reaches `main`. Revert to the path dependency then. |
|
||||
| ~~P7 / naming — the four unnamed builds~~ | ~~which locale and variant is each of entries 0, 1, 12, 15?~~ | — | ✅ **answered 2026-08-29** (`docs/re/ui-title-build-map.md`): all four are the loading screen, two variants — plain (7 elements) and dressed (10) — decoded from their own `pgloading_*` element names. ⚠️ **Not adopted as names yet, for two reasons the RE agent gave and one the port found.** Theirs: the executable names exactly two, and *which* bundle takes which name is 🟡 undecided, so `LOADING`/`LOADING2` must not go in an asset path; and locale is 🟡 — the English member of a pair is the one in the first half of `GP_TITLE.p00`, 8/8 structurally but only 3/3 where a capture can check, and the three pairs that matter are the three no capture can check. Mine: **the message gives the bundles as "0/1 and 10/11", which is the `is_build` ordinal, and `authored/screen_names.json` is keyed by PAK ENTRY** — in entry space 10 and 11 are `palogo_sqex` and `palogo_gamearts`, the splashes. See the refutation section in `DECISIONS.md`. |
|
||||
|
||||
## New ask, 2026-08-31 — derived from HANDOFF (today's blend-mode delivery), port `HEAD` `0a054d6`
|
||||
|
||||
**Four elements on EXTRAS are in no draw capture: `ptframe4`, `pteff21`, `pteff22`,
|
||||
`pteff23`. What blend mode do they use?**
|
||||
|
||||
The measured table (`docs/re/data/ui-blend-mode-measured.txt`) named `pteff20` and
|
||||
`ptframe3` additive on EXTRAS, and the port now draws those two that way. **The
|
||||
result is exactly the shape you want and exactly why this ask matters:**
|
||||
|
||||
| EXTRAS element | before | after | signed after |
|
||||
|---|---|---|---|
|
||||
| **`ptframe3`** — measured, applied | 34.80 | **7.97** | **−0.61** |
|
||||
| **`ptframe4`** — *not measured, left alone* | 25.58 | **31.90** | −31.81 |
|
||||
| `pteff21` / `22` / `23` — *not measured* | 10.25 / 10.63 / 10.09 | 14.34 / 13.15 / 12.04 | all negative |
|
||||
|
||||
📌 **Where the blend is measured the element is now near-exact; where it is not,
|
||||
it is the worst thing on the screen.** The four unmeasured ones also got *worse* in
|
||||
absolute terms, which is consistent rather than alarming: their neighbours are now
|
||||
correctly brighter, so an alpha-over deficit that scales with the background scales
|
||||
up with it.
|
||||
|
||||
🔴 **I am not inferring them from the pattern.** `ptframe4` is the third frame on a
|
||||
screen whose other frame is measured additive, and it is dark, and additive would
|
||||
plainly help. That is precisely the argument I must not act on — the Decoder's own
|
||||
warning with the table was to read it as **per-element facts**, because which field
|
||||
selects the mode is still unknown, and a fourth frame added by pattern would be
|
||||
indistinguishable from a measured one in a month.
|
||||
|
||||
⚠️ They appear in **no** captured draw on either screen, so this may need a
|
||||
different pose rather than a re-read: they may simply not have been drawing in the
|
||||
frames that were captured.
|
||||
|
||||
## ✅ ANSWERED SAME DAY, and the answer is a negative — HANDOFF `5a7f34d`, port `HEAD` `6af06bd`
|
||||
|
||||
**Asked: what blend mode do `ptframe1` and `ptframe2` use on the main menu?**
|
||||
|
||||
@@ -9,7 +9,7 @@ dies, which is what this file is for.
|
||||
|
||||
<!-- INDEX: generated by tools/port/index-decisions -- do not hand-edit -->
|
||||
|
||||
330 sections. Search this before re-deriving anything.
|
||||
332 sections. Search this before re-deriving anything.
|
||||
|
||||
* [P0 — the exporter, 2026-08-28](#p0--the-exporter-2026-08-28)
|
||||
* [P1 — Godot draws the screen, 2026-08-28](#p1--godot-draws-the-screen-2026-08-28)
|
||||
@@ -341,6 +341,8 @@ dies, which is what this file is for.
|
||||
* [The frames generalise, premultiplied alpha is refuted, and the shortfall tracks the background](#the-frames-generalise-premultiplied-alpha-is-refuted-and-the-shortfall-tracks-the-background)
|
||||
* [Which blend? Additive halves the error, on both frames — proposed, not adopted](#which-blend-additive-halves-the-error-on-both-frames--proposed-not-adopted)
|
||||
* [Refutation attempt: the Decoder's kind-0 claim survives, checked from my own data](#refutation-attempt-the-decoders-kind-0-claim-survives-checked-from-my-own-data)
|
||||
* [The blend is measured, so the port draws it — main_menu 13.21 → 10.67](#the-blend-is-measured-so-the-port-draws-it--main_menu-1321--1067)
|
||||
* [🔴 Refuted: my "no fully-opaque pixel" sharpener](#refuted-my-no-fully-opaque-pixel-sharpener)
|
||||
|
||||
<!-- /INDEX -->
|
||||
## P0 — the exporter, 2026-08-28
|
||||
@@ -16085,3 +16087,89 @@ field agree, and the claim is now stronger than when only one side had read it.
|
||||
declared *identically* to `ptbase` (drawn at 1.31× the frame mean) and `pteff05`
|
||||
(0.92×). Same declaration, opposite accuracy — so whatever distinguishes them is
|
||||
not in the field either of us can read.
|
||||
|
||||
## The blend is measured, so the port draws it — main_menu 13.21 → 10.67
|
||||
|
||||
The Decoder took the draw-path route and logged `RB_BLENDCONTROL0` per draw in
|
||||
Canary on both screens. `0x01010101` is `src=ONE dst=ONE`: **additive**. That
|
||||
turns my proposal into a transcription, and they said so explicitly — *"withdraw
|
||||
the instruction I gave you last time; additive is transcribed now, not authored."*
|
||||
|
||||
📌 **Their control is what licenses the change:** one pixel shader,
|
||||
`0xE59B2B3DA4AA9008`, runs with **both** blend states on the main menu — 12 draws
|
||||
additive, 18 alpha-over. The frames and `ptbase` share a shader. **Only the blend
|
||||
register differs**, so this is a blend result and not a shader result.
|
||||
|
||||
Recorded in `authored/rendering.json` as `additive_elements`, per screen, with
|
||||
every id being a measured draw and the reach written next to it.
|
||||
|
||||
### The result, and a neutrality control that came free
|
||||
|
||||
| screen | before | after |
|
||||
|---|---|---|
|
||||
| **`main_menu`** | 13.21 / 0.06 % | **10.67 / 0.02 %** |
|
||||
| **`extras`** | 13.38 / 0.20 % | **11.43 / 0.07 %** |
|
||||
| main menu, focus `ptbtn04` | 13.82 / 0.15 % | 11.36 / 0.11 % |
|
||||
| title / title_plate / title_band | 14.16 / 13.04 / 12.86 | 14.10 / 13.03 / 12.85 |
|
||||
| **`publisher_logo`** | **2.17** | **2.17** |
|
||||
| **`developer_logos`** | **3.05** | **3.05** |
|
||||
|
||||
✅ **The last two rows are the control.** They are the screens `verify-capture`
|
||||
marks *"no free-running element — absolute, means what it says"*, and they have no
|
||||
additive element. They did not move **at all**. The rewrite routed every draw in
|
||||
the project through `RenderingServer` canvas items, so "did the plumbing change
|
||||
the picture?" was a live question; those two rows answer it. The improvement is
|
||||
the blend, not the refactor.
|
||||
|
||||
Per element on `main_menu`: `ptframe1` **22.72 → 4.17** (signed −22.72 → −3.51),
|
||||
`ptframe2` 13.09 → 3.32 (−12.31 → **+1.80**), whole-screen mean 2.40 → 1.55.
|
||||
|
||||
### 🔴 The change ran, produced a number, and the number was wrong by looking right
|
||||
|
||||
First run after wiring it all up: `ptframe1` moved from **22.72 to 22.69**. Bands
|
||||
were created, ordered and assigned correctly; the screen composited exactly as
|
||||
before. I had written `CanvasItemMaterial.new()` and **never set `blend_mode`**, so
|
||||
every band was MIX.
|
||||
|
||||
📌 Nothing errored. A 0.03 move is a *plausible* outcome — I could have written
|
||||
"additive does not help after all, the two-background solve overstated it" and it
|
||||
would have read as a careful negative result. **It was caught only because the
|
||||
measurement predicted a large move and 0.03 is not one.** The comment now sits on
|
||||
that line.
|
||||
|
||||
### Why it is `RenderingServer` and not child nodes
|
||||
|
||||
Godot sets blend mode per **canvas item**, not per draw call. The obvious
|
||||
implementation — a child `Node2D` per band with a `CanvasItemMaterial` — **loses a
|
||||
frame**: `boot.gd` calls `view.queue_redraw()` from nine places and none reaches a
|
||||
child node, so bands would paint the *previous* pose. Under `--script=wait` that
|
||||
surfaces as a plausible wrong capture, not an error. The bands are canvas items
|
||||
filled synchronously inside `_draw()` instead.
|
||||
|
||||
The runs are recomputed every frame rather than cached. The additive elements are
|
||||
consecutive in paint order on both measured screens — **that is an accident of
|
||||
those two screens**, and a cache keyed on "the additive block" would be right today
|
||||
and silently wrong on the first screen that interleaves.
|
||||
|
||||
### ⚠️ What I did not do: `ptframe4`
|
||||
|
||||
`ptframe4` is now the worst element on EXTRAS (31.90, 16.19× the frame mean) and
|
||||
additive would plainly help it. **It is not in the measured table and it is not in
|
||||
the file.** Filed in `BLOCKED.md` with `pteff21`/`22`/`23`, which are also absent
|
||||
from every captured draw. Where the blend is measured the element is near-exact
|
||||
(`ptframe3` signed **−0.61**); where it is not, it is the worst thing on screen.
|
||||
That contrast is the argument for asking rather than inferring.
|
||||
|
||||
## 🔴 Refuted: my "no fully-opaque pixel" sharpener
|
||||
|
||||
I offered, as the thing that distinguished the frames, that **neither frame has a
|
||||
single fully-opaque pixel** against `ptbase`'s 99.1 %. The Decoder refuted it with
|
||||
a census (`docs/re/data/menu-sprite-alpha-census.txt`): **`pteff10` has max alpha
|
||||
130, is 100 % partial, has no opaque pixel either — and I measure it as nearly
|
||||
exact.** `pteff12`, `pteff20` and `pteff21`–`23` likewise.
|
||||
|
||||
✅ **The observation was true and it was not the discriminator.** My *direction*
|
||||
survived — the draw path was the right place to look, and it answered — but the
|
||||
reason I gave for looking there was wrong. Recording it because the conclusion
|
||||
being vindicated is exactly the circumstance in which a bad supporting argument
|
||||
survives unexamined.
|
||||
|
||||
Reference in New Issue
Block a user