feat(menu): an Uncapped choice for the Game frame rate cap #2122

Merged
hckrman101 merged 2 commits from menu/fps-uncapped into main 2026-11-11 04:11:03 +00:00
hckrman101 commented 2026-11-11 03:56:40 +00:00 (Migrated from github.com)

The Game frame rate cap stops at 240, so a player with a fast PC, or one who wants the least delay, cannot let the game run free. This adds Uncapped as the row's last choice, with the game still at real speed.

  • The row: Game frame rate cap now offers 60 (the console's), 90, 120, 144, 165, 240 and Uncapped, after a restart as before. It is saved as frame_rate_cap=6. 0 to 5 mean what they did, and a value a build does not know (an older build reading 6) is 60.
  • How it runs: Uncapped is a cap of 1000 fps, the pacing's 1 ms. The display pacing, the game's own limiter and the vsync event follow it, as they follow the other caps above 60.
  • Game speed: as with any cap above 60, the game's time step is the frames' own time, so game time follows the clock. That step had a floor of a 240th of a second. Above 240 fps every frame would have advanced the game by more than its own time, and the game would have run fast. The floor is now 1 / max(240, cap): unchanged for every cap up to 240, a 1000th uncapped.
  • V-Sync: the row's help says the game keeps real time, and that with V-Sync on the display's refresh rate is the limit. A display that waits for its refresh (V-Sync On in #2041, or the driver's FIFO mode) still shows at most its refresh rate. Auto (mailbox) and Off let the game render past it. The readme says the same.
  • HOS_FPS_MAX takes 61 to 1000 now (it stopped at 240).
  • Docs: the readme's menu table and notes and the development guide follow. The guide also lists HOS_FPS_MAX, and notes that HOS_FPS_LOG logs the game clock's speed.

Tested

Linux, RTX 3090:

  • Build: a full build of the game and hookshot_vk.so, its exported-symbol check clean.
  • Checks: python -I -B tests/run_all.py: 340 passed, 13 skipped. The three failures (nx2/test_nup_read_name, tests/test_builder_log_read_only, tests/test_wayland_libdecor_hint) also fail on main on this machine.
  • tests/test_frame_rate_cap_step.py compiles the real fps_max and realtime_step and checks:
    • Uncapped from the options file (frame_rate_cap=6) and from HOS_FPS_MAX=1000: the limiter at 1000, and frames 500 a second apart stepping a 500th each, which is real time.
    • The shortest step, 1 ms.
    • An unknown frame_rate_cap read as 60.
    • A cap of 120 still floored at a 240th.
    • The menu's row: Uncapped as its seventh choice, and its help.
  • In game (headless, Kokiri Forest, handheld profile, Render resolution 50%, HOS_FPS_LOG=1):
    • Uncapped: the log said vi: frame rate uncapped, and the game clock ran at 1.000 of wall time (0.998 to 1.001, ten readings over a minute and a half).
    • The same run at the 60 cap: 1.010 to 1.013 at 60 fps, the game's own step.

Not tested

  • Frame rates above 240. This PC was loaded by other jobs and the runs were held to six cores. The Uncapped run reached about 43 fps, and a cap-240 run only 6 to 12 fps while it compiled pipelines, so the runs could not show frames past 240. They do show the game clock staying at real time while uncapped. A run on an idle PC, with HOS_FPS_LOG=1, should show the fps past 240 at a speed of 1.000.
  • V-Sync On (#2041) together with Uncapped, on a visible display.
  • Windows.
The Game frame rate cap stops at 240, so a player with a fast PC, or one who wants the least delay, cannot let the game run free. This adds **Uncapped** as the row's last choice, with the game still at real speed. - **The row:** Game frame rate cap now offers 60 (the console's), 90, 120, 144, 165, 240 and **Uncapped**, after a restart as before. It is saved as `frame_rate_cap=6`. 0 to 5 mean what they did, and a value a build does not know (an older build reading 6) is 60. - **How it runs:** Uncapped is a cap of 1000 fps, the pacing's 1 ms. The display pacing, the game's own limiter and the vsync event follow it, as they follow the other caps above 60. - **Game speed:** as with any cap above 60, the game's time step is the frames' own time, so game time follows the clock. That step had a floor of a 240th of a second. Above 240 fps every frame would have advanced the game by more than its own time, and the game would have run fast. The floor is now `1 / max(240, cap)`: unchanged for every cap up to 240, a 1000th uncapped. - **V-Sync:** the row's help says the game keeps real time, and that with V-Sync on the display's refresh rate is the limit. A display that waits for its refresh (V-Sync On in #2041, or the driver's FIFO mode) still shows at most its refresh rate. Auto (mailbox) and Off let the game render past it. The readme says the same. - **`HOS_FPS_MAX`** takes 61 to 1000 now (it stopped at 240). - **Docs:** the readme's menu table and notes and the development guide follow. The guide also lists `HOS_FPS_MAX`, and notes that `HOS_FPS_LOG` logs the game clock's speed. ## Tested Linux, RTX 3090: - **Build:** a full build of the game and `hookshot_vk.so`, its exported-symbol check clean. - **Checks:** `python -I -B tests/run_all.py`: 340 passed, 13 skipped. The three failures (`nx2/test_nup_read_name`, `tests/test_builder_log_read_only`, `tests/test_wayland_libdecor_hint`) also fail on `main` on this machine. - **`tests/test_frame_rate_cap_step.py`** compiles the real `fps_max` and `realtime_step` and checks: - Uncapped from the options file (`frame_rate_cap=6`) and from `HOS_FPS_MAX=1000`: the limiter at 1000, and frames 500 a second apart stepping a 500th each, which is real time. - The shortest step, 1 ms. - An unknown `frame_rate_cap` read as 60. - A cap of 120 still floored at a 240th. - The menu's row: Uncapped as its seventh choice, and its help. - **In game (headless, Kokiri Forest, handheld profile, Render resolution 50%, `HOS_FPS_LOG=1`):** - Uncapped: the log said `vi: frame rate uncapped`, and the game clock ran at 1.000 of wall time (0.998 to 1.001, ten readings over a minute and a half). - The same run at the 60 cap: 1.010 to 1.013 at 60 fps, the game's own step. ## Not tested - **Frame rates above 240.** This PC was loaded by other jobs and the runs were held to six cores. The Uncapped run reached about 43 fps, and a cap-240 run only 6 to 12 fps while it compiled pipelines, so the runs could not show frames past 240. They do show the game clock staying at real time while uncapped. A run on an idle PC, with `HOS_FPS_LOG=1`, should show the fps past 240 at a speed of 1.000. - **V-Sync On** (#2041) together with Uncapped, on a visible display. - **Windows.**
Commenting is not possible because the repository is archived.
No description provided.