Files
Sylpheed/docs/re/data/input-decoder-output-map.txt
sylph-decoder 1e388d0176 re: the pad word is REMAPPED -- my own bit table was mislabelled throughout
input-pad-read-path.md says of the word the C_PAD_DECODER reads: "There is
no shift and no remap on the way in -- the bit positions are XINPUT's own."
That is wrong. sub_8220D500 rebuilds the word out of XINPUT_GAMEPAD before
anything else sees it, into the game's own numbering.

  bits  0-3   A B X Y
  bits  4-7   left stick  UP DOWN LEFT RIGHT   (+/-20000 of 32767)
  bits  8-11  right stick UP DOWN LEFT RIGHT
  bits 12-15  D-pad       UP DOWN LEFT RIGHT
  bits 16-17  START, BACK
  bits 18-19  LB, RB
  bits 20-21  LT, RT  -- digital, threshold >220 of 255
  bits 22-23  L3, R3

Extracted mechanically from the image, no row typed by hand. The control is
the shape of the result: the 24 assignments land on bits 0..23, each used
exactly once, none repeated. A misdecode does not produce a bijection over a
contiguous range, and coincidence does not put the stick and D-pad
directions in the same order in two aligned nibbles.

So every mask in that page's tables names the wrong button. The 0xE000 x18
site, read there as "B | X | Y", is "D-pad DOWN | LEFT | RIGHT" -- eighteen
sites testing a menu cursor, which is what 18 sites should be.

And its headline negative is REFUTED: "LB and RB are not menu inputs" is
false. They are bound at config fields this+0x70 and this+0x84, LT/RT at
+0x74/+0x80. The negative was searched for 0x0100/0x0200 -- LB and RB in
XINPUT's numbering -- in a word where they live at 0x40000/0x80000. Right
function, right buttons, wrong bit positions, so it could only come back
empty. A negative is only as good as the numbering it was searched in.

Also decodes the ring record: +12 HELD, +16 PRESSED, +20 RELEASED, +28/+32
raw trigger bytes. Edge and level are one struct four bytes apart, which
displaces that page's guess that press-vs-hold was split between GetState
and the XamInputGetKeystrokeEx queue.

The superset claim in that page survives and is untouched: sub_82457038
really does compare every XINPUT_GAMEPAD field, and it really is
XINPUT-layout. This page depends on it.

Not decoded: which output bit means which ACTION, and per-screen sets. 5 of
18 output-bit sites did not resolve to a pad guard, so the output map is a
lower bound -- in particular "START is not tested" is NOT claimed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jc4pciRArGHfxGGhEbwp5t
2026-09-01 18:33:42 +00:00

53 lines
1.9 KiB
Plaintext

# C_PAD_DECODER: what sets each bit of the OUTPUT word at this+0x24C.
# Guards are in the RING word's numbering (see ringmap.txt), NOT XINPUT's.
# 'cfg +0xNN' = a REMAPPABLE binding written by the ctor sub_8220B610
# 'literal' = a mask hard-coded in the update sub_8220B8C0
# '(internal)'= guarded by decoder state, not by a pad bit, in this window
site out bit guard means
8220BBB0 0x000004 (internal) -
8220BE78 0x002000 cfg +0x90 R3
8220BEBC 0x000002 cfg +0x84 RB
8220BF00 0x000001 cfg +0x80 RT>220
8220BFB8 0x000800 cfg +0x74 LT>220
8220C0B0 0x000800 cfg +0x70 LB
8220C118 0x000020 (internal) -
8220C13C 0x000040 (internal) -
8220C2F0 0x000010 cfg +0xA0 B
8220C338 0x000100 cfg +0x7C X
8220C37C 0x200000 cfg +0xA4 DPAD DOWN
8220C404 0x010000 cfg +0x98 BACK
8220C458 0x040000 literal LS LEFT
8220C474 0x080000 literal LS RIGHT
8220C490 0x000200 literal LS UP
8220C4AC 0x000400 literal LS DOWN
8220C4EC 0x100000 (internal) -
8220CB48 0x000008 (internal) -
# 13 of 18 output bits resolve to a pad guard.
# every config field the ctor sets to a ring-word button set:
# +0x4C = 0x00000100 RS UP
# +0x64 = 0x00000001 A
# +0x70 = 0x00040000 LB
# +0x74 = 0x00100000 LT>220
# +0x7C = 0x00000004 X
# +0x80 = 0x00200000 RT>220
# +0x84 = 0x00080000 RB
# +0x8C = 0x00400000 L3
# +0x90 = 0x00800000 R3
# +0x94 = 0x00000001 A
# +0x98 = 0x00020000 BACK
# +0x9C = 0x00000008 Y
# +0xA0 = 0x00000002 B
# +0xA4 = 0x00002000 DPAD DOWN
# +0xAC = 0x00000014 X | LS UP
# +0xB4 = 0x0000000A B | Y
# +0xB8 = 0x0000005A B | Y | LS UP | LS LEFT
# +0xBC = 0x0000000A B | Y
# +0xC0 = 0x0000005A B | Y | LS UP | LS LEFT
# +0xC4 = 0x0000000A B | Y
# +0xC8 = 0x00000008 Y
# +0xD4 = 0x00000002 B
# +0xD8 = 0x00000078 Y | LS UP | LS DOWN | LS LEFT