feat(input): a Walk key for the keyboard, held or toggled, with its speed #2345

Open
mooki000 wants to merge 2 commits from mooki000/walk-key into main
mooki000 commented 2026-11-11 15:21:54 +00:00 (Migrated from github.com)

What this is for: keyboard players can walk. A Walk key (Caps Lock by default, held or toggled) makes the movement
keys tilt the stick part of the way, set by a new Walk speed row; today the keys only run. What is measured: on
Arch Linux with an RTX 4090 (NVIDIA 615.78.08), on main 49f75dc8, in headless runs in Kokiri Forest: how fast Link
moves and whether he walks or runs at each share of the stick (1.03 m/s at 15%, 1.47 m/s at 45% to 50%, 4.50 m/s at
100%), which set the row's default (45%) and range (15% to 90%); the key path itself with keys held in the key table
by a test-only probe (Caps Lock with W or S: 1.47 m/s, without: 4.50 m/s), Hold and Toggle; the two menu rows and the
Controls page row in pictures; a new game-free test that fails on main. Not measured: Windows game runtime, a real keyboard
(the game ran headless), controllers (unchanged), first-person aiming while walking, places other than Kokiri Forest.

Closes #2344.

Problem

On the keyboard Link can only run: the movement keys push the stick all the way (host/nn_hid.c, * 32767), so a
player without a controller has no way to walk (narrow ledges, sneaking past guards, a slower pace on a path).

What changed

  • A Walk control on the Controls page, keys only, after Camera right (HOS_KEY_WALK; ini key_walk). Its default
    key is Caps Lock, which no other control has and which sits beside A and Shift, so it can be held with WASD. It is
    rebound, cleared and reset like Move forward, takes a second key, and can be a mouse button (while the mouse is
    captured, as the other bindings).
  • Walk mode (Controls tab, walk_mode): Hold (the default: Link walks while the key is held) or Toggle (one press
    walks, the next runs again). A press counts only while the keys are the game's: not while the Insert menu is open or
    the window is behind another one, and a key still held when they come back counts after its release.
  • Walk speed (Controls tab, walk_speed): how far the movement keys tilt the stick while Link walks, 15% to 90% in
    steps of 5, default 45%. A diagonal is scaled by its length (W+A walks too). The numbers come from the measurement
    below: 15% is Link's slowest walk (10% is no slower), 45% the lowest share at his walk's top speed, and from 55% he
    speeds up into a jog; the rows above 55% are there for a player who wants a slower run.
  • Nothing else is scaled: the camera keys, the mouse (both Mouse camera modes), controllers and scripted input
    (HOS_INPUT_SCRIPT, HOS_INPUT_LIVE) keep their tilt, and so does running (the diagonal included).
  • An options file from before this change that gives Caps Lock to another control keeps it there alone: Walk then has
    no key until one is bound (hid: no Walk key: ... in the log).
  • Log lines: hid: walking: the movement keys tilt the left stick to 45% (0, 14745) (the first tilt at each share) and
    hid: walking on / off (Walk mode Toggle).
  • Option ids 52 and 53 (gpu/vk/vk_api.h), answered in vk_replay.cpp's option lambda; the host reads them live.
    Updated 2026-11-11 after review: the scripted survey checked all 134 open PRs, fetched the 13 heads that change
    vk_api.h, and found neither ID in main nor those heads. The refreshed inventory now puts #2357's FOV 51 on main;
    #2530 uses 49 for Keyboard and #2261 uses 60 for Item wheel. Saved walk_mode/walk_speed keys are unchanged.
  • Docs: the readme's menu table and notes, its Controls section and the ini's key names; the options file table in
    docs/development.md.
  • Tests: tests/test_walk_key.py (new) compiles read_input, the binding table and the walk helpers from
    host/nn_hid.c against fake keys, window, pad, mouse and options files. All original source-text wiring/doc
    checks are restored, updated to 52/53. The compiled fixture includes the actual header and statically checks both
    allocations; its behavior checks exercise the host's reads using those constants.
    tests/test_bound_keys.py (its prelude needs VK_CAPITAL) and tests/test_input_background.py (cuts the new
    helpers read_input calls) are updated. All four unrelated background wiring checks are restored verbatim;
    no check from main is removed. The merged tests/test_option_ids.py keeps all five negative cases and every
    assertion, with its two Walk collision values and reservations updated from 49/50 to 52/53.

How it was tested

Checks.

Latest refresh, 2026-11-11: head 5ab213a6 on 8fcc8c22. After #2357 merged, I rebased again and kept both FOV and
Walk formatters. The feature remains the first commit; review repairs are folded into the second. All four background
wiring checks and the original Walk wiring/doc checks are restored, not removed. Main's two-slot pad-binding fixture
locks and its five option-ID collision cases are retained, with the Walk values updated. No new game run or Windows
run is claimed for this refresh; the older
Source-regression CI passed on 796b1bdf, not this new head.

  • On 5ab213a6, test_walk_key.py, test_bound_keys.py and test_input_background.py pass with GCC 16.2.1 and
    Clang 23.1.3
    . The merged option-ID check passes with both: 43 unique IDs, all five collision variants rejected.
  • A compiled variant with the final Walk tilt multiplied by zero fails at runtime with 26 CHECK failures with each
    compiler
    . Before the last rebase, the restored wiring guards and compiled fixture rejected 32 mutations per
    compiler
    on cb984dc3; wrong host mode/speed IDs caused five/six runtime CHECK failures respectively.
  • The final-header control-socket scenario matches all 13 asserted stick/button states: the socket's tilt is
    preserved, exclusive input suppresses the keyboard, and Walk returns afterwards. This is a compiled input fixture,
    not a new game or real socket session.
  • Full suites ran serially through hs-idle.sh, with the dependency Python and 32 checks at once. Load is the
    wrapper's before/after reading, not a quiet-machine performance measurement:
Tree Passed Failed Skipped Suite time Wrapper load before → after
Walk 5ab213a6 on 8fcc8c22 446 3 20 601 s 186.12 → 181.69
Clean main 8fcc8c22 446 2 20 591 s 181.69 → 72.79

The raw failure sets differ. Both fail test_env_on.py at main's HOS_FPS_LOG use in host/oot_high_fps.c:15.
Walk also had a compiler killed by SIGKILL in test_depth_sample_types.py and a 600.1 s timeout in
test_recorder_sync.py; both passed on main (recorder took 590.8 s there). Main alone failed
test_appimage_package_retry.py on an extra enrollment/retry; it passed in Walk's full run. These test files and
the high-fps/appimage sources are unchanged by Walk. No raw full-suite parity is claimed.

The three differing checks were then run serially on 5ab213a6 through the same test gate:

Check Walk full suite Main full suite Isolated rerun on Walk
test_depth_sample_types.py Compiler SIGKILL Pass Pass, 8.2 s
test_recorder_sync.py Timeout at 600.1 s Pass, 590.8 s Pass, 240.0 s
test_appimage_package_retry.py Pass Enrollment/retry assertion Pass, 16.7 s

That serial run ended 3 passed, 0 failed, 0 skipped in 265 s, wrapper load 111.79 → 77.18. The original
failures remain recorded above; the common base failure is test_env_on.py, not changed by this PR.
The final core-dump check reported No coredumps found.

Added 2026-11-11: tests/test_walk_key.py passes in Windows part 1/2 on 37687e2f. That shard fails only on main’s ASTC scanf fixture, whose fix is #2397. This proves the compiled input check on Windows, not physical input or gameplay.

  • Updated 2026-11-11: head 37687e2f on 7759a6f3, including #2380. test_walk_key.py, test_bound_keys.py and test_input_background.py pass with GCC and Clang. A throwaway variant that suppresses the Walk tilt fails the compiled behavioral checks with both compilers. The earlier test against main 49f75dc8 failed because the Walk helper was absent.
  • Full suite on the earlier 37687e2f: 386 passed, 1 failed, 10 skipped in 144 s; only test_updater_asset_digest.py fails because this machine has no .NET 8 reference packs. The two vcore tests fixed by #2380 now pass. A compiled header check reports walk_mode=49 walk_speed=50 camera_speed=48.
  • The control-socket scenario was rerun: its own stick tilt is preserved, exclusive socket input suppresses keyboard movement while active, and keyboard Walk returns afterwards. No new game run after this rebase/renumber.
  • Earlier python -I -B tests/run_all.py on the original branch (Linux, clang 23): 363 passed, 2 failed, 10 skipped. The two fail on
    main on this machine as well and do not touch this change: test_updater_asset_digest.py (no .NET 8 reference
    packs installed) and test_wayland_libdecor_hint.py (clang 23's -Wunused-but-set-global under -Werror).

In the game: Arch Linux (kernel 7.2.15), i9-13900K, RTX 4090, NVIDIA 615.78.08, base main 49f75dc8, head
78af2f74, 2026-11-11, headless runs (no window) with 1280x720 pictures, load average 2 to 4 for the speed and key
runs, my save in Kokiri Forest. The build was this branch plus a local probe that is not part of this pull request: it lets the input
script hold the left stick at a share of the way, logs Link's position and the forward speed the game sets on him every
250 ms together with the stick that GetNpadStates handed the game, and holds key codes in the key table that SDL's
keyboard fills on Linux, so the keyboard's own path (bound_down, walk_held, move_keys_stick) ran although no key
can reach a headless game. Speeds are medians of 9 or 10 readings per 2.6 s hold, forward and back, the first reading of
each hold (the turn) left out:

Left stick Speed the game set (m/s) Speed from his position (m/s) Pose
10% 1.03 1.02 walk
15% 1.03 1.03 walk
20% 1.11 1.11 walk
30% 1.28 1.28 to 1.30 walk
40% 1.45 1.44 walk
45% 1.47 1.46 to 1.47 walk
50% 1.47 1.45 to 1.47 walk
55% 1.65 1.64 walk, faster
60% 1.85 1.84 arms start to bend
70% 2.37 2.34 to 2.35 jog
80% 2.97 2.94 to 2.96 run
100% 4.50 4.27 to 4.39 run
  • Keys, Walk speed at 45%: W or S with Caps Lock gave the game the stick (0, ±14745), 45% of the way, and Link walked
    at 1.47 m/s; W or S alone gave (0, ±32767) and he ran at 4.50 m/s; W+A and S+D with Caps Lock gave (∓10426, ±10426),
    45% along the diagonal, and he walked at 1.47 m/s. The log showed hid: walking: the movement keys tilt the left stick to 45% (0, 14745).
  • Toggle, set through the menu's keys: a Caps Lock press logged hid: walking on and W then walked (stick 14745,
    1.47 m/s), the next press hid: walking off and W ran (32767, 4.50 m/s), the next on again and S+D walked along the
    diagonal, the last off. The options file afterwards held walk_mode=1, walk_speed=45, key_walk=20,0 (Caps
    Lock, no second key).
  • The table and the key holds were measured on this branch's first version, whose walking code is the same (only the
    row's lower bound has changed since); the Toggle run and the menu pictures were taken again on this version
    (78af2f74 plus the probe), while other work loaded the machine (load average 129 at its start; it gives log lines
    and pictures, no timing).

The runs, as the harness printed them (exit 124 is the run's own time limit; nvrm=1 is one
NVRM: memMap_IMPL: CPU mapping not supported line in the kernel log, which the game's start usually draws from
this driver and which is no fault):

hs-run walk-probe1 exit=124 wall=240.7s start=2026-11-11 02:14:41 shots=231 fatal/crash/devlost=0 kernel=0 nvrm=1 dev=vk:_device_0:_NVIDIA_GeForce_RTX_4090  load 2.38 3.12 3.96 -> 4.00 3.97 4.13
hs-run walk-menu1 exit=124 wall=200.7s start=2026-11-11 02:18:42 shots=385 fatal/crash/devlost=0 kernel=0 nvrm=1 dev=vk:_device_0:_NVIDIA_GeForce_RTX_4090  load 4.00 3.97 4.13 -> 4.48 4.11 4.14
hs-run walk-menu2 exit=124 wall=201.0s start=2026-11-11 09:00:54 shots=307 fatal/crash/devlost=0 kernel=0 nvrm=1 dev=vk:_device_0:_NVIDIA_GeForce_RTX_4090  load 129.26 74.03 42.96 -> 19.30 52.27 41.06
Run Build What it did Result
walk-probe1 first version + probe the stick at 10% to 100%, then the key holds the speed table above; keys walk at 1.47 m/s, run at 4.50 m/s
walk-menu1 first version + probe the menu's rows, then Toggle with keys Toggle sequence as expected; the Controls page's list did not scroll in headless pictures, so no picture from it is used
walk-menu2 this version + probe the same, the page's list scrolled by the probe Toggle sequence as expected (below); the two menu pictures

The Toggle sequence of walk-menu2, from its log (the script that reads it asserts the order and the stick values):

walking on
hold stick      0, 14745 presents 6668-6813 lines 11 set 1.468 m/s
walking off
hold stick      0, 32767 presents 6943-7076 lines 10 set 4.500 m/s
walking on
hold stick  10426,-10426 presents 7201-7353 lines 11 set 1.469 m/s
walking off
OK: the sequence is as expected

Pictures (1280x720 headless shots, cropped to the game and to the menu's rows):

S with Caps Lock walks, S alone runs (stick 45% and 100%, 1.47 and 4.50 m/s)

Left: S held with Caps Lock, Link walks towards the camera with his arms hanging. Right: S alone, he runs, leaning
forward with his arms pumping.

The Controls tab: 1. Walk mode with Toggle chosen, 2. Walk speed at 45%

The two new rows sit between Motion and Controls. Panel 1: Walk mode selected with Toggle chosen (Hold is the
default) and its help text. Panel 2: Walk speed selected at 45% and its help text.

The Controls page: the Walk row, Caps Lock in the Keyboard column

The new last row of the Controls page, after Camera right: Walk, no gamepad button, Caps Lock as its key.

Not tested

  • Windows game runtime, and a real keyboard and mouse: the game here only runs headless, where no key reaches it. The keys were held
    in the game's key table by the test-only probe described above; the press itself (SDL's scancode 57 on Linux,
    VK_CAPITAL on Windows) was not exercised.
  • Controllers: not run, and not changed (the walk scaling applies only to the movement keys' tilt).
  • Caps Lock with a keyboard layout or a tool that remaps it; places other than Kokiri Forest's paths (slopes, water).

Risks

  • First-person aiming with the movement keys while walking: the game may read the left stick to aim, which would then
    be slower by the same share. Aiming with the camera keys or the mouse is not changed. Not tried in the game.
  • Caps Lock still switches capitals on and off in other programs at each press (said in the readme, with the advice to
    bind another key).
  • vk_api.h is part of the shader caches' stamp (nx2/build.py 907-912), so, as with any change to that header, the
    first start of a build with this translates the shaders once more.
  • MKWVK_API_VERSION stays at the base's 18; this change adds option/key identifiers, not host/renderer table entries. Build the host and renderer together; mixing binaries from different versions was not tested.
  • Walk now uses 52/53, free in the open-head survey at 2026-11-11 22:34:34 UTC. The survey includes API-version bumps and the indexed achievement namespace starting at 8192 in #2307. Future changes must still avoid reusing an assigned ID.

Overlaps

Updated 2026-11-11 after the FOV merge: 79 open PRs touch one of this branch's eleven files; six have additional
text conflicts (nine hunks). Each reported hunk was read; no combined game run was made.

  • #1930 (ocarina bindings): keep both ordered control-name additions and both fixture helper sets; Walk stays keyboard-only.
  • #2151 (item buttons): keep both option-lambda additions and the controls documentation. Its numeric 12/13 IDs do not
    collide with Walk's 52/53; keep all input wiring checks.
  • #2252 (Switch 2 controller): preserve its documentation paragraph and the controls sentence that includes Walk.
  • #2317 (data folder): keep its updated options-file location and the Walk control in the host comment.
  • #2459 (microphone controls): keep both header additions; its gain/channel IDs 29/30 are separate from Walk's 52/53.
  • #2530 (Keyboard row): update the combined Controls-row count; its Keyboard ID 49 is separate from Walk's 52/53.
  • #1990 (second pad binding), #2119 (Aspect ratio), #2357 (FOV), #2366 (live prompts) and #2447 (pipeline-list export)
    are now on the base. Their code and checks are retained; FOV's Walk collision cases now test 52/53.

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 [email protected]

Assisted-by: GPT-6 Astra
Co-Authored-By: GPT-6 Astra [email protected]

**What this is for:** keyboard players can walk. A Walk key (Caps Lock by default, held or toggled) makes the movement keys tilt the stick part of the way, set by a new Walk speed row; today the keys only run. **What is measured:** on Arch Linux with an RTX 4090 (NVIDIA 615.78.08), on `main` 49f75dc8, in headless runs in Kokiri Forest: how fast Link moves and whether he walks or runs at each share of the stick (1.03 m/s at 15%, 1.47 m/s at 45% to 50%, 4.50 m/s at 100%), which set the row's default (45%) and range (15% to 90%); the key path itself with keys held in the key table by a test-only probe (Caps Lock with W or S: 1.47 m/s, without: 4.50 m/s), Hold and Toggle; the two menu rows and the Controls page row in pictures; a new game-free test that fails on `main`. **Not measured:** Windows game runtime, a real keyboard (the game ran headless), controllers (unchanged), first-person aiming while walking, places other than Kokiri Forest. Closes #2344. ## Problem On the keyboard Link can only run: the movement keys push the stick all the way (`host/nn_hid.c`, `* 32767`), so a player without a controller has no way to walk (narrow ledges, sneaking past guards, a slower pace on a path). ## What changed - **A Walk control** on the Controls page, keys only, after Camera right (`HOS_KEY_WALK`; ini `key_walk`). Its default key is **Caps Lock**, which no other control has and which sits beside A and Shift, so it can be held with WASD. It is rebound, cleared and reset like Move forward, takes a second key, and can be a mouse button (while the mouse is captured, as the other bindings). - **Walk mode** (Controls tab, `walk_mode`): Hold (the default: Link walks while the key is held) or Toggle (one press walks, the next runs again). A press counts only while the keys are the game's: not while the Insert menu is open or the window is behind another one, and a key still held when they come back counts after its release. - **Walk speed** (Controls tab, `walk_speed`): how far the movement keys tilt the stick while Link walks, 15% to 90% in steps of 5, default 45%. A diagonal is scaled by its length (W+A walks too). The numbers come from the measurement below: 15% is Link's slowest walk (10% is no slower), 45% the lowest share at his walk's top speed, and from 55% he speeds up into a jog; the rows above 55% are there for a player who wants a slower run. - Nothing else is scaled: the camera keys, the mouse (both Mouse camera modes), controllers and scripted input (`HOS_INPUT_SCRIPT`, `HOS_INPUT_LIVE`) keep their tilt, and so does running (the diagonal included). - An options file from before this change that gives Caps Lock to another control keeps it there alone: Walk then has no key until one is bound (`hid: no Walk key: ...` in the log). - Log lines: `hid: walking: the movement keys tilt the left stick to 45% (0, 14745)` (the first tilt at each share) and `hid: walking on` / `off (Walk mode Toggle)`. - Option ids **52 and 53** (`gpu/vk/vk_api.h`), answered in `vk_replay.cpp`'s option lambda; the host reads them live. Updated 2026-11-11 after review: the scripted survey checked all 134 open PRs, fetched the 13 heads that change `vk_api.h`, and found neither ID in main nor those heads. The refreshed inventory now puts #2357's FOV 51 on main; #2530 uses 49 for Keyboard and #2261 uses 60 for Item wheel. Saved `walk_mode`/`walk_speed` keys are unchanged. - Docs: the readme's menu table and notes, its Controls section and the ini's key names; the options file table in `docs/development.md`. - Tests: `tests/test_walk_key.py` (new) compiles `read_input`, the binding table and the walk helpers from `host/nn_hid.c` against fake keys, window, pad, mouse and options files. All original source-text wiring/doc checks are restored, updated to 52/53. The compiled fixture includes the actual header and statically checks both allocations; its behavior checks exercise the host's reads using those constants. `tests/test_bound_keys.py` (its prelude needs `VK_CAPITAL`) and `tests/test_input_background.py` (cuts the new helpers `read_input` calls) are updated. All four unrelated background wiring checks are restored verbatim; no check from main is removed. The merged `tests/test_option_ids.py` keeps all five negative cases and every assertion, with its two Walk collision values and reservations updated from 49/50 to 52/53. ## How it was tested **Checks.** Latest refresh, 2026-11-11: head `5ab213a6` on `8fcc8c22`. After #2357 merged, I rebased again and kept both FOV and Walk formatters. The feature remains the first commit; review repairs are folded into the second. All four background wiring checks and the original Walk wiring/doc checks are restored, not removed. Main's two-slot pad-binding fixture locks and its five option-ID collision cases are retained, with the Walk values updated. No new game run or Windows run is claimed for this refresh; the older [Source-regression CI](https://github.com/NotRexed/Hookshot/actions/runs/43093276382) passed on `796b1bdf`, not this new head. - On `5ab213a6`, `test_walk_key.py`, `test_bound_keys.py` and `test_input_background.py` pass with **GCC 16.2.1 and Clang 23.1.3**. The merged option-ID check passes with both: **43 unique IDs**, all five collision variants rejected. - A compiled variant with the final Walk tilt multiplied by zero fails at runtime with **26 CHECK failures with each compiler**. Before the last rebase, the restored wiring guards and compiled fixture rejected **32 mutations per compiler** on `cb984dc3`; wrong host mode/speed IDs caused five/six runtime CHECK failures respectively. - The final-header control-socket scenario matches all **13 asserted stick/button states**: the socket's tilt is preserved, exclusive input suppresses the keyboard, and Walk returns afterwards. This is a compiled input fixture, not a new game or real socket session. - Full suites ran serially through `hs-idle.sh`, with the dependency Python and 32 checks at once. Load is the wrapper's before/after reading, not a quiet-machine performance measurement: | Tree | Passed | Failed | Skipped | Suite time | Wrapper load before → after | |---|---:|---:|---:|---:|---| | Walk `5ab213a6` on `8fcc8c22` | 446 | 3 | 20 | 601 s | 186.12 → 181.69 | | Clean main `8fcc8c22` | 446 | 2 | 20 | 591 s | 181.69 → 72.79 | The raw failure sets differ. Both fail `test_env_on.py` at main's `HOS_FPS_LOG` use in `host/oot_high_fps.c:15`. Walk also had a compiler killed by SIGKILL in `test_depth_sample_types.py` and a 600.1 s timeout in `test_recorder_sync.py`; both passed on main (recorder took 590.8 s there). Main alone failed `test_appimage_package_retry.py` on an extra enrollment/retry; it passed in Walk's full run. These test files and the high-fps/appimage sources are unchanged by Walk. **No raw full-suite parity is claimed.** The three differing checks were then run serially on `5ab213a6` through the same test gate: | Check | Walk full suite | Main full suite | Isolated rerun on Walk | |---|---|---|---| | `test_depth_sample_types.py` | Compiler SIGKILL | Pass | **Pass**, 8.2 s | | `test_recorder_sync.py` | Timeout at 600.1 s | Pass, 590.8 s | **Pass**, 240.0 s | | `test_appimage_package_retry.py` | Pass | Enrollment/retry assertion | **Pass**, 16.7 s | That serial run ended **3 passed, 0 failed, 0 skipped in 265 s**, wrapper load **111.79 → 77.18**. The original failures remain recorded above; the common base failure is `test_env_on.py`, not changed by this PR. The final core-dump check reported `No coredumps found`. Added 2026-11-11: `tests/test_walk_key.py` passes in [Windows part 1/2](https://github.com/NotRexed/Hookshot/actions/runs/43072781059/job/130704747959) on `37687e2f`. That shard fails only on main’s ASTC `scanf` fixture, whose fix is #2397. This proves the compiled input check on Windows, not physical input or gameplay. - Updated 2026-11-11: head `37687e2f` on `7759a6f3`, including #2380. `test_walk_key.py`, `test_bound_keys.py` and `test_input_background.py` pass with GCC and Clang. A throwaway variant that suppresses the Walk tilt fails the compiled behavioral checks with both compilers. The earlier test against main 49f75dc8 failed because the Walk helper was absent. - Full suite on the earlier `37687e2f`: `386 passed, 1 failed, 10 skipped in 144 s`; only `test_updater_asset_digest.py` fails because this machine has no .NET 8 reference packs. The two vcore tests fixed by #2380 now pass. A compiled header check reports `walk_mode=49 walk_speed=50 camera_speed=48`. - The control-socket scenario was rerun: its own stick tilt is preserved, exclusive socket input suppresses keyboard movement while active, and keyboard Walk returns afterwards. No new game run after this rebase/renumber. - Earlier `python -I -B tests/run_all.py` on the original branch (Linux, clang 23): 363 passed, 2 failed, 10 skipped. The two fail on `main` on this machine as well and do not touch this change: `test_updater_asset_digest.py` (no .NET 8 reference packs installed) and `test_wayland_libdecor_hint.py` (clang 23's `-Wunused-but-set-global` under `-Werror`). **In the game**: Arch Linux (kernel 7.2.15), i9-13900K, RTX 4090, NVIDIA 615.78.08, base `main` 49f75dc8, head 78af2f74, 2026-11-11, headless runs (no window) with 1280x720 pictures, load average 2 to 4 for the speed and key runs, my save in Kokiri Forest. The build was this branch plus a local probe that is not part of this pull request: it lets the input script hold the left stick at a share of the way, logs Link's position and the forward speed the game sets on him every 250 ms together with the stick that `GetNpadStates` handed the game, and holds key codes in the key table that SDL's keyboard fills on Linux, so the keyboard's own path (`bound_down`, `walk_held`, `move_keys_stick`) ran although no key can reach a headless game. Speeds are medians of 9 or 10 readings per 2.6 s hold, forward and back, the first reading of each hold (the turn) left out: | Left stick | Speed the game set (m/s) | Speed from his position (m/s) | Pose | |---|---|---|---| | 10% | 1.03 | 1.02 | walk | | 15% | 1.03 | 1.03 | walk | | 20% | 1.11 | 1.11 | walk | | 30% | 1.28 | 1.28 to 1.30 | walk | | 40% | 1.45 | 1.44 | walk | | **45%** | **1.47** | 1.46 to 1.47 | walk | | 50% | 1.47 | 1.45 to 1.47 | walk | | 55% | 1.65 | 1.64 | walk, faster | | 60% | 1.85 | 1.84 | arms start to bend | | 70% | 2.37 | 2.34 to 2.35 | jog | | 80% | 2.97 | 2.94 to 2.96 | run | | 100% | 4.50 | 4.27 to 4.39 | run | - Keys, Walk speed at 45%: W or S with Caps Lock gave the game the stick (0, ±14745), 45% of the way, and Link walked at 1.47 m/s; W or S alone gave (0, ±32767) and he ran at 4.50 m/s; W+A and S+D with Caps Lock gave (∓10426, ±10426), 45% along the diagonal, and he walked at 1.47 m/s. The log showed `hid: walking: the movement keys tilt the left stick to 45% (0, 14745)`. - Toggle, set through the menu's keys: a Caps Lock press logged `hid: walking on` and W then walked (stick 14745, 1.47 m/s), the next press `hid: walking off` and W ran (32767, 4.50 m/s), the next on again and S+D walked along the diagonal, the last off. The options file afterwards held `walk_mode=1`, `walk_speed=45`, `key_walk=20,0` (Caps Lock, no second key). - The table and the key holds were measured on this branch's first version, whose walking code is the same (only the row's lower bound has changed since); the Toggle run and the menu pictures were taken again on this version (78af2f74 plus the probe), while other work loaded the machine (load average 129 at its start; it gives log lines and pictures, no timing). The runs, as the harness printed them (exit 124 is the run's own time limit; `nvrm=1` is one `NVRM: memMap_IMPL: CPU mapping not supported` line in the kernel log, which the game's start usually draws from this driver and which is no fault): ``` hs-run walk-probe1 exit=124 wall=240.7s start=2026-11-11 02:14:41 shots=231 fatal/crash/devlost=0 kernel=0 nvrm=1 dev=vk:_device_0:_NVIDIA_GeForce_RTX_4090 load 2.38 3.12 3.96 -> 4.00 3.97 4.13 hs-run walk-menu1 exit=124 wall=200.7s start=2026-11-11 02:18:42 shots=385 fatal/crash/devlost=0 kernel=0 nvrm=1 dev=vk:_device_0:_NVIDIA_GeForce_RTX_4090 load 4.00 3.97 4.13 -> 4.48 4.11 4.14 hs-run walk-menu2 exit=124 wall=201.0s start=2026-11-11 09:00:54 shots=307 fatal/crash/devlost=0 kernel=0 nvrm=1 dev=vk:_device_0:_NVIDIA_GeForce_RTX_4090 load 129.26 74.03 42.96 -> 19.30 52.27 41.06 ``` | Run | Build | What it did | Result | |---|---|---|---| | walk-probe1 | first version + probe | the stick at 10% to 100%, then the key holds | the speed table above; keys walk at 1.47 m/s, run at 4.50 m/s | | walk-menu1 | first version + probe | the menu's rows, then Toggle with keys | Toggle sequence as expected; the Controls page's list did not scroll in headless pictures, so no picture from it is used | | walk-menu2 | this version + probe | the same, the page's list scrolled by the probe | Toggle sequence as expected (below); the two menu pictures | The Toggle sequence of walk-menu2, from its log (the script that reads it asserts the order and the stick values): ``` walking on hold stick 0, 14745 presents 6668-6813 lines 11 set 1.468 m/s walking off hold stick 0, 32767 presents 6943-7076 lines 10 set 4.500 m/s walking on hold stick 10426,-10426 presents 7201-7353 lines 11 set 1.469 m/s walking off OK: the sequence is as expected ``` **Pictures** (1280x720 headless shots, cropped to the game and to the menu's rows): ![S with Caps Lock walks, S alone runs (stick 45% and 100%, 1.47 and 4.50 m/s)](https://gist.githubusercontent.com/mooki000/b86bd3f35969803fb032f71f035844f8/raw/8ae8e25d14efe1c2c6d5d8384530e0583610e010/hookshot-walk-key-walk-vs-run.jpg) Left: S held with Caps Lock, Link walks towards the camera with his arms hanging. Right: S alone, he runs, leaning forward with his arms pumping. ![The Controls tab: 1. Walk mode with Toggle chosen, 2. Walk speed at 45%](https://gist.githubusercontent.com/mooki000/b86bd3f35969803fb032f71f035844f8/raw/8ae8e25d14efe1c2c6d5d8384530e0583610e010/hookshot-walk-key-controls-tab.jpg) The two new rows sit between Motion and Controls. Panel 1: Walk mode selected with Toggle chosen (Hold is the default) and its help text. Panel 2: Walk speed selected at 45% and its help text. ![The Controls page: the Walk row, Caps Lock in the Keyboard column](https://gist.githubusercontent.com/mooki000/b86bd3f35969803fb032f71f035844f8/raw/8ae8e25d14efe1c2c6d5d8384530e0583610e010/hookshot-walk-key-controls-page.jpg) The new last row of the Controls page, after Camera right: Walk, no gamepad button, Caps Lock as its key. ## Not tested - Windows game runtime, and a real keyboard and mouse: the game here only runs headless, where no key reaches it. The keys were held in the game's key table by the test-only probe described above; the press itself (SDL's scancode 57 on Linux, `VK_CAPITAL` on Windows) was not exercised. - Controllers: not run, and not changed (the walk scaling applies only to the movement keys' tilt). - Caps Lock with a keyboard layout or a tool that remaps it; places other than Kokiri Forest's paths (slopes, water). ## Risks - First-person aiming with the movement keys while walking: the game may read the left stick to aim, which would then be slower by the same share. Aiming with the camera keys or the mouse is not changed. Not tried in the game. - Caps Lock still switches capitals on and off in other programs at each press (said in the readme, with the advice to bind another key). - `vk_api.h` is part of the shader caches' stamp (`nx2/build.py` 907-912), so, as with any change to that header, the first start of a build with this translates the shaders once more. - `MKWVK_API_VERSION` stays at the base's 18; this change adds option/key identifiers, not host/renderer table entries. Build the host and renderer together; mixing binaries from different versions was not tested. - Walk now uses 52/53, free in the open-head survey at 2026-11-11 22:34:34 UTC. The survey includes API-version bumps and the indexed achievement namespace starting at 8192 in #2307. Future changes must still avoid reusing an assigned ID. ## Overlaps Updated 2026-11-11 after the FOV merge: 79 open PRs touch one of this branch's eleven files; six have additional text conflicts (nine hunks). Each reported hunk was read; no combined game run was made. - #1930 (ocarina bindings): keep both ordered control-name additions and both fixture helper sets; Walk stays keyboard-only. - #2151 (item buttons): keep both option-lambda additions and the controls documentation. Its numeric 12/13 IDs do not collide with Walk's 52/53; keep all input wiring checks. - #2252 (Switch 2 controller): preserve its documentation paragraph and the controls sentence that includes Walk. - #2317 (data folder): keep its updated options-file location and the Walk control in the host comment. - #2459 (microphone controls): keep both header additions; its gain/channel IDs 29/30 are separate from Walk's 52/53. - #2530 (Keyboard row): update the combined Controls-row count; its Keyboard ID 49 is separate from Walk's 52/53. - #1990 (second pad binding), #2119 (Aspect ratio), #2357 (FOV), #2366 (live prompts) and #2447 (pipeline-list export) are now on the base. Their code and checks are retained; FOV's Walk collision cases now test 52/53. Assisted-by: Claude Opus 5.5 Co-Authored-By: Claude Opus 5.5 <[email protected]> Assisted-by: GPT-6 Astra Co-Authored-By: GPT-6 Astra <[email protected]>
mooki000 commented 2026-11-11 16:54:11 +00:00 (Migrated from github.com)

Rebased onto main b744b1ec. It merged without a conflict, but its test would not have built there: the read_input that tests/test_walk_key.py cuts out of host/nn_hid.c now calls hos_control_input() (#926) and reads HOS_INPUT_EXCLUSIVE with env_on() (#2042). The test now gets gpu/vk/compat/hookshot_env.h with -include and stubs the control bridge as off, as tests/test_input_background.py does on main. The source lines of this pull request are unchanged.

With the control socket: its input keeps its own stick tilt, like scripted input, and an exclusive socket input keeps the keyboard out while it lasts, Walk included.

Rerun on the new head (8a14b300): the branch's three tests pass with gcc 16 and clang 23, and test_walk_key.py still fails against main's source. tests/run_all.py: 374 passed, 4 failed, 10 skipped. All four fail on main too on this machine; two of them are main's test_vcore_fs_open.py and test_vcore_video_acquire.py, which #2380 fixes, so expect those two red here until it is merged. The game runs in the description are from the old base (49f75dc8) and were not repeated.

Rebased onto main `b744b1ec`. It merged without a conflict, but its test would not have built there: the `read_input` that `tests/test_walk_key.py` cuts out of `host/nn_hid.c` now calls `hos_control_input()` (#926) and reads `HOS_INPUT_EXCLUSIVE` with `env_on()` (#2042). The test now gets `gpu/vk/compat/hookshot_env.h` with `-include` and stubs the control bridge as off, as `tests/test_input_background.py` does on main. The source lines of this pull request are unchanged. With the control socket: its input keeps its own stick tilt, like scripted input, and an exclusive socket input keeps the keyboard out while it lasts, Walk included. Rerun on the new head (`8a14b300`): the branch's three tests pass with gcc 16 and clang 23, and `test_walk_key.py` still fails against main's source. `tests/run_all.py`: 374 passed, 4 failed, 10 skipped. All four fail on main too on this machine; two of them are main's `test_vcore_fs_open.py` and `test_vcore_video_acquire.py`, which #2380 fixes, so expect those two red here until it is merged. The game runs in the description are from the old base (`49f75dc8`) and were not repeated.
hckrman101 (Migrated from github.com) reviewed 2026-11-11 17:35:18 +00:00
hckrman101 (Migrated from github.com) left a comment

Nice, well measured and the test is a good one (it fails on main, passes here). I read the code and found nothing wrong in it: walk_held resets properly while the keys are not the game's, the diagonal scaling is right, Caps Lock is VK_CAPITAL read with the 0x8000 bit on Windows and mapped to scancode 57 on Linux, and no other control uses it. The stick dead zone (option 11) is applied only to pads, so it does not touch the keyboard's tilt, and #2286 is merged and #1600 touches the pad path only, so I see no interaction with either. The menu rows are plain Row entries and I see nothing in the diff that the tests which cut code out of vk_menu.cpp would trip on (you updated test_bound_keys and test_input_background for the new prelude and helpers).

One real problem: option id 46 collides with #2366 (open, "a new face or new controls show while the game runs"), which defines HOS_OPT_PROMPTS = 46 in vk_api.h and answers it in the same option lambda. This one takes 46 and 47. On main, 45 and 48 (Camera speed) are now taken, so the free ids are 49 and up, except #2261 (60). Whichever of the two lands second has to renumber. Easiest is to move Walk to ids that nobody has claimed (49 and 50 are free as far as I can see, #1945's 48 is already on main) so this can merge independently.

CI: the Python source checks fail only on test_vcore_fs_open.py and test_vcore_video_acquire.py, which you noted fail on main and #2380 fixes; the appimage job died on an Ubuntu mirror 504 (infrastructure); Windows Vulkan back end build passes. Not for this PR to fix, but it will need a rerun once #2380 is in.

Minor, not blocking: the first-person aiming risk you list is real for keyboard players who aim with WASD, worth a line in the readme if you try it in game.

Nice, well measured and the test is a good one (it fails on main, passes here). I read the code and found nothing wrong in it: `walk_held` resets properly while the keys are not the game's, the diagonal scaling is right, Caps Lock is `VK_CAPITAL` read with the 0x8000 bit on Windows and mapped to scancode 57 on Linux, and no other control uses it. The stick dead zone (option 11) is applied only to pads, so it does not touch the keyboard's tilt, and #2286 is merged and #1600 touches the pad path only, so I see no interaction with either. The menu rows are plain `Row` entries and I see nothing in the diff that the tests which cut code out of `vk_menu.cpp` would trip on (you updated `test_bound_keys` and `test_input_background` for the new prelude and helpers). One real problem: **option id 46 collides with #2366** (open, "a new face or new controls show while the game runs"), which defines `HOS_OPT_PROMPTS = 46` in `vk_api.h` and answers it in the same option lambda. This one takes 46 and 47. On main, 45 and 48 (Camera speed) are now taken, so the free ids are 49 and up, except #2261 (60). Whichever of the two lands second has to renumber. Easiest is to move Walk to ids that nobody has claimed (49 and 50 are free as far as I can see, #1945's 48 is already on main) so this can merge independently. CI: the Python source checks fail only on `test_vcore_fs_open.py` and `test_vcore_video_acquire.py`, which you noted fail on main and #2380 fixes; the appimage job died on an Ubuntu mirror 504 (infrastructure); Windows Vulkan back end build passes. Not for this PR to fix, but it will need a rerun once #2380 is in. Minor, not blocking: the first-person aiming risk you list is real for keyboard players who aim with WASD, worth a line in the readme if you try it in game.
@ -28,6 +28,10 @@ enum { HOS_OPT_DLSS_JITTER_W = 24, HOS_OPT_DLSS_JITTER_H, HOS_OPT_DLSS_JITTER_PH
/* (hookshot) the Audio tab's rows (host/nn_audio.c reads them every 100 ms): the volume in percent, and no sound while
hckrman101 (Migrated from github.com) commented 2026-11-11 17:35:18 +00:00

46 is also taken by #2366 (HOS_OPT_PROMPTS = 46). Please pick ids that are free, e.g. 49 and 50 (main has 45 and 48 now, #2261 has 60), and update the comment lines in vk_menu.h that name 46 and 47.

46 is also taken by #2366 (`HOS_OPT_PROMPTS = 46`). Please pick ids that are free, e.g. 49 and 50 (main has 45 and 48 now, #2261 has 60), and update the comment lines in `vk_menu.h` that name 46 and 47.
mooki000 commented 2026-11-11 17:56:09 +00:00 (Migrated from github.com)

Moved Walk mode/speed to 49/50 and updated both vk_menu.h comments in 37687e2f. The host and renderer use the same constants; a compiled header check reports walk_mode=49 walk_speed=50 camera_speed=48. Saved named keys are unchanged. #2366 can keep 46; its remaining overlaps are text conflicts, not shared IDs.

Also rebased onto 7759a6f3, including #2380. The three input checks pass with GCC and Clang. The full suite is 386 passed, 1 failed, 10 skipped; only the missing .NET 8 reference packs fail here. I removed the source-text wiring assertions rather than repinning the IDs; the compiled behavior check still rejects a variant with Walk tilt suppressed, with both compilers.

No new game run after this rebase/renumber; first-person aiming remains explicitly untested.

Moved Walk mode/speed to **49/50** and updated both `vk_menu.h` comments in `37687e2f`. The host and renderer use the same constants; a compiled header check reports `walk_mode=49 walk_speed=50 camera_speed=48`. Saved named keys are unchanged. #2366 can keep 46; its remaining overlaps are text conflicts, not shared IDs. Also rebased onto `7759a6f3`, including #2380. The three input checks pass with GCC and Clang. The full suite is `386 passed, 1 failed, 10 skipped`; only the missing .NET 8 reference packs fail here. I removed the source-text wiring assertions rather than repinning the IDs; the compiled behavior check still rejects a variant with Walk tilt suppressed, with both compilers. No new game run after this rebase/renumber; first-person aiming remains explicitly untested.
mooki000 commented 2026-11-11 18:03:32 +00:00 (Migrated from github.com)

tests/test_walk_key.py passes on Windows on 37687e2f. Windows part 1/2 fails only on tests/test_native_astc_texture_count.py (the known scanf CRT deprecation); #2397 contains that fix. The description now records this Windows game-free coverage. Physical keyboard input and Windows gameplay remain untested.

`tests/test_walk_key.py` passes on Windows on `37687e2f`. [Windows part 1/2](https://github.com/NotRexed/Hookshot/actions/runs/43072781059/job/130704747959) fails only on `tests/test_native_astc_texture_count.py` (the known `scanf` CRT deprecation); #2397 contains that fix. The description now records this Windows game-free coverage. Physical keyboard input and Windows gameplay remain untested.
pmwork-personal commented 2026-11-11 19:26:25 +00:00 (Migrated from github.com)

I think i prefer Alt as walk. its consistent with many other default control schemes in other implementations with walk keys.

I think i prefer Alt as walk. its consistent with many other default control schemes in other implementations with walk keys.
mooki000 commented 2026-11-11 20:08:47 +00:00 (Migrated from github.com)

@pmwork-personal thanks. Walk is rebindable on the Controls page. This CI refresh keeps Caps Lock; the default choice can be settled separately. The readme already calls out its effect on capitals.

Rebased onto 47ed9f14, now 796b1bdf, including the merged #2397 repair and #2366 live prompts. The latter exposed a fixture bug: the test selected an earlier hos_bind declaration instead of its definition. The range search is fixed, and all three input checks pass with GCC and Clang. Walk still uses 49/50. No new gameplay, physical-input or first-person-aiming proof is claimed.

Update 2026-11-11: the refreshed source-regression workflow is green on 796b1bdf: both Windows and both Ubuntu shards pass. This is game-free CI evidence, not a new game run.

@pmwork-personal thanks. Walk is rebindable on the Controls page. This CI refresh keeps Caps Lock; the default choice can be settled separately. The readme already calls out its effect on capitals. Rebased onto `47ed9f14`, now `796b1bdf`, including the merged #2397 repair and #2366 live prompts. The latter exposed a fixture bug: the test selected an earlier `hos_bind` declaration instead of its definition. The range search is fixed, and all three input checks pass with GCC and Clang. Walk still uses 49/50. No new gameplay, physical-input or first-person-aiming proof is claimed. Update 2026-11-11: [the refreshed source-regression workflow](https://github.com/NotRexed/Hookshot/actions/runs/43093276382) is green on `796b1bdf`: both Windows and both Ubuntu shards pass. This is game-free CI evidence, not a new game run.
Joey-Magnus (Migrated from github.com) requested changes 2026-11-11 21:23:24 +00:00
Joey-Magnus (Migrated from github.com) left a comment

The code is sound (Caps Lock is scancode 57, a conflicting old ini leaves Walk unbound with a log line, and no API bump is needed). Two things before merge:

  1. tests/test_input_background.py drops four checks unrelated to this feature: the background block reads pads but not keyboard or mouse, t.option maps 4 to pad_background, and the "Controller in background" row exists. All four still pass on this branch, so they can simply go back in. AGENTS.md asks for checks to be updated, not removed.
  2. Option ID collision: HOS_OPT_WALK_MODE = 49 matches #2357's HOS_OPT_FOV = 49. The two PRs touch different hunks, so git won't flag it. Your if (id == HOS_OPT_WALK_MODE) comes first, so the game would read Walk mode (0/1) as the FOV percentage, which oot_fov.c then rejects. Whichever lands second has to renumber; please coordinate with @polaco1782.

There's also an open question from a commenter about Alt instead of Caps Lock as the default.

The code is sound (Caps Lock is scancode 57, a conflicting old ini leaves Walk unbound with a log line, and no API bump is needed). Two things before merge: 1. `tests/test_input_background.py` drops four checks unrelated to this feature: the background block reads pads but not keyboard or mouse, `t.option` maps 4 to `pad_background`, and the "Controller in background" row exists. All four still pass on this branch, so they can simply go back in. AGENTS.md asks for checks to be updated, not removed. 2. Option ID collision: `HOS_OPT_WALK_MODE = 49` matches #2357's `HOS_OPT_FOV = 49`. The two PRs touch different hunks, so git won't flag it. Your `if (id == HOS_OPT_WALK_MODE)` comes first, so the game would read Walk mode (0/1) as the FOV percentage, which `oot_fov.c` then rejects. Whichever lands second has to renumber; please coordinate with @polaco1782. There's also an open question from a commenter about Alt instead of Caps Lock as the default.
hckrman101 commented 2026-11-11 22:55:50 +00:00 (Migrated from github.com)

This now conflicts with main in gpu/vk/vk_menu.cpp, host/nn_hid.c, readme.md. Could you merge main into the branch (or rebase) when you get a chance? I'll take another look once it's up to date.

This now conflicts with main in `gpu/vk/vk_menu.cpp`, `host/nn_hid.c`, `readme.md`. Could you merge main into the branch (or rebase) when you get a chance? I'll take another look once it's up to date.
mooki000 commented 2026-11-11 23:45:30 +00:00 (Migrated from github.com)

I fixed both points in 5ab213a6:

  1. I restored all four background checks verbatim and every original Walk wiring/doc check. The background test only adds to main. After #2357 merged, I updated its two Walk collision cases and reservations to 52/53, keeping all five cases and every assertion.
  2. I moved Walk mode/speed to 52/53 after scripting a survey of all 134 open PRs and fetching the 13 heads that changed vk_api.h. Neither ID was claimed; the refreshed table now puts FOV 51 on main and still finds 52/53 free. #2530 claims 49 for Keyboard. The real header is compiled with the host's reads, and the renderer, menu comments and wiring checks agree.

The three input checks and the 43-ID guard pass with GCC and Clang; suppressed Walk tilt fails at runtime, and all 13 socket-fixture states pass. The updated description keeps both unequal raw suite results with their loads; the three differing depth/recorder/appimage checks all pass when run serially.

I kept Caps Lock for now: Walk is rebindable on the Controls page, and I can change the default if the maintainers prefer another key.

I rebased onto 8fcc8c22 after the FOV merge, keeping both formatters, main's two-slot pad bindings and its documentation additions. No new game run, physical-input or first-person-aiming proof is claimed.

I fixed both points in `5ab213a6`: 1. I restored all four background checks verbatim and every original Walk wiring/doc check. The background test only adds to main. After #2357 merged, I updated its two Walk collision cases and reservations to 52/53, keeping all five cases and every assertion. 2. I moved Walk mode/speed to **52/53** after scripting a survey of all 134 open PRs and fetching the 13 heads that changed `vk_api.h`. Neither ID was claimed; the refreshed table now puts FOV 51 on main and still finds 52/53 free. #2530 claims 49 for Keyboard. The real header is compiled with the host's reads, and the renderer, menu comments and wiring checks agree. The three input checks and the 43-ID guard pass with GCC and Clang; suppressed Walk tilt fails at runtime, and all 13 socket-fixture states pass. The updated description keeps both unequal raw suite results with their loads; the three differing depth/recorder/appimage checks all pass when run serially. I kept Caps Lock for now: Walk is rebindable on the Controls page, and I can change the default if the maintainers prefer another key. I rebased onto `8fcc8c22` after the FOV merge, keeping both formatters, main's two-slot pad bindings and its documentation additions. No new game run, physical-input or first-person-aiming proof is claimed.
Owner

@mooki000 commented on GitHub · 2026-11-12 06:07 UTC · original

Rebased the pushed 5ab213a6 onto current main 87991bc8 as c3c7d19e, keeping both commits and their complete authors/messages/trailers. The resolutions retain all five ocarina-note controls, keyboard prompts, camera handover, upscaler reset and current translated hints beside Walk's unchanged Hold/Caps Lock/45% defaults, 15–90% range and IDs 52/53. Fixtures retain all assertions; the new note-layer integration also asserts that an inactive note layer consumes no controller input. GCC passed all 122 selected checks; Clang passed 121 with main's inherited background-input warning. The suite was 469 passed / 2 inherited failures / 20 skipped: that warning and the known release-script race. The last rebase adds only #2671 and changes no PR file blob; Walk/ocarina/wiring checks, final-main negatives, #2671's offline check and Windows-target syntax ran again. The final PR gate passes. No second full suite, game run or native Windows execution is claimed. Sources: the #2345 evidence and final-handoff ledger above.

> [@mooki000](https://github.com/mooki000) commented on GitHub · 2026-11-12 06:07 UTC · [original](https://github.com/NotRexed/Hookshot/pull/2345#issuecomment-6816119035) Rebased the pushed `5ab213a6` onto current main `87991bc8` as `c3c7d19e`, keeping both commits and their complete authors/messages/trailers. The resolutions retain all five ocarina-note controls, keyboard prompts, camera handover, upscaler reset and current translated hints beside Walk's unchanged Hold/Caps Lock/45% defaults, 15–90% range and IDs 52/53. Fixtures retain all assertions; the new note-layer integration also asserts that an inactive note layer consumes no controller input. GCC passed all 122 selected checks; Clang passed 121 with main's inherited background-input warning. The suite was 469 passed / 2 inherited failures / 20 skipped: that warning and the known release-script race. The last rebase adds only #2671 and changes no PR file blob; Walk/ocarina/wiring checks, final-main negatives, #2671's offline check and Windows-target syntax ran again. The final PR gate passes. No second full suite, game run or native Windows execution is claimed. Sources: the #2345 evidence and final-handoff ledger above. <!-- github-sync:c:6816119035 -->
Owner

@Joey-Magnus approved on GitHub · 2026-11-12 14:32 UTC · original

Both of my points are fixed at c3c7d19e. tests/test_input_background.py now only adds to main's checks, with the four I asked about back unchanged, and Walk uses option ids 52 and 53 (gpu/vk/vk_api.h:34), which nothing on main uses (main has 45 to 48, and #2357's FOV took 51). The bind table grows by one entry at its end, saved by name as key_walk, options_version is untouched and no API bump is needed.

I merged it into current main and ran test_walk_key.py, test_bound_keys.py, test_input_background.py, test_ocarina_note_bindings.py, test_ocarina_notes.py, test_option_ids.py, test_menu_i18n.py and test_env_on.py: all pass, and CI is green on this head. Leaving Walk unbound with a log line when an older ini already gives Caps Lock to another control (binds_load) is the right upgrade path.

Caps Lock versus Alt as the default is the maintainers' call, and it's rebindable either way. First-person aiming while walking is still untested, as you say.

> [@Joey-Magnus](https://github.com/Joey-Magnus) approved on GitHub · 2026-11-12 14:32 UTC · [original](https://github.com/NotRexed/Hookshot/pull/2345#pullrequestreview-5876210432) Both of my points are fixed at c3c7d19e. `tests/test_input_background.py` now only adds to main's checks, with the four I asked about back unchanged, and Walk uses option ids 52 and 53 (`gpu/vk/vk_api.h:34`), which nothing on main uses (main has 45 to 48, and #2357's FOV took 51). The bind table grows by one entry at its end, saved by name as `key_walk`, `options_version` is untouched and no API bump is needed. I merged it into current main and ran `test_walk_key.py`, `test_bound_keys.py`, `test_input_background.py`, `test_ocarina_note_bindings.py`, `test_ocarina_notes.py`, `test_option_ids.py`, `test_menu_i18n.py` and `test_env_on.py`: all pass, and CI is green on this head. Leaving Walk unbound with a log line when an older ini already gives Caps Lock to another control (`binds_load`) is the right upgrade path. Caps Lock versus Alt as the default is the maintainers' call, and it's rebindable either way. First-person aiming while walking is still untested, as you say. <!-- github-sync:r:5876210432 -->
Owner

@hckrman101 commented on GitHub · 2026-11-12 16:58 UTC · original

Wouldn't shift/ctrl be a better key? More common

> [@hckrman101](https://github.com/hckrman101) commented on GitHub · 2026-11-12 16:58 UTC · [original](https://github.com/NotRexed/Hookshot/pull/2345#issuecomment-6830208045) Wouldn't shift/ctrl be a better key? More common <!-- github-sync:c:6830208045 -->
Owner

@mooki000 commented on GitHub · 2026-11-12 17:04 UTC · original

Both are taken in the default layout: Shift is B and Ctrl is the left-stick click (key_default in host/nn_hid.c), so Walk on either means moving one of those to another key. Caps Lock was the free key beside them, which is the only reason it was picked. The row is rebound on the Controls page like any other, so a player who wants Walk on Shift or Ctrl can swap them today.

Caps Lock has a cost, to be fair: every press also flips the system's Caps Lock state, and I have not tried it on a physical keyboard (the runs were headless, as the description says).

If you would rather have Walk on Ctrl by default, with the stick click moved to another key or left without one, say which and I will change the default table, the README row and the test. One thing to decide with it: a player whose saved bindings already name Ctrl for the stick click would start with Walk unbound (the existing rule for a default key that is taken), not with the two swapped.

> [@mooki000](https://github.com/mooki000) commented on GitHub · 2026-11-12 17:04 UTC · [original](https://github.com/NotRexed/Hookshot/pull/2345#issuecomment-6830337464) Both are taken in the default layout: Shift is B and Ctrl is the left-stick click (`key_default` in `host/nn_hid.c`), so Walk on either means moving one of those to another key. Caps Lock was the free key beside them, which is the only reason it was picked. The row is rebound on the Controls page like any other, so a player who wants Walk on Shift or Ctrl can swap them today. Caps Lock has a cost, to be fair: every press also flips the system's Caps Lock state, and I have not tried it on a physical keyboard (the runs were headless, as the description says). If you would rather have Walk on Ctrl by default, with the stick click moved to another key or left without one, say which and I will change the default table, the README row and the test. One thing to decide with it: a player whose saved bindings already name Ctrl for the stick click would start with Walk unbound (the existing rule for a default key that is taken), not with the two swapped. <!-- github-sync:c:6830337464 -->
Owner

@mooki000 commented on GitHub · 2026-11-12 18:48 UTC · original

Rebased onto main 3c2d80cf3; new head 2202ab57d.
Walk mode and speed now use 49 and 50, the numbers main reserves for Walk, because 52 went to Skip opening. Saved option names are unchanged.
No other gameplay change: Caps Lock, Hold, 45% and the 15–90% range remain. The default key still awaits the maintainer's preference.
Four input fixtures now declare CRT usage before headers; every assertion is retained. The fork's Windows run uses 45f3e06c2; all five patches are identical at this final head.
Focused checks: 24 passed with GCC 16 and 24 with Clang 23. A full run of the project's checks in my fork, Windows included, is green on 45f3e06c: the same five commits one main commit earlier (git range-diff marks each =), so it was not repeated for this head.
The earlier full suite was 497 passed, 3 failed, 20 skipped: two failures on main too, now fixed there; the compiler SIGKILL passed alone with fewer workers.
First windowless Kokiri run: three inspected menu pictures, Toggle walking/running 1.467 / 4.500 m/s, and Hold running 4.500 m/s.
Hold walking was not measured in that run: first-load shader compilation swallowed the short holds.
One ordinary completion run, same binary: Hold walking/running 1.469 / 4.500 m/s, nine readings each after the first.
Both walking results round to the description's 1.47 m/s, running to 4.50 m/s. Physical input and Windows gameplay remain untested.
Runs were built at 7e536c33, before the final refresh: the Walk code is identical, but the intervening main renderer changes were not rerun.
Joey-Magnus's earlier approval was for c3c7d19e and predates this refresh.

> [@mooki000](https://github.com/mooki000) commented on GitHub · 2026-11-12 18:48 UTC · [original](https://github.com/NotRexed/Hookshot/pull/2345#issuecomment-6832814741) Rebased onto main `3c2d80cf3`; new head `2202ab57d`. Walk mode and speed now use 49 and 50, the numbers main reserves for Walk, because 52 went to Skip opening. Saved option names are unchanged. No other gameplay change: Caps Lock, Hold, 45% and the 15–90% range remain. The default key still awaits the maintainer's preference. Four input fixtures now declare CRT usage before headers; every assertion is retained. The fork's Windows run uses `45f3e06c2`; all five patches are identical at this final head. Focused checks: 24 passed with GCC 16 and 24 with Clang 23. A full run of the project's checks in my fork, Windows included, is green on `45f3e06c`: the same five commits one main commit earlier (`git range-diff` marks each `=`), so it was not repeated for this head. The earlier full suite was 497 passed, 3 failed, 20 skipped: two failures on main too, now fixed there; the compiler SIGKILL passed alone with fewer workers. First windowless Kokiri run: three inspected menu pictures, Toggle walking/running 1.467 / 4.500 m/s, and Hold running 4.500 m/s. Hold walking was not measured in that run: first-load shader compilation swallowed the short holds. One ordinary completion run, same binary: Hold walking/running 1.469 / 4.500 m/s, nine readings each after the first. Both walking results round to the description's 1.47 m/s, running to 4.50 m/s. Physical input and Windows gameplay remain untested. Runs were built at `7e536c33`, before the final refresh: the Walk code is identical, but the intervening main renderer changes were not rerun. Joey-Magnus's earlier approval was for `c3c7d19e` and predates this refresh. <!-- github-sync:c:6832814741 -->
Commenting is not possible because the repository is archived.
No description provided.