Skip to content

Arkham Knight Performance: 120 fps, 60 fps, 1080 resolution unlocked. Tested. - #1152

Open
stephenschloesser wants to merge 2 commits into
seedds:mainfrom
stephenschloesser:Arkham-Knight
Open

stephenschloesser wants to merge 2 commits into
seedds:mainfrom
stephenschloesser:Arkham-Knight

Conversation

@stephenschloesser

@stephenschloesser stephenschloesser commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

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 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; 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, build-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: the host's DM_RENDER_SCALE is 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), the render_fix key in dm/games/README.md, docs/settings.md, docs/env_switches.tsv, the patches page (docs_patches.py classification), and the README gallery note.

Checked

  • Tests: dm/host/tests/build/t_fpslock 22 cases (three new RRS ones: the write, the game setting 75 again, DM_RRS=0.75, and a field not yet set); t_link_ticks 33 checks; t_nvn 232 checks; test_launcher_settings, test_player_env and test_docs 27 tests. The host builds with make -C dm/host GAME=0100ACD0163D0000.
  • Games run, with title ID and version: Batman: Arkham Knight 0100ACD0163D0000 1.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.
    • Render resolution, by DM_CTL passdump at the title: the 3D passes are 1440x812 / 720x406 / 360x203 at 0.75x and 1920x1080 / 960x540 / 480x270 at 1x (1.78x the pixels); peek of main+0x5117248 reads 75 75 and 100 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).
    • Both render sizes hold 59.7-59.8 fps at the title.
  • Devices and OS: MacBook Pro, Apple M1 Pro (16 GB), macOS 26.6.2; headless. An unsigned IPA was built from the same tree (Payload/DmIOS.app, 83,274 files) and its launcher.json carries both rows, but no iPhone or iPad has installed it.
  • Measurements before and after: frame rate 30 -> 59.6-60.0 (60 target) -> 120.2/120.0 (120 target); 3D view 1440x812 -> 1920x1080 at the title screen.
  • Not checked: a windowed run on a 120 Hz display (the display link's step on screen), gameplay past the title at 1x, and any iOS device.

Docs

  • The findings are in the game note (dm/games/0100ACD0163D0000/README.md: Frame rate, Render resolution, status line) and the render_fix key is in dm/games/README.md; python3 dm/tools/docs_patches.py was run (its HOST_BINDING / SWITCH_BINDING needed the new row and keys) and the README gallery regenerated with docs_gallery.py.
  • A chain tool changed: no.
  • No game files, keys or data extracted from a game in the change or the attachments.

@github-actions github-actions Bot added host The Horizon host: SVCs, services, threads, memory (dm/host) nvn NVN on Metal and its tests (dm/gfx/nvn, dm/gfx/tests) tools Tools and scripts (dm/tools, scripts) docs Documentation game: 0100ACD0163D0000 Batman: Arkham Knight labels Nov 4, 2026
@stephenschloesser
stephenschloesser marked this pull request as ready for review November 4, 2026 02:28
@stephenschloesser
stephenschloesser force-pushed the Arkham-Knight branch 3 times, most recently from c5f02de to 47b0454 Compare November 4, 2026 05:09
Oliver Ames and others added 2 commits November 3, 2026 21:50
…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
stephenschloesser marked this pull request as draft November 4, 2026 06:45
@stephenschloesser
stephenschloesser marked this pull request as ready for review November 4, 2026 23:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs Documentation game: 0100ACD0163D0000 Batman: Arkham Knight host The Horizon host: SVCs, services, threads, memory (dm/host) nvn NVN on Metal and its tests (dm/gfx/nvn, dm/gfx/tests) tools Tools and scripts (dm/tools, scripts)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant