MODE="$(detect_mode)"
[ "$MODE" = unknown ] && die "Cannot find BL2 - neither $NATIVE_BIN nor $WIN_EXE_REL under $GAME_DIR"
if [ -z "$ISOLATION" ]; then ISOLATION=bwrap; fi # device-masking works for both modes
-GOLDBERG_SO="$BASE/goldberg/libsteam_api.so" # native
-GOLDBERG_DLL="$BASE/goldberg/steam_api.dll" # proton
+GOLDBERG_SO="$BASE/goldberg/libsteam_api.so" # native (classic Mr_Goldberg)
+GOLDBERG_DLL="$BASE/goldberg/steam_api.dll" # proton (gbe_fork)
+
+# Goldberg emulator downloads (NOT committed to git - fetched by `fetch`). Pinned
+# to known-good releases; override via env if these ever move.
+GBE_FORK_TAG="${GBE_FORK_TAG:-release-2026_05_30}"
+GBE_FORK_WIN_URL="${GBE_FORK_WIN_URL:-https://github.com/Detanup01/gbe_fork/releases/download/$GBE_FORK_TAG/emu-win-release.7z}"
+CLASSIC_GOLDBERG_URL="${CLASSIC_GOLDBERG_URL:-https://gitlab.com/Mr_Goldberg/goldberg_emulator/uploads/2524331e488ec6399c396cf48bbe9903/Goldberg_Lan_Steam_Emu_v0.2.5.zip}"
resolve_pad() { local m; for m in $1; do [ -e "$m" ] && { readlink -f "$m"; return; }; done; }
+# --------------------------------------------------------------- fetch deps -
+# Download the Goldberg emulator binaries (kept out of git). Proton needs the
+# gbe_fork Windows steam_api.dll; native needs the classic Mr_Goldberg Linux .so.
+cmd_fetch() { # downloads the Goldberg binary the detected MODE needs
+ command -v bsdtar >/dev/null || die "bsdtar missing (sudo pacman -S libarchive)"
+ command -v curl >/dev/null || die "curl missing (sudo pacman -S curl)"
+ mkdir -p "$BASE/goldberg"
+ local tmp; tmp="$(mktemp -d)"; trap 'rm -rf "$tmp"' RETURN
+
+ if [ "$MODE" = proton ]; then
+ if [ -f "$GOLDBERG_DLL" ]; then ok "gbe_fork steam_api.dll already present"; return; fi
+ say "Downloading gbe_fork (Windows) $GBE_FORK_TAG ..."
+ curl -fsSL -o "$tmp/win.7z" "$GBE_FORK_WIN_URL" || die "download failed: $GBE_FORK_WIN_URL"
+ bsdtar -xf "$tmp/win.7z" -C "$tmp" release/experimental/x86/steam_api.dll \
+ || die "could not extract steam_api.dll from the archive"
+ cp "$tmp/release/experimental/x86/steam_api.dll" "$GOLDBERG_DLL"
+ file "$GOLDBERG_DLL" | grep -qi "PE32 .*i386" && ok "steam_api.dll (proton) fetched" \
+ || die "fetched steam_api.dll is not the expected 32-bit PE"
+ else
+ if [ -f "$GOLDBERG_SO" ]; then ok "classic goldberg libsteam_api.so already present"; return; fi
+ say "Downloading classic Mr_Goldberg (Linux) ..."
+ curl -fsSL -o "$tmp/lin.zip" "$CLASSIC_GOLDBERG_URL" || die "download failed: $CLASSIC_GOLDBERG_URL"
+ bsdtar -xf "$tmp/lin.zip" -C "$tmp" linux/x86/libsteam_api.so \
+ || die "could not extract libsteam_api.so from the archive"
+ cp "$tmp/linux/x86/libsteam_api.so" "$GOLDBERG_SO"
+ file "$GOLDBERG_SO" | grep -q "ELF 32-bit" && ok "libsteam_api.so (native) fetched" \
+ || die "fetched libsteam_api.so is not the expected 32-bit ELF"
+ fi
+}
+
# ------------------------------------------------------------------ check ---
cmd_check() {
local fail=0
# other via UDP broadcast, so co-op hangs at "Creating online session". Tell the
# emu to send discovery directly to localhost so they always find each other.
printf '127.0.0.1\n' > "$ss/custom_broadcasts.txt"
+ # BL2 stalls on "Creating online session" waiting on (unreachable) online Steam
+ # servers; offline mode makes the emu report Steam offline so it skips that wait
+ # and goes to LAN. LAN co-op still works. Remove this file if it ever breaks join.
+ cat > "$ss/configs.main.ini" <<EOF
+[main::connectivity]
+offline=1
+EOF
}
# Old games hard-crash if the emu returns interfaces they don't expect. Extract
}
cmd_setup() {
+ cmd_fetch # download Goldberg if not present
REQUIRE_PADS=0 cmd_check || die "check failed - resolve the above before setup"
say ""; say "== Building player copies ($MODE) =="
build_player 1 "Player1" "76561197960287930"
cmd_clean() { say "Removing generated copies/saves (real game untouched)..."; rm -rf "$BASE/p1" "$BASE/p2"; ok "Done."; }
case "${1:-}" in
+ fetch) cmd_fetch ;;
check) cmd_check ;;
setup) cmd_setup ;;
run) cmd_run ;;
tile) cmd_tile ;;
clean) cmd_clean ;;
- *) say "Usage: $0 {check|setup|run|tile|clean} (MODE=native|proton to force)"; exit 1 ;;
+ *) say "Usage: $0 {fetch|check|setup|run|tile|clean} (MODE=native|proton to force)"; exit 1 ;;
esac