Project Mjölnir: Part 3 - Controller Profiles and Vibration Rework
This is the final part of a multipart rewrite to yuzu's HID (Human Interface Device) frontend and backend implementations.
Wrapping this up, we bring you the final part of Project Mjölnir with 2 big features - Controller Profiles and Vibration Rework, both requiring many other miscellaneous improvements to all aspects of HID in the frontend and backend.
Controller Profiles
The placeholder since Part 1 of the input rewrite is no more! Controller Profiles are finally here!

Due to the way input is handled in yuzu, we had to create a profile system that adapts the existing system to ensure maximum compatibility. As a result, controller profiles are formatted similarly to the [Controls]
section of the qt-config.ini
file.
Controller Profiles currently save the following data:
- Emulated Controller (Only Left and Right Joycons)
- Real Input Device used (engine/guid/port)
- All buttons
- All axes
- All vibration devices (auto-generated by yuzu)
- All motion devices (via the Motion 0 and 1 buttons)
Everything else, such as the docked/undocked state, vibration and motion enabled, per player vibration (enabled and strength modifier), player connection status are NOT saved the input profile.
Controller profiles are saved under config/input
in the yuzu AppData directory or user directory for portable installations.
Profiles are loaded by clicking on the dropdown/combobox and selecting the desired profile as shown below.

Vibration Rework
After the initial work on rumble done by german77, there were a few games where rumble didn't work, and the implementation was incomplete, not supporting vibrations beyond the first connected player.
The Nintendo Switch has the capability to 1. Distinguish between left and right vibration devices or motors and 2. Vibrate them independently of one another. This poses a challenge for libraries like SDL, which do not expose these capabilities. Furthermore, sending these vibrations in quick succession would result into performance issues for some controllers, as evidenced by the various reports using the Xbox controllers.
In order to solve these issues, we had to look into how HID encodes the vibration device handle - a unique handle used to distinguish between different controllers.
After decoding the device handle, it consists of the following:
A u8 npad_type, a u8 npad_id, and finally, a u8 device_index
These are all the information needed to vibrate a vibration device/motor at the correct location.
Armed with this knowledge, we can implement more vibration related HID commands such as InitializeVibrationDevice
, GetVibrationDeviceInfo
and IsVibrationDeviceMounted
, and properly implement commands such as SendVibrationValue
, SendVibrationValues
and GetVibrationValue
.
By implementing these commands, we have fixed all the games that previously had issues with rumble or exhibit no rumble at all, such as Hollow Knight, Fire Emblem Three Houses, 1-2 Switch, Xenoblade Chronicles and many more.
This has also allowed us to implement per player vibrations - allowing for vibrations to be separated per player and per vibration device. This means that if you have single joycons connected via programs such as BetterJoy, you can select the "Any" input device, map both joycons to the left and right buttons/analogs/motions respectively, and both joycons will be able to vibrate! The process of "mapping" a vibration device is done automatically so there is no setup required!
We have also allowed for enabling/disabling vibrations per player, and controlling the vibration strengths for each, allowing for fine tuning of rumble to meet your needs.
Performance issues are also resolved by adding a few heuristics to reduce vibration state changes, and a toggle to enable/disable accurate vibrations, This toggle reduces the effective vibration rate - the rate at which vibrations are sent. By default this is set to disabled.

Controllers that do not support vibration are automatically detected and will have their rumble capabilities disabled in the backend. Resulting in no vibrations sent to SDL/GCAdapter.
Keep in mind that all these changes to vibration required a significant overhaul to the rumble system. In order for vibrations to work, you must open the Configure
window and click on Ok
once to allow the vibration devices to be "mapped" properly.
Misc. changes
There are many other improvements that streamlines the user experience, some of which are detailed below:
- Cleaned up many UI element sizes between all three themes - now button/combobox/spinbox sizes and spacing are more consistent
- The controller applet now auto-accepts a valid singleplayer configuration. Multiplayer configurations will still have to be manually accepted.
- Mouse clicks now register (only if touch is disabled under
Controls -> Advanced
)
- The Player 1 controller is automatically connected on boot if none are connected
- Testing period for motion is reduced to 5 seconds from 8
- Input devices no longer revert to "Any" and selecting an input device would properly block inputs from other input devices
- The "Defaults" button now restores the automapped bindings for the selected input device
- Rewrite and correct all input parameters in all HID service commands
- Per game configs are moved to
config/custom
- Return of "Map Analog Stick" for manual mapping - fixes analog stick mapping for controllers without SDL_GameController bindings
- The input config in the controller applet is replaced by a button to create input profiles - this will be used in a future PR
This fixes #3743, fixes #4738, fixes #4800, fixes #4818 and fixes #4928
early-access-merge