Repository navigation
Fire Emblem Fortune's Weave: 60 fps through the game's own target frame rate - #1015
b1tdr3amer24 wants to merge 1 commit into
Conversation
…me rate The game's graphics object (a global at [main+0x21e60d8]) holds a target frame rate at +0x1dc. The game sets it to 60 for its title and menus (main+0x652960, main+0x66af3c) and to 30 when gameplay starts (main+0x7bf1c0); its present asks for interval min([+0x1e0], [+0x1d8] / min([+0x1d8], [+0x1dc])), so 2 in gameplay. About 40 readers step the game by 60 / target, so the game is built to run at either rate. hle_fpslock.c gets a build-gated row (main db93b012..., FPS_I32) that writes the profile's fps_target there, and the profile sets fps_target 60, which also gives the settings window its Frame rate choice. The game then asks for interval 1 itself. Checked on an M4 Pro: the log shows "target frame rate 30 → 60" followed by the game's own interval 2 → 1; title frame time p50 16.6 ms, battle map p50 16.7 / p95 17.1 ms, about 2 of 300 frames dropped, in a window. DM_FPS_TARGET=30 holds 30 (p50 33.3 ms). t_fpslock, test_docs and test_profile_guess pass. Game speed at 60 against 30 over the same route was not measured. Generated with Claude Code. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Thanks, @b1tdr3amer24 — landed on What changed from the PR: no build-gated fixed-address row in Played on an M4 Pro: the host writes 30 → 60, the game asks for interval 1 itself, frame time p50 16.7 ms. The playtest also hit a crash at the title when the game showed the controller strap guide through SDK 22's |
What and why
Fire Emblem Fortune's Weave (
04007EF01F8AE000, v131072) runs its gameplay at 30 fps and asks for present interval 2, with the GPU mostly idle on a Mac.That is the game's own choice, and the game is built to run at either rate:
[main+0x21e60d8], holds a target frame rate at +0x1dc. The game sets it to 60 for its title and menus (main+0x652960,main+0x66af3c) and to 30 when gameplay starts (main+0x7bf1c0).main+0x648da0, throughgxc::NvnDevice's present atmain+0x5d170) asks for intervalmin([+0x1e0], [+0x1d8] / min([+0x1d8], [+0x1dc])), where +0x1d8 is the display rate (60) and +0x1e0 the longest interval (5).60 / target(main+0x770d5c,main+0x11e6310,main+0x13a6c94): 2.0 per frame at 30, 1.0 at 60.The change:
hle_fpslock.c: a build-gatedk_locksrow (FPS_I32) writesfps_targetinto that field. The game then asks for interval 1 itself and its step follows. No game code is cut.game.tsv:fps_target 60, which also gives the settings window its Frame rate choice.frame-rate.mdentry ("A target frame rate the game steps by"), the binding entry indocs_patches.py, and the regeneratedgame-patches.mdandsymptoms.md.Checked
make -C dm/host/tests GAME=04007EF01F8AE000t_fpslockpasses.dm/tools/tests/test_docs.pyandtest_profile_guess.pypass.make -C dm/host GAME=04007EF01F8AE000 dmhostbuilds.lint_c.py tidy dm/host/hle_fpslock.c: 0 findings.maindb93b0125f4850601d61c3edde012f8e), Mac app from this branch's parent plus The NSP script builds a Switch 2 game from a dump with only an update, and surveys a dump with no profile #973 for the update-only dump.main: Intelligent Systems target frame rate 30 → 60 fps (game profile fps_target), thenthe game sets present interval 2 → 1 (from main+0x5d1c8).DM_FPS_TARGET=30holds 30 (p50 33.3 ms).DM_FPS_TARGET=30writes 30 everywhere, including the title and menus that the game itself runs at 60.regress.py: not run. The row is gated on this game'smainbuild ID, so no other game reaches it.Docs
docs/reference/frame-rate.mdentry, andpython3 dm/tools/docs_symptoms.pywas run (the symptom index)