Turns a PS5 DualSense (USB or Bluetooth, DualSense Edge too) into a virtual Xbox 360 controller, and hides the real DualSense from every other app while running — so games only ever see one pad (no double input). On exit it restores everything automatically.
Under the hood it reads the DualSense raw HID reports itself and drives two standard signed kernel drivers (the same foundation DS4Windows uses, because virtual pads and device hiding are impossible from pure user mode):
- ViGEmBus — hosts the virtual Xbox 360 pad
- HidHide — cloaks the physical DualSense (X360EMU talks straight to the driver; the HidHide GUI does not need to run)
- Windows 10/11 x64, .NET 8 runtime
- Drivers (one-time install, reboot after):
winget install Nefarius.ViGEmBus winget install Nefarius.HidHide
dotnet build -c Release
.\bin\Release\net8.0-windows\X360EMU.exe
It runs as a system-tray app — no console, no taskbar entry, just a green icon in the tray. Double-click the icon for the status/log window (closing it hides it again), right-click → Exit to stop and un-hide the DualSense. The tray tooltip shows transport + battery. A second launch just tells you it's already running.
| Option | Effect |
|---|---|
| (none) | Tray mode: emulate + hide. Restores on exit. |
--no-hide |
Emulate only; DualSense stays visible (double input possible). |
--unhide |
Repair: strip every DualSense entry from HidHide and exit. Use after a crash/kill left the pad invisible. |
--status |
Show driver, HidHide and controller state (prints to the terminal, or a dialog if launched from Explorer). |
--startup on / off |
Launch automatically at Windows sign-in (per-user Run key, no admin). Also togglable via the tray menu: Start with Windows. |
--seconds N |
Auto-exit after N seconds (testing). |
Crash safety: every HidHide change is journaled to %LOCALAPPDATA%\X360EMU\hidhide-state.json. If the process is killed without cleanup, the next start (or --unhide) restores visibility automatically.
- Parses DualSense input reports natively: USB report
0x01, Bluetooth full report0x31(switched on automatically via feature report0x05), and the simplified BT fallback. - Feeds a ViGEm virtual X360 pad; games receive genuine XInput (
VID_045E&PID_028E). - Rumble passthrough: XInput vibration from the game is translated to DualSense motors (Bluetooth output reports are CRC32-signed as the firmware requires).
- Lightbar: blue while active, red when battery ≤ 15%; player-1 LED lit. Battery % shown in console.
- Hides only the exact DualSense device instance, allow-lists only itself, and undoes only its own changes on exit — an existing HidHide setup (e.g. DS4Windows entries) is left untouched.
- Hot-plug: unplug/re-plug or switch USB↔BT while running; it reconnects and re-hides.
| DualSense | X360 | DualSense | X360 | |
|---|---|---|---|---|
| Cross | A | L1 / R1 | LB / RB | |
| Circle | B | L2 / R2 | Triggers (analog) | |
| Square | X | L3 / R3 | LS / RS click | |
| Triangle | Y | Options | Start | |
| D-Pad | D-Pad | Create / Touchpad click | Back | |
| Sticks | Sticks | PS | Guide |
- Controller invisible after a crash → run
X360EMU.exe --unhide. - HidHide config fails → try once as administrator (normally not needed).
- Steam still shows the DualSense → restart Steam; it caches devices opened before hiding. Also disable Steam Input's PlayStation support if you use it, or Steam will double-translate the virtual X360 pad.
- Don't run together with DS4Windows/DSX — two mappers on one pad = double virtual pads.
- Quick check: open
joy.cplwhile running — you should see only "Controller (XBOX 360 For Windows)".