HowTo: Getting Steam, WINE, Game Controllers Working Together
Part 1: Native Games
Most Linux-native game use SDL2, which has hardcoded support for most gamepads. With a kernel gamepad driver (as in, without userspace drivers such as xboxdrv or ds4drv), most gamepads should work out of the box.
If yours does not, you can add its mapping to SDL2 by setting the SDL_GAMECONTROLLERCONFIG environment variable. To generate the value that makes your gamepad work, you can use the following program:
Refer to the following for background:
Part 2: Steam Games in WINE
Overview
There are currently two protocols that games in Windows can use for gamepad support. If the game expects an Xbox 360 pad, it's using
XInput. If it expects you to bind gamepad controls to game actions before playing, it's using
DirectInput. In the following video, you can hear Icculus explaining the difference between the two:
Controller support is an issue in WINE because as of this writing (WINE 2.21), WINE does not support XInput. Rather, it sees all connected controllers as DirectInput controllers. Hence, we'll use a program called
x360ce, which is normally used on Windows to get DirectInput controllers working with XInput games.
There are many guides, both written and video, to using x360ce, and most of the ones aimed at Windows gamers apply to WINE gamers. One particularly good one for WINE users is here:
I'm aware that many of these previous guides recommend using xboxdrv. That is now outdated information. Do not use xboxdrv unless you're actually having issues without it. I've found that it certainly isn't needed for either an Xbox One S controller or a Wii U Pro Controller.
Another issue is that WINE accepts input from both of the interfaces that Linux creates per gamepad: the
evdev interface (/dev/input/event) and the
joydev interface (/dev/input/js). We'll deal with that by disabling the joydev interface.
For the following steps, you need a 64-bit multilib system and a WOW64-enabled WINE build. In other words, the same
wine binary needs to be able to run both 64-bit and 32-bit Windows applications.
Setting Up XInput Emulation
With the gamepad plugged in, and when ~/.local/share/wineprefixes/x36ce does
not exist:
Code:
export WINEPREFIX=~/.local/share/wineprefixes/x360ce
WINEARCH=win32 winecfg
winetricks -q dotnet45
cd $WINEPREFIX/drive_c
mkdir x360ce
cd x360ce
unzip ~/Downloads/x360ce.zip
wine control
wine x360ce
export -n WINEPREFIX
In "wine control", disable the "(js)" gamepad, and leave the "(event)" gamepad active. The "js" interface is deprecated, and the "event" interface is its replacement. If you keep both enabled, WINE will see both as a separate joystick. This does cause problems.
In x360ce, you set your gamepad's button mappings. For the sticks, the axes increase when going up and right. When you're ready, save. The output should be the following file:
It probably also output the following DLL file:
This is functionally identical to the xinput.dll you can download as an
x360ce resource.
Save the x360ce.ini file.
Testing XInput Emulation
Download
XInputTest and unzip it:
Code:
cd ~/.wine/drive_c
unzip ~/Downloads/x360ce\ vibmod\ 3.1.4.1.zip
Fire up winecfg. Go to the "Applications" tab and add a profile for XInputTest.exe, which is where you unzipped it to. For that profile, add an override for xinput1_3.dll to have the native version loaded before the builtin version.
Go into "wine control" and disable the "(js)" gamepad.
Now you're ready to test your gamepad:
Code:
cd x360ce\ vibmod\ 3.1.4.1
WINEDEBUG=loaddll wine XInputTest
XInputTest should now be responding when you test with your gamepad!
In your terminal, you should see confirmation that your XInput DLL override is being loaded:
Code:
trace:loaddll:load_native_dll Loaded L”C:\\x360ce vibmod 3.1.4.1\\xinput1_3.dll” at 0x2cd0000: native
Installing Steam
Create a new 64-Bit WINE bottle for Steam.
Code:
export WINEPREFIX=~/.local/share/wineprefixes/steam
winecfg
wine control
In "wine control", disable the (js) gamepad.
Then install Steam:
Code:
winetricks -q steam
Steam will have created two launchers:
- ~/Desktop/Steam.desktop
- ~/.local/share/applications/wine/Programs/Steam/Steam.desktop
Each will look like the following:
Code:
[Desktop Entry]
Name=Steam
Exec=env WINEPREFIX="/home/dugan/.local/share/wineprefixes/steam" /usr/bin/wine C:\\\\windows\\\\command\\\\start.exe /Unix /home/dugan/.local/share/wineprefixes/steam/dosdevices/c:/users/Public/Desktop/Steam.lnk
Type=Application
StartupNotify=true
Path=/home/dugan/.local/share/wineprefixes/steam/dosdevices/c:/Program Files/Steam
Icon=BAC4_steam.0
StartupWMClass=steam.exe
Add WINEDEBUG flags to the Exec lines so that they disable logging:
Code:
Exec=env WINEDEBUG="-all" WINEPREFIX="/home/dugan/.local/share/wineprefixes/steam" /usr/bin/wine C:\\\\windows\\\\command\\\\start.exe /Unix /home/dugan/.local/share/wineprefixes/steam/dosdevices/c:/users/Public/Desktop/Steam.lnk
Disabling logging is one of the most valuable optimizations you can add. In many games, it will lead to a significant increase in speed. You're not going to see this logging anyway if you're running Steam from the shortcut. If you need logging, run WINE from a terminal.
You probably also want change the name to something like:
Code:
Name=Steam (32-Bit WINE)
Feel free to add a comment below that line:
Code:
Comment=Steam for Windows
Because we allowed winemenubuilder to run, you might discover file associations that might need to be set back:
Code:
> xdg-mime query default application/pdf
wine-extension-pdf.desktop
> xdg-mime default xpdf.desktop application/pdf
Enjoy!
From this point on you will launch Steam from the shortcut, use Steam to install your games, and, when you're ready to play, use Steam to launch them.
Use the terminal to test and set up overrides on a game-by-game basis. Set WINEPREFIX in the environment, fire up winecfg, and browse for the game's .exe. Then set whatever overrides are needed for that game.
If a game needs x360ce overrides, you'll start by copying x360ce's xinput1_3.dll to the same directory as the game's .exe, along with your x360ce.ini. Some games might need that DLL renamed (e.g. to xinput1_4.dll); use WINEDEBUG=loaddll to find out.
Example: Wolfenstein: The New Order
Wolfenstein: The New Order is a 64-Bit game. So you download the 64-bit xinput DLL for x360ce:
Then you rename it to xinput1_3.dll, and put both it, and your x360ce.ini file, in the same directory as the game's executable. Then you set WINEPREFIX to Steam, fire up winecfg, and set an override so that it prefers the native xinput1_3.dll when it's running the game's executable.
Example: Deathsmiles
Deathsmiles recognizes both XInput and DirectInput. If you allow it to receive both XInput and DirectInput game controller input, (and/or if you have both the js and event joystick interfaces active), then the game will think it's receiving input from two game controllers, and you'll mysteriously find yourself controlling two characters with one controller. (I've seen Steam forum posts indicating that this can also happen when you run the game on Windows).
The solution is to use the DirectInput Blocker from here:
Set DeathSmiles up with x360ce as usual (put x360ce.ini and the 32-bit xinput1_3.dll in the game's directory, set the DLL override). Then add the DirectInput Blocker (dinput8.dll) to the game's directory, and add a native override for that too.
(This also applies to DoDonPachi Resurrection, except that DoDonPachi Resurrection messes up less dramatically if you miss a step).
Part 3: Steam Controller
Setting up a Steam Controller is similar to setting up any other gamepad. Start by replacing the xinput DLL from x360ce with one from
dumbxinputemu. This is like x360ce, except that it doesn't need to be configured. Instead, it has hardcoded mappings that are correct for the Steam Controller's Xbox 360 emulation.
Then, you have three options for how to set up your Steam Controller mappings.
You can can use
sc-controller.
The next two options use Steam for Linux to set the mappings.
The first option is to use Steam for Linux's Big Picture Mode to set up your Steam Controller for the game, and then to make sure that Steam is running at the same time that the game is. In most cases, that means you'll have both Steam for Linux and Steam for Windows running at the same time.
You can set up Steam for Linux's desktop configuration to be correct for the game, as demonstrated in the following video:
The second option write a shell script to run the game, add it to Steam for Linux as a non-Steam game, and set up your Steam Controller for that game.