From e02b2f885476eb1553e72ac914bc8c2ea80886c8 Mon Sep 17 00:00:00 2001 From: Max Vilimpoc Date: Mon, 13 Jul 2026 10:14:58 +0200 Subject: [PATCH] Add kill command, fix Ctrl-C teardown, speed up 2nd instance startup --- .gitignore | 3 +++ README.md | 9 ++++++++- bl2-splitscreen.sh | 41 +++++++++++++++++++++++++++++++++++++---- 3 files changed, 48 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 3451bd5..65ffd21 100644 --- a/.gitignore +++ b/.gitignore @@ -10,5 +10,8 @@ !/p1/.gitkeep !/p2/.gitkeep +# Shared DXVK shader cache (generated) +/dxvk-cache/ + # Logs and scratch *.log diff --git a/README.md b/README.md index 2ce0f74..bf009c7 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,8 @@ their own controller, save, and screen. Tested on **Arch + KDE Plasma 6 (Wayland | `./bl2-splitscreen.sh setup` | fetch Goldberg + build `p1/`, `p2/` | | `./bl2-splitscreen.sh run` | launch both instances + place windows | | `./bl2-splitscreen.sh tile` | re-place the two windows | -| `./bl2-splitscreen.sh clean` | remove `p1/`, `p2/` (copies + saves + prefixes) | +| `./bl2-splitscreen.sh kill` | terminate all running Borderlands 2 instances | +| `./bl2-splitscreen.sh clean` | kill instances, then remove `p1/`, `p2/` (copies + saves + prefixes) | Useful env overrides: `MODE=native|proton`, `DISPLAY_MODE=dual|split`, `ISOLATION=bwrap|sdl`, `SPLASH_WAIT=`, `STAGGER=`. @@ -117,6 +118,12 @@ So another person clones the repo, forces Proton on their own BL2 in Steam, runs `rm p{1,2}/game/Binaries/Win32/steam_settings/configs.main.ini` - **They don't see each other on LAN:** Player 1 hosts first (the script staggers launches). Discovery uses `custom_broadcasts.txt` (localhost). +- **The 2nd instance takes ages to reach the menu:** the two share a DXVK shader + cache (`dxvk-cache/`) so the 2nd reuses the 1st's shaders; the first-ever run + still compiles them. If it's still slow, raise the gap between launches so the 1st + is fully loaded before the 2nd starts: `STAGGER=45 ./bl2-splitscreen.sh run`. +- **Ctrl-C / kill left something running:** `./bl2-splitscreen.sh kill` tears down + the whole game + Proton/Wine tree. - **A window won't sit on its monitor:** re-run `./bl2-splitscreen.sh tile`; raise `SPLASH_WAIT` if it fires before the game settles. - **Reset everything:** `./bl2-splitscreen.sh clean` (removes copies + saves; the diff --git a/bl2-splitscreen.sh b/bl2-splitscreen.sh index 2b1a7ce..ed4e040 100755 --- a/bl2-splitscreen.sh +++ b/bl2-splitscreen.sh @@ -339,7 +339,12 @@ launch_player() { # $1=n $2=pad-node $3=vidpid -> sets LAUNCHED_PID else wd="$pg/Binaries/Win32" patch_proton_config "$BASE/p$n/prefix" # skip intro movies (if prefix exists) - env=( "WINEPREFIX=$BASE/p$n/prefix" "GAMEID=0" "STORE=none" ) + mkdir -p "$BASE/dxvk-cache" + env=( "WINEPREFIX=$BASE/p$n/prefix" "GAMEID=0" "STORE=none" + "UMU_RUNTIME_UPDATE=0" # skip umu's startup update check + # Shared D3D shader cache: the 2nd instance reuses shaders the 1st already + # compiled instead of recompiling them while the 1st is using the GPU. + "DXVK_STATE_CACHE_PATH=$BASE/dxvk-cache" ) # Only use the SDL VID/PID filter in "sdl" mode. With bwrap masking it is # redundant AND can over-filter (it wrongly dropped the 360 pad), so skip it. [ "$ISOLATION" = sdl ] && env+=( "SDL_GAMECONTROLLER_IGNORE_DEVICES_EXCEPT=$vidpid" ) @@ -434,12 +439,39 @@ cmd_run() { say "${c_dim}Windows settle onto $where ~${SPLASH_WAIT}s in (after the splash)." say "Re-place any time with: ./bl2-splitscreen.sh tile${c_rst}" say ""; say "Press Ctrl-C to kill both instances." - trap 'kill "$pid1" "$pid2" 2>/dev/null' INT TERM + # Killing $pid1/$pid2 only hits the top of each tree; the game runs deeper inside + # umu/pressure-vessel and survives. kill_instances tears down the whole tree. + trap 'echo; kill_instances; exit 130' INT TERM wait "$pid1" "$pid2" } +# ------------------------------------------------------------------ kill ---- +# Terminate every Borderlands 2 process we launched (game exe + umu/Proton/Wine +# tree for our prefixes), SIGTERM first then SIGKILL. Scoped to our BASE dir so it +# won't touch unrelated Wine apps. +kill_instances() { + local sig + for sig in TERM KILL; do + pkill -"$sig" -f 'Borderlands2\.exe' 2>/dev/null # proton game + pkill -"$sig" -x 'Borderlands2' 2>/dev/null # native game + pkill -"$sig" -f "$BASE/p[12]/" 2>/dev/null # umu/proton/wine for our copies+prefixes + [ "$sig" = TERM ] && sleep 2 + done +} + +cmd_kill() { + # Match the process NAME (comm) as a substring, not the full cmdline - otherwise + # helper shells that merely have the game path in their args get counted. This + # matches "Borderlands2.ex" (Proton, 15-char truncated) and "Borderlands2". + pgrep 'Borderlands2' >/dev/null || { ok "No Borderlands 2 instances running."; return 0; } + say "Killing Borderlands 2 instances..." + kill_instances + local left; left=$(pgrep -c 'Borderlands2' 2>/dev/null || echo 0) + [ "$left" = 0 ] && ok "All instances killed." || warn "$left process(es) still lingering." +} + # ------------------------------------------------------------------ clean --- -cmd_clean() { say "Removing generated copies/saves (real game untouched)..."; rm -rf "$BASE/p1" "$BASE/p2"; ok "Done."; } +cmd_clean() { cmd_kill; say "Removing generated copies/saves (real game untouched)..."; rm -rf "$BASE/p1" "$BASE/p2"; ok "Done."; } case "${1:-}" in fetch) cmd_fetch ;; @@ -447,6 +479,7 @@ case "${1:-}" in setup) cmd_setup ;; run) cmd_run ;; tile) cmd_tile ;; + kill) cmd_kill ;; clean) cmd_clean ;; - *) say "Usage: $0 {fetch|check|setup|run|tile|clean} (MODE=native|proton to force)"; exit 1 ;; + *) say "Usage: $0 {fetch|check|setup|run|tile|kill|clean} (MODE=native|proton to force)"; exit 1 ;; esac -- 2.48.2