Repository navigation
Support the NSO GameCube controller - #30
Open
thisishuey wants to merge 1 commit into
Open
thisishuey wants to merge 1 commit into
thisishuey wants to merge 1 commit into
Conversation
The NSO GameCube controller advertises product ID 0x2073, which the scanner didn't know. It connected as an unknown side, and a lone unknown controller is treated as a sideways Joy-Con. So its stick and D-pad were turned 90 degrees, its C-stick was never decoded, L + R didn't assign it, and it played as whichever Joy-Con the first button pressed suggested. The scanner now names a ControllerModel from the product ID. The GameCube controller reports in the Pro Controller's layout, so it's parsed and assigned as one: one body, both sticks. It shares nothing else with the Pro. For button mapping it's a body of its own, beside a pair and a lone Joy-Con, with its own layouts and saved bindings. Its default puts Z on its Z button (reported as ZR) and the triggers on L/R. The mapping editor offers only the buttons it has, with ZR shown as Z. Dolphin setup configures a GameCube player and still skips Pro players, as before. Joy-Con pairs and Pro Controllers keep their layouts exactly as they were. Each controller card now has a Controller type menu: Auto, Pro Controller, Left or Right Joy-Con. This covers any controller whose advertisement names no type or the wrong one. The choice is stored per BLE address, which captures show is a fixed public address, so it applies again on reconnect. On a connected controller it takes effect at once: the parser reads the new side's sticks, and stick calibration starts over. A controller assigned to a player is unassigned first, since its slot was checked against the old type. Analog L/R now reach Dolphin. The controller reports trigger travel at 0x3C/0x3D. TriggerCalibrator maps it from the factory zero (SPI 0x013140) to the first stop, where analog travel ends, and drives the virtual gamepad's trigger bytes with it. Dolphin setup binds L-Analog and R-Analog to those axes and keeps the click at the second stop on L/R. Every other controller keeps ZL/ZR on the trigger bytes. On this controller ZL and Z also move off BUTTON_L2/R2 and onto the stick clicks, which it doesn't have. On a Retroid Pocket Nova those keys followed the trigger axes, so pulling R pressed Z and Z itself did nothing. With the move, both work. At connect it also reads its factory stick calibration (0x0130A8 for the main stick, 0x0130E8 for the C-stick, decoded as the Linux and SDL Switch 2 drivers do), so its sticks start centred with their full range. Learning still applies on top, and takes over when the flash is unset or implausible. Only the GameCube controller's values have been checked against its sticks, so Joy-Con 2 and Pro Controllers aren't read and keep learning theirs. Tested on a Retroid Pocket Nova (Android 13), with three GameCube controllers connected at once as players 1–3 in Dolphin. Recognition, L + R assign, both sticks, the D-pad, every button, analog L/R with a separate click, and the type menu all behave. Packet captures from the three controllers back the offsets and calibration values in protocol.md. Four controllers and Android 14+ are untested. Rumble is left out: the app has no rumble path yet. Closes JoeGeC#27 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
The NSO GameCube controller advertises product ID 0x2073, which the scanner didn't know. It connected as an unknown side, and a lone unknown controller is treated as a sideways Joy-Con. So its stick and D-pad were turned 90 degrees, its C-stick was never decoded, L + R didn't assign it, and it played as whichever Joy-Con the first button pressed suggested.
The scanner now names a ControllerModel from the product ID. The GameCube controller reports in the Pro Controller's layout, so it's parsed and assigned as one: one body, both sticks.
It shares nothing else with the Pro. For button mapping it's a body of its own, beside a pair and a lone Joy-Con, with its own layouts and saved bindings. Its default puts Z on its Z button (reported as ZR) and the triggers on L/R. The mapping editor offers only the buttons it has, with ZR shown as Z. Dolphin setup configures a GameCube player and still skips Pro players, as before. Joy-Con pairs and Pro Controllers keep their layouts exactly as they were.
Each controller card now has a Controller type menu: Auto, Pro Controller, Left or Right Joy-Con. This covers any controller whose advertisement names no type or the wrong one. The choice is stored per BLE address, which captures show is a fixed public address, so it applies again on reconnect. On a connected controller it takes effect at once: the parser reads the new side's sticks, and stick calibration starts over. A controller assigned to a player is unassigned first, since its slot was checked against the old type.
Analog L/R now reach Dolphin. The controller reports trigger travel at 0x3C/0x3D. TriggerCalibrator maps it from the factory zero (SPI 0x013140) to the first stop, where analog travel ends, and drives the virtual gamepad's trigger bytes with it. Dolphin setup binds L-Analog and R-Analog to those axes and keeps the click at the second stop on L/R. Every other controller keeps ZL/ZR on the trigger bytes.
On this controller ZL and Z also move off BUTTON_L2/R2 and onto the stick clicks, which it doesn't have. On a Retroid Pocket Nova those keys followed the trigger axes, so pulling R pressed Z and Z itself did nothing. With the move, both work.
At connect it also reads its factory stick calibration (0x0130A8 for the main stick, 0x0130E8 for the C-stick, decoded as the Linux and SDL Switch 2 drivers do), so its sticks start centred with their full range. Learning still applies on top, and takes over when the flash is unset or implausible. Only the GameCube controller's values have been checked against its sticks, so Joy-Con 2 and Pro Controllers aren't read and keep learning theirs.
Tested on a Retroid Pocket Nova (Android 13), with three GameCube controllers connected at once as players 1–3 in Dolphin. Recognition, L + R assign, both sticks, the D-pad, every button, analog L/R with a separate click, and the type menu all behave. Packet captures from the three controllers back the offsets and calibration values in protocol.md. Four controllers and Android 14+ are untested.
Rumble is left out: the app has no rumble path yet.
Closes #27