Repository navigation
Ocarina of Time draws its 3D above its Switch 2 resolution: Render scale 1.333 gives native 2560x1440 and 2.0 native 3840x2160 docked, where the console draws 1920x1080 and upscales - #2532
Conversation
…own size: 1.333 draws the 3D views at 2560x1440 instead of 1920x1080 docked With Dynamic resolution off, the dynamic-resolution stub's level 0 now also writes level 0's scale (the first entry of the game's level list) as the game's own scale times DM_RENDER_SCALE (state +0x10), at most 1.0 of the output. The game's own scale is kept in the state page (+0x2a0) on the first call, so 1.0, the default, writes it back and nothing changes. The stub declares RENDER_SCALE 2, so the launcher offers the setting; above 1.333 the 3D views stay at the output's size. The game reads the scale when it sets its views' sizes, at start and when the level changes, so the setting takes effect at start, as the launcher sets it. Checked on an M5 Max (40-core GPU), docked, a window, kokiri-deck from the deck save: pass dumps in play show the main passes at 1920x1080 with 1.0 and 2560x1440 with 1.333; three alternating runs of each gave 56.2 fps / GPU p50 13.46 ms with 1.0 and 57.5 fps / 13.34 ms with 1.333. docs_patches.py --check, test_docs, test_patches, test_settings and test_launcher_settings pass. The game note's new Render scale section also records why 3840x2160 is not done: the frame buffer can be raised to it, but the game's upscaler library has no variant above 2560x1440 and the window's textures stay that size.
…raws its 3D views native at it Above 1.333 the output is the game's own 3840x2160 docked instead of 2560x1440, and the 3D views are drawn at 1080 x the render scale lines of it: 2.0 at 3840x2160, 1.5 at 2880x1620 with the game's upscaler filling the rest. 1.333 or less keeps every size as before. Four sites, each found by its function's fingerprint (output_4k in patches.py): - the output size x 1.5 at the game's init (main+0x1087b70, v131072) and on a mode change (main+0x6502e0) - the window textures' size x 1.5 at the graphics init (main+0x346be50); without it every present crops a 2560x1440 window texture - the render-target memory x 2.25: the app object's budget (+0x5b8, 305 MB) and block size (+0x5c0, 64 MB), which main+0x36ae9d0 copies into the allocator; without it the per-frame render targets of a 3840x2160 view do not fit, the allocator hands out a null block and the game crashes at the first frame of play (main+0x404fc) The level-0 stub writes 1.5 x 0.75 x the render scale above 1.333, since the dynamic resolution's update and the view-size update each scale the level by 1440 / the output's height. Checked on an M5 Max (docked, a window, kokiri-deck from the deck save, two runs each): main passes at 1920x1080 / 2560x1440 / 2880x1620 / 3840x2160 with 1.0 / 1.333 / 1.5 / 2.0 (pass dumps in play), no red line; GPU p50 13.41-13.85 ms with 1.0, 13.88-13.90 with 1.333, 14.54-14.71 with 2.0, 59-60 fps. docs_patches.py --check, test_docs, test_patches, test_settings, test_launcher_settings. Not run: handheld, a slower Mac, the iPhone.
|
Tested on a slower Mac, which the description lists as not checked. The PR works as described on an M2 Pro, but native 3840x2160 costs about 31 ms of GPU time a frame there, not 1 ms. Setup: MacBook Pro M2 Pro (19-core GPU, 32 GB), macOS 27.2, built-in screen, a window, SDR, docked. Host: main
Not checked: handheld, HDR, other areas, a long session. |
|
Tested on an M2 Max (38-core GPU, 64 GB, macOS 26.6), windowed, docked, SDR, from a save in Kokiri Forest and Hyrule Castle. Engine: NX2Apple 1.5.0-rc1 (pin
The scale works as described, and 1.333 is visibly sharper (1:1 with the window). But: At 1.333 the dark areas flicker: black shapes appear for single frames at night — outdoors after dusk and in unlit interiors. It is not there at 1.0 (same save, same spot, two runs each), and it comes back at 1.333 and 1.5. It looks like the same family as the profile's "models black for one frame when a streaming step replaces their textures" (below), but the save stands still, so no streaming step should run. Reproduced with Two questions:
Either way, 1.0 is what I am running for now. Thanks for the patch: the picture at 1.333 is the best this Mac has looked. |
What and why
This lets Ocarina draw its 3D at a higher resolution than it does on a Switch 2, up to native 3840x2160. Docked, the game never draws its 3D views above 1920x1080: that's level 0, the top of its dynamic resolution, at 0.75 of its 2560x1440 output, and its upscaler fills the rest. On main the launcher's Render scale doesn't reach this game at all, because the dynamic-resolution stub never reads
DM_RENDER_SCALEand the profile doesn't declareRENDER_SCALE.With this PR the Render scale sets the 3D views at 1080 x the scale lines, docked:
Up to 1.333 it's one change: when Dynamic resolution is off, the dynamic-resolution stub's level 0 also writes level 0's scale as the game's own scale times the render scale, capped at the output's size. 1.0 writes the game's own scale back, so nothing changes unless you raise the setting.
Above 1.333 the game outputs its own 3840x2160 instead, which took four more patches. Each site is found by its function's fingerprint (
output_4kinpatches.py):I found these with probes of the view-size update in play, the host's write watch (
DM_PROBE_WATCH) on the view's size fields, and a decompile of the game's render-target allocator. The game note's Render scale section has the addresses.The game only reads these sizes at start and on a level change, so the setting takes effect at start, which is how the launcher sets it. The stub declares
RENDER_SCALE 2, so the launcher's slider goes up to 2.0.Checked
On an M5 Max (40-core GPU, 64 GB), docked, in a window, on main at c9d57d2 plus this change:
bench.pyonkokiri-deckfrom the deck save, two runs of each:On this Mac native 4K costs about 0.7 ms of GPU time a frame over native 1440p, and the game holds 60 fps.
docs_patches.py --check,test_docs,test_patches,test_settingsandtest_launcher_settings.Not checked: handheld (the output stubs scale the handheld size too, but I haven't run it), a slower Mac, or the iPhone.
Screenshots
The same spot on the Kokiri Forest deck at render scale 1.0, 1.333 and 2.0. The 1.0 and 1.333 crops are shown at 3x and the 2.0 crop at 2x, so all three cover the same area at the same size:
Render scale 1.0 on the left and 1.333 on the right (crops shown at 2x):



Full frames at 1.0, 1.333 and 2.0:


Docs
python3 dm/tools/docs_symptoms.pywas run (the symptom index, unchanged)docs/agents/game-patches.mdis regenerated for the new sitesRelated
Both only lower the size. This PR raises it, up to native 4K, and leaves the lower range to those PRs. If #1903 lands first, its stubs and this one would need one combined
RENDER_SCALE.