Skip to content

Read each emulator's device identity instead of deriving it - #4

Merged
JoeGeC merged 2 commits into
mainfrom
fix/dolphin-gc-mapping
Sep 2, 2026
Merged

Read each emulator's device identity instead of deriving it#4
JoeGeC merged 2 commits into
mainfrom
fix/dolphin-gc-mapping

Conversation

@JoeGeC

@JoeGeC JoeGeC commented Sep 2, 2026

Copy link
Copy Markdown
Owner

Three faults in the emulator auto-setup, all found on an AYN Thor. The common cause: we were deriving the number each emulator uses to identify our virtual pads, instead of reading it.

Every emulator picks a different quantity, and none of them is the player number. Each rule below was read from that emulator's own source, not inferred.

Dolphin: wrong Device id

Dolphin's qualifier is Source/ID/Name, and the ID comes from InputDevice.getControllerNumber(). ControllerInterface::AddDevice prefers GetPreferredId(), which the Android backend fills from getControllerNumber(), falling back to a duplicate-name index only for non-gamepads:

std::optional<int> GetPreferredId() const override
{
  return m_controller_number != 0 ? std::make_optional(m_controller_number) : std::nullopt;
}

We wrote the pad's rank among our own virtual gamepads (rank + 1), which only coincides when nothing else is connected.

Eden: wrong port

Eden (yuzu lineage) numbers port by walking InputDevice.getDeviceIds() and counting every physical game controller it passes — a controller number already registered is skipped but still consumes a port:

deviceIds.forEach { deviceId ->
    InputDevice.getDevice(deviceId)?.apply {
        if (isPhysicalGameController(this)) {
            if (!gameControllerDeviceIds.contains(controllerNumber)) { ...port... }
            port++
        }
    }
}

We were ranking our pads among themselves, so any built-in controller shifts ours along unnoticed. This was invisible on devices where our pad happens to enumerate first.

Measured on the Thor

Exactly two devices pass Eden's isPhysicalGameController:

  Device 10: Odin Controller              Sources: KEYBOARD | GAMEPAD | JOYSTICK   ControllerNum: 1
  Device 15: Joy-Con Virtual Gamepad 1    Sources: KEYBOARD | GAMEPAD | JOYSTICK   ControllerNum: 3
we wrote actually expected
Dolphin id Android/1/… Android/3/… (controller number)
Eden port port:0 port:1 (Odin takes 0)

The Dolphin value matches the hand-corrected working config exactly. Any handheld with a built-in controller breaks the old assumption — the Thor, and the Odin 2 Portal a reporter is using.

Crossed sticks on dual Joy-Cons

gameCubeSticks(DUAL) routed the GameCube main stick from the right Joy-Con and the C-stick from the left. The Switch Pro and Nunchuk defaults already route left→left; GameCube was the outlier.

Structure

Both lookups now sit together in VirtualGamepadIdentity (renamed from VirtualGamepadPorts), each documented with the emulator rule it mirrors, so a future auto-mapping can't quietly go back to deriving a number. Dolphin's Wii Remote config addresses our own DSU slot (DSUClient/<slot>/Joycon2), so it has nothing to look up — audited, unchanged.

A player whose pad isn't enumerated is now skipped rather than handed a guessed id, since a wrong id binds to the wrong device or to none.

Verified

  • ./gradlew build :konsist:test green; DolphinGcpadConfigTest updated — the case that asserted the old rank behaviour now asserts the reported controller number, plus a new case covering the skip.
  • Device numbers above read off the Thor with dumpsys input and cross-checked against the hand-corrected GCPadNew.ini.
  • Not yet run end-to-end on device: verifying means overwriting the working hand-corrected config, so that check is still outstanding.

Note

Unrelated to #3 (stick calibration) and based on main, so the two can merge in either order.

🤖 Generated with Claude Code

JoeGeC and others added 2 commits September 2, 2026 19:11
Two faults in the GameCube auto-setup, both found on an AYN Thor:

Dolphin's Android device qualifier is Source/ID/Name, and the ID comes from
InputDevice.getControllerNumber() — Android's own gamepad enumeration counter
(ControllerInterface::AddDevice prefers GetPreferredId(), which the Android
backend fills from getControllerNumber, falling back to a duplicate-name index
only for non-gamepads). We wrote the pad's rank among our own virtual gamepads
instead, which only matches when nothing else is connected: on a handheld with
a built-in controller that number is already taken, so the section bound to the
wrong device or to none. On the Thor the built-in pad holds number 1 and ours
reports 3. It is now read from the live input-device list, alongside the port
lookup Eden already used, and a player whose pad isn't enumerated is skipped
rather than given a guessed id.

The dual-Joy-Con stick default also had the GameCube sticks crossed — main
stick driven by the right Joy-Con and C-stick by the left. The Switch Pro and
Nunchuk defaults already route left to left.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Eden numbers its `port` by walking InputDevice.getDeviceIds() and counting
every physical game controller it passes (InputHandler.getDevices), so a
built-in pad shifts ours along — a controller number already registered is
skipped but still consumes a port. We were ranking our own virtual pads among
themselves, which only agrees when nothing else is connected.

On the AYN Thor the built-in Odin Controller (device id 10) takes port 0 and
our pad (id 15) is port 1, but we wrote port 0 — the same fault just fixed for
Dolphin, and invisible on any device where our pad happens to enumerate first.

Both rules now live in VirtualGamepadIdentity next to each other, each read
from the emulator's own source: Dolphin wants getControllerNumber(), Eden wants
that walk order, and neither is the player number. Dolphin's Wii Remote config
addresses our own DSU slot, so it has nothing to look up.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@JoeGeC JoeGeC changed the title Fix Dolphin GameCube device id and dual-Joy-Con stick order Read each emulator's device identity instead of deriving it Sep 2, 2026
@JoeGeC
JoeGeC merged commit 46c9492 into main Sep 2, 2026
1 check passed
@JoeGeC
JoeGeC deleted the fix/dolphin-gc-mapping branch September 2, 2026 18:26
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.

1 participant