port: Ⓐ was never bound to the pad, and the stick is not an edge

Both found by a human playing the port on a real controller. Both were
invisible to every check this port has, for one reason:

  `--script` sends InputEventAction, which BYPASSES the input map.

So the harness asserted every line of code AFTER the map and nothing about the
map itself. Measured on this Godot, not remembered -- the remembered answer was
wrong:

  ui_accept   key:Enter, key:Kp Enter, key:Space     <- no joypad at all
  ui_cancel   key:Escape                             <- no joypad at all
  ui_up       key:Up, JOYBTN:11, JOYAXIS:1-          <- d-pad AND left stick
  ui_down     key:Down, JOYBTN:12, JOYAXIS:1+

Four actions worked on the pad and two did not, which presents as a broken
controller: navigation moved, Ⓐ skipped nothing and opened nothing. Godot
4.7.2 binds no joypad button to ui_accept or ui_cancel.

Gamepad.bind_missing() ADDS the two buttons to the built-in actions rather than
redefining them in project.godot, which would replace the built-ins wholesale
and drop the keyboard bindings silently.

Second defect, same blind spot: an InputEventAction is not an analog axis. The
left stick is bound to axis 1, and an axis is not an edge -- held at deflection
it emits an event per jitter, each reporting the action pressed. That was one
cursor step per jitter ("moves the cursor too fast"). The stick is now latched
to one step per deflection, with hysteresis so a stick resting near the
threshold does not chatter.

AUTHORED, and deliberately the conservative half: whether the game REPEATS a
held direction, and how fast, is an oracle question. One deflection one step
cannot run away and invents no rate. Logged as BLOCKED H1.

tools/port/verify-input asserts the map and the latch, with a control that
removes each check's OWN subject -- its first version inverted all nine
assertions when only two depended on the fixup, and reported seven correct
checks as broken. Three rows say plainly they are not controllable (they assert
Godot's own bindings) and one is a negative carrying a positive control (R4),
rather than faking an inversion for either.

Also logged BLOCKED H2, unguessed: the splash blur/fade-in is more pronounced
in the game than in the port. The port applies no blur at all. Noted there that
the two splashes are the only screens reaching the rest() plateau-less
fallback, which the R1 pass just re-opened in both directions.
This commit is contained in:
MechaCat02
2026-09-01 17:45:36 +02:00
parent 0f1b11920c
commit 72f116a3b4
6 changed files with 433 additions and 0 deletions

View File

@@ -103,6 +103,16 @@ func _ready() -> void:
if args.has(flag) and not _has_display(flag):
get_tree().quit(4)
return
# 🔴 BEFORE ANYTHING ELSE, and announced. Godot 4.7.2 binds no joypad button
# to `ui_accept` or `ui_cancel`, so on a real pad Ⓐ and Ⓑ did nothing while
# navigation worked — which reads as a broken controller. `Gamepad` explains
# it. Both lines are printed because "the pad is seen" and "Ⓐ is bound" are
# different facts and the human debugging this needs to separate them.
var _pad_bound := Gamepad.bind_missing()
if _pad_bound != "":
print(_pad_bound)
print(Gamepad.report_devices())
var export_tree := ExportTree.locate()
_tree = export_tree
if export_tree.root == "":
@@ -400,6 +410,8 @@ func _ready() -> void:
var _frozen := false
## Holds the left stick's latch state. See `gamepad.gd`.
var _pad := Gamepad.new()
var _flow: Variant = null
var _menu: MenuFlow = null
var _play := false
@@ -774,6 +786,13 @@ func _report_unused_mods() -> void:
func _unhandled_input(event: InputEvent) -> void:
# The left stick is bound to ui_up/ui_down by Godot's own defaults, and an
# analog axis is not an edge: held at deflection it emits an event per
# jitter, each reporting the action as pressed. `accepts()` latches it to one
# step per deflection. Everything already edge-shaped passes through
# untouched. See `gamepad.gd` -- including what is authored about it.
if not _pad.accepts(event):
return
# HANDOFF Q9, measured: one (A) press skips a movie -- the title was reached
# at 57 s against a 193 s baseline.
if _player != null: