ViGEm Virtual Controller - AL2009man/JoyShockMapper GitHub Wiki

JoyShockMapper can create a virtual xbox or DS4 controller thanks to Nefarius' ViGEm Bus and ViGEm Client softwares. The former needs to be installed by the user before the latter can be used. Once installed, you can set which virtual device you desire to create for each connected device using the command VIRTUAL_CONTROLLER = XBOX or VIRTUAL_CONTROLLER = DS4. The default value is NONE, which is no virtual controller at all. Rumble will then work on DS4 controllers, but obviously support is game dependant. Using virtual controllers is most likely to work well only if whitelisting is active (HIDGuardian/HIDCerberus), in order to hide the original controller entry from the game and only expose the virtual one. Funny thing to note is that hiding DS4s with HIDGuardian will also hide the virtual DS4 from ViGEm, since Windows cannot tell the virtual controller form the physical one.

Xbox bindings

If you have set the virtual controller to the xbox scheme, then the following becomes available to you:

  • New digital bindings
X_A, X_B, X_X, X_Y : The xbox face button diamond
X_LB, X_RB : The xbox bumper buttons
X_LS, X_RS : The xbox stick click buttons
X_BACK, X_START, X_GUIDE : The xbox control buttons
X_UP, X_DOWN, X_LEFT, X_RIGHT : The xbox dpad directions
X_LT, X_RT : Digital trigger bindings
# There is no CAPTURE / SHARE (Series X) button binding yet in ViGEm
  • New stick mode available
LEFT_STICK_MODE = LEFT_STICK
RIGHT_STICK_MODE = RIGHT_STICK

While these map very simply from your real sticks to the virtual sticks, there are other new stick modes available for giving finer control over a single axis:

LEFT_ANGLE_TO_X
LEFT_ANGLE_TO_Y
RIGHT_ANGLE_TO_X
RIGHT_ANGLE_TO_Y

These will take the stick's angle into account for inputs that are normally only in one axis. For example, steering a car: instead of just moving the left stick left and right for adjusting your steering, rotating it around the edge of the stick will give you more precision and finer control over how hard you're steering. Set up the relevant UNDEADZONEs and UNPOWER for best effect.

These stick modes have inner and outer deadzones, set in degrees:

ANGLE_TO_AXIS_DEADZONE_INNER = 0
ANGLE_TO_AXIS_DEADZONE_OUTER = 10

There's also:

LEFT_WIND_X
RIGHT_WIND_X

These also use the angle of the stick to control the virtual stick in a single axis, but these are relative instead of absolute, and can use a much wider range. This means pointing the stick in a direction doesn't really do anything, but rotating the stick does, letting you wind the stick left or right to adjust the stick position left or right. When you release the stick the virtual stick will quickly pull back to its neutral position. Here are the relevant options:

  • WIND_STICK_RANGE (default 900.0°) - This is the total range of winding motion available on the stick. It's from full-left to full-right, but the "neutral" position is in the middle. So the default of 900° means you can rotate the stick 450° to the left and 450° to the right.
  • WIND_STICK_POWER (default 1.0) - What is the shape of the curve used for converting the wound position to a stick offset? 1.0 is a simple linear relationship. Larger values will mean rotations are reduced when near the neutral position and increased towards the edge of the range. Smaller values will mean the opposite.
  • UNWIND_RATE (default 1800.0 degrees per second) - This is how quickly the wound stick position pulls back to its neutral position when the stick is released. If the stick is only partially engaged, the virtual stick position will unwind more slowly.

For MOTION_STICK_MODE in particular, there are two new options:

LEFT_STEER_X
RIGHT_STEER_X

These will map leaning the controller to the X axis of either the left or right stick. For steering a car, this works better than mapping MOTION_STICK to a stick. But like mapping it to a stick, UNPOWER and UNDEADZONE come into play. Make sure to set MOTION_DEADZONE_INNER and MOTION_DEADZONE_OUTER to suitable values -- they're both in degrees, with the max motion / lean angle being 180 degrees.

  • New trigger mode available
# Using analog triggers
ZL_MODE = X_LT
ZR_MODE = X_RT

Using both analog and digital trigger bindings at the same time leads to undefined behaviours. Use modeshift as defined in the next section to disable analog triggers while a digital trigger binding is active.

You will also find a default xbox layout in the GyroConfigs folder that you can use to set up a standard xbox controller configuration. But of course, you can remap buttons elsewhere, or combine them in using the event modifiers, chords, simultaneous presses and such.

GyroConfigs/xbox.txt # load the generic xbox mapping

# Map the dpad as chords of the face buttons
L3 = NONE
L3,N = X_UP
L3,W = X_LEFT
L3,S = X_DOWN
L3,E = X_RIGHT

S,S = X_LS # Double click jump to sprint instead

L+R = X_RS # I don't like to stick click often

MOTION_STICK_MODE = RIGHT_STICK # Gyro driving

DS4 bindings

ViGEm also the ability to emulate a Dualshock 4 controller. This can allow you to use a switch pro as a DS4 in a game that has this support built in for example. Setting the virtual controller to DS4 enables the use of these features as well. Take note that these names are aliases to the xbox names, so the logs might display the other label.

  • New digital bindings
PS_CROSS, PS_CIRCLE, PS_SQUARE, PS_TRIANGLE : The playstation face button diamond
PS_L1, PS_R1 : The playstation bumper buttons
PS_L3, PS_R3 : The playstation stick click buttons
PS_SHARE, PS_OPTIONS : The playstation control buttons
PS_UP, PS_DOWN, PS_LEFT, PS_RIGHT : The playstation dpad directions
PS_HOME, PS_PAD_CLICK : The playstation home and pad click buttons
PS_L2, PS_R2 : The playstation digital trigger bindings
  • New stick mode available These are exactly the same as the xbox names
LEFT_STICK_MODE = LEFT_STICK
RIGHT_STICK_MODE = RIGHT_STICK
  • New GYRO_OUTPUT mode available
GYRO_OUTPUT = PS_MOTION
  • New TOUCHPAD_MODE mode available
TOUCHPAD_MODE = PS_TOUCHPAD

A ds4 can also use the more advanced angle-to-axis stick modes described in the xbox section:

LEFT_ANGLE_TO_X
LEFT_ANGLE_TO_Y
RIGHT_ANGLE_TO_X
RIGHT_ANGLE_TO_Y
LEFT_WIND_X
RIGHT_WIND_X

As well as the MOTION_STICK-specific modes:

LEFT_STEER_X
RIGHT_STEER_X
  • New trigger mode available. JoyShockMapper will display the trigger mode as the xbox name : the trigger will still work properly.
# Using analog triggers
ZL_MODE = PS_L2
ZR_MODE = PS_R2

If there is multiple sources of analog data (such as a trigger and a digital binding) the two sources will add up and clamp within the limit of the data. Soft and full pull chords will still be available for use and for the gyro button.

Virtual Controller Gyro

While the virtual controller can't output gyro, JoyShockMapper can convert gyro input to stick output. For example:

GYRO_OUTPUT = RIGHT_STICK

GYRO_OUTPUT can also be set to LEFT_STICK or left at its default value of MOUSE, which means gyro will be converted to mouse input.

Because games tend to do a lof of processing on stick input to turn it into camera movement, you'll want to counter that processing to convert it to a decent camera movement. So far, here are your options:

  • RIGHT_STICK_UNDEADZONE_INNER / LEFT_STICK_UNDEADZONE_INNER (default 0) - This will counter the game's inner deadzone. For example, if a game has a deadzone of 0.25 (that's 25% off the stick movement range), very small gyro inputs will convert to a stick radius of just over 0.25 so that the game detects them right away. When gyro output is assigned to this stick and no gyro is detected (if GYRO_SENS is 0, for example), this stick position will be set to the edge of this deadzone. This means you can tweak this deadzone value until you get the largest value that doesn't move the camera automatically to find the exact inner deadzone.
  • RIGHT_STICK_UNDEADZONE_OUTER / LEFT_STICK_UNDEADZONE_OUTER (default 0) - Distance from the outer theoretical edge of the stick's range that will be considered "full tilt". Gyro velocity will be mapped to a stick position between _STICK_UNDEADZONE_INNER and _STICK_UNDEADZONE_OUTER.
  • RIGHT_STICK_UNPOWER / LEFT_STICK_UNPOWER (default 0) - A power curve is often applied to stick input to give players more with small movements at the cost of less precision with very large movements. If you know what the exponent is, putting it here will counter that power curve to hopefully give you linearly proportional camera control. The default value of 0 does nothing, which is effectively the same as setting it to 1, since that assumes a linear curve.
  • RIGHT_STICK_VIRTUAL_SCALE / LEFT_STICK_VIRTUAL_SCALE (default 1) - Use this to scale down virtual stick output. For example, if you're converting gyro to right stick aim (GYRO_OUTPUT = RIGHT_STICK), you'll want a high in game stick sensitivity so you can do fast flicks with the gyro. But you may not want your regular stick aim to be that high. You could set this setting to 0.5 to halve the strength of your stick aiming. JSM will take into account your "UNPOWER" and "UNDEADZONE" settings when calculating this new stick output.

Games sometimes do a lot of other processing to the stick input: easing in, acceleration, direction warping, angular deadzones, for example. JSM does not yet have a way to counter these effects.