Repository navigation
Switch 2 controllers: a Controller menu and panel in the game window test a stick's drift and save its calibration in the controller - #2129
Open
UserDerezzed wants to merge 3 commits into
Conversation
UserDerezzed
marked this pull request as ready for review
November 10, 2026 09:39
…test a stick's drift and save its calibration in the controller The game window's menu bar gets a Controller menu between Cheats and Window: Show Controller Window (Cmd-Shift-P) and a line for each connected Switch 2 controller. The panel shows a stick live, with markers where it comes to rest after each release and a tally of releases inside and past the dead zone. It has a dead zone slider that changes the game's dead zone at once and keeps it for the next launch (launcher.DM_SW2_DEADZONE), and a guided calibration (let go, edges, review and save) that writes the stick's centre and travel into the controller as its user calibration, as the console's calibration does. While the panel is open the game gets no Switch 2 input. The write (switch2_ops_apple.m) backs the 4 KB user calibration sector up to a file first, erases, checks it reads blank, writes, reads back, and puts the backup back on a mismatch. Only the first stick slot is saved (a Pro Controller 2's left stick, a Joy-Con 2's stick): where the second slot's user calibration lives is not settled. A saved calibration applies to the game without a restart. DM_SW2_CALIBRATE=1 writes the released stick's rest at connect without the panel; DM_CONTROLLER_WINDOW=1 opens the panel at launch.
… slots (0x1FC040, 0x1FC060, 0x1FC080) carry the marker, and their bytes (read only), to settle where the second stick's lives
…ted and saved too, its user calibration read and written at 0x1FC080 as SDL and Linux read it (was read at 0x1FC062)
UserDerezzed
force-pushed
the
sw2-stick-calibration-pr
branch
from
November 14, 2026 09:11
daa1fc6 to
55f5332
Compare
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
Switch 2 controllers drift, and a Pro Controller 2's left stick drifting makes Link creep in Ocarina of Time (
0400486024DEC000). The host already raises the dead zone (DM_SW2_DEADZONE), but that only hides drift. On a console, the fix is to recalibrate the stick in System Settings. Without a console, there was no way to do that.This adds a Controller menu to the game window's menu bar, between Cheats and Window:
launcher.DM_SW2_DEADZONEsetting as the launcher's Stick dead zone row.The write (
dm/host/switch2_ops_apple.m, behind a smallS2Commanderprotocol so it runs against a fake controller int_switch2_ops):Writes below 0x1F5000 are never sent. A memory read is taken only when its reply carries that read's length (byte 8) and address (bytes 12-15), so a late reply can't stand in for another read's data. A Pro Controller 2 doesn't echo the request's
0x7Eat byte 9, so that byte isn't compared. Quitting (⌘Q, the Home prompt, closing the window) waits for a running save, up to 30 s.DM_SW2_CALIBRATE=1writes the released stick's rest at connect without the panel.DM_CONTROLLER_WINDOW=1opens the panel at launch.Both sticks of a Pro Controller 2 can be saved: the left at 0x1FC040, the right at 0x1FC080. At each connection the log shows which stick blocks (0x1FC040, 0x1FC060, 0x1FC080) carry the marker, with their bytes. This only reads.
Open questions:
SDL_hidapi_switch2.c) and Linux (hid-nintendo.c) read it. Main's 0x1FC062 came with no source. No controller calibrated on a console has been seen yet to confirm either. The one tested here had never been calibrated on a console: its whole 4 KB block was 0xFF before the first save. A dump from a controller calibrated on a Switch 2 would settle it.Checked
make -C dm/host/tests GAME=0400486024DEC000 build/t_switch2 build/t_switch2_ops: 173 and 97 checks pass. They cover the payloads, the reply check, release markers, reach and recentre, and the whole save sequence for both stick slots against a fake controller, including late replies, failed erases and restores.make -C dm/host GAME=0400486024DEC000 dmhostbuilds.env_switches.py --checkreports only the three switches it already reports on main.0400486024DEC000, v131072) in the Mac app with a Pro Controller 2.DM_SW2_CALIBRATE=1also wrote and read back.command 0x02 timed outreads, which the retries absorb.Docs
docs/settings.md(Controller menu and panel, Stick dead zone),docs/reference/services.md,docs/playing.md,docs/env_switches.tsv,dm/tools/impact_map.tsv