Repository navigation
Ocarina of Time: keep the frame ratio at step × base / 60, count a half-rate frame once, and test the stub - #2071
Open
oliverames wants to merge 2 commits into
Open
oliverames wants to merge 2 commits into
oliverames wants to merge 2 commits into
Conversation
…e, the stub's branches are computed, and a test runs it at both base rates Base 30 in the frame ratio is the framework's half rate, not a cutscene speed: bit 0 of its +0x24f is the mode and bit 1 flips each pass of its frame function, and with both set the draw and the present return at once while the calc tree runs. The game then calcs twice a drawn frame, the ratio's function among them, so each calc takes half the frame's step: step x base / 60 is right, and the step alone (PR seedds#1996) would run that mode at twice its speed. The ratio's unit is 1/60 s whatever the base (the time object's step in seconds is ratio x 1/60). The stub counted the frame's vsyncs at both calcs, so the host's game time would read twice the real time in that mode. It now counts them at the calc that is drawn. Its branch targets are computed from the words emitted instead of fixed offsets. test_oot_frame_step.py runs the emitted stub under Unicorn (optional, as test_astral_fps.py): both bases at steps 1 to 3, the count, x17 lost after a store, and the game's own division at target 0 and before a step is decided. It fails on main's stub (the count) and on PR seedds#1996's (the ratio). Co-authored-by: Zard Studios <96824937+Zard-Studios@users.noreply.github.com> Co-authored-by: dsi-hub <260802842+dsi-hub@users.noreply.github.com>
oliverames
force-pushed
the
oot-frame-step-half-rate
branch
from
November 10, 2026 14:04
b0d9c3d to
02dc1b2
Compare
Conflicts: dm/games/0400486024DEC000/README.md (kept both bullets).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What and why
#1996 changes the frame-step stub's ratio from
step × base / 60to the step alone, reading the base rate of 30 as a cutscene speed. I went through the game code before porting that to my iPhone Duo build, and main's formula is the right one. This PR keeps it, fixes a smaller counting error I found on the way, and adds a test that tells the two formulas apart.Here's what base 30 is on v131072
main:main+0x3b4e300) stores the step in seconds as ratio × 0.0166667.+0x24fis a half-rate mode, and bit 1 flips on each pass of its frame function (main+0x346c680). With both set, the draw (main+0x2cb020) and the present (main+0x40cd20) return at once, but the calc tree still runs. The ratio's function is in that tree, so it runs twice for each drawn frame.step × 30 / 60. The step alone would run that mode at twice its speed.The counting error is in the same mode. The stub added the frame's vsyncs to the host's count at both calcs, so the log's game time would read twice the real time there. It now counts at the calc that's drawn. I also compute the stub's branch offsets from the words emitted instead of fixed numbers, so the next edit to the stub can't leave a stale branch behind.
I don't think the half-speed cutscenes behind #1996 come from the ratio. My phone never entered the half-rate mode (see below), and the slow part was the movies, because the game's player takes one picture a calc. That's #1922. #2072 and its follow-up #2082 are both closed (#2082 crashed the game in the half rate), and #2456 by PucaVaz now lets the movie player take two pictures a frame.
The game note has the finding under "Current: the base rate of 30 is the framework's half rate".
Checked
dm/tools/tests/test_oot_frame_step.pyis new. It runs the emitted stub under Unicorn and skips without it, liketest_astral_fps.py. It covers both bases at steps 1 to 3, the vsync count, x17 lost after a store, and the game's own division at target 0 and before a step is decided. All 5 pass here. The same test fails on main's stub (the count) and on Fix Ocarina of Time frame ratio calculation and enable frame buffering (0400486024DEC000) #1996's formula (the ratio).test_patches.py,test_nso_match.py,test_docs.pyandlint_python.pypass, andpatch_nso.pyplaces the stub on the real v131072main.Docs
docs/reference/<subsystem>.mdentry, andpython3 dm/tools/docs_symptoms.pywas run (the symptom index)dmsh_chain.py --headerwas run anddm/gfx/nvn/dmsh_chain.his part of the change (no chain tool changed)