Repository navigation
Arkham Knight Performance: 120 fps, 60 fps, 1080 resolution unlocked. Tested. - #1152
Open
stephenschloesser wants to merge 2 commits into
Open
stephenschloesser wants to merge 2 commits into
stephenschloesser wants to merge 2 commits into
Conversation
stephenschloesser
marked this pull request as ready for review
November 4, 2026 02:28
stephenschloesser
force-pushed
the
Arkham-Knight
branch
3 times, most recently
from
November 4, 2026 05:09
c5f02de to
47b0454
Compare
(cherry picked from commit 0a07e21)
…iews at 1x of the console mode's size The game asks for present interval 2 and draws its 3D views at 0.75 of the console mode's size (1440x810 docked). Two profile keys raise both through the game's own data, each with a row in the launcher. Frame rate. The engine caps itself with MaxSmoothedFrameRate, a float at GEngine+0x884 (GEngine: main+0x511a150) that Coalesced_INT.bin sets to 62; appUpdateTimeAndHandleMaxTickRate (main+0x1932960) sleeps until 1 / it has passed and the game steps by the time that really passed. A new hle_fpslock.c row kind, CAP_F32, writes the profile's target 2 above it — 62 at 60, the game's own value, and 122 at 120 — and the host's presents pace the frames: the present tick and the display link run at 120 Hz, one tick per frame (hle_nvn.c present_cfg / link_wait, nvn_mtl.m link_sync), on a screen that runs at 120 Hz. A prerendered movie keeps 30 fps. The launcher's Frame rate row offers 30, 60 (the default) and 120, and DM_FPS_TARGET overrides it. Render resolution. The port keeps its render resolution scale (RRS) as two percentages in main's bss, 75.0 and 75.0 at boot, with the output size right after them (0x780 1920, 0x438 1080); the code at main+0x13cd7cc divides the first by 100, clamps it to 0..1 and sizes the view with it. hle_fpslock.c now writes 100 into both fields on every present their value differs, gated on this main (a red line when another build has no row). The launcher's Render resolution row (DM_RRS, profile key render_fix, on by default) offers 1x (1080p), the default, and 0.75x (the game's own); 1x pins the pair, so the game's dynamic resolution cannot lower it again. It is the internal render size that changes, not an upscale: DM_RENDER_SCALE is untouched. Checked, headless: DM_FPS_TARGET=60 reads 59.6-60.0 fps and 120 reads 120.2 / 120.0 fps at frames 2400 / 3000; DM_CTL passdump reads 1440x812 / 720x406 / 360x203 at 0.75x and 1920x1080 / 960x540 / 480x270 at 1x, with peek of main+0x5117248 reading 75 75 and 100 100. t_fpslock passes 22 cases, t_link_ticks 33 checks and t_nvn 234. The launcher-settings, player-env and docs tests pass. Not checked: a windowed run on a 120 Hz display, gameplay past the title screen at 1x, and an iOS device.
stephenschloesser
force-pushed
the
Arkham-Knight
branch
from
November 4, 2026 05:55
47b0454 to
5c7b146
Compare
stephenschloesser
marked this pull request as draft
November 4, 2026 06:45
stephenschloesser
marked this pull request as ready for review
November 4, 2026 23:57
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.
This is the solution discussed in #384 and #115 and @v0lumehi's original solution, working now on main better than ever.
On an M1 Pro, the game is able to sustain 100+ fps at 1080p compared to 30 fps and 720p. MUCH better. The underlying nx native engine improvements have had a huge effect.
Tested on iPad Pro M4: similar performance to above, beating previous builds considerably.
What and why
Depends on #1164 — merge that first. This branch carries its clang-tidy fix as its first commit (main is red on the same five file/check pairs); that commit drops out on rebase once #1164 lands.
Batman: Arkham Knight (
0100ACD0163D0000, update 1.0.5) draws its 3D views at 0.75 of the console mode's size and asks for present interval 2, so it runs at 30 fps and 1440x810 docked, whatever paces it — the Switch's numbers. This raises both through the game's own data, with a choice for each in the launcher:Frame rate. The engine caps itself with
MaxSmoothedFrameRate, a float atGEngine+0x884(GEngine:main+0x511a150) thatCoalesced_INT.binsets to 62;appUpdateTimeAndHandleMaxTickRate(main+0x1932960) sleeps until 1 / it has passed and the game steps by the time that really passed. A newhle_fpslock.crow kind,CAP_F32, writes the profile's target 2 above it — 62 at 60, the game's own value, and 122 at 120 — and the host's presents pace the frames: the present tick and the display link run at 120 Hz, one tick per frame (hle_nvn.cpresent_cfg/link_wait,nvn_mtl.mlink_sync), on a screen that runs at 120 Hz. A prerendered movie keeps 30 fps. The launcher's Frame rate row offers 30, 60 (the default) and 120;DM_FPS_TARGEToverrides it.Render resolution. The port keeps its render resolution scale (RRS) as two percentages in
main's bss,75.0and75.0at boot, with the output size right after them (0x7801920,0x4381080); the code atmain+0x13cd7ccdivides the first by 100, clamps it to 0..1 and sizes the view with it.hle_fpslock.cnow writes 100 into both fields on every present their value differs, build-gated on this main (a red line when another build has no row). The launcher's Render resolution row (DM_RRS, profile keyrender_fix, on by default) offers 1x (1080p), the default, and 0.75x (the game's own). 1x pins the pair, so the game's dynamic resolution cannot lower it again. It is the internal render size that changes, not an upscale: the host'sDM_RENDER_SCALEis untouched and still not offered for this game.The v1.0.3 cheat
08000000 051151C8 42C80000 42C80000("Docked RRS 100% (1080p)") names the same pair, but its address holds a pointer list in 1.0.5 — the pair moved by 0x2080, which is why this is a row for this build rather than the cheat's address.Docs: the game note (new Render resolution section and status line in
dm/games/0100ACD0163D0000/README.md), therender_fixkey indm/games/README.md,docs/settings.md,docs/env_switches.tsv, the patches page (docs_patches.pyclassification), and the README gallery note.Checked
dm/host/tests/build/t_fpslock22 cases (three new RRS ones: the write, the game setting 75 again,DM_RRS=0.75, and a field not yet set);t_link_ticks33 checks;t_nvn232 checks;test_launcher_settings,test_player_envandtest_docs27 tests. The host builds withmake -C dm/host GAME=0100ACD0163D0000.0100ACD0163D00001.0.5, headless (no window) on the Mac, each run booted through the language screen, the health warning, the license notice and the title (2-4 minutes a run):DM_FPS_TARGET=60:present tick 60 Hz, the limiter left at the game's own 62, the host's accounting 59.6-60.0 fps.DM_FPS_TARGET=120:present tick 120 Hz,MaxSmoothedFrameRate 62 -> 122 cap (120 fps), 120.2 / 120.0 fps at frames 2400 / 3000.DM_CTLpassdumpat the title: the 3D passes are 1440x812 / 720x406 / 360x203 at 0.75x and 1920x1080 / 960x540 / 480x270 at 1x (1.78x the pixels);peekofmain+0x5117248reads75 75and100 100. The pair was also written through the host's own cheat VM as an independent check of the address, and the 1080p title screenshot is clean (no stretched or shifted UI).Payload/DmIOS.app, 83,274 files) and itslauncher.jsoncarries both rows, but no iPhone or iPad has installed it.Docs
dm/games/0100ACD0163D0000/README.md: Frame rate, Render resolution, status line) and therender_fixkey is indm/games/README.md;python3 dm/tools/docs_patches.pywas run (itsHOST_BINDING/SWITCH_BINDINGneeded the new row and keys) and the README gallery regenerated withdocs_gallery.py.