fix(menu): show learned songs correctly in the inventory editor #429

Open
gustavogyn wants to merge 1 commit from gustavogyn/Longshot:fix/song-inventory-flags into main
First-time contributor

The Debug inventory editor keeps showing learned songs as Locked because it reads their pouch quantity. Unlock can succeed in the game while the editor still offers Unlock; this change makes its status and toggle follow the saved learned-song flag.

Why

Songs set saved IsGet.Item_Melody_* Bool flags and do not retain ordinary pouch quantities. The editor must use those flags to display and toggle the learned state.

What changed

  • host/hos_main.c: map the twelve song entries to their learned flags; read those flags for status, toggle only the selected flag, report unavailable state, and use the same values in the inventory diagnostic log. Ordinary items and mask handling retain their pouch paths.
  • tests/test_oot_song_inventory.py: compile the real host helpers with fake GameData and pouch calls. Cover all twelve mappings, unlock/relock, missing flags, refused writes, quantity requests, and an ordinary item.
  • docs/tested/: record the player's confirmed Linux run and a separate unattended Epona toggle run with screenshots.

Flags and settings

None. No new settings, environment switches, renderer API changes, or shader changes.

Measurements

main: 5e072fc8c2 (2026-11-14)
this PR: fix/song-inventory-flags @ ba05271c85

Hardware: RTX 5090, NVIDIA 620.70.06, Ryzen 9 9950X3D, 31 GiB RAM, CachyOS Linux, kernel 7.3.4-1-cachyos, Wayland.
Scene: Hyrule Field, adult Link; 3840x2160, Debug tools enabled. This is a correctness fix; no frame-rate or performance claim.
Method: game-free regression against the host helpers, plus the player's manual validation and session log. The manual build was main 0caf0618 with this song fix (source 71a08907). The two subsequent upstream commits change renderer code and test records, not this inventory path; the cleanup since that run changes comments and mask-only local setup, not the song logic.
How to reproduce: load a save with a learned song, press F1, enable Debug tools, open Inventory > Quest, inspect that song, then Relock and Unlock it. Its status must match the game's song list.

Check main @ 5e072fc8c2 this PR @ ba05271c85
Learned song, empty pouch Editor reports Locked Editor reports Unlocked from the saved flag
Selected flag edit Ordinary pouch operation does not provide the correct learned-state toggle Only the selected learned flag changes

Player log, manual fixed build:

cheats: song Item_Melody_StormSong relocked (had 1, now 0)
cheats: song Item_Melody_StormSong unlocked (had 0, now 1)
cheats: song Item_Melody_StormSong relocked (had 1, now 0)
cheats: song Item_Melody_StormSong unlocked (had 0, now 1)
cheats: song Item_Melody_StormSong relocked (had 1, now 0)

Unattended run02: this branch on main 5e072fc8, built with dev_packs.py (source dd8ba6a9), in a separate runtime and virtual display. Same PC as above; 1600x900 window / 1600x896 output, DLSS Transformer 2 (M), 83% render resolution, frame generation Off, RX_VK_PRECOMPILE=0, HOS_AUDIO=0. A copied save loaded Hyrule Field with adult Link on horseback. Enter performed one relock/unlock cycle; mouse clicks performed another. The menu showed Locked / Unlock and Unlocked / Relock after the respective operations. The original save folders were read-only in the test process; afterward all 14 source files matched their original SHA-256, size and modification time, and the shared-save links were unchanged.

cheats: song Item_Melody_EponaSong relocked (had 1, now 0)
cheats: song Item_Melody_EponaSong unlocked (had 0, now 1)
cheats: song Item_Melody_EponaSong relocked (had 1, now 0)
cheats: song Item_Melody_EponaSong unlocked (had 0, now 1)

Regression against main 5e072fc8: FAIL:128 oot_item_count(&c, name) == 1. With this PR: PASS: all 12 songs read and toggle their saved flags; ordinary inventory still uses the pouch.

Testing

Tested: Live song checks cover Epona's Song and Song of Storms. The player confirmed the corrected UI in the game on the Linux configuration above; the unattended run02 also verified both Epona toggle directions with Enter and the mouse, with screenshots and flag-transition logs. The regression passes with GCC and Clang, including refused writes and missing flags. The repository test-record validator passes. The full branch suite is recorded below.

Full branch suite: 543 passed, 3 failed, 16 skipped in 171 s (python -I -B tests/run_all.py --jobs 4).

The known baseline failures are test_framegen_resources.py (missing fixture driver-gate declarations), test_module_ids.py (stale source-function signature), and test_pad_layout.py (missing fixture HoldToggle declaration). They were reproduced from unchanged upstream files; this PR does not change their source inputs.

Not tested: Native Windows compilation/runtime and other GPUs. The ten remaining mappings have game-free coverage; they were not changed during the live runs.

Needs other testers:
None required before review by the author's decision. Windows compilation and runtime remain untested; a Windows check would be welcome but is not being requested as a review prerequisite for this small host-logic fix.

Screenshots

Original report and run02 screenshots

Original report: learned songs still shown as Locked

Epona's Song after Relock

Epona's Song after Unlock

The original report image predates the fix; its exact commit was not recorded. The two new screenshots are from this PR on main 5e072fc8, in the same Hyrule Field scene: Epona's Song Locked / Unlock, then Unlocked / Relock. They were captured from the actual game window, with a copied save.

Risk and rollback

Limited to debug inventory operations for the twelve fixed songs. An incorrect mapping could affect a different learned flag; the regression independently checks all mappings against their IsGet. name hashes and verifies that unrelated state is unchanged. Missing flags are unavailable and refused writes do not fall back to pouch edits. Revert this commit to restore the previous editor behavior.

Reviewer notes

Start with oot_item_count and the song branch in oot_inventory_edit; the regression exercises those actual helpers. The change uses existing GameData helpers and standard C types and does not add platform-specific code or dependencies.

The author requested that this minor correctness fix be marked ready using the Linux game validation and regression evidence already recorded. Windows validation and the checklist's interleaved gameplay comparison remain outstanding and are disclosed above; they have not been represented as completed.

Issues

No issue linked; reported and reproduced by the player.

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). No additional test request is required before review by the author's decision; Windows is explicitly untested.
  • Measured: main and this PR at named commits, on the same PC, scene and settings, at least 2 interleaved runs each, the median reported. Correctness regression, screenshots and flag-transition logs are provided above. Interleaved gameplay runs were not collected; the author has requested review with this limitation disclosed.
  • 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.
  • Screenshots for a change that shows on screen. Original report and both fixed toggle states attached.
  • A file in docs/tested/ for each new measured run (format in docs/tested-configurations.md; no appended row or assembled view).
  • 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. The new regression compiles the actual host helpers.
  • Host code builds on both Windows (llvm-mingw) and Linux, with UTF-8 paths. Linux built and tested; Windows not built. The author has waived Windows validation as a prerequisite for review; this box remains unticked.
  • Docs updated.
The Debug inventory editor keeps showing learned songs as Locked because it reads their pouch quantity. Unlock can succeed in the game while the editor still offers Unlock; this change makes its status and toggle follow the saved learned-song flag. ## Why Songs set saved `IsGet.Item_Melody_*` Bool flags and do not retain ordinary pouch quantities. The editor must use those flags to display and toggle the learned state. ## What changed - `host/hos_main.c`: map the twelve song entries to their learned flags; read those flags for status, toggle only the selected flag, report unavailable state, and use the same values in the inventory diagnostic log. Ordinary items and mask handling retain their pouch paths. - `tests/test_oot_song_inventory.py`: compile the real host helpers with fake GameData and pouch calls. Cover all twelve mappings, unlock/relock, missing flags, refused writes, quantity requests, and an ordinary item. - `docs/tested/`: record the player's confirmed Linux run and a separate unattended Epona toggle run with screenshots. ## Flags and settings None. No new settings, environment switches, renderer API changes, or shader changes. ## Measurements main: 5e072fc8c2adadba5ea610148be1c47800ba0cca (2026-11-14) this PR: fix/song-inventory-flags @ ba05271c85fa657982f02740c0d95f762d199e3b Hardware: RTX 5090, NVIDIA 620.70.06, Ryzen 9 9950X3D, 31 GiB RAM, CachyOS Linux, kernel 7.3.4-1-cachyos, Wayland. Scene: Hyrule Field, adult Link; 3840x2160, Debug tools enabled. This is a correctness fix; no frame-rate or performance claim. Method: game-free regression against the host helpers, plus the player's manual validation and session log. The manual build was main 0caf0618 with this song fix (source 71a08907). The two subsequent upstream commits change renderer code and test records, not this inventory path; the cleanup since that run changes comments and mask-only local setup, not the song logic. How to reproduce: load a save with a learned song, press F1, enable Debug tools, open Inventory > Quest, inspect that song, then Relock and Unlock it. Its status must match the game's song list. | Check | main @ 5e072fc8c2adadba5ea610148be1c47800ba0cca | this PR @ ba05271c85fa657982f02740c0d95f762d199e3b | |---|---|---| | Learned song, empty pouch | Editor reports Locked | Editor reports Unlocked from the saved flag | | Selected flag edit | Ordinary pouch operation does not provide the correct learned-state toggle | Only the selected learned flag changes | Player log, manual fixed build: ```text cheats: song Item_Melody_StormSong relocked (had 1, now 0) cheats: song Item_Melody_StormSong unlocked (had 0, now 1) cheats: song Item_Melody_StormSong relocked (had 1, now 0) cheats: song Item_Melody_StormSong unlocked (had 0, now 1) cheats: song Item_Melody_StormSong relocked (had 1, now 0) ``` Unattended run02: this branch on main `5e072fc8`, built with `dev_packs.py` (source `dd8ba6a9`), in a separate runtime and virtual display. Same PC as above; 1600x900 window / 1600x896 output, DLSS Transformer 2 (M), 83% render resolution, frame generation Off, `RX_VK_PRECOMPILE=0`, `HOS_AUDIO=0`. A copied save loaded Hyrule Field with adult Link on horseback. Enter performed one relock/unlock cycle; mouse clicks performed another. The menu showed **Locked / Unlock** and **Unlocked / Relock** after the respective operations. The original save folders were read-only in the test process; afterward all 14 source files matched their original SHA-256, size and modification time, and the shared-save links were unchanged. ```text cheats: song Item_Melody_EponaSong relocked (had 1, now 0) cheats: song Item_Melody_EponaSong unlocked (had 0, now 1) cheats: song Item_Melody_EponaSong relocked (had 1, now 0) cheats: song Item_Melody_EponaSong unlocked (had 0, now 1) ``` Regression against main `5e072fc8`: `FAIL:128 oot_item_count(&c, name) == 1`. With this PR: `PASS: all 12 songs read and toggle their saved flags; ordinary inventory still uses the pouch`. ## Testing **Tested:** Live song checks cover Epona's Song and Song of Storms. The player confirmed the corrected UI in the game on the Linux configuration above; the unattended run02 also verified both Epona toggle directions with Enter and the mouse, with screenshots and flag-transition logs. The regression passes with GCC and Clang, including refused writes and missing flags. The repository test-record validator passes. The full branch suite is recorded below. Full branch suite: `543 passed, 3 failed, 16 skipped in 171 s` (`python -I -B tests/run_all.py --jobs 4`). The known baseline failures are `test_framegen_resources.py` (missing fixture driver-gate declarations), `test_module_ids.py` (stale source-function signature), and `test_pad_layout.py` (missing fixture HoldToggle declaration). They were reproduced from unchanged upstream files; this PR does not change their source inputs. **Not tested:** Native Windows compilation/runtime and other GPUs. The ten remaining mappings have game-free coverage; they were not changed during the live runs. **Needs other testers:** None required before review by the author's decision. Windows compilation and runtime remain untested; a Windows check would be welcome but is not being requested as a review prerequisite for this small host-logic fix. ## Screenshots [Original report and run02 screenshots](https://git.magicbean.dev/MagicBeanDev/Longshot/pulls/429#issuecomment-17998) ![Original report: learned songs still shown as Locked](https://git.magicbean.dev/attachments/39377a5d-4ca9-45a2-826f-2bdfd1dd745e) ![Epona's Song after Relock](https://git.magicbean.dev/attachments/89c3b683-97c6-4bd3-b659-17043cdd3ef1) ![Epona's Song after Unlock](https://git.magicbean.dev/attachments/b77491e5-6df1-4d53-b45b-17a60314d309) The original report image predates the fix; its exact commit was not recorded. The two new screenshots are from this PR on main `5e072fc8`, in the same Hyrule Field scene: Epona's Song **Locked / Unlock**, then **Unlocked / Relock**. They were captured from the actual game window, with a copied save. ## Risk and rollback Limited to debug inventory operations for the twelve fixed songs. An incorrect mapping could affect a different learned flag; the regression independently checks all mappings against their `IsGet.` name hashes and verifies that unrelated state is unchanged. Missing flags are unavailable and refused writes do not fall back to pouch edits. Revert this commit to restore the previous editor behavior. ## Reviewer notes Start with `oot_item_count` and the song branch in `oot_inventory_edit`; the regression exercises those actual helpers. The change uses existing GameData helpers and standard C types and does not add platform-specific code or dependencies. The author requested that this minor correctness fix be marked ready using the Linux game validation and regression evidence already recorded. Windows validation and the checklist's interleaved gameplay comparison remain outstanding and are disclosed above; they have not been represented as completed. ## Issues No issue linked; reported and reproduced by the player. ## 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). No additional test request is required before review by the author's decision; Windows is explicitly untested. - [ ] Measured: main and this PR at named commits, on the same PC, scene and settings, at least 2 interleaved runs each, the median reported. Correctness regression, screenshots and flag-transition logs are provided above. Interleaved gameplay runs were not collected; the author has requested review with this limitation disclosed. - [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] Screenshots for a change that shows on screen. Original report and both fixed toggle states attached. - [x] A file in `docs/tested/` for each new measured run (format in `docs/tested-configurations.md`; no appended row or assembled view). - [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. The new regression compiles the actual host helpers. - [ ] Host code builds on both Windows (llvm-mingw) and Linux, with UTF-8 paths. Linux built and tested; Windows not built. The author has waived Windows validation as a prerequisite for review; this box remains unticked. - [x] Docs updated.
fix(menu): show learned songs correctly in the inventory editor
Some checks failed
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) Blocked by required conditions
Website / Website on Cloudflare (pull_request_target) Has been skipped
PR description / Description follows the template (pull_request_target) Failing after 3s
ba05271c85
Read and toggle each song's saved learned flag instead of its pouch
quantity, and report that state in the inventory probe. Cover all twelve
mappings and refused edits with a game-free regression.

Assisted-by: OpenAI Codex
Co-Authored-By: OpenAI Codex <[email protected]>
Author
First-time contributor

Captured the actual game window on an isolated save copy in Hyrule Field. Enter and the mouse action button each completed a relock/unlock cycle. The original save files and shared-save links were verified unchanged after the test.

Original report image (exact build commit was not recorded):

Original report: learned songs still shown as Locked

this PR @ ba05271c85 after Relock: Epona's Song is Locked and the action reads Unlock.

Epona's Song after Relock

this PR @ ba05271c85 after Unlock: Epona's Song is Unlocked and the action reads Relock.

Epona's Song after Unlock

The new screenshots come from the branch build on main 5e072fc8 (source dd8ba6a9), before committing the already-built source. The configuration and run are recorded in docs/tested/2026-11-14-song-inventory-gustavo-run02.md.

Captured the actual game window on an isolated save copy in Hyrule Field. Enter and the mouse action button each completed a relock/unlock cycle. The original save files and shared-save links were verified unchanged after the test. Original report image (exact build commit was not recorded): ![Original report: learned songs still shown as Locked](https://git.magicbean.dev/attachments/39377a5d-4ca9-45a2-826f-2bdfd1dd745e) this PR @ ba05271c85fa657982f02740c0d95f762d199e3b after Relock: Epona's Song is Locked and the action reads Unlock. ![Epona's Song after Relock](https://git.magicbean.dev/attachments/89c3b683-97c6-4bd3-b659-17043cdd3ef1) this PR @ ba05271c85fa657982f02740c0d95f762d199e3b after Unlock: Epona's Song is Unlocked and the action reads Relock. ![Epona's Song after Unlock](https://git.magicbean.dev/attachments/b77491e5-6df1-4d53-b45b-17a60314d309) The new screenshots come from the branch build on main 5e072fc8 (source dd8ba6a9), before committing the already-built source. The configuration and run are recorded in docs/tested/2026-11-14-song-inventory-gustavo-run02.md.
Author
First-time contributor

Added the original report image and actual game screenshots of both Epona toggle states. Run02 verified Enter and mouse activation using a copied save; original save checksums, modification times and links were unchanged. Windows validation and interleaved gameplay comparisons remain outstanding, so this stays WIP.

Added the original report image and actual game screenshots of both Epona toggle states. Run02 verified Enter and mouse activation using a copied save; original save checksums, modification times and links were unchanged. Windows validation and interleaved gameplay comparisons remain outstanding, so this stays WIP.
Author
First-time contributor

Clarified the live-testing scope and recorded the source-reading regression in the checklist. Epona and Storms were checked in the game on Linux; the remaining ten mappings have game-free coverage.

Clarified the live-testing scope and recorded the source-reading regression in the checklist. Epona and Storms were checked in the game on Linux; the remaining ten mappings have game-free coverage.
Author
First-time contributor

Marking this minor host-logic fix ready for review at the author's request, based on the existing Linux game validation, screenshots and regression evidence. Windows is unavailable to the author and remains untested. The change uses existing GameData helpers and standard C types, with no new platform-specific code or dependencies. The unmet Windows and interleaved-gameplay checklist items remain unticked and disclosed; they are being waived as prerequisites for review.

Marking this minor host-logic fix ready for review at the author's request, based on the existing Linux game validation, screenshots and regression evidence. Windows is unavailable to the author and remains untested. The change uses existing GameData helpers and standard C types, with no new platform-specific code or dependencies. The unmet Windows and interleaved-gameplay checklist items remain unticked and disclosed; they are being waived as prerequisites for review.
gustavogyn changed title from WIP: fix(menu): show learned songs correctly in the inventory editor to fix(menu): show learned songs correctly in the inventory editor 2026-11-14 14:21:30 +00:00
Some checks failed
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) Blocked by required conditions
Website / Website on Cloudflare (pull_request_target) Has been skipped
PR description / Description follows the template (pull_request_target) Failing after 3s
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/song-inventory-flags:gustavogyn-fix/song-inventory-flags'
git switch 'gustavogyn-fix/song-inventory-flags'
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!429
No description provided.