D341 - Cross-port key conflicts were invisible, and a keyboard could not move a stick
decided · 2026-08-27 · found by review against a parallel implementation
Prosperous grew a controller model of its own, for sending input to real hardware, and reading the two side by side found three things here.
A keyboard could not move a stick at all.
Port mapped Button only, and the reader set
buttons and triggers and returned. Since the shipped configuration is
one keyboard port, the out-of-the-box setup could press seventeen
buttons and drive nothing analogue - which is most 3D titles, and
nothing said so.
Sticks are not buttons: a button is a bit and an axis is a number, so
they get their own table keyed by [Push] - one of eight
named directions, because a key is on or off and one key per axis could
only move it one way. Opposite pushes sum and clamp, so
left and right held together mean centre. Letting the first win would
make the pair mean something no pad can express.
A key bound on two ports was never reported, because
conflicts() built its seen-map inside the per-port loop.
That left two ways to add a second keyboard player: copy the first
port's layout, where all seventeen keys silently drive both pads and one
person moves two characters, or bind every one by hand. The docstring
already made the argument against the first - "a binding that half
works with nothing saying so" - and the cross-port case is the same
failure with a wider blast radius.
Worth recording as a deliberate disagreement, so
neither project gets "fixed" to match the other: this
PadState is host-shaped floats and does not guess the guest
layout, while prosperous's is unsigned bytes centred on 128 because that
layout has since been measured on hardware. Same question, different
evidence, both right for their own project.