Skip to content

Latest commit

 

History

History
194 lines (147 loc) · 8.04 KB

File metadata and controls

194 lines (147 loc) · 8.04 KB

IL-2 Sturmovik: Great Battles with ControllerBuddy on Linux

📖 Description

This guide describes the installation of IL-2 Sturmovik: Great Battles (Steam) for use with ControllerBuddy on Linux via the Proton compatibility layer.

What you get with this setup:

  • An installation of IL-2 Sturmovik: Great Battles that is nicely integrated into your Steam library.
  • ControllerBuddy will start automatically when you start the game, load the correct profile, and exit when you quit the game.

🧩 Prerequisites

🪜 Steps

Important

Before starting with the steps, make sure to read the Important Notes section in the README of this repository.

  1. Download IL-2 Sturmovik: Great Battles in Steam.

  2. Select Proton 10.0-4 as compatibility tool.

  3. Launch IL-2 Sturmovik: Great Battles so that the Proton prefix gets created. The game will likely crash on the first launch, but that's expected.

  4. Export the APP_ID environment variable:

    export APP_ID=307960

Important

All subsequent commands must be executed within the same shell session to retain the APP_ID environment variable.

  1. Make sure all your game controllers are connected.

  2. Hide all game controllers from the Proton prefix, except for ControllerBuddy's UINPUT joystick device:

    reg_file=$(mktemp -p '' joysticks-XXXX.reg) &&
    python3 - <<'EOF' "$reg_file" &&
    import ctypes
    import ctypes.util
    import sys
    
    sdl2_path = ctypes.util.find_library("SDL2")
    if not sdl2_path:
        raise RuntimeError("Could not find SDL2 library")
    
    sdl = ctypes.CDLL(sdl2_path)
    
    Uint16 = ctypes.c_uint16
    Uint32 = ctypes.c_uint32
    class SDL_JoystickGUID(ctypes.Structure):
        _fields_ = [("data", ctypes.c_uint8 * 16)]
    
    sdl.SDL_Init.argtypes = [ctypes.c_uint32]
    sdl.SDL_Init.restype = ctypes.c_int
    
    sdl.SDL_Quit.argtypes = []
    sdl.SDL_Quit.restype = None
    
    sdl.SDL_NumJoysticks.argtypes = []
    sdl.SDL_NumJoysticks.restype = ctypes.c_int
    
    sdl.SDL_JoystickNameForIndex.argtypes = [ctypes.c_int]
    sdl.SDL_JoystickNameForIndex.restype = ctypes.c_char_p
    
    sdl.SDL_JoystickGetDeviceGUID.argtypes = [ctypes.c_int]
    sdl.SDL_JoystickGetDeviceGUID.restype = SDL_JoystickGUID
    
    sdl.SDL_GetJoystickGUIDInfo.argtypes = [SDL_JoystickGUID, ctypes.POINTER(Uint16), ctypes.POINTER(Uint16), ctypes.POINTER(Uint16), ctypes.POINTER(Uint16)]
    sdl.SDL_GetJoystickGUIDInfo.restype = None
    
    SDL_INIT_JOYSTICK = 0x00002000
    
    if sdl.SDL_Init(SDL_INIT_JOYSTICK) != 0:
        print("SDL_Init failed:", sdl.SDL_GetError().decode("utf-8"))
        sys.exit(1)
    
    # see: https://github.com/wine-mirror/wine/blob/master/dlls/hidclass.sys/device.c
    device_strings = {
        (0x045E, 0x028E): "Controller (XBOX 360 For Windows)",
        (0x045E, 0x028F): "Controller (XBOX 360 For Windows)",
        (0x045E, 0x02D1): "Controller (Xbox One For Windows)",
        (0x045E, 0x02DD): "Controller (Xbox One For Windows)",
        (0x045E, 0x02E3): "Controller (Xbox One For Windows)",
        (0x045E, 0x02EA): "Controller (Xbox One For Windows)",
        (0x045E, 0x02FD): "Controller (Xbox One For Windows)",
        (0x045E, 0x0719): "Controller (XBOX 360 For Windows)",
        (0x045E, 0x0B00): "Controller (Xbox One For Windows)",
        (0x045E, 0x0B05): "Controller (Xbox One For Windows)",
        (0x045E, 0x0B12): "Controller (Xbox One For Windows)",
        (0x045E, 0x0B13): "Controller (Xbox One For Windows)",
        (0x054C, 0x05C4): "Wireless Controller",
        (0x054C, 0x09CC): "Wireless Controller",
        (0x054C, 0x0BA0): "Wireless Controller",
        (0x054C, 0x0CE6): "Wireless Controller",
        (0x054C, 0x0DF2): "Wireless Controller",
    }
    
    count = sdl.SDL_NumJoysticks()
    joysticks = []
    
    for i in range(count):
        name_ptr = sdl.SDL_JoystickNameForIndex(i)
        if not name_ptr:
            continue
        name = name_ptr.decode("utf-8")
    
        if name == "ControllerBuddy Joystick":
            continue
    
        guid = sdl.SDL_JoystickGetDeviceGUID(i)
        vendor = Uint16()
        product = Uint16()
        version = Uint16()
        crc16 = Uint16()
        sdl.SDL_GetJoystickGUIDInfo(guid, ctypes.byref(vendor), ctypes.byref(product), ctypes.byref(version), ctypes.byref(crc16))
    
        key = (vendor.value, product.value)
        if key in device_strings:
            name = device_strings[key]
    
        joysticks.append(name)
    
    sdl.SDL_Quit()
    
    if not joysticks:
        print("Error: No joysticks detected on this system.", file=sys.stderr)
        sys.exit(1)
    
    def escape_reg_string(s: str) -> str:
        return s.replace('"', '""')
    
    print("Found the following joysticks:")
    for name in joysticks:
        print(f" {name}")
    
    if len(sys.argv) > 1:
        path = sys.argv[1]
        with open(path, "w", encoding="utf-16") as f:
            f.write("\ufeffWindows Registry Editor Version 5.00\n\n")
            f.write("[HKEY_CURRENT_USER\\Software\\Wine\\DirectInput\\Joysticks]\n")
            for name in joysticks:
                safe_name = escape_reg_string(name)
                f.write(f"\"{safe_name}\"=\"disabled\"\n")
        print(f"Wrote registry file: {path}")
    EOF
    flatpak run --filesystem="$reg_file":ro com.github.Matoking.protontricks -c "wine reg import '$reg_file'" "$APP_ID"
    rm -f "$reg_file"
  3. Install d3dcompiler_47 and powershell into the Proton prefix:

    flatpak run com.github.Matoking.protontricks "$APP_ID" d3dcompiler_47 powershell
  4. Make sure your game controller is still connected.

  5. Launch ControllerBuddy, and start local run mode to initialize the UINPUT joystick device:

    flatpak run de.bwravencl.ControllerBuddy -autostart local &
  6. Configure IL-2 Sturmovik: Great Battles to work with the ControllerBuddy-Profiles:

    controller_buddy_profiles_dir=$(realpath -s "$(flatpak info -l de.bwravencl.ControllerBuddy)/../active/files/share/ControllerBuddy-Profiles") &&
    cd "$controller_buddy_profiles_dir/configs/IL-2_GB" &&
    WINEDEBUG='-all' flatpak run --filesystem="$controller_buddy_profiles_dir" com.github.Matoking.protontricks -c 'wine pwsh Configure.ps1' "$APP_ID"
  7. Update the IL-2 Sturmovik: Great Battles Steam shortcut as follows:

    LAUNCH OPTIONS:

    "${STEAM_RUNTIME}"/scripts/switch-runtime.sh --runtime='' -- flatpak run de.bwravencl.ControllerBuddy -autostart local -profile /app/share/ControllerBuddy-Profiles/IL-2_GB.json -tray & timeout=15; timeout "$timeout" bash -c 'until grep -q "ControllerBuddy Joystick" /proc/bus/input/devices ; do sleep 1 ; done' && %command% || { [ $? -eq 124 ] && zenity --error --text="Launch aborted because ControllerBuddy wasn't ready within $timeout seconds.\n\nCheck if your controller is connected." --width 500 ; } ; killall -q ControllerBuddy

🔄 Re-running the Configuration Script

The configuration script must be run again whenever the ControllerBuddy-Profiles receive an update.

  1. Make sure your game controller is connected.

  2. Execute the following command (steps 4, 9, and 10 combined):

    export APP_ID=307960
    flatpak run de.bwravencl.ControllerBuddy -autostart local &
    controller_buddy_profiles_dir=$(realpath -s "$(flatpak info -l de.bwravencl.ControllerBuddy)/../active/files/share/ControllerBuddy-Profiles") &&
    cd "$controller_buddy_profiles_dir/configs/IL-2_GB" &&
    WINEDEBUG='-all' flatpak run --filesystem="$controller_buddy_profiles_dir" com.github.Matoking.protontricks -c 'wine pwsh Configure.ps1' "$APP_ID"