]> vilimpoc.org git repositories - bl2-split/blame - README.md
Document haveged entropy fix and in-game-quit workaround
[bl2-split] / README.md
CommitLineData
948cce3b 1# Borderlands 2 — 2-player split-screen / dual-monitor co-op on Linux
cb05cf8e 2
948cce3b
MV
3Runs **two local instances** of Borderlands 2 that connect to each other over
4Goldberg's emulated Steam LAN, so two people can play co-op on one PC — each with
5their own controller, save, and screen. Tested on **Arch + KDE Plasma 6 (Wayland)**.
cb05cf8e 6
948cce3b
MV
7- **Two monitors:** one instance fullscreen on each (auto-detected).
8- **One monitor:** side-by-side split.
9- Each Xbox controller drives only its own instance.
cb05cf8e 10
948cce3b
MV
11> BL2 has no native PC split-screen; this launches two copies networked over LAN.
12> Only legitimate because you own the game. No game files or saves are committed here.
cb05cf8e 13
948cce3b 14![Two Borderlands 2 instances running co-op across two monitors, each on its own main menu in the shared LAN lobby with per-player Xbox controller prompts](sxs.jpg)
cb05cf8e 15
948cce3b 16## Requirements
cb05cf8e 17
948cce3b
MV
18- **Borderlands 2 installed via Steam, forced to the Windows build under Proton**
19 (see setup step 1). The native Linux (Aspyr) build is supported as a fallback but
20 is crash-prone with two instances — Proton is the recommended path.
21- Packages: `umu-launcher`, `gamescope` *(optional)*, `qt6-tools` (for `qdbus6`),
22 `bubblewrap`, `libarchive` (`bsdtar`), `curl`, `binutils` (`strings`).
23 ```
24 sudo pacman -S umu-launcher qt6-tools bubblewrap libarchive curl binutils
25 ```
5765b872
MV
26- **Recommended:** an entropy daemon so the second instance doesn't stall on
27 startup waiting for randomness (see Troubleshooting):
28 ```
29 sudo pacman -S haveged && sudo systemctl enable --now haveged
30 ```
948cce3b 31- Two Xbox controllers (any two distinguishable pads).
cb05cf8e 32
948cce3b 33## Setup
cb05cf8e 34
948cce3b
MV
351. **Point Steam at the Windows build.** Steam → *Borderlands 2 → Properties →
36 Compatibility →* tick **"Force the use of a specific Steam Play compatibility
37 tool"** → pick **Proton Experimental** (or a stable Proton). Steam re-downloads
38 the Windows depot. (To use the native Linux build instead, skip this — the script
39 auto-detects which is installed.)
40
412. **Build the two copies:**
42 ```
43 cd bl2-split
44 ./bl2-splitscreen.sh check # verifies prerequisites; shows detected mode
45 ./bl2-splitscreen.sh setup # downloads Goldberg + builds p1/ and p2/
46 ```
47 `setup` auto-downloads the Goldberg emulator (it is **not** committed to this
48 repo) and builds two symlink-mirror copies of the game with per-player Steam
49 identities. First `run` also makes umu download Proton + build each prefix (slow,
50 one time).
cb05cf8e 51
948cce3b
MV
523. **Play** (turn on both controllers first):
53 ```
54 ./bl2-splitscreen.sh run
55 ```
56 With two monitors each game opens fullscreen on its own display; with one, they
57 tile side-by-side. In-game: **Player 1** *Play → host over LAN*; **Player 2**
58 *Play → Join → pick the LAN game*. `Ctrl-C` kills both.
cb05cf8e
MV
59
60## Commands
61
62| Command | Does |
63|---|---|
948cce3b
MV
64| `./bl2-splitscreen.sh fetch` | download the Goldberg emulator into `goldberg/` |
65| `./bl2-splitscreen.sh check` | verify prerequisites; print the detected mode |
66| `./bl2-splitscreen.sh setup` | fetch Goldberg + build `p1/`, `p2/` |
67| `./bl2-splitscreen.sh run` | launch both instances + place windows |
68| `./bl2-splitscreen.sh tile` | re-place the two windows |
e02b2f88
MV
69| `./bl2-splitscreen.sh kill` | terminate all running Borderlands 2 instances |
70| `./bl2-splitscreen.sh clean` | kill instances, then remove `p1/`, `p2/` (copies + saves + prefixes) |
948cce3b
MV
71
72Useful env overrides: `MODE=native|proton`, `DISPLAY_MODE=dual|split`,
73`ISOLATION=bwrap|sdl`, `SPLASH_WAIT=<secs>`, `STAGGER=<secs>`.
cb05cf8e 74
948cce3b 75## How it works
cb05cf8e
MV
76
77| Concern | Solution |
78|---|---|
948cce3b
MV
79| Two instances at once | Each copy uses **Goldberg** (`steam_api.dll`) instead of real Steam; they connect over emulated LAN |
80| Goldberg actually loads | The `.exe` is copied **real** (not symlinked) so Wine loads DLLs from our dir, not the real install's `steam_api.dll` |
81| Two different LAN players | Per-copy `force_account_name.txt` + `force_steamid.txt` |
82| No startup crash | `steam_interfaces.txt` extracted from the original Steam lib per copy |
83| Separate saves | Each instance has its own Proton prefix (`p1/prefix`, `p2/prefix`) |
84| Co-op finds each other | Goldberg `custom_broadcasts.txt` → `127.0.0.1` (broadcast doesn't cross the two Proton containers) |
85| Skips slow "Creating online session" | Goldberg `configs.main.ini` → `offline=1` |
86| Windowed at the right size | `-windowed -ResX -ResY`; **no gamescope** (it hides raw controllers from nested clients) |
87| One controller per instance | **bwrap** masks the other pad's `/dev/input` nodes (the Xbox pads are evdev-only, no hidraw) |
88| Window placement | KWin script via `qdbus6` — one monitor each (dual) or side-by-side (single) |
89| No intro-logo wait | Intro movies disabled in each prefix's `WillowEngine.ini` |
90| No 13 GB duplication | `cp -as` symlink-mirror; only `steam_api.dll` + the `.exe` are real copies |
91
92## What's in git (and what isn't)
93
94**Committed** (enough for anyone to reproduce):
95```
96bl2-splitscreen.sh the launcher/setup script
97README.md this file
98.gitignore
99goldberg/.gitkeep empty dir; setup downloads binaries into it
100p1/.gitkeep p2/.gitkeep
101```
cb05cf8e 102
948cce3b
MV
103**Never committed** (`.gitignore`):
104- `goldberg/steam_api.dll`, `goldberg/libsteam_api.so` — the Goldberg emulator
105 binaries. They implement Steam's proprietary API, so they aren't redistributed
106 here; `setup` downloads them from the upstream releases (gbe_fork / Mr_Goldberg).
107- `p1/`, `p2/` (except `.gitkeep`) — the game copies, **your save games**, and Wine
108 prefixes. Machine-specific and large.
109- `*.log`.
cb05cf8e 110
948cce3b
MV
111So another person clones the repo, forces Proton on their own BL2 in Steam, runs
112`./bl2-splitscreen.sh setup`, and everything else is pulled/generated locally.
cb05cf8e 113
948cce3b 114## Troubleshooting
cb05cf8e 115
948cce3b
MV
116- **Both pads control both screens / keyboard controls both:** the games read input
117 globally. Controllers are isolated by `bwrap` device-masking (default). Keyboard &
118 mouse are *not* isolated — use a controller per player; kb/mouse is only for menus.
119- **A pad drives the wrong screen or none:** ensure `ISOLATION=bwrap` (default). If
120 **Steam is running**, its Steam Input virtual pads can interfere — quit Steam.
121- **Stuck on "Creating online session":** should be quick with `offline=1` (set by
122 setup). If a co-op *join* ever breaks, remove the offline setting:
123 `rm p{1,2}/game/Binaries/Win32/steam_settings/configs.main.ini`
124- **They don't see each other on LAN:** Player 1 hosts first (the script staggers
125 launches). Discovery uses `custom_broadcasts.txt` (localhost).
5765b872
MV
126- **The 2nd instance takes ages to reach the menu — and speeds up when you jiggle
127 the mouse:** classic **entropy starvation** — something in the Wine/Goldberg/crypto
128 path blocks on `/dev/random` waiting for randomness, and mouse movement feeds the
129 pool. Fix it with an entropy daemon (also in Requirements):
130 `sudo pacman -S haveged && sudo systemctl enable --now haveged`.
131 The two instances also share a DXVK shader cache (`dxvk-cache/`) so the 2nd reuses
132 the 1st's shaders; if still slow, raise the launch gap: `STAGGER=45 ./bl2-splitscreen.sh run`.
133- **In-game "Quit Borderlands 2 → Yes" does nothing / hangs:** the game's shutdown
134 path stalls under Goldberg (Steam-networking cleanup, worse with offline mode).
135 Don't use in-game Quit — close with **`./bl2-splitscreen.sh kill`** or **Ctrl-C**
136 in the run terminal (safe: you're at the menu, nothing is saving).
e02b2f88
MV
137- **Ctrl-C / kill left something running:** `./bl2-splitscreen.sh kill` tears down
138 the whole game + Proton/Wine tree.
948cce3b
MV
139- **A window won't sit on its monitor:** re-run `./bl2-splitscreen.sh tile`; raise
140 `SPLASH_WAIT` if it fires before the game settles.
141- **Reset everything:** `./bl2-splitscreen.sh clean` (removes copies + saves; the
142 real Steam install is untouched).
143
144## Native (Aspyr Linux) fallback
145
146If Steam has the native Linux build installed, the script auto-detects `native` mode:
147it uses the **classic Mr_Goldberg** `.so` (gbe_fork crashes that old binary), runs
148inside the Steam scout runtime, and isolates controllers the same way. It works, but
149the second instance is prone to crashing — prefer the Proton path.