diff --git a/docs/re/INDEX.md b/docs/re/INDEX.md index 55492ad3..8fcbd2ab 100644 --- a/docs/re/INDEX.md +++ b/docs/re/INDEX.md @@ -180,6 +180,7 @@ files, which is how the same ground got covered twice. | [`structures/ui-clock-freezes-at-settle.md`](structures/ui-clock-freezes-at-settle.md) | The top-level clock stops at the settle point — observed in the running game | ✅ **measured**: `GP_TITLE` build 4 declares `t = 0…269`, about 120 presented frames at this run's pacing, and the dwell lasted **~1 100**. `ptcopyright` declares alpha≥1 for **106 units** (t=138…244) and is **drawn for 1 050 frames**; `ptlogo1` declares an exit at t=264 and is drawn for 1 095. Both vanish within three frames of the dwell ending. **The clock advances through the build-in, stops inside the settle window `[160,236]`, and holds; the exit ramp plays when the screen leaves, not on a timer** — [`ui-settle-time.md`](structures/ui-settle-time.md)'s decode observed from the other side. A nested record keeps looping on its own clock throughout. 🔴 **This closes the 114-vs-120 gap, and it was my arithmetic**: 2.231 units/frame was regressed over *build-in* events (the only stretch the top-level clock advances) and applied to a period measured during the freeze — two different clocks. The declared **120** was never in doubt from the calibration-free dark-fraction test. ✅ The 51.158-frame period is now confirmed by a **second independent estimator** (autocorrelation, lag 51 with harmonics at 102/154) — ⚠️ whose first version **failed its control**, returning 48, because it indexed by sample position where the log's frame numbers have gaps. ❔ The **sweeps'** period stays unmeasured: the same validated estimator disagrees between two dwells of one screen (515 vs 452 frames). 🔴 **Blocker: a single Ⓐ on the title faults the guest** — 3 attempts, 2 register dumps of 223 MB and 519 MB, against 3 no-input runs that all completed; bounds menu-side dynamic RE here, and any scripted button press needs a `canary.stdout` size guard | | [`structures/boot-splash-dwells-are-declared.md`](structures/boot-splash-dwells-are-declared.md) | How long each boot splash is shown | ✅ **decoded**: the dwells are the bundles' own declared timelines — publisher **t=0…255 = 4.250 s**, developer **t=0…210 = 3.500 s** at 60 units/s. The corpus's independent screenshot timing over 3 cold boots gives 4.30/4.60/4.37 and **3.51/3.50/3.37** — the developer agreeing to **1.1 %**, two of its three runs to 0.3 %. 🔴 **Wall clock is the wrong unit to author**: a fresh no-input boot measured the same two dwells at **5.10–5.61 s** and 3.83–4.30 s, 15–20 % longer than both the declared values and the corpus's runs, on the same disc — so a seconds figure is one run's emulator pacing. Boundaries from the draw stream: publisher wordmark frames 6–119, **3 frames with no sprite drawn**, developer glows 123, wordmarks 140–209, intro video 216. 🔴 **The frame→wall-clock instrument resolves to one BUFFER FLUSH, not one frame** — 69 of 125 samples showed no advance and the rest jumped 7–15 frames, making the apparent rate swing 0.0164–0.0316 s/frame; frames 119 and 123 fall in one burst, so the inter-splash gap is **not separable** by it. Quoted as brackets; sub-flush estimates withdrawn before reporting. ⚠️ `palogo_anima` never appears — almost certainly the 8-vertex cap (7 elements batched, 2 logged), the same trap as the `eff3` false negative, so it is named not reported. ❔ the publisher's 4.1 % error vs the developer's 1.1 % is unexplained | | [`structures/ui-forced-backdrop.md`](structures/ui-forced-backdrop.md) *(colour census + self-refutation)* | What colour a keyless element is, and which forced verdicts the argument actually supports | ✅ **decoded, disc-wide**: every full-screen `*eff00*` **primitive** is **pure black** at its various alphas (`ff000000`, `7f000000`, `40000000`, `b2000000`, `cc000000`, `d4000000`, `00000000`) — exactly an alpha-over dim or fade, and an *additive* black quad would be a no-op nobody would author. The **only** non-black primitive on the disc is `pbafc.prm`, RGB `00e8e0` cyan at alphas to `ff`, and it is **844×600, not full-screen**, so outside the backdrop rule's geometry guard — ❔ it is now the sole additive candidate. 🔴 **Self-refutation: of the 80 forced-first instances only 42 are `.prm`; 38 are `.tbm` carrying fade `ffffffff`.** A *solid* white quad painted first would make the screen white and no screen is white, so a `.tbm` is a white **modulation on a texture** — and element alpha does not establish its coverage. That is the `.t32` error one extension further out: I had fixed the symptom (`el.sprite.is_some()`) not the cause, **an element's alpha is not its texture's opacity, and only an untextured primitive makes the two the same fact**. So 42 verdicts stay **decoded**, 38 drop to 🟡 (still almost certainly right — all named `*base*`, full-screen, and `pfbase.tbm`'s first position is *measured* — but on a name-and-role argument this page elsewhere calls the weaker kind). ⚠️ Code deliberately unchanged: restricting to `.prm` would send eleven screens' backgrounds back to last, the blank-screen bug the rule fixed. Split pinned by a test | +| [`structures/ui-blend-mode-decoded.md`](structures/ui-blend-mode-decoded.md) | Which blend the game draws a sprite with | ✅ **DECODED** — **`T8aD +0x04` bit `0x02` set ⇒ ADDITIVE (`RB_BLENDCONTROL0 = 0x01010101`), clear ⇒ premultiplied alpha-over (`0x07010701`)**. 🔴 **Reverses two of my own pages**: [`t32-blend-mode-not-on-disc.md`](structures/t32-blend-mode-not-on-disc.md) ("not on the disc") and [`ui-blend-mode-measured.md`](structures/ui-blend-mode-measured.md) (classified *measured*, "which field selects the mode is still unknown"). ✅ **Fit**: 35 elements, 3 screens, 16 set/additive + 19 clear/alpha-over, **0 errors**, every label read out of the guest command stream. ✅ **Control**: of every bit of the first 12 header words, **exactly one** separates those 35 without error — no tie, which is what `+0x08 = 0x8050` failed. ✅ **Within-pair**: `ptbtn00` `0x0110` alpha-over vs `ptbtn00f` `0x0112` additive — same screen, same bundle, adjacent draws, one bit apart; and other `f` variants (`ptbtn01f`, `ptbtn11f`) are bit-clear and alpha-over, killing "focused variants are additive". ✅ **Out-of-sample prediction, committed before its capture** (`bbd85e9`): `GP_OPTIONS` entry 19 predicted 3 additive of 16 — the game drew exactly `po_menu_eff01/02/03` additive and nothing else. 🔴 **Revives a REFUTED claim**, whose refutation was a claim about our renderer while that renderer had a stale keyframe association, no leaf geometry and no rotation. ⚠️ Two *other* readings of the same bit stay refuted (`eff` in the name; premultiplied storage) — those were its **meaning**, this is its **effect**. ⚠️ `.prm` primitives have no `T8aD` header, so the bit cannot speak for them | | [`structures/ui-blend-mode-measured.md`](structures/ui-blend-mode-measured.md) | Which blend the UI draws each element with | ✅ **measured** off the GPU, per draw, on the main menu and `EXTRAS`. **Two states and one pixel shader**: `RB_BLENDCONTROL0 = 0x07010701` (src `ONE`, dst `1−SRC_ALPHA`, alpha-over) for `ptbase`, `pteff05`, the fade quad, `ptmsg`, `ptmsg2`, `pttitle` and every button; **`0x01010101` (src `ONE`, dst `ONE`, ADDITIVE)** for **`ptframe1`, `ptframe2`, `ptframe3`**, `pteff20` and both rotated sweep strips. ✅ **Control 1** — the NDC→pixel conversion that names a draw by its quad size reproduces **1134** and **1303** px for the two sweep strips, measured by a different tool in a different session, on both screens; the tool prints PASS/FAIL and disclaims itself on FAIL. ✅ **Control 2** — pixel shader `0xE59B2B3DA4AA9008` is used with **both** states (12 additive, 18 alpha-over), so `ptframe1` and `ptbase` run the same shader and this is a blend result, not a shader result. ✅ Independently corroborated by the port, which solved the composite per pixel from two backgrounds and ranked additive 34.3/28.9 against alpha-over's 65.0/71.3. 🔴 Supersedes the *conclusion* of [`t32-blend-mode-not-on-disc.md`](structures/t32-blend-mode-not-on-disc.md) — its negative and reach stand, its instruction *"any blend you choose is authored"* does not. ❔ **Which field selects the mode is still unknown**; 🔴 and a first phrasing of this page — *"elements sharing a mode are batched into one draw call"* — is **refuted by its own log**: menu draws 5, 6 and 7 are three separate additive draws. Only the one-way implication holds, elements inside one draw share a state. ⚠️ Two additive menu draws unidentified; the **title screen was not captured** | | [`structures/ui-prm-blend-mode.md`](structures/ui-prm-blend-mode.md) | Whether a primitive blends additively or alpha-over | ❔ **undecodable, with reach** — but the consequence is closed. Looked in **the bundle** (no field: the declaration words are constant and a primitive has no RATC child at all), **the colour census** (every full-screen `*eff00*` primitive is **pure black**; the only non-black primitive on the disc is `pbafc.prm`, cyan `00e8e0`), **the occlusion constraint** (inapplicable — `pbafc.prm` strobes 255/124 every 2 units, travels, and is scaled **2 %×3 %**, so it draws ~**17×18 px**, not its declared 844×600), and **the oracle** (`GP_READY_ROOM` is a recorded no-go and gameplay needs the Ⓐ that faults the guest). ✅ **Why it stopped mattering:** for a *black* quad the hypotheses differ only in whether it hides what is beneath — drawn **first** it is correct under **both**, drawn **last** only under additive. So `forced_backdrop`'s verdict is robust to the open question, and the port's original "layerless sorts last" was wrong under alpha-over and merely pointless under additive. ⚠️ This is not evidence *for* alpha-over. 🔴 The investigation found `forced_backdrop` judged coverage from the **pivot alone**, ignoring scale; checked first, **all 80 forced instances are at 100 %**, so no verdict moved and the added guard is defensive | | [`structures/title-a-press-fault.md`](structures/title-a-press-fault.md) | Why a single Ⓐ on the title faults the guest — the blocker on all menu-side dynamic RE | ✅ **SOLVED 2026-08-30, and it is the emulator, not the game.** Xenia returns `X_ERROR_SUCCESS` with a *zeroed* keystroke on every `XamInputGetKeystrokeEx` while a XAM dialog is up (`xam_input.cc:197`, upstream); the game's pump is an **unbounded** `while (GetKeystrokeEx()==SUCCESS) queue.push_back()`, so it queued **8 388 608** empty keystrokes, grew its vector to 64 MB, asked for 128 MB, got a failed allocation back **unchecked** and copied off the top of the guest thread stack. ✅ **The number is the argument**: the Canary counter reports **8 388 601** swallowed calls at the last report before the crash, the dump's `r29` says the vector held **8 388 608** — two independent instruments, 7 apart, inside the 600-call reporting granularity. No new boot: the failing run's 326 MB log was still on disk. 🔴 **RETRACTED — "`r9` is a wild pointer above 4 GB"**. Xenia prints `si_addr`, a *host* address, and the guest is mapped at `0x100000000`: `0x1701D0000 − 0x100000000 = 0x701D0000`, which **is** `r9` in the dump — an ordinary guest heap address on an uncommitted page. Subtract `0x100000000` from every `Access Violation … at 0x1________` before reading it. ✅ **Decoded code path**, image-checked with **0 mismatches** over 586 instructions: `sub_824574C0` the input-manager singleton at `0x828F3888`, `sub_82457038` the keystroke pump, `sub_82457780` its `vector` insert-with-grow. ✅ **It explains the earlier successes**: whether a XAM dialog is up is *emulator* state, so "reproduced 4/4" and "Q4/Q5 pressed Ⓐ fine" were both always true. 🟡 **Which** dialog is still open — `XamShowDeviceSelectorUI` is ruled out (`storage_selection_dialog = false` takes the headless path), `XamShowSigninUI` / `XamShowMessageBoxUIEx` are not; the settling experiment is one log line per `is_xam_dialog_present_.store(true)` site, not another blind boot. 🟡 Three untried routes out: dismiss the dialog, `--headless`, or return `X_ERROR_EMPTY` from the swallow. ✅ `frame_clock.sh`'s 300 MB guard killed the run as designed — keep it | diff --git a/docs/re/REFUTED.md b/docs/re/REFUTED.md index 6ea30aa2..8c094167 100644 --- a/docs/re/REFUTED.md +++ b/docs/re/REFUTED.md @@ -83,8 +83,28 @@ neighbourhood, not just the line. * "the plate-free title capture (t ≈ 4.0 s) may be too early to be settled" → **mine, and refuted.** The swoosh band correlates 0.7342 at t = 4.0 s and 0.7353 at t = 21.5 s — identical to 0.001 over 17.5 s. -* "`T8aD +0x04` bit `0x02` selects an additive blend" → **mine, and refuted.** - Blending those sprites additively worsens every measure against the capture. +* ~~"`T8aD +0x04` bit `0x02` selects an additive blend" → **mine, and refuted.** + Blending those sprites additively worsens every measure against the capture.~~ + 🔴 **REVIVED AND ESTABLISHED 2026-08-31 — the refutation was wrong, and it was + wrong in a way this corpus has a rule for.** *"Blending them additively worsens + every measure against the capture"* is a claim about **our renderer**, which the + protocol calls a hypothesis under test; at the time it had a stale keyframe + association, no leaf geometry and no rotation. The claim was never tested + against the game. + ✅ It is now: the blend is read per draw out of `RB_BLENDCONTROL0`, and the bit + partitions **35 elements over three screens with zero errors** — and of every + bit of the first twelve header words, **exactly one** does so, with no tie. + ✅ The within-pair case: `ptbtn00` `0x0110` alpha-over, `ptbtn00f` `0x0112` + **additive** — same screen, same bundle, adjacent draws, one bit apart. + ✅ And an **out-of-sample prediction committed before its capture** held on a + different archive: `GP_OPTIONS` entry 19 was predicted 3 additive of 16, and + the game drew exactly `po_menu_eff01/02/03` additive and nothing else. + → [`structures/ui-blend-mode-decoded.md`](structures/ui-blend-mode-decoded.md) + ⚠️ Two *other* readings of this same bit stay refuted, and are not revived by + this: "the bit means the name contains `eff`" (fails on 2 657 of 4 995 disc-wide) + and "the bit selects premultiplied alpha" (the flagged group violates `RGB ≤ A` + *more* than the unflagged one). Those were readings of the bit's **meaning**; + what is established here is its **effect**. [`ui-title-build-map.md`](ui-title-build-map.md) * "the title logo elements' wrong pivots (off by up to 59 px, authored against the other language's sprite) explain the swoosh rendering too thick" → **mine, and diff --git a/docs/re/captures/ui-draws/blend-options-2026-08-31.log b/docs/re/captures/ui-draws/blend-options-2026-08-31.log new file mode 100644 index 00000000..7badb359 --- /dev/null +++ b/docs/re/captures/ui-draws/blend-options-2026-08-31.log @@ -0,0 +1,76 @@ +# every draw in SUBMISSION ORDER, undeduplicated, frames 1..3 +# tex dimensions identify the sprite; base is the guest address + 0 prim=8 indices=3 vs=0x0A6D1DD7767FDF27 ps=0x2E372EA28CC404B7 blend=0x00010001[c:src=1 op=0 dst=0 a:src=1 op=0 dst=0] cc=0x00000000 mask=0xFFFF + vb=0x14D93338 stride=28 attrs=[57@0 38@12 ] fmt0=57 v: [-0.50,-0.50,z=0.00000] [1279.50,-0.50,z=0.00000] [1279.50,719.50,z=0.00000] + 1 prim=13 indices=20 vs=0xE0BAFB4F520FE441 ps=0xE59B2B3DA4AA9008 blend=0x07010701[c:src=1 op=0 dst=7 a:src=1 op=0 dst=7] cc=0x8700000C mask=0xF tex[base=0x0C9F0000 1280x768 fmt=6] + vb=0x14D93390 stride=24 attrs=[57@0 6@12 37@16 ] fmt0=57 v: [-1.00,1.00,z=0.00000,col=FFFFFFFF] [-0.00,1.00,z=0.00000,col=FFFFFFFF] [-0.00,-1.00,z=0.00000,col=FFFFFFFF] [-1.00,-1.00,z=0.00000,col=FFFFFFFF] [1.00,1.00,z=0.00000,col=FFFFFFFF] [0.50,1.00,z=0.00000,col=FFFFFFFF] [0.50,0.00,z=0.00000,col=FFFFFFFF] [1.00,0.00,z=0.00000,col=FFFFFFFF] [0.50,1.00,z=0.00000,col=FFFFFFFF] [-0.00,1.00,z=0.00000,col=FFFFFFFF] [-0.00,0.00,z=0.00000,col=FFFFFFFF] [0.50,0.00,z=0.00000,col=FFFFFFFF] [1.00,0.00,z=0.00000,col=FFFFFFFF] [0.50,0.00,z=0.00000,col=FFFFFFFF] [0.50,-1.00,z=0.00000,col=FFFFFFFF] [1.00,-1.00,z=0.00000,col=FFFFFFFF] [0.50,0.00,z=0.00000,col=FFFFFFFF] [-0.00,0.00,z=0.00000,col=FFFFFFFF] [-0.00,-1.00,z=0.00000,col=FFFFFFFF] [0.50,-1.00,z=0.00000,col=FFFFFFFF] + 2 prim=13 indices=8 vs=0xE0BAFB4F520FE441 ps=0xE59B2B3DA4AA9008 blend=0x01010101[c:src=1 op=0 dst=1 a:src=1 op=0 dst=1] cc=0x8700000C mask=0xF tex[base=0x0C340000 1280x768 fmt=6] + vb=0x14D93570 stride=24 attrs=[57@0 6@12 37@16 ] fmt0=57 v: [-0.94,1.00,z=0.00000,col=FFFFFFFF] [0.04,1.00,z=0.00000,col=FFFFFFFF] [0.04,-1.00,z=0.00000,col=FFFFFFFF] [-0.94,-1.00,z=0.00000,col=FFFFFFFF] [-0.86,0.64,z=0.00000,col=FFFFFFFF] [-0.10,0.64,z=0.00000,col=FFFFFFFF] [-0.10,-0.78,z=0.00000,col=FFFFFFFF] [-0.86,-0.78,z=0.00000,col=FFFFFFFF] + 3 prim=13 indices=4 vs=0xE0BAFB4F520FE441 ps=0xE59B2B3DA4AA9008 blend=0x07010701[c:src=1 op=0 dst=7 a:src=1 op=0 dst=7] cc=0x8700000C mask=0xF tex[base=0x0B2C0000 1280x768 fmt=6] + vb=0x14D93630 stride=24 attrs=[57@0 6@12 37@16 ] fmt0=57 v: [-0.76,-0.73,z=0.00000,col=FFFFFFFF] [-0.22,-0.73,z=0.00000,col=FFFFFFFF] [-0.22,-0.84,z=0.00000,col=FFFFFFFF] [-0.76,-0.84,z=0.00000,col=FFFFFFFF] + 4 prim=13 indices=4 vs=0xE0BAFB4F520FE441 ps=0xE59B2B3DA4AA9008 blend=0x01010101[c:src=1 op=0 dst=1 a:src=1 op=0 dst=1] cc=0x8700000C mask=0xF tex[base=0x0C9F0000 1280x768 fmt=6] + vb=0x14D93690 stride=24 attrs=[57@0 6@12 37@16 ] fmt0=57 v: [-0.76,0.48,z=0.00000,col=FFFFFFFF] [-0.20,0.48,z=0.00000,col=FFFFFFFF] [-0.20,-0.60,z=0.00000,col=FFFFFFFF] [-0.76,-0.60,z=0.00000,col=FFFFFFFF] + 5 prim=13 indices=4 vs=0xE0BAFB4F520FE441 ps=0xE59B2B3DA4AA9008 blend=0x07010701[c:src=1 op=0 dst=7 a:src=1 op=0 dst=7] cc=0x8700000C mask=0xF tex[base=0x11C30000 1280x768 fmt=6] + vb=0x14D936F0 stride=24 attrs=[57@0 6@12 37@16 ] fmt0=57 v: [-0.72,0.31,z=0.00000,col=FFFFFFFF] [-0.78,0.35,z=0.00000,col=FFFFFFFF] [-0.76,0.47,z=0.00000,col=FFFFFFFF] [-0.69,0.43,z=0.00000,col=FFFFFFFF] + 6 prim=13 indices=8 vs=0xE0BAFB4F520FE441 ps=0xE59B2B3DA4AA9008 blend=0x07010701[c:src=1 op=0 dst=7 a:src=1 op=0 dst=7] cc=0x8700000C mask=0xF tex[base=0x0C340000 1280x768 fmt=6] + vb=0x14D93750 stride=24 attrs=[57@0 6@12 37@16 ] fmt0=57 v: [-0.71,0.46,z=0.00000,col=FFFFFFFF] [-0.31,0.46,z=0.00000,col=FFFFFFFF] [-0.31,0.31,z=0.00000,col=FFFFFFFF] [-0.71,0.31,z=0.00000,col=FFFFFFFF] [-0.70,0.25,z=0.00000,col=FFFFFFFF] [-0.26,0.25,z=0.00000,col=FFFFFFFF] [-0.26,0.13,z=0.00000,col=FFFFFFFF] [-0.70,0.13,z=0.00000,col=FFFFFFFF] + 7 prim=13 indices=8 vs=0xE0BAFB4F520FE441 ps=0xE59B2B3DA4AA9008 blend=0x07010701[c:src=1 op=0 dst=7 a:src=1 op=0 dst=7] cc=0x8700000C mask=0xF tex[base=0x0B2C0000 1280x768 fmt=6] + vb=0x14D93810 stride=24 attrs=[57@0 6@12 37@16 ] fmt0=57 v: [-0.70,0.05,z=0.00000,col=FFFFFFFF] [-0.30,0.05,z=0.00000,col=FFFFFFFF] [-0.30,-0.07,z=0.00000,col=FFFFFFFF] [-0.70,-0.07,z=0.00000,col=FFFFFFFF] [-0.70,-0.14,z=0.00000,col=FFFFFFFF] [-0.28,-0.14,z=0.00000,col=FFFFFFFF] [-0.28,-0.26,z=0.00000,col=FFFFFFFF] [-0.70,-0.26,z=0.00000,col=FFFFFFFF] + 8 prim=13 indices=4 vs=0xE0BAFB4F520FE441 ps=0xE59B2B3DA4AA9008 blend=0x07010701[c:src=1 op=0 dst=7 a:src=1 op=0 dst=7] cc=0x8700000C mask=0xF tex[base=0x0C340000 1280x768 fmt=6] + vb=0x14D938D0 stride=24 attrs=[57@0 6@12 37@16 ] fmt0=57 v: [-0.70,-0.33,z=0.00000,col=FFFFFFFF] [-0.54,-0.33,z=0.00000,col=FFFFFFFF] [-0.54,-0.45,z=0.00000,col=FFFFFFFF] [-0.70,-0.45,z=0.00000,col=FFFFFFFF] + 9 prim=13 indices=12 vs=0xE0BAFB4F520FE441 ps=0xE59B2B3DA4AA9008 blend=0x07010701[c:src=1 op=0 dst=7 a:src=1 op=0 dst=7] cc=0x8700000C mask=0xF tex[base=0x11C30000 1280x768 fmt=6] + vb=0x14D93930 stride=24 attrs=[57@0 6@12 37@16 ] fmt0=57 v: [-1.00,0.77,z=0.00000,col=FFFFFFFF] [-0.80,0.77,z=0.00000,col=FFFFFFFF] [-0.80,0.76,z=0.00000,col=FFFFFFFF] [-1.00,0.76,z=0.00000,col=FFFFFFFF] [-0.44,0.76,z=0.00000,col=FFFFFFFF] [-0.28,0.76,z=0.00000,col=FFFFFFFF] [-0.28,0.74,z=0.00000,col=FFFFFFFF] [-0.44,0.74,z=0.00000,col=FFFFFFFF] [-0.41,0.78,z=0.00000,col=FFFFFFFF] [-0.25,0.78,z=0.00000,col=FFFFFFFF] [-0.25,0.77,z=0.00000,col=FFFFFFFF] [-0.41,0.77,z=0.00000,col=FFFFFFFF] + 10 prim=13 indices=8 vs=0xE0BAFB4F520FE441 ps=0xE59B2B3DA4AA9008 blend=0x07010701[c:src=1 op=0 dst=7 a:src=1 op=0 dst=7] cc=0x8700000C mask=0xF tex[base=0x0C340000 1280x768 fmt=6] + vb=0x14D93A50 stride=24 attrs=[57@0 6@12 37@16 ] fmt0=57 v: [-1.00,0.75,z=0.00000,col=FFFFFFFF] [-0.31,0.75,z=0.00000,col=FFFFFFFF] [-0.31,0.71,z=0.00000,col=FFFFFFFF] [-1.00,0.71,z=0.00000,col=FFFFFFFF] [-0.78,0.90,z=0.00000,col=FFFFFFFF] [-0.44,0.90,z=0.00000,col=FFFFFFFF] [-0.44,0.71,z=0.00000,col=FFFFFFFF] [-0.78,0.71,z=0.00000,col=FFFFFFFF] + 11 prim=8 indices=3 vs=0x72CBCAA6A7984111 ps=0xE59B2B3DA4AA9008 blend=0x07010701[c:src=1 op=0 dst=7 a:src=1 op=0 dst=7] cc=0x8700000C mask=0xF tex[base=0x10000000 1x1 fmt=26] + 12 prim=8 indices=3 vs=0x72CBCAA6A7984111 ps=0xE59B2B3DA4AA9008 blend=0x07010701[c:src=1 op=0 dst=7 a:src=1 op=0 dst=7] cc=0x8700000C mask=0xF tex[base=0x10000000 1x1 fmt=26] +--- frame 2 --- + 13 prim=8 indices=3 vs=0x0A6D1DD7767FDF27 ps=0x2E372EA28CC404B7 blend=0x00010001[c:src=1 op=0 dst=0 a:src=1 op=0 dst=0] cc=0x00000000 mask=0xFFFF + vb=0x14DB3BB8 stride=28 attrs=[57@0 38@12 ] fmt0=57 v: [-0.50,-0.50,z=0.00000] [1279.50,-0.50,z=0.00000] [1279.50,719.50,z=0.00000] + 14 prim=13 indices=20 vs=0xE0BAFB4F520FE441 ps=0xE59B2B3DA4AA9008 blend=0x07010701[c:src=1 op=0 dst=7 a:src=1 op=0 dst=7] cc=0x8700000C mask=0xF tex[base=0x0C9F0000 1280x768 fmt=6] + vb=0x14DB3C10 stride=24 attrs=[57@0 6@12 37@16 ] fmt0=57 v: [-1.00,1.00,z=0.00000,col=FFFFFFFF] [-0.00,1.00,z=0.00000,col=FFFFFFFF] [-0.00,-1.00,z=0.00000,col=FFFFFFFF] [-1.00,-1.00,z=0.00000,col=FFFFFFFF] [1.00,1.00,z=0.00000,col=FFFFFFFF] [0.50,1.00,z=0.00000,col=FFFFFFFF] [0.50,0.00,z=0.00000,col=FFFFFFFF] [1.00,0.00,z=0.00000,col=FFFFFFFF] [0.50,1.00,z=0.00000,col=FFFFFFFF] [-0.00,1.00,z=0.00000,col=FFFFFFFF] [-0.00,0.00,z=0.00000,col=FFFFFFFF] [0.50,0.00,z=0.00000,col=FFFFFFFF] [1.00,0.00,z=0.00000,col=FFFFFFFF] [0.50,0.00,z=0.00000,col=FFFFFFFF] [0.50,-1.00,z=0.00000,col=FFFFFFFF] [1.00,-1.00,z=0.00000,col=FFFFFFFF] [0.50,0.00,z=0.00000,col=FFFFFFFF] [-0.00,0.00,z=0.00000,col=FFFFFFFF] [-0.00,-1.00,z=0.00000,col=FFFFFFFF] [0.50,-1.00,z=0.00000,col=FFFFFFFF] + 15 prim=13 indices=8 vs=0xE0BAFB4F520FE441 ps=0xE59B2B3DA4AA9008 blend=0x01010101[c:src=1 op=0 dst=1 a:src=1 op=0 dst=1] cc=0x8700000C mask=0xF tex[base=0x0C340000 1280x768 fmt=6] + vb=0x14DB3DF0 stride=24 attrs=[57@0 6@12 37@16 ] fmt0=57 v: [-0.94,1.00,z=0.00000,col=FFFFFFFF] [0.04,1.00,z=0.00000,col=FFFFFFFF] [0.04,-1.00,z=0.00000,col=FFFFFFFF] [-0.94,-1.00,z=0.00000,col=FFFFFFFF] [-0.86,0.64,z=0.00000,col=FFFFFFFF] [-0.10,0.64,z=0.00000,col=FFFFFFFF] [-0.10,-0.78,z=0.00000,col=FFFFFFFF] [-0.86,-0.78,z=0.00000,col=FFFFFFFF] + 16 prim=13 indices=4 vs=0xE0BAFB4F520FE441 ps=0xE59B2B3DA4AA9008 blend=0x07010701[c:src=1 op=0 dst=7 a:src=1 op=0 dst=7] cc=0x8700000C mask=0xF tex[base=0x0B2C0000 1280x768 fmt=6] + vb=0x14DB3EB0 stride=24 attrs=[57@0 6@12 37@16 ] fmt0=57 v: [-0.76,-0.73,z=0.00000,col=FFFFFFFF] [-0.22,-0.73,z=0.00000,col=FFFFFFFF] [-0.22,-0.84,z=0.00000,col=FFFFFFFF] [-0.76,-0.84,z=0.00000,col=FFFFFFFF] + 17 prim=13 indices=4 vs=0xE0BAFB4F520FE441 ps=0xE59B2B3DA4AA9008 blend=0x01010101[c:src=1 op=0 dst=1 a:src=1 op=0 dst=1] cc=0x8700000C mask=0xF tex[base=0x0C9F0000 1280x768 fmt=6] + vb=0x14DB3F10 stride=24 attrs=[57@0 6@12 37@16 ] fmt0=57 v: [-0.76,0.48,z=0.00000,col=FFFFFFFF] [-0.20,0.48,z=0.00000,col=FFFFFFFF] [-0.20,-0.60,z=0.00000,col=FFFFFFFF] [-0.76,-0.60,z=0.00000,col=FFFFFFFF] + 18 prim=13 indices=4 vs=0xE0BAFB4F520FE441 ps=0xE59B2B3DA4AA9008 blend=0x07010701[c:src=1 op=0 dst=7 a:src=1 op=0 dst=7] cc=0x8700000C mask=0xF tex[base=0x11C30000 1280x768 fmt=6] + vb=0x14DB3F70 stride=24 attrs=[57@0 6@12 37@16 ] fmt0=57 v: [-0.72,0.31,z=0.00000,col=FFFFFFFF] [-0.78,0.36,z=0.00000,col=FFFFFFFF] [-0.75,0.47,z=0.00000,col=FFFFFFFF] [-0.69,0.43,z=0.00000,col=FFFFFFFF] + 19 prim=13 indices=8 vs=0xE0BAFB4F520FE441 ps=0xE59B2B3DA4AA9008 blend=0x07010701[c:src=1 op=0 dst=7 a:src=1 op=0 dst=7] cc=0x8700000C mask=0xF tex[base=0x0C340000 1280x768 fmt=6] + vb=0x14DB3FD0 stride=24 attrs=[57@0 6@12 37@16 ] fmt0=57 v: [-0.71,0.46,z=0.00000,col=FFFFFFFF] [-0.31,0.46,z=0.00000,col=FFFFFFFF] [-0.31,0.31,z=0.00000,col=FFFFFFFF] [-0.71,0.31,z=0.00000,col=FFFFFFFF] [-0.70,0.25,z=0.00000,col=FFFFFFFF] [-0.26,0.25,z=0.00000,col=FFFFFFFF] [-0.26,0.13,z=0.00000,col=FFFFFFFF] [-0.70,0.13,z=0.00000,col=FFFFFFFF] + 20 prim=13 indices=8 vs=0xE0BAFB4F520FE441 ps=0xE59B2B3DA4AA9008 blend=0x07010701[c:src=1 op=0 dst=7 a:src=1 op=0 dst=7] cc=0x8700000C mask=0xF tex[base=0x0B2C0000 1280x768 fmt=6] + vb=0x14DB4090 stride=24 attrs=[57@0 6@12 37@16 ] fmt0=57 v: [-0.70,0.05,z=0.00000,col=FFFFFFFF] [-0.30,0.05,z=0.00000,col=FFFFFFFF] [-0.30,-0.07,z=0.00000,col=FFFFFFFF] [-0.70,-0.07,z=0.00000,col=FFFFFFFF] [-0.70,-0.14,z=0.00000,col=FFFFFFFF] [-0.28,-0.14,z=0.00000,col=FFFFFFFF] [-0.28,-0.26,z=0.00000,col=FFFFFFFF] [-0.70,-0.26,z=0.00000,col=FFFFFFFF] + 21 prim=13 indices=4 vs=0xE0BAFB4F520FE441 ps=0xE59B2B3DA4AA9008 blend=0x07010701[c:src=1 op=0 dst=7 a:src=1 op=0 dst=7] cc=0x8700000C mask=0xF tex[base=0x0C340000 1280x768 fmt=6] + vb=0x14DB4150 stride=24 attrs=[57@0 6@12 37@16 ] fmt0=57 v: [-0.70,-0.33,z=0.00000,col=FFFFFFFF] [-0.54,-0.33,z=0.00000,col=FFFFFFFF] [-0.54,-0.45,z=0.00000,col=FFFFFFFF] [-0.70,-0.45,z=0.00000,col=FFFFFFFF] + 22 prim=13 indices=12 vs=0xE0BAFB4F520FE441 ps=0xE59B2B3DA4AA9008 blend=0x07010701[c:src=1 op=0 dst=7 a:src=1 op=0 dst=7] cc=0x8700000C mask=0xF tex[base=0x11C30000 1280x768 fmt=6] + vb=0x14DB41B0 stride=24 attrs=[57@0 6@12 37@16 ] fmt0=57 v: [-1.00,0.77,z=0.00000,col=FFFFFFFF] [-0.80,0.77,z=0.00000,col=FFFFFFFF] [-0.80,0.76,z=0.00000,col=FFFFFFFF] [-1.00,0.76,z=0.00000,col=FFFFFFFF] [-0.44,0.76,z=0.00000,col=FFFFFFFF] [-0.28,0.76,z=0.00000,col=FFFFFFFF] [-0.28,0.74,z=0.00000,col=FFFFFFFF] [-0.44,0.74,z=0.00000,col=FFFFFFFF] [-0.41,0.78,z=0.00000,col=FFFFFFFF] [-0.25,0.78,z=0.00000,col=FFFFFFFF] [-0.25,0.77,z=0.00000,col=FFFFFFFF] [-0.41,0.77,z=0.00000,col=FFFFFFFF] + 23 prim=13 indices=8 vs=0xE0BAFB4F520FE441 ps=0xE59B2B3DA4AA9008 blend=0x07010701[c:src=1 op=0 dst=7 a:src=1 op=0 dst=7] cc=0x8700000C mask=0xF tex[base=0x0C340000 1280x768 fmt=6] + vb=0x14DB42D0 stride=24 attrs=[57@0 6@12 37@16 ] fmt0=57 v: [-1.00,0.75,z=0.00000,col=FFFFFFFF] [-0.31,0.75,z=0.00000,col=FFFFFFFF] [-0.31,0.71,z=0.00000,col=FFFFFFFF] [-1.00,0.71,z=0.00000,col=FFFFFFFF] [-0.78,0.90,z=0.00000,col=FFFFFFFF] [-0.44,0.90,z=0.00000,col=FFFFFFFF] [-0.44,0.71,z=0.00000,col=FFFFFFFF] [-0.78,0.71,z=0.00000,col=FFFFFFFF] + 24 prim=8 indices=3 vs=0x72CBCAA6A7984111 ps=0xE59B2B3DA4AA9008 blend=0x07010701[c:src=1 op=0 dst=7 a:src=1 op=0 dst=7] cc=0x8700000C mask=0xF tex[base=0x10000000 1x1 fmt=26] + 25 prim=8 indices=3 vs=0x72CBCAA6A7984111 ps=0xE59B2B3DA4AA9008 blend=0x07010701[c:src=1 op=0 dst=7 a:src=1 op=0 dst=7] cc=0x8700000C mask=0xF tex[base=0x10000000 1x1 fmt=26] +--- frame 3 --- + 26 prim=8 indices=3 vs=0x0A6D1DD7767FDF27 ps=0x2E372EA28CC404B7 blend=0x00010001[c:src=1 op=0 dst=0 a:src=1 op=0 dst=0] cc=0x00000000 mask=0xFFFF + vb=0x14DD4438 stride=28 attrs=[57@0 38@12 ] fmt0=57 v: [-0.50,-0.50,z=0.00000] [1279.50,-0.50,z=0.00000] [1279.50,719.50,z=0.00000] + 27 prim=13 indices=20 vs=0xE0BAFB4F520FE441 ps=0xE59B2B3DA4AA9008 blend=0x07010701[c:src=1 op=0 dst=7 a:src=1 op=0 dst=7] cc=0x8700000C mask=0xF tex[base=0x0C9F0000 1280x768 fmt=6] + vb=0x14DD4490 stride=24 attrs=[57@0 6@12 37@16 ] fmt0=57 v: [-1.00,1.00,z=0.00000,col=FFFFFFFF] [-0.00,1.00,z=0.00000,col=FFFFFFFF] [-0.00,-1.00,z=0.00000,col=FFFFFFFF] [-1.00,-1.00,z=0.00000,col=FFFFFFFF] [1.00,1.00,z=0.00000,col=FFFFFFFF] [0.50,1.00,z=0.00000,col=FFFFFFFF] [0.50,0.00,z=0.00000,col=FFFFFFFF] [1.00,0.00,z=0.00000,col=FFFFFFFF] [0.50,1.00,z=0.00000,col=FFFFFFFF] [-0.00,1.00,z=0.00000,col=FFFFFFFF] [-0.00,0.00,z=0.00000,col=FFFFFFFF] [0.50,0.00,z=0.00000,col=FFFFFFFF] [1.00,0.00,z=0.00000,col=FFFFFFFF] [0.50,0.00,z=0.00000,col=FFFFFFFF] [0.50,-1.00,z=0.00000,col=FFFFFFFF] [1.00,-1.00,z=0.00000,col=FFFFFFFF] [0.50,0.00,z=0.00000,col=FFFFFFFF] [-0.00,0.00,z=0.00000,col=FFFFFFFF] [-0.00,-1.00,z=0.00000,col=FFFFFFFF] [0.50,-1.00,z=0.00000,col=FFFFFFFF] + 28 prim=13 indices=8 vs=0xE0BAFB4F520FE441 ps=0xE59B2B3DA4AA9008 blend=0x01010101[c:src=1 op=0 dst=1 a:src=1 op=0 dst=1] cc=0x8700000C mask=0xF tex[base=0x0C340000 1280x768 fmt=6] + vb=0x14DD4670 stride=24 attrs=[57@0 6@12 37@16 ] fmt0=57 v: [-0.94,1.00,z=0.00000,col=FFFFFFFF] [0.04,1.00,z=0.00000,col=FFFFFFFF] [0.04,-1.00,z=0.00000,col=FFFFFFFF] [-0.94,-1.00,z=0.00000,col=FFFFFFFF] [-0.86,0.64,z=0.00000,col=FFFFFFFF] [-0.10,0.64,z=0.00000,col=FFFFFFFF] [-0.10,-0.78,z=0.00000,col=FFFFFFFF] [-0.86,-0.78,z=0.00000,col=FFFFFFFF] + 29 prim=13 indices=4 vs=0xE0BAFB4F520FE441 ps=0xE59B2B3DA4AA9008 blend=0x07010701[c:src=1 op=0 dst=7 a:src=1 op=0 dst=7] cc=0x8700000C mask=0xF tex[base=0x0B2C0000 1280x768 fmt=6] + vb=0x14DD4730 stride=24 attrs=[57@0 6@12 37@16 ] fmt0=57 v: [-0.76,-0.73,z=0.00000,col=FFFFFFFF] [-0.22,-0.73,z=0.00000,col=FFFFFFFF] [-0.22,-0.84,z=0.00000,col=FFFFFFFF] [-0.76,-0.84,z=0.00000,col=FFFFFFFF] + 30 prim=13 indices=4 vs=0xE0BAFB4F520FE441 ps=0xE59B2B3DA4AA9008 blend=0x01010101[c:src=1 op=0 dst=1 a:src=1 op=0 dst=1] cc=0x8700000C mask=0xF tex[base=0x0C9F0000 1280x768 fmt=6] + vb=0x14DD4790 stride=24 attrs=[57@0 6@12 37@16 ] fmt0=57 v: [-0.76,0.48,z=0.00000,col=FFFFFFFF] [-0.20,0.48,z=0.00000,col=FFFFFFFF] [-0.20,-0.60,z=0.00000,col=FFFFFFFF] [-0.76,-0.60,z=0.00000,col=FFFFFFFF] + 31 prim=13 indices=4 vs=0xE0BAFB4F520FE441 ps=0xE59B2B3DA4AA9008 blend=0x07010701[c:src=1 op=0 dst=7 a:src=1 op=0 dst=7] cc=0x8700000C mask=0xF tex[base=0x11C30000 1280x768 fmt=6] + vb=0x14DD47F0 stride=24 attrs=[57@0 6@12 37@16 ] fmt0=57 v: [-0.73,0.31,z=0.00000,col=FFFFFFFF] [-0.78,0.36,z=0.00000,col=FFFFFFFF] [-0.75,0.48,z=0.00000,col=FFFFFFFF] [-0.69,0.42,z=0.00000,col=FFFFFFFF] + 32 prim=13 indices=8 vs=0xE0BAFB4F520FE441 ps=0xE59B2B3DA4AA9008 blend=0x07010701[c:src=1 op=0 dst=7 a:src=1 op=0 dst=7] cc=0x8700000C mask=0xF tex[base=0x0C340000 1280x768 fmt=6] + vb=0x14DD4850 stride=24 attrs=[57@0 6@12 37@16 ] fmt0=57 v: [-0.71,0.46,z=0.00000,col=FFFFFFFF] [-0.31,0.46,z=0.00000,col=FFFFFFFF] [-0.31,0.31,z=0.00000,col=FFFFFFFF] [-0.71,0.31,z=0.00000,col=FFFFFFFF] [-0.70,0.25,z=0.00000,col=FFFFFFFF] [-0.26,0.25,z=0.00000,col=FFFFFFFF] [-0.26,0.13,z=0.00000,col=FFFFFFFF] [-0.70,0.13,z=0.00000,col=FFFFFFFF] + 33 prim=13 indices=8 vs=0xE0BAFB4F520FE441 ps=0xE59B2B3DA4AA9008 blend=0x07010701[c:src=1 op=0 dst=7 a:src=1 op=0 dst=7] cc=0x8700000C mask=0xF tex[base=0x0B2C0000 1280x768 fmt=6] + vb=0x14DD4910 stride=24 attrs=[57@0 6@12 37@16 ] fmt0=57 v: [-0.70,0.05,z=0.00000,col=FFFFFFFF] [-0.30,0.05,z=0.00000,col=FFFFFFFF] [-0.30,-0.07,z=0.00000,col=FFFFFFFF] [-0.70,-0.07,z=0.00000,col=FFFFFFFF] [-0.70,-0.14,z=0.00000,col=FFFFFFFF] [-0.28,-0.14,z=0.00000,col=FFFFFFFF] [-0.28,-0.26,z=0.00000,col=FFFFFFFF] [-0.70,-0.26,z=0.00000,col=FFFFFFFF] + 34 prim=13 indices=4 vs=0xE0BAFB4F520FE441 ps=0xE59B2B3DA4AA9008 blend=0x07010701[c:src=1 op=0 dst=7 a:src=1 op=0 dst=7] cc=0x8700000C mask=0xF tex[base=0x0C340000 1280x768 fmt=6] + vb=0x14DD49D0 stride=24 attrs=[57@0 6@12 37@16 ] fmt0=57 v: [-0.70,-0.33,z=0.00000,col=FFFFFFFF] [-0.54,-0.33,z=0.00000,col=FFFFFFFF] [-0.54,-0.45,z=0.00000,col=FFFFFFFF] [-0.70,-0.45,z=0.00000,col=FFFFFFFF] + 35 prim=13 indices=12 vs=0xE0BAFB4F520FE441 ps=0xE59B2B3DA4AA9008 blend=0x07010701[c:src=1 op=0 dst=7 a:src=1 op=0 dst=7] cc=0x8700000C mask=0xF tex[base=0x11C30000 1280x768 fmt=6] + vb=0x14DD4A30 stride=24 attrs=[57@0 6@12 37@16 ] fmt0=57 v: [-1.00,0.77,z=0.00000,col=FFFFFFFF] [-0.80,0.77,z=0.00000,col=FFFFFFFF] [-0.80,0.76,z=0.00000,col=FFFFFFFF] [-1.00,0.76,z=0.00000,col=FFFFFFFF] [-0.44,0.76,z=0.00000,col=FFFFFFFF] [-0.28,0.76,z=0.00000,col=FFFFFFFF] [-0.28,0.74,z=0.00000,col=FFFFFFFF] [-0.44,0.74,z=0.00000,col=FFFFFFFF] [-0.41,0.78,z=0.00000,col=FFFFFFFF] [-0.25,0.78,z=0.00000,col=FFFFFFFF] [-0.25,0.77,z=0.00000,col=FFFFFFFF] [-0.41,0.77,z=0.00000,col=FFFFFFFF] + 36 prim=13 indices=8 vs=0xE0BAFB4F520FE441 ps=0xE59B2B3DA4AA9008 blend=0x07010701[c:src=1 op=0 dst=7 a:src=1 op=0 dst=7] cc=0x8700000C mask=0xF tex[base=0x0C340000 1280x768 fmt=6] + vb=0x14DD4B50 stride=24 attrs=[57@0 6@12 37@16 ] fmt0=57 v: [-1.00,0.75,z=0.00000,col=FFFFFFFF] [-0.31,0.75,z=0.00000,col=FFFFFFFF] [-0.31,0.71,z=0.00000,col=FFFFFFFF] [-1.00,0.71,z=0.00000,col=FFFFFFFF] [-0.78,0.90,z=0.00000,col=FFFFFFFF] [-0.44,0.90,z=0.00000,col=FFFFFFFF] [-0.44,0.71,z=0.00000,col=FFFFFFFF] [-0.78,0.71,z=0.00000,col=FFFFFFFF] + 37 prim=8 indices=3 vs=0x72CBCAA6A7984111 ps=0xE59B2B3DA4AA9008 blend=0x07010701[c:src=1 op=0 dst=7 a:src=1 op=0 dst=7] cc=0x8700000C mask=0xF tex[base=0x10000000 1x1 fmt=26] + 38 prim=8 indices=3 vs=0x72CBCAA6A7984111 ps=0xE59B2B3DA4AA9008 blend=0x07010701[c:src=1 op=0 dst=7 a:src=1 op=0 dst=7] cc=0x8700000C mask=0xF tex[base=0x10000000 1x1 fmt=26] diff --git a/docs/re/data/blend-bit-prediction-result.txt b/docs/re/data/blend-bit-prediction-result.txt new file mode 100644 index 00000000..18735db3 --- /dev/null +++ b/docs/re/data/blend-bit-prediction-result.txt @@ -0,0 +1,51 @@ +# THE PREDICTION HELD. GP_OPTIONS, out of sample, a different archive. +# 2026-08-31. +# +# Committed before this capture, in data/blend-bit-prediction-gp-options.txt: +# "FALSIFIED IF: po_menu_eff01/02/03 draw alpha-over, or any other GP_OPTIONS +# element draws additive." +# +# GP_OPTIONS entry 19 -- the OPTIONS menu, reached from the main menu by (A) -- +# declares 16 sprites: 3 predicted ADDITIVE, 13 predicted alpha-over. +# +# MEASURED: 39 draws over 3 frames. Exactly THREE additive quads per frame, and +# they are po_menu_eff01, po_menu_eff02 and po_menu_eff03. Every other draw is +# alpha-over. Zero errors. + +=== GP_OPTIONS entry 19, the OPTIONS menu === +draw prim idx blend state quad px (w x h) best name match + 1 13 20 0x07010701 alpha-over(premul) 640.0 x 720.0 (no match, nearest po_menu_eff01.t32 [declared] off 2.5 quanta) + 1 13 20 0x07010701 alpha-over(premul) 320.0 x 360.0 po_menu_eff01.t32 [texture@2x] + 1 13 20 0x07010701 alpha-over(premul) 320.0 x 360.0 po_menu_eff01.t32 [texture@2x] + 1 13 20 0x07010701 alpha-over(premul) 320.0 x 360.0 po_menu_eff01.t32 [texture@2x] + 1 13 20 0x07010701 alpha-over(premul) 320.0 x 360.0 po_menu_eff01.t32 [texture@2x] + 2 13 8 0x01010101 ADDITIVE 627.2 x 720.0 po_menu_eff01.t32 [declared] + 2 13 8 0x01010101 ADDITIVE 486.4 x 511.2 po_menu_eff02.t32 [texture@2x] + 3 13 4 0x07010701 alpha-over(premul) 345.6 x 39.6 po_menu_msg.t32 [texture] + 4 13 4 0x01010101 ADDITIVE 358.4 x 388.8 po_menu_eff03.t32 [texture] + 5 13 4 0x07010701 alpha-over(premul) 57.6 x 57.6 (no match, nearest po_menu_btneff01.t32 [texture] off 5.7 quanta) + 6 13 8 0x07010701 alpha-over(premul) 256.0 x 54.0 po_menu_btn1f.t32 [texture] + 6 13 8 0x07010701 alpha-over(premul) 281.6 x 43.2 po_menu_btn2.t32 [texture] + 7 13 8 0x07010701 alpha-over(premul) 256.0 x 43.2 po_menu_btn3.t32 [texture] + 7 13 8 0x07010701 alpha-over(premul) 268.8 x 43.2 po_menu_btn2b.t32 [texture] + 8 13 4 0x07010701 alpha-over(premul) 102.4 x 43.2 po_menu_btn5.t32 [texture] + 9 13 12 0x07010701 alpha-over(premul) 128.0 x 3.6 (no match, nearest po_menu_btn5.t32 [texture] off 14.9 quanta) + 9 13 12 0x07010701 alpha-over(premul) 102.4 x 7.2 (no match, nearest po_menu_btn5.t32 [texture] off 10.0 quanta) + 9 13 12 0x07010701 alpha-over(premul) 102.4 x 3.6 (no match, nearest po_menu_btn5.t32 [texture] off 11.0 quanta) + 10 13 8 0x07010701 alpha-over(premul) 441.6 x 14.4 (no match, nearest po_menu_msg.t32 [declared] off 16.8 quanta) + 10 13 8 0x07010701 alpha-over(premul) 217.6 x 68.4 (no match, nearest po_menu_btn5.t32 [texture@2x] off 6.7 quanta) + 14 13 20 0x07010701 alpha-over(premul) 640.0 x 720.0 (no match, nearest po_menu_eff01.t32 [declared] off 2.5 quanta) + +=== blend histogram over the whole capture === + 3 blend=0x00010001 + 6 blend=0x01010101 + 30 blend=0x07010701 + +⚠️ WHAT IS AND IS NOT IDENTIFIED HERE + * the three ADDITIVE quads are named, and they are the three predicted ones. + * the alpha-over side is a COUNT, not 13 individual identifications: draw 1 is + a 20-index batch of tiled background quads at 320x360, a size several + elements share, so the matcher's label on those rows is a candidate. What is + measured is that no draw on the screen carries 0x01010101 except the three. + * that asymmetry is the right way round for a falsification: the prediction + would have died if a fourth additive draw existed, and none does. diff --git a/docs/re/structures/ui-blend-mode-decoded.md b/docs/re/structures/ui-blend-mode-decoded.md new file mode 100644 index 00000000..c4ab77ca --- /dev/null +++ b/docs/re/structures/ui-blend-mode-decoded.md @@ -0,0 +1,120 @@ +# 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*.