]> vilimpoc.org git repositories - bl2-split/blob - README.md
b94f4c737126366cce69a76b929620e8fb779982
[bl2-split] / README.md
1 # Borderlands 2 — 2-player split screen (Linux / KDE)
2
3 Borderlands 2 has **no built-in PC split screen**. This runs **two copies** of the
4 game side-by-side that connect over Goldberg's emulated Steam LAN — each with its
5 own save, its own identity, and its own controller — auto-tiled on KDE (KWin).
6
7 **Status: working & validated on this machine.** Both instances start, initialize
8 Steamworks + engine, and run simultaneously. Goldberg is already downloaded and
9 staged; `setup` has been run. You just need both controllers on, then `run`.
10
11 ## What this install is, and why the setup looks the way it does
12
13 Your BL2 is the **native Aspyr Linux build** (a 2012, 32-bit `Borderlands2` ELF) —
14 not the Windows/Proton version. Getting split screen out of it took solving three
15 real problems, all handled by the script:
16
17 1. **The binary is too old for modern system libs** → it's launched inside the
18    **Steam scout runtime** (`ubuntu12_32/steam-runtime/run.sh`), which ships the
19    old libraries it expects.
20 2. **gbe_fork (the modern Goldberg) segfaults this binary** → we use the
21    **classic Mr_Goldberg 0.2.5** emulator instead (`goldberg/libsteam_api.so`).
22    gbe_fork's experimental *and* regular builds both crash it at a fixed address
23    right after Steam init; classic goldberg works.
24 3. **The old binary crashes if the emu returns unexpected Steam interfaces** → at
25    setup we extract the exact interface versions from the game's original
26    `libsteam_api.so` into each copy's `steam_settings/steam_interfaces.txt`.
27
28 A Windows **proton** mode is also supported (see below); the script auto-detects
29 which build is installed.
30
31 ## Playing (native — your current install)
32
33 ```
34 cd /home/max/Games/bl2-split
35 # 1. QUIT STEAM COMPLETELY (see why below)
36 # 2. turn on BOTH controllers (the wireless 360 pad idle-sleeps — wake it)
37 ./bl2-splitscreen.sh run
38 ```
39
40 > **Quit Steam first.** While Steam runs, Steam Input creates *virtual* gamepads
41 > that the game grabs instead of the real pads — which breaks per-player controller
42 > isolation (and can leave input not working). Goldberg replaces Steam, so you don't
43 > need it running. The script warns and pauses if it detects Steam.
44
45 - Two game windows open (no gamescope). During the intro logos they look
46   unaligned — that's expected; **~45 s in (after the splash) they snap to their
47   halves.** The delay is because the game resizes itself during the splash, so
48   tiling earlier just gets overridden.
49 - The split is computed in **logical** pixels (your 2560×1440 panel at 125% scale
50   = 2048×1152 logical → two 1024×1152 halves), so it lands right despite scaling.
51 - **Player 1** (Xbox Series S|X pad): *Play → host over LAN*.
52 - **Player 2** (Xbox 360 wireless pad): *Play → Join → pick the LAN game*.
53 - Each window is pinned to one controller and, thanks to SDL background events,
54   responds even when the other window has focus.
55 - Re-tile any time (e.g. after both reach the menu): `./bl2-splitscreen.sh tile`.
56 - Snapping too early (still on the splash)? Raise the wait: `SPLASH_WAIT=70 ./bl2-splitscreen.sh run`.
57 - `Ctrl-C` in the terminal kills both instances.
58
59 If you change hardware or want to rebuild the copies: `./bl2-splitscreen.sh setup`.
60
61 ## Commands
62
63 | Command | Does |
64 |---|---|
65 | `./bl2-splitscreen.sh check` | verify prerequisites for the detected mode |
66 | `./bl2-splitscreen.sh setup` | build the two patched game copies (already done) |
67 | `./bl2-splitscreen.sh run`   | launch both halves + tile |
68 | `./bl2-splitscreen.sh tile`  | (re)tile the two windows on KDE |
69 | `./bl2-splitscreen.sh clean` | remove generated copies/saves (real game untouched) |
70
71 ## How each piece works
72
73 | Concern | Solution |
74 |---|---|
75 | Two instances at once | Each copy uses classic Mr_Goldberg (no Steam needed); they LAN together |
76 | Runs the ancient binary | Launched via the Steam scout runtime |
77 | No crash on Steam init | `steam_interfaces.txt` extracted from the original lib, per copy |
78 | Separate saves | Per-player `HOME` (`p1/home`, `p2/home`) — also isolates each `~/.steam` |
79 | Two different LAN players | `force_account_name.txt` + `force_steamid.txt` per copy |
80 | Half-screen windows | Game runs windowed at the **logical** half size (`-ResX/-ResY` + config), **no gamescope** — gamescope doesn't pass raw controllers to nested clients, so the SDL game would see no pad |
81 | Correct size on a scaled display | Split computed from KDE's **logical** screen size (physical ÷ scale), auto-detected via `kscreen-doctor`. Using physical px tiles at the wrong fraction (2/3 + 1/3 at 125%) |
82 | Both windows get input | `SDL_JOYSTICK_ALLOW_BACKGROUND_EVENTS=1` (SDL otherwise ignores the pad of an unfocused window) |
83 | One controller per instance | `bwrap` masks the other pad's `/dev/input` nodes — reliable only with Steam quit (else Steam Input's virtual pads leak through) |
84 | Side-by-side placement | KWin script (`qdbus6`) sizes each window to a logical half + removes borders, fired **after** the splash so the game has stopped resizing itself |
85 | No 13 GB duplication | `cp -as` symlink-mirror; only the Steam API lib is a real copy |
86
87 > The game statically links an **old SDL2** (pre-2.0.9), so it reads controllers via
88 > SDL/udev, needs `ALLOW_BACKGROUND_EVENTS` for split focus, and can't use SDL's
89 > newer per-VID/PID filtering — hence bwrap for isolation.
90
91 ## Switching to the Windows / Proton version (optional)
92
93 If the native port misbehaves, the Windows build under Proton is an alternative:
94
95 1. Steam → **Borderlands 2 → Properties → Compatibility →** *Force a specific
96    Steam Play compatibility tool* → e.g. Proton Experimental.
97 2. Steam re-downloads the **Windows** depot (`Borderlands2.exe`).
98 3. Re-run the script — it auto-detects **proton** mode and uses the already-staged
99    Windows `goldberg/steam_api.dll` (gbe_fork) via `umu-run`:
100    ```
101    ./bl2-splitscreen.sh check    # mode: proton
102    ./bl2-splitscreen.sh setup && ./bl2-splitscreen.sh run
103    ```
104    First launch downloads Proton + builds each Wine prefix (slow, one time).
105
106 > Native and Windows builds share the same folder, so only one is installed at a
107 > time. Switching modes = switching what Steam has downloaded.
108
109 ## Troubleshooting
110
111 - **They don't see each other on LAN:** let Player 1 host first (the script starts
112   it ~10 s earlier). Both use classic goldberg's LAN broadcast; each player's own
113   `~/.steam`/config is isolated via the per-player HOME. If needed, check each
114   copy's `steam_settings/`.
115 - **Controllers don't work at all:** make sure **Steam is fully quit** before `run`
116   (Steam Input's virtual pads block the real ones). Native runs the game *without*
117   gamescope for this reason — gamescope hides raw controllers from nested clients.
118 - **Both pads control both screens / wrong window got a controller:** almost always
119   Steam still running (virtual pads bypass the `bwrap` mask). Quit Steam. Isolation
120   is `ISOLATION=bwrap` (default); masking real pad nodes only works with Steam off.
121 - **Halves look uneven (one fills ~2/3, the other ~1/3):** display-scaling mismatch
122   — the script now auto-detects the *logical* screen size (`kscreen-doctor`), but if
123   detection fails set it explicitly, e.g. `SCREEN_W=2048 SCREEN_H=1152 ./bl2-splitscreen.sh run`.
124 - **Windows tile while still on the splash / too early:** raise `SPLASH_WAIT`
125   (seconds), e.g. `SPLASH_WAIT=70 ./bl2-splitscreen.sh run`, or just re-run
126   `./bl2-splitscreen.sh tile` once both are at the menu.
127 - **A game crashes on launch:** confirm `./bl2-splitscreen.sh check` is all green;
128   the native path needs the scout runtime + classic goldberg + `steam_interfaces.txt`
129   (all set up by `setup`).
130 - **Reset everything:** `./bl2-splitscreen.sh clean`.
131
132 ## Files
133
134 ```
135 bl2-split/
136 ├── bl2-splitscreen.sh          the launcher
137 ├── goldberg/
138 │   ├── libsteam_api.so         classic Mr_Goldberg 0.2.5, 32-bit (native mode)
139 │   └── steam_api.dll           gbe_fork, Windows 32-bit (proton mode)
140 ├── p1/ , p2/                   per-player: game/ (symlink mirror) + home/ (saves)
141 └── README.md
142 ```