Skip to content

Calibrate Dolphin's sticks so they stop at the GameCube gate - #32

Merged
JoeGeC merged 2 commits into
JoeGeC:mainfrom
thisishuey:add-dolphin-stick-calibration
Oct 15, 2026
Merged

JoeGeC merged 2 commits into
JoeGeC:mainfrom
thisishuey:add-dolphin-stick-calibration

Conversation

@thisishuey

@thisishuey thisishuey commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

Dolphin passes an uncalibrated stick straight through, so a full tilt reaches GameCube ±127, where a real pad's gate stops near ±101 on the main stick and ±92 on the C-stick. Every push lands about a quarter further than on hardware, so walking slowly or aiming finely is hard: a light push already runs, and a scope overshoots. Dolphin for Android has no Calibrate button, and nothing else sets it.

Dolphin setup now writes Calibration = 100.00, a full circle, for each stick it binds. Dolphin then maps the stick's rim onto its default Gate Size octagon: 79.37% for the main stick and 72.21% for the C-stick, values Dolphin averaged from genuine controllers. A full push still reaches the real gate. Sources are Dolphin's GCPadEmu.h and StickGate.cpp, and Dolphin PR #8963.

Setup keeps a Calibration value a section already has, so a player who calibrated by hand keeps it across Set up. It still leaves a Pro Controller player's section to the player: there it only adds the two calibration keys, keeping the bindings they made, and only to a section that already exists. The README gains a troubleshooting row so anyone who set up before this knows to run Set up again.

Tested on a Retroid Pocket Nova (Android 13) with NSO GameCube controllers, using the GameCube controller support from #30: walking and scope aiming feel like an original controller. Joy-Con 2 and Pro Controllers are untested.

If #30 merges first, the Pro-only step should skip GameCube players, since setup writes their whole section: it.hasPro && !it.hasGameCube. I can update whichever branch lands second.

@JoeGeC JoeGeC left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this, and for the sources. I checked the maths against Dolphin's code: with no Calibration key, Dolphin treats the stick as already stopping at the gate, so a full push goes straight through to ±127. Setting 100.00 scales it down to roughly ±101 for the main stick and ±92 for the C-stick, as you said. Our stick handling scales each axis to full range, so a full circle is the right calibration for the Joy-Cons too. I'd like to merge this, with a few changes:

1. Drop the Calibrate sticks switch. As far as I can tell, a full circle is the right calibration for any round stick: Dolphin maps it onto the GameCube gate, which is what a real pad does. I've tested it with Joy-Cons on an AYN Thor and it feels right, so I don't think the switch is needed. It's about half the diff (repository, DataStore key, use case, ViewModel, composable, strings, wiring), and dropping it fixes point 2 as well. Could Dolphin setup just always write the calibration?

2. Turning calibration off doesn't undo it for Pro Controllers. Setup rewrites a Joy-Con player's whole section, so the keys disappear when the switch is off. calibrateHandMapped only ever adds keys, though, so a Pro section stays calibrated, and the README line "Run Set up again after changing it" isn't true there. This goes away if the switch goes.

3. Don't overwrite an existing calibration. If a Pro player's section already has a Calibration value, setup replaces it. A quick IniEditor.valueOf check before writing would leave a value the player set alone.

4. Move FULL_CIRCLE_CALIBRATION up. It currently sits between the "D-Pad target reads the hat switch" comment and HAT_NAMES, so that comment now labels the wrong line. Putting it next to STANDARD_CONTROLLER would fix that.

5. Tests. "a pro controller with no section of its own gets none" checks the same thing as the existing "pro controllers are skipped", so I'd drop one of them. If the switch stays, please add a test for a Pro section with calibration off.

6. Smaller things. If the switch is removed, the README settings entry and the line added to architecture.md can go too. Otherwise, please re-wrap that architecture.md line to match the ones around it.

@thisishuey
thisishuey force-pushed the add-dolphin-stick-calibration branch 2 times, most recently from 4d2010e to dd951c2 Compare October 13, 2026 19:07
@thisishuey

Copy link
Copy Markdown
Contributor Author

Thanks for the review, and for checking the math against Dolphin's code!

Everything is addressed in 4d2010e, and the branch is rebased onto main.

Switch (1, 2): gone, along with its setting, use case and strings, so setup always calibrates. That also settles the Pro sections that turning it off couldn't undo.

Existing calibration (3): setup keeps a Calibration value the section already has. I applied it to the Joy-Con sections setup writes as well as Pro ones, so a hand calibration survives Set up everywhere; one calibrationFor helper covers both paths.

Constant (4): FULL_CIRCLE_CALIBRATION now sits next to STANDARD_CONTROLLER, so the hat-switch comment describes its own line again.

Tests (5): dropped "a pro controller with no section of its own gets none" and the switch-off test, and added one for a kept calibration in a Joy-Con section and one in a Pro section.

Docs (6): the README settings entry and the architecture.md line are gone. I kept a shorter troubleshooting row, without the switch, so anyone who set up before this knows to run Set up again. Happy to drop it if you'd rather.

Unit tests and Konsist pass locally for every module but :app, which I couldn't configure without the NDK, so CI covers that one.

@thisishuey
thisishuey requested a review from JoeGeC October 13, 2026 23:51

@JoeGeC JoeGeC left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, looks good! Just need to fix the conflict then we can merge it 👍

thisishuey and others added 2 commits October 14, 2026 20:09
Dolphin passes an uncalibrated stick straight through, so a full tilt
reaches GameCube ±127, where a real pad's gate stops near ±101 on the
main stick and ±92 on the C-stick. Every push lands about a quarter
further than on hardware, so walking slowly or aiming finely is hard: a
light push already runs, and a scope overshoots. Dolphin for Android has
no Calibrate button, and nothing else sets it.

Dolphin setup now writes `Calibration = 100.00`, a full circle, for each
stick it binds. Dolphin then maps the stick's rim onto its default Gate
Size octagon: 79.37% for the main stick and 72.21% for the C-stick,
values Dolphin averaged from genuine controllers. A full push still
reaches the real gate. Sources are Dolphin's GCPadEmu.h and
StickGate.cpp, and Dolphin PR #8963.

Setup still leaves a Pro Controller player's section to the player. It
only adds the two calibration keys there, keeping the bindings they
made, and only to a section that already exists.

A new Dolphin section in Settings has a Calibrate sticks switch. It's on
by default, for anyone who prefers the old full-range feel, and takes
effect at the next Set up. The README covers the setting and adds a
troubleshooting row.

Tested on a Retroid Pocket Nova (Android 13) with NSO GameCube
controllers, using the GameCube controller support from JoeGeC#30: walking and
scope aiming feel like an original controller. Joy-Con 2 and Pro
Controllers are untested.

The hand-mapped step skips a GameCube controller player, since setup
writes their whole section.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review feedback: the Calibrate sticks switch only served someone who
prefers the twitchier full-range feel, and turning it off never undid the
keys setup had added to a Pro Controller's section. Setup now always
calibrates, and the switch, its setting and its use case are gone.

Setup keeps a Calibration the section already has instead of overwriting
it, in a Joy-Con section it writes as well as a Pro Controller's. A
player who calibrated by hand keeps it across Set up.

The full-circle constant moves next to STANDARD_CONTROLLER, out from
under the hat-switch comment. A duplicate Pro Controller test goes, and
two tests cover a kept calibration. The README drops the settings entry
and keeps the troubleshooting row.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@thisishuey
thisishuey force-pushed the add-dolphin-stick-calibration branch from dd951c2 to 03cda1a Compare October 14, 2026 20:12
@thisishuey

thisishuey commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor Author

Thanks! Rebased onto main with #30 in, so the conflict is gone.

#30 counts a GameCube controller as a Pro-type controller, so the step that adds calibration to a hand-mapped Pro section now uses #30's isSetUpByApp and leaves GameCube players to the section setup writes for them. A new test covers a GameCube player getting each stick's calibration exactly once. Everything else is unchanged, and unit tests and Konsist pass locally.

@thisishuey
thisishuey requested a review from JoeGeC October 14, 2026 21:15
@JoeGeC
JoeGeC merged commit 55c8fa9 into JoeGeC:main Oct 15, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants