fix(prompts): the Keyboard prompts show the movement keys as they are bound #529

Open
jarynclouatre wants to merge 1 commit from jarynclouatre/Longshot:fix/keyboard-move-key-pictures into main
Contributor

Type: fix · Risk: low · Tested on: Linux x86-64 (game-free checks only) · Needs: none

Why

With Button prompts on Keyboard, the left stick's icons always show W, A, S and D.

The pictures are fixed at the build (nx2/prompt_draw.py keyboard_glyphs, from prompt_keys.MOVE), cmap4_bind in host/prompts.c always points the stick codes at them, and current_binds reads only the Switch buttons' controls.

Found reading host/prompts.c and nx2/prompt_draw.py against the Controls page's movement rows.

How to reproduce

Seen on: found reading host/prompts.c and nx2/prompt_draw.py; not seen in the game. Game-free checks on Linux x86-64.
Settings and switches: Button prompts on Keyboard; Move up bound to I on the Controls page.
Steps: Look at a prompt for "stick up" after binding Move up to I. Restart, or change a movement key while the game runs.
Expected: The prompt shows the bound movement key, at the start and after a change while the game runs.
Actual: Bind Move up to I on the Controls page and a prompt for "stick up" still shows W, which no longer moves Link. A restart doesn't change it, and a movement key changed while the game runs isn't noticed at all.

What changed

Keyboard prompts follow the movement keys on the Controls page, including changes while the game runs. A single direction shows its key when the font has an icon; other changed directions fall back to the game's stick icon.

  • prompts (host/prompts.c): a new stick_shows(i, move) says what each stick icon shows on the Keyboard face from the first key of Move up, down, left and right:
    • an icon whose directions are all on the default keys keeps the build's picture, as today;
    • an icon for one direction on another key shows that key's icon;
    • an icon for several directions (W A S D, W S, A D) with any of them on another key shows the game's own stick icon, since the font has no picture of other keys together. The same goes for a direction with no key, or on a key the font has no icon for;
    • the right stick's icons keep the mouse pictures.
  • cmap4_bind uses it for the font served at the start and after a change.
  • text_code uses it for texts rewritten after a change while the game runs. A direction on a non-default key takes a code of its own from the existing key_slot codes, the way a button on a key does, because the game keeps each code's glyph as first drawn. text_code maps such a code back to its stick, so a later change or another face still finds it.
  • current_binds carries the four movement keys after the buttons' controls (BINDS grows by 4), so hos_prompts_live sees a movement key change and serves the font again. The textures and the layouts compare only the buttons' part (BUTTON_BINDS), and the textures' cache key hashes only that part, so a movement key change rewrites neither and no player's cache is written again because of this change.
  • docs (README.md, nx2/prompt_keys.py): the Button prompts paragraph and the table's comment say what the stick icons show now.
  • tests (tests/test_prompt_font_bind.py): the stand-in controls have the four movement rows with both slots, and the test cmap has the icons for W, A, S, D and I. Five sets of movement keys (the defaults, up on I, up on I in the second slot only, up on a key without an icon, up unbound) are checked through the real cmap4_bind, text_code and current_binds. One text's up icon is followed through W, I, E, W and a pad's face. stick_ways and move_default are compared with prompt_keys.STICKS and MOVE. The stand-in key_slot now refuses a key without an icon, as the real one does.

Measurements

Verdict: the movement-key prompt check fails on main and passes here; the suite has the same three failures on both sides.

Hardware: none used (game-free checks on a Linux x86-64 PC, gcc 15.2, Python 3.14)
Scene: none, the game was not run
Method: 2026-11-14; branch fix/keyboard-move-key-pictures. python3 -I -B tests/run_all.py --jobs 4 --timeout 120, main and this PR in turn, two runs each. The branch's tests/test_prompt_font_bind.py was also run over main's host/prompts.c.
How to reproduce: the commands above in a checkout of each commit

Before: main @ 543846eb After: this PR @ a8bd1592
tests/run_all.py (run 1, run 2) 484 passed, 3 failed, 84 skipped (both) 484 passed, 3 failed, 84 skipped (both)
failing checks test_bake_portability.py, test_crash_record.py, test_walk_key.py the same three
the branch's tests/test_prompt_font_bind.py FAIL: the keyboard face, up on I: stick icon 1 (U+E052, u) on glyph 987, not 973 pass

In the test's cmap glyph 987 is W's icon and 973 is I's. test_bake_portability.py fails here for a missing Python module (zstandard). test_walk_key.py's fixture doesn't link on main (undefined reference to hos_oot_autoload_input). test_crash_record.py stopped in all four runs at assert child.wait(timeout=10) == -signo, a signalled child's exit status on this PC.

Flags and settings

None.

Testing

Tested: the game-free suite on a Linux PC, as in Measurements; the test compiles first_key, current_binds, stick_shows, cmap4_bind, bind_font and text_code from host/prompts.c with gcc. host/prompts.c compiles (-fsyntax-only -Wall -Wextra) with llvm-mingw 20261104's x86_64-w64-mingw32-clang with no warnings, and whole with gcc in tests/test_mods_size_table.py's fixture.

Not tested: the game. A look at a prompt with the left stick's icon after binding Move up to another key, at the start and while the game runs, would show it.

No screenshots taken: the game was not run.

Must be tested: None.

Risks

What could break: Each direction on a non-default key takes one of the 320 key_slot codes per key it was seen on.

The change touches current_binds on the line under the one #485 changes; whichever lands second needs a two-line rebase.

Turning it off: Reverting the commit puts the fixed pictures back.

Compatibility: With the default movement keys every icon and every text code is what main gives. Only a movement key bound to something else shows something new. An icon for several directions then falls back to the game's stick icon instead of a picture of the new keys; drawing those would be a build-side change.

Checklist

Everyone

  • One topic.
  • The title is a Conventional Commit (type(scope): description) of the status line's type.
  • Why gives the reason plainly and links the issues that fit (the tracker searched).
  • Measurements has a verdict, or one line saying why there is nothing to measure.
  • Testing names what was tested, what wasn't, and what must still be tested, where and how.
  • Rebased on current main.
  • python -I -B tests/run_all.py passes (any failure that also fails on main is named).
  • No game files, dumps, build output or generated files.
  • third_party/ untouched (a new folder with a PROVENANCE.md instead).
  • The license is OK: GPL-3.0-or-later, nothing incompatible and nothing decompiled.

When it applies

  • Numbers from the same PC, scene and settings, at least 2 interleaved runs each, the median reported.
  • A game-free test added for the fix, failing on main and passing here.
  • A check under tests/ that reads changed source updated in this PR, not weakened.
  • Host code builds on both Windows (llvm-mingw) and Linux, with UTF-8 paths.
  • Docs updated.
**Type:** fix · **Risk:** low · **Tested on:** Linux x86-64 (game-free checks only) · **Needs:** none ## Why With Button prompts on Keyboard, the left stick's icons always show W, A, S and D. The pictures are fixed at the build (`nx2/prompt_draw.py` `keyboard_glyphs`, from `prompt_keys.MOVE`), `cmap4_bind` in `host/prompts.c` always points the stick codes at them, and `current_binds` reads only the Switch buttons' controls. Found reading `host/prompts.c` and `nx2/prompt_draw.py` against the Controls page's movement rows. ## How to reproduce **Seen on:** found reading `host/prompts.c` and `nx2/prompt_draw.py`; not seen in the game. Game-free checks on Linux x86-64. **Settings and switches:** Button prompts on Keyboard; Move up bound to I on the Controls page. **Steps:** Look at a prompt for "stick up" after binding Move up to I. Restart, or change a movement key while the game runs. **Expected:** The prompt shows the bound movement key, at the start and after a change while the game runs. **Actual:** Bind Move up to I on the Controls page and a prompt for "stick up" still shows W, which no longer moves Link. A restart doesn't change it, and a movement key changed while the game runs isn't noticed at all. ## What changed Keyboard prompts follow the movement keys on the Controls page, including changes while the game runs. A single direction shows its key when the font has an icon; other changed directions fall back to the game's stick icon. - prompts (`host/prompts.c`): a new `stick_shows(i, move)` says what each stick icon shows on the Keyboard face from the first key of Move up, down, left and right: - an icon whose directions are all on the default keys keeps the build's picture, as today; - an icon for one direction on another key shows that key's icon; - an icon for several directions (W A S D, W S, A D) with any of them on another key shows the game's own stick icon, since the font has no picture of other keys together. The same goes for a direction with no key, or on a key the font has no icon for; - the right stick's icons keep the mouse pictures. - `cmap4_bind` uses it for the font served at the start and after a change. - `text_code` uses it for texts rewritten after a change while the game runs. A direction on a non-default key takes a code of its own from the existing `key_slot` codes, the way a button on a key does, because the game keeps each code's glyph as first drawn. `text_code` maps such a code back to its stick, so a later change or another face still finds it. - `current_binds` carries the four movement keys after the buttons' controls (`BINDS` grows by 4), so `hos_prompts_live` sees a movement key change and serves the font again. The textures and the layouts compare only the buttons' part (`BUTTON_BINDS`), and the textures' cache key hashes only that part, so a movement key change rewrites neither and no player's cache is written again because of this change. - docs (`README.md`, `nx2/prompt_keys.py`): the Button prompts paragraph and the table's comment say what the stick icons show now. - tests (`tests/test_prompt_font_bind.py`): the stand-in controls have the four movement rows with both slots, and the test cmap has the icons for W, A, S, D and I. Five sets of movement keys (the defaults, up on I, up on I in the second slot only, up on a key without an icon, up unbound) are checked through the real `cmap4_bind`, `text_code` and `current_binds`. One text's up icon is followed through W, I, E, W and a pad's face. `stick_ways` and `move_default` are compared with `prompt_keys.STICKS` and `MOVE`. The stand-in `key_slot` now refuses a key without an icon, as the real one does. ## Measurements **Verdict:** the movement-key prompt check fails on main and passes here; the suite has the same three failures on both sides. Hardware: none used (game-free checks on a Linux x86-64 PC, gcc 15.2, Python 3.14) Scene: none, the game was not run Method: 2026-11-14; branch `fix/keyboard-move-key-pictures`. `python3 -I -B tests/run_all.py --jobs 4 --timeout 120`, main and this PR in turn, two runs each. The branch's `tests/test_prompt_font_bind.py` was also run over main's `host/prompts.c`. How to reproduce: the commands above in a checkout of each commit | | Before: main @ 543846eb | After: this PR @ a8bd1592 | |---|---|---| | `tests/run_all.py` (run 1, run 2) | 484 passed, 3 failed, 84 skipped (both) | 484 passed, 3 failed, 84 skipped (both) | | failing checks | `test_bake_portability.py`, `test_crash_record.py`, `test_walk_key.py` | the same three | | the branch's `tests/test_prompt_font_bind.py` | `FAIL: the keyboard face, up on I: stick icon 1 (U+E052, u) on glyph 987, not 973` | pass | In the test's cmap glyph 987 is W's icon and 973 is I's. `test_bake_portability.py` fails here for a missing Python module (zstandard). `test_walk_key.py`'s fixture doesn't link on main (`undefined reference to hos_oot_autoload_input`). `test_crash_record.py` stopped in all four runs at `assert child.wait(timeout=10) == -signo`, a signalled child's exit status on this PC. ### Flags and settings None. ## Testing **Tested:** the game-free suite on a Linux PC, as in Measurements; the test compiles `first_key`, `current_binds`, `stick_shows`, `cmap4_bind`, `bind_font` and `text_code` from `host/prompts.c` with gcc. `host/prompts.c` compiles (`-fsyntax-only -Wall -Wextra`) with llvm-mingw 20261104's x86_64-w64-mingw32-clang with no warnings, and whole with gcc in `tests/test_mods_size_table.py`'s fixture. **Not tested:** the game. A look at a prompt with the left stick's icon after binding Move up to another key, at the start and while the game runs, would show it. No screenshots taken: the game was not run. **Must be tested:** None. ## Risks **What could break:** Each direction on a non-default key takes one of the 320 `key_slot` codes per key it was seen on. The change touches `current_binds` on the line under the one #485 changes; whichever lands second needs a two-line rebase. **Turning it off:** Reverting the commit puts the fixed pictures back. **Compatibility:** With the default movement keys every icon and every text code is what main gives. Only a movement key bound to something else shows something new. An icon for several directions then falls back to the game's stick icon instead of a picture of the new keys; drawing those would be a build-side change. ## Checklist ### Everyone - [x] One topic. - [x] The title is a Conventional Commit (`type(scope): description`) of the status line's type. - [x] Why gives the reason plainly and links the issues that fit (the tracker searched). - [x] Measurements has a verdict, or one line saying why there is nothing to measure. - [x] Testing names what was tested, what wasn't, and what must still be tested, where and how. - [x] Rebased on current `main`. - [x] `python -I -B tests/run_all.py` passes (any failure that also fails on `main` is named). - [x] No game files, dumps, build output or generated files. - [x] `third_party/` untouched (a new folder with a `PROVENANCE.md` instead). - [x] The license is OK: GPL-3.0-or-later, nothing incompatible and nothing decompiled. ### When it applies - [x] Numbers from the same PC, scene and settings, at least 2 interleaved runs each, the median reported. - [x] A game-free test added for the fix, failing on `main` and passing here. - [x] A check under `tests/` that reads changed source updated in this PR, not weakened. - [x] Host code builds on both Windows (llvm-mingw) and Linux, with UTF-8 paths. - [x] Docs updated.
fix(prompts): the Keyboard prompts show the movement keys as they are bound
Some checks are pending
CI / Conventional Commit title (pull_request) Blocked by required conditions
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Blocked by required conditions
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Blocked by required conditions
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Blocked by required conditions
CI / Workflow lint (actionlint) (pull_request) Blocked by required conditions
Third-party parts / As their notes say (pull_request) Blocked by required conditions
Third-party parts / The same as upstream (pull_request) Blocked by required conditions
Website / Website on Cloudflare (pull_request_target) Has been skipped
PR description / Description follows the template (pull_request_target) Successful in 5s
beanstalk/approval Test farm not requested
a8bd159237
The left stick's icons on the Keyboard face were fixed at the build: W, S, A
and D for one way, and the WASD, WS and AD pictures for several. With Move up
bound to another key the prompt for it still showed W, and a movement key
changed while the game runs was not seen at all: current_binds took only the
Switch buttons' controls.

stick_shows picks what each of those icons shows from the movement keys now.
While its ways are on the default keys an icon keeps the build's picture. One
way on another key shows that key's icon, and in a text rewritten after a
change it gets a code of its own, as a button on a key does, since the game
keeps each code's glyph as first drawn. Several ways on other keys, or a way
on no key or on a key without an icon, show the game's own stick icon: the
font has no picture of other keys together.

current_binds carries the four movement keys after the buttons' controls, so
a change reaches the font while the game runs. The textures and the layouts
follow the buttons' part alone, and the textures' cache key hashes that part,
so no cache is written again.
jarynclouatre changed title from WIP: fix(prompts): the Keyboard prompts show the movement keys as they are bound to fix(prompts): the Keyboard prompts show the movement keys as they are bound 2026-11-14 17:55:58 +00:00
Some checks are pending
CI / Conventional Commit title (pull_request) Blocked by required conditions
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Blocked by required conditions
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Blocked by required conditions
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Blocked by required conditions
CI / Workflow lint (actionlint) (pull_request) Blocked by required conditions
Third-party parts / As their notes say (pull_request) Blocked by required conditions
Third-party parts / The same as upstream (pull_request) Blocked by required conditions
Website / Website on Cloudflare (pull_request_target) Has been skipped
PR description / Description follows the template (pull_request_target) Successful in 5s
beanstalk/approval Test farm not requested
This pull request doesn't have enough approvals yet. 0 of 1 approvals granted.
Some workflows are waiting to be reviewed.
This branch is out-of-date with the base branch
You are not authorized to merge this pull request.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u 'fix/keyboard-move-key-pictures:jarynclouatre-fix/keyboard-move-key-pictures'
git switch 'jarynclouatre-fix/keyboard-move-key-pictures'
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
MagicBeanDev/Longshot!529
No description provided.