Digital Inputs - AL2009man/JoyShockMapper GitHub Wiki
Digital inputs are really simple. They are structured mostly like the following:
[Controller Input] = [Key or Mouse Button]
For example, to map directional pad LEFT to the F1 key, you'd enter:
LEFT = F1
One important feature of JoyShockMapper is that a configuration that works for a PlayStation controller works the same for a pair of JoyCons or a Pro Controller. Because JoyCons can have slightly more inputs than the DualShock 4, the button names are mostly from the Nintendo devices. The main exceptions are the face buttons and the stick-clicks. Because they are named more concisely, the stick-clicks are named after the DualShock 4: L3
and R3
.
The face buttons are a more complicated matter.
The Xbox layout has become the defacto layout for PC controllers. Most PC gamers who use some sort of controller will be familiar with the Xbox layout, whether from Xbox controllers, Steam controller, or other 3rd party controllers that can be interpreted by a game as an Xbox controller. Even PlayStation users will be somewhat used to interpreting Xbox face button names. Nintendo devices have the same face buttons in a different layout. X and Y are swapped, and so are A and B. Nintendo's layout has also been around for longer, but is less familiar to PC players.
So the best solution, in my opinion, is to use neither layout, and use an unambiguous layout with button names that aren't used by any controller, but still have obvious positions: the cardinal layout. North, East, South, West, denoted by N
, E
, S
, W
, respectively.
So, here's the complete list of digital inputs:
UP, DOWN, LEFT, RIGHT: D-pad directional buttons
L: L1, LB or L the top left shoulder button
ZL: L2, LT or ZL the bottom left shoulder button (or trigger)
R: R1, RB or R, the top right shoulder button
ZR: R2, RT or ZR, the bottom right shoulder button
ZRF: Full pull binding of right trigger, only on controllers with analog triggers
ZLF: Full pull binding of left trigger, only on controllers with analog triggers
-: Share, Back or -
+: Options, Start or +
HOME: PS, Guide or Home
CAPTURE: Touchpad click or Capture
LSL, RSL: SL on JoyCons, or left paddles on Xbox elite
LSR, RSR: SR on JoyCons, or right paddles on Xbox elite
L3: L3 or Left-stick click
R3: R3 or Right-stick click
N: The North face button, △, Y (Xbox) or X (Nintendo)
E: The East face button, ○, B (Xbox) or A (Nintendo)
S: The South face button, ⨉, A (Xbox) or B (Nintendo)
W: The West face button, □, X (Xbox) or Y (Nintendo)
LUP, LDOWN, LLEFT, LRIGHT: Left stick tilted up, down left or right
LRING: Left ring binding, either inner or outer.
RUP, RDOWN, RLEFT, RRIGHT: Right stick tilted up, down, left or right
RRING: Right ring binding, either inner or outer.
MUP, MDOWN, MLEFT, MRIGHT: Motion stick tilted forward, back, left or right
MRING: Motion ring binding, either inner or outer.
LEAN_LEFT, LEAN_RIGHT: Tilt the controller to the left or right
TOUCH : The Playstation touchpad senses a finger
MIC: The Sony Dualsense microphone button
These can all be mapped to the following keyboard and mouse inputs:
0-9: number keys across the top of the keyboard
N0-N9: numpad number keys
ADD, SUBTRACT, DIVIDE, MULTIPLY, DECIMAL: numpad operator and decimal keys
F1-F29: F1, F2, F3... etc
A-Z: letter keys
UP, DOWN, LEFT, RIGHT: the arrow keys
LCONTROL, RCONTROL, CONTROL: left Ctrl, right Ctrl, generic Ctrl, respectively
LALT, RALT, ALT: left Alt, right Alt, generic Alt, respectively
LSHIFT, RSHIFT, SHIFT: left Shift, right Shift, generic Shift, respectively
LWINDOWS, RWINDOWS, CONTEXT: Both Windows keys and the context menu key
TAB, ESC, ENTER, SPACE, BACKSPACE, CAPS_LOCK, SCROLL_LOCK, NUM_LOCK,
PAGEUP, PAGEDOWN, HOME, END, INSERT, DELETE
LMOUSE, MMOUSE, RMOUSE: mouse left click, middle click and right click respectively
BMOUSE, FMOUSE: mouse back (button 4) click and mouse forward (button 5) click respectively
SCROLLUP, SCROLLDOWN: scroll the mouse wheel up, down, respectively
VOLUME_UP, VOLUME_DOWN, MUTE: Volume controls
NEXT_TRACK, PREV_TRACK, STOP_TRACK, PLAY_PAUSE: media control
SCREENSHOT: print screen button
NONE, DEFAULT: No input
CALIBRATE: recalibrate gyro when pressing this input
GYRO_ON, GYRO_OFF: Enable or disable gyro
GYRO_INVERT, GYRO_INV_X, GYRO_INV_Y: Invert gyro, or in just the x or y axes, respectively
GYRO_TRACKBALL, GYRO_TRACK_X, GYRO_TRACK_Y: Keep last gyro input, or in just the x or y axes, respectively
; ' , . / \ [ ] + - `
"any console command": Any console command can be run on button press, including loading a file
SMALL_RUMBLE, BIG_RUMBLE, Rhhhh: rumble commands. The 'h' are capital hex digits, such as 'R8000' or 'RFFFF'
For example, in a game where R is 'reload' and E is 'use’, you can do the following to map □ to 'reload' and △ to 'use':
W = R
N = E
Those familiar with Steam Input can implement Action Layers and Action Sets using the quotation marks to load a file on demand. That file can contain partial or full remapping of the controller bindings. This is very useful for having a different scheme for vehicles, menus or characters.
# Load the driving control scheme.
HOME = "Autoload/GTA5/GTA_driving.txt" # That file should bind HOME to loading the walking scheme file!
Take note that the command bound in this way cannot contain quotation marks, and thus cannot contain the binding of a command itself. In this case, you should put the command in a file and load that file.
Tap & Hold
Since a keyboard has many more inputs available than most controllers, console games will often map multiple actions to the same button while the PC version has those actions mapped to different keys. In order to fit keyboard mappings onto a controller, JoyShockMapper allows you to map taps and holds of a button to different keyboard/mouse inputs. So let's take that same game and make it so we can tap □ to 'reload' or hold □ to 'use':
W = R E
If you want □ to 'reload' when tapped, but do nothing at all when held, you can do the following:
W = R NONE
The time to hold the button before enabling the hold binding can be changed by assigning a number of milliseconds to HOLD_PRESS_TIME
. The default value is 150 milliseconds.
See the tap press and hold press event modifiers below for more details on how keybinds are applied.
Binding Modifiers
Taps and holds are the most common bindings used on a controller. But sometimes, you will find the need to require bindings that are somewhat more complicated, either because you want to work around an in-game behaviour, or you want to create some unusual key press combination. In any case, JoyShockMapper allows you to highly customize how mappings are assigned to your button through binding modifiers.
Before we dive in, there's a few notions to understand. A key press always involves a key down and a key up action. In a simple binding, JoyShockMapper will match the button down and button up events with a key down and key up action respectively. However when you use Tap and Hold bindings, JoyShockMapper will bind the key down and key up to different events that will happen a certain time while the button is down and after the button is released. Some bindings do not have a matching "key up" action such as scroll wheel bindings and console command bindings.
There are two kinds of modifiers that can be applied to key bindings: action modifiers and event modifiers. They are represented by symbols added before and after the key name respectively. And each binding can only ever have one of each. You can however have multiple keys bound to the same events, thus sending multiple key presses at once.
Action modifiers affect how the key down and key up actions are bound to the events. They come in two kinds: toggle (^) and instant (!).
- ^ Toggle makes it so that the key will alternate between applying and releasing the key at each press.
- ! Instant will send the key up action very shortly after the key down, making it seem instant.
Event Modifiers affect what button events the key up and key down actions will be bound to. They come in five kinds: start press (\), release press (/), tap press ('), hold press (_),\ and turbo (+).
- \ Start press is the default event modifier when there is only a single key bind. It will apply the key down action as soon as the button is pressed and the key up when the button is released by default. This can be useful to have a key held while other keys are being activated.
- / Release press will apply the binding when the button is released. A binding on release press needs an action modifier to be valid.
- ' Tap press is the default event modifier for the first key bind when there are multiple of them. It will apply the key press when the button is released if the total press time is less than the
HOLD_PRESS_TIME
. By default the key press is released a short time after, with that time being longer for gyro related actions and calibration. - _ Hold press is the default event modifier for the second key bind when there are multiple of them. It will apply the key only after the button is held down for the
HOLD_PRESS_TIME
. By default, the key is released when the button is released as well. - + Turbo will apply a key press repeatedly (with consideration of action modifiers), resulting in a fast pulsing of the key. The turbo pulsing starts only after the button has been held for
HOLD_PRESS_TIME
.
These modifiers can enable you to work around in game tap and holds, or convert one form of press into another. Here's a few example of how you can make use of those modifiers.
ZL = ^RMOUSE\ RMOUSE_ # ADS toggle on tap and release the toggle on hold
E = !C\ !C/ # Convert in game toggle crouch to regular press
UP = !1\ 1 # Convert Batarang throw double press to hold press
W = R E\ # In Halo MCC, reload on tap but apply E right away to cover for in-game hold processing
-,S = SPACE+ # Turbo press for button mash QTEs. No one likes to button mash :(
R3 = !1\ LMOUSE+ !Q/ # Half life melee button
UP,UP = !ENTER\ LSHIFT\ !G\ !L\ !SPACE\ !H\ !F\ !ENTER/ # Pre recorded message
UP,E = BACKSPACE+ # Erase pre recorded message if I change my mind
Take note that the Simultaneous Press below introduce delays in the raising of the events (notably StartPress) until the right mapping is determined. Those time windows are not added but events will be pushed together within a poll callback or two.
Also, Double Press bindings has some special timing handling in order to give the user the option to have the first binding skippable or not. See its dedicated section below for details
Finally, Here is a graph containing a comprehensive description of when the button events are raised over the course of a press.
less than 150 ms hold time
150 ms hold time 80ms turbo period V 500 ms for gyro and calibration
V V |------|< actions or 40 ms otherwise
______|-----|---|---|---|---|---|--|___________|---|____________
\____________________________/ \___/ |
| | | | | | | | | | |
(a) (b) (c) (c) (c) (c) (c)(d) (a) (d) (g)
(c) (f) (e)
a: start press \
b: hold press _
c: turbo +
d: release press /
e: tap press '
f: hold release
g: tap release
Events a, b, c, d and e have an Instant Release event attached to them 40ms after they occur.
Simultaneous Press
JoyShockMapper additionally allows you to map simultaneous button presses to different mappings. For example you can bind character abilities on your bumpers and an ultimate ability on both like this:
L = LSHIFT # Ability 1
R = E # Ability 2
L+R = Q # Ultimate Ability
To enable a simultaneous binding, both buttons need to be pressed within a very short time of each other. Doing so will ignore the individual button bindings and apply the specified binding until either of the button is released. Simultaneous bindings also support tap & hold bindings as well as modifiers just like other mappings. This feature is great to make use of the dpad diagonals, or to add JSM specific features like gyro calibration and gyro control without taking away accessible buttons.
The time window in which both buttons need to be pressed can be changed by assigning a different number of milliseconds to SIM_PRESS_WINDOW
. This setting cannot be changed by modeshift (covered later).
Chorded Press
Chorded press works differently from Simultaneous Press, despite being similar at first blush. A chorded press mapping allows you to override a button mapping when the chord button is down. This enables a world of different practical combinations, allowing you to have contextual bindings. Here's an example for Left 4 Dead 2, that would enable you to equip items without lifting the thumb from the left stick.
W = R E # Reload / Use
S = SPACE # Jump
E = CONTROL # Crouch
N = T # Voice Chat
L = Q NONE # Other weapon, hold to select with face button.
L,W = 3 # Explosives
L,S = 4 # Pills
L,E = 5 # Medpack
L,N = F # Flashlight
A button can be chorded with multiple other buttons. In this case, the latest chord takes precedence over previous chords. This can be understood as a stack of layers being put on top of the binding each time a chord is pressed, where only the top one is active. Notice that you don't need to have NONE as a binding : the chord binding could very well be bound to a button that brings up a weapon wheel for example.
Double Press
You can also assign the double press of a button to a different binding. Double press notation is the same as chorded button notation, except the button is chorded with itself. It supports taps & holds and modifiers like all previous entries.
The double press binding is applied when a down press occurs within 150 milliseconds from a previous down press. The regular binding will apply any on press event on the first press, but will only apply the tap binding if the second press is ommitted and with a delay. The double press binding also supports tap & hold bindings as well as modifiers. The time window in which to perform the double press can be changed by assigning a different number of milliseconds to DBL_PRESS_WINDOW
.
N = SCROLLDOWN # Cycle weapon
N,N = X # Cycle weapon fire mode
W = !E\ # Pick up item
W,W = I # Pick up item and open Inventory
E = C' # Crouch
E,E = Z # Don't crouch but go prone
Gyro Button
Lastly, there is one digital input that works differently, because it can overlap with any other input. Well, two inputs, but you'll use at most one of them in a given configuration:
GYRO_OFF
GYRO_ON
When you assign a button to GYRO_ON
, gyro mouse only work while that button is pressed. GYRO_OFF
disables the gyro while the button is pressed. This is a really important feature absent from most games that have gyro aiming -- just as a PC gamer can temporarily "disable" the mouse by lifting it off the mousepad in order to reposition it, a gyro gamer should be able to temporarily disable the gyro in order to reposition it. This binding doesn't affect other mappings associated with that button. This is so that the gyro can be enabled alongside certain in-game actions, or so that the gyro can be disabled or enabled instantly regardless of what taps or holds are mapped to that button.
For games that really need to use all the buttons available on the controller, but one of those inputs is rarely used and can be toggled easily (like crouching, for example), it might make sense to make that input tap-only, and make it double as the gyro-off button when held:
E = LCONTROL NONE
GYRO_OFF = E
Or if you really can't spare a button for disabling the gyro, you can use LEFT_STICK or RIGHT_STICK to disable the gyro while that input is being used:
GYRO_OFF = RIGHT_STICK # Disable gyro while aiming with stick
I prefer to be able to use stick aiming (or flick stick) at the same time as aiming with the gyro, but this can still be better than having no way to disable the gyro at all if your game doesn't have an obvious function to tie to enabling gyro aiming (like a dedicated "aim weapon" button as is common in third-person action games).
GYRO_ON
is really useful for games where you only sometimes need to aim precisely. If ZL causes your character to aim their bow (like in Zelda: Breath of the Wild or Shadow of Mordor), maybe that's the only time you want to have gyro aiming enabled:
ZL = RMOUSE # Aim with Bow
GYRO_ON = ZL # Turn on gyro when ZL is pressed
GYRO_ON
and GYRO_OFF
can also be bound as an action to particular buttons. Contrary to the command above, this takes the spot of the action binding. But you can still find creative ways with taps & holds or chorded press to bind the right gyro control where you need it.
Take note that taps apply gyro-related bindings for half a second. Another option is inverting the gyro input with GYRO_INVERT
. Such a binding can be handy if you play with a single joycon because you don't have a second stick. When that action is enabled, the inversion makes it so that you can recenter the hands by continuing to turn in the opposite direction!
SL + SR = GYRO_OFF GYRO_INVERT # Disable for .5s / Invert axis on simultaneous bumper hold
Bound gyro actions like those have priority over the assigned gyro button should they conflict.
The command NO_GYRO_BUTTON
can be used to remove the gyro-on or gyro-off mapping, making gyro always enabled. To have it always disabled, just set GYRO_ON = NONE
or leave GYRO_SENS
at 0.
If you're using GYRO_TRACKBALL
or its single-axis variants, you can use TRACKBALL_DECAY to choose how quickly the trackball effect loses momentum. It can be set to 0 for no decay. Its default value of 1 halves the gyro trackball's momentum over each second. 2 will halve it in 1/2 seconds, 3 in 1/3 seconds, and so on. Some smoothing is applied when getting the trackball initial velocity in order to reduce the effects of noise or controller instability when pressing the button.