feat(menu): skip the title screen and load the newest save #399

Merged
HumanBean merged 4 commits from mooki/Longshot:feat/skip-title into main 2026-11-14 15:32:53 +00:00
Member

Why

What this is for: Nicholas Gower's Skip title work lets a returning player launch into the game's newest save without pressing through the title and file list. Michael Schienbein carried it here from https://github.com/NotRexed/Hookshot/pull/1560 with Nicholas credited as co-author, so restart in place can build on it.

What is measured: current game-free checks, four standalone Linux/RTX 4090 functional cases at 5c175a472, and a completed quiet interleaved Off-cost comparison against 0caf06184. It finds no cost distinguishable from main's 0.8566% repeat spread; this change's own spread is 1.3907%. Not measured: Windows runtime, physical input, other hardware/scenes or a game run on the current head.

Below, "r4" is the earlier head 5c175a472 (on main 0caf06184), where the game runs and the measurement were taken, and "r5" is the current head db39383ba (on main 5e072fc8c), which carries the same three feature and test commits unchanged plus the run records.

What changed

  • gpu/vk/vk_menu.cpp and vk_menu.h: the Gameplay row Skip title screen, Off by default, saved as skip_title_screen. It takes effect after a restart.
  • gpu/vk/vk_api.h and vk_replay.cpp: use the already reserved option 44 and answer it through the existing option callback. Skip opening remains 52; neither renderer interface changes.
  • host/oot_autoload.c and .h: find the newest save by modification time, then use the existing host input-tap implementation to press A through the title and file list. The game chooses which save to load; this code does not select a slot or check save contents. With no save, it leaves the title alone.
  • host/nn_hid.c and hos_main.c: run the title helper from input reads and reuse the existing player-seen signal to stop once play begins. No second input-tap implementation is added.
  • tests/test_skip_title.py: compile the actual host implementation against temporary files and controlled clock/input observations. Preserve the background-input fixture and the Skip opening/option-allocation checks. The standalone fixture carries its existing README case and secure-CRT fixes, split from the mixed test commit in 61.
  • README.md and docs/development.md: retain the option-table entry, player explanation and saved-key reference. This feature changes no language catalogue entries or counts; its row and help still use English fallback. Main's current translations are retained.

This does not include save-before-restart, continuation notes, the windowless Restart/Quit repair, or restart's later idle-demand guard. Those remain in 61. All added and removed lines of the three Skip title commits are preserved through this carry; that is patch evidence, not a new game result.

  • docs/tested/: eight new run records in one separate documentation commit, preserving the first window's rejection and the second window's within-repeat-spread result.

Flags and settings

Flag What it does Default now Recommendation Helps on Doesn't help on Untested on
Skip title screen Gameplay row: press through the title and file list after the next start Off Off by default: an explicit player choice Returning to an existing save Starting a new game; choosing a different save manually Windows; real input; other scenes and unusual prompts
skip_title_screen Saved key for the row: 0 Off, 1 On 0 Off by default: follows the row Remembering the player's choice Repairing or validating saves Windows non-ASCII and long paths
HOS_OPT_SKIP_TITLE Internal option callback, using reserved number 44 0 Off by default: follows the row, not an environment switch Connecting the menu to the host Skip opening, which retains option 52 Windows game/runtime

Measurements

Final r5 source checks, 14 November

main: 5e072fc8c2 (2026-11-14 UTC)
this PR: feat/skip-title @ db39383ba0
Hardware: Core i9-13900K, 96 GB RAM, Arch Linux 7.2.15-1-omarchy, GCC 16.2.1, Clang 23.1.3, Python 3.12.16; RTX 4090/NVIDIA 615.78.08 for windowless game evidence.
Scene: authored temporary-file, menu/input and save-state fixtures; no game is started by these checks.
Method: focused GCC/Clang checks and the whole strict suite once on the final head, including the run-record commit; main's retained exact-head suite is the baseline.
How to reproduce: python -I -B tests/run_all.py --jobs 6 --strict; run tests/test_tested_configurations.py for the records and the Skip title drivers with GCC and Clang.

Check main @ 5e072fc8c this PR @ db39383ba
Whole strict suite 542 passed, 3 failed, 16 skipped 543 passed, the same 3 failures, 16 skipped
Focused checks Inherited GCC menu-key failure; matrix not repeated GCC 28 passed / 1 inherited failure; Clang 24 passed
Feature source guard Expected absent-row failure Pass
Per-run catalogue format Existing catalogue Complete driver passes before and after the added records
Feature runtime/build evidence Actual base 0caf06184 Game runs carried from r4 5c175a472; r5 built and linked for Windows and Linux, not run
28 passed, 1 failed, 0 skipped in 11 s (linux, 1 at once)
24 passed, 0 failed, 0 skipped in 10 s (linux, 1 at once)
543 passed, 3 failed, 16 skipped in 152 s (linux, 6 at once)

The whole-suite failures are exactly main's tests/test_framegen_resources.py (missing Intel-gate/guarded-call declarations in its fixture), tests/test_module_ids.py (an old exact function signature), and tests/test_pad_layout.py (missing HoldToggle declaration). The separate GCC-only tests/test_menu_keys.py failure is g++ rejecting three C-header _Static_assert spellings; Clang passes. No failing check or assertion was removed.

The carry onto main 5e072fc8c changed no added or removed line of the feature/test commits. Its two later commits are 5ed8141af (PsychoV35's adapted scene-tone-map permutation) and 5e072fc8c (actor-motion pose capture and pairing model copies by place), with their tests and run records. Neither changes the title, input, save or restart code. The measured settings use the game's upscaler with frame generation and HDR Off. Earlier game runs and measurements remain attributed to 0caf06184, 5c175a472 and d89cb5992 as applicable; they were not rerun on r5, and are not a new absolute frame-time result for current main. Each r5 layer adds only its separate measured-run documentation commit.

Completed Skip title Off measurement at r4

main: 0caf06184b (2026-11-14 UTC)
this PR: feat/skip-title @ 5c175a4727
Hardware: Core i9-13900K, 96 GB RAM, Arch Linux 7.2.15-1-omarchy, GCC 16.2.1, Clang 23.1.3, Python 3.12.16; RTX 4090/NVIDIA 615.78.08 for windowless game evidence.
Scene: Kokiri Forest, the same copied save, stationary view by the sign, menu closed.
Settings: Windowless, game output 1280x720, render 100%, game's upscaler, frame generation/HDR/FPS overlay Off, real-time speed, HOS_FPS_MAX=1000 (Uncapped). Saved V-Sync is 0, labelled Auto; there is no swapchain or display wait in this run. Skip title is Off.
Method: both scenes warmed, then A1/B1/A2/B2 in each quiet exclusive window; 85-second game bounds, three seconds of scene settling followed by 25 seconds of game-present-return CPU intervals. This clock measures neither GPU completion nor display latency. Matched release builds, lift and profile. Other-work CPU must average below 3 cores and peak at most 6 over five seconds, repeat spread at most 5%, with no measured gap over one second.
How to reproduce: load the same valid copied save on the two named builds, keep the above settings and fixed camera, then collect two interleaved stationary samples per build after settling.

Result: no cost distinguishable from the repeats' spread. In the quiet second window, main's two medians are 13.758351 and 13.641001 ms; Skip title Off's are 13.730049 and 13.540422 ms. Main's repeat span is 0.117350 ms (0.8566%); the candidate's is 0.189627 ms (1.3907%). Main's span exceeds the between-arm difference, so this is neither a speed gain nor proof of zero cost. It is a completed measurement with a within-repeat-spread result, not a missing measurement.

Quiet window 2 main @ 0caf06184 this PR @ 5c175a472
Run medians, ms 13.758351; 13.641001 13.730049; 13.540422
Median of the two run medians, ms 13.699676 13.635236
Repeat span, ms / percent 0.117350 / 0.8566% 0.189627 / 1.3907%

The first window is disturbed and rejected in full: A2 used 7.942 other-work cores on average and peaked at 28.797. The second passed two five-second admission samples (0.608 and 0.296 cores) and all four sample-window quiet checks. Every run is retained, including the rejected window:

Window/run Build Median ms Mean ms p99 ms Other CPU mean / 5-s peak (cores) Load before to after Status
W1 A1 main @ 0caf06184 13.618077 13.881730 21.311780 1.689 / 1.746 1.47 to 5.81 Rejected whole window: A2 disturbed
W1 B1 this PR, Skip title Off @ 5c175a472 13.463051 13.837404 21.195355 1.675 / 1.776 5.81 to 6.90 Rejected whole window: A2 disturbed
W1 A2 main @ 0caf06184 13.905075 17.108690 102.825698 7.942 / 28.797 6.90 to 17.73 Rejected whole window: A2 disturbed
W1 B2 this PR, Skip title Off @ 5c175a472 13.653566 14.017513 21.309892 1.788 / 1.868 17.73 to 9.92 Rejected whole window: A2 disturbed
W2 A1 main @ 0caf06184 13.758351 14.152099 21.785438 1.767 / 1.904 1.26 to 7.04 Valid, quiet; within repeat spread
W2 B1 this PR, Skip title Off @ 5c175a472 13.730049 14.100743 22.106411 1.768 / 1.893 7.04 to 7.31 Valid, quiet; within repeat spread
W2 A2 main @ 0caf06184 13.641001 13.981753 21.407780 1.836 / 1.911 7.31 to 12.32 Valid, quiet; within repeat spread
W2 B2 this PR, Skip title Off @ 5c175a472 13.540422 13.815604 20.891918 1.696 / 1.766 12.32 to 8.24 Valid, quiet; within repeat spread
W1 A1: 0caf0618  exit=124 valid=True disturbed=False others 1.69 cores (highest 5 s 1.75) load 1.47 -> 5.81 kernel=0 fps=72.04 mean=13.882 ms readbacks/frame=- wait/frame=- ms
W1 B1: 5c175a47  exit=124 valid=True disturbed=False others 1.68 cores (highest 5 s 1.78) load 5.81 -> 6.90 kernel=0 fps=72.27 mean=13.837 ms readbacks/frame=- wait/frame=- ms
W1 A2: 0caf0618  exit=124 valid=True disturbed=True others 7.94 cores (highest 5 s 28.80) load 6.90 -> 17.73 kernel=0 fps=58.45 mean=17.109 ms readbacks/frame=- wait/frame=- ms
W1 B2: 5c175a47  exit=124 valid=True disturbed=False others 1.79 cores (highest 5 s 1.87) load 17.73 -> 9.92 kernel=0 fps=71.34 mean=14.018 ms readbacks/frame=- wait/frame=- ms
W2 A1: 0caf0618  exit=124 valid=True disturbed=False others 1.77 cores (highest 5 s 1.90) load 1.26 -> 7.04 kernel=0 fps=70.66 mean=14.152 ms readbacks/frame=- wait/frame=- ms
W2 B1: 5c175a47  exit=124 valid=True disturbed=False others 1.77 cores (highest 5 s 1.89) load 7.04 -> 7.31 kernel=0 fps=70.92 mean=14.101 ms readbacks/frame=- wait/frame=- ms
W2 A2: 0caf0618  exit=124 valid=True disturbed=False others 1.84 cores (highest 5 s 1.91) load 7.31 -> 12.32 kernel=0 fps=71.52 mean=13.982 ms readbacks/frame=- wait/frame=- ms
W2 B2: 5c175a47  exit=124 valid=True disturbed=False others 1.70 cores (highest 5 s 1.77) load 12.32 -> 8.24 kernel=0 fps=72.38 mean=13.816 ms readbacks/frame=- wait/frame=- ms

The two holds occupied 348.1 and 353.295 seconds including settling and shutdown. All eight games ended at the intended bound (124), with complete journal coverage and no fatal/device/kernel fault. Scene pictures were inspected. Eight self-contained files under docs/tested/ retain these actual measured commits and mark every first-window row rejected. The original baseline warm-up's clean Quit was first misclassified as invalid by its exit check; the retained game evidence established successful warming without repeating it.

Testing

Tested: final r5 focused GCC/Clang and whole-suite checks above; the per-run catalogue before and after the added records. The feature's main-source control fails for the intended absent row. On r4 5c175a472, the native Linux executable/renderer and Windows cross-build both linked; all four captured Windows-target fixture units passed, not Windows execution. The four Linux/RTX 4090 cases below and the Off-cost measurement retain that r4 head.

Carried standalone game cases, 14 November

Same head 5c175a472, source fingerprint 7a3c888d; 1920×1080 output, render resolution 100%, frame generation/V-Sync/FPS overlay Off, real-time speed and a 60 cap. These are pass/fail observations, not frame-time or startup-speed measurements.

Case Result and criterion
On, two intact copied saves, no input at all Pass: the real option reads 1. No input environment/file/menu script and no controller presses. It opens the uniquely newest slot_01/progress.sav, logs automatic loading complete, and reaches fresh playable forest state without an event/load.
On, fresh empty profile Pass: after an 80.4-second observation it remains at New Game; the helper reports no save. No regular file is created in the disposable user profile.
Off, same copied saves Pass: after an 80.4-second observation it remains at Continue waiting for input, with no automatic-loading line or save load.
Gameplay row and help Pass: the standalone build's selected Skip title screen row, On value and complete help are visible in the inspected menu capture.

slot_01 is newest because its original modification time is 11 November 02:45:19 local, later than slot_00 at 01:38:45. Both were known-valid test-library saves; this run also proves the selected one loads. This does not claim content validation or recovery from a newer damaged file.

skip title: .../slot_01/progress.sav is the most recent save: pressing A from 20 s
fs: OpenFile(save:/slot_01/progress.sav)
skip title: loaded, the player is running
skip title: no saved game yet: the title screen stays

The On run observes fresh playable state at frame 2013 (game sample frame 2013, event/loading false), then frame 2325 with a fresh sample and the same saved position. All four games exit 0, leave no owned process, and have complete journal coverage with zero fatal/crash/device/driver faults or NVIDIA mapping/allocation refusals. The copied saves and registered source stay byte-identical. Every picture below was inspected.

Built at r5: At db39383ba042ca131ea9ddf8fe520d39833fc8ec, the Windows x86-64 Vulkan renderer DLL and all 48 selected host translation units were cross-built on Linux with llvm-mingw 20261104 (Clang 23.1.5), using the project's production flags and pinned dependencies (renderer: 35 newly compiled / 170 reused; host: 1 newly compiled / 47 reused; lifted C: 0 newly compiled / 80 reused; all Windows units: 36 newly compiled / 611 reused from matching object-cache entries), the renderer DLL linked and the full game executable linked; nothing was run on Windows or under Wine, and this is neither the project's hosted builder run nor a Windows UTF-8 run-time path test.

The exact same head db39383ba042ca131ea9ddf8fe520d39833fc8ec also compiled and linked its full native Linux executable and renderer with Clang 23.1.3 through the documented resume path (247 newly compiled units, 242 matching Linux-cache units, source stamp 63776eb6), using the verified target-neutral C from lift 5c175a4727d82f85e425e85400dca17fea0750fb rather than carrying the patch onto another commit; neither Linux binary was run.

Not tested: game execution on r5; Windows execution of the new/changed C fixtures; Windows game/runtime, non-ASCII/long Windows save paths, real keyboard/controller input, AMD/Deck, other areas, unusual title prompts and damaged-save handling. Automatic title loading with non-default held/toggled A has not been tried in the game. Opening the Insert menu during automatic loading was not tested; the row picture is after loading. The row/help still use English fallback. The measured within-repeat-spread result does not establish zero cost.

Needs other testers:

  • Windows x64 with a real keyboard or controller: use disposable valid saves and a path with spaces and a non-ASCII letter. Check Off stays at the title; On reaches the newest save without manual loading; a fresh profile stays at New Game; opening the Insert menu pauses automatic presses (T-TSA8, open).

Screenshots

Standalone 5c175a472, Skip title On: the newest valid copied save loads with no test input; Link, hearts, minimap and movement controls are visible.

Standalone 5c175a472, Skip title On with a fresh profile: New Game stays; no save file is created.

Standalone 5c175a472, Skip title Off with saves present: Continue waits for the player.

Standalone 5c175a472: the selected Skip title screen row is On; the full help explains newest-save startup, no-save behavior and restart applicability.

Window 1, physical A1/B1/A2/B2 order: same scene, main 0caf06184 versus title 5c175a472 Off. A2 is labelled disturbed; the whole window is rejected.

Window 2, same order and builds: all rows quiet, but the result is no distinguishable cost within repeat spread. Pictures establish the scene, not a cost or speed gain.

Risk and rollback

The helper presses A on a timer, starting after 20 seconds, every 2 seconds, until play begins or 120 seconds pass. It does not identify the active title prompt. The Insert menu pauses it and switching the row Off stops it, but touching another control does not automatically cancel it. Unexpected confirmations and damaged saves remain risks. A file's presence and modification time do not establish that it is safe to load. Set skip_title_screen=0 or turn the row Off, then restart, to return to manual loading. Reverting these commits removes the option; it does not repair a damaged save.

Reviewer notes

Read hos_oot_autoload_input, hos_oot_newest_save, the input call and option 44 first. The original provenance and Nicholas Gower's exact co-author trailer remain. Three carried commits compare equal by range-diff, with author/date/message and every added/removed patch line preserved; the fourth commit records the eight runs only.

The archived review questioned timed A presses on unexpected prompts and the absence of cancellation on physical player input. Those remain disclosed design risks for review, not a claim that every prompt is safe. The current forge review can decide the approach. The standalone helper still reads the clock on input calls when Off; the measurement does not claim that instruction costs zero.

Skip title retains reserved option 44; Skip opening remains 52. The earlier 128-PR option survey is historical, not a new inventory. #61 contains these same three feature/test commits and the run-record commit until this merges. The separate restart layer uses option 64, which clashes with HOS_OPT_GFX_OBJECTS in #227 at 0fc2e8c9268d8611d5070cef9540725d60364874; that is not a title-only collision.

Issues

Original work: https://github.com/NotRexed/Hookshot/pull/1560
Dependent restart work: #61

Checklist

For everyone

  • One topic.
  • The title is a Conventional Commit (type(scope): description).
  • Rebased on current main. Exact base 5e072fc8c; final head db39383ba.
  • python -I -B tests/run_all.py run and passing (any failure that also fails on main is named above). 543 passed, 3 inherited failures, 16 skipped on this final head.
  • Tested in the game, or what wasn't is named under Testing. The r4 functional evidence is carried with unchanged feature/test patches, not relabelled as an r5 run.
  • 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. Quiet window 2 is complete at the named r4 commits; no distinguishable cost within repeat spread.
  • 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.
  • Flags noted, and the switch reference updated (docs/development.md, the README).
  • Screenshots for a change that shows on screen. Existing inspected attachments keep their actual tested heads.
  • A file in docs/tested/ for each new measured run (format in docs/tested-configurations.md; no appended row or assembled view). Eight records, including the rejected first window.
  • 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.
  • Host code builds on both Windows (llvm-mingw) and Linux, with UTF-8 paths. Built and linked for both at db39383ba042ca131ea9ddf8fe520d39833fc8ec (under Testing); nothing was run on Windows, so UTF-8 path behavior at run time is not claimed.
  • Docs updated.

Moved from NotRexed/Hookshot#1560.

Co-Authored-By: Nicholas Gower [email protected]
Assisted-by: GPT-6 Astra
Co-Authored-By: GPT-6 Astra [email protected]

## Why **What this is for:** Nicholas Gower's Skip title work lets a returning player launch into the game's newest save without pressing through the title and file list. Michael Schienbein carried it here from https://github.com/NotRexed/Hookshot/pull/1560 with Nicholas credited as co-author, so restart in place can build on it. **What is measured:** current game-free checks, four standalone Linux/RTX 4090 functional cases at `5c175a472`, and a completed quiet interleaved Off-cost comparison against `0caf06184`. It finds no cost distinguishable from main's 0.8566% repeat spread; this change's own spread is 1.3907%. **Not measured:** Windows runtime, physical input, other hardware/scenes or a game run on the current head. Below, "r4" is the earlier head `5c175a472` (on main `0caf06184`), where the game runs and the measurement were taken, and "r5" is the current head `db39383ba` (on main `5e072fc8c`), which carries the same three feature and test commits unchanged plus the run records. ## What changed - `gpu/vk/vk_menu.cpp` and `vk_menu.h`: the Gameplay row **Skip title screen**, Off by default, saved as `skip_title_screen`. It takes effect after a restart. - `gpu/vk/vk_api.h` and `vk_replay.cpp`: use the already reserved option 44 and answer it through the existing option callback. Skip opening remains 52; neither renderer interface changes. - `host/oot_autoload.c` and `.h`: find the newest save by modification time, then use the existing host input-tap implementation to press A through the title and file list. The game chooses which save to load; this code does not select a slot or check save contents. With no save, it leaves the title alone. - `host/nn_hid.c` and `hos_main.c`: run the title helper from input reads and reuse the existing player-seen signal to stop once play begins. No second input-tap implementation is added. - `tests/test_skip_title.py`: compile the actual host implementation against temporary files and controlled clock/input observations. Preserve the background-input fixture and the Skip opening/option-allocation checks. The standalone fixture carries its existing README case and secure-CRT fixes, split from the mixed test commit in 61. - `README.md` and `docs/development.md`: retain the option-table entry, player explanation and saved-key reference. This feature changes no language catalogue entries or counts; its row and help still use English fallback. Main's current translations are retained. This does not include save-before-restart, continuation notes, the windowless Restart/Quit repair, or restart's later idle-demand guard. Those remain in 61. All added and removed lines of the three Skip title commits are preserved through this carry; that is patch evidence, not a new game result. - `docs/tested/`: eight new run records in one separate documentation commit, preserving the first window's rejection and the second window's within-repeat-spread result. ## Flags and settings | Flag | What it does | Default now | Recommendation | Helps on | Doesn't help on | Untested on | |---|---|---|---|---|---|---| | `Skip title screen` | Gameplay row: press through the title and file list after the next start | Off | Off by default: an explicit player choice | Returning to an existing save | Starting a new game; choosing a different save manually | Windows; real input; other scenes and unusual prompts | | `skip_title_screen` | Saved key for the row: 0 Off, 1 On | 0 | Off by default: follows the row | Remembering the player's choice | Repairing or validating saves | Windows non-ASCII and long paths | | `HOS_OPT_SKIP_TITLE` | Internal option callback, using reserved number 44 | 0 | Off by default: follows the row, not an environment switch | Connecting the menu to the host | Skip opening, which retains option 52 | Windows game/runtime | ## Measurements ### Final r5 source checks, 14 November main: 5e072fc8c2adadba5ea610148be1c47800ba0cca (2026-11-14 UTC) this PR: feat/skip-title @ db39383ba042ca131ea9ddf8fe520d39833fc8ec Hardware: Core i9-13900K, 96 GB RAM, Arch Linux 7.2.15-1-omarchy, GCC 16.2.1, Clang 23.1.3, Python 3.12.16; RTX 4090/NVIDIA 615.78.08 for windowless game evidence. Scene: authored temporary-file, menu/input and save-state fixtures; no game is started by these checks. Method: focused GCC/Clang checks and the whole strict suite once on the final head, including the run-record commit; main's retained exact-head suite is the baseline. How to reproduce: `python -I -B tests/run_all.py --jobs 6 --strict`; run `tests/test_tested_configurations.py` for the records and the Skip title drivers with GCC and Clang. | Check | main @ 5e072fc8c | this PR @ db39383ba | |---|---|---| | Whole strict suite | 542 passed, 3 failed, 16 skipped | 543 passed, the same 3 failures, 16 skipped | | Focused checks | Inherited GCC menu-key failure; matrix not repeated | GCC 28 passed / 1 inherited failure; Clang 24 passed | | Feature source guard | Expected absent-row failure | Pass | | Per-run catalogue format | Existing catalogue | Complete driver passes before and after the added records | | Feature runtime/build evidence | Actual base 0caf06184 | Game runs carried from r4 5c175a472; r5 built and linked for Windows and Linux, not run | ```text 28 passed, 1 failed, 0 skipped in 11 s (linux, 1 at once) 24 passed, 0 failed, 0 skipped in 10 s (linux, 1 at once) 543 passed, 3 failed, 16 skipped in 152 s (linux, 6 at once) ``` The whole-suite failures are exactly main's `tests/test_framegen_resources.py` (missing Intel-gate/guarded-call declarations in its fixture), `tests/test_module_ids.py` (an old exact function signature), and `tests/test_pad_layout.py` (missing `HoldToggle` declaration). The separate GCC-only `tests/test_menu_keys.py` failure is g++ rejecting three C-header `_Static_assert` spellings; Clang passes. No failing check or assertion was removed. The carry onto main `5e072fc8c` changed no added or removed line of the feature/test commits. Its two later commits are `5ed8141af` (PsychoV35's adapted scene-tone-map permutation) and `5e072fc8c` (actor-motion pose capture and pairing model copies by place), with their tests and run records. Neither changes the title, input, save or restart code. The measured settings use the game's upscaler with frame generation and HDR Off. Earlier game runs and measurements remain attributed to `0caf06184`, `5c175a472` and `d89cb5992` as applicable; they were not rerun on r5, and are not a new absolute frame-time result for current main. Each r5 layer adds only its separate measured-run documentation commit. ### Completed Skip title Off measurement at r4 main: 0caf06184b391a5259d3741bb006ef5826eb6417 (2026-11-14 UTC) this PR: feat/skip-title @ 5c175a4727d82f85e425e85400dca17fea0750fb Hardware: Core i9-13900K, 96 GB RAM, Arch Linux 7.2.15-1-omarchy, GCC 16.2.1, Clang 23.1.3, Python 3.12.16; RTX 4090/NVIDIA 615.78.08 for windowless game evidence. Scene: Kokiri Forest, the same copied save, stationary view by the sign, menu closed. Settings: Windowless, game output 1280x720, render 100%, game's upscaler, frame generation/HDR/FPS overlay Off, real-time speed, `HOS_FPS_MAX=1000` (Uncapped). Saved V-Sync is 0, labelled Auto; there is no swapchain or display wait in this run. Skip title is Off. Method: both scenes warmed, then A1/B1/A2/B2 in each quiet exclusive window; 85-second game bounds, three seconds of scene settling followed by 25 seconds of game-present-return CPU intervals. This clock measures neither GPU completion nor display latency. Matched release builds, lift and profile. Other-work CPU must average below 3 cores and peak at most 6 over five seconds, repeat spread at most 5%, with no measured gap over one second. How to reproduce: load the same valid copied save on the two named builds, keep the above settings and fixed camera, then collect two interleaved stationary samples per build after settling. **Result: no cost distinguishable from the repeats' spread.** In the quiet second window, main's two medians are 13.758351 and 13.641001 ms; Skip title Off's are 13.730049 and 13.540422 ms. Main's repeat span is 0.117350 ms (0.8566%); the candidate's is 0.189627 ms (1.3907%). Main's span exceeds the between-arm difference, so this is neither a speed gain nor proof of zero cost. It is a completed measurement with a `within-repeat-spread` result, not a missing measurement. | Quiet window 2 | main @ 0caf06184 | this PR @ 5c175a472 | |---|---:|---:| | Run medians, ms | 13.758351; 13.641001 | 13.730049; 13.540422 | | Median of the two run medians, ms | 13.699676 | 13.635236 | | Repeat span, ms / percent | 0.117350 / 0.8566% | 0.189627 / 1.3907% | The first window is disturbed and rejected in full: A2 used 7.942 other-work cores on average and peaked at 28.797. The second passed two five-second admission samples (0.608 and 0.296 cores) and all four sample-window quiet checks. Every run is retained, including the rejected window: | Window/run | Build | Median ms | Mean ms | p99 ms | Other CPU mean / 5-s peak (cores) | Load before to after | Status | |---|---|---:|---:|---:|---:|---|---| | W1 A1 | main @ 0caf06184 | 13.618077 | 13.881730 | 21.311780 | 1.689 / 1.746 | 1.47 to 5.81 | Rejected whole window: A2 disturbed | | W1 B1 | this PR, Skip title Off @ 5c175a472 | 13.463051 | 13.837404 | 21.195355 | 1.675 / 1.776 | 5.81 to 6.90 | Rejected whole window: A2 disturbed | | W1 A2 | main @ 0caf06184 | 13.905075 | 17.108690 | 102.825698 | 7.942 / 28.797 | 6.90 to 17.73 | Rejected whole window: A2 disturbed | | W1 B2 | this PR, Skip title Off @ 5c175a472 | 13.653566 | 14.017513 | 21.309892 | 1.788 / 1.868 | 17.73 to 9.92 | Rejected whole window: A2 disturbed | | W2 A1 | main @ 0caf06184 | 13.758351 | 14.152099 | 21.785438 | 1.767 / 1.904 | 1.26 to 7.04 | Valid, quiet; within repeat spread | | W2 B1 | this PR, Skip title Off @ 5c175a472 | 13.730049 | 14.100743 | 22.106411 | 1.768 / 1.893 | 7.04 to 7.31 | Valid, quiet; within repeat spread | | W2 A2 | main @ 0caf06184 | 13.641001 | 13.981753 | 21.407780 | 1.836 / 1.911 | 7.31 to 12.32 | Valid, quiet; within repeat spread | | W2 B2 | this PR, Skip title Off @ 5c175a472 | 13.540422 | 13.815604 | 20.891918 | 1.696 / 1.766 | 12.32 to 8.24 | Valid, quiet; within repeat spread | ```text W1 A1: 0caf0618 exit=124 valid=True disturbed=False others 1.69 cores (highest 5 s 1.75) load 1.47 -> 5.81 kernel=0 fps=72.04 mean=13.882 ms readbacks/frame=- wait/frame=- ms W1 B1: 5c175a47 exit=124 valid=True disturbed=False others 1.68 cores (highest 5 s 1.78) load 5.81 -> 6.90 kernel=0 fps=72.27 mean=13.837 ms readbacks/frame=- wait/frame=- ms W1 A2: 0caf0618 exit=124 valid=True disturbed=True others 7.94 cores (highest 5 s 28.80) load 6.90 -> 17.73 kernel=0 fps=58.45 mean=17.109 ms readbacks/frame=- wait/frame=- ms W1 B2: 5c175a47 exit=124 valid=True disturbed=False others 1.79 cores (highest 5 s 1.87) load 17.73 -> 9.92 kernel=0 fps=71.34 mean=14.018 ms readbacks/frame=- wait/frame=- ms W2 A1: 0caf0618 exit=124 valid=True disturbed=False others 1.77 cores (highest 5 s 1.90) load 1.26 -> 7.04 kernel=0 fps=70.66 mean=14.152 ms readbacks/frame=- wait/frame=- ms W2 B1: 5c175a47 exit=124 valid=True disturbed=False others 1.77 cores (highest 5 s 1.89) load 7.04 -> 7.31 kernel=0 fps=70.92 mean=14.101 ms readbacks/frame=- wait/frame=- ms W2 A2: 0caf0618 exit=124 valid=True disturbed=False others 1.84 cores (highest 5 s 1.91) load 7.31 -> 12.32 kernel=0 fps=71.52 mean=13.982 ms readbacks/frame=- wait/frame=- ms W2 B2: 5c175a47 exit=124 valid=True disturbed=False others 1.70 cores (highest 5 s 1.77) load 12.32 -> 8.24 kernel=0 fps=72.38 mean=13.816 ms readbacks/frame=- wait/frame=- ms ``` The two holds occupied 348.1 and 353.295 seconds including settling and shutdown. All eight games ended at the intended bound (124), with complete journal coverage and no fatal/device/kernel fault. Scene pictures were inspected. Eight self-contained files under `docs/tested/` retain these actual measured commits and mark every first-window row rejected. The original baseline warm-up's clean Quit was first misclassified as invalid by its exit check; the retained game evidence established successful warming without repeating it. ## Testing **Tested:** final r5 focused GCC/Clang and whole-suite checks above; the per-run catalogue before and after the added records. The feature's main-source control fails for the intended absent row. On r4 `5c175a472`, the native Linux executable/renderer and Windows cross-build both linked; all four captured Windows-target fixture units passed, not Windows execution. The four Linux/RTX 4090 cases below and the Off-cost measurement retain that r4 head. ### Carried standalone game cases, 14 November Same head `5c175a472`, source fingerprint `7a3c888d`; 1920×1080 output, render resolution 100%, frame generation/V-Sync/FPS overlay Off, real-time speed and a 60 cap. These are pass/fail observations, not frame-time or startup-speed measurements. | Case | Result and criterion | |---|---| | On, two intact copied saves, **no input at all** | **Pass:** the real option reads 1. No input environment/file/menu script and no controller presses. It opens the uniquely newest `slot_01/progress.sav`, logs automatic loading complete, and reaches fresh playable forest state without an event/load. | | On, fresh empty profile | **Pass:** after an 80.4-second observation it remains at New Game; the helper reports no save. No regular file is created in the disposable user profile. | | Off, same copied saves | **Pass:** after an 80.4-second observation it remains at Continue waiting for input, with no automatic-loading line or save load. | | Gameplay row and help | **Pass:** the standalone build's selected Skip title screen row, On value and complete help are visible in the inspected menu capture. | `slot_01` is newest because its original modification time is 11 November 02:45:19 local, later than `slot_00` at 01:38:45. Both were known-valid test-library saves; this run also proves the selected one loads. This does not claim content validation or recovery from a newer damaged file. ```text skip title: .../slot_01/progress.sav is the most recent save: pressing A from 20 s fs: OpenFile(save:/slot_01/progress.sav) skip title: loaded, the player is running skip title: no saved game yet: the title screen stays ``` The On run observes fresh playable state at frame 2013 (game sample frame 2013, event/loading false), then frame 2325 with a fresh sample and the same saved position. All four games exit 0, leave no owned process, and have complete journal coverage with zero fatal/crash/device/driver faults or NVIDIA mapping/allocation refusals. The copied saves and registered source stay byte-identical. Every picture below was inspected. **Built at r5:** At `db39383ba042ca131ea9ddf8fe520d39833fc8ec`, the Windows x86-64 Vulkan renderer DLL and all 48 selected host translation units were cross-built on Linux with llvm-mingw 20261104 (Clang 23.1.5), using the project's production flags and pinned dependencies (renderer: 35 newly compiled / 170 reused; host: 1 newly compiled / 47 reused; lifted C: 0 newly compiled / 80 reused; all Windows units: 36 newly compiled / 611 reused from matching object-cache entries), the renderer DLL linked and the full game executable linked; nothing was run on Windows or under Wine, and this is neither the project's hosted builder run nor a Windows UTF-8 run-time path test. The exact same head `db39383ba042ca131ea9ddf8fe520d39833fc8ec` also compiled and linked its full native Linux executable and renderer with Clang 23.1.3 through the documented resume path (247 newly compiled units, 242 matching Linux-cache units, source stamp `63776eb6`), using the verified target-neutral C from lift `5c175a4727d82f85e425e85400dca17fea0750fb` rather than carrying the patch onto another commit; neither Linux binary was run. **Not tested:** game execution on r5; Windows execution of the new/changed C fixtures; Windows game/runtime, non-ASCII/long Windows save paths, real keyboard/controller input, AMD/Deck, other areas, unusual title prompts and damaged-save handling. Automatic title loading with non-default held/toggled A has not been tried in the game. Opening the Insert menu during automatic loading was not tested; the row picture is after loading. The row/help still use English fallback. The measured within-repeat-spread result does not establish zero cost. **Needs other testers:** - Windows x64 with a real keyboard or controller: use disposable valid saves and a path with spaces and a non-ASCII letter. Check Off stays at the title; On reaches the newest save without manual loading; a fresh profile stays at New Game; opening the Insert menu pauses automatic presses (T-TSA8, open). ## Screenshots ![Standalone 5c175a472, Skip title On: the newest valid copied save loads with no test input; Link, hearts, minimap and movement controls are visible.](https://git.magicbean.dev/attachments/4eed061c-7be2-4a6e-bf99-4d5663111ca4) ![Standalone 5c175a472, Skip title On with a fresh profile: New Game stays; no save file is created.](https://git.magicbean.dev/attachments/aab6f8c8-d838-4119-a678-84a0d8fd5791) ![Standalone 5c175a472, Skip title Off with saves present: Continue waits for the player.](https://git.magicbean.dev/attachments/4cc3ab25-ed8b-4f3c-b334-3d206d148bae) ![Standalone 5c175a472: the selected Skip title screen row is On; the full help explains newest-save startup, no-save behavior and restart applicability.](https://git.magicbean.dev/attachments/062855be-7060-4541-8a9c-6743e1cde072) ![Window 1, physical A1/B1/A2/B2 order: same scene, main 0caf06184 versus title 5c175a472 Off. A2 is labelled disturbed; the whole window is rejected.](https://git.magicbean.dev/attachments/cb225db6-905a-43c7-ae13-038de3fbe5fd) ![Window 2, same order and builds: all rows quiet, but the result is no distinguishable cost within repeat spread. Pictures establish the scene, not a cost or speed gain.](https://git.magicbean.dev/attachments/09425b46-6432-4fd9-ba57-57e226256a3d) ## Risk and rollback The helper presses A on a timer, starting after 20 seconds, every 2 seconds, until play begins or 120 seconds pass. It does not identify the active title prompt. The Insert menu pauses it and switching the row Off stops it, but touching another control does not automatically cancel it. Unexpected confirmations and damaged saves remain risks. A file's presence and modification time do not establish that it is safe to load. Set `skip_title_screen=0` or turn the row Off, then restart, to return to manual loading. Reverting these commits removes the option; it does not repair a damaged save. ## Reviewer notes Read `hos_oot_autoload_input`, `hos_oot_newest_save`, the input call and option 44 first. The original provenance and Nicholas Gower's exact co-author trailer remain. Three carried commits compare equal by range-diff, with author/date/message and every added/removed patch line preserved; the fourth commit records the eight runs only. The archived review questioned timed A presses on unexpected prompts and the absence of cancellation on physical player input. Those remain disclosed design risks for review, not a claim that every prompt is safe. The current forge review can decide the approach. The standalone helper still reads the clock on input calls when Off; the measurement does not claim that instruction costs zero. Skip title retains reserved option 44; Skip opening remains 52. The earlier 128-PR option survey is historical, not a new inventory. https://git.magicbean.dev/MagicBeanDev/Longshot/pulls/61 contains these same three feature/test commits and the run-record commit until this merges. The separate restart layer uses option 64, which clashes with `HOS_OPT_GFX_OBJECTS` in https://git.magicbean.dev/MagicBeanDev/Longshot/pulls/227 at `0fc2e8c9268d8611d5070cef9540725d60364874`; that is not a title-only collision. ## Issues Original work: https://github.com/NotRexed/Hookshot/pull/1560 Dependent restart work: https://git.magicbean.dev/MagicBeanDev/Longshot/pulls/61 ## Checklist ### For everyone - [x] One topic. - [x] The title is a Conventional Commit (`type(scope): description`). - [x] Rebased on current `main`. Exact base 5e072fc8c; final head db39383ba. - [x] `python -I -B tests/run_all.py` run and passing (any failure that also fails on `main` is named above). 543 passed, 3 inherited failures, 16 skipped on this final head. - [x] Tested in the game, or what wasn't is named under Testing. The r4 functional evidence is carried with unchanged feature/test patches, not relabelled as an r5 run. - [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. Quiet window 2 is complete at the named r4 commits; no distinguishable cost within repeat spread. - [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] Flags noted, and the switch reference updated (docs/development.md, the README). - [x] Screenshots for a change that shows on screen. Existing inspected attachments keep their actual tested heads. - [x] A file in `docs/tested/` for each new measured run (format in `docs/tested-configurations.md`; no appended row or assembled view). Eight records, including the rejected first window. - [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. - [x] Host code builds on both Windows (llvm-mingw) and Linux, with UTF-8 paths. Built and linked for both at `db39383ba042ca131ea9ddf8fe520d39833fc8ec` (under Testing); nothing was run on Windows, so UTF-8 path behavior at run time is not claimed. - [x] Docs updated. --- Moved from NotRexed/Hookshot#1560. Co-Authored-By: Nicholas Gower <[email protected]> Assisted-by: GPT-6 Astra Co-Authored-By: GPT-6 Astra <[email protected]>
Rebase Nicholas Gower’s pull request #1560 for the restart-in-place dependency. Keep the existing hos_hid_tap implementation, current menu rows and option handlers. The option remains off by default.

Co-Authored-By: Nicholas Gower <[email protected]>
Assisted-by: GPT-6 Astra
Co-Authored-By: GPT-6 Astra <[email protected]>
Skip title now occupies reserved option 44. Check its actual enum declaration while retaining all opening, option 52, no-collision and gameplay assertions. Declare the standard fixture CRT policy before headers for the Windows-target check.

Assisted-by: GPT-6 Astra
Co-Authored-By: GPT-6 Astra <[email protected]>
test(menu): keep the Skip title fixture portable on its own
All checks were successful
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Has been skipped
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Has been skipped
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Has been skipped
Third-party parts / The same as upstream (pull_request) Has been skipped
CI / Conventional Commit title (pull_request) Successful in 4s
CI / Workflow lint (actionlint) (pull_request) Successful in 7s
Third-party parts / As their notes say (pull_request) Successful in 8s
Website / Website on Cloudflare (pull_request_target) Has been skipped
PR description / Description follows the template (pull_request_target) Successful in 9s
5c175a4727
Split only the Skip title fixture changes from 99c86180d5. Follow the README.md case and apply the existing secure-CRT policy before all translation units. The restart and file-open changes stay with restart in place; no assertion or runtime behavior changes.

Assisted-by: GPT-6 Astra
Co-Authored-By: GPT-6 Astra <[email protected]>
Author
Member

Carried onto main 5e072fc8c; new head db39383ba042ca131ea9ddf8fe520d39833fc8ec. The three feature and test commits replay unchanged; one new commit adds the eight run files of the two measurement windows under docs/tested/. The whole suite on this exact head: 543 passed, 3 failed, 16 skipped; the three failures are main's own tests/test_pad_layout.py, tests/test_module_ids.py and tests/test_framegen_resources.py.

The measurement is complete, so its box is ticked: with Skip title off, frame times cannot be told apart from main's within the spread between repeats. In the quiet second window main's two medians are 13.758 and 13.641 ms and this change's are 13.730 and 13.540 ms. The first window was disturbed by other work on the PC and is kept in the run files as rejected. That is neither a speed gain nor proof of zero cost.

The game runs and pictures keep the earlier head 5c175a472 they were taken on. The build box stays unticked until this pushed head has been built for Windows and Linux. The Windows test request T-TSA8 is still open.

Carried onto main `5e072fc8c`; new head `db39383ba042ca131ea9ddf8fe520d39833fc8ec`. The three feature and test commits replay unchanged; one new commit adds the eight run files of the two measurement windows under `docs/tested/`. The whole suite on this exact head: 543 passed, 3 failed, 16 skipped; the three failures are main's own `tests/test_pad_layout.py`, `tests/test_module_ids.py` and `tests/test_framegen_resources.py`. The measurement is complete, so its box is ticked: with Skip title off, frame times cannot be told apart from main's within the spread between repeats. In the quiet second window main's two medians are 13.758 and 13.641 ms and this change's are 13.730 and 13.540 ms. The first window was disturbed by other work on the PC and is kept in the run files as rejected. That is neither a speed gain nor proof of zero cost. The game runs and pictures keep the earlier head `5c175a472` they were taken on. The build box stays unticked until this pushed head has been built for Windows and Linux. The Windows test request T-TSA8 is still open.
mooki force-pushed feat/skip-title from 5c175a4727
All checks were successful
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Has been skipped
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Has been skipped
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Has been skipped
Third-party parts / The same as upstream (pull_request) Has been skipped
CI / Conventional Commit title (pull_request) Successful in 4s
CI / Workflow lint (actionlint) (pull_request) Successful in 7s
Third-party parts / As their notes say (pull_request) Successful in 8s
Website / Website on Cloudflare (pull_request_target) Has been skipped
PR description / Description follows the template (pull_request_target) Successful in 9s
to db39383ba0
All checks were successful
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Has been skipped
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Has been skipped
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Has been skipped
Third-party parts / The same as upstream (pull_request) Has been skipped
Website / Website on Cloudflare (pull_request) Has been skipped
CI / Conventional Commit title (pull_request) Successful in 3s
CI / Workflow lint (actionlint) (pull_request) Successful in 5s
Third-party parts / As their notes say (pull_request) Successful in 7s
PR description / Description follows the template (pull_request_target) Successful in 6s
2026-11-14 14:12:49 +00:00
Compare
Author
Member

The pushed head db39383ba042ca131ea9ddf8fe520d39833fc8ec is now built and linked for Windows (cross-built with llvm-mingw 20261104, Clang 23.1.5) and for Linux (Clang 23.1.3); the details are under Testing and the build box is ticked. Nothing was run on Windows. With the measurement complete and every box ticked, this is ready for review.

The pushed head `db39383ba042ca131ea9ddf8fe520d39833fc8ec` is now built and linked for Windows (cross-built with llvm-mingw 20261104, Clang 23.1.5) and for Linux (Clang 23.1.3); the details are under Testing and the build box is ticked. Nothing was run on Windows. With the measurement complete and every box ticked, this is ready for review.
mooki changed title from WIP: feat(menu): skip the title screen and load the newest save to feat(menu): skip the title screen and load the newest save 2026-11-14 14:54:49 +00:00
HumanBean deleted branch feat/skip-title 2026-11-14 15:32:54 +00:00
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!399
No description provided.