Skip to content

Latest commit

History

93 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

joycon2cpp

A C++ executable that makes Switch 2 controllers into working PC controllers.


UI made with ImGui

DISCLAIMER

This project is Windows-only, primarily because the ViGEmBus Driver (used for virtual controller output) is exclusive to Windows.
You're free to make your own macOS/Linux fork if you want.

DEPENDENCIES


Usage Guide

  • Download the latest release's .exe file (or, optionally, build from source as detailed below) and open it
  • Use the UI to add players, pick their controllers and set everything up (settings are explained in detail below)
  • Follow the onscreen pairing instructions and pair the correct controllers for each player
  • When completed, you will have WGInput controllers ready for every player to use. (they show up as Sony DualShock4 Gamepad)
  • Click the chat button to toggle mouse functions,3 adjustable modes for the mouse pointer.

Note: Bit layouts differ slightly between left and right Joy-Cons, so correct side pairing is important.


Rumble Instructions

  • When picking the motor in your emulator, pick the corresponding side depending on controller. (eg. Motor L for left joycon)
  • If playing with Dual Joycons or a ProCon2 controller, all rumble data gets replicated to all motors, so picking any of them works fine.
  • Rumble is not supported for the NSOGC Controller
  • (pro controller rumble is untested! let me know if it doesnt work!!!)

Building from source

If you want to build the project yourself, follow these instructions (Windows + Visual Studio):

Requirements

Make sure the following are installed via Visual Studio Installer:

Visual Studio 2022 or newer Workload: Desktop development with C++ Component: Windows 10 or 11 SDK Component: MSVC v14.x

(Optional but useful) C++/WinRT

  1. Open the x64 Native Tools Command Prompt for VS (whatever your version is)

  2. Go into the project's root directory and make a build folder:

    cd (path to the main directory of the project here)
    mkdir build
    cd build
    
  3. Generate Visual Studio project files with CMake:

    cmake .. -G "Visual Studio 17 2022" -A x64
  4. Build the project in Release mode:

    cmake --build . --config Release
  5. The compiled executable will be located in:

    build\Release\testapp.exe
    

Other

In-App Settings This section details what each setting does.

CONTROLLER SETTINGS (the settings on each player's controller)

  • Side (Single Joycons) Details the side this joycon is. (L/R)

  • Orientation (Single Joycons) Details what orientation this joycon is. (Upright/Sideways)

  • Gyro Source (Dual Joycons)

Controls what joycon's gyro/accel data to use.

  • Gyro Output

This setting controls where gyro/accel data will be fed to.

DS4 Raw: Feeds the data directly into the virtual DS4 controller using DS4 axis conventions.

DS4 Switch Emu: Same as DS4 Raw, but remaps gyro axes to match Switch controller conventions. Use this if motion controls feel wrong or inverted in your emulator.

DSU UDP: Sends gyro/accel data over the DSU protocol to a local DSU client. Uses the standard DSU server address (127.0.0.1, port 26760), compatible with Dolphin, Cemu, and other DSU-supporting emulators.

  • Mouse (Singular Joycons) Toggles the mouse input.
  • DPAD (Left Joycon) Toggles whether the left joycon's buttons map to DPAD or ABXY.
  • Remap (Sideways Singular Joycons) Toggles whether the buttons get rotated 90 degrees for sideways use (e.g X becomes A, Y becomes X)

GLOBAL SETTINGS (found under the Settings dropdown menu)

Swap A/B and X/Y buttons - changes the layout to Nintendo ABXY instead of DualShock4

Joy-Con 2 BLE Notification Layout

This document outlines some findings related to Joy-Con 2 BLE input behavior. If you're developing or reverse-engineering Joy-Con 2, Pro Controller 2, or other supported Nintendo controllers over BLE, this may be useful.

Behavior Quirks

A notable quirk of these controllers is that if you attempt to connect or pair them repeatedly in a short time span, they may stop responding or fail to connect entirely for several minutes. This appears to be a controller-level cooldown behavior rather than an OS/BLE stack issue.

If your controller stops connecting:
Wait a few minutes before trying again. It should recover on its own.

BLE Notification (with IMU enabled, Left Joy-Con)

Here’s an example notification received from a Joy-Con 2 via BLE, with the IMU command sent. (Pro Controller 2 and GC Controller notifications follow similar layouts but may shift certain fields.)

08670000000000e0ff0ffff77f23287a0000000000000000000000000000005f0e007907000000000001ce7b52010500beffb501ee0ffeff04000200000000

Field Breakdown (based on known Joy-Con 2 layout)

huge thanks to @german77 for providing me with the notification layout below!!

OffsetSizeValueComment
0x000x4Packet IDSequence or timestamp
0x040x4ButtonsButton state bitmap
0x080x3Left Stick12-bit X/Y packed
0x0B0x3Right Stick12-bit X/Y packed
0x0E0x2Mouse X
0x100x2Mouse Y
0x120x2Mouse UnkPossibly extra motion data
0x140x2Mouse DistanceDistance to IR/motion surface
0x160x2Magnetometer X
0x180x2Magnetometer Y
0x1A0x2Magnetometer Z
0x1C0x2Battery Voltage1000 = 1V
0x1E0x2Battery Current100 = 1mA
0x200xEReservedUndocumented region
0x2E0x2Temperature25°C + raw / 127
0x300x2Accel X4096 = 1G
0x320x2Accel Y
0x340x2Accel Z
0x360x2Gyro X48000 = 360°/s
0x380x2Gyro Y
0x3A0x2Gyro Z
0x3C0x1Analog Trigger L
0x3D0x1Analog Trigger R

🧪 Field Example Breakdown

OffsetSizeFieldRaw ValueInterpreted
0x004Packet ID08 67 00 000x0000670826376
0x044Buttons00 00 00 00No buttons pressed
0x083Left Sticke0 ff 0fX = 0x0FF0 = 4080, Y = 0x0FE0 = 4064
0x0B3Right Stickff f7 7fGarbage on Left Joy-Con
0x2E2Temperature5f 0e0x0E5F = 3679 → ~54°C
0x302Accel X00 790x7900 = 30976
0x322Accel Y07 000x0007 = 7
0x342Accel Z00 000
0x362Gyro X01 ce0xCE01 = 52737
0x382Gyro Y7b 520x527B = 21115
0x3A2Gyro Z01 050x0501 = 1281

📘 Notes

  • Left Joy-Con does not use Right Stick, so data at 0x0B–0x0D is typically junk.
  • Stick values use 12-bit X/Y packed across 3 bytes:
    • X = upper 12 bits of first 1.5 bytes
    • Y = lower 12 bits of next 1.5 bytes
  • Accel/Gyro fields are signed 16-bit:
    • Accelerometer: 4096 = 1G
    • Gyroscope: 48000 = 360°/s
  • Temperature:
    25°C + (raw / 127)
    25 + (3679 / 127) ≈ 54°C
  • Battery voltage:
    Reported as millivolts. 3000 = 3.0V. If 0x0000, likely unavailable at that time.
Latency Diagnostics

The test app can write an internal latency CSV while you compare update policies:

.\testapp.exe--latency-test --update-policy low --latency-csv low.csv
.\testapp.exe--latency-test --update-policy balanced --latency-csv balanced.csv
.\testapp.exe--latency-test --update-policy legacy --latency-csv legacy.csv

Policies:

  • low / LowLatency: send a ViGEm update for each BLE notification.
  • balanced / Balanced120Hz: limit output to about 120 Hz.
  • legacy / Legacy60Hz: limit output to about 60 Hz for comparison.

The CSV columns are:

mode,controller_type,event_index,ble_delta_ms,buffer_age_left_ms,buffer_age_right_ms,decode_to_vigem_us,total_pipeline_us

For a repeatable manual comparison, run each policy with the same controller, keep it still for 10 seconds, then press one button 30 times at a steady rhythm. Repeat for Single Joy-Con, Dual Joy-Con, and Pro Controller. For perceived end-to-end latency, record the physical controller and gamepad-tester.com or Steam Input at 240 fps, count frames between the visible press and on-screen response, and convert with latency_ms = frames / fps * 1000.

About

repo for the joycon2cpp syncer script

Resources

Stars

139 stars

Watchers

10 watching

Forks

Releases

Packages

Contributors

Languages