Redesign the Debug tab, Inventory and Teleport pages, and add a 5K output #1670

Merged
ArmstrongThomas merged 2 commits from feat/debug-menu-redesign into main 2026-11-10 18:04:11 +00:00
ArmstrongThomas commented 2026-11-10 12:53:03 +00:00 (Migrated from github.com)

Requested by Tommy

The Debug tab was one long list where the tools were hard to scan, the inventory editor was a plain list of 85 lines, and clicking a destination in the teleport list travelled at once. This redesigns the Debug tab and its two pages so the tools are grouped, readable at every menu size, and safe to click. It also adds a 5120x2880 (5K) Output resolution, which 5K screens did not have.

What changed

Debug tab

  • The tools are laid out in two columns under Player (Heart protection, No-clip flight, Switch age, Inventory), Travel (Teleport, Mark position, Return to mark) and Camera & world (Free camera, Set time). The Developer rows stay across the foot.
  • Each row is boxed like the other tabs' rows (name cell and value cell, gold bar and glow on the selection).
  • It falls back to one column when a name would not fit whole beside its value (Menu size Medium or Large on smaller windows). Value cells shrink toward their narrowest before that.
  • Up/Down follow the layout. On/off tools use the Off | On halves: Left picks Off, Right picks On, confirm flips, and a click picks a half.
  • Switch age shows Kid | Adult with Link's current age lit once a save is loaded. The game side now reports Sequence_IsChildhood alongside the inventory counts (OOT_CHEAT_AGE_ID).
  • Inventory item and Change quantity stay in the row table but are not shown, since the Inventory page edits every amount.

Inventory page

  • A grid of cards with section tabs (All, Equipment, Items, Masks, Upgrades, Quest) kept on one line, and a page control (arrows, "Page n of m", the range).
  • Owned, locked, quantity and unavailable states each look different. On the title screen one note replaces "Load a save" on every card.
  • An action button for Unlock / Relock / Edit amount. Q/E while editing an amount ends the edit and switches section.

Teleport page

  • Destination cards grouped under Overworld and Dungeons headings. Notes such as "adult only" stay on the card.
  • A click selects a card. Travel, Enter or A goes. Up/Down move by row inside the sections and keep the column.

Output resolution: 5120x2880 (5K) (its own commit)

  • ID 5, after 5120x1440 in the menu's order, with its hint, the host's size lookup (host/nn_applet.c), the readme, docs/development.md and tests/test_output_resolution.py, following #1290.
  • The render-target pool would scale to 1220 MB at 5K, but the game crashed at boot with 1220 MB and with 1000 MB (its own reservation fails). The 5K output's pool is kept to 900 MB; every other output keeps its whole scaled pool (4K 687 MB, 5120x1440 610 MB, a 32:9 screen at 4K 1373 MB, unchanged; tests/test_rt_pool_minimum.py has 5K cases). At 900 MB and 800 MB the game booted, loaded a save and played with the 3D at the full 5120x2880 (Render resolution 100%). HOS_RT_POOL_MB still overrides it.
  • ID 5 is also claimed by #1641 (1280x720). As agreed in review, storing output_res as the size instead of an index (so players can set custom resolutions in the config) comes in a follow-up PR; until then whichever of the two lands second renumbers.

Unchanged: the mouse wheel still only scrolls (#1557), on both pages too. Apart from the 5K row, Graphics, Gameplay and Controls are untouched. Outside the menu, the redesign only adds the age report in host/hos_main.c and its id in gpu/vk/oot_cheat_items.h.

Testing

  • Windows, RTX 4090, the standalone build from this branch. Headless runs at 3840x2160 and 2560x1500 on the title screen and with a save loaded, at Menu size Small, Medium and Large, plus 1280x1024 and a 1080x1440 window. Reviewed in game by hand at Small; the Medium and Large fixes were checked in the headless runs.
  • Switch age: with a save loaded the row showed Kid, Right switched Link to adult, and the row then showed Adult.
  • 5K: booted headless with HOS_OUTPUT_RES=5 into a save at Render resolution 100% with the 900 MB pool, walked around, no crash. Not yet run at 5K: the Castle Town guard-house conversation.
  • python -I -B tests/run_all.py: the same results as main on this machine (it has no g++ on PATH, so some C++ checks skip or fail the same way on both). The menu, output-resolution and render-target pool checks were also compiled and run here with clang and pass: test_rt_pool_minimum, test_output_resolution, test_menu_keys, test_rumble_menu, test_menu_hit, test_menu_utf8, test_menu_restart. tests/test_rumble_menu.py's wheel check now names the new pages' mouse functions. tests/test_menu_keys.py's source checks pass.

Screenshots

Debug tab, Menu size Small (2560x1500):

Debug tab, small

Debug tab, Menu size Medium (2560x1500), one column:

Debug tab, medium

Inventory with a save loaded (3840x2160, Small):

Inventory

Inventory on the title screen (2560x1500, Small) and at Large:

Inventory, title screen

Inventory, large

Output resolution set to 5120x2880 (2560x1440 window):

Output resolution 5K

Teleport (3840x2160, Small):

Teleport

🤖 Generated with Claude Code

<!-- claude-projects-attribution: {"github_login":"ArmstrongThomas"} --> _Requested by **Tommy**_ The Debug tab was one long list where the tools were hard to scan, the inventory editor was a plain list of 85 lines, and clicking a destination in the teleport list travelled at once. This redesigns the Debug tab and its two pages so the tools are grouped, readable at every menu size, and safe to click. It also adds a 5120x2880 (5K) Output resolution, which 5K screens did not have. ## What changed **Debug tab** - The tools are laid out in two columns under **Player** (Heart protection, No-clip flight, Switch age, Inventory), **Travel** (Teleport, Mark position, Return to mark) and **Camera & world** (Free camera, Set time). The Developer rows stay across the foot. - Each row is boxed like the other tabs' rows (name cell and value cell, gold bar and glow on the selection). - It falls back to one column when a name would not fit whole beside its value (Menu size Medium or Large on smaller windows). Value cells shrink toward their narrowest before that. - Up/Down follow the layout. On/off tools use the Off | On halves: Left picks Off, Right picks On, confirm flips, and a click picks a half. - **Switch age** shows **Kid | Adult** with Link's current age lit once a save is loaded. The game side now reports `Sequence_IsChildhood` alongside the inventory counts (`OOT_CHEAT_AGE_ID`). - Inventory item and Change quantity stay in the row table but are not shown, since the Inventory page edits every amount. **Inventory page** - A grid of cards with section tabs (All, Equipment, Items, Masks, Upgrades, Quest) kept on one line, and a page control (arrows, "Page n of m", the range). - Owned, locked, quantity and unavailable states each look different. On the title screen one note replaces "Load a save" on every card. - An action button for Unlock / Relock / Edit amount. Q/E while editing an amount ends the edit and switches section. **Teleport page** - Destination cards grouped under Overworld and Dungeons headings. Notes such as "adult only" stay on the card. - A click selects a card. Travel, Enter or A goes. Up/Down move by row inside the sections and keep the column. **Output resolution: 5120x2880 (5K)** (its own commit) - ID 5, after 5120x1440 in the menu's order, with its hint, the host's size lookup (`host/nn_applet.c`), the readme, `docs/development.md` and `tests/test_output_resolution.py`, following #1290. - The render-target pool would scale to 1220 MB at 5K, but the game crashed at boot with 1220 MB and with 1000 MB (its own reservation fails). The **5K output's pool is kept to 900 MB**; every other output keeps its whole scaled pool (4K 687 MB, 5120x1440 610 MB, a 32:9 screen at 4K 1373 MB, unchanged; `tests/test_rt_pool_minimum.py` has 5K cases). At 900 MB and 800 MB the game booted, loaded a save and played with the 3D at the full 5120x2880 (Render resolution 100%). `HOS_RT_POOL_MB` still overrides it. - ID 5 is also claimed by #1641 (1280x720). As agreed in review, storing `output_res` as the size instead of an index (so players can set custom resolutions in the config) comes in a follow-up PR; until then whichever of the two lands second renumbers. **Unchanged:** the mouse wheel still only scrolls (#1557), on both pages too. Apart from the 5K row, Graphics, Gameplay and Controls are untouched. Outside the menu, the redesign only adds the age report in `host/hos_main.c` and its id in `gpu/vk/oot_cheat_items.h`. ## Testing - Windows, RTX 4090, the standalone build from this branch. Headless runs at 3840x2160 and 2560x1500 on the title screen and with a save loaded, at Menu size Small, Medium and Large, plus 1280x1024 and a 1080x1440 window. Reviewed in game by hand at Small; the Medium and Large fixes were checked in the headless runs. - Switch age: with a save loaded the row showed Kid, Right switched Link to adult, and the row then showed Adult. - 5K: booted headless with `HOS_OUTPUT_RES=5` into a save at Render resolution 100% with the 900 MB pool, walked around, no crash. Not yet run at 5K: the Castle Town guard-house conversation. - `python -I -B tests/run_all.py`: the same results as `main` on this machine (it has no g++ on PATH, so some C++ checks skip or fail the same way on both). The menu, output-resolution and render-target pool checks were also compiled and run here with clang and pass: `test_rt_pool_minimum`, `test_output_resolution`, `test_menu_keys`, `test_rumble_menu`, `test_menu_hit`, `test_menu_utf8`, `test_menu_restart`. `tests/test_rumble_menu.py`'s wheel check now names the new pages' mouse functions. `tests/test_menu_keys.py`'s source checks pass. ## Screenshots Debug tab, Menu size Small (2560x1500): ![Debug tab, small](https://raw.githubusercontent.com/ArmstrongThomas/Hookshot/pr-assets/debug-menu-redesign/debug-small.jpg) Debug tab, Menu size Medium (2560x1500), one column: ![Debug tab, medium](https://raw.githubusercontent.com/ArmstrongThomas/Hookshot/pr-assets/debug-menu-redesign/debug-medium.jpg) Inventory with a save loaded (3840x2160, Small): ![Inventory](https://raw.githubusercontent.com/ArmstrongThomas/Hookshot/pr-assets/debug-menu-redesign/inventory.jpg) Inventory on the title screen (2560x1500, Small) and at Large: ![Inventory, title screen](https://raw.githubusercontent.com/ArmstrongThomas/Hookshot/pr-assets/debug-menu-redesign/inventory-title.jpg) ![Inventory, large](https://raw.githubusercontent.com/ArmstrongThomas/Hookshot/pr-assets/debug-menu-redesign/inventory-large.jpg) Output resolution set to 5120x2880 (2560x1440 window): ![Output resolution 5K](https://raw.githubusercontent.com/ArmstrongThomas/Hookshot/pr-assets/debug-menu-redesign/output-5k.jpg) Teleport (3840x2160, Small): ![Teleport](https://raw.githubusercontent.com/ArmstrongThomas/Hookshot/pr-assets/debug-menu-redesign/teleport.jpg) 🤖 Generated with [Claude Code](https://claude.com/claude-code)
hckrman101 (Migrated from github.com) reviewed 2026-11-10 15:50:21 +00:00
@ -184,7 +184,7 @@ number is not the obvious one:
| `gpu_device` | 0 Auto, n the n-th card with Vulkan 1.3 as the row lists them |
| `frame_generation` | 0 Off, 2 to 8 the multiplier |
| `resolution` | 0 Auto, 1 100%, 2 75%, 3 67%, 4 50% |
hckrman101 (Migrated from github.com) commented 2026-11-10 15:50:21 +00:00

Maybe now is the time to rewrite output_res, even if it breaks existing, so that we aren't using ints anymore

Maybe now is the time to rewrite `output_res`, even if it breaks existing, so that we aren't using ints anymore
hckrman101 (Migrated from github.com) reviewed 2026-11-10 16:15:58 +00:00
hckrman101 (Migrated from github.com) left a comment

Thanks, the Debug tab grouping and the card pages look like a real improvement, and the Debug tab's Up/Down order (debug_rows / debug_step) and the teleport row stepping read correctly to me. A few things before this can go in:

  1. The 900 MB cap breaks tests/test_rt_pool_minimum.py (the only failure in both Python source checks jobs, and it's new, not one of main's known ones). The cap applies to every scaled pool, not just 5K: a 32:9 screen at the 4K output (hos_wide_out 7680x2160) drops from 1373 MB to 900 MB, and a larger game pool at 4K from 1728 MB to 900 MB. The first one is the issue 1031 case the comment above the function describes, so "only 5K reaches it" in the description isn't right. Could the cap be limited to the 5120x2880 output (and the test get a 5K case) so the existing growth stays as it was?
  2. The wheel doesn't turn the Inventory page. inventory_mouse moves inventory_page and sets changed, but then in the same tick the non-amount branch hits if (changed && !step) inventory_reveal();, which snaps the page back to the chosen item's page. Inline below.
  3. Output resolution ID 5 is also claimed by #1641 (1280x720 as ID 5). Whichever lands second has to renumber, and anyone who saved 5 on one build gets the other size. Appending at the end is fine for existing users (nothing shifts), but this is a good argument for the earlier comment about storing output_res as the size instead of an index.
  4. The branch conflicts with main now (#1500's mouse work and the startup changes landed today), so it needs a rebase. From a quick look main's vk_menu.cpp changes are mostly elsewhere (startup screen), so it should be manageable.

Smaller points:

  • 5K headroom: the 512 MB floor exists because the Castle Town guard-house conversation needed more than 305 MB at 1440p. At 5K (4x the pixels) 900 MB is a lot less than that ratio, and the test was walking around. Worth running that guard-house scene at 5K with Render resolution 100% before calling it supported.
  • Light note: the 5K output is unrelated to the menu redesign; it would be easier to review and land (or revert) as its own PR, especially with the pool cap and the #1641 ID clash attached to it.
  • Nit: oot_inventory_refresh counts item 0 a second time for loaded; the loop just did that call.
Thanks, the Debug tab grouping and the card pages look like a real improvement, and the Debug tab's Up/Down order (`debug_rows` / `debug_step`) and the teleport row stepping read correctly to me. A few things before this can go in: 1. **The 900 MB cap breaks `tests/test_rt_pool_minimum.py`** (the only failure in both Python source checks jobs, and it's new, not one of main's known ones). The cap applies to every scaled pool, not just 5K: a 32:9 screen at the 4K output (`hos_wide_out` 7680x2160) drops from 1373 MB to 900 MB, and a larger game pool at 4K from 1728 MB to 900 MB. The first one is the issue 1031 case the comment above the function describes, so "only 5K reaches it" in the description isn't right. Could the cap be limited to the 5120x2880 output (and the test get a 5K case) so the existing growth stays as it was? 2. **The wheel doesn't turn the Inventory page.** `inventory_mouse` moves `inventory_page` and sets `changed`, but then in the same tick the non-amount branch hits `if (changed && !step) inventory_reveal();`, which snaps the page back to the chosen item's page. Inline below. 3. **Output resolution ID 5 is also claimed by #1641** (1280x720 as ID 5). Whichever lands second has to renumber, and anyone who saved 5 on one build gets the other size. Appending at the end is fine for existing users (nothing shifts), but this is a good argument for the earlier comment about storing `output_res` as the size instead of an index. 4. The branch conflicts with main now (#1500's mouse work and the startup changes landed today), so it needs a rebase. From a quick look main's `vk_menu.cpp` changes are mostly elsewhere (startup screen), so it should be manageable. Smaller points: - 5K headroom: the 512 MB floor exists because the Castle Town guard-house conversation needed more than 305 MB at 1440p. At 5K (4x the pixels) 900 MB is a lot less than that ratio, and the test was walking around. Worth running that guard-house scene at 5K with Render resolution 100% before calling it supported. - Light note: the 5K output is unrelated to the menu redesign; it would be easier to review and land (or revert) as its own PR, especially with the pool cap and the #1641 ID clash attached to it. - Nit: `oot_inventory_refresh` counts item 0 a second time for `loaded`; the loop just did that call.
hckrman101 (Migrated from github.com) commented 2026-11-10 16:15:58 +00:00

When the wheel turned the page in inventory_mouse, changed is true and step is 0, so this puts inventory_page straight back on the chosen item's page. The wheel has no visible effect unless an amount is being edited. Maybe only reveal when the choice actually moved (compare item_choice before and after).

When the wheel turned the page in `inventory_mouse`, `changed` is true and `step` is 0, so this puts `inventory_page` straight back on the chosen item's page. The wheel has no visible effect unless an amount is being edited. Maybe only reveal when the choice actually moved (compare `item_choice` before and after).
@ -134,7 +135,9 @@ uint32_t hos_output_size(int height) {
hos_wide_out, the output's height at the screen's shape: 7680 x 2160 for a 32:9 screen at the 4K output, twice the pixels the pool
hckrman101 (Migrated from github.com) commented 2026-11-10 16:15:58 +00:00

This cap applies to the hos_wide_out growth and to larger game pools too, not just 5K: test_rt_pool_minimum.py now fails on {3840x2160, wide 7680x2160} -> 1373 and {3840x2160, game 768} -> 1728, both clamped to 900. Limiting it to the 5120x2880 output would keep those as they were.

This cap applies to the `hos_wide_out` growth and to larger game pools too, not just 5K: `test_rt_pool_minimum.py` now fails on `{3840x2160, wide 7680x2160} -> 1373` and `{3840x2160, game 768} -> 1728`, both clamped to 900. Limiting it to the 5120x2880 output would keep those as they were.
hckrman101 (Migrated from github.com) approved these changes 2026-11-10 17:17:40 +00:00
hckrman101 (Migrated from github.com) left a comment

Thanks for the updates, this looks good to me now.

Fixed:

  • The pool cap only applies to the 5120x2880 output now, so the 32:9-at-4K (1373 MB) and larger-pool-at-4K (1728 MB) cases are back to their scaled sizes, and test_rt_pool_minimum.py has the two 5K cases.
  • The wheel turns the Inventory page now: inventory_reveal() only runs when item_choice actually moved.
  • The age check reuses the first item's count instead of reading it twice.
  • 5K is in its own commit, which helps.

Still open, none of it blocking:

  • The branch still conflicts with main (gpu/vk/vk_menu.cpp, gpu/vk/vk_menu.h, readme.md, docs/development.md; it's 48 commits behind), so it needs a merge of main before it can go in. The Python checks haven't run on this push yet either.
  • Output resolution id 5 still clashes with #1641 (1280x720). Fine to sort out with the size-instead-of-index follow-up, but whichever lands second has to renumber, and that should happen before both are merged.
  • The Castle Town guard-house scene hasn't been tried at 5K with the 900 MB pool. Since 5K is opt-in that's OK to land, but it'd be good to try before calling 5K fully supported.
Thanks for the updates, this looks good to me now. Fixed: - The pool cap only applies to the 5120x2880 output now, so the 32:9-at-4K (1373 MB) and larger-pool-at-4K (1728 MB) cases are back to their scaled sizes, and `test_rt_pool_minimum.py` has the two 5K cases. - The wheel turns the Inventory page now: `inventory_reveal()` only runs when `item_choice` actually moved. - The age check reuses the first item's count instead of reading it twice. - 5K is in its own commit, which helps. Still open, none of it blocking: - The branch still conflicts with main (`gpu/vk/vk_menu.cpp`, `gpu/vk/vk_menu.h`, `readme.md`, `docs/development.md`; it's 48 commits behind), so it needs a merge of main before it can go in. The Python checks haven't run on this push yet either. - Output resolution id 5 still clashes with #1641 (1280x720). Fine to sort out with the size-instead-of-index follow-up, but whichever lands second has to renumber, and that should happen before both are merged. - The Castle Town guard-house scene hasn't been tried at 5K with the 900 MB pool. Since 5K is opt-in that's OK to land, but it'd be good to try before calling 5K fully supported.
hckrman101 (Migrated from github.com) approved these changes 2026-11-10 18:01:41 +00:00
hckrman101 (Migrated from github.com) left a comment

Thanks for the rebase. It merges cleanly now, and it's still good to go from my side.

I compared the new branch against what I approved at a724deb. The PR's own changes are the same line for line; only the surrounding context moved, onto the newer main (Anti-Lag 2 and #1500's mouse menus are kept, and Inventory and Teleport still go through inventory_mouse/teleport_mouse). Nothing of main's is dropped. Main's later Ultrawide menus row (#1352) only touches the Graphics rows and Options, and doesn't overlap with this.

CI is red, but it isn't this PR. The failing tests are test_recomplauncher_json.py, test_lift_cleanup_error.py, nx2/test_draw_parameters.py (Linux) and nx2/test_nup_out_of_space.py (Windows), and main at ae08298 fails the same four. The launcher-json and lift-cleanup ones are already fixed on main (ae44d7d, #1836). The tests this PR touches (test_output_resolution, test_rt_pool_minimum, test_rumble_menu, test_menu_hit) pass on both OSes.

Still open, as before:

  • 5K is still output_res index 5, so it still clashes with #1641's 1280x720. #1814 (storing the size) is still open, and this branch doesn't build on it. Since 5K is its own commit (ce175ac), it should be easy to rebase onto #1814 once that lands, or to renumber. Whichever of #1670 or #1641 goes in second needs to sort out the id first.
  • The Castle Town guard-house scene still hasn't been tried at 5K with the 900 MB pool. That's fine while 5K is opt-in.
Thanks for the rebase. It merges cleanly now, and it's still good to go from my side. I compared the new branch against what I approved at a724deb. The PR's own changes are the same line for line; only the surrounding context moved, onto the newer main (Anti-Lag 2 and #1500's mouse menus are kept, and Inventory and Teleport still go through `inventory_mouse`/`teleport_mouse`). Nothing of main's is dropped. Main's later Ultrawide menus row (#1352) only touches the Graphics rows and `Options`, and doesn't overlap with this. CI is red, but it isn't this PR. The failing tests are `test_recomplauncher_json.py`, `test_lift_cleanup_error.py`, `nx2/test_draw_parameters.py` (Linux) and `nx2/test_nup_out_of_space.py` (Windows), and main at ae08298 fails the same four. The launcher-json and lift-cleanup ones are already fixed on main (ae44d7d, #1836). The tests this PR touches (`test_output_resolution`, `test_rt_pool_minimum`, `test_rumble_menu`, `test_menu_hit`) pass on both OSes. Still open, as before: - 5K is still output_res index 5, so it still clashes with #1641's 1280x720. #1814 (storing the size) is still open, and this branch doesn't build on it. Since 5K is its own commit (ce175ac), it should be easy to rebase onto #1814 once that lands, or to renumber. Whichever of #1670 or #1641 goes in second needs to sort out the id first. - The Castle Town guard-house scene still hasn't been tried at 5K with the 900 MB pool. That's fine while 5K is opt-in.
Commenting is not possible because the repository is archived.
No description provided.