The port isolated main_menu's 10.88 -> 13.02 regression to pteff10 and asked whether the per-draw log shows it alpha-over, which would be a counter-example to ui-blend-mode-decoded.md. It does not. blend-bit-vs-oracle.txt has pteff10 ADDITIVE on entry 5 (main menu) AND entry 6 (extras), both labels read out of the guest command stream, and HANDOFF states it from three independent menu sessions, every frame. The premise came from a stale coverage table of mine that the same HANDOFF entry had already corrected in place. Recording that: a correction which leaves the wrong table visible upstream of it has not landed. And the regression was predicted on this exact element before adoption -- HANDOFF flagged pteff10 as the one row the port's renderer would not corroborate, because for a dim wholly-semi-transparent glow (max alpha 130) over a dark background additive and alpha-over nearly coincide. A renderer metric getting worse while the render gets more correct is the standing rule with a number on it. Separately, the port answered my finding-3 candidate: a frozen sweep of the plate region rises monotonically across the declared 214->236, so the port fades rather than pops and its t=236 is a completion. That kills the onset branch. Two of the play-test's four named candidates for finding 3 are now dead -- units/s (measured at 60) and the ramp. Finding 3 has no surviving named cause. The clock origin is the one to take next, because every measurement so far is a DIFFERENCE between two events and a difference cannot detect a common offset. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Jc4pciRArGHfxGGhEbwp5t
170 lines
8.3 KiB
Markdown
170 lines
8.3 KiB
Markdown
# The UI blend mode is on the disc after all — ✅ **DECODED**: `T8aD +0x04` bit `0x02`
|
||
|
||
**Status:** ✅ `CONFIRMED`, classification **decoded** — the field, plus a
|
||
disc-wide check and an out-of-sample prediction that could have died and did not.
|
||
2026-08-31.
|
||
|
||
> 🔴 **This reverses two of my own published conclusions.**
|
||
> [`t32-blend-mode-not-on-disc.md`](t32-blend-mode-not-on-disc.md) said the mode is
|
||
> *not on the disc*, and [`ui-blend-mode-measured.md`](ui-blend-mode-measured.md)
|
||
> classified it **measured** and told the port to read the table as per-element
|
||
> facts because *"which field selects the mode is still unknown"*. Both stand as
|
||
> honest records of what was known; neither is current. **The port can derive the
|
||
> blend for any element on any screen instead of transcribing a table.**
|
||
|
||
## The field
|
||
|
||
> **`T8aD +0x04` bit `0x02` set ⇒ the game draws that sprite ADDITIVE
|
||
> (`RB_BLENDCONTROL0 = 0x01010101`, src `ONE` / dst `ONE`).
|
||
> Clear ⇒ premultiplied alpha-over (`0x07010701`, src `ONE` / dst `1−SRC_ALPHA`).**
|
||
|
||
## Why the old refutation was wrong, and why that matters
|
||
|
||
[`REFUTED.md`](../REFUTED.md) killed this exact 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 this corpus's own rule
|
||
calls a hypothesis under test — and at the time the renderer had a stale keyframe
|
||
association, no leaf geometry and no rotation. The claim was never tested against
|
||
the game. It is now, and the field survives.
|
||
|
||
📌 The lesson is not "the old test was sloppy". It is that **a negative produced by
|
||
comparing two renders inherits every defect of both**, and that a field can sit
|
||
refuted for weeks because the instrument that killed it was the thing under
|
||
repair.
|
||
|
||
## The evidence
|
||
|
||
### 1. The fit — 35 elements, three screens, zero errors
|
||
|
||
Every label is an `RB_BLENDCONTROL0` value read out of the guest command stream
|
||
and attributed by quad size ([`data/blend-bit-vs-oracle.txt`](../data/blend-bit-vs-oracle.txt)):
|
||
|
||
| | count |
|
||
|---|---|
|
||
| bit set **and** drawn additive | **16** |
|
||
| bit clear **and** drawn alpha-over | **19** |
|
||
| bit set but alpha-over | **0** |
|
||
| bit clear but additive | **0** |
|
||
|
||
### 2. The control — no rival field
|
||
|
||
A perfect partition on 35 elements is worthless if half the header partitions
|
||
equally well; that is exactly the mistake `+0x08 = 0x8050` was. So every bit of
|
||
the first twelve header words was tested against the same 35 labels:
|
||
|
||
**Exactly one separates them without error, and it is `+0x04` bit `0x02`.**
|
||
Nothing ties with it.
|
||
|
||
### 3. The within-pair case that no confound survives
|
||
|
||
| element | `+0x04` | drawn |
|
||
|---|---|---|
|
||
| `ptbtn00.t32` | `0x0110` | alpha-over |
|
||
| `ptbtn00f.t32` | `0x0112` | **ADDITIVE** |
|
||
|
||
The `PRESS Ⓐ` plate and its own highlight variant. Same screen, same bundle,
|
||
adjacent in draw order, differing in exactly this bit — and the game blends them
|
||
differently. Screen, archive, element family and draw order are all held fixed.
|
||
|
||
⚠️ And the obvious rival reading dies here too: `ptbtn01f`, `ptbtn11f` — other
|
||
`f` highlight variants — are `0x8130`, bit clear, and are drawn **alpha-over**.
|
||
It is not "focused variants are additive".
|
||
|
||
### 4. The prediction, written and committed **before** the capture
|
||
|
||
[`data/blend-bit-prediction-gp-options.txt`](../data/blend-bit-prediction-gp-options.txt),
|
||
committed at `bbd85e9`, said of `GP_OPTIONS` — **a different archive, an entirely
|
||
different element set, never captured**:
|
||
|
||
> *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.
|
||
|
||
**Result** ([`data/blend-bit-prediction-result.txt`](../data/blend-bit-prediction-result.txt),
|
||
[capture](../captures/ui-draws/blend-options-2026-08-31.log)): the game was driven
|
||
to `OPTIONS` and captured — 39 draws over 3 frames. **Exactly three additive quads
|
||
per frame, and they are `po_menu_eff01`, `po_menu_eff02`, `po_menu_eff03`.** Entry
|
||
19 declares 16 sprites, 3 predicted additive and 13 not. Zero errors.
|
||
|
||
## Reach, and what is *not* claimed
|
||
|
||
⚠️ **The alpha-over side of the `OPTIONS` test is a count, not 13 identifications.**
|
||
Draw 1 is a 20-index batch of tiled 320×360 background quads, a size several
|
||
elements share. What is measured there is that **no draw on that screen carries
|
||
`0x01010101` except the three**. That asymmetry is the right way round: the
|
||
prediction would have died on a fourth additive draw, and there was none.
|
||
|
||
⚠️ **Two blend states, not a general mode field.** Every UI draw observed on four
|
||
screens is one of `0x01010101`, `0x07010701`, or `0x00010001` for the one
|
||
non-UI blit that opens the frame. The bit chooses between the first two. Nothing
|
||
here says what a third mode would look like or whether one exists.
|
||
|
||
⚠️ **`src = ONE` in both states.** The fixed-function stage multiplies the pixel
|
||
shader's output by 1, so whatever alpha weighting happens is the shader's. This
|
||
says nothing about whether `.t32` texels are stored premultiplied; the shader is
|
||
unread.
|
||
|
||
⚠️ **Untextured primitives (`.prm`) have no `T8aD` header**, so the bit cannot
|
||
speak for them. `pteff00.prm` and `pteff02.prm` are observed alpha-over; that is
|
||
a measurement, not a decode.
|
||
|
||
📊 **Disc-wide population:** the bit is set on **4 995 of 14 709** sprites (34 %),
|
||
so it is not degenerate in either direction. Prior work established separately
|
||
that it is **not** "the name contains `eff`" (`P(eff|set) = 0.468` against
|
||
`P(eff|clear) = 0.144`) and **not** premultiplied-alpha storage — both refuted
|
||
disc-wide, and both remain refuted. Those were readings of the bit's *meaning*;
|
||
this is its *effect*.
|
||
|
||
## Challenged 2026-09-01 as a possible counter-example — and it SURVIVES
|
||
|
||
The port reported that adopting the bit moved `main_menu` **10.88 → 13.02**
|
||
against its oracle capture, isolated the only newly-additive top-level element as
|
||
**`pteff10`**, and asked whether the per-draw log shows `main_menu`'s `pteff10`
|
||
drawn **alpha-over** — which would put a counter-example on one element.
|
||
|
||
**It does not. The oracle measures it ADDITIVE on that screen.**
|
||
|
||
```
|
||
data/blend-bit-vs-oracle.txt
|
||
5 pteff10.t32 +0x04 = 00008832 bit 0x02 = true ADDITIVE
|
||
6 pteff10.t32 +0x04 = 00008832 bit 0x02 = true ADDITIVE
|
||
```
|
||
|
||
Entry 5 is the main menu and entry 6 is `EXTRAS`; the element is additive on
|
||
**both**, and every label there is an `RB_BLENDCONTROL0` value read out of the
|
||
guest command stream. `HANDOFF.md` states it directly and from three sessions:
|
||
*"Is `pteff10` additive on the MAIN MENU too? — **YES.** … additive, **in all
|
||
three menu sessions, every frame**."*
|
||
|
||
⚠️ **The premise came from a stale table of mine.** The port's *"your own map
|
||
lists `pteff10` additive on `extras` and not on `main_menu`"* is reading a
|
||
coverage table that the same HANDOFF entry had already corrected in place —
|
||
*"My coverage table listing `pteff10` as uncovered on the menu is corrected."*
|
||
A correction that leaves the wrong table visible upstream of it is a correction
|
||
that has not landed.
|
||
|
||
### 📌 The regression was PREDICTED, on this exact element, before adoption
|
||
|
||
`HANDOFF.md`, flagged as 🟡 at the time the port was told to take the bit:
|
||
|
||
> *"One flag on `pteff10` before you adopt it. You measure it as nearly exact
|
||
> under alpha-over, and the game draws it additive. Both can be true for a dim
|
||
> wholly-semi-transparent glow (max alpha 130) over a dark background, where the
|
||
> two nearly coincide — but it is the one row here your renderer does **not**
|
||
> independently corroborate."*
|
||
|
||
So `main_menu` getting *worse* on a renderer metric while getting *more correct*
|
||
against the GPU is the flagged case arriving on schedule, not a new fact. It is
|
||
the corpus's standing rule with a number attached: **a claim resting on our
|
||
renderer is a claim about our renderer**, and here the renderer and the oracle
|
||
disagree on the one element where the two blends are known to nearly coincide.
|
||
|
||
The port shipped the decoded bit anyway and recorded the movement as a known
|
||
regression. That was the right call for a better reason than the one it used:
|
||
not merely that `+2.14` sits inside the screen's `±3.78` capture-phase term, but
|
||
that the oracle had already adjudicated this element, three sessions deep.
|