Files
Sylpheed/docs/re/structures/ui-blend-mode-decoded.md
sylph-decoder f4987977a3 re: the blend mode IS on the disc -- T8aD +0x04 bit 0x02, DECODED
Reverses two of my own pages. t32-blend-mode-not-on-disc.md said the mode is not
on the disc; ui-blend-mode-measured.md classified it measured and told the port
that which field selects it was unknown. Both were honest and neither is current.

Bit 0x02 of +0x04 set means the game draws that sprite ADDITIVE
(RB_BLENDCONTROL0 = 0x01010101); clear means premultiplied alpha-over.

Fit: 35 elements over three screens, 16 set/additive and 19 clear/alpha-over,
zero errors, every label read out of the guest command stream rather than off a
render.

Control: of every bit of the first twelve header words, exactly one separates
those 35 without error. Nothing ties with it -- which is precisely what the
+0x08 = 0x8050 candidate failed.

Within-pair: ptbtn00 0x0110 alpha-over against ptbtn00f 0x0112 additive, same
screen, same bundle, adjacent draws, one bit apart. And other f variants are
bit-clear and alpha-over, so it is not 'focused variants are additive'.

Out of sample: a prediction committed at bbd85e9, before its capture, on a
different archive -- GP_OPTIONS entry 19, 3 additive of 16, falsified if any
other element drew additive. The game drew exactly po_menu_eff01/02/03 additive
and nothing else.

This revives a claim REFUTED.md killed. The refutation said blending those
sprites additively worsens every measure against the capture -- a claim about
our renderer, made while that renderer had a stale keyframe association, no leaf
geometry and no rotation. Recorded as a revival with its evidence;
check_refuted.py passes with 0 unmarked assertions.

Two other readings of the same bit stay refuted and are explicitly not revived:
'the name contains eff' and 'premultiplied storage'. Those were the bit's
meaning; this is its effect.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
2026-08-31 07:20:12 +00:00

121 lines
5.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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*.