diff --git a/docs/port/DECISIONS.md b/docs/port/DECISIONS.md index 2732e585..6068ca6c 100644 --- a/docs/port/DECISIONS.md +++ b/docs/port/DECISIONS.md @@ -9,7 +9,7 @@ dies, which is what this file is for. -328 sections. Search this before re-deriving anything. +330 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) @@ -339,6 +339,8 @@ dies, which is what this file is for. * [The residual map: no local displacement either, and the split I expected is not there](#the-residual-map-no-local-displacement-either-and-the-split-i-expected-is-not-there) * [Suppression beats coordinates: the menu residual is two frame elements, drawn too dark](#suppression-beats-coordinates-the-menu-residual-is-two-frame-elements-drawn-too-dark) * [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) ## P0 — the exporter, 2026-08-28 @@ -16013,3 +16015,73 @@ they locate the remaining question rather than closing it. ⚠️ Not settled: whether it is additive, screen, or something else — `+0.77` and `+0.80` say "scales with the background", not which curve. Two screens; I have not checked the title. + +## Which blend? Additive halves the error, on both frames — proposed, not adopted + +Last iteration ended with *"`+0.77` and `+0.80` say 'scales with the background', +not which curve."* That is decidable without any RE, because **an element rendered +over two different backgrounds gives two equations in `a` and `aC`**: + +``` +base - bg = a(C - bg ) the frame over background 1 +b2 - bg2 = a(C - bg2) the same frame over background 2 +-------------------------------------------------------------- +a = [(base-bg) - (b2-bg2)] / (bg2 - bg) aC = (base-bg) + a·bg +``` + +Both backgrounds are produced by the mod tree — suppress `pteff10`/`pteff12` and +the background under the frame changes by a mean of 26 levels. **No placement, no +coordinate transform, no texture decoding assumed.** + +### ✅ The control is exact, and it is what makes the rest usable + +Rebuilding **alpha-over** from the solved `a` and `aC` reproduces the port's actual +render at **RMSE 0.0000** on both screens. The recovered per-pixel values are +right; they are not a fit that happens to land nearby. + +### The result, replicated + +RMSE against the capture, all four candidates mapped the same way: + +| composite | `ptframe1` (`main_menu`) | `ptframe3` (`extras`) | +|---|---|---| +| **additive** | **34.305** | **28.948** | +| screen | 50.052 | 50.368 | +| **alpha-over — what the port does** | **65.046** | **71.299** | +| frame not drawn at all | 90.916 | 109.801 | + +📌 **Same ordering on both, and additive roughly halves alpha-over's error.** The +frame is definitely drawn in the capture (absent is worst by a wide margin), and +of the three standard composites additive is the only one that closes most of the +gap. Solved on 1 743 and 1 999 pixels; median `a` 0.429 and 0.594. + +### ⚠️ What this is not + +**Additive is not established as the answer.** It still leaves 28.9–34.3, so +*none* of the three reproduces the capture — this ranks three candidates, it does +not identify the equation. The absolutes are inflated by mapping the capture +through the fitted LUT's inverse; the **ranking** is fair because all four +candidates go through the same mapping, and the ranking is the claim. Grayscale +only. + +🔴 **And I have not adopted it.** The Decoder established that nothing on the disc +selects a blend for `.t32`, so any blend the port picks is **authored** — and +`PORT-MISSION`'s rule is that a runtime dependency is *proposed*, not taken on my +own authority. The renderer is unchanged. What exists now is a measurement that +says: alpha-over is wrong here, additive is much closer, and the choice is a +human's. + +## Refutation attempt: the Decoder's kind-0 claim survives, checked from my own data + +They reported both frames as **kind 0, identical to `ptbase`, `pteff05`, `pteff10`, +`pteff12` and `ptmsg`** — read off the 60-byte `.t32` declaration. + +My exporter decodes that field independently and stores it as `kind_raw`. Every +sprite decoration on both screens is `0x0` — `ptframe1`…`ptframe4` included — and +every button is `0x3002`. ✅ **Survives.** Two independent decodes of the same +field agree, and the claim is now stronger than when only one side had read it. + +📌 That matters because it is what makes the blend question sharp: the frames are +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.