fix(oot): preserve Scarecrow's Song recording and playback timing #78
No reviewers
Labels
No labels
accessibility
autorelease: pending
autorelease: tagged
bug
dependencies
documentation
duplicate
enhancement
github_actions
good first issue
help wanted
invalid
needs measurements
question
testing wanted
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
MagicBeanDev/Longshot!78
Loading…
Reference in a new issue
No description provided.
Delete branch "mooki/Longshot:fix/oot-scarecrow-song-timing"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Why
Scarecrow's Song can lose its recorded rhythm or appear stuck on its first note when the game runs above 60 fps. This keeps fractional time for all three updates of the eight-note song's elapsed counter, without changing existing saves.
The run-wide diagnostic median was lower on the branch, but it is not a speed comparison: the fixed song returns to gameplay while main stays in the note screen.
What changed
nx2/oot_patches.py: add playback, eight-note recording and final-note completion to the existing whole-frame carry table. They share the same elapsed counter; no new helper, forced minimum step or frame cap.tests/test_scarecrow_timing.py: compile authored conversion shapes with the real patch and fraction helper. Cover all nine recording/playback combinations at 60, 120 and 240, the final note, counter resets, shared remainders, idempotence and the untouched other recording branch.README.md: explain that already-lost rhythm cannot be recovered; re-record an affected song after updating. Correctly recorded old songs need no re-teaching.docs/tested-configurations.md: keep a row for each of the four new Longshot correctness runs, including the fourth run's pre-play core escapes.Flags and settings
None. No setting, menu choice, environment variable or saved format is added or changed. The existing above-60 warning still applies to other gameplay.
Measurements
Branch state: on main
f41db065cf6667ec638a10aa6990099392d10dca; head5dd2ee53566bbf9f918bac55eca3e33dc2a6cbcb; whole game-free suite on this head:510 passed, 0 failed, 19 skipped(mainf41db065cf6667ec638a10aa6990099392d10dca:509 passed, 0 failed, 19 skipped); the commits are unchanged by rebases apart from the results table.main:
d4a69456c9(2026-11-12)this PR: fix/oot-scarecrow-song-timing @ 57696d0c21178b439ca35f9ddda27728da2f1de0
Hardware: RTX 4090 24 GB, NVIDIA 615.78.08; Core i9-13900K, 96 GB installed (93 GB reported by the game); Arch Linux 7.2.15-1-omarchy
Scene: adult Link in Hyrule Field at the same saved spot, the same correctly recorded eight-note song; 1280x720 game output, 1920x1080 offscreen renderer surface, Custom preset, Game's own upscaler at 50%, frame generation off, cap 240, precompile off, no window
Method: warmed both builds, then main / branch / main / branch in one isolated 344-second correctness session. Four 85.7–85.8-second processes. Captures at five and twenty seconds after the last scripted note release; actual five-second captures completed at 5.04–5.05 seconds. Native present traces show a mean above 60 during the measured 20-second interval on every run. The table counts visible notes and completion, not fps gains or exact song duration.
How to reproduce: teach an eight-note Scarecrow song as young Link at a 60 cap, keep that save, then play it as adult Link on a PC actually running above 60 with a 240 cap. Compare the note sheet after five and twenty seconds. Run
python -I -B tests/test_scarecrow_timing.py --cc gcc; its--sourceoption accepts the main patch file for the negative control.d4a69456The fixture's main execution used
d725b363, whose runtime source is identical to the measured main. Afterward main gained only the DLSS model-settle runtime change and documentation/tooling/tests; DLSS was off in these runs, and the song code and fixture inputs are unchanged. The measured commits above are retained rather than relabelled as the current branch.Actual fixture output, repeated identically in both pairs:
d4a69456d4a69456Every game had the intended bounded exit 124, not a claimed graceful quit. Fatal, device-loss and kernel-fault counts were zero, with complete journal coverage. The fourth run had five virtual-core escapes around present 7530, before controllable play at frame 7905; the others had none. Those lines are retained, not discarded to make the result look cleaner.
Earlier ordinary attempts first hit the game's first-use ocarina tutorial, so their notes were not accepted and their pictures were rejected. The corrected ordinary main warm-up completed the song under shared load, without establishing the above-60 failing condition. Those attempts are retained, not used as before/after proof.
Testing
Tested: native Linux Longshot build and the four adult-field playback runs above, using matching release-profile builds and copied saves. Both pairs' source images and the final panel were inspected. The same real-source fixture failed on main and passed here in two interleaved pairs. The complete game-free suite ran on the exact branch state above. One C translation unit compiles for the Windows target with strict warnings: zero failures and zero unjudged files; not run on Windows.
Historical Hookshot evidence, not a new Longshot run: a fresh child recording at a 240 cap retained all eight notes, including the last note; that recording played at caps 60/120/240. The original correctly recorded song also completed at adult Bonooru. The original three-site fix was included in the combined successful GitHub Windows/Ubuntu check; the renamed branch is not claimed to have new Windows execution.
Not tested: the new Longshot runs replay an existing song recorded historically as young Link at a 60 cap; they do not newly teach it as young Link, traverse the age change, or confirm the scarecrow's answer. The separate mode-13 recording loop is unchanged and untested. No Windows/AMD/Intel gameplay, physical controller or microphone, audible output, real-window presentation, long-session coverage or general above-60 gameplay guarantee. The changed fixture was not executed on Windows after the rename; target compilation is not Windows runtime evidence.
Needs other testers:
Screenshots
Risk and rollback
A wrong patch-site match could leave a song counter uncorrected; the existing patch-count warning and authored three-site fixture make that visible. The separate recording mode is deliberately untouched. No save is rewritten. Reverting these entries restores the old behavior; a cap of 60 remains the workaround until a fixed build is used. Songs whose old recording lost its rhythm must be recorded again.
Reviewer notes
Start with the three whole-frame entries and the shared counter key. The third entry is necessary: the earlier two-site attempt lost the final note and was rejected. No generic timing abstraction, global minimum step or stored-song migration is introduced. The current publication remains a draft for the requested end-to-end player scenario.
Issues
Fixes #87
Original report: https://github.com/NotRexed/Hookshot/issues/2668.
Checklist
For everyone
type(scope): description).main.python -I -B tests/run_all.pyrun and passing (any failure that also fails onmainis named above).third_party/untouched (a new folder with aPROVENANCE.mdinstead).If applicable
Assisted-by:/Co-Authored-By:trailers.docs/tested-configurations.mdfor each measured run.mainand passing here.tests/that reads changed source updated in this PR, not weakened.New on this forge; not opened on GitHub.
Assisted-by: GPT-6 Astra
Co-Authored-By: GPT-6 Astra [email protected]
The test request for the reporter's scenario is open (T-LZ6Y). Rebased onto main
f41db065cwith the patches unchanged; whole suite on the new head5dd2ee535: 510 passed, 0 failed, 19 skipped. Ready for review.f3281c7c7dto5dd2ee5356WIP: fix(oot): preserve Scarecrow's Song recording and playback timingto fix(oot): preserve Scarecrow's Song recording and playback timingView command line instructions
Checkout
From your project repository, check out a new branch and test the changes.