Closes the one route t32-blend-mode-not-on-disc.md left open: the executable's
draw path. Canary's UI draw capture now logs RB_BLENDCONTROL0 per draw, and the
game was driven to the main menu and to EXTRAS with F10 at each.
The title-side UI uses two blend states and ONE pixel shader:
0x07010701 src=ONE dst=1-SRC_ALPHA alpha-over (premultiplied)
ptbase, pteff05, the fade quad, ptmsg, ptmsg2, pttitle, buttons
0x01010101 src=ONE dst=ONE ADDITIVE
ptframe1, ptframe2, ptframe3, pteff20, both rotated sweep strips
Two controls, both run before the result was read:
* the NDC->pixel conversion that identifies a draw by its quad size reproduces
1134 and 1303 px for the two rotated sweep strips -- numbers measured by a
different tool in a different session -- on BOTH screens. The tool prints
PASS/FAIL and disclaims its own output on FAIL.
* pixel shader 0xE59B2B3DA4AA9008 is used with BOTH states, 12 draws additive
and 18 alpha-over. ptframe1 and ptbase run the same shader; only the blend
register differs. So this is a blend result, not a shader result.
This confirms the port's independent measurement -- it solved the composite per
pixel from two backgrounds and found additive halves alpha-over's error on both
frames -- by a route with nothing in common with it.
So the blend is no longer authored: 'any blend you choose is authored' was true
of the disc and is not true of the game. What is still unknown is which field
selects it; elements sharing a mode are batched into one draw call, so the
selection happens before the draw.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
110 lines
7.7 KiB
Plaintext
110 lines
7.7 KiB
Plaintext
# The UI blend mode, MEASURED from the running game. 2026-08-31.
|
|
#
|
|
# Question: the port's renderer composites every UI element with straight
|
|
# alpha-over, and four elements come out too dark against the capture --
|
|
# ptframe1/ptframe2 on the main menu and ptframe3/ptframe4 on EXTRAS -- with the
|
|
# shortfall correlating with the BACKGROUND. Nothing on the disc selects a
|
|
# per-element mode (docs/re/structures/t32-blend-mode-not-on-disc.md, reach:
|
|
# declaration entry, T8aD header word- and bit-wise, keyframe record).
|
|
#
|
|
# Method: Canary's CaptureUiDrawForRE was extended to log RB_BLENDCONTROL0,
|
|
# RB_COLORCONTROL and RB_COLOR_MASK per draw. One emulator, driven to the main
|
|
# menu and then to EXTRAS, F10 at each. Elements are identified by the PIXEL SIZE
|
|
# of their quad (NDC extents x the 1280x720 surface) against sprite dimensions
|
|
# read off the disc -- the log names no elements.
|
|
#
|
|
# Xenos enum (xenos.h): BlendFactor kZero=0 kOne=1 kSrcAlpha=6 kOneMinusSrcAlpha=7;
|
|
# BlendOp kAdd=0. RB_BLENDCONTROL0 = src | op<<5 | dst<<8, colour in the low half
|
|
# and alpha in the high half.
|
|
#
|
|
# 0x00010001 src=ONE dst=ZERO opaque -- blending effectively off
|
|
# 0x07010701 src=ONE dst=ONE_MINUS_SRC_A alpha-over, PREMULTIPLIED (src is ONE)
|
|
# 0x01010101 src=ONE dst=ONE ADDITIVE
|
|
#
|
|
# CONTROL, run before reading anything below: the two rotated sweep strips were
|
|
# measured independently at 1134 and 1303 px tall
|
|
# (docs/re/data/title-sweep-drawn-at-rest.txt). The NDC->pixel conversion here
|
|
# reproduces BOTH, on BOTH screens. The tool prints PASS/FAIL and refuses to be
|
|
# trusted otherwise.
|
|
#
|
|
# SECOND CONTROL, and it is the one that makes this a blend result rather than a
|
|
# shader result: ONE pixel shader, 0xE59B2B3DA4AA9008, is used with BOTH states
|
|
# on the main menu -- 12 draws additive and 18 alpha-over. The frames and ptbase
|
|
# run the same shader. Only the blend register differs.
|
|
|
|
=== main menu (GP_TITLE build 5), 36 draws over 5 frames ===
|
|
draw prim idx blend state quad px (w x h) best name match
|
|
1 13 4 0x07010701 alpha-over(premul) 1280.0 x 720.0 ptbase.t32 @2x
|
|
2 13 8 0x01010101 ADDITIVE 889.6 x 1134.0 (no match, nearest pteff12.t32 @2x off 610)
|
|
2 13 8 0x01010101 ADDITIVE 1299.2 x 1303.2 (no match, nearest ptbase.t32 @2x off 602)
|
|
3 13 4 0x07010701 alpha-over(premul) 1280.0 x 720.0 ptbase.t32 @2x
|
|
4 13 4 0x07010701 alpha-over(premul) 1280.0 x 720.0 ptbase.t32 @2x
|
|
5 13 4 0x01010101 ADDITIVE 819.2 x 720.0 (no match, nearest pteff12.t32 @2x off 125)
|
|
6 13 4 0x01010101 ADDITIVE 691.2 x 720.0 pteff12.t32 @2x
|
|
7 13 8 0x01010101 ADDITIVE 243.2 x 280.8 ptframe1.t32 @1x
|
|
7 13 8 0x01010101 ADDITIVE 256.0 x 309.6 ptframe2.t32 @1x
|
|
8 13 4 0x07010701 alpha-over(premul) 224.0 x 39.6 ptmsg.t32 @1x
|
|
9 13 24 0x07010701 alpha-over(premul) 51.2 x 46.8 (no match, nearest ptbtneff01.t32 @1x off 10)
|
|
9 13 24 0x07010701 alpha-over(premul) 211.2 x 54.0 ptbtn01f.t32 @1x
|
|
13 13 4 0x07010701 alpha-over(premul) 1280.0 x 720.0 ptbase.t32 @2x
|
|
14 13 8 0x01010101 ADDITIVE 889.6 x 1134.0 (no match, nearest pteff12.t32 @2x off 610)
|
|
14 13 8 0x01010101 ADDITIVE 1299.2 x 1303.2 (no match, nearest ptbase.t32 @2x off 602)
|
|
15 13 4 0x07010701 alpha-over(premul) 1280.0 x 720.0 ptbase.t32 @2x
|
|
16 13 4 0x07010701 alpha-over(premul) 1280.0 x 720.0 ptbase.t32 @2x
|
|
17 13 4 0x01010101 ADDITIVE 819.2 x 720.0 (no match, nearest pteff12.t32 @2x off 125)
|
|
18 13 4 0x01010101 ADDITIVE 691.2 x 720.0 pteff12.t32 @2x
|
|
19 13 8 0x01010101 ADDITIVE 243.2 x 280.8 ptframe1.t32 @1x
|
|
19 13 8 0x01010101 ADDITIVE 256.0 x 309.6 ptframe2.t32 @1x
|
|
20 13 4 0x07010701 alpha-over(premul) 224.0 x 39.6 ptmsg.t32 @1x
|
|
21 13 24 0x07010701 alpha-over(premul) 64.0 x 61.2 (no match, nearest ptbtneff01.t32 @1x off 37)
|
|
21 13 24 0x07010701 alpha-over(premul) 211.2 x 54.0 ptbtn01f.t32 @1x
|
|
25 13 4 0x07010701 alpha-over(premul) 1280.0 x 720.0 ptbase.t32 @2x
|
|
26 13 8 0x01010101 ADDITIVE 889.6 x 1134.0 (no match, nearest pteff12.t32 @2x off 610)
|
|
26 13 8 0x01010101 ADDITIVE 1299.2 x 1303.2 (no match, nearest ptbase.t32 @2x off 602)
|
|
27 13 4 0x07010701 alpha-over(premul) 1280.0 x 720.0 ptbase.t32 @2x
|
|
28 13 4 0x07010701 alpha-over(premul) 1280.0 x 720.0 ptbase.t32 @2x
|
|
29 13 4 0x01010101 ADDITIVE 819.2 x 720.0 (no match, nearest pteff12.t32 @2x off 125)
|
|
30 13 4 0x01010101 ADDITIVE 691.2 x 720.0 pteff12.t32 @2x
|
|
31 13 8 0x01010101 ADDITIVE 243.2 x 280.8 ptframe1.t32 @1x
|
|
31 13 8 0x01010101 ADDITIVE 256.0 x 309.6 ptframe2.t32 @1x
|
|
32 13 4 0x07010701 alpha-over(premul) 224.0 x 39.6 ptmsg.t32 @1x
|
|
33 13 24 0x07010701 alpha-over(premul) 51.2 x 54.0 (no match, nearest ptbtneff01.t32 @1x off 17)
|
|
33 13 24 0x07010701 alpha-over(premul) 211.2 x 54.0 ptbtn01f.t32 @1x
|
|
|
|
CONTROL — the two rotated sweep strips measured independently at 1134 and 1303 px:
|
|
tall quads found: ['1134', '1303']
|
|
PASS
|
|
|
|
=== EXTRAS (GP_TITLE build 6), 22 draws over 4 frames ===
|
|
draw prim idx blend state quad px (w x h) best name match
|
|
1 13 4 0x07010701 alpha-over(premul) 1280.0 x 720.0 ptbase.t32 @2x
|
|
2 13 4 0x01010101 ADDITIVE 883.2 x 1134.0 (no match, nearest ptbase.t32 @2x off 811)
|
|
3 13 4 0x01010101 ADDITIVE 1299.2 x 1303.2 (no match, nearest ptbase.t32 @2x off 602)
|
|
4 13 4 0x07010701 alpha-over(premul) 1280.0 x 720.0 ptbase.t32 @2x
|
|
5 13 4 0x07010701 alpha-over(premul) 1280.0 x 720.0 ptbase.t32 @2x
|
|
6 13 4 0x01010101 ADDITIVE 819.2 x 720.0 (no match, nearest pteff03.t32 @2x off 381)
|
|
7 13 24 0x01010101 ADDITIVE 614.4 x 518.4 pteff20.t32 @2x
|
|
7 13 24 0x01010101 ADDITIVE 243.2 x 219.6 ptframe3.t32 @1x
|
|
8 13 24 0x07010701 alpha-over(premul) 352.0 x 39.6 ptmsg2.t32 @1x
|
|
8 13 24 0x07010701 alpha-over(premul) 179.2 x 32.4 pttitle.t32 @1x
|
|
12 13 4 0x07010701 alpha-over(premul) 1280.0 x 720.0 ptbase.t32 @2x
|
|
13 13 4 0x01010101 ADDITIVE 889.6 x 1134.0 (no match, nearest ptbase.t32 @2x off 804)
|
|
14 13 4 0x01010101 ADDITIVE 1299.2 x 1303.2 (no match, nearest ptbase.t32 @2x off 602)
|
|
15 13 4 0x07010701 alpha-over(premul) 1280.0 x 720.0 ptbase.t32 @2x
|
|
16 13 4 0x07010701 alpha-over(premul) 1280.0 x 720.0 ptbase.t32 @2x
|
|
17 13 4 0x01010101 ADDITIVE 819.2 x 720.0 (no match, nearest pteff03.t32 @2x off 381)
|
|
18 13 24 0x01010101 ADDITIVE 614.4 x 518.4 pteff20.t32 @2x
|
|
18 13 24 0x01010101 ADDITIVE 243.2 x 219.6 ptframe3.t32 @1x
|
|
19 13 24 0x07010701 alpha-over(premul) 352.0 x 39.6 ptmsg2.t32 @1x
|
|
19 13 24 0x07010701 alpha-over(premul) 179.2 x 32.4 pttitle.t32 @1x
|
|
|
|
CONTROL — the two rotated sweep strips measured independently at 1134 and 1303 px:
|
|
tall quads found: ['1134', '1303']
|
|
PASS
|
|
|
|
=== shader x blend cross-tab, main menu ===
|
|
3 ps=0x2E372EA28CC404B7 blend=0x00010001
|
|
3 ps=0x5773DC18083C4C20 blend=0x07010701
|
|
12 ps=0xE59B2B3DA4AA9008 blend=0x01010101
|
|
18 ps=0xE59B2B3DA4AA9008 blend=0x07010701
|