fix(oot): the scarecrow's recall takes the note remaps too (kind 11) #281

Merged
HumanBean merged 1 commit from bluetoe/Longshot:lb/ocarina-kind11 into main 2026-11-14 00:56:07 +00:00
Contributor

Why

The Scarecrow's Song recall as an adult goes deaf for players who remapped the ocarina notes: the conversation with Bonooru asks for the song back, and during that performance the custom note keys did nothing - only the game's own buttons worked.

What changed

  • nx2/oot_patches.py: HOS_OC_BUTTONS gains kind 11, the scarecrow's recall of the recorded song. Kinds 1/3 (field ocarina), 2 (a song lesson) and 10 (the scarecrow's recording) already armed the note layer (host/nn_hid.c, oc_pad_word); the recall fell through to the game's own buttons. 13 stays out on purpose - that wait is a dialogue's and its buttons stay the game's.
  • tests/test_ocarina_wait.py: the check now reads the kind list the patch writes (and that 11 is in it while 13 is not), so the claim is testable without the game: red where the recall is missing, green here.

Flags and settings

None.

Measurements

main: 7315957c
this PR: lb/ocarina-kind11 @ 2c03ce9a
Hardware: i9-13900K (32 threads), 62 GB, Ubuntu 24.04, RTX 5070 Ti 16 GB (the play log's run)
Scene: the scarecrow's recall - the Bonooru conversation as an adult, the note wait's input kind 11 - with a field ocarina performance (kind 1) as the case that already worked; the game-free half is the note-wait patch of nx2/oot_patches.py
Method: the wait action reports the input kind it began with and whether the note layer armed, and the host logs one line per wait: oc: the note wait turned on (buttons) (the action's kind N) where the layer armed, (another way) where it did not; the check reads that same kind list out of the patch source
How to reproduce: python -I -B tests/test_ocarina_wait.py against each arm's source (this branch's test, main's nx2/oot_patches.py, is the red arm) - run twice per arm, interleaved, identical every time; the whole suite is python -I -B tests/run_all.py; the log lines are from the reporter's play log at the recall, on a build without the change
Baseline: main @ 7315957c

main @ 7315957c this PR @ 2c03ce9a
kinds the patch arms the five note controls for (the check's own output) 1 2 3 10 1 2 3 10 11
test_ocarina_wait.py, twice per arm FAIL: "the kinds that arm the note buttons are not the ocarina's performances: 1 2 3 10", both runs PASS, both runs
the whole suite, same box 465 passed, 0 failed, 63 skipped (the skips want spirv-val, the Vulkan headers and Windows-only tools) 465 passed, 0 failed, 63 skipped
a recall at the note wait, in the game 11 waits of kind 11 in the reporter's play log, every one (another way); 9 waits of kind 1 in the same log, every one (buttons) this PR's build at the same flow: not run yet, named under Testing

The game-free rows are the claim's measurement: the change is one entry in a list the host reads, and both arms are checked the same way twice. Nothing here is a performance number - no path gets faster or slower, one more input kind takes the branch the others already take.

Testing

Tested: the whole suite on this branch and on main on the same box: python -I -B tests/run_all.py 465 passed, 0 failed, 63 skipped each; the focused check twice per arm (the red/green pair in the table); test_ocarina_notes and test_ocarina_note_bindings green (the five note controls and their bindings).

Not tested: the recall flow in the game on this PR's build - the scripted Bonooru conversation has not reached the note wait in the runs so far, so the (buttons) line for kind 11 on this build is still to be captured. The other note kinds (1/2/3/10) are untouched by the one line.

Needs other testers: None: the reporter plays the recall on their own save and will add the log line here.

Screenshots

Nothing on screen.

Risk and rollback

Kinds the game does not treat as ocarina performances could take the five buttons away from other actions: the wait action is the only place the layer arms, and 11 is a performance of the same actor as 10 (recording), whose notes are the same five buttons. Reverting is one line.

Reviewer notes

One define and a comment; the test reads the kind list so the entry cannot quietly drop again. Host-side behaviour is unchanged code: hos_oc_wait=1 already drives the swap for the other kinds.

Issues

None.

Checklist

For everyone

  • One topic.
  • The title is a Conventional Commit (type(scope): description).
  • Rebased on current main.
  • python -I -B tests/run_all.py run and passing (any failure that also fails on main is named above).
  • Tested in the game, or what wasn't is named under Testing.
  • Testing filled in: what was tested, what wasn't, and what needs other testers (with test requests).
  • Measured: main and this PR at named commits, on the same PC, scene and settings, at least 2 interleaved runs each, the median reported.
  • 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.

If applicable

  • AI assistance recorded with Assisted-by: / Co-Authored-By: trailers.
  • 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.
## Why The Scarecrow's Song recall as an adult goes deaf for players who remapped the ocarina notes: the conversation with Bonooru asks for the song back, and during that performance the custom note keys did nothing - only the game's own buttons worked. ## What changed - nx2/oot_patches.py: `HOS_OC_BUTTONS` gains kind 11, the scarecrow's recall of the recorded song. Kinds 1/3 (field ocarina), 2 (a song lesson) and 10 (the scarecrow's recording) already armed the note layer (host/nn_hid.c, `oc_pad_word`); the recall fell through to the game's own buttons. 13 stays out on purpose - that wait is a dialogue's and its buttons stay the game's. - tests/test_ocarina_wait.py: the check now reads the kind list the patch writes (and that 11 is in it while 13 is not), so the claim is testable without the game: red where the recall is missing, green here. ## Flags and settings None. ## Measurements main: 7315957c this PR: lb/ocarina-kind11 @ 2c03ce9a Hardware: i9-13900K (32 threads), 62 GB, Ubuntu 24.04, RTX 5070 Ti 16 GB (the play log's run) Scene: the scarecrow's recall - the Bonooru conversation as an adult, the note wait's input kind 11 - with a field ocarina performance (kind 1) as the case that already worked; the game-free half is the note-wait patch of nx2/oot_patches.py Method: the wait action reports the input kind it began with and whether the note layer armed, and the host logs one line per wait: `oc: the note wait turned on (buttons) (the action's kind N)` where the layer armed, `(another way)` where it did not; the check reads that same kind list out of the patch source How to reproduce: `python -I -B tests/test_ocarina_wait.py` against each arm's source (this branch's test, main's nx2/oot_patches.py, is the red arm) - run twice per arm, interleaved, identical every time; the whole suite is `python -I -B tests/run_all.py`; the log lines are from the reporter's play log at the recall, on a build without the change Baseline: main @ 7315957c | | main @ 7315957c | this PR @ 2c03ce9a | |---|---|---| | kinds the patch arms the five note controls for (the check's own output) | 1 2 3 10 | 1 2 3 10 11 | | `test_ocarina_wait.py`, twice per arm | FAIL: "the kinds that arm the note buttons are not the ocarina's performances: 1 2 3 10", both runs | PASS, both runs | | the whole suite, same box | 465 passed, 0 failed, 63 skipped (the skips want spirv-val, the Vulkan headers and Windows-only tools) | 465 passed, 0 failed, 63 skipped | | a recall at the note wait, in the game | 11 waits of kind 11 in the reporter's play log, every one `(another way)`; 9 waits of kind 1 in the same log, every one `(buttons)` | this PR's build at the same flow: not run yet, named under Testing | The game-free rows are the claim's measurement: the change is one entry in a list the host reads, and both arms are checked the same way twice. Nothing here is a performance number - no path gets faster or slower, one more input kind takes the branch the others already take. ## Testing **Tested:** the whole suite on this branch and on main on the same box: `python -I -B tests/run_all.py` 465 passed, 0 failed, 63 skipped each; the focused check twice per arm (the red/green pair in the table); `test_ocarina_notes` and `test_ocarina_note_bindings` green (the five note controls and their bindings). **Not tested:** the recall flow in the game on this PR's build - the scripted Bonooru conversation has not reached the note wait in the runs so far, so the `(buttons)` line for kind 11 on this build is still to be captured. The other note kinds (1/2/3/10) are untouched by the one line. **Needs other testers:** None: the reporter plays the recall on their own save and will add the log line here. ## Screenshots Nothing on screen. ## Risk and rollback Kinds the game does not treat as ocarina performances could take the five buttons away from other actions: the wait action is the only place the layer arms, and 11 is a performance of the same actor as 10 (recording), whose notes are the same five buttons. Reverting is one line. ## Reviewer notes One define and a comment; the test reads the kind list so the entry cannot quietly drop again. Host-side behaviour is unchanged code: `hos_oc_wait=1` already drives the swap for the other kinds. ## Issues None. ## Checklist ### For everyone - [x] One topic. - [x] The title is a Conventional Commit (`type(scope): description`). - [x] Rebased on current `main`. - [x] `python -I -B tests/run_all.py` run and passing (any failure that also fails on `main` is named above). - [x] Tested in the game, or what wasn't is named under Testing. - [x] Testing filled in: what was tested, what wasn't, and what needs other testers (with test requests). - [x] Measured: main and this PR at named commits, on the same PC, scene and settings, at least 2 interleaved runs each, the median reported. - [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. ### If applicable - [x] AI assistance recorded with `Assisted-by:` / `Co-Authored-By:` trailers. - [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.
bluetoe changed title from fix(oot): the scarecrow recall takes the note remaps too (kind 11) to WIP: fix(oot): the scarecrow recall takes the note remaps too (kind 11) 2026-11-13 19:28:18 +00:00
bluetoe force-pushed lb/ocarina-kind11 from 1cd2f91bd2
Some checks failed
PR description / Description follows the template (pull_request_target) Successful in 5s
CI / Conventional Commit title (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Has been cancelled
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Has been cancelled
CI / Workflow lint (actionlint) (pull_request) Has been cancelled
Third-party parts / As their notes say (pull_request) Has been cancelled
Third-party parts / The same as upstream (pull_request) Has been cancelled
to 66fb8b785f
Some checks failed
PR description / Description follows the template (pull_request_target) Successful in 4s
CI / Conventional Commit title (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Has been cancelled
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Has been cancelled
CI / Workflow lint (actionlint) (pull_request) Has been cancelled
Third-party parts / As their notes say (pull_request) Has been cancelled
Third-party parts / The same as upstream (pull_request) Has been cancelled
2026-11-13 19:39:17 +00:00
Compare
bluetoe force-pushed lb/ocarina-kind11 from 66fb8b785f
Some checks failed
PR description / Description follows the template (pull_request_target) Successful in 4s
CI / Conventional Commit title (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Has been cancelled
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Has been cancelled
CI / Workflow lint (actionlint) (pull_request) Has been cancelled
Third-party parts / As their notes say (pull_request) Has been cancelled
Third-party parts / The same as upstream (pull_request) Has been cancelled
to fbb4b518bc
Some checks failed
PR description / Description follows the template (pull_request_target) Successful in 3s
CI / Conventional Commit title (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Has been cancelled
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Has been cancelled
CI / Workflow lint (actionlint) (pull_request) Has been cancelled
Third-party parts / As their notes say (pull_request) Has been cancelled
Third-party parts / The same as upstream (pull_request) Has been cancelled
2026-11-13 19:39:30 +00:00
Compare
bluetoe force-pushed lb/ocarina-kind11 from fbb4b518bc
Some checks failed
PR description / Description follows the template (pull_request_target) Successful in 3s
CI / Conventional Commit title (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Has been cancelled
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Has been cancelled
CI / Workflow lint (actionlint) (pull_request) Has been cancelled
Third-party parts / As their notes say (pull_request) Has been cancelled
Third-party parts / The same as upstream (pull_request) Has been cancelled
to 609b9e566d
Some checks failed
PR description / Description follows the template (pull_request_target) Successful in 3s
CI / Conventional Commit title (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Has been cancelled
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Has been cancelled
CI / Workflow lint (actionlint) (pull_request) Has been cancelled
Third-party parts / As their notes say (pull_request) Has been cancelled
Third-party parts / The same as upstream (pull_request) Has been cancelled
2026-11-13 22:38:19 +00:00
Compare
bluetoe force-pushed lb/ocarina-kind11 from 609b9e566d
Some checks failed
PR description / Description follows the template (pull_request_target) Successful in 3s
CI / Conventional Commit title (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Has been cancelled
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Has been cancelled
CI / Workflow lint (actionlint) (pull_request) Has been cancelled
Third-party parts / As their notes say (pull_request) Has been cancelled
Third-party parts / The same as upstream (pull_request) Has been cancelled
to 2c03ce9ab5
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 / The same as upstream (pull_request) Blocked by required conditions
Third-party parts / As their notes say (pull_request) Blocked by required conditions
PR description / Description follows the template (pull_request_target) Successful in 3s
Website / Website on Cloudflare (pull_request_target) Has been skipped
2026-11-13 22:39:48 +00:00
Compare
bluetoe changed title from WIP: fix(oot): the scarecrow recall takes the note remaps too (kind 11) to fix(oot): the scarecrow's recall takes the note remaps too (kind 11) 2026-11-13 22:41:05 +00:00
HumanBean added this to the v3.0.0 milestone 2026-11-14 00:56:10 +00:00
Owner

Post-merge code review of 2c03ce9a, which is already on main as b7a46d6b. forge.py won't post a formal review on a merged PR, so this is a comment. Read only: nothing built or run here.

Looks right; nothing to change. Kind 11 is the adult's playback of the recorded song to Bonooru, a player performance of the same actor as kind 10, so arming the note layer for it is the correct fix. HOS_OC_BUTTONS is the one macro both arming sites use (the entry and the tick's re-arm), so the tick can't drop it again. 13 (a dialogue's wait) stays out. The test now reads the kind set out of OC_DECL and fails on main, which makes the claim checkable without the game. The CI jobs for the head never ran (still pending); only the description check did.

Notes, no action needed:

  • Untested in game. The PR says so: the (buttons) line for kind 11 on this build was still to be captured, and no comment has added it since. For the release notes, the fix is verified by reading and by the game-free check, not in game. A one-line confirmation from the reporter's save would close it.
  • Re-applying the patch by hand to a gen patched before this change keeps kind 10 only. patch_ocarina_wait sees neither the old nor the new entry text and returns the file unchanged. Real builds re-lift (the lift key covers oot_patches.py), so only a by-hand python -I nx2/oot_patches.py hits this.

v3.0.0: already in, since it's on main. Low risk: one entry in a list, and only during a note wait of kind 11.

Post-merge code review of 2c03ce9a, which is already on `main` as b7a46d6b. `forge.py` won't post a formal review on a merged PR, so this is a comment. Read only: nothing built or run here. **Looks right; nothing to change.** Kind 11 is the adult's playback of the recorded song to Bonooru, a player performance of the same actor as kind 10, so arming the note layer for it is the correct fix. `HOS_OC_BUTTONS` is the one macro both arming sites use (the entry and the tick's re-arm), so the tick can't drop it again. 13 (a dialogue's wait) stays out. The test now reads the kind set out of `OC_DECL` and fails on main, which makes the claim checkable without the game. The CI jobs for the head never ran (still pending); only the description check did. Notes, no action needed: - **Untested in game.** The PR says so: the `(buttons)` line for kind 11 on this build was still to be captured, and no comment has added it since. For the release notes, the fix is verified by reading and by the game-free check, not in game. A one-line confirmation from the reporter's save would close it. - **Re-applying the patch by hand to a gen patched before this change keeps kind 10 only.** `patch_ocarina_wait` sees neither the old nor the new entry text and returns the file unchanged. Real builds re-lift (the lift key covers `oot_patches.py`), so only a by-hand `python -I nx2/oot_patches.py` hits this. **v3.0.0:** already in, since it's on `main`. Low risk: one entry in a list, and only during a note wait of kind 11.
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 / The same as upstream (pull_request) Blocked by required conditions
Third-party parts / As their notes say (pull_request) Blocked by required conditions
PR description / Description follows the template (pull_request_target) Successful in 3s
Website / Website on Cloudflare (pull_request_target) Has been skipped
Some workflows are waiting to be reviewed.
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
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!281
No description provided.