Skip to content

macOS: native Switch 2 controllers with automatic setup, rumble and calibrated motion - #1

Merged
jmonster merged 7 commits into
mainfrom
feature/native-switch2kit
Sep 18, 2026
Merged

jmonster merged 7 commits into
mainfrom
feature/native-switch2kit

Conversation

@jmonster

@jmonster jmonster commented Sep 17, 2026 •

Copy link
Copy Markdown
Owner

Controller support

Embed Switch2Kit directly in Cemu on macOS. No separate controller app, UDP bridge or system driver is required.

In Options → Input settings, use Find Switch 2 Controllers, then choose a GameCube or Pro controller beside the emulated controller selector. Cemu applies the Nintendo-labelled buttons, sticks, triggers and rumble automatically. Existing Wii U GamePad, Wii U Pro Controller and Classic Controller types are supported; an empty first slot defaults to GamePad.

  • Separate GameCube and Pro mappings, persistent physical-controller identity, player indicators and reconnect handling.
  • GameCube motor on/off rumble and Pro HD-rumble output, plus a half-second Test rumble button.
  • Replacing a populated slot asks first, saves a backup profile and rolls back on save failure. Hotplug never overwrites mappings. Duplicate assignments and active game-profile overrides are rejected before opening another controller handle, so rejected setup cannot interrupt another slot's rumble.
  • Complementary Joy-Con 2 mappings through Cemu's multiple-controller input path: add both halves to one slot with + → SDLController.
  • Calibrated gyro/accelerometer integration with motion-profile import, removal and status. Missing or stale motion is unavailable rather than fabricated.
  • Disconnect remains stopped until discovery is restarted. The settings-window event subscription retains only a shared notification flag, not the window pointer, so an in-flight device notification cannot access a destroyed window. UI refreshes remain on the main thread.

Build and try

Use macOS 15+, Xcode 26+/Swift 6.2+, and the dependencies in docs/Switch2Kit.md. Run bash scripts/build-switch2kit.sh --run in this checkout. The helper builds the pinned SDK, embeds the required libraries, signs the completed app ad hoc and opens Cemu. Vulkan remains enabled.

The backend is optional and off by default. Ordinary builds retain existing controller APIs and the deployment target. This uses the already-merged GameCube-rumble SDK revision used by Dolphin; no additional Switch2Kit PR is required.

Validation

Ready for code review. The final native and cross-platform build checks are still pending; wait for those checks before merging.

  • Current native workflow: the policy job passed, including all nine source-wiring checks and executable mapping, identity, session, rollback and notification-lifetime regressions with AddressSanitizer/UndefinedBehaviorSanitizer. The Apple-silicon application, Intel application and native SDK jobs are awaiting runners.
  • Current cross-platform build check is unfinished. The translation-template check passed.
  • Both native application builds, architecture/signature checks and exact-ZIP launch/normal-quit/relaunch tests passed on the preceding implementation. That run then failed an assertion which incorrectly assumed CMake's deployment-target cache entry was typed STRING. The target value was correctly 13.4 with type UNINITIALIZED. The corrected assertion checks the value. Current native builds must also include the subsequent setup and notification-lifetime fixes.
  • The pinned SDK's complete portable suite passed locally, including 82 Swift package tests and motor packet/session tests. All six real-SDL/Cemu host integration CTests passed, including the actual Cemu motion processor.
  • The new notification ownership tests passed locally and in the isolated review job. A separate local sanitizer check also exercised the actual EventService/Boost signal binding while releasing window ownership concurrently.

No test assertions have been weakened or checks disabled to obtain a pass. Nothing has been merged.

Hardware and scope

Physical Bluetooth reconnection, motor start/stop and Cemu gameplay still need a real Mac/controller test. Motion requires a measured calibration profile for the specific controller, not a test fixture. Ordinary buttons and rumble do not need a motion profile. Wiimote mappings remain manual, and a gamepad does not replace the GamePad touchscreen. Application artifacts are development builds, not notarized releases.

github-actions Bot and others added 6 commits September 17, 2026 21:39
… macOS

Embed the pinned controller SDK; add per-slot recommended mappings, persistent device identity, safe profile replacement and timed rumble testing. Preserve ordinary controller APIs and disabled builds. Add host, mapping and transaction regressions and a local build helper.
Check duplicate assignments, game-profile ownership and unsupported emulated types before opening the candidate SDL handle. A rejected temporary handle must not stop another slot's rumble or change its sensor policy. Add an ordering regression alongside the existing mapping, rollback and lifecycle checks.
@jmonster
jmonster marked this pull request as ready for review September 18, 2026 00:52
…down

Retain a shared coalescing flag in the event subscription instead of binding the window pointer. Callbacks already in flight can finish after disconnect without touching destroyed widgets; only the main-thread timer refreshes the UI. Add executable notification lifetime and reopened-window isolation tests alongside the source wiring regression.
@jmonster
jmonster merged commit a580909 into main Sep 18, 2026
12 checks passed
@jmonster
jmonster deleted the feature/native-switch2kit branch September 18, 2026 04:45
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