Files
Sylpheed/docs/re/data/input-ring-record-layout.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

33 lines
1.5 KiB
Plaintext

# C_PAD_RINGBUF output record -- the tail of sub_8220D500, read from
# /image/sylpheed.pe. r3 = the ringbuf; r9 = the XINPUT_GAMEPAD source.
# This is where a menu gets edge-vs-level, and it is one struct, not two paths.
8220D7C0 7D0A582E
8220D7C4 9103000C +12 <- cur : HELD (level)
8220D7C8 7D0A582E
8220D7CC 80E3000C
8220D7D0 7D083278 r8 = cur XOR prev : CHANGED
8220D7D4 91030010 +16 <- changed : (overwritten below)
8220D7D8 5508003E
8220D7DC 7CCA582E
8220D7E0 7D063078 r6 = changed ANDC cur : RELEASED this frame
8220D7E4 90C30014 +20 <- released : FALLING EDGE
8220D7E8 7D6A582E
8220D7EC 90E30018 +24 <- cur : HELD (second copy)
8220D7F0 7D0B5838 r11 = changed AND cur : PRESSED this frame
8220D7F4 91630010 +16 <- pressed : RISING EDGE (final value)
8220D7F8 8969002A
8220D7FC 9163001C +28 <- bLeftTrigger : RAW ANALOG byte
8220D800 8969002B
8220D804 91630020 +32 <- bRightTrigger : RAW ANALOG byte
8220D808 A169002C
8220D80C 7D6B0734
# So the ring record is:
# +12 buttons HELD (level) -- a menu that repeats on hold reads this
# +16 buttons PRESSED (rising) -- a menu that fires once per press reads this
# +20 buttons RELEASED (falling)
# +24 buttons HELD (copy)
# +28 bLeftTrigger raw 0..255, analog value preserved alongside the bit
# +32 bRightTrigger raw 0..255