Skip to content

feat: add a 1920x1080 docked output mode - #1144

Merged
hckrman101 merged 2 commits into
NotRexed:mainfrom
arthur-moebios:feat/docked-1080p
Nov 9, 2026
Merged

hckrman101 merged 2 commits into
NotRexed:mainfrom
arthur-moebios:feat/docked-1080p

Conversation

@arthur-moebios

Copy link
Copy Markdown

Summary

Add 1920×1080 as a docked output size for the full game image and HUD. The new mode uses output_res=3 or HOS_OUTPUT_RES=3. The existing saved mode IDs and the default output are preserved.

Testing

Compared the two output sizes in the same patched v2.0.7 executable on Windows with a Core i7-13700H and RTX 4060 Laptop GPU (driver 617.42). Both headless Vulkan runs loaded the same Hyrule Field save and held the same camera at fixed 100% render scale with frame generation off. Measured one 25-second window per mode after loading. The native present trace measures time between game present-call returns.

Output Mean native FPS Frame time p95 Median GPU time per frame
2048×1152 38.77 29.59 ms 19.40 ms
1920×1080 42.78 26.23 ms 17.40 ms

Verified the 1920×1080 render dimensions in the log and checked HUD placement in local gameplay captures. The regression test covers mode IDs, the environment override, handheld fallback, and render-target budgets. The full local source suite reported 119 passed, 12 skipped and four failures that also reproduced on unmodified main (test_nup_paths.py, test_fps_overlay_order.py, test_precompile_compute_guard.py, and test_program_answer_domains.py).

Refs #1007 and #1134.

Add 1920x1080 as a docked output size, with output_res=3 and
HOS_OUTPUT_RES=3. Keep the saved identifiers for all existing modes and
show the corresponding internal resolution in the Graphics menu.

Add a game-free regression covering saved modes, the override, handheld
fallback, and render-target budgets. On Windows, 119 checks passed and
12 were skipped. The four failures also reproduce on unmodified main.

Smoke-tested the same runtime/menu patch on v2.0.7 on Windows with an
RTX 4060 Laptop GPU (driver 617.42). The startup run reported 1920x1080
NVN window textures, a 1920x1080 scene at fixed 100%, and frame presents.
No gameplay performance comparison was run.

Refs NotRexed#1134

Assisted-by: OpenAI Codex
Co-Authored-By: OpenAI Codex <codex@openai.com>

@hckrman101 hckrman101 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice addition. I checked the other users of the output size, and the new mode needs nothing more. The game patches in nx2/oot_patches.py all go through hos_output_size(). The graphics-scale answer in nn_applet.c gives x1 for any chosen output. The render-target pool only grows at 4K, so 1080p keeps the shipped one. The ultrawide width in hos_main.c follows hos_output_size(1). Keeping the saved ids stable and sending an out-of-range value to 0 instead of clamping it to 1080p is the right call too.

One note on the motivation: the fps gain over 2048x1152 is mostly the ~13% fewer pixels, which the Resolution row can already trade. I think the stronger case is image quality on 1080p screens, the most common ones. Today the whole frame, HUD and text included, is composed at 2048x1152 and then scaled down to the window, which softens it, and 1080p output maps 1:1. Might be worth saying so in the readme row.

Comment thread gpu/vk/vk_menu.cpp
struct Out {
uint32_t w, h;
};
constexpr Out kOutputs[] = {{2048, 1152}, {2560, 1440}, {3840, 2160}, {1920, 1080}};

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With 1080p appended, the menu now cycles 2048x1152 → 2560x1440 → 3840x2160 → 1920x1080, so the smallest size comes after 4K. To keep the saved ids as they are (3 = 1080p) but show the sizes in order, the row could step through a display-order table, e.g. {3, 0, 1, 2} (with Left/Right mapping through it), or tx_output_res / the row could use a small id↔position mapping. Same for the readme table, which lists it last.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should break away from this int setting now before we add other of other resolutions too

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, the kOutputOrder table does it: Left/Right, wheel and the value halves all go through set_row, so they step in size order, and the saved output_res / HOS_OUTPUT_RES ids keep their meaning. Fine with keeping the int setting here, a different format can be its own PR if more sizes come.

Comment thread tests/test_output_resolution.py Outdated

host = (ROOT / "host/nn_applet.c").read_text(encoding="utf-8")
menu = (ROOT / "gpu/vk/vk_menu.cpp").read_text(encoding="utf-8")
assert '"Output resolution", &opts.output_res, 0, kLastOutput, 1, tx_output_res' in menu

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor: this asserts on the exact text of the menu row, and the fixture below slices nn_applet.c / vk_menu.cpp between marker strings, so an unrelated rewording or reorder of those files breaks the test. The behavioural checks in the fixture are good. The row's range could be checked through kLastOutput (which the fixture already asserts) rather than the source text. Also a heads-up that #841 rewrites this same row (labels plus per-value help lines), so whichever lands second will need a small merge there.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, dropping the row-text assert and testing the step order covers it. The marker slicing is still there but that is fine for now.

@arthur-moebios

Copy link
Copy Markdown
Author

Thanks for the review, @hckrman101. I agree that sharper HUD and text on a 1080p display are the stronger reason to add this mode. I'll make that the main point in the README and keep the benchmark in the PR as a measured result.

I'll put 1080p first in the menu and README while keeping the saved IDs stable. I'll also replace the exact menu-row text assertion with checks for the selectable modes and their order.

I'd keep the integer setting for this PR to preserve compatibility with existing configs. If we expect to add more resolutions, I'm happy to discuss a more extensible format separately. Thanks for the heads-up about #841.

Step through the sizes from 1080p to 4K, with the saved IDs intact.
Describe native HUD and text scaling in the README and test navigation
in both directions, including the endpoints.

Assisted-by: OpenAI Codex
Co-Authored-By: OpenAI Codex <codex@openai.com>

@hckrman101 hckrman101 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. 1080p now comes first in the menu and readme with the saved ids unchanged, and the readme leads with the 1:1 HUD/text point.

One small nit, not blocking: the output row now stops at its ends rather than wrapping like the other multi-value rows, so at 3840x2160 Enter/A (which acts as Right) and a click on the right half do nothing. Since the arrow hides at the end that seems fine, just mentioning it in case it wasn't intended.

@hckrman101
hckrman101 merged commit d39923e into NotRexed:main Nov 9, 2026
hckrman101 added a commit to hckrman101/Hookshot that referenced this pull request Nov 9, 2026
Brings in the 1920x1080 docked output (NotRexed#1144), Windows' UTF-8 code page (NotRexed#1191) and the saves guide (NotRexed#1190).

Conflicts, resolved for both sides:
- gpu/vk/vk_menu.cpp: the Output resolution row keeps this branch's place among the scaling rows, its short help and its
  restart flag, and takes main's four sizes (kLastOutput) and smallest-to-largest order (step_output_choice, after
  row_fixed and the Upscaler's steps in set_row). Its value no longer says "restart" (the restart rows show "(after
  restart)" and offer Restart now); 2048x1152 stays "(game's)". 1920x1080 has its own per-value hint. menu_init reads
  HOS_OUTPUT_RES through output_choice, then restart_init. DLSS's modes and DLAA at 1920x1080 need nothing else: their
  sizes are twelfths of the output (1280x720, 1120x630, 960x540, 640x360), and vk_dlss.cpp takes the output's size from
  the picture, not from a list.
- gpu/vk/vk_menu.h: output_res lists 3 1920x1080 and still says it is read once, at the start.
- readme.md: the Output resolution row with 1920x1080 in this branch's table; the scaling notes take main's 1920x1080
  sentence and HOS_OUTPUT_RES values.
- tests/run_all.py: both test_menu_restart.py and test_output_resolution.py.

Also:
- gpu/vk/vk_dlss.cpp: ngx_log no longer converts NGX's lines from the ANSI code page. With the manifest's UTF-8 code
  page it is UTF-8 (tests/test_utf8_paths.py forbids CP_ACP in gpu/vk).
- tests/test_output_resolution.py: the labels without "restart", the menu's pieces it compiles taken around the
  Render resolution's hint and the Upscaler's rows (upscaler_rows.h, an Upscaler stand-in), DLSS's mode sizes and DLAA
  at 1920x1080 checked, and hos_wide_out defined (hos_rt_pool_size reads it; it did not link without it).
- tests/test_rumble_menu.py: a stand-in for step_output_choice, which set_row now calls.
NotRexed added a commit that referenced this pull request Nov 9, 2026
…, Windows paths in two tests)

- test_output_resolution: hos_wide_out, which nn_applet.c reads since the ultrawide pool fix.
- test_rumble_menu: step_output_choice, which set_row calls since #1144's Output row.
- utf8_paths_test.c: the log is written through text-mode stderr, CR LF on Windows: compared without the CRs.
- test_oot_saves: USERPROFILE redirected too, and skipped on Windows (its discovery is the Linux one).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants