Applying my own lesson to my own corpus rather than only stating it. I
exported the content-hash patch and stopped; auditing the docs for
"/canary sha" citations found three pages naming d90d14e02, and checking
/canary's history found the exposure is four commits deep, not one.
Bounded by measurement rather than guess: branch -r --contains puts
590912722 on origin/sylpheed-re and finds no remote for anything after it,
so the container-only stack is exactly these four.
0f920e645 blend= per draw <- the ENTIRE blend decode rests on this
fa1e4c221 vertex dump 8 -> 64 <- at 8 the log silently dropped four
quads of the EXTRAS 24-index batch
d90d14e02 RT state, resolves, PS constants
ab3203f79 h= content hash
The sharpest case is 0f920e645. Without it a draw log records no blend
state at all, so ui-blend-mode-decoded.md's 35-element oracle -- which
overturned a REFUTED entry and deleted the port's authored blend map --
could not be re-derived by anyone who cloned this repository.
The failure mode is silent: the recipe LOOKS complete and only fails for
someone on a different machine, long after its author could say what the
flag did.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jc4pciRArGHfxGGhEbwp5t
59 lines
3.2 KiB
Diff
59 lines
3.2 KiB
Diff
From 0f920e645441f42d006a3d2635115ff9bcfb37b8 Mon Sep 17 00:00:00 2001
|
|
From: Sylpheed RE agent <agent@localhost>
|
|
Date: Mon, 31 Aug 2026 06:09:25 +0000
|
|
Subject: [PATCH 1/4] [RE] Log the blend state of every UI draw
|
|
|
|
CaptureUiDrawForRE now records RB_BLENDCONTROL0, RB_COLORCONTROL and
|
|
RB_COLOR_MASK per draw, raw alongside the decoded src/op/dst fields so a decode
|
|
bug here cannot quietly become the answer.
|
|
|
|
The question it answers: the Godot port composites every UI element with
|
|
straight alpha-over and four elements come out too dark against the capture,
|
|
with the shortfall correlating with the background. Nothing on the disc selects
|
|
a per-element mode, so this reads what the GPU was actually told. Result: the
|
|
title-side UI uses two states and one pixel shader -- 0x07010701 (src ONE, dst
|
|
1-SRC_ALPHA) for backgrounds, text and buttons, and 0x01010101 (src ONE, dst
|
|
ONE, ADDITIVE) for the frame sprites and the rotated sweep strips.
|
|
---
|
|
src/xenia/gpu/command_processor.cc | 27 +++++++++++++++++++++++++++
|
|
1 file changed, 27 insertions(+)
|
|
|
|
diff --git a/src/xenia/gpu/command_processor.cc b/src/xenia/gpu/command_processor.cc
|
|
index e350f1132..d389e299c 100644
|
|
--- a/src/xenia/gpu/command_processor.cc
|
|
+++ b/src/xenia/gpu/command_processor.cc
|
|
@@ -296,6 +296,33 @@ void CommandProcessor::CaptureUiDrawForRE(
|
|
if (ps) {
|
|
ui_out << fmt::format(" ps=0x{:016X}", ps->ucode_data_hash());
|
|
}
|
|
+ // ── RE: the BLEND STATE of this draw ──────────────────────────────────────
|
|
+ // The question this answers: the port's renderer composites every UI element
|
|
+ // with straight alpha-over, and four elements (the menu's `ptframe1`/`2` and
|
|
+ // EXTRAS' `ptframe3`/`4`) come out too dark against the capture, with the
|
|
+ // shortfall correlating with the BACKGROUND rather than with the element's own
|
|
+ // contribution — the signature of a blend that scales what is already there.
|
|
+ // Nothing on the disc selects a per-element mode (checked in the declaration
|
|
+ // entry, every word and bit of the T8aD header, and the keyframe record), so
|
|
+ // the remaining candidate is the draw path. This logs what the GPU was
|
|
+ // actually told, per draw, rather than inferring it:
|
|
+ // blend=<raw RB_BLENDCONTROL0> src/dst factors and combine op, colour+alpha
|
|
+ // cc=<raw RB_COLORCONTROL> alpha test / blend enable
|
|
+ // mask=<raw RB_COLOR_MASK>
|
|
+ // Raw values are printed alongside the decoded fields so a decode bug here
|
|
+ // cannot silently become the answer.
|
|
+ {
|
|
+ auto bc = register_file_->Get<reg::RB_BLENDCONTROL>();
|
|
+ auto cc = register_file_->Get<reg::RB_COLORCONTROL>();
|
|
+ uint32_t mask = register_file_->values[XE_GPU_REG_RB_COLOR_MASK];
|
|
+ ui_out << fmt::format(
|
|
+ " blend=0x{:08X}[c:src={} op={} dst={} a:src={} op={} dst={}]"
|
|
+ " cc=0x{:08X} mask=0x{:X}",
|
|
+ bc.value, uint32_t(bc.color_srcblend), uint32_t(bc.color_comb_fcn),
|
|
+ uint32_t(bc.color_destblend), uint32_t(bc.alpha_srcblend),
|
|
+ uint32_t(bc.alpha_comb_fcn), uint32_t(bc.alpha_destblend), cc.value,
|
|
+ mask);
|
|
+ }
|
|
if (ps && ps->is_ucode_analyzed()) {
|
|
for (const auto& tb : ps->texture_bindings()) {
|
|
xenos::xe_gpu_texture_fetch_t tf =
|