Expand local_machine docs and automation for connectivity, games, and ops.
Add proxy/VPN/telegram launchd and emergency runbooks; reorganize apps docs; document JA3 CrossOver runbook and Wine troubleshooting; add GOG/HoMM game scripts, disk cleanup guides, and gitea push-via-proxy helper. Ignore temp/. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
1
scripts/games/gog/.gitignore
vendored
Normal file
1
scripts/games/gog/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
bottle.env
|
||||
64
scripts/games/gog/README.md
Normal file
64
scripts/games/gog/README.md
Normal file
@@ -0,0 +1,64 @@
|
||||
# GOG web-installer (без Steam)
|
||||
|
||||
Отдельный Whisky-bottle. Скрипты **не** трогают HoMM-OldenEra, Steam, `start.sh play`, дампы Steam.
|
||||
|
||||
Антипаттерны (swap, winedbg, «20 GB»): [docs/games/TROUBLESHOOTING.md](../../../docs/games/TROUBLESHOOTING.md#антипаттерны-не-делать).
|
||||
|
||||
## Один раз
|
||||
|
||||
```bash
|
||||
# 1) Whisky → New Bottle → Windows 10 64-bit → имя «GOG-Install»
|
||||
bash ~/code/local_machine/scripts/games/gog/list-bottles.sh
|
||||
bash ~/code/local_machine/scripts/games/gog/use-bottle.sh <UUID> GOG-Install
|
||||
|
||||
# 2) Подготовка bottle (или одной командой: bash gog/install-all.sh /path/stub.exe)
|
||||
bash ~/code/local_machine/scripts/games/gog/create-bottle.sh GOG-Install # если bottle ещё нет
|
||||
bash ~/code/local_machine/scripts/games/gog/setup-bottle.sh
|
||||
bash ~/code/local_machine/scripts/games/gog/install-gdiplus.sh # обязательно (~900MB скачивание)
|
||||
brew install cabextract
|
||||
bash ~/code/local_machine/scripts/games/gog/install-corefonts.sh
|
||||
```
|
||||
|
||||
## Запуск web-stub
|
||||
|
||||
```bash
|
||||
bash ~/code/local_machine/scripts/games/gog/run-web-installer.sh \
|
||||
~/path/to/GOG_Galaxy_Jagged_Alliance_3.exe
|
||||
```
|
||||
|
||||
Лог: `/tmp/gog-web-installer-GOG-Install.log`
|
||||
|
||||
## Jagged Alliance 3 **без GOG Galaxy** (канон)
|
||||
|
||||
**Runbook (установка + графика + RCA + антипаттерны):** [JA3_RUNBOOK.md](../../../docs/games/JA3_RUNBOOK.md)
|
||||
|
||||
```bash
|
||||
# Установка (Whisky GOG-Install): 5 частей offline backup в ~/Games/
|
||||
bash ~/code/local_machine/scripts/games/gog/install-ja3-innoextract.sh
|
||||
bash ~/code/local_machine/scripts/games/gog/finish-ja3-layout.sh
|
||||
|
||||
# Запуск (CrossOver D3DMetal — один раз setup, затем каждый раз run):
|
||||
brew install --cask crossover
|
||||
bash ~/code/local_machine/scripts/games/gog/setup-ja3-crossover.sh
|
||||
bash ~/code/local_machine/scripts/games/gog/run-ja3-crossover.sh
|
||||
```
|
||||
|
||||
| Скрипт | Назначение |
|
||||
|--------|------------|
|
||||
| `install-ja3-innoextract.sh` | **Канон установки** (Whisky) |
|
||||
| `finish-ja3-layout.sh` | CommonLua, реестр GOG |
|
||||
| `setup-ja3-crossover.sh` | CrossOver bottle JA3-GOG + clone игры |
|
||||
| **`run-ja3-crossover.sh`** | **Канон запуска** (D3D12 / D3DMetal) |
|
||||
| `run-ja3.sh` | Whisky — **графика D3D12 не работает** (см. runbook) |
|
||||
|
||||
Galaxy / web-stub — **не использовать** для JA3 ([GOG_GALAXY_7H_RCA.md](../../../docs/games/GOG_GALAXY_7H_RCA.md)).
|
||||
|
||||
## Сброс только GOG
|
||||
|
||||
```bash
|
||||
bash ~/code/local_machine/scripts/games/gog/reset.sh
|
||||
```
|
||||
|
||||
## Устаревшее (не использовать для GOG)
|
||||
|
||||
- `setup-wine-bottle.sh` / bottle **HoMM-OldenEra** — там Steam и общий префикс.
|
||||
6
scripts/games/gog/bottle.env.example
Normal file
6
scripts/games/gog/bottle.env.example
Normal file
@@ -0,0 +1,6 @@
|
||||
# Скопируйте в bottle.env и укажите отдельный Whisky-bottle (без Steam/HoMM).
|
||||
# Создайте в Whisky: New Bottle → Windows 10 64-bit → имя «GOG-Install»
|
||||
# UUID: Whisky → bottle → правый клик / About, или: bash list-bottles.sh
|
||||
|
||||
BOTTLE_ID=00000000-0000-0000-0000-000000000000
|
||||
BOTTLE_NAME=GOG-Install
|
||||
70
scripts/games/gog/collect-gog-logs-7h.sh
Executable file
70
scripts/games/gog/collect-gog-logs-7h.sh
Executable file
@@ -0,0 +1,70 @@
|
||||
#!/usr/bin/env bash
|
||||
# Собрать GOG/Whisky логи за N часов (по умолчанию 7) + timeline событий.
|
||||
set -euo pipefail
|
||||
GOG_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
# shellcheck source=config.sh
|
||||
source "${GOG_DIR}/config.sh"
|
||||
|
||||
HOURS="${1:-7}"
|
||||
OUT="${2:-${HOME}/code/local_machine/temp/gog-logs-${HOURS}h-$(date +%Y%m%d-%H%M%S)}"
|
||||
GALOG="${BOTTLE_DIR}/drive_c/ProgramData/GOG.com/Galaxy/logs"
|
||||
mkdir -p "${OUT}"
|
||||
|
||||
cp -R "${GALOG}" "${OUT}/galaxy-logs" 2>/dev/null || true
|
||||
mkdir -p "${OUT}/whisky-logs"
|
||||
cp "${HOME}/Library/Logs/com.franke.Whisky"/*.log "${OUT}/whisky-logs/" 2>/dev/null || true
|
||||
[[ -f "/tmp/gog-galaxy-client-${BOTTLE_NAME}.log" ]] && cp "/tmp/gog-galaxy-client-${BOTTLE_NAME}.log" "${OUT}/" || true
|
||||
|
||||
df -h "$(gog_data_volume_path)" >"${OUT}/disk.txt"
|
||||
pgrep -fl 'Galaxy|GOG|explorer.*GOG' >"${OUT}/processes-now.txt" 2>/dev/null || echo "(none)" >"${OUT}/processes-now.txt"
|
||||
plutil -p "${BOTTLE_DIR}/Metadata.plist" >"${OUT}/metadata.plist.txt" 2>/dev/null || true
|
||||
[[ -f "${BOTTLE_DIR}/Program Settings/GalaxyClient.exe.plist" ]] && \
|
||||
plutil -p "${BOTTLE_DIR}/Program Settings/GalaxyClient.exe.plist" >"${OUT}/GalaxyClient.exe.plist.txt"
|
||||
|
||||
python3 <<PY
|
||||
import re
|
||||
from datetime import datetime, timedelta
|
||||
from pathlib import Path
|
||||
|
||||
hours = int("${HOURS}")
|
||||
out = Path("${OUT}")
|
||||
cutoff = datetime.now() - timedelta(hours=hours)
|
||||
pat = re.compile(r"^(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3})")
|
||||
keys = (
|
||||
"will continue", "will exit", "Second client", "Showing login", "foreground",
|
||||
"Deelevate", "Fatal", "deelevated", "Reloaded without", "Command-line parameters",
|
||||
"parent window", "eglInitialize",
|
||||
)
|
||||
logdir = Path("${GALOG}")
|
||||
lines = [f"# GOG Galaxy timeline (last {hours}h)\n", f"cutoff_local={cutoff.isoformat()}\n", f"bottle={Path('${BOTTLE_DIR}').name}\n\n"]
|
||||
for fn in sorted(logdir.glob("*.log")):
|
||||
lines.append(f"## {fn.name}\n")
|
||||
for line in fn.read_text(errors="replace").splitlines():
|
||||
m = pat.match(line)
|
||||
if not m:
|
||||
continue
|
||||
try:
|
||||
ts = datetime.strptime(m.group(1), "%Y-%m-%d %H:%M:%S.%f")
|
||||
except ValueError:
|
||||
continue
|
||||
if ts < cutoff:
|
||||
continue
|
||||
if any(k.lower() in line.lower() for k in keys):
|
||||
lines.append(line[:600] + "\n")
|
||||
lines.append("\n")
|
||||
(out / "timeline.md").write_text("".join(lines), encoding="utf-8")
|
||||
PY
|
||||
|
||||
cat >"${OUT}/README.txt" <<EOF
|
||||
GOG log bundle (${HOURS}h)
|
||||
Generated: $(date)
|
||||
Bottle: ${BOTTLE_NAME} (${BOTTLE_ID})
|
||||
|
||||
Read first: timeline.md
|
||||
Galaxy logs: galaxy-logs/
|
||||
Whisky: whisky-logs/
|
||||
EOF
|
||||
|
||||
echo "OK: ${OUT}"
|
||||
echo " timeline.md — события за ${HOURS}ч"
|
||||
ls -la "${OUT}"
|
||||
38
scripts/games/gog/collect-setup-rca.sh
Executable file
38
scripts/games/gog/collect-setup-rca.sh
Executable file
@@ -0,0 +1,38 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
GOG_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
# shellcheck source=config.sh
|
||||
source "${GOG_DIR}/config.sh"
|
||||
|
||||
OUT="${1:-${HOME}/code/local_machine/temp/gog-setup-rca-$(date +%Y%m%d-%H%M%S)}"
|
||||
mkdir -p "${OUT}"
|
||||
|
||||
{
|
||||
echo "=== $(date) ==="
|
||||
echo "Bottle: ${BOTTLE_NAME} ${BOTTLE_ID}"
|
||||
echo ""
|
||||
echo "=== disk ==="
|
||||
df -h /System/Volumes/Data | tail -1
|
||||
echo ""
|
||||
echo "=== processes ==="
|
||||
pgrep -fl 'Galaxy|GOG_Galaxy' 2>/dev/null || echo "(none)"
|
||||
echo ""
|
||||
echo "=== GalaxyClient ==="
|
||||
find "${BOTTLE_DIR}/drive_c" -name 'GalaxyClient.exe' 2>/dev/null || true
|
||||
} >"${OUT}/summary.txt"
|
||||
|
||||
for f in \
|
||||
"/tmp/gog-web-installer-${BOTTLE_NAME}.log" \
|
||||
"/tmp/gog-galaxy-setup-${BOTTLE_NAME}.log"; do
|
||||
[[ -f "${f}" ]] && cp "${f}" "${OUT}/"
|
||||
done
|
||||
|
||||
find "${BOTTLE_DIR}/drive_c" -name 'Setup Log*.txt' 2>/dev/null | while read -r f; do
|
||||
cp "${f}" "${OUT}/$(basename "${f}" | tr ' #' '_')"
|
||||
done
|
||||
|
||||
find "${BOTTLE_DIR}/drive_c/ProgramData/GOG.com" -name '*.log' 2>/dev/null | while read -r f; do
|
||||
cp "${f}" "${OUT}/$(basename "${f}")"
|
||||
done
|
||||
|
||||
echo "${OUT}"
|
||||
238
scripts/games/gog/config.sh
Executable file
238
scripts/games/gog/config.sh
Executable file
@@ -0,0 +1,238 @@
|
||||
# GOG-only Wine/Whisky — без Steam, HoMM, export_wine_env_steam.
|
||||
GOG_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
GAMES_DIR="$(cd "${GOG_DIR}/.." && pwd)"
|
||||
GAMES_CACHE_DIR="${GAMES_DIR}/cache"
|
||||
|
||||
_env_file="${GOG_DIR}/bottle.env"
|
||||
if [[ -f "${_env_file}" ]]; then
|
||||
# shellcheck source=/dev/null
|
||||
source "${_env_file}"
|
||||
elif [[ -n "${GOG_BOTTLE_ID:-}" ]]; then
|
||||
BOTTLE_ID="${GOG_BOTTLE_ID}"
|
||||
BOTTLE_NAME="${GOG_BOTTLE_NAME:-GOG-Install}"
|
||||
else
|
||||
echo "❌ Нет bottle для GOG."
|
||||
echo " 1) Whisky → New Bottle (Windows 10 64-bit), имя GOG-Install"
|
||||
echo " 2) bash ${GOG_DIR}/list-bottles.sh"
|
||||
echo " 3) bash ${GOG_DIR}/use-bottle.sh <UUID>"
|
||||
echo ""
|
||||
echo " Не используйте bottle HoMM-OldenEra — там Steam, дампы и winedbg."
|
||||
exit 1
|
||||
fi
|
||||
unset _env_file
|
||||
|
||||
_FRANKE="${HOME}/Library/Containers/com.franke.Whisky/Bottles/${BOTTLE_ID}"
|
||||
_ISAAC="${HOME}/Library/Containers/com.isaacmarovitz.Whisky/Bottles/${BOTTLE_ID}"
|
||||
if [[ -d "${_FRANKE}/drive_c" ]]; then
|
||||
BOTTLE_DIR="${_FRANKE}"
|
||||
WHISKY_LIBS="${HOME}/Library/Application Support/com.franke.Whisky"
|
||||
elif [[ -d "${_ISAAC}/drive_c" ]]; then
|
||||
BOTTLE_DIR="${_ISAAC}"
|
||||
WHISKY_LIBS="${HOME}/Library/Application Support/com.isaacmarovitz.Whisky"
|
||||
else
|
||||
echo "❌ Bottle не найден: ${BOTTLE_NAME} (${BOTTLE_ID})"
|
||||
echo " Проверьте UUID: bash ${GOG_DIR}/list-bottles.sh"
|
||||
exit 1
|
||||
fi
|
||||
unset _FRANKE _ISAAC
|
||||
|
||||
WINE64="${WHISKY_LIBS}/Libraries/Wine/bin/wine64"
|
||||
WINE_LIB="${WHISKY_LIBS}/Libraries/Wine/lib"
|
||||
WINEPATH_BIN="${WHISKY_LIBS}/Libraries/Wine/bin/winepath"
|
||||
|
||||
gog_data_volume_path() {
|
||||
if [[ -d /System/Volumes/Data ]]; then
|
||||
echo /System/Volumes/Data
|
||||
else
|
||||
echo "${HOME}"
|
||||
fi
|
||||
}
|
||||
|
||||
gog_disk_free_kb() {
|
||||
df -k "$(gog_data_volume_path)" | awk 'NR==2 {print $4}'
|
||||
}
|
||||
|
||||
gog_disk_guard() {
|
||||
local min_gb="${1:-5}"
|
||||
local min_kb free_kb
|
||||
min_kb=$((min_gb * 1024 * 1024))
|
||||
free_kb="$(gog_disk_free_kb)"
|
||||
if [[ "${free_kb}" -lt "${min_kb}" ]]; then
|
||||
echo "❌ Мало места (<${min_gb} GB на Data)."
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
gog_swap_used_mb() {
|
||||
local used
|
||||
used="$(sysctl vm.swapusage 2>/dev/null | sed -n 's/.*used = \([0-9.]*\)M.*/\1/p')"
|
||||
[[ -n "${used}" ]] || return 1
|
||||
printf '%.0f' "${used}"
|
||||
}
|
||||
|
||||
gog_swap_guard() {
|
||||
local max_mb="${1:-400}"
|
||||
local used
|
||||
used="$(gog_swap_used_mb)" || return 0
|
||||
if awk -v u="${used}" -v m="${max_mb}" 'BEGIN{exit !(u>=m)}'; then
|
||||
echo "❌ Swap уже ~${used}MB (лимит ${max_mb}MB) — запуск GOG/Wine запрещён."
|
||||
echo " bash ${GOG_DIR}/emergency-stop.sh"
|
||||
echo " затем перезагрузка Mac (swap macOS отдаёт медленно)"
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
# JA3/CrossOver: жёсткий стоп только если swap высокий И Wine/JA3 ещё живы.
|
||||
# «Залипший» swap после закрытия (macOS не отдал) — предупреждение, запуск разрешён.
|
||||
gog_wine_or_ja3_active() {
|
||||
pgrep -f 'JA3\.exe|wineserver|wine64-preloader|winedbg|wine64\.exe|CrossOver.*wine' >/dev/null 2>&1
|
||||
}
|
||||
|
||||
gog_swap_guard_ja3_launch() {
|
||||
local soft_mb="${1:-1200}"
|
||||
local hard_mb="${2:-4096}"
|
||||
local used
|
||||
used="$(gog_swap_used_mb)" || return 0
|
||||
if [[ "${JA3_IGNORE_SWAP:-0}" == "1" ]]; then
|
||||
echo "⚠️ JA3_IGNORE_SWAP=1 — swap ~${used}MB"
|
||||
return 0
|
||||
fi
|
||||
if gog_wine_or_ja3_active; then
|
||||
if awk -v u="${used}" -v m="${soft_mb}" 'BEGIN{exit !(u>=m)}'; then
|
||||
echo "❌ Swap ~${used}MB и Wine/JA3 ещё работают (лимит ${soft_mb}MB)."
|
||||
echo " bash ${GOG_DIR}/reset-ja3-crossover.sh или bash ${GOG_DIR}/emergency-stop.sh"
|
||||
echo " затем reboot Mac. Или: JA3_IGNORE_SWAP=1 bash …/run-ja3-crossover.sh"
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
fi
|
||||
if awk -v u="${used}" -v m="${hard_mb}" 'BEGIN{exit !(u>=m)}'; then
|
||||
echo "❌ Swap ~${used}MB (лимит ${hard_mb}MB) — reboot Mac."
|
||||
echo " Или: JA3_IGNORE_SWAP=1 bash …/run-ja3-crossover.sh"
|
||||
return 1
|
||||
fi
|
||||
if awk -v u="${used}" -v m="${soft_mb}" 'BEGIN{exit !(u>=m)}'; then
|
||||
echo "⚠️ Swap ~${used}MB — залип после прошлых сессий (Wine не запущен). Запуск JA3…"
|
||||
echo " (reboot снизит swap; JA3_IGNORE_SWAP=1 — принудительный игнор)"
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
# Виртуальный стол Wine — окно CEF часто «есть в логах», но не видно на macOS без /desktop.
|
||||
GOG_VDESKTOP="${GOG_VDESKTOP:-1280x800}"
|
||||
# 0 = прямой GalaxyClient (рекомендуется; vdesktop — в Whisky Metadata или launch-galaxy-ui.sh).
|
||||
GOG_USE_WINEVDESKTOP="${GOG_USE_WINEVDESKTOP:-0}"
|
||||
# GOG_LAUNCH_FG=1 — exec в текущем терминале (лучше для видимости окна, блокирует shell).
|
||||
GOG_LAUNCH_FG="${GOG_LAUNCH_FG:-0}"
|
||||
# GOG_CEF_PROFILE=steam — добавить -cef-in-process-gpu (A/B если login пустой).
|
||||
# /deelevated — обязательно в Wine (иначе DeelevateStrategy + exit -31, см. WineHQ #41584).
|
||||
GOG_GALAXY_BASE_ARGS="${GOG_GALAXY_BASE_ARGS:-/runWithoutUpdating /deelevated}"
|
||||
GOG_GALAXY_CEF_ARGS="${GOG_GALAXY_CEF_ARGS:--allosarches -cef-force-32bit -no-cef-sandbox -cef-disable-gpu}"
|
||||
|
||||
gog_galaxy_cef_args_array() {
|
||||
local -a a=(${GOG_GALAXY_BASE_ARGS} ${GOG_GALAXY_CEF_ARGS})
|
||||
if [[ "${GOG_CEF_PROFILE:-}" == "steam" ]]; then
|
||||
a+=(-cef-in-process-gpu)
|
||||
fi
|
||||
printf '%s\n' "${a[@]}"
|
||||
}
|
||||
|
||||
export_wine_env_gog() {
|
||||
export WINEPREFIX="${BOTTLE_DIR}"
|
||||
export WINEMSYNC=1
|
||||
unset WINEESYNC 2>/dev/null || true
|
||||
local _wine_ext="${WHISKY_LIBS}/Libraries/Wine/lib/external"
|
||||
if [[ -d "${_wine_ext}/D3DMetal.framework" ]]; then
|
||||
export DYLD_FRAMEWORK_PATH="${_wine_ext}:${DYLD_FRAMEWORK_PATH:-}"
|
||||
export DYLD_LIBRARY_PATH="${_wine_ext}:${WINE_LIB}:${DYLD_LIBRARY_PATH:-}"
|
||||
else
|
||||
export DYLD_LIBRARY_PATH="${WINE_LIB}:${DYLD_LIBRARY_PATH:-}"
|
||||
fi
|
||||
unset _wine_ext
|
||||
export WINEDLLOVERRIDES="gdiplus=n,b"
|
||||
unset DXVK_ASYNC DXVK_HUD 2>/dev/null || true
|
||||
export WINEDEBUG=-all
|
||||
export MVK_CONFIG_LOG_LEVEL=0
|
||||
}
|
||||
|
||||
ja3_gptk_available() {
|
||||
[[ -d "${WHISKY_LIBS}/Libraries/Wine/lib/external/D3DMetal.framework" ]] && return 0
|
||||
[[ -f "${WHISKY_LIBS}/Libraries/.gptk_installed" ]] && return 0
|
||||
[[ -d "${WHISKY_LIBS}/D3DMetal" ]] && return 0
|
||||
[[ -d "${WHISKY_LIBS}/GPTK" ]] && return 0
|
||||
return 1
|
||||
}
|
||||
|
||||
ja3_bottle_uses_d3dmetal() {
|
||||
local meta="${BOTTLE_DIR}/Metadata.plist"
|
||||
[[ -f "${meta}" ]] || return 1
|
||||
plutil -extract graphicsConfig.backend raw -o - "${meta}" 2>/dev/null | grep -q d3dMetal
|
||||
}
|
||||
|
||||
ja3_dxmt_installed() {
|
||||
[[ -f "${BOTTLE_DIR}/.ja3_dxmt_installed" ]]
|
||||
}
|
||||
|
||||
# JA3 = D3D12 (Porting Kit / GPTK). Без GPTK — best-effort D3D11+DXVK (d3d12=d).
|
||||
export_wine_env_ja3() {
|
||||
export_wine_env_gog
|
||||
if ja3_gptk_available || ja3_bottle_uses_d3dmetal; then
|
||||
export WINED3DMETAL=1
|
||||
unset DXVK_ASYNC DXVK_HUD DXVK_CONFIG_FILE 2>/dev/null || true
|
||||
# builtin d3d12/dxgi + libd3dshared.so; без n,b на GPTK PE
|
||||
export WINEDLLOVERRIDES="libxess,xess,dxcompiler,dxil,nvngx_dlss,XeFX,XeFX_Loader=d;gdiplus=n,b"
|
||||
return 0
|
||||
fi
|
||||
if ja3_dxmt_installed; then
|
||||
# DXMT builtin: не ставить dxgi/d3d11=n,b (ломает загрузку, c000007b).
|
||||
export WINEDLLOVERRIDES="d3d12=d;libxess,xess,dxcompiler,dxil,nvngx_dlss,XeFX,XeFX_Loader=d;gdiplus=n,b"
|
||||
else
|
||||
export WINEDLLOVERRIDES="d3d11,d3d10core=n,b;d3d12=d;libxess,xess,dxcompiler,dxil,nvngx_dlss,XeFX,XeFX_Loader=d;gdiplus=n,b"
|
||||
fi
|
||||
unset DXVK_ASYNC DXVK_HUD DXVK_CONFIG_FILE 2>/dev/null || true
|
||||
export SDL_VIDEO_MAC_FULLSCREEN_SPACES="${SDL_VIDEO_MAC_FULLSCREEN_SPACES:-0}"
|
||||
export MVK_CONFIG_RESUME_LOST_DEVICE=1
|
||||
}
|
||||
|
||||
export_wine_env_ja3_d3dmetal() {
|
||||
export_wine_env_gog
|
||||
export WINED3DMETAL=1
|
||||
export WINEDLLOVERRIDES="libxess,xess,dxcompiler,dxil,nvngx_dlss,XeFX,XeFX_Loader=d;gdiplus=n,b"
|
||||
unset DXVK_ASYNC DXVK_HUD 2>/dev/null || true
|
||||
}
|
||||
|
||||
gog_steam_client_in_bottle() {
|
||||
local f
|
||||
[[ -d "${BOTTLE_DIR}/drive_c/Program Files (x86)/Steam" ]] && return 0
|
||||
[[ -f "${BOTTLE_DIR}/drive_c/Program Files (x86)/Steam/steam.exe" ]] && return 0
|
||||
f="$(find "${BOTTLE_DIR}/drive_c" -maxdepth 4 -iname 'steam.exe' -print -quit 2>/dev/null || true)"
|
||||
[[ -n "${f}" ]]
|
||||
}
|
||||
|
||||
gog_assert_no_steam_client() {
|
||||
if gog_steam_client_in_bottle; then
|
||||
echo "❌ В bottle ${BOTTLE_NAME} найден Steam client — контур GOG/JA3 без Steam."
|
||||
echo " bash ${GOG_DIR}/purge-steam-from-bottle.sh"
|
||||
return 1
|
||||
fi
|
||||
if [[ "${BOTTLE_ID}" == "38412122-AAE1-4831-9F2E-6A0EB364B3F9" ]]; then
|
||||
echo "❌ Это bottle HoMM-OldenEra (Steam). JA3 только в GOG-Install:"
|
||||
echo " bash ${GOG_DIR}/use-bottle.sh <UUID-GOG-Install>"
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
gog_wine_check() {
|
||||
if [[ ! -x "${WINE64}" ]]; then
|
||||
echo "Нет Wine: bash ${GAMES_DIR}/install-whiskywine-manual.sh"
|
||||
exit 1
|
||||
fi
|
||||
if [[ ! -d "${BOTTLE_DIR}/drive_c" ]]; then
|
||||
echo "❌ Нет drive_c в ${BOTTLE_DIR}"
|
||||
echo " Откройте bottle «${BOTTLE_NAME}» в Whisky один раз."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
37
scripts/games/gog/configure-ja3-d3dmetal.sh
Executable file
37
scripts/games/gog/configure-ja3-d3dmetal.sh
Executable file
@@ -0,0 +1,37 @@
|
||||
#!/usr/bin/env bash
|
||||
# JA3 = DirectX 12. На Apple Silicon канон: Whisky + Game Porting Toolkit (D3DMetal), не DXVK.
|
||||
set -euo pipefail
|
||||
GOG_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
# shellcheck source=config.sh
|
||||
source "${GOG_DIR}/config.sh"
|
||||
|
||||
META="${BOTTLE_DIR}/Metadata.plist"
|
||||
[[ -f "${META}" ]] || {
|
||||
echo "❌ Нет ${META} — откройте bottle ${BOTTLE_NAME} в Whisky."
|
||||
exit 1
|
||||
}
|
||||
|
||||
if ! ja3_gptk_available; then
|
||||
if [[ -d "/Applications/Game Porting Toolkit.app" ]]; then
|
||||
bash "${GOG_DIR}/install-gptk-whisky.sh"
|
||||
else
|
||||
echo "❌ Game Porting Toolkit не установлен."
|
||||
echo " brew install --cask gcenx/wine/game-porting-toolkit"
|
||||
echo " bash ${GOG_DIR}/install-gptk-whisky.sh"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
/usr/libexec/PlistBuddy -c 'Set :graphicsConfig:backend d3dMetal' "${META}" 2>/dev/null || \
|
||||
/usr/libexec/PlistBuddy -c 'Add :graphicsConfig:backend string d3dMetal' "${META}"
|
||||
/usr/libexec/PlistBuddy -c 'Set :dxvkConfig:dxvk false' "${META}" 2>/dev/null || true
|
||||
|
||||
bash "${GOG_DIR}/force-ja3-d3d11.sh" >/dev/null 2>&1 || true
|
||||
# С GPTK можно d3d12 — сбросить принудительный d3d11 в LocalStorage при желании:
|
||||
# perl -i -pe 's/GraphicsApi = "d3d11"/GraphicsApi = "d3d12"/' ...
|
||||
|
||||
bash "${GOG_DIR}/prepare-ja3-d3dmetal.sh"
|
||||
|
||||
echo "OK: bottle ${BOTTLE_NAME} → Graphics Backend D3DMetal"
|
||||
echo " Запуск: bash ${GOG_DIR}/run-ja3.sh"
|
||||
echo " Whisky Run: C:\\GOG Games\\Jagged Alliance 3\\run-ja3.cmd (не JA3.exe — иначе graphics/CommonLua)"
|
||||
102
scripts/games/gog/create-bottle.sh
Executable file
102
scripts/games/gog/create-bottle.sh
Executable file
@@ -0,0 +1,102 @@
|
||||
#!/usr/bin/env bash
|
||||
# Создать пустой Whisky-bottle «GOG-Install» (wineboot --init), без Steam.
|
||||
set -euo pipefail
|
||||
GOG_SCRIPTS="$(cd "$(dirname "$0")" && pwd)"
|
||||
FRANKE="${HOME}/Library/Containers/com.franke.Whisky"
|
||||
WHISKY_LIBS="${HOME}/Library/Application Support/com.franke.Whisky/Libraries"
|
||||
WINE64="${WHISKY_LIBS}/Wine/bin/wine64"
|
||||
WINE_LIB="${WHISKY_LIBS}/Wine/lib"
|
||||
NAME="${1:-GOG-Install}"
|
||||
|
||||
if [[ -f "${GOG_SCRIPTS}/bottle.env" ]]; then
|
||||
# shellcheck source=/dev/null
|
||||
source "${GOG_SCRIPTS}/bottle.env"
|
||||
if [[ -d "${FRANKE}/Bottles/${BOTTLE_ID}/drive_c" ]]; then
|
||||
echo "Bottle уже есть: ${BOTTLE_NAME} (${BOTTLE_ID})"
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ ! -x "${WINE64}" ]]; then
|
||||
echo "Нет Wine: bash $(dirname "$GOG_SCRIPTS")/install-whiskywine-manual.sh"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
BOTTLE_ID="$(uuidgen | tr '[:upper:]' '[:lower:]')"
|
||||
BOTTLE_PATH="${FRANKE}/Bottles/${BOTTLE_ID}"
|
||||
mkdir -p "${BOTTLE_PATH}"
|
||||
|
||||
echo "Создаю префикс Wine: ${BOTTLE_PATH} (2–5 мин)…"
|
||||
export WINEPREFIX="${BOTTLE_PATH}"
|
||||
export DYLD_LIBRARY_PATH="${WINE_LIB}:${DYLD_LIBRARY_PATH:-}"
|
||||
export WINEDEBUG=-all
|
||||
"${WINE64}" wineboot --init
|
||||
|
||||
python3 <<PY
|
||||
import plistlib
|
||||
from pathlib import Path
|
||||
|
||||
meta = Path("${BOTTLE_PATH}") / "Metadata.plist"
|
||||
data = {
|
||||
"info": {"name": "${NAME}", "pins": [], "blocklist": []},
|
||||
"displayConfig": {
|
||||
"customWidth": 1920,
|
||||
"customHeight": 1080,
|
||||
"resolutionPreset": "r1920x1080",
|
||||
"virtualDesktopEnabled": False,
|
||||
},
|
||||
"dxvkConfig": {"dxvk": False, "dxvkAsync": True, "dxvkHud": {"off": {}}},
|
||||
"graphicsConfig": {"backend": "recommended"},
|
||||
"audioConfig": {
|
||||
"audioDriver": "auto",
|
||||
"latencyPreset": "defaultPreset",
|
||||
"outputDeviceMode": "followSystem",
|
||||
},
|
||||
"cleanupConfig": {
|
||||
"clipboardPolicy": "auto",
|
||||
"clipboardThreshold": 10240,
|
||||
"closeWithProcessesPolicy": "ask",
|
||||
"killOnQuit": "inherit",
|
||||
},
|
||||
"customDLLOverrides": [],
|
||||
"fileVersion": {"major": 1, "minor": 0, "patch": 0, "build": "", "preRelease": ""},
|
||||
}
|
||||
with meta.open("wb") as f:
|
||||
plistlib.dump(data, f)
|
||||
print("Metadata.plist OK")
|
||||
PY
|
||||
|
||||
BOTTLE_VM="${FRANKE}/BottleVM.plist"
|
||||
python3 <<PY
|
||||
import plistlib
|
||||
from pathlib import Path
|
||||
|
||||
vm = Path("${BOTTLE_VM}")
|
||||
url = "file://${BOTTLE_PATH}"
|
||||
if vm.exists():
|
||||
with vm.open("rb") as f:
|
||||
data = plistlib.load(f)
|
||||
else:
|
||||
data = {"fileVersion": {"major": 1, "minor": 0, "patch": 0, "build": "", "preRelease": ""}, "paths": []}
|
||||
paths = data.setdefault("paths", [])
|
||||
if not any(p.get("relative", "").endswith("${BOTTLE_ID}") for p in paths):
|
||||
paths.append({"relative": url})
|
||||
with vm.open("wb") as f:
|
||||
plistlib.dump(data, f)
|
||||
print("BottleVM.plist OK")
|
||||
PY
|
||||
|
||||
if command -v whisky >/dev/null 2>&1; then
|
||||
whisky add "${BOTTLE_PATH}" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
cat >"${GOG_SCRIPTS}/bottle.env" <<EOF
|
||||
BOTTLE_ID=${BOTTLE_ID}
|
||||
BOTTLE_NAME=${NAME}
|
||||
EOF
|
||||
|
||||
echo ""
|
||||
echo "OK: ${NAME}"
|
||||
echo " UUID: ${BOTTLE_ID}"
|
||||
echo " Path: ${BOTTLE_PATH}"
|
||||
echo "Дальше: bash ${GOG_SCRIPTS}/setup-bottle.sh"
|
||||
44
scripts/games/gog/diagnose-galaxy-window.sh
Executable file
44
scripts/games/gog/diagnose-galaxy-window.sh
Executable file
@@ -0,0 +1,44 @@
|
||||
#!/usr/bin/env bash
|
||||
# RCA: процесс жив, окна нет — логи + процессы (без Apple Events).
|
||||
set -euo pipefail
|
||||
GOG_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
# shellcheck source=config.sh
|
||||
source "${GOG_DIR}/config.sh"
|
||||
|
||||
OUT="${1:-${HOME}/code/local_machine/temp/gog-window-rca-$(date +%Y%m%d-%H%M%S)}"
|
||||
mkdir -p "${OUT}"
|
||||
|
||||
GALAXY_LOG="${BOTTLE_DIR}/drive_c/ProgramData/GOG.com/Galaxy/logs/GalaxyClient.log"
|
||||
INIT_LOG="${BOTTLE_DIR}/drive_c/ProgramData/GOG.com/Galaxy/logs/GalaxyInitialization.log"
|
||||
CEF_LOG="${BOTTLE_DIR}/drive_c/ProgramData/GOG.com/Galaxy/logs/cef.log"
|
||||
LAUNCH_LOG="/tmp/gog-galaxy-client-${BOTTLE_NAME}.log"
|
||||
|
||||
{
|
||||
echo "=== GOG Galaxy window RCA ==="
|
||||
date
|
||||
echo "bottle: ${BOTTLE_NAME} ${BOTTLE_ID}"
|
||||
echo "GOG_USE_WINEVDESKTOP=${GOG_USE_WINEVDESKTOP:-?} GOG_VDESKTOP=${GOG_VDESKTOP:-?}"
|
||||
echo ""
|
||||
echo "--- pgrep Galaxy ---"
|
||||
pgrep -fl 'GalaxyClient|explorer.exe /desktop=GOG' 2>/dev/null || echo "(нет процессов)"
|
||||
echo ""
|
||||
echo "--- disk ---"
|
||||
df -h "$(gog_data_volume_path)" 2>/dev/null | tail -1
|
||||
} >"${OUT}/summary.txt"
|
||||
|
||||
for f in "${GALAXY_LOG}" "${INIT_LOG}" "${CEF_LOG}" "${LAUNCH_LOG}"; do
|
||||
[[ -f "${f}" ]] || continue
|
||||
base="$(basename "${f}")"
|
||||
tail -80 "${f}" >"${OUT}/${base}.tail" 2>/dev/null || true
|
||||
done
|
||||
|
||||
grep -E 'Second client|will continue|Showing login|foreground|Failed to locate|parent window' \
|
||||
"${GALAXY_LOG}" "${CEF_LOG}" 2>/dev/null >"${OUT}/signals.txt" || true
|
||||
|
||||
echo "OK: ${OUT}"
|
||||
echo " summary.txt, signals.txt, *.tail"
|
||||
echo ""
|
||||
echo "Если в signals.txt есть login/foreground, а окна нет:"
|
||||
echo " bash ${GOG_DIR}/reset.sh"
|
||||
echo " bash ${GOG_DIR}/launch-galaxy-ui.sh # vdesktop + foreground"
|
||||
echo " Cmd+Tab → wine64 / GOGGalaxy / GalaxyClient"
|
||||
28
scripts/games/gog/diagnose-session.sh
Executable file
28
scripts/games/gog/diagnose-session.sh
Executable file
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
GOG_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
# shellcheck source=config.sh
|
||||
source "${GOG_DIR}/config.sh"
|
||||
|
||||
RCA="${GAMES_DIR}/../temp/gog-rca-$(date +%Y%m%d-%H%M%S)"
|
||||
LOG="/tmp/gog-web-installer-${BOTTLE_NAME}.log"
|
||||
mkdir -p "${RCA}"
|
||||
|
||||
{
|
||||
echo "GOG bottle: ${BOTTLE_NAME} (${BOTTLE_ID})"
|
||||
df -h "$(gog_data_volume_path)"
|
||||
sysctl vm.swapusage 2>/dev/null || true
|
||||
echo ""
|
||||
echo "markers:"; ls -la "${BOTTLE_DIR}"/.gog_* 2>/dev/null || true
|
||||
echo ""
|
||||
du -sh "${BOTTLE_DIR}" "${BOTTLE_DIR}/drive_c/windows/Fonts" 2>/dev/null || true
|
||||
echo ""
|
||||
echo "log ${LOG}:"
|
||||
tail -30 "${LOG}" 2>/dev/null || echo "(нет)"
|
||||
echo ""
|
||||
echo "winedbg: $(pgrep winedbg 2>/dev/null | wc -l | tr -d ' ')"
|
||||
pgrep -lf 'GOG_Galaxy|GalaxyWeb' 2>/dev/null || echo "(нет GOG процессов)"
|
||||
} | tee "${RCA}/report.txt"
|
||||
|
||||
cp "${LOG}" "${RCA}/" 2>/dev/null || true
|
||||
echo "RCA: ${RCA}"
|
||||
26
scripts/games/gog/emergency-stop.sh
Executable file
26
scripts/games/gog/emergency-stop.sh
Executable file
@@ -0,0 +1,26 @@
|
||||
#!/usr/bin/env bash
|
||||
# Снять нагрузку GOG/Wine + winedbg (swap). Безопасно для GOG-bottle.
|
||||
set -euo pipefail
|
||||
GOG_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
# shellcheck source=gog-process.sh
|
||||
source "${GOG_DIR}/gog-process.sh"
|
||||
|
||||
_winedbg_count() {
|
||||
pgrep winedbg 2>/dev/null | wc -l | tr -d ' '
|
||||
}
|
||||
|
||||
echo "=== До ==="
|
||||
sysctl vm.swapusage 2>/dev/null || true
|
||||
echo "winedbg: $(_winedbg_count)"
|
||||
|
||||
gog_kill_all
|
||||
pkill -9 winedbg 2>/dev/null || true
|
||||
|
||||
echo ""
|
||||
echo "=== После kill ==="
|
||||
pgrep -fl 'Galaxy|GOG Galaxy' 2>/dev/null || echo "Galaxy: (нет)"
|
||||
echo "winedbg: $(_winedbg_count)"
|
||||
sysctl vm.swapusage 2>/dev/null || true
|
||||
echo ""
|
||||
echo "Если Mac всё ещё тормозит — перезагрузка (swap отдаётся медленно)."
|
||||
echo "Galaxy UI в Wine на этом Mac не подтверждён — JA3: docs/games/GOG_GALAXY_7H_RCA.md § Offline"
|
||||
42
scripts/games/gog/fetch-ja3-setup-exe.sh
Executable file
42
scripts/games/gog/fetch-ja3-setup-exe.sh
Executable file
@@ -0,0 +1,42 @@
|
||||
#!/usr/bin/env bash
|
||||
# Скачать только лаунчер (~1 MB) для multipart offline backup JA3.
|
||||
set -euo pipefail
|
||||
GOG_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
JA3_GAMES_DIR="${JA3_GAMES_DIR:-${HOME}/Games}"
|
||||
OUT="${JA3_GAMES_DIR}/setup_jagged_alliance_3_1.5.2_(80730).exe"
|
||||
|
||||
mkdir -p "${JA3_GAMES_DIR}"
|
||||
|
||||
if [[ -f "${OUT}" ]]; then
|
||||
echo "Уже есть: ${OUT}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if ! command -v lgogdownloader >/dev/null 2>&1; then
|
||||
echo "❌ Нужен lgogdownloader: brew install lgogdownloader"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Скачивание en1installer0 (~1 MB) → ${OUT}"
|
||||
echo "Если ошибка login — выполните: lgogdownloader --login"
|
||||
echo ""
|
||||
|
||||
lgogdownloader \
|
||||
--download-file "jagged_alliance_3/en1installer0" \
|
||||
--output-file "$(basename "${OUT}")" \
|
||||
--directory "${JA3_GAMES_DIR}"
|
||||
|
||||
if [[ -f "${OUT}" ]]; then
|
||||
ls -lh "${OUT}"
|
||||
echo "OK. Дальше: bash ${GOG_DIR}/install-ja3-multipart.sh"
|
||||
else
|
||||
# lgogdownloader может сохранить под другим именем
|
||||
f="$(find "${JA3_GAMES_DIR}" -maxdepth 1 -iname 'setup*jagged*alliance*3*.exe' -print -quit 2>/dev/null || true)"
|
||||
if [[ -n "${f}" ]]; then
|
||||
echo "Скачан как: ${f}"
|
||||
echo "Запуск: JA3_SETUP_EXE='${f}' bash ${GOG_DIR}/install-ja3-multipart.sh"
|
||||
else
|
||||
echo "❌ .exe не появился в ${JA3_GAMES_DIR}"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
7
scripts/games/gog/finish-ja3-install.sh
Executable file
7
scripts/games/gog/finish-ja3-install.sh
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
# Устарело: Galaxy UI. Канон — install-ja3.sh (offline backup без Galaxy).
|
||||
set -euo pipefail
|
||||
GOG_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
echo "Канон JA3 без Galaxy: bash ${GOG_DIR}/install-ja3.sh"
|
||||
echo "Док: docs/games/JA3_MAC_WITHOUT_GALAXY.md"
|
||||
exec bash "${GOG_DIR}/install-ja3.sh"
|
||||
48
scripts/games/gog/finish-ja3-layout.sh
Executable file
48
scripts/games/gog/finish-ja3-layout.sh
Executable file
@@ -0,0 +1,48 @@
|
||||
#!/usr/bin/env bash
|
||||
# Доп. шаги после innoextract: layout GOG, реестр, DXVK, CommonLua.
|
||||
set -euo pipefail
|
||||
GOG_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
GAMES_DIR="$(cd "${GOG_DIR}/.." && pwd)"
|
||||
# shellcheck source=config.sh
|
||||
source "${GOG_DIR}/config.sh"
|
||||
|
||||
JA3="${BOTTLE_DIR}/drive_c/GOG Games/Jagged Alliance 3"
|
||||
|
||||
[[ -f "${JA3}/JA3.exe" ]] || {
|
||||
echo "❌ Нет JA3 — сначала install-ja3-innoextract.sh"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Inno Setup копирует CommonLua в корень; innoextract — только ModTools/ (Wine не видит symlink)
|
||||
if [[ ! -f "${JA3}/CommonLua/Core/autorun.lua" ]]; then
|
||||
rm -rf "${JA3}/CommonLua"
|
||||
cp -R "${JA3}/ModTools/Src/CommonLua" "${JA3}/CommonLua"
|
||||
echo " CommonLua скопирован из ModTools/Src (~9 MB)"
|
||||
fi
|
||||
|
||||
bash "${GOG_DIR}/register-ja3-registry.sh"
|
||||
bash "${GOG_DIR}/install-ja3-redist.sh" 2>/dev/null || true
|
||||
if ja3_gptk_available || ja3_bottle_uses_d3dmetal; then
|
||||
bash "${GOG_DIR}/prepare-ja3-d3dmetal.sh" 2>/dev/null || bash "${GOG_DIR}/install-gptk-whisky.sh" || true
|
||||
else
|
||||
if [[ -d "/Applications/Game Porting Toolkit.app" ]]; then
|
||||
bash "${GOG_DIR}/install-gptk-whisky.sh"
|
||||
else
|
||||
bash "${GOG_DIR}/install-ja3-dxmt.sh" 2>/dev/null || bash "${GOG_DIR}/install-dxvk.sh"
|
||||
fi
|
||||
fi
|
||||
cp -f "${GOG_DIR}/ja3-dxvk.conf" "${JA3}/dxvk.conf" 2>/dev/null || true
|
||||
if ja3_gptk_available || ja3_bottle_uses_d3dmetal; then
|
||||
perl -i -pe 's/^\t\tGraphicsApi = "d3d11"/\t\tGraphicsApi = "d3d12"/' \
|
||||
"${BOTTLE_DIR}/drive_c/users/${WINE_USER:-eternal}/AppData/Roaming/Jagged Alliance 3/LocalStorage.lua" 2>/dev/null || true
|
||||
else
|
||||
bash "${GOG_DIR}/force-ja3-d3d11.sh"
|
||||
fi
|
||||
# Intel XeSS / DLSS DLL в папке игры ломают D3D11 на MoltenVK — убрать с пути загрузки
|
||||
mkdir -p "${JA3}/.disabled-upscale"
|
||||
for dll in libxess.dll nvngx_dlss.dll XeFX.dll XeFX_Loader.dll dxcompiler.dll dxil.dll; do
|
||||
[[ -f "${JA3}/${dll}" ]] && mv -f "${JA3}/${dll}" "${JA3}/.disabled-upscale/${dll}"
|
||||
done
|
||||
bash "${GOG_DIR}/purge-steam-from-bottle.sh" >/dev/null 2>&1 || true
|
||||
|
||||
echo "OK: finish-ja3-layout"
|
||||
77
scripts/games/gog/fix-ja3-crossover-mouse.sh
Executable file
77
scripts/games/gog/fix-ja3-crossover-mouse.sh
Executable file
@@ -0,0 +1,77 @@
|
||||
#!/usr/bin/env bash
|
||||
# Курсор JA3 в CrossOver (Retina / HiDPI).
|
||||
# Профили (JA3_MOUSE_PROFILE):
|
||||
# legacy — RetinaMode=n (полный ход по Y; возможен сдвиг клика) — default
|
||||
# retina-lite — RetinaMode=y без LogPixels (если legacy смещает, но нет клипа)
|
||||
# retina — RetinaMode=y + LogPixels=192 (клип на середине экрана — не default)
|
||||
set -euo pipefail
|
||||
GOG_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
CX="/Applications/CrossOver.app/Contents/SharedSupport/CrossOver"
|
||||
CX_BOTTLE="JA3-GOG"
|
||||
CX_DIR="${HOME}/Library/Application Support/CrossOver/Bottles/${CX_BOTTLE}"
|
||||
|
||||
[[ -d "${CX}" ]] || {
|
||||
echo "❌ CrossOver не установлен"
|
||||
exit 1
|
||||
}
|
||||
|
||||
PROFILE="${JA3_MOUSE_PROFILE:-legacy}"
|
||||
WREG() { "${CX}/bin/wine" --bottle "${CX_BOTTLE}" "$@"; }
|
||||
|
||||
case "${PROFILE}" in
|
||||
retina)
|
||||
RETINA="y"
|
||||
SET_DPI=1
|
||||
DPI="${JA3_LOG_PIXELS:-192}"
|
||||
SET_WIN8=1
|
||||
;;
|
||||
retina-lite)
|
||||
RETINA="y"
|
||||
SET_DPI=0
|
||||
SET_WIN8=0
|
||||
;;
|
||||
legacy|*)
|
||||
RETINA="n"
|
||||
SET_DPI=0
|
||||
SET_WIN8=0
|
||||
PROFILE="legacy"
|
||||
;;
|
||||
esac
|
||||
|
||||
WREG reg add 'HKCU\Software\Wine\Mac Driver' /v RetinaMode /t REG_SZ /d "${RETINA}" /f >/dev/null
|
||||
|
||||
if [[ "${SET_DPI}" == "1" ]]; then
|
||||
WREG reg add 'HKCU\Control Panel\Desktop' /v LogPixels /t REG_DWORD /d "${DPI}" /f >/dev/null
|
||||
else
|
||||
WREG reg delete 'HKCU\Control Panel\Desktop' /v LogPixels /f >/dev/null 2>&1 || true
|
||||
fi
|
||||
|
||||
if [[ "${SET_WIN8}" == "1" ]]; then
|
||||
WREG reg add 'HKCU\Control Panel\Desktop' /v Win8DpiScaling /t REG_DWORD /d 1 /f >/dev/null
|
||||
else
|
||||
WREG reg delete 'HKCU\Control Panel\Desktop' /v Win8DpiScaling /f >/dev/null 2>&1 || true
|
||||
fi
|
||||
|
||||
CONF="${CX_DIR}/cxbottle.conf"
|
||||
if [[ -f "${CONF}" ]] && ! grep -q 'SDL_VIDEO_MAC_FULLSCREEN_SPACES' "${CONF}"; then
|
||||
sed -i '' '/^\[EnvironmentVariables\]/a\
|
||||
"SDL_VIDEO_MAC_FULLSCREEN_SPACES" = "0"
|
||||
' "${CONF}" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
echo "OK: profile=${PROFILE} RetinaMode=${RETINA} → ${CX_BOTTLE}"
|
||||
echo " Перезапуск: bash ${GOG_DIR}/reset-ja3-crossover.sh && bash ${GOG_DIR}/run-ja3-crossover.sh"
|
||||
case "${PROFILE}" in
|
||||
legacy)
|
||||
echo " Если клик смещён: JA3_MOUSE_PROFILE=retina-lite bash ${GOG_DIR}/fix-ja3-crossover-mouse.sh"
|
||||
echo " Без перезапуска: верхний левый угол окна = угол экрана."
|
||||
;;
|
||||
retina-lite)
|
||||
echo " Если смещение осталось: JA3_MOUSE_PROFILE=legacy …"
|
||||
echo " Если клип на середине: JA3_MOUSE_PROFILE=legacy …"
|
||||
;;
|
||||
retina)
|
||||
echo " ⚠️ retina+LogPixels=192 часто режет курсор на середине экрана."
|
||||
echo " Если так: JA3_MOUSE_PROFILE=legacy bash ${GOG_DIR}/fix-ja3-crossover-mouse.sh"
|
||||
;;
|
||||
esac
|
||||
35
scripts/games/gog/force-ja3-d3d11.sh
Executable file
35
scripts/games/gog/force-ja3-d3d11.sh
Executable file
@@ -0,0 +1,35 @@
|
||||
#!/usr/bin/env bash
|
||||
# JA3 на Mac (Whisky без GPTK): рендер через D3D11 + DXVK, не D3D12 (wine d3d12 → «Failed creating render device»).
|
||||
set -euo pipefail
|
||||
GOG_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
# shellcheck source=config.sh
|
||||
source "${GOG_DIR}/config.sh"
|
||||
|
||||
WINE_USER="${WINE_USER:-eternal}"
|
||||
LS="${BOTTLE_DIR}/drive_c/users/${WINE_USER}/AppData/Roaming/Jagged Alliance 3/LocalStorage.lua"
|
||||
|
||||
if [[ ! -f "${LS}" ]]; then
|
||||
mkdir -p "$(dirname "${LS}")"
|
||||
cat >"${LS}" <<'EOF'
|
||||
return {
|
||||
Options = {
|
||||
GraphicsApi = "d3d11",
|
||||
VideoPreset = "Low",
|
||||
},
|
||||
}
|
||||
EOF
|
||||
echo "OK: создан ${LS} (GraphicsApi=d3d11)"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if grep -q 'GraphicsApi = "d3d11"' "${LS}"; then
|
||||
echo "OK: GraphicsApi уже d3d11"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
perl -i -pe '
|
||||
if (/^\t\tGraphicsApi = /) {
|
||||
$_ = "\t\tGraphicsApi = \"d3d11\",\n";
|
||||
}
|
||||
' "${LS}"
|
||||
echo "OK: ${LS} → GraphicsApi=d3d11 (было d3d12 или пусто)"
|
||||
72
scripts/games/gog/gog-process.sh
Executable file
72
scripts/games/gog/gog-process.sh
Executable file
@@ -0,0 +1,72 @@
|
||||
#!/usr/bin/env bash
|
||||
# Общие kill/lock для GOG Galaxy в GOG-bottle.
|
||||
GOG_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
# shellcheck source=config.sh
|
||||
source "${GOG_DIR}/config.sh"
|
||||
|
||||
WINE_SERV="${WHISKY_LIBS}/Libraries/Wine/bin/wineserver"
|
||||
|
||||
gog_lock_files_dir() {
|
||||
echo "${BOTTLE_DIR}/drive_c/ProgramData/GOG.com/Galaxy/lock-files"
|
||||
}
|
||||
|
||||
gog_remove_lock_files() {
|
||||
local d
|
||||
d="$(gog_lock_files_dir)"
|
||||
[[ -d "${d}" ]] || return 0
|
||||
rm -f "${d}"/*.lock 2>/dev/null || true
|
||||
}
|
||||
|
||||
gog_kill_all() {
|
||||
pkill -9 -f 'explorer.exe /desktop=GOGGalaxy' 2>/dev/null || true
|
||||
pkill -9 -f 'explorer /desktop=GOGGalaxy' 2>/dev/null || true
|
||||
pkill -9 -f 'GalaxyClient Helper' 2>/dev/null || true
|
||||
pkill -9 -f 'GalaxyClient' 2>/dev/null || true
|
||||
pkill -9 -f 'GalaxyUpdater' 2>/dev/null || true
|
||||
pkill -9 -f 'GalaxyInstaller' 2>/dev/null || true
|
||||
pkill -9 -f 'GalaxySetup' 2>/dev/null || true
|
||||
pkill -9 -f 'GalaxyWebInstaller' 2>/dev/null || true
|
||||
pkill -9 -f 'GOG_Galaxy_' 2>/dev/null || true
|
||||
pkill -9 -f 'GOG Galaxy' 2>/dev/null || true
|
||||
pkill -9 -f "${BOTTLE_ID}.*[Ss]team" 2>/dev/null || true
|
||||
pkill -9 -f "${BOTTLE_DIR}.*steam\.exe" 2>/dev/null || true
|
||||
pkill -9 -f "${BOTTLE_ID}.*wine" 2>/dev/null || true
|
||||
pkill -9 -f 'winedevice\.exe' 2>/dev/null || true
|
||||
pkill -9 -f 'wine64-preloader' 2>/dev/null || true
|
||||
pkill -9 -f 'wine64\.exe' 2>/dev/null || true
|
||||
sleep 1
|
||||
if [[ -d "${BOTTLE_DIR}" ]]; then
|
||||
export WINEPREFIX="${BOTTLE_DIR}"
|
||||
[[ -x "${WINE_SERV}" ]] && "${WINE_SERV}" -k 2>/dev/null || true
|
||||
sleep 1
|
||||
gog_remove_lock_files
|
||||
fi
|
||||
sleep 1
|
||||
}
|
||||
|
||||
gog_galaxy_running() {
|
||||
pgrep -f 'GalaxyClient\.exe' >/dev/null 2>&1 \
|
||||
|| pgrep -f 'GalaxyClient Helper' >/dev/null 2>&1
|
||||
}
|
||||
|
||||
gog_wait_log_line() {
|
||||
local log="$1" pattern="$2" timeout="${3:-30}"
|
||||
local i
|
||||
for i in $(seq 1 "${timeout}"); do
|
||||
[[ -f "${log}" ]] && grep -q "${pattern}" "${log}" 2>/dev/null && return 0
|
||||
sleep 1
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
gog_mac_activate_wine() {
|
||||
osascript -e '
|
||||
tell application "System Events"
|
||||
repeat with proc in (every process whose name contains "wine" or name contains "Wine")
|
||||
try
|
||||
set frontmost of proc to true
|
||||
exit repeat
|
||||
end try
|
||||
end repeat
|
||||
end tell' 2>/dev/null || true
|
||||
}
|
||||
37
scripts/games/gog/install-all.sh
Executable file
37
scripts/games/gog/install-all.sh
Executable file
@@ -0,0 +1,37 @@
|
||||
#!/usr/bin/env bash
|
||||
# Полный сетап GOG-bottle + web-stub. Аргумент: путь к GOG_Galaxy_*.exe
|
||||
set -euo pipefail
|
||||
GOG_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
STUB="${1:-}"
|
||||
|
||||
if [[ ! -f "${GOG_DIR}/bottle.env" ]]; then
|
||||
bash "${GOG_DIR}/create-bottle.sh" GOG-Install
|
||||
fi
|
||||
|
||||
bash "${GOG_DIR}/setup-bottle.sh" --force
|
||||
|
||||
# shellcheck source=config.sh
|
||||
source "${GOG_DIR}/config.sh"
|
||||
if [[ ! -f "${BOTTLE_DIR}/.gog_gdiplus_installed" ]]; then
|
||||
bash "${GOG_DIR}/install-gdiplus.sh"
|
||||
fi
|
||||
|
||||
command -v cabextract >/dev/null || brew install cabextract
|
||||
bash "${GOG_DIR}/install-corefonts.sh"
|
||||
bash "${GOG_DIR}/install-galaxy-extract.sh"
|
||||
|
||||
if [[ -z "${STUB}" ]]; then
|
||||
echo "Готово. Установка JA3:"
|
||||
echo " bash ${GOG_DIR}/launch-galaxy.sh # вход → Install в библиотеке"
|
||||
echo " bash ${GOG_DIR}/finish-ja3-install.sh"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "${GOG_USE_WEB_STUB:-0}" == "1" ]]; then
|
||||
echo "Web-stub (эксперимент; GalaxySetup часто падает на gdi32 в Wine)…"
|
||||
bash "${GOG_DIR}/run-web-installer.sh" "${STUB}"
|
||||
else
|
||||
echo "Galaxy уже распакован. Для игры — launch-galaxy.sh (не web-stub)."
|
||||
echo "Принудительно stub: GOG_USE_WEB_STUB=1 bash $0 ${STUB}"
|
||||
bash "${GOG_DIR}/launch-galaxy.sh"
|
||||
fi
|
||||
48
scripts/games/gog/install-corefonts.sh
Executable file
48
scripts/games/gog/install-corefonts.sh
Executable file
@@ -0,0 +1,48 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
GOG_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
# shellcheck source=config.sh
|
||||
source "${GOG_DIR}/config.sh"
|
||||
# shellcheck source=wine-fonts.sh
|
||||
source "${GOG_DIR}/wine-fonts.sh"
|
||||
|
||||
CACHE="${GAMES_CACHE_DIR}/corefonts"
|
||||
FONTS="${BOTTLE_DIR}/drive_c/windows/Fonts"
|
||||
|
||||
cmd_fetch() {
|
||||
local name="$1" url="$2"
|
||||
mkdir -p "${CACHE}"
|
||||
if [[ -f "${CACHE}/${name}" ]] && [[ "$(wc -c <"${CACHE}/${name}")" -gt 10000 ]]; then
|
||||
return 0
|
||||
fi
|
||||
echo "Скачиваю ${name}…"
|
||||
curl -fsSL --retry 3 -o "${CACHE}/${name}" "${url}" || return 1
|
||||
}
|
||||
|
||||
cmd_extract_cab() {
|
||||
local cab="$1" out="${CACHE}/extract-${2:-x}"
|
||||
rm -rf "${out}"
|
||||
mkdir -p "${out}"
|
||||
cabextract -d "${out}" "${cab}"
|
||||
find "${out}" -iname '*.ttf' -exec cp -n {} "${FONTS}/" \;
|
||||
}
|
||||
|
||||
gog_wine_check
|
||||
command -v cabextract >/dev/null || { echo "brew install cabextract"; exit 1; }
|
||||
mkdir -p "${FONTS}" "${CACHE}"
|
||||
|
||||
cmd_fetch andale32.exe "https://downloads.sourceforge.net/corefonts/andale32.exe" \
|
||||
|| cmd_fetch andale32.exe "https://ftp.debian.org/debian/pool/contrib/m/msttcorefonts/andale32.exe" || true
|
||||
cmd_fetch arial32.exe "https://downloads.sourceforge.net/corefonts/arial32.exe" \
|
||||
|| cmd_fetch arial32.exe "https://ftp.debian.org/debian/pool/contrib/m/msttcorefonts/arial32.exe" || true
|
||||
cmd_fetch times32.exe "https://downloads.sourceforge.net/corefonts/times32.exe" \
|
||||
|| cmd_fetch times32.exe "https://ftp.debian.org/debian/pool/contrib/m/msttcorefonts/times32.exe" || true
|
||||
|
||||
for cab in andale32.exe arial32.exe times32.exe; do
|
||||
[[ -f "${CACHE}/${cab}" ]] && [[ "$(wc -c <"${CACHE}/${cab}")" -gt 10000 ]] \
|
||||
&& cmd_extract_cab "${CACHE}/${cab}" "${cab%.exe}" || true
|
||||
done
|
||||
|
||||
gog_wine_ensure_fonts 1
|
||||
touch "${BOTTLE_DIR}/.gog_corefonts_installed"
|
||||
echo "OK: corefonts в GOG bottle ($(ls "${FONTS}" | wc -l | tr -d ' ') файлов)"
|
||||
35
scripts/games/gog/install-dxvk.sh
Executable file
35
scripts/games/gog/install-dxvk.sh
Executable file
@@ -0,0 +1,35 @@
|
||||
#!/usr/bin/env bash
|
||||
# DXVK-macOS в GOG-bottle (для JA3).
|
||||
set -euo pipefail
|
||||
GOG_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
GAMES_DIR="$(cd "${GOG_DIR}/.." && pwd)"
|
||||
# shellcheck source=config.sh
|
||||
source "${GOG_DIR}/config.sh"
|
||||
|
||||
# install-dxvk-macos.sh привязан к HoMM config — дублируем install для GOG-bottle
|
||||
DXVK_CACHE="${GAMES_DIR}/cache/dxvk-macos"
|
||||
DXVK_TAR="${DXVK_CACHE}/dxvk-macOS-async.tar.gz"
|
||||
DXVK_URL="https://github.com/Gcenx/DXVK-macOS/releases/download/v1.10.3-20230507-repack/dxvk-macOS-async-v1.10.3-20230507-repack.tar.gz"
|
||||
DXVK_DIR="${DXVK_CACHE}/dxvk-macOS-async-v1.10.3-20230507-repack"
|
||||
DXVK_X64="${DXVK_DIR}/x64"
|
||||
WINE_LIB64="${WHISKY_LIBS}/Libraries/Wine/lib/wine/x86_64-windows"
|
||||
SYS32="${BOTTLE_DIR}/drive_c/windows/system32"
|
||||
|
||||
gog_wine_check
|
||||
mkdir -p "${DXVK_CACHE}"
|
||||
[[ -f "${DXVK_TAR}" ]] || curl -L --fail -o "${DXVK_TAR}" "${DXVK_URL}"
|
||||
[[ -f "${DXVK_X64}/d3d11.dll" ]] || tar -xzf "${DXVK_TAR}" -C "${DXVK_CACHE}"
|
||||
cp -f "${WINE_LIB64}/dxgi.dll" "${SYS32}/dxgi.dll"
|
||||
cp -f "${DXVK_X64}/d3d11.dll" "${SYS32}/d3d11.dll"
|
||||
cp -f "${DXVK_X64}/d3d10core.dll" "${SYS32}/d3d10core.dll"
|
||||
export WINEPREFIX="${BOTTLE_DIR}"
|
||||
export DYLD_LIBRARY_PATH="${WINE_LIB}:${DYLD_LIBRARY_PATH:-}"
|
||||
"${WINE64}" reg add 'HKEY_CURRENT_USER\Software\Wine\DllOverrides' /v d3d11 /d native,b /f >/dev/null
|
||||
"${WINE64}" reg add 'HKEY_CURRENT_USER\Software\Wine\DllOverrides' /v d3d10core /d native,b /f >/dev/null
|
||||
"${WINE64}" reg add 'HKEY_CURRENT_USER\Software\Wine\Direct3D' /v renderer /t REG_SZ /d vulkan /f >/dev/null 2>&1 || true
|
||||
# Whisky UI: DXVK для HoMM; JA3 предпочитает D3DMetal (configure-ja3-d3dmetal.sh)
|
||||
if [[ -f "${BOTTLE_DIR}/Metadata.plist" ]]; then
|
||||
/usr/libexec/PlistBuddy -c 'Set :dxvkConfig:dxvk true' "${BOTTLE_DIR}/Metadata.plist" 2>/dev/null || \
|
||||
/usr/libexec/PlistBuddy -c 'Add :dxvkConfig:dxvk bool true' "${BOTTLE_DIR}/Metadata.plist" 2>/dev/null || true
|
||||
fi
|
||||
echo "OK: DXVK-macOS в ${BOTTLE_NAME}"
|
||||
100
scripts/games/gog/install-galaxy-extract.sh
Executable file
100
scripts/games/gog/install-galaxy-extract.sh
Executable file
@@ -0,0 +1,100 @@
|
||||
#!/usr/bin/env bash
|
||||
# GOG Galaxy в GOG-bottle без Wine-Inno (gdi32/botva2). Как install-gog-galaxy.sh для HoMM.
|
||||
set -euo pipefail
|
||||
GOG_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
# shellcheck source=config.sh
|
||||
source "${GOG_DIR}/config.sh"
|
||||
|
||||
GAMES_DIR="$(cd "${GOG_DIR}/.." && pwd)"
|
||||
GOG_SETUP="${GAMES_CACHE_DIR:-${GAMES_DIR}/cache}/setup_galaxy.exe"
|
||||
EXTRACT_DIR="${GAMES_CACHE_DIR:-${GAMES_DIR}/cache}/gog-galaxy-extract-gog-bottle"
|
||||
GOG_PF="${BOTTLE_DIR}/drive_c/Program Files (x86)/GOG Galaxy"
|
||||
GOG_PD="${BOTTLE_DIR}/drive_c/ProgramData/GOG.com/Galaxy"
|
||||
MARKER="${BOTTLE_DIR}/.gog_galaxy_extract_installed"
|
||||
|
||||
gog_galaxy_exe() {
|
||||
if [[ -f "${GOG_PF}/GalaxyClient.exe" ]]; then
|
||||
echo "${GOG_PF}/GalaxyClient.exe"
|
||||
return 0
|
||||
fi
|
||||
local found
|
||||
found="$(find "${BOTTLE_DIR}/drive_c/Program Files"* -maxdepth 3 -name 'GalaxyClient.exe' 2>/dev/null | head -1)"
|
||||
[[ -n "${found}" ]] && echo "${found}" && return 0
|
||||
return 1
|
||||
}
|
||||
|
||||
homm_gog_setup_url() {
|
||||
if [[ -n "${GOG_SETUP_URL:-}" ]]; then
|
||||
echo "${GOG_SETUP_URL}"
|
||||
return 0
|
||||
fi
|
||||
local json url
|
||||
json="$(curl -fsSL "https://remote-config.gog.com/components/webinstaller?component_version=2.0.0")"
|
||||
url="$(python3 -c 'import json,sys; d=json.load(sys.stdin); print(d["content"]["windows"]["downloadLink"])' <<<"${json}" 2>/dev/null)" || true
|
||||
if [[ -z "${url}" ]]; then
|
||||
url="https://content-system.gog.com/open_link/download?path=/open/galaxy/client/setup_galaxy_2.0.100.1.exe"
|
||||
fi
|
||||
echo "${url}"
|
||||
}
|
||||
|
||||
main() {
|
||||
gog_wine_check
|
||||
gog_disk_guard 3 || exit 1
|
||||
|
||||
if gog_galaxy_exe >/dev/null 2>&1; then
|
||||
echo "GOG Galaxy уже в bottle: $(gog_galaxy_exe)"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ ! -f "${GOG_SETUP}" ]]; then
|
||||
mkdir -p "$(dirname "${GOG_SETUP}")"
|
||||
dl_url="$(homm_gog_setup_url)"
|
||||
echo "Скачиваю setup_galaxy.exe (~290 MB)…"
|
||||
curl -L --fail --retry 3 -C - -o "${GOG_SETUP}" "${dl_url}"
|
||||
fi
|
||||
|
||||
if ! command -v innoextract >/dev/null 2>&1; then
|
||||
echo "Нужен innoextract: brew install innoextract"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Распаковка GOG Galaxy (innoextract) → ${BOTTLE_NAME}…"
|
||||
rm -rf "${EXTRACT_DIR}"
|
||||
mkdir -p "${EXTRACT_DIR}"
|
||||
innoextract -e -d "${EXTRACT_DIR}" "${GOG_SETUP}"
|
||||
|
||||
mkdir -p "${GOG_PF}" "${GOG_PD}"
|
||||
cp -R "${EXTRACT_DIR}/app/." "${GOG_PF}/"
|
||||
local pd_src
|
||||
pd_src="$(find "${EXTRACT_DIR}" -type d -path '*/GOG.com/Galaxy' 2>/dev/null | head -1)"
|
||||
if [[ -n "${pd_src}" ]]; then
|
||||
cp -R "${pd_src}/." "${GOG_PD}/"
|
||||
fi
|
||||
|
||||
if ! gog_galaxy_exe >/dev/null 2>&1; then
|
||||
echo "❌ GalaxyClient.exe не найден после распаковки"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "VC++ redist (из setup_galaxy)…"
|
||||
local vc_x86="${EXTRACT_DIR}/tmp/VC_redist.x86.exe"
|
||||
local vc_x64="${EXTRACT_DIR}/tmp/VC_redist.x64.exe"
|
||||
if [[ -f "${vc_x86}" ]]; then
|
||||
export_wine_env_gog
|
||||
cp -f "${vc_x86}" "${BOTTLE_DIR}/drive_c/VC_redist.x86.exe"
|
||||
cp -f "${vc_x64}" "${BOTTLE_DIR}/drive_c/VC_redist.x64.exe"
|
||||
"${WINE64}" C:\\VC_redist.x86.exe /install /quiet /norestart
|
||||
"${WINE64}" C:\\VC_redist.x64.exe /install /quiet /norestart
|
||||
fi
|
||||
|
||||
local fonts_dst="${BOTTLE_DIR}/drive_c/windows/Fonts"
|
||||
mkdir -p "${fonts_dst}"
|
||||
cp -f "${EXTRACT_DIR}"/fonts/*.ttf "${fonts_dst}/" 2>/dev/null || true
|
||||
|
||||
bash "${GOG_DIR}/register-galaxy-registry.sh"
|
||||
|
||||
date -u +%Y-%m-%dT%H:%M:%SZ >"${MARKER}"
|
||||
echo "OK: $(gog_galaxy_exe)"
|
||||
}
|
||||
|
||||
main "$@"
|
||||
20
scripts/games/gog/install-gdiplus.sh
Executable file
20
scripts/games/gog/install-gdiplus.sh
Executable file
@@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env bash
|
||||
# MS gdiplus.dll — без этого .NET падает на GenericSansSerif (GdipGetGenericFontFamilySansSerif).
|
||||
set -euo pipefail
|
||||
GOG_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
# shellcheck source=config.sh
|
||||
source "${GOG_DIR}/config.sh"
|
||||
|
||||
gog_wine_check
|
||||
command -v winetricks >/dev/null || { echo "brew install winetricks"; exit 1; }
|
||||
|
||||
export WINE="${WINE64}"
|
||||
export WINEPREFIX="${BOTTLE_DIR}"
|
||||
export DYLD_LIBRARY_PATH="${WINE_LIB}:${DYLD_LIBRARY_PATH:-}"
|
||||
export WINEDEBUG=-all
|
||||
|
||||
echo "winetricks gdiplus (~3–5 мин, скачает win7sp1)…"
|
||||
winetricks -q gdiplus
|
||||
|
||||
touch "${BOTTLE_DIR}/.gog_gdiplus_installed"
|
||||
echo "OK: gdiplus в ${BOTTLE_NAME}"
|
||||
51
scripts/games/gog/install-gptk-whisky.sh
Executable file
51
scripts/games/gog/install-gptk-whisky.sh
Executable file
@@ -0,0 +1,51 @@
|
||||
#!/usr/bin/env bash
|
||||
# Apple D3DMetal (GPTK) в Whisky Libraries — только framework + unix-мост.
|
||||
# НЕ ditto всего GPTK lib (перезапишет wine64 на 7.7 и сломает bottle).
|
||||
# Канон: https://github.com/Whisky-App/Whisky/issues/124
|
||||
set -euo pipefail
|
||||
GOG_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
# shellcheck source=config.sh
|
||||
source "${GOG_DIR}/config.sh"
|
||||
|
||||
GPTK_APP="${GPTK_APP:-/Applications/Game Porting Toolkit.app}"
|
||||
GPTK_WINE="${GPTK_APP}/Contents/Resources/wine"
|
||||
WHISKY_WINE="${WHISKY_LIBS}/Libraries/Wine"
|
||||
EXT="${WHISKY_WINE}/lib/external"
|
||||
WINE_UNIX="${WHISKY_WINE}/lib/wine/x86_64-unix"
|
||||
|
||||
[[ -d "${GPTK_WINE}/lib/external/D3DMetal.framework" ]] || {
|
||||
echo "❌ Нет Game Porting Toolkit.app"
|
||||
echo " brew install --cask gcenx/wine/game-porting-toolkit"
|
||||
exit 1
|
||||
}
|
||||
|
||||
mkdir -p "${EXT}"
|
||||
ditto "${GPTK_WINE}/lib/external/D3DMetal.framework" "${EXT}/D3DMetal.framework"
|
||||
cp -f "${GPTK_WINE}/lib/external/libd3dshared.dylib" "${EXT}/libd3dshared.dylib"
|
||||
|
||||
# @rpath @loader_path — копия в корень lib/ (fixmywhisky)
|
||||
cp -Rf "${EXT}/D3DMetal.framework" "${WHISKY_WINE}/lib/D3DMetal.framework"
|
||||
cp -f "${EXT}/libd3dshared.dylib" "${WHISKY_WINE}/lib/libd3dshared.dylib"
|
||||
|
||||
fix_d3dmetal_fw() {
|
||||
local fw="$1"
|
||||
[[ -d "${fw}/Versions" ]] || return 0
|
||||
rm -f "${fw}/D3DMetal" "${fw}/Resources" 2>/dev/null || true
|
||||
ln -sf Versions/Current/D3DMetal "${fw}/D3DMetal"
|
||||
ln -sf Versions/Current/Resources "${fw}/Resources"
|
||||
chmod +x "${fw}/Versions/Current/D3DMetal" 2>/dev/null || true
|
||||
xattr -d com.apple.quarantine "${fw}" 2>/dev/null || true
|
||||
}
|
||||
fix_d3dmetal_fw "${EXT}/D3DMetal.framework"
|
||||
fix_d3dmetal_fw "${WHISKY_WINE}/lib/D3DMetal.framework"
|
||||
chmod +x "${EXT}/libd3dshared.dylib" "${WHISKY_WINE}/lib/libd3dshared.dylib" 2>/dev/null || true
|
||||
xattr -d com.apple.quarantine "${EXT}/libd3dshared.dylib" 2>/dev/null || true
|
||||
|
||||
# Мост D3DMetal: unix .so → libd3dshared. PE d3d12/dxgi — от Gcenx Wine 11.x (не GPTK 7.7).
|
||||
mkdir -p "${WINE_UNIX}"
|
||||
ln -sf ../../external/libd3dshared.dylib "${WINE_UNIX}/d3d12.so"
|
||||
ln -sf ../../external/libd3dshared.dylib "${WINE_UNIX}/dxgi.so"
|
||||
|
||||
touch "${WHISKY_LIBS}/Libraries/.gptk_installed"
|
||||
echo "OK: GPTK D3DMetal + d3d12/dxgi bridge → ${WHISKY_WINE}"
|
||||
echo " Запуск: bash ${GOG_DIR}/prepare-ja3-d3dmetal.sh && bash ${GOG_DIR}/run-ja3.sh"
|
||||
58
scripts/games/gog/install-ja3-dxmt.sh
Executable file
58
scripts/games/gog/install-ja3-dxmt.sh
Executable file
@@ -0,0 +1,58 @@
|
||||
#!/usr/bin/env bash
|
||||
# DXMT (D3D10/11 → Metal) для JA3 без GPTK. JA3 на D3D12 всё равно нужен GPTK; скрипт + -graphicsapi d3d11.
|
||||
set -euo pipefail
|
||||
GOG_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
GAMES_DIR="$(cd "${GOG_DIR}/.." && pwd)"
|
||||
# shellcheck source=config.sh
|
||||
source "${GOG_DIR}/config.sh"
|
||||
|
||||
DXMT_CACHE="${GAMES_DIR}/cache/dxmt"
|
||||
DXMT_TAR="${DXMT_CACHE}/dxmt-v0.80-builtin.tar.gz"
|
||||
DXMT_URL="https://github.com/3Shain/dxmt/releases/download/v0.80/dxmt-v0.80-builtin.tar.gz"
|
||||
WINE_LIB="${WHISKY_LIBS}/Libraries/Wine/lib"
|
||||
WINE_LIB64="${WINE_LIB}/wine/x86_64-windows"
|
||||
WINE_UNIX="${WINE_LIB}/wine/x86_64-unix"
|
||||
SYS32="${BOTTLE_DIR}/drive_c/windows/system32"
|
||||
|
||||
gog_wine_check
|
||||
mkdir -p "${DXMT_CACHE}" "${SYS32}"
|
||||
[[ -f "${DXMT_TAR}" ]] || curl -L --fail -o "${DXMT_TAR}" "${DXMT_URL}"
|
||||
tar -xzf "${DXMT_TAR}" -C "${DXMT_CACHE}"
|
||||
|
||||
# builtin layout: bin/ or root with dlls — find files
|
||||
DXMT_ROOT="${DXMT_CACHE}"
|
||||
for sub in dxmt-v0.80-builtin bin .; do
|
||||
[[ -f "${DXMT_CACHE}/${sub}/d3d11.dll" ]] && DXMT_ROOT="${DXMT_CACHE}/${sub}" && break
|
||||
done
|
||||
[[ -f "${DXMT_ROOT}/d3d11.dll" ]] || DXMT_ROOT="$(find "${DXMT_CACHE}" -name d3d11.dll -print -quit | xargs dirname)"
|
||||
|
||||
install_one() {
|
||||
local src="$1" dest="$2"
|
||||
[[ -f "${src}" ]] || return 0
|
||||
cp -f "${src}" "${dest}/"
|
||||
}
|
||||
|
||||
install_one "${DXMT_ROOT}/winemetal.so" "${WINE_UNIX}"
|
||||
install_one "${DXMT_ROOT}/winemetal.dll" "${WINE_LIB64}"
|
||||
install_one "${DXMT_ROOT}/winemetal.dll" "${SYS32}"
|
||||
install_one "${DXMT_ROOT}/d3d11.dll" "${WINE_LIB64}"
|
||||
install_one "${DXMT_ROOT}/dxgi.dll" "${WINE_LIB64}"
|
||||
install_one "${DXMT_ROOT}/d3d10core.dll" "${WINE_LIB64}"
|
||||
# Только wine lib + system32 (не в папку игры — иначе конфликт с overrides).
|
||||
install_one "${DXMT_ROOT}/d3d11.dll" "${SYS32}"
|
||||
install_one "${DXMT_ROOT}/dxgi.dll" "${SYS32}"
|
||||
install_one "${DXMT_ROOT}/d3d10core.dll" "${SYS32}"
|
||||
|
||||
export WINEPREFIX="${BOTTLE_DIR}"
|
||||
export DYLD_LIBRARY_PATH="${WINE_LIB}:${DYLD_LIBRARY_PATH:-}"
|
||||
"${WINE64}" reg add 'HKEY_CURRENT_USER\Software\Wine\DllOverrides' /v d3d12 /d disabled /f >/dev/null 2>&1 || true
|
||||
"${WINE64}" reg delete 'HKEY_CURRENT_USER\Software\Wine\DllOverrides' /v d3d11 /f >/dev/null 2>&1 || true
|
||||
"${WINE64}" reg delete 'HKEY_CURRENT_USER\Software\Wine\DllOverrides' /v d3d10core /f >/dev/null 2>&1 || true
|
||||
"${WINE64}" reg delete 'HKEY_CURRENT_USER\Software\Wine\DllOverrides' /v dxgi /f >/dev/null 2>&1 || true
|
||||
|
||||
touch "${BOTTLE_DIR}/.ja3_dxmt_installed"
|
||||
if [[ -f "${BOTTLE_DIR}/Metadata.plist" ]]; then
|
||||
/usr/libexec/PlistBuddy -c 'Set :dxvkConfig:dxvk false' "${BOTTLE_DIR}/Metadata.plist" 2>/dev/null || true
|
||||
/usr/libexec/PlistBuddy -c 'Set :performanceConfig:forceD3D11 true' "${BOTTLE_DIR}/Metadata.plist" 2>/dev/null || true
|
||||
fi
|
||||
echo "OK: DXMT v0.80 в ${BOTTLE_NAME} (+ game dir)"
|
||||
203
scripts/games/gog/install-ja3-innoextract.sh
Executable file
203
scripts/games/gog/install-ja3-innoextract.sh
Executable file
@@ -0,0 +1,203 @@
|
||||
#!/usr/bin/env bash
|
||||
# JA3: multipart GOG → innoextract в bottle (без Wine-Inno). Экономия диска: .bin удаляются по ходу.
|
||||
set -euo pipefail
|
||||
GOG_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
# shellcheck source=config.sh
|
||||
source "${GOG_DIR}/config.sh"
|
||||
|
||||
JA3_GAMES_DIR="${JA3_GAMES_DIR:-${HOME}/Games}"
|
||||
JA3_PREFIX='setup_jagged_alliance_3_1.5.2_(80730)'
|
||||
JA3_EXE="${JA3_GAMES_DIR}/${JA3_PREFIX}.exe"
|
||||
JA3_TARGET="${BOTTLE_DIR}/drive_c/GOG Games/Jagged Alliance 3"
|
||||
MARKER="${BOTTLE_DIR}/.ja3_installed"
|
||||
LOG="/tmp/ja3-innoextract-${BOTTLE_NAME}.log"
|
||||
JA3_MIN_FREE_MB="${JA3_MIN_FREE_MB:-800}"
|
||||
JA3_KEEP_BINS="${JA3_KEEP_BINS:-0}"
|
||||
|
||||
gog_disk_free_mb() {
|
||||
local kb
|
||||
kb="$(gog_disk_free_kb)"
|
||||
echo $((kb / 1024))
|
||||
}
|
||||
|
||||
gog_disk_watch() {
|
||||
local min_mb="$1"
|
||||
local free
|
||||
free="$(gog_disk_free_mb)"
|
||||
if [[ "${free}" -lt "${min_mb}" ]]; then
|
||||
echo "❌ Мало места на диске: ${free} MB свободно (нужно ≥${min_mb} MB)" >&2
|
||||
df -h "$(gog_data_volume_path)" | awk 'NR==2' >&2
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
gog_ja3_safe_cleanup() {
|
||||
local freed=0
|
||||
local d f
|
||||
|
||||
for d in \
|
||||
"${GAMES_CACHE_DIR}/gog-galaxy-extract-gog-bottle" \
|
||||
"${GAMES_CACHE_DIR}/ja3-extract-test" \
|
||||
"${GAMES_CACHE_DIR}/ja3-innoextract-staging"; do
|
||||
if [[ -d "${d}" ]]; then
|
||||
local sz
|
||||
sz="$(du -sk "${d}" | awk '{print $1}')"
|
||||
rm -rf "${d}"
|
||||
freed=$((freed + sz))
|
||||
echo " удалён cache: ${d}"
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ -f "${GAMES_CACHE_DIR}/setup_galaxy.exe" ]] \
|
||||
&& [[ -f "${BOTTLE_DIR}/drive_c/Program Files (x86)/GOG Galaxy/GalaxyClient.exe" ]]; then
|
||||
f="${GAMES_CACHE_DIR}/setup_galaxy.exe"
|
||||
sz="$(du -sk "${f}" | awk '{print $1}')"
|
||||
rm -f "${f}"
|
||||
freed=$((freed + sz))
|
||||
echo " удалён setup_galaxy.exe (Galaxy уже в bottle)"
|
||||
fi
|
||||
|
||||
if [[ "${freed}" -gt 0 ]]; then
|
||||
echo "Освобождено ~$((freed / 1024)) MB (cache)"
|
||||
fi
|
||||
}
|
||||
|
||||
ja3_bin_path() {
|
||||
echo "${JA3_GAMES_DIR}/${JA3_PREFIX}-$1.bin"
|
||||
}
|
||||
|
||||
ja3_delete_bin() {
|
||||
local n="$1"
|
||||
local p
|
||||
p="$(ja3_bin_path "${n}")"
|
||||
if [[ -f "${p}" ]]; then
|
||||
rm -f "${p}"
|
||||
echo " 🗑 удалён $(basename "${p}") (~$(du -sh "${p}" 2>/dev/null | cut -f1 || echo '?'))"
|
||||
gog_disk_watch "${JA3_MIN_FREE_MB}" || true
|
||||
fi
|
||||
}
|
||||
|
||||
ja3_delete_all_bins() {
|
||||
local n
|
||||
for n in 1 2 3 4; do
|
||||
ja3_delete_bin "${n}" || true
|
||||
done
|
||||
if [[ -f "${JA3_EXE}" && "${JA3_KEEP_BINS}" != "1" ]]; then
|
||||
rm -f "${JA3_EXE}"
|
||||
echo " 🗑 удалён $(basename "${JA3_EXE}")"
|
||||
fi
|
||||
}
|
||||
|
||||
ja3_watch_bins() {
|
||||
local line opened=0
|
||||
while IFS= read -r line; do
|
||||
printf '%s\n' "${line}"
|
||||
case "${line}" in
|
||||
*"Opening \"${JA3_PREFIX}-2.bin\""*)
|
||||
ja3_delete_bin 1
|
||||
opened=2
|
||||
;;
|
||||
*"Opening \"${JA3_PREFIX}-3.bin\""*)
|
||||
ja3_delete_bin 2
|
||||
opened=3
|
||||
;;
|
||||
*"Opening \"${JA3_PREFIX}-4.bin\""*)
|
||||
ja3_delete_bin 3
|
||||
opened=4
|
||||
;;
|
||||
esac
|
||||
gog_disk_watch "${JA3_MIN_FREE_MB}" || return 1
|
||||
done
|
||||
if [[ "${opened}" -ge 4 ]]; then
|
||||
ja3_delete_bin 4 || true
|
||||
fi
|
||||
}
|
||||
|
||||
verify() {
|
||||
local n
|
||||
[[ -f "${JA3_EXE}" ]] || {
|
||||
echo "❌ Нет: ${JA3_EXE}"
|
||||
return 1
|
||||
}
|
||||
for n in 1 2 3 4; do
|
||||
[[ -f "$(ja3_bin_path "${n}")" ]] || {
|
||||
echo "❌ Нет: $(ja3_bin_path "${n}")"
|
||||
return 1
|
||||
}
|
||||
done
|
||||
command -v innoextract >/dev/null 2>&1 || {
|
||||
echo "❌ brew install innoextract"
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
main() {
|
||||
verify || exit 1
|
||||
gog_wine_check
|
||||
|
||||
if [[ -f "${JA3_TARGET}/JA3.exe" ]]; then
|
||||
echo "JA3 уже установлен: ${JA3_TARGET}/JA3.exe"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
bash "${GOG_DIR}/emergency-stop.sh" || true
|
||||
|
||||
echo "=== Очистка cache (без трогания архивов игры) ==="
|
||||
gog_ja3_safe_cleanup
|
||||
|
||||
gog_disk_watch "${JA3_MIN_FREE_MB}" || {
|
||||
echo "❌ Перед установкой нужно ≥$((JA3_MIN_FREE_MB / 1024)) GB свободно."
|
||||
exit 1
|
||||
}
|
||||
|
||||
echo ""
|
||||
echo "Свободно на Data: $(gog_disk_free_mb) MB"
|
||||
echo "Распаковка JA3 → ${JA3_TARGET}"
|
||||
echo "Лог: ${LOG}"
|
||||
echo "(архивы .bin удаляются по мере чтения innoextract)"
|
||||
echo ""
|
||||
|
||||
rm -rf "${JA3_TARGET}"
|
||||
mkdir -p "${JA3_TARGET}"
|
||||
: >"${LOG}"
|
||||
|
||||
cd "${JA3_GAMES_DIR}"
|
||||
set +e
|
||||
innoextract -e -m -d "${JA3_TARGET}" "$(basename "${JA3_EXE}")" 2>&1 \
|
||||
| tee "${LOG}" | ja3_watch_bins
|
||||
local rc=${PIPESTATUS[0]}
|
||||
set -e
|
||||
|
||||
if [[ "${rc}" -ne 0 ]]; then
|
||||
echo ""
|
||||
echo "❌ innoextract exit ${rc}"
|
||||
tail -15 "${LOG}" 2>/dev/null || true
|
||||
df -h "$(gog_data_volume_path)" | awk 'NR==2'
|
||||
if [[ "${JA3_CLEANUP_PARTIAL:-1}" == "1" ]]; then
|
||||
echo "Удаляю незавершённую распаковку в bottle…"
|
||||
rm -rf "${JA3_TARGET}"
|
||||
fi
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -f "${JA3_TARGET}/JA3.exe" ]]; then
|
||||
bash "${GOG_DIR}/finish-ja3-layout.sh"
|
||||
date -u +"%Y-%m-%dT%H:%M:%SZ" >"${MARKER}"
|
||||
if [[ "${JA3_KEEP_BINS}" != "1" ]]; then
|
||||
echo ""
|
||||
echo "Удаляю GOG-архивы (~15 GB)…"
|
||||
ja3_delete_all_bins
|
||||
fi
|
||||
echo ""
|
||||
echo "OK: JA3 установлен."
|
||||
echo " Свободно: $(gog_disk_free_mb) MB"
|
||||
echo " Запуск: bash ${GOG_DIR}/run-ja3.sh"
|
||||
else
|
||||
echo "❌ JA3.exe не найден"
|
||||
find "${JA3_TARGET}" -maxdepth 2 -iname 'JA3.exe' 2>/dev/null | head -5
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
main "$@"
|
||||
152
scripts/games/gog/install-ja3-multipart.sh
Executable file
152
scripts/games/gog/install-ja3-multipart.sh
Executable file
@@ -0,0 +1,152 @@
|
||||
#!/usr/bin/env bash
|
||||
# JA3 из GOG offline backup: setup_*.exe + setup_*-1.bin … -4.bin в одной папке.
|
||||
# Galaxy не нужен. Установщик читает .bin рядом с .exe (не копируем 15 GB в bottle).
|
||||
set -euo pipefail
|
||||
GOG_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
# shellcheck source=config.sh
|
||||
source "${GOG_DIR}/config.sh"
|
||||
|
||||
JA3_GAMES_DIR="${JA3_GAMES_DIR:-${HOME}/Games}"
|
||||
JA3_SETUP_EXE="${JA3_SETUP_EXE:-}"
|
||||
LOG="/tmp/ja3-multipart-install-${BOTTLE_NAME}.log"
|
||||
|
||||
# Имена GOG v1.5.2 (80730); при другой версии задайте JA3_SETUP_EXE.
|
||||
JA3_EXE_DEFAULT="${JA3_GAMES_DIR}/setup_jagged_alliance_3_1.5.2_(80730).exe"
|
||||
JA3_BINS=(
|
||||
"${JA3_GAMES_DIR}/setup_jagged_alliance_3_1.5.2_(80730)-1.bin"
|
||||
"${JA3_GAMES_DIR}/setup_jagged_alliance_3_1.5.2_(80730)-2.bin"
|
||||
"${JA3_GAMES_DIR}/setup_jagged_alliance_3_1.5.2_(80730)-3.bin"
|
||||
"${JA3_GAMES_DIR}/setup_jagged_alliance_3_1.5.2_(80730)-4.bin"
|
||||
)
|
||||
|
||||
gog_unix_to_win() {
|
||||
local u="$1"
|
||||
if [[ -x "${WINEPATH_BIN}" ]]; then
|
||||
"${WINEPATH_BIN}" -w "${u}"
|
||||
else
|
||||
# fallback: Z: = /
|
||||
local rest="${u#/}"
|
||||
echo "Z:\\\\${rest//\//\\\\}"
|
||||
fi
|
||||
}
|
||||
|
||||
find_setup_exe() {
|
||||
if [[ -n "${JA3_SETUP_EXE}" && -f "${JA3_SETUP_EXE}" ]]; then
|
||||
echo "${JA3_SETUP_EXE}"
|
||||
return 0
|
||||
fi
|
||||
if [[ -f "${JA3_EXE_DEFAULT}" ]]; then
|
||||
echo "${JA3_EXE_DEFAULT}"
|
||||
return 0
|
||||
fi
|
||||
local f
|
||||
f="$(find "${JA3_GAMES_DIR}" -maxdepth 1 -iname 'setup*jagged*alliance*3*.exe' -print -quit 2>/dev/null || true)"
|
||||
[[ -n "${f}" && -f "${f}" ]] && echo "${f}" && return 0
|
||||
return 1
|
||||
}
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Использование: bash $0
|
||||
|
||||
Папка с архивами (по умолчанию): ${JA3_GAMES_DIR}
|
||||
|
||||
Нужны 5 файлов в одной папке:
|
||||
setup_jagged_alliance_3_1.5.2_(80730).exe (~1 MB, лаунчер Inno)
|
||||
setup_jagged_alliance_3_1.5.2_(80730)-1.bin … -4.bin
|
||||
|
||||
Скачать недостающий .exe: https://www.gog.com/account → JA3 → offline backup (первая, ~1 MB часть).
|
||||
|
||||
Или:
|
||||
lgogdownloader --login
|
||||
bash ${GOG_DIR}/fetch-ja3-setup-exe.sh
|
||||
|
||||
Переменные: JA3_GAMES_DIR, JA3_SETUP_EXE
|
||||
EOF
|
||||
}
|
||||
|
||||
verify_parts() {
|
||||
local exe="$1"
|
||||
local missing=0
|
||||
local b
|
||||
|
||||
if [[ ! -d "${JA3_GAMES_DIR}" ]]; then
|
||||
echo "❌ Нет каталога: ${JA3_GAMES_DIR}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
for b in "${JA3_BINS[@]}"; do
|
||||
if [[ ! -f "${b}" ]]; then
|
||||
echo "❌ Нет: ${b}"
|
||||
missing=1
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ ! -f "${exe}" ]]; then
|
||||
echo "❌ Нет лаунчера .exe (~1 MB) в ${JA3_GAMES_DIR}"
|
||||
echo " У вас есть 4× .bin — без .exe установка GOG не стартует."
|
||||
echo " Скачайте с account.gog.com первую часть offline backup (installer0, ~1 MB)."
|
||||
echo " Или: bash ${GOG_DIR}/fetch-ja3-setup-exe.sh"
|
||||
missing=1
|
||||
fi
|
||||
|
||||
[[ "${missing}" -eq 0 ]]
|
||||
}
|
||||
|
||||
main() {
|
||||
local exe win_exe
|
||||
exe="$(find_setup_exe)" || exe=""
|
||||
|
||||
if ! verify_parts "${exe}"; then
|
||||
echo ""
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
bash "${GOG_DIR}/emergency-stop.sh" || true
|
||||
gog_swap_guard "${GOG_SWAP_MAX_MB:-400}" || exit 1
|
||||
# bins (~15 GB) + распаковка в bottle (~16 GB) — пик ~25–30 GB на Data
|
||||
gog_disk_guard "${JA3_MIN_DISK_GB:-25}" || {
|
||||
echo "❌ Мало места: нужно ≥25 GB свободно на Data (архивы + игра в bottle)."
|
||||
echo " Сейчас: $(df -h "$(gog_data_volume_path)" | awk 'NR==2 {print $4 " свободно, " $5 " занято"}')"
|
||||
exit 1
|
||||
}
|
||||
|
||||
export_wine_env_gog
|
||||
gog_wine_check
|
||||
|
||||
win_exe="$(gog_unix_to_win "${exe}")"
|
||||
SILENT=(/VERYSILENT /SUPPRESSMSGBOXES /NORESTART)
|
||||
|
||||
echo "Установка JA3 из multipart (без Galaxy)"
|
||||
echo " Папка: ${JA3_GAMES_DIR}"
|
||||
echo " Wine: ${win_exe}"
|
||||
echo " Лог: ${LOG}"
|
||||
: >"${LOG}"
|
||||
|
||||
# Inno ищет .bin в каталоге установщика — запуск из JA3_GAMES_DIR
|
||||
cd "${JA3_GAMES_DIR}"
|
||||
if ! "${WINE64}" "${win_exe}" "${SILENT[@]}" >>"${LOG}" 2>&1; then
|
||||
echo "⚠️ Wine-Inno не прошёл — пробуем innoextract (без botva2/gdi32)…"
|
||||
if command -v innoextract >/dev/null 2>&1; then
|
||||
exec bash "${GOG_DIR}/install-ja3-innoextract.sh"
|
||||
fi
|
||||
echo "❌ Установщик завершился с ошибкой:"
|
||||
strings "${LOG}" 2>/dev/null | tail -20 || tail -20 "${LOG}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -f "${BOTTLE_DIR}/drive_c/GOG Games/Jagged Alliance 3/JA3.exe" ]]; then
|
||||
date -u +"%Y-%m-%dT%H:%M:%SZ" >"${BOTTLE_DIR}/.ja3_installed"
|
||||
echo ""
|
||||
echo "OK: JA3 установлен."
|
||||
echo " Запуск: bash ${GOG_DIR}/run-ja3.sh"
|
||||
echo " После проверки игры можно удалить .bin в ${JA3_GAMES_DIR} (~15 GB)."
|
||||
else
|
||||
echo "⚠️ JA3.exe не найден в bottle — tail лога:"
|
||||
tail -40 "${LOG}"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
main "$@"
|
||||
64
scripts/games/gog/install-ja3-offline.sh
Executable file
64
scripts/games/gog/install-ja3-offline.sh
Executable file
@@ -0,0 +1,64 @@
|
||||
#!/usr/bin/env bash
|
||||
# JA3 из GOG offline backup installer — без Galaxy. Inno /VERYSILENT.
|
||||
set -euo pipefail
|
||||
GOG_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
GAMES_DIR="$(cd "${GOG_DIR}/.." && pwd)"
|
||||
# shellcheck source=config.sh
|
||||
source "${GOG_DIR}/config.sh"
|
||||
|
||||
INSTALLER="${1:-}"
|
||||
LOG="/tmp/ja3-offline-install-${BOTTLE_NAME}.log"
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Использование: bash $0 /path/to/setup_jagged_alliance_3_*.exe
|
||||
|
||||
Скачать (Windows offline backup):
|
||||
https://www.gog.com/account → Jagged Alliance 3 → Download offline backup game installers
|
||||
|
||||
Документация: docs/games/JA3_MAC_WITHOUT_GALAXY.md
|
||||
EOF
|
||||
}
|
||||
|
||||
if [[ -z "${INSTALLER}" || ! -f "${INSTALLER}" ]]; then
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
bash "${GOG_DIR}/emergency-stop.sh"
|
||||
gog_swap_guard "${GOG_SWAP_MAX_MB:-400}" || exit 1
|
||||
gog_disk_guard 40 || {
|
||||
echo "❌ Для JA3 нужно ~40+ GB свободно на Data (игра + установка)."
|
||||
exit 1
|
||||
}
|
||||
|
||||
export_wine_env_gog
|
||||
gog_wine_check
|
||||
|
||||
# Inno silent (GOG offline installers)
|
||||
SILENT=(/VERYSILENT /SUPPRESSMSGBOXES /NORESTART)
|
||||
local_base="$(basename "${INSTALLER}")"
|
||||
cp -f "${INSTALLER}" "${BOTTLE_DIR}/drive_c/${local_base}"
|
||||
|
||||
win="C:\\${local_base}"
|
||||
echo "Установка JA3 (без Galaxy): ${INSTALLER}"
|
||||
echo "Лог: ${LOG}"
|
||||
: >"${LOG}"
|
||||
|
||||
cd "${BOTTLE_DIR}/drive_c"
|
||||
if ! "${WINE64}" "${win}" "${SILENT[@]}" >>"${LOG}" 2>&1; then
|
||||
echo "❌ Установщик завершился с ошибкой. tail:"
|
||||
tail -40 "${LOG}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -f "${BOTTLE_DIR}/drive_c/GOG Games/Jagged Alliance 3/JA3.exe" ]]; then
|
||||
date -u +"%Y-%m-%dT%H:%M:%SZ" >"${BOTTLE_DIR}/.ja3_installed"
|
||||
echo ""
|
||||
echo "OK: JA3 установлен."
|
||||
echo " Запуск: bash ${GOG_DIR}/run-ja3.sh"
|
||||
else
|
||||
echo "⚠️ JA3.exe пока не найден — проверьте лог, возможно нужны ещё offline .exe (DLC/base):"
|
||||
tail -30 "${LOG}"
|
||||
exit 1
|
||||
fi
|
||||
35
scripts/games/gog/install-ja3-redist.sh
Executable file
35
scripts/games/gog/install-ja3-redist.sh
Executable file
@@ -0,0 +1,35 @@
|
||||
#!/usr/bin/env bash
|
||||
# VC++ 2015 из __redist JA3 (innoextract не запускает установщики).
|
||||
set -euo pipefail
|
||||
GOG_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
# shellcheck source=config.sh
|
||||
source "${GOG_DIR}/config.sh"
|
||||
|
||||
JA3="${BOTTLE_DIR}/drive_c/GOG Games/Jagged Alliance 3"
|
||||
VC_X86="${JA3}/__redist/MSVC2015/VC_redist.x86.exe"
|
||||
VC_X64="${JA3}/__redist/MSVC2015_x64/VC_redist.x64.exe"
|
||||
MARKER="${BOTTLE_DIR}/.ja3_redist_installed"
|
||||
|
||||
[[ -f "${JA3}/JA3.exe" ]] || {
|
||||
echo "❌ Сначала install-ja3-innoextract.sh"
|
||||
exit 1
|
||||
}
|
||||
|
||||
if [[ -f "${MARKER}" ]]; then
|
||||
echo "JA3 redist уже ставился: ${MARKER}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
export_wine_env_gog
|
||||
gog_wine_check
|
||||
|
||||
for vc in "${VC_X86}" "${VC_X64}"; do
|
||||
[[ -f "${vc}" ]] || continue
|
||||
base="$(basename "${vc}")"
|
||||
cp -f "${vc}" "${BOTTLE_DIR}/drive_c/${base}"
|
||||
echo "VC++ ${base}…"
|
||||
"${WINE64}" "C:\\${base}" /install /quiet /norestart || true
|
||||
done
|
||||
|
||||
date -u +"%Y-%m-%dT%H:%M:%SZ" >"${MARKER}"
|
||||
echo "OK: VC++ redist для JA3"
|
||||
53
scripts/games/gog/install-ja3-wine-finish.sh
Executable file
53
scripts/games/gog/install-ja3-wine-finish.sh
Executable file
@@ -0,0 +1,53 @@
|
||||
#!/usr/bin/env bash
|
||||
# Довести установку JA3 через Wine-Inno (пост-скрипты GOG), если есть архивы в JA3_GAMES_DIR.
|
||||
# innoextract одного не хватает для Lua/VFS — Wine-установщик создаёт правильный layout.
|
||||
set -euo pipefail
|
||||
GOG_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
# shellcheck source=config.sh
|
||||
source "${GOG_DIR}/config.sh"
|
||||
|
||||
JA3_GAMES_DIR="${JA3_GAMES_DIR:-${HOME}/Games}"
|
||||
PREFIX='setup_jagged_alliance_3_1.5.2_(80730)'
|
||||
EXE="${JA3_GAMES_DIR}/${PREFIX}.exe"
|
||||
TARGET='C:\GOG Games\Jagged Alliance 3'
|
||||
|
||||
verify_archives() {
|
||||
[[ -f "${EXE}" ]] || {
|
||||
echo "❌ Нет ${EXE}"
|
||||
echo " Положите 5 частей offline backup в ${JA3_GAMES_DIR}"
|
||||
exit 1
|
||||
}
|
||||
local n
|
||||
for n in 1 2 3 4; do
|
||||
[[ -f "${JA3_GAMES_DIR}/${PREFIX}-${n}.bin" ]] || {
|
||||
echo "❌ Нет ${JA3_GAMES_DIR}/${PREFIX}-${n}.bin"
|
||||
exit 1
|
||||
}
|
||||
done
|
||||
}
|
||||
|
||||
main() {
|
||||
verify_archives
|
||||
bash "${GOG_DIR}/emergency-stop.sh" || true
|
||||
gog_swap_guard "${GOG_SWAP_MAX_MB:-800}" || exit 1
|
||||
gog_disk_guard 20 || exit 1
|
||||
|
||||
export_wine_env_gog
|
||||
gog_wine_check
|
||||
|
||||
local win
|
||||
win="$("${WINEPATH_BIN}" -w "${EXE}")"
|
||||
echo "Wine-установщик GOG (пост-скрипты, Lua.hpk)…"
|
||||
echo " ${win}"
|
||||
cd "${JA3_GAMES_DIR}"
|
||||
if ! "${WINE64}" "${win}" /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /DIR="${TARGET}"; then
|
||||
echo "❌ Wine-Inno упал — см. docs/games/TROUBLESHOOTING.md § Setup gdi32"
|
||||
echo " Запасной путь: innoextract + -unpacked (run-ja3.sh)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
bash "${GOG_DIR}/finish-ja3-layout.sh"
|
||||
echo "OK. Запуск: bash ${GOG_DIR}/run-ja3.sh"
|
||||
}
|
||||
|
||||
main "$@"
|
||||
66
scripts/games/gog/install-ja3.sh
Executable file
66
scripts/games/gog/install-ja3.sh
Executable file
@@ -0,0 +1,66 @@
|
||||
#!/usr/bin/env bash
|
||||
# JA3 без GOG Galaxy: подготовка bottle + подсказка по offline installer.
|
||||
set -euo pipefail
|
||||
GOG_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
|
||||
echo "=== Jagged Alliance 3 без GOG Galaxy ==="
|
||||
echo "Док: docs/games/JA3_MAC_WITHOUT_GALAXY.md"
|
||||
echo ""
|
||||
|
||||
bash "${GOG_DIR}/emergency-stop.sh" || true
|
||||
|
||||
USED="$(bash -c 'source '"${GOG_DIR}"'/config.sh 2>/dev/null; gog_swap_used_mb' 2>/dev/null || echo 0)"
|
||||
if [[ "${USED:-0}" -gt 400 ]] 2>/dev/null; then
|
||||
echo "❌ Swap ~${USED}MB — сначала перезагрузите Mac, затем снова этот скрипт."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
bash "${GOG_DIR}/setup-ja3-bottle.sh"
|
||||
|
||||
echo ""
|
||||
echo "=== Скачайте offline installer (Windows) ==="
|
||||
echo " https://www.gog.com/account → Jagged Alliance 3"
|
||||
echo " → Download offline backup game installers (все части)"
|
||||
echo ""
|
||||
open "https://www.gog.com/account" 2>/dev/null || true
|
||||
|
||||
JA3_GAMES_DIR="${HOME}/Games"
|
||||
ja3_bins_ok=1
|
||||
for n in 1 2 3 4; do
|
||||
[[ -f "${JA3_GAMES_DIR}/setup_jagged_alliance_3_1.5.2_(80730)-${n}.bin" ]] || ja3_bins_ok=0
|
||||
done
|
||||
if [[ "${ja3_bins_ok}" -eq 1 ]]; then
|
||||
echo "Найдены 4× .bin в ${JA3_GAMES_DIR} — multipart offline backup."
|
||||
if [[ -f "${JA3_GAMES_DIR}/setup_jagged_alliance_3_1.5.2_(80730).exe" ]] \
|
||||
|| find "${JA3_GAMES_DIR}" -maxdepth 1 -iname 'setup*jagged*alliance*3*.exe' -print -quit 2>/dev/null | grep -q .; then
|
||||
echo "Запуск install-ja3-innoextract.sh (innoextract, без Wine-Inno) …"
|
||||
exec bash "${GOG_DIR}/install-ja3-innoextract.sh"
|
||||
fi
|
||||
echo "❌ Не хватает лаунчера .exe (~1 MB) рядом с .bin."
|
||||
echo " Скачайте с https://www.gog.com/account или:"
|
||||
echo " bash ${GOG_DIR}/fetch-ja3-setup-exe.sh"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Автоустановка, если installer уже в Downloads
|
||||
found=()
|
||||
while IFS= read -r -d '' f; do
|
||||
found+=("$f")
|
||||
done < <(find "${HOME}/Downloads" -maxdepth 1 -iname 'setup*jagged*alliance*3*.exe' -print0 2>/dev/null)
|
||||
|
||||
if [[ ${#found[@]} -eq 0 ]]; then
|
||||
echo "Когда .exe скачан (или все 5 частей в ~/Games):"
|
||||
echo " bash ${GOG_DIR}/install-ja3-offline.sh ~/Downloads/setup_jagged_alliance_3_*.exe"
|
||||
echo " bash ${GOG_DIR}/install-ja3-multipart.sh"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "Найдены installers в Downloads:"
|
||||
printf ' %s\n' "${found[@]}"
|
||||
echo ""
|
||||
for f in "${found[@]}"; do
|
||||
echo "Установка: ${f}"
|
||||
bash "${GOG_DIR}/install-ja3-offline.sh" "${f}" || exit 1
|
||||
done
|
||||
echo ""
|
||||
echo "Запуск: bash ${GOG_DIR}/run-ja3.sh"
|
||||
6
scripts/games/gog/ja3-dxvk.conf
Normal file
6
scripts/games/gog/ja3-dxvk.conf
Normal file
@@ -0,0 +1,6 @@
|
||||
# JA3 на Apple Silicon + MoltenVK (Whisky / DXVK-macOS)
|
||||
dxgi.hideIntelGpu = True
|
||||
d3d11.enableFeatureLevel11_1 = True
|
||||
d3d11.maxFeatureLevel = 12_1
|
||||
d3d11.dxgiBindBackBufferAsRT = True
|
||||
dxgi.deferSurfaceCreation = True
|
||||
9
scripts/games/gog/launch-galaxy-ui.sh
Executable file
9
scripts/games/gog/launch-galaxy-ui.sh
Executable file
@@ -0,0 +1,9 @@
|
||||
#!/usr/bin/env bash
|
||||
# Запуск GOG Galaxy с максимальным шансом увидеть окно на macOS:
|
||||
# виртуальный desktop Wine + foreground в этом терминале.
|
||||
set -euo pipefail
|
||||
# Suppress verbose MoltenVK capability dump in foreground mode.
|
||||
export MVK_CONFIG_LOG_LEVEL=0
|
||||
export GOG_USE_WINEVDESKTOP=1
|
||||
export GOG_LAUNCH_FG=1
|
||||
exec bash "$(cd "$(dirname "$0")" && pwd)/launch-galaxy.sh" "$@"
|
||||
22
scripts/games/gog/launch-galaxy-whisky.sh
Executable file
22
scripts/games/gog/launch-galaxy-whisky.sh
Executable file
@@ -0,0 +1,22 @@
|
||||
#!/usr/bin/env bash
|
||||
# Запуск GOG Galaxy через Whisky GUI (pin gog-galaxy) — лучший шанс увидеть окно на macOS.
|
||||
set -euo pipefail
|
||||
GOG_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
# shellcheck source=config.sh
|
||||
source "${GOG_DIR}/config.sh"
|
||||
|
||||
bash "${GOG_DIR}/pin-galaxy-whisky.sh" >/dev/null 2>&1 || bash "${GOG_DIR}/pin-galaxy-whisky.sh"
|
||||
bash "${GOG_DIR}/reset.sh"
|
||||
|
||||
echo "Открываю Whisky → bottle «${BOTTLE_NAME}»."
|
||||
echo ""
|
||||
echo "В GUI Whisky:"
|
||||
echo " 1) Выберите bottle «${BOTTLE_NAME}»"
|
||||
echo " 2) Pin «gog-galaxy» → Run (не GalaxySetup_full / не web-stub)"
|
||||
echo " 3) Cmd+Tab → wine64 / GOG Galaxy"
|
||||
echo ""
|
||||
echo "Если pin нет: bash ${GOG_DIR}/pin-galaxy-whisky.sh"
|
||||
echo "Логи: bash ${GOG_DIR}/collect-gog-logs-7h.sh"
|
||||
echo ""
|
||||
|
||||
open -a Whisky 2>/dev/null || open -a "Whisky.app"
|
||||
133
scripts/games/gog/launch-galaxy.sh
Executable file
133
scripts/games/gog/launch-galaxy.sh
Executable file
@@ -0,0 +1,133 @@
|
||||
#!/usr/bin/env bash
|
||||
# GOG Galaxy в GOG-bottle (CEF). По умолчанию — виртуальный desktop Wine (окно видно на Mac).
|
||||
set -euo pipefail
|
||||
GOG_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
# shellcheck source=config.sh
|
||||
source "${GOG_DIR}/config.sh"
|
||||
# shellcheck source=gog-process.sh
|
||||
source "${GOG_DIR}/gog-process.sh"
|
||||
|
||||
LOG="/tmp/gog-galaxy-client-${BOTTLE_NAME}.log"
|
||||
GALAXY_LOG="${BOTTLE_DIR}/drive_c/ProgramData/GOG.com/Galaxy/logs/GalaxyClient.log"
|
||||
INIT_LOG="${BOTTLE_DIR}/drive_c/ProgramData/GOG.com/Galaxy/logs/GalaxyInitialization.log"
|
||||
CEF_LOG="${BOTTLE_DIR}/drive_c/ProgramData/GOG.com/Galaxy/logs/cef.log"
|
||||
|
||||
gog_launch_wine() {
|
||||
local win='C:\Program Files (x86)\GOG Galaxy\GalaxyClient.exe'
|
||||
local -a args=()
|
||||
mapfile -t args < <(gog_galaxy_cef_args_array)
|
||||
|
||||
cd "${BOTTLE_DIR}/drive_c"
|
||||
if [[ "${GOG_USE_WINEVDESKTOP:-1}" == "1" ]]; then
|
||||
local w h
|
||||
IFS='x' read -r w h <<< "${GOG_VDESKTOP:-1280x800}"
|
||||
echo "Режим: explorer /desktop=GOGGalaxy,${w}x${h}"
|
||||
if [[ "${GOG_LAUNCH_FG:-0}" == "1" ]]; then
|
||||
exec "${WINE64}" explorer "/desktop=GOGGalaxy,${w}x${h}" "${win}" "${args[@]}"
|
||||
fi
|
||||
nohup "${WINE64}" explorer "/desktop=GOGGalaxy,${w}x${h}" "${win}" "${args[@]}" >>"${LOG}" 2>&1 &
|
||||
else
|
||||
echo "Режим: прямой GalaxyClient (GOG_USE_WINEVDESKTOP=0)"
|
||||
if [[ "${GOG_LAUNCH_FG:-0}" == "1" ]]; then
|
||||
exec "${WINE64}" "${win}" "${args[@]}"
|
||||
fi
|
||||
nohup "${WINE64}" "${win}" "${args[@]}" >>"${LOG}" 2>&1 &
|
||||
fi
|
||||
}
|
||||
|
||||
main() {
|
||||
gog_wine_check
|
||||
gog_swap_guard "${GOG_SWAP_MAX_MB:-400}" || exit 1
|
||||
gog_disk_guard 8 || exit 1
|
||||
if [[ ! -f "${BOTTLE_DIR}/.gog_galaxy_extract_installed" ]]; then
|
||||
echo "Сначала: bash ${GOG_DIR}/install-galaxy-extract.sh"
|
||||
exit 1
|
||||
fi
|
||||
if ! find "${BOTTLE_DIR}/drive_c/Program Files"* -name 'GalaxyClient.exe' -print -quit 2>/dev/null | grep -q .; then
|
||||
bash "${GOG_DIR}/install-galaxy-extract.sh"
|
||||
fi
|
||||
|
||||
echo "Останавливаем старые процессы GOG Galaxy…"
|
||||
gog_kill_all
|
||||
pkill -f 'explorer.exe /desktop=GOGGalaxy' 2>/dev/null || true
|
||||
|
||||
if gog_galaxy_running; then
|
||||
echo "❌ Galaxy всё ещё в процессах — повторите: bash ${GOG_DIR}/reset.sh"
|
||||
pgrep -fl 'Galaxy' 2>/dev/null || true
|
||||
exit 1
|
||||
fi
|
||||
|
||||
export_wine_env_gog
|
||||
echo "Bottle: ${BOTTLE_NAME}"
|
||||
echo "Лог: ${LOG}"
|
||||
: >"${LOG}"
|
||||
|
||||
if [[ "${GOG_LAUNCH_FG:-0}" == "1" ]]; then
|
||||
echo ""
|
||||
echo "Foreground: окно Wine привязано к этому терминалу. Закройте Galaxy — Ctrl+C."
|
||||
echo "Ищите окно «GOGGalaxy» или полосу заголовка Wine desktop."
|
||||
echo ""
|
||||
gog_launch_wine
|
||||
exit 0
|
||||
fi
|
||||
|
||||
gog_launch_wine
|
||||
echo "Запуск wine64…"
|
||||
|
||||
local ok=0 i
|
||||
for i in $(seq 1 30); do
|
||||
sleep 1
|
||||
if grep -q 'Second client instance detected' "${INIT_LOG}" 2>/dev/null; then
|
||||
if tail -5 "${INIT_LOG}" 2>/dev/null | grep -q 'The client will exit'; then
|
||||
echo "❌ Второй экземпляр: bash ${GOG_DIR}/reset.sh && bash $0"
|
||||
tail -8 "${INIT_LOG}"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
if [[ -f "${GALAXY_LOG}" ]] && grep -qE 'Showing login form|No refresh token found|will continue' "${GALAXY_LOG}" 2>/dev/null; then
|
||||
ok=1
|
||||
break
|
||||
fi
|
||||
if [[ -f "${INIT_LOG}" ]] && grep -q 'will continue' "${INIT_LOG}" 2>/dev/null; then
|
||||
ok=1
|
||||
break
|
||||
fi
|
||||
if ! gog_galaxy_running; then
|
||||
sleep 2
|
||||
if ! gog_galaxy_running; then
|
||||
break
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
if ! gog_galaxy_running; then
|
||||
echo "❌ GalaxyClient не остался в процессах:"
|
||||
tail -25 "${LOG}"
|
||||
[[ -f "${INIT_LOG}" ]] && tail -15 "${INIT_LOG}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
sleep 2
|
||||
gog_mac_activate_wine || true
|
||||
|
||||
echo ""
|
||||
echo "OK: GOG Galaxy запущен (процесс + login в логе — окно на Mac не гарантировано)."
|
||||
echo " • Окно: bash ${GOG_DIR}/launch-galaxy-whisky.sh → Whisky → pin gog-galaxy → Run"
|
||||
echo " • RCA/логи 7ч: docs/games/GOG_GALAXY_7H_RCA.md | collect-gog-logs-7h.sh"
|
||||
if [[ "${GOG_USE_WINEVDESKTOP:-1}" == "1" ]]; then
|
||||
echo " • Cmd+Tab → «wine64» / «GOGGalaxy» — отдельное окно виртуального стола Wine"
|
||||
else
|
||||
echo " • Cmd+Tab → «GalaxyClient» или «wine64»"
|
||||
fi
|
||||
echo " • Не видно окна? bash ${GOG_DIR}/launch-galaxy-ui.sh (vdesktop + foreground)"
|
||||
echo " • Whisky → «${BOTTLE_NAME}» → pin gog-galaxy → Run"
|
||||
echo " • Лог: ${GALAXY_LOG}"
|
||||
if [[ "${ok}" -eq 1 ]]; then
|
||||
echo " • В логе login UI — войдите → Jagged Alliance 3 → Install"
|
||||
if [[ -f "${CEF_LOG}" ]] && grep -q 'parent window' "${CEF_LOG}" 2>/dev/null; then
|
||||
echo " • cef.log: «parent window» — типично для Wine; vdesktop/Whisky Run часто лечит"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
main "$@"
|
||||
11
scripts/games/gog/list-bottles.sh
Executable file
11
scripts/games/gog/list-bottles.sh
Executable file
@@ -0,0 +1,11 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
echo "Whisky bottles (franke):"
|
||||
for meta in "${HOME}/Library/Containers/com.franke.Whisky/Bottles/"*/Metadata.plist; do
|
||||
[[ -f "${meta}" ]] || continue
|
||||
id="$(basename "$(dirname "${meta}")")"
|
||||
name="$(plutil -extract info.name raw "${meta}" 2>/dev/null || echo "?")"
|
||||
du -sh "$(dirname "${meta}")" 2>/dev/null | awk -v id="${id}" -v n="${name}" '{printf " %s %-20s %s\n", id, n, $1}'
|
||||
done
|
||||
echo ""
|
||||
echo "Привязать GOG: bash $(dirname "$0")/use-bottle.sh <UUID> [имя]"
|
||||
45
scripts/games/gog/pin-galaxy-whisky.sh
Executable file
45
scripts/games/gog/pin-galaxy-whisky.sh
Executable file
@@ -0,0 +1,45 @@
|
||||
#!/usr/bin/env bash
|
||||
# Pin GOG Galaxy в Whisky для bottle GOG-Install (как start.sh gog в HoMM).
|
||||
set -euo pipefail
|
||||
GOG_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
# shellcheck source=config.sh
|
||||
source "${GOG_DIR}/config.sh"
|
||||
|
||||
GOG_EXE="${BOTTLE_DIR}/drive_c/Program Files (x86)/GOG Galaxy/GalaxyClient.exe"
|
||||
[[ -f "${GOG_EXE}" ]] || { echo "Нет GalaxyClient — install-galaxy-extract.sh"; exit 1; }
|
||||
|
||||
METADATA="${BOTTLE_DIR}/Metadata.plist"
|
||||
PROG_SETTINGS="${BOTTLE_DIR}/Program Settings/GalaxyClient.exe.plist"
|
||||
GOG_URL="file://${BOTTLE_DIR}/drive_c/Program%20Files%20(x86)/GOG%20Galaxy/GalaxyClient.exe"
|
||||
CEF="$(gog_galaxy_cef_args_array | tr '\n' ' ')"
|
||||
|
||||
python3 <<PY
|
||||
import plistlib
|
||||
from pathlib import Path
|
||||
|
||||
meta = Path("${METADATA}")
|
||||
with meta.open("rb") as f:
|
||||
data = plistlib.load(f)
|
||||
pins = data.setdefault("info", {}).setdefault("pins", [])
|
||||
if not any(p.get("name") == "gog-galaxy" for p in pins):
|
||||
pins.append({
|
||||
"name": "gog-galaxy",
|
||||
"removable": False,
|
||||
"url": {"relative": "${GOG_URL}"},
|
||||
})
|
||||
with meta.open("wb") as f:
|
||||
plistlib.dump(data, f)
|
||||
print("pin gog-galaxy added")
|
||||
else:
|
||||
print("pin exists")
|
||||
|
||||
ps = Path("${PROG_SETTINGS}")
|
||||
ps.parent.mkdir(parents=True, exist_ok=True)
|
||||
with ps.open("wb") as f:
|
||||
plistlib.dump({"arguments": "${CEF}", "environment": {}, "locale": ""}, f)
|
||||
print("OK:", ps)
|
||||
PY
|
||||
|
||||
echo ""
|
||||
echo "Whisky → ${BOTTLE_NAME} → pin «gog-galaxy» → Run"
|
||||
echo "Или: bash ${GOG_DIR}/launch-galaxy.sh"
|
||||
84
scripts/games/gog/prepare-ja3-d3dmetal.sh
Executable file
84
scripts/games/gog/prepare-ja3-d3dmetal.sh
Executable file
@@ -0,0 +1,84 @@
|
||||
#!/usr/bin/env bash
|
||||
# JA3 + D3DMetal: убрать DXVK/GPTK PE из system32, оставить builtin Gcenx + d3d12/dxgi.so → libd3dshared.
|
||||
set -euo pipefail
|
||||
GOG_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
# shellcheck source=config.sh
|
||||
source "${GOG_DIR}/config.sh"
|
||||
|
||||
SYS32="${BOTTLE_DIR}/drive_c/windows/system32"
|
||||
WINE_PE="${WHISKY_LIBS}/Libraries/Wine/lib/wine/x86_64-windows"
|
||||
WINE_UNIX="${WHISKY_LIBS}/Libraries/Wine/lib/wine/x86_64-unix"
|
||||
BAK="${SYS32}/.ja3-d3dmetal-bak"
|
||||
LS="${BOTTLE_DIR}/drive_c/users/${WINE_USER:-eternal}/AppData/Roaming/Jagged Alliance 3/LocalStorage.lua"
|
||||
|
||||
ja3_gptk_available || ja3_bottle_uses_d3dmetal || {
|
||||
echo "❌ Нет GPTK/D3DMetal — configure-ja3-d3dmetal.sh"
|
||||
exit 1
|
||||
}
|
||||
|
||||
bash "${GOG_DIR}/install-gptk-whisky.sh"
|
||||
|
||||
mkdir -p "${BAK}"
|
||||
# DXVK / GPTK PE в system32 ломают D3DMetal (114688/86016 → «graphics subsystem»).
|
||||
for dll in d3d12.dll dxgi.dll d3d11.dll d3d10core.dll d3d12core.dll winemetal.dll; do
|
||||
if [[ -f "${SYS32}/${dll}" ]]; then
|
||||
mv -f "${SYS32}/${dll}" "${BAK}/${dll}" 2>/dev/null || true
|
||||
fi
|
||||
done
|
||||
|
||||
# Мост Metal + Gcenx PE (94208/200704). НЕ GPTK PE — __wine_unix_call на Wine 11.
|
||||
# НЕ копировать в system32 DXVK/GPTK DLL.
|
||||
mkdir -p "${WINE_UNIX}"
|
||||
ln -sf ../../external/libd3dshared.dylib "${WINE_UNIX}/d3d12.so"
|
||||
ln -sf ../../external/libd3dshared.dylib "${WINE_UNIX}/dxgi.so"
|
||||
# system32: убрать overrides — builtin из Wine lib
|
||||
for dll in d3d12.dll dxgi.dll d3d11.dll d3d10core.dll d3d12core.dll winemetal.dll; do
|
||||
if [[ -f "${SYS32}/${dll}" ]]; then
|
||||
mv -f "${SYS32}/${dll}" "${BAK}/${dll}" 2>/dev/null || true
|
||||
fi
|
||||
done
|
||||
|
||||
export WINEPREFIX="${BOTTLE_DIR}"
|
||||
export DYLD_LIBRARY_PATH="${WHISKY_LIBS}/Libraries/Wine/lib/external:${WINE_LIB}:${DYLD_LIBRARY_PATH:-}"
|
||||
export WINED3DMETAL=1
|
||||
export WINEDEBUG=-all
|
||||
|
||||
"${WINE64}" reg delete 'HKCU\Software\Wine\DllOverrides' /v d3d11 /f >/dev/null 2>&1 || true
|
||||
"${WINE64}" reg delete 'HKCU\Software\Wine\DllOverrides' /v d3d10core /f >/dev/null 2>&1 || true
|
||||
"${WINE64}" reg delete 'HKCU\Software\Wine\DllOverrides' /v dxgi /f >/dev/null 2>&1 || true
|
||||
"${WINE64}" reg delete 'HKCU\Software\Wine\DllOverrides' /v d3d12 /f >/dev/null 2>&1 || true
|
||||
"${WINE64}" reg delete 'HKCU\Software\Wine\Direct3D' /v renderer /f >/dev/null 2>&1 || true
|
||||
|
||||
if [[ -f "${LS}" ]]; then
|
||||
perl -i -pe 's/^\t\tGraphicsApi = ".*"/\t\tGraphicsApi = "d3d12"/' "${LS}"
|
||||
else
|
||||
mkdir -p "$(dirname "${LS}")"
|
||||
cat >"${LS}" <<'EOF'
|
||||
return {
|
||||
Options = {
|
||||
GraphicsApi = "d3d12",
|
||||
VideoPreset = "Low",
|
||||
},
|
||||
}
|
||||
EOF
|
||||
fi
|
||||
|
||||
if [[ -f "${BOTTLE_DIR}/Metadata.plist" ]]; then
|
||||
/usr/libexec/PlistBuddy -c 'Set :dxvkConfig:dxvk false' "${BOTTLE_DIR}/Metadata.plist" 2>/dev/null || true
|
||||
/usr/libexec/PlistBuddy -c 'Set :performanceConfig:forceD3D11 false' "${BOTTLE_DIR}/Metadata.plist" 2>/dev/null || \
|
||||
/usr/libexec/PlistBuddy -c 'Add :performanceConfig:forceD3D11 bool false' "${BOTTLE_DIR}/Metadata.plist" 2>/dev/null || true
|
||||
/usr/libexec/PlistBuddy -c 'Set :graphicsConfig:backend d3dMetal' "${BOTTLE_DIR}/Metadata.plist" 2>/dev/null || true
|
||||
/usr/libexec/PlistBuddy -c 'Set :metalConfig:sequoiaCompatMode true' "${BOTTLE_DIR}/Metadata.plist" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
touch "${BOTTLE_DIR}/.ja3_d3dmetal_prepared"
|
||||
# Ярлык для Whisky Run (тот же CWD + D3DMetal env из Metadata)
|
||||
cat >"${BOTTLE_DIR}/drive_c/GOG Games/Jagged Alliance 3/run-ja3.cmd" <<'EOF'
|
||||
@echo off
|
||||
cd /d "C:\GOG Games\Jagged Alliance 3"
|
||||
start "" "JA3.exe" -unpacked %*
|
||||
EOF
|
||||
|
||||
echo "OK: D3DMetal graphics для ${BOTTLE_NAME}"
|
||||
echo " Скрипт: bash ${GOG_DIR}/run-ja3.sh"
|
||||
echo " Whisky Run: C:\\GOG Games\\Jagged Alliance 3\\run-ja3.cmd (не JA3.exe напрямую)"
|
||||
52
scripts/games/gog/purge-steam-from-bottle.sh
Executable file
52
scripts/games/gog/purge-steam-from-bottle.sh
Executable file
@@ -0,0 +1,52 @@
|
||||
#!/usr/bin/env bash
|
||||
# Удалить клиент Steam из GOG-bottle (если попал). JA3/GOG — без Steam.app.
|
||||
# Не трогает steam_api64.dll в папке игры (GOG Galaxy wrapper, не Steam client).
|
||||
set -euo pipefail
|
||||
GOG_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
# shellcheck source=config.sh
|
||||
source "${GOG_DIR}/config.sh"
|
||||
|
||||
STEAM_DIRS=(
|
||||
"${BOTTLE_DIR}/drive_c/Program Files (x86)/Steam"
|
||||
"${BOTTLE_DIR}/drive_c/Program Files/Steam"
|
||||
"${BOTTLE_DIR}/drive_c/Steam"
|
||||
)
|
||||
|
||||
main() {
|
||||
echo "=== Purge Steam из bottle ${BOTTLE_NAME} ==="
|
||||
|
||||
pkill -9 -f "${BOTTLE_ID}.*[Ss]team" 2>/dev/null || true
|
||||
pkill -9 -f "${BOTTLE_DIR}.*steam\.exe" 2>/dev/null || true
|
||||
|
||||
local d removed=0
|
||||
for d in "${STEAM_DIRS[@]}"; do
|
||||
if [[ -d "${d}" ]]; then
|
||||
echo " удаляю: ${d}"
|
||||
rm -rf "${d}"
|
||||
removed=1
|
||||
fi
|
||||
done
|
||||
|
||||
find "${BOTTLE_DIR}/drive_c" -maxdepth 4 \( -iname 'steam.exe' -o -iname 'steamservice.exe' \) 2>/dev/null | while read -r f; do
|
||||
echo " удаляю: ${f}"
|
||||
rm -f "${f}"
|
||||
removed=1
|
||||
done
|
||||
|
||||
export WINEPREFIX="${BOTTLE_DIR}"
|
||||
export DYLD_LIBRARY_PATH="${WINE_LIB}:${DYLD_LIBRARY_PATH:-}"
|
||||
if [[ -x "${WINE64}" ]]; then
|
||||
"${WINE64}" reg delete 'HKCU\Software\Valve' /f >/dev/null 2>&1 || true
|
||||
"${WINE64}" reg delete 'HKLM\Software\Valve' /f >/dev/null 2>&1 || true
|
||||
fi
|
||||
|
||||
if [[ "${removed}" -eq 0 ]]; then
|
||||
echo "OK: каталога Steam в bottle не было."
|
||||
else
|
||||
echo "OK: Steam client удалён из bottle."
|
||||
fi
|
||||
echo ""
|
||||
echo "Примечание: JA3.exe использует steam_api64.dll + Galaxy.dll (GOG), это не Steam.app."
|
||||
}
|
||||
|
||||
main "$@"
|
||||
20
scripts/games/gog/register-galaxy-registry.sh
Executable file
20
scripts/games/gog/register-galaxy-registry.sh
Executable file
@@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env bash
|
||||
# Реестр после innoextract — web-installer видит установленный Galaxy.
|
||||
set -euo pipefail
|
||||
GOG_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
# shellcheck source=config.sh
|
||||
source "${GOG_DIR}/config.sh"
|
||||
|
||||
GOG_PF='C:\Program Files (x86)\GOG Galaxy'
|
||||
CLIENT="${GOG_PF}\\GalaxyClient.exe"
|
||||
SERVICE="${GOG_PF}\\GalaxyClientService.exe"
|
||||
|
||||
gog_wine_check
|
||||
export_wine_env_gog
|
||||
|
||||
"${WINE64}" reg add 'HKLM\Software\WOW6432Node\GOG.com\GalaxyClient' /v version /t REG_SZ /d '2.0.100.1' /f
|
||||
"${WINE64}" reg add 'HKLM\Software\WOW6432Node\GOG.com\GalaxyClient\paths' /v GalaxyClientExePath /t REG_SZ /d "${CLIENT}" /f
|
||||
"${WINE64}" reg add 'HKLM\Software\WOW6432Node\GOG.com\GalaxyClient\paths' /v GalaxyClientServiceExePath /t REG_SZ /d "${SERVICE}" /f
|
||||
"${WINE64}" reg add 'HKCU\Software\GOG.com\Galaxy' /f 2>/dev/null || true
|
||||
|
||||
echo "OK: GalaxyClient paths → ${CLIENT}"
|
||||
27
scripts/games/gog/register-ja3-registry.sh
Executable file
27
scripts/games/gog/register-ja3-registry.sh
Executable file
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env bash
|
||||
# Реестр GOG для JA3 (innoextract не запускает Inno-скрипт с ключами).
|
||||
set -euo pipefail
|
||||
GOG_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
# shellcheck source=config.sh
|
||||
source "${GOG_DIR}/config.sh"
|
||||
|
||||
GAME_ID='1556263729'
|
||||
JA3_WIN='C:\GOG Games\Jagged Alliance 3'
|
||||
JA3_EXE="${JA3_WIN}\\JA3.exe"
|
||||
KEY="HKLM\\Software\\WOW6432Node\\GOG.com\\Games\\${GAME_ID}"
|
||||
|
||||
gog_wine_check
|
||||
export_wine_env_gog
|
||||
|
||||
"${WINE64}" reg add "${KEY}" /v gameName /t REG_SZ /d 'Jagged Alliance 3' /f
|
||||
"${WINE64}" reg add "${KEY}" /v exe /t REG_SZ /d 'JA3.exe' /f
|
||||
"${WINE64}" reg add "${KEY}" /v path /t REG_SZ /d "${JA3_WIN}\\" /f
|
||||
"${WINE64}" reg add "${KEY}" /v startMenu /t REG_SZ /d 'Jagged Alliance 3\' /f
|
||||
"${WINE64}" reg add "${KEY}" /v version /t REG_SZ /d '1.5.2' /f
|
||||
"${WINE64}" reg add "${KEY}" /v language /t REG_SZ /d 'English' /f
|
||||
"${WINE64}" reg add "${KEY}" /v launchParam /t REG_SZ /d '' /f
|
||||
"${WINE64}" reg add 'HKLM\Software\WOW6432Node\GOG.com\DefaultPackPath' /ve /t REG_SZ /d 'C:\GOG Games' /f 2>/dev/null || true
|
||||
|
||||
bash "${GOG_DIR}/register-galaxy-registry.sh" 2>/dev/null || true
|
||||
|
||||
echo "OK: GOG registry → ${KEY}"
|
||||
17
scripts/games/gog/reset-ja3-crossover.sh
Executable file
17
scripts/games/gog/reset-ja3-crossover.sh
Executable file
@@ -0,0 +1,17 @@
|
||||
#!/usr/bin/env bash
|
||||
# Остановить JA3 / Wine (CrossOver bottle JA3-GOG) перед перезапуском.
|
||||
set -euo pipefail
|
||||
GOG_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
# shellcheck source=gog-process.sh
|
||||
source "${GOG_DIR}/gog-process.sh"
|
||||
|
||||
bash "${GOG_DIR}/emergency-stop.sh" 2>/dev/null || gog_kill_all
|
||||
pkill -f 'JA3\.exe' 2>/dev/null || true
|
||||
pkill -f 'wineserver.*JA3-GOG' 2>/dev/null || true
|
||||
|
||||
CX="/Applications/CrossOver.app/Contents/SharedSupport/CrossOver"
|
||||
if [[ -x "${CX}/bin/wine" ]]; then
|
||||
"${CX}/bin/wine" --bottle JA3-GOG wineboot --kill 2>/dev/null || true
|
||||
fi
|
||||
sleep 2
|
||||
pgrep -fl 'JA3\.exe|wineserver' 2>/dev/null | head -5 || echo "OK: процессы JA3/Wine остановлены"
|
||||
9
scripts/games/gog/reset.sh
Executable file
9
scripts/games/gog/reset.sh
Executable file
@@ -0,0 +1,9 @@
|
||||
#!/usr/bin/env bash
|
||||
# Только GOG web-installer / Galaxy в этом bottle — без Steam, wineboot -k всего префикса.
|
||||
set -euo pipefail
|
||||
GOG_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
# shellcheck source=gog-process.sh
|
||||
source "${GOG_DIR}/gog-process.sh"
|
||||
|
||||
gog_kill_all
|
||||
echo "OK: GOG-процессы остановлены, lock снят (bottle ${BOTTLE_NAME})."
|
||||
117
scripts/games/gog/run-galaxy-setup.sh
Executable file
117
scripts/games/gog/run-galaxy-setup.sh
Executable file
@@ -0,0 +1,117 @@
|
||||
#!/usr/bin/env bash
|
||||
# Запуск GalaxySetup.exe (JA3 и др.) без родительского GalaxyInstaller — обход «Galaxy already running» + gdi32.
|
||||
set -euo pipefail
|
||||
GOG_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
# shellcheck source=config.sh
|
||||
source "${GOG_DIR}/config.sh"
|
||||
|
||||
PRODUCT_ID="${1:-1556263729}"
|
||||
GAME_NAME="${2:-Jagged Alliance 3}"
|
||||
LOG="/tmp/gog-galaxy-setup-${BOTTLE_NAME}.log"
|
||||
|
||||
gog_kill_all_galaxy() {
|
||||
pkill -f 'GOG_Galaxy_' 2>/dev/null || true
|
||||
pkill -f 'GalaxyWebInstaller' 2>/dev/null || true
|
||||
pkill -f 'GalaxyInstaller' 2>/dev/null || true
|
||||
pkill -f 'GalaxySetup' 2>/dev/null || true
|
||||
pkill -f "${BOTTLE_ID}.*Galaxy" 2>/dev/null || true
|
||||
sleep 2
|
||||
}
|
||||
|
||||
find_galaxy_setup() {
|
||||
local d
|
||||
for d in "${BOTTLE_DIR}/drive_c/users/"*/AppData/Local/Temp/GalaxyInstaller_*; do
|
||||
[[ -f "${d}/GalaxySetup.exe" ]] || continue
|
||||
echo "${d}/GalaxySetup.exe"
|
||||
return 0
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
export_wine_env_gog_setup() {
|
||||
export WINEPREFIX="${BOTTLE_DIR}"
|
||||
export WINEMSYNC=1
|
||||
export WINEESYNC=1
|
||||
export DYLD_LIBRARY_PATH="${WINE_LIB}:${DYLD_LIBRARY_PATH:-}"
|
||||
# Inno/botva2: native gdiplus ломает gdi32 в MsgBox; stub/.NET — gdiplus=n,b
|
||||
export WINEDLLOVERRIDES="gdiplus=b"
|
||||
export WINEDEBUG="${WINEDEBUG:--all}"
|
||||
unset DXVK_ASYNC DXVK_HUD 2>/dev/null || true
|
||||
}
|
||||
|
||||
main() {
|
||||
gog_wine_check
|
||||
|
||||
if [[ ! -f "${BOTTLE_DIR}/.gog_galaxy_extract_installed" ]] \
|
||||
&& ! find "${BOTTLE_DIR}/drive_c/Program Files"* -name 'GalaxyClient.exe' -print -quit 2>/dev/null | grep -q .; then
|
||||
echo "Сначала: bash ${GOG_DIR}/install-galaxy-extract.sh"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
local setup
|
||||
setup="$(find_galaxy_setup || true)"
|
||||
if [[ -z "${setup}" ]]; then
|
||||
echo "Нет GalaxySetup.exe в Temp. Сначала web-stub:"
|
||||
echo " bash ${GOG_DIR}/run-web-installer.sh /path/GOG_Galaxy_*.exe"
|
||||
echo "Дождитесь скачивания ~277 MB, затем снова этот скрипт."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
gog_kill_all_galaxy
|
||||
export_wine_env_gog_setup
|
||||
|
||||
local win="Z:${setup#${BOTTLE_DIR}}"
|
||||
win="${win//\//\\\\}"
|
||||
# Wine path: C:\users\...
|
||||
local cpath
|
||||
cpath="$("${WINEPATH_BIN}" -w "${setup}" 2>/dev/null || true)"
|
||||
if [[ -z "${cpath}" ]]; then
|
||||
cpath="C:\\users\\eternal\\AppData\\Local\\Temp\\$(basename "$(dirname "${setup}")")\\GalaxySetup.exe"
|
||||
fi
|
||||
|
||||
echo "Setup: ${setup}"
|
||||
echo "Лог: ${LOG}"
|
||||
: >"${LOG}"
|
||||
|
||||
"${WINE64}" "${cpath}" \
|
||||
/VERYSILENT /SUPPRESSMSGBOXES /NORESTART /FORCECLOSEAPPLICATIONS /SP- \
|
||||
/lang=en_US /webinstaller "/product_id=${PRODUCT_ID}" "/game_name=${GAME_NAME}" \
|
||||
>>"${LOG}" 2>&1 &
|
||||
local pid=$!
|
||||
|
||||
local i
|
||||
for i in $(seq 1 120); do
|
||||
sleep 5
|
||||
if ! kill -0 "${pid}" 2>/dev/null; then
|
||||
break
|
||||
fi
|
||||
if grep -qi 'Install successful\|Successfully installed' "${LOG}" 2>/dev/null; then
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
gog_kill_all_galaxy
|
||||
|
||||
local setup_log
|
||||
setup_log="$(find "${BOTTLE_DIR}/drive_c/users" -name 'Setup Log*.txt' -print 2>/dev/null | sort | tail -1)"
|
||||
if [[ -n "${setup_log}" ]]; then
|
||||
echo "--- Inno Setup log (tail) ---"
|
||||
tail -30 "${setup_log}"
|
||||
fi
|
||||
|
||||
if grep -qi 'Install successful\|Successfully installed' "${setup_log:-/dev/null}" 2>/dev/null; then
|
||||
echo "OK: установка завершена."
|
||||
exit 0
|
||||
fi
|
||||
if grep -q 'Deinitializing Setup' "${setup_log:-/dev/null}" 2>/dev/null \
|
||||
&& ! grep -q 'Access violation' "${setup_log:-/dev/null}" 2>/dev/null; then
|
||||
echo "OK: Setup завершился без AV (проверьте игру в Galaxy)."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "Лог Wine:"
|
||||
tail -25 "${LOG}"
|
||||
exit 1
|
||||
}
|
||||
|
||||
main "$@"
|
||||
35
scripts/games/gog/run-ja3-crossover.sh
Executable file
35
scripts/games/gog/run-ja3-crossover.sh
Executable file
@@ -0,0 +1,35 @@
|
||||
#!/usr/bin/env bash
|
||||
# JA3 (GOG) через CrossOver + D3DMetal — D3D12 на Apple Silicon.
|
||||
set -euo pipefail
|
||||
GOG_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
# shellcheck source=config.sh
|
||||
source "${GOG_DIR}/config.sh"
|
||||
# shellcheck source=gog-process.sh
|
||||
source "${GOG_DIR}/gog-process.sh"
|
||||
|
||||
CX="${HOME}/Applications/CrossOver.app/Contents/SharedSupport/CrossOver"
|
||||
[[ -d "/Applications/CrossOver.app" ]] && CX="/Applications/CrossOver.app/Contents/SharedSupport/CrossOver"
|
||||
CX_BOTTLE="JA3-GOG"
|
||||
CX_DIR="${HOME}/Library/Application Support/CrossOver/Bottles/${CX_BOTTLE}"
|
||||
|
||||
[[ -d "${CX}" ]] || {
|
||||
echo "❌ CrossOver не установлен: brew install --cask crossover"
|
||||
exit 1
|
||||
}
|
||||
|
||||
if [[ ! -f "${CX_DIR}/drive_c/GOG Games/Jagged Alliance 3/JA3.exe" ]]; then
|
||||
bash "${GOG_DIR}/setup-ja3-crossover.sh"
|
||||
fi
|
||||
|
||||
bash "${GOG_DIR}/emergency-stop.sh" >/dev/null 2>&1 || gog_kill_all
|
||||
sleep 2
|
||||
|
||||
gog_swap_guard_ja3_launch "${JA3_SWAP_SOFT_MB:-1200}" "${JA3_SWAP_HARD_MB:-4096}" || exit 1
|
||||
|
||||
echo "Запуск JA3 (CrossOver D3DMetal; без Steam.app)…"
|
||||
echo "Cmd+Tab → JA3. В графике: отключить heat haze."
|
||||
echo "(лог «Steam … GOG» = GOG API-шим, не Steam client)"
|
||||
|
||||
# start /d — CWD с CommonLua/ (обязательно; --cx-app без /d → autorun.lua not found)
|
||||
exec "${CX}/bin/wine" --bottle "${CX_BOTTLE}" start /d "C:\\GOG Games\\Jagged Alliance 3" \
|
||||
"C:\\GOG Games\\Jagged Alliance 3\\JA3.exe" ${JA3_EXTRA_ARGS:--unpacked}
|
||||
57
scripts/games/gog/run-ja3-gptk-wine.sh
Executable file
57
scripts/games/gog/run-ja3-gptk-wine.sh
Executable file
@@ -0,0 +1,57 @@
|
||||
#!/usr/bin/env bash
|
||||
# JA3 через Wine 7.7 + D3DMetal (Game Porting Toolkit). Канон для D3D12 на Apple Silicon.
|
||||
set -euo pipefail
|
||||
GOG_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
GAMES_DIR="$(cd "${GOG_DIR}/.." && pwd)"
|
||||
# shellcheck source=config.sh
|
||||
source "${GOG_DIR}/config.sh"
|
||||
# shellcheck source=gog-process.sh
|
||||
source "${GOG_DIR}/gog-process.sh"
|
||||
|
||||
GPTK_WINE="/Applications/Game Porting Toolkit.app/Contents/Resources/wine"
|
||||
GPTK_WINE64="${GPTK_WINE}/bin/wine64"
|
||||
JA3_WIN='C:\GOG Games\Jagged Alliance 3\JA3.exe'
|
||||
MARKER="${GAMES_CACHE_DIR}/.ja3_gptk_prefix"
|
||||
|
||||
[[ -x "${GPTK_WINE64}" ]] || {
|
||||
echo "❌ brew install --cask gcenx/wine/game-porting-toolkit"
|
||||
exit 1
|
||||
}
|
||||
|
||||
if [[ -f "${MARKER}" ]]; then
|
||||
GPTK_PREFIX="$(cat "${MARKER}")"
|
||||
else
|
||||
GPTK_PREFIX="${JA3_GPTK_PREFIX:-${GAMES_CACHE_DIR}/ja3-gptk-prefix}"
|
||||
fi
|
||||
|
||||
if [[ ! -f "${GPTK_PREFIX}/system.reg" ]]; then
|
||||
bash "${GOG_DIR}/setup-ja3-gptk-prefix.sh"
|
||||
GPTK_PREFIX="$(cat "${MARKER}" 2>/dev/null || echo "${GPTK_PREFIX}")"
|
||||
fi
|
||||
|
||||
JA3_UNIX="${GPTK_PREFIX}/drive_c/GOG Games/Jagged Alliance 3"
|
||||
[[ -f "${JA3_UNIX}/JA3.exe" ]] || JA3_UNIX="$(readlink "${JA3_UNIX}" 2>/dev/null || true)"
|
||||
[[ -f "${JA3_UNIX}/JA3.exe" ]] || {
|
||||
echo "❌ Нет JA3 в GPTK prefix — bash ${GOG_DIR}/setup-ja3-gptk-prefix.sh"
|
||||
exit 1
|
||||
}
|
||||
|
||||
bash "${GOG_DIR}/emergency-stop.sh" >/dev/null 2>&1 || gog_kill_all
|
||||
sleep 2
|
||||
|
||||
if [[ "${JA3_IGNORE_SWAP:-0}" != "1" ]] && ! gog_swap_guard "${JA3_SWAP_MAX_MB:-800}"; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
export WINEPREFIX="${GPTK_PREFIX}"
|
||||
export WINEARCH=win64
|
||||
export WINED3DMETAL=1
|
||||
export WINEMSYNC=1
|
||||
export WINEDEBUG=-all
|
||||
export MVK_CONFIG_LOG_LEVEL=0
|
||||
export DYLD_LIBRARY_PATH="${GPTK_WINE}/lib:${DYLD_LIBRARY_PATH:-}"
|
||||
export WINEDLLOVERRIDES="libxess,xess,dxcompiler,dxil,nvngx_dlss,XeFX,XeFX_Loader=d;gdiplus=n,b"
|
||||
|
||||
echo "Запуск JA3 (GPTK Wine 7.7 + D3DMetal, prefix ${GPTK_PREFIX})…"
|
||||
cd "${JA3_UNIX}"
|
||||
exec "${GPTK_WINE64}" "${JA3_WIN}" ${JA3_EXTRA_ARGS:--unpacked}
|
||||
103
scripts/games/gog/run-ja3.sh
Executable file
103
scripts/games/gog/run-ja3.sh
Executable file
@@ -0,0 +1,103 @@
|
||||
#!/usr/bin/env bash
|
||||
# Запуск Jagged Alliance 3 (GOG) без Steam client.
|
||||
set -euo pipefail
|
||||
GOG_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
# shellcheck source=config.sh
|
||||
source "${GOG_DIR}/config.sh"
|
||||
# shellcheck source=gog-process.sh
|
||||
source "${GOG_DIR}/gog-process.sh"
|
||||
|
||||
JA3_WIN='C:\GOG Games\Jagged Alliance 3\JA3.exe'
|
||||
JA3_UNIX="${BOTTLE_DIR}/drive_c/GOG Games/Jagged Alliance 3"
|
||||
JA3_EXE="${JA3_UNIX}/JA3.exe"
|
||||
GALAXY_SVC='C:\Program Files (x86)\GOG Galaxy\GalaxyClientService.exe'
|
||||
|
||||
if [[ ! -f "${JA3_EXE}" ]]; then
|
||||
echo "❌ Нет ${JA3_EXE}"
|
||||
echo " Установите: bash ${GOG_DIR}/install-ja3-innoextract.sh"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
bash "${GOG_DIR}/emergency-stop.sh" >/dev/null 2>&1 || gog_kill_all
|
||||
sleep 2
|
||||
|
||||
if [[ "${JA3_IGNORE_SWAP:-0}" == "1" ]]; then
|
||||
echo "⚠️ JA3_IGNORE_SWAP=1 — swap $(gog_swap_used_mb 2>/dev/null || echo '?')MB"
|
||||
elif ! gog_swap_guard_ja3_launch "${JA3_SWAP_SOFT_MB:-1200}" "${JA3_SWAP_HARD_MB:-4096}"; then
|
||||
used="$(gog_swap_used_mb 2>/dev/null || echo '?')"
|
||||
echo ""
|
||||
echo "Swap ~${used}MB — bash ${GOG_DIR}/reset-ja3-crossover.sh или reboot Mac"
|
||||
echo "Или: JA3_IGNORE_SWAP=1 bash ${GOG_DIR}/run-ja3.sh"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
gog_assert_no_steam_client || exit 1
|
||||
|
||||
if ! ja3_gptk_available && ! ja3_bottle_uses_d3dmetal; then
|
||||
if [[ -d "/Applications/Game Porting Toolkit.app" ]]; then
|
||||
bash "${GOG_DIR}/install-gptk-whisky.sh" >/dev/null 2>&1 || true
|
||||
bash "${GOG_DIR}/configure-ja3-d3dmetal.sh" >/dev/null 2>&1 || true
|
||||
else
|
||||
echo ""
|
||||
echo "⚠️ JA3 нужен D3D12 (GPTK). Установите:"
|
||||
echo " brew install --cask gcenx/wine/game-porting-toolkit"
|
||||
echo " bash ${GOG_DIR}/install-gptk-whisky.sh && bash ${GOG_DIR}/configure-ja3-d3dmetal.sh"
|
||||
echo ""
|
||||
fi
|
||||
fi
|
||||
|
||||
CX="/Applications/CrossOver.app/Contents/SharedSupport/CrossOver"
|
||||
if [[ ! -x "${CX}/bin/wine" ]]; then
|
||||
:
|
||||
elif [[ ! -f "${HOME}/Library/Application Support/CrossOver/Bottles/JA3-GOG/drive_c/GOG Games/Jagged Alliance 3/JA3.exe" ]]; then
|
||||
echo ""
|
||||
echo "ℹ️ JA3 (D3D12) на Mac: Whisky/Gcenx не поддерживает D3DMetal."
|
||||
echo " brew install --cask crossover"
|
||||
echo " bash ${GOG_DIR}/setup-ja3-crossover.sh && bash ${GOG_DIR}/run-ja3-crossover.sh"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# Whisky D3DMetal path — не работает для JA3/D3D12 на Gcenx (см. JA3_MAC_WITHOUT_GALAXY.md)
|
||||
if ja3_gptk_available || ja3_bottle_uses_d3dmetal; then
|
||||
bash "${GOG_DIR}/prepare-ja3-d3dmetal.sh" >/dev/null 2>&1 || true
|
||||
fi
|
||||
bash "${GOG_DIR}/finish-ja3-layout.sh" >/dev/null 2>&1 || true
|
||||
if ja3_gptk_available || ja3_bottle_uses_d3dmetal; then
|
||||
:
|
||||
else
|
||||
bash "${GOG_DIR}/force-ja3-d3d11.sh" >/dev/null 2>&1 || true
|
||||
fi
|
||||
|
||||
export_wine_env_ja3
|
||||
gog_wine_check
|
||||
|
||||
# Фоновый Galaxy service (Music/Matchmaking wrapper — не Steam)
|
||||
if [[ -f "${BOTTLE_DIR}/drive_c/Program Files (x86)/GOG Galaxy/GalaxyClientService.exe" ]]; then
|
||||
if ! pgrep -f 'GalaxyClientService' >/dev/null 2>&1; then
|
||||
nohup "${WINE64}" "${GALAXY_SVC}" >>/tmp/ja3-galaxy-service.log 2>&1 &
|
||||
sleep 2
|
||||
fi
|
||||
fi
|
||||
|
||||
if ja3_gptk_available || ja3_bottle_uses_d3dmetal; then
|
||||
echo "⚠️ Whisky D3DMetal не поддерживает JA3/D3D12 (Gcenx без D3DMetal hooks)."
|
||||
echo " Используйте: bash ${GOG_DIR}/run-ja3-crossover.sh"
|
||||
echo ""
|
||||
fi
|
||||
if ja3_gptk_available || ja3_bottle_uses_d3dmetal; then
|
||||
echo "Запуск JA3 (Whisky — эксперимент; D3D12 → CrossOver)…"
|
||||
else
|
||||
echo "Запуск JA3 (GOG, DXVK D3D11 fallback; без Steam.app)…"
|
||||
fi
|
||||
echo "Cmd+Tab → wine64. В графике: отключить heat haze."
|
||||
echo "(лог «Steam … GOG» = GOG API-шим, не Steam client)"
|
||||
if ja3_gptk_available || ja3_bottle_uses_d3dmetal; then
|
||||
_ja3_args="${JA3_EXTRA_ARGS:--unpacked}"
|
||||
export MTL_HUD_ENABLED="${MTL_HUD_ENABLED:-0}"
|
||||
else
|
||||
_ja3_args="${JA3_EXTRA_ARGS:--unpacked -graphicsapi d3d11}"
|
||||
fi
|
||||
# start /d — CWD = папка игры (CommonLua/, иначе «graphics subsystem»/autorun.lua из Whisky Run)
|
||||
# innoextract не запускает Inno-постскрипты; -unpacked + CommonLua на диске обязательны
|
||||
# shellcheck disable=SC2086
|
||||
exec "${WINE64}" start /d "C:\\GOG Games\\Jagged Alliance 3" "${JA3_WIN}" ${_ja3_args}
|
||||
96
scripts/games/gog/run-web-installer.sh
Executable file
96
scripts/games/gog/run-web-installer.sh
Executable file
@@ -0,0 +1,96 @@
|
||||
#!/usr/bin/env bash
|
||||
# GOG web-stub в отдельном GOG-bottle. Без Steam/HoMM.
|
||||
set -euo pipefail
|
||||
GOG_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
# shellcheck source=config.sh
|
||||
source "${GOG_DIR}/config.sh"
|
||||
# shellcheck source=wine-fonts.sh
|
||||
source "${GOG_DIR}/wine-fonts.sh"
|
||||
|
||||
GOG_SETUP_MARKER="${BOTTLE_DIR}/.gog_setup_v1"
|
||||
LOG="/tmp/gog-web-installer-${BOTTLE_NAME}.log"
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Использование: $(basename "$0") /path/to/GOG_Galaxy_GameName.exe
|
||||
|
||||
Bottle: ${BOTTLE_NAME} (${BOTTLE_ID}) — только GOG, без Steam.
|
||||
Один раз: bash ${GOG_DIR}/use-bottle.sh <UUID>
|
||||
bash ${GOG_DIR}/setup-bottle.sh
|
||||
bash ${GOG_DIR}/install-corefonts.sh
|
||||
|
||||
Лог: ${LOG}
|
||||
EOF
|
||||
}
|
||||
|
||||
gog_kill_installers() {
|
||||
pkill -f 'GOG_Galaxy_' 2>/dev/null || true
|
||||
pkill -f 'GalaxyWebInstaller' 2>/dev/null || true
|
||||
sleep 1
|
||||
}
|
||||
|
||||
main() {
|
||||
local src="${1:-}"
|
||||
if [[ -z "${src}" || "${src}" == "-h" || "${src}" == "--help" ]]; then
|
||||
usage
|
||||
exit 0
|
||||
fi
|
||||
[[ -f "${src}" ]] || { echo "Нет файла: ${src}"; exit 1; }
|
||||
|
||||
gog_wine_check
|
||||
gog_disk_guard 5 || exit 1
|
||||
|
||||
if [[ ! -f "${BOTTLE_DIR}/.gog_gdiplus_installed" ]]; then
|
||||
echo "⚠️ Нет gdiplus — один раз: bash ${GOG_DIR}/install-gdiplus.sh"
|
||||
fi
|
||||
if [[ ! -f "${BOTTLE_DIR}/.gog_corefonts_installed" ]]; then
|
||||
echo "⚠️ Сначала: bash ${GOG_DIR}/install-corefonts.sh"
|
||||
fi
|
||||
|
||||
[[ -f "${GOG_SETUP_MARKER}" ]] || bash "${GOG_DIR}/setup-bottle.sh"
|
||||
gog_wine_ensure_fonts 0
|
||||
|
||||
local base dest_win
|
||||
base="$(basename "${src}")"
|
||||
dest_win="C:\\${base}"
|
||||
cp -f "${src}" "${BOTTLE_DIR}/drive_c/${base}"
|
||||
|
||||
gog_kill_installers
|
||||
export_wine_env_gog
|
||||
|
||||
echo "Bottle: ${BOTTLE_NAME}"
|
||||
echo "Запуск: ${dest_win}"
|
||||
echo "Лог: ${LOG}"
|
||||
|
||||
: >"${LOG}"
|
||||
nohup "${WINE64}" "${dest_win}" >"${LOG}" 2>&1 &
|
||||
local i alive=0
|
||||
for i in 1 2 3 4 5 6; do
|
||||
sleep 2
|
||||
if pgrep -f "${base}" >/dev/null 2>&1; then
|
||||
alive=1
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ "${alive}" -eq 1 ]]; then
|
||||
sleep 3
|
||||
if grep -q 'FontFamily could not be found' "${LOG}" 2>/dev/null; then
|
||||
echo "❌ FontFamily в логе — bash ${GOG_DIR}/install-gdiplus.sh && install-corefonts.sh"
|
||||
tail -5 "${LOG}"
|
||||
exit 1
|
||||
fi
|
||||
echo "OK: установщик запущен (Cmd+Tab → ${base})."
|
||||
exit 0
|
||||
fi
|
||||
if grep -q 'FontFamily could not be found' "${LOG}" 2>/dev/null; then
|
||||
echo "❌ FontFamilyNotFound:"
|
||||
tail -8 "${LOG}"
|
||||
exit 1
|
||||
fi
|
||||
echo "Процесс завершился:"
|
||||
tail -20 "${LOG}"
|
||||
exit 1
|
||||
}
|
||||
|
||||
main "$@"
|
||||
53
scripts/games/gog/setup-bottle.sh
Executable file
53
scripts/games/gog/setup-bottle.sh
Executable file
@@ -0,0 +1,53 @@
|
||||
#!/usr/bin/env bash
|
||||
# Один раз: GOG-bottle — шрифты + сеть Wine. Без Steam/HoMM.
|
||||
set -euo pipefail
|
||||
GOG_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
# shellcheck source=config.sh
|
||||
source "${GOG_DIR}/config.sh"
|
||||
# shellcheck source=wine-fonts.sh
|
||||
source "${GOG_DIR}/wine-fonts.sh"
|
||||
|
||||
GOG_SETUP_VERSION="1"
|
||||
GOG_SETUP_MARKER="${BOTTLE_DIR}/.gog_setup_v${GOG_SETUP_VERSION}"
|
||||
|
||||
main() {
|
||||
local force=0 fonts_only=0
|
||||
for arg in "$@"; do
|
||||
case "${arg}" in
|
||||
--force) force=1 ;;
|
||||
--fonts-only) fonts_only=1 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
gog_wine_check
|
||||
|
||||
if [[ "${fonts_only}" -eq 1 ]]; then
|
||||
gog_wine_ensure_fonts 1
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ -f "${GOG_SETUP_MARKER}" && "${force}" -eq 0 ]]; then
|
||||
echo "GOG bottle готов: ${GOG_SETUP_MARKER}"
|
||||
echo " Шрифты: bash ${GOG_DIR}/setup-bottle.sh --fonts-only"
|
||||
echo " Заново: bash ${GOG_DIR}/setup-bottle.sh --force"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "Подготовка GOG bottle «${BOTTLE_NAME}» (v${GOG_SETUP_VERSION})…"
|
||||
gog_wine_ensure_fonts 1
|
||||
export_wine_env_gog
|
||||
"${WINE64}" reg add 'HKCU\Software\Wine\Network' /v DnsIPv6Enabled /t REG_DWORD /d 0 /f >/dev/null 2>&1 || true
|
||||
"${WINE64}" reg add 'HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings' \
|
||||
/v DisableIPv6 /t REG_DWORD /d 1 /f >/dev/null 2>&1 || true
|
||||
"${WINE64}" reg add 'HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings' \
|
||||
/v ProxyEnable /t REG_DWORD /d 0 /f >/dev/null 2>&1 || true
|
||||
echo "Wine: DnsIPv6Enabled=0, ProxyEnable=0"
|
||||
date -u +"%Y-%m-%dT%H:%M:%SZ" >"${GOG_SETUP_MARKER}"
|
||||
echo ""
|
||||
echo "OK. Дальше:"
|
||||
echo " bash ${GOG_DIR}/install-gdiplus.sh # обязательно для .NET"
|
||||
echo " bash ${GOG_DIR}/install-corefonts.sh"
|
||||
echo " bash ${GOG_DIR}/run-web-installer.sh /path/GOG_Galaxy_*.exe"
|
||||
}
|
||||
|
||||
main "$@"
|
||||
24
scripts/games/gog/setup-ja3-bottle.sh
Executable file
24
scripts/games/gog/setup-ja3-bottle.sh
Executable file
@@ -0,0 +1,24 @@
|
||||
#!/usr/bin/env bash
|
||||
# Bottle только для JA3 (offline GOG installer + игра). Без Galaxy CEF.
|
||||
set -euo pipefail
|
||||
GOG_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
GAMES_DIR="$(cd "${GOG_DIR}/.." && pwd)"
|
||||
|
||||
# shellcheck source=config.sh
|
||||
source "${GOG_DIR}/config.sh"
|
||||
gog_swap_guard "${GOG_SWAP_MAX_MB:-400}" || exit 1
|
||||
gog_disk_guard 10 || exit 1
|
||||
|
||||
if [[ ! -f "${GOG_DIR}/bottle.env" ]]; then
|
||||
echo "Сначала: Whisky → New Bottle → bash ${GOG_DIR}/create-bottle.sh GOG-Install"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "=== Подготовка bottle для JA3 (без Galaxy) ==="
|
||||
bash "${GOG_DIR}/setup-bottle.sh"
|
||||
bash "${GOG_DIR}/install-dxvk.sh" 2>/dev/null || bash "${GAMES_DIR}/install-dxvk-macos.sh" 2>/dev/null || \
|
||||
echo "⚠️ DXVK не установлен — JA3 может не стартовать (D3D11). Повторите install-dxvk."
|
||||
|
||||
echo ""
|
||||
echo "OK. Дальше:"
|
||||
echo " bash ${GOG_DIR}/install-ja3-offline.sh ~/Downloads/setup_jagged_alliance_3_*.exe"
|
||||
72
scripts/games/gog/setup-ja3-crossover.sh
Executable file
72
scripts/games/gog/setup-ja3-crossover.sh
Executable file
@@ -0,0 +1,72 @@
|
||||
#!/usr/bin/env bash
|
||||
# CrossOver bottle JA3-GOG: D3D12 через D3DMetal (единственный подтверждённый путь на M1 Pro).
|
||||
# Whisky/Gcenx Wine не содержит D3DMetal hooks (см. Gcenx/macOS_Wine_builds#97).
|
||||
set -euo pipefail
|
||||
GOG_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
# shellcheck source=config.sh
|
||||
source "${GOG_DIR}/config.sh"
|
||||
|
||||
CX_APP="/Applications/CrossOver.app"
|
||||
CX="${CX_APP}/Contents/SharedSupport/CrossOver"
|
||||
CX_BOTTLE="JA3-GOG"
|
||||
CX_DIR="${HOME}/Library/Application Support/CrossOver/Bottles/${CX_BOTTLE}"
|
||||
JA3_SRC="${BOTTLE_DIR}/drive_c/GOG Games/Jagged Alliance 3"
|
||||
JA3_DEST="${CX_DIR}/drive_c/GOG Games/Jagged Alliance 3"
|
||||
|
||||
[[ -d "${CX_APP}" ]] || {
|
||||
echo "❌ Нет CrossOver.app"
|
||||
echo " brew install --cask crossover"
|
||||
exit 1
|
||||
}
|
||||
[[ -f "${JA3_SRC}/JA3.exe" ]] || {
|
||||
echo "❌ Нет JA3 в ${BOTTLE_NAME} — install-ja3-innoextract.sh"
|
||||
exit 1
|
||||
}
|
||||
|
||||
bash "${GOG_DIR}/finish-ja3-layout.sh" >/dev/null 2>&1 || true
|
||||
|
||||
if [[ ! -f "${CX_DIR}/system.reg" ]]; then
|
||||
echo "Создание CrossOver bottle ${CX_BOTTLE} (win10_64)…"
|
||||
"${CX}/bin/cxbottle" --create --bottle "${CX_BOTTLE}" --description "Jagged Alliance 3 GOG" --template win10_64
|
||||
fi
|
||||
|
||||
CONF="${CX_DIR}/cxbottle.conf"
|
||||
touch "${CONF}"
|
||||
sed -i '' '/^"WINED3DMETAL"/d;/^"WINEDXVK"/d' "${CONF}" 2>/dev/null || true
|
||||
{
|
||||
echo '"WINED3DMETAL" = "1"'
|
||||
echo '"WINEDXVK" = "0"'
|
||||
} >> "${CONF}"
|
||||
|
||||
mkdir -p "${CX_DIR}/drive_c/GOG Games"
|
||||
if [[ -L "${JA3_DEST}" ]] || [[ ! -d "${JA3_DEST}" ]]; then
|
||||
rm -f "${JA3_DEST}"
|
||||
echo "Клон игры в CrossOver bottle (APFS clonefile, ~0 доп. места)…"
|
||||
cp -cR "${JA3_SRC}" "${JA3_DEST}"
|
||||
elif [[ ! -f "${JA3_DEST}/CommonLua/Core/autorun.lua" ]]; then
|
||||
echo "Обновление CommonLua в CrossOver bottle…"
|
||||
rm -rf "${JA3_DEST}/CommonLua"
|
||||
cp -R "${JA3_SRC}/CommonLua" "${JA3_DEST}/CommonLua"
|
||||
fi
|
||||
|
||||
LS="${CX_DIR}/drive_c/users/crossover/AppData/Roaming/Jagged Alliance 3"
|
||||
mkdir -p "${LS}"
|
||||
if [[ ! -f "${LS}/LocalStorage.lua" ]]; then
|
||||
cat >"${LS}/LocalStorage.lua" <<'EOF'
|
||||
return {
|
||||
Options = {
|
||||
GraphicsApi = "d3d12",
|
||||
VideoPreset = "Low",
|
||||
},
|
||||
}
|
||||
EOF
|
||||
fi
|
||||
|
||||
export WINEPREFIX="${CX_DIR}"
|
||||
"${CX}/bin/wine" --bottle "${CX_BOTTLE}" reg add 'HKLM\Software\WOW6432Node\GOG.com\Games\1556263729' /v gameName /t REG_SZ /d 'Jagged Alliance 3' /f >/dev/null 2>&1 || true
|
||||
"${CX}/bin/wine" --bottle "${CX_BOTTLE}" reg add 'HKLM\Software\WOW6432Node\GOG.com\Games\1556263729' /v exe /t REG_SZ /d 'JA3.exe' /f >/dev/null 2>&1 || true
|
||||
"${CX}/bin/wine" --bottle "${CX_BOTTLE}" reg add 'HKLM\Software\WOW6432Node\GOG.com\Games\1556263729' /v path /t REG_SZ /d 'C:\GOG Games\Jagged Alliance 3\' /f >/dev/null 2>&1 || true
|
||||
|
||||
echo "OK: CrossOver ${CX_BOTTLE} + D3DMetal"
|
||||
bash "${GOG_DIR}/fix-ja3-crossover-mouse.sh"
|
||||
echo " Запуск: bash ${GOG_DIR}/run-ja3-crossover.sh"
|
||||
64
scripts/games/gog/setup-ja3-gptk-prefix.sh
Executable file
64
scripts/games/gog/setup-ja3-gptk-prefix.sh
Executable file
@@ -0,0 +1,64 @@
|
||||
#!/usr/bin/env bash
|
||||
# Отдельный WINEPREFIX под Wine 7.7 из Game Porting Toolkit (D3D12 + D3DMetal).
|
||||
# Whisky Wine 11 не грузит GPTK dxgi/d3d12 PE — JA3 падает на «Failed creating render device».
|
||||
set -euo pipefail
|
||||
GOG_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
GAMES_DIR="$(cd "${GOG_DIR}/.." && pwd)"
|
||||
# shellcheck source=config.sh
|
||||
source "${GOG_DIR}/config.sh"
|
||||
|
||||
GPTK_WINE="/Applications/Game Porting Toolkit.app/Contents/Resources/wine"
|
||||
GPTK_WINE64="${GPTK_WINE}/bin/wine64"
|
||||
JA3_SRC="${BOTTLE_DIR}/drive_c/GOG Games/Jagged Alliance 3"
|
||||
GPTK_PREFIX="${JA3_GPTK_PREFIX:-${GAMES_CACHE_DIR}/ja3-gptk-prefix}"
|
||||
|
||||
[[ -x "${GPTK_WINE64}" ]] || {
|
||||
echo "❌ brew install --cask gcenx/wine/game-porting-toolkit"
|
||||
exit 1
|
||||
}
|
||||
[[ -f "${JA3_SRC}/JA3.exe" ]] || {
|
||||
echo "❌ Нет JA3 в bottle ${BOTTLE_NAME} — install-ja3-innoextract.sh"
|
||||
exit 1
|
||||
}
|
||||
|
||||
export WINEARCH=win64
|
||||
export WINEPREFIX="${GPTK_PREFIX}"
|
||||
export WINED3DMETAL=1
|
||||
export WINEMSYNC=1
|
||||
export WINEDEBUG=-all
|
||||
export DYLD_LIBRARY_PATH="${GPTK_WINE}/lib:${DYLD_LIBRARY_PATH:-}"
|
||||
|
||||
mkdir -p "${GPTK_PREFIX}"
|
||||
|
||||
if [[ ! -f "${GPTK_PREFIX}/system.reg" ]]; then
|
||||
echo "Инициализация GPTK prefix: ${GPTK_PREFIX}"
|
||||
"${GPTK_WINE64}" wineboot -i
|
||||
fi
|
||||
|
||||
GOG_DRIVE="${GPTK_PREFIX}/drive_c/GOG Games"
|
||||
JA3_LINK="${GOG_DRIVE}/Jagged Alliance 3"
|
||||
mkdir -p "${GOG_DRIVE}"
|
||||
if [[ -L "${JA3_LINK}" ]]; then
|
||||
:
|
||||
elif [[ -d "${JA3_LINK}" ]]; then
|
||||
echo " JA3 уже в prefix (не symlink)"
|
||||
else
|
||||
ln -s "${JA3_SRC}" "${JA3_LINK}"
|
||||
fi
|
||||
|
||||
# CommonLua + upscale cleanup (на исходной копии в GOG bottle)
|
||||
bash "${GOG_DIR}/finish-ja3-layout.sh" >/dev/null 2>&1 || true
|
||||
|
||||
WINE64="${GPTK_WINE64}" BOTTLE_DIR="${GPTK_PREFIX}" export_wine_env_gog
|
||||
export WINED3DMETAL=1
|
||||
export WINEDLLOVERRIDES="libxess,xess,dxcompiler,dxil,nvngx_dlss,XeFX,XeFX_Loader=d;gdiplus=n,b"
|
||||
|
||||
GAME_ID='1556263729'
|
||||
KEY="HKLM\\Software\\WOW6432Node\\GOG.com\\Games\\${GAME_ID}"
|
||||
"${GPTK_WINE64}" reg add "${KEY}" /v gameName /t REG_SZ /d 'Jagged Alliance 3' /f >/dev/null
|
||||
"${GPTK_WINE64}" reg add "${KEY}" /v exe /t REG_SZ /d 'JA3.exe' /f >/dev/null
|
||||
"${GPTK_WINE64}" reg add "${KEY}" /v path /t REG_SZ /d 'C:\GOG Games\Jagged Alliance 3\' /f >/dev/null
|
||||
|
||||
echo "${GPTK_PREFIX}" >"${GAMES_CACHE_DIR}/.ja3_gptk_prefix"
|
||||
echo "OK: GPTK prefix → ${GPTK_PREFIX}"
|
||||
echo " Запуск: bash ${GOG_DIR}/run-ja3-gptk-wine.sh"
|
||||
45
scripts/games/gog/upgrade-whisky-wine-gcenx.sh
Executable file
45
scripts/games/gog/upgrade-whisky-wine-gcenx.sh
Executable file
@@ -0,0 +1,45 @@
|
||||
#!/usr/bin/env bash
|
||||
# Whisky Libraries Wine 11.0 → Gcenx wine-staging 11.9 + GPTK D3DMetal bridge (JA3 / D3D12).
|
||||
set -euo pipefail
|
||||
GOG_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
GAMES_DIR="$(cd "${GOG_DIR}/.." && pwd)"
|
||||
# shellcheck source=config.sh
|
||||
source "${GOG_DIR}/config.sh"
|
||||
|
||||
CACHE="${GAMES_CACHE_DIR}"
|
||||
TAR="${CACHE}/wine-staging-11.9-osx64.tar.xz"
|
||||
URL="https://github.com/Gcenx/macOS_Wine_builds/releases/download/11.9/wine-staging-11.9-osx64.tar.xz"
|
||||
WHISKY_WINE="${WHISKY_LIBS}/Libraries/Wine"
|
||||
STAMP="${WHISKY_LIBS}/Libraries/.wine_gcenx_11.9"
|
||||
|
||||
[[ -f "${TAR}" ]] || curl -L --fail -o "${TAR}" "${URL}"
|
||||
EXTRACT="${CACHE}/wine-staging-11.9-extract"
|
||||
rm -rf "${EXTRACT}"
|
||||
mkdir -p "${EXTRACT}"
|
||||
tar -xJf "${TAR}" -C "${EXTRACT}"
|
||||
SRC="${EXTRACT}/Wine Staging.app/Contents/Resources/wine"
|
||||
|
||||
[[ -d "${SRC}/bin" ]] || {
|
||||
echo "❌ Неверная структура архива"
|
||||
exit 1
|
||||
}
|
||||
|
||||
if [[ ! -f "${STAMP}" ]]; then
|
||||
bak="${WHISKY_WINE}.bak.$(date +%Y%m%d%H%M)"
|
||||
echo "Бэкап Wine → ${bak}"
|
||||
cp -a "${WHISKY_WINE}" "${bak}"
|
||||
fi
|
||||
|
||||
rsync -a --delete \
|
||||
--exclude 'lib/external/' \
|
||||
"${SRC}/" "${WHISKY_WINE}/"
|
||||
|
||||
# Gcenx: wine64 → wine; Whisky-скрипты ожидают bin/wine64
|
||||
if [[ -x "${WHISKY_WINE}/bin/wine" ]] && [[ ! -e "${WHISKY_WINE}/bin/wine64" ]]; then
|
||||
ln -sf wine "${WHISKY_WINE}/bin/wine64"
|
||||
fi
|
||||
|
||||
bash "${GOG_DIR}/install-gptk-whisky.sh"
|
||||
touch "${STAMP}"
|
||||
echo "OK: Whisky Wine → staging 11.9 + GPTK D3DMetal"
|
||||
"${WHISKY_WINE}/bin/wine64" --version 2>&1 | head -1
|
||||
20
scripts/games/gog/use-bottle.sh
Executable file
20
scripts/games/gog/use-bottle.sh
Executable file
@@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
GOG_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
id="${1:-}"
|
||||
name="${2:-GOG-Install}"
|
||||
if [[ -z "${id}" ]]; then
|
||||
echo "Использование: $(basename "$0") <BOTTLE_UUID> [имя]"
|
||||
bash "${GOG_DIR}/list-bottles.sh"
|
||||
exit 1
|
||||
fi
|
||||
if [[ "${id}" == "38412122-AAE1-4831-9F2E-6A0EB364B3F9" ]]; then
|
||||
echo "❌ Это bottle HoMM-OldenEra (Steam/HoMM). Создайте новый bottle в Whisky."
|
||||
exit 1
|
||||
fi
|
||||
cat >"${GOG_DIR}/bottle.env" <<EOF
|
||||
BOTTLE_ID=${id}
|
||||
BOTTLE_NAME=${name}
|
||||
EOF
|
||||
echo "OK: ${GOG_DIR}/bottle.env → ${name} (${id})"
|
||||
echo "Дальше: bash ${GOG_DIR}/setup-bottle.sh"
|
||||
85
scripts/games/gog/wine-fonts.sh
Executable file
85
scripts/games/gog/wine-fonts.sh
Executable file
@@ -0,0 +1,85 @@
|
||||
# shellcheck shell=bash
|
||||
# Шрифты для GOG web-installer (.NET). Только macOS + corefonts — без Steam.
|
||||
|
||||
gog_wine_install_fonts_mac() {
|
||||
local fonts="${BOTTLE_DIR}/drive_c/windows/Fonts"
|
||||
mkdir -p "${fonts}"
|
||||
for f in /System/Library/Fonts/Supplemental/{Arial,Tahoma,Verdana,"Times New Roman","Courier New","Segoe UI"}.ttf \
|
||||
/System/Library/Fonts/Supplemental/Arial*.ttf \
|
||||
/Library/Fonts/Arial*.ttf; do
|
||||
[[ -f "${f}" ]] && cp -n "${f}" "${fonts}/" 2>/dev/null || true
|
||||
done
|
||||
# .NET GenericSansSerif → Microsoft Sans Serif / Arial
|
||||
cp -n "${fonts}/Arial.ttf" "${fonts}/sans-serif.ttf" 2>/dev/null || true
|
||||
cp -n "${fonts}/Arial.ttf" "${fonts}/arial.ttf" 2>/dev/null || true
|
||||
cp -n "${fonts}/Arial.ttf" "${fonts}/micross.ttf" 2>/dev/null || true
|
||||
cp -n "${fonts}/Arial.ttf" "${fonts}/Microsoft Sans Serif.ttf" 2>/dev/null || true
|
||||
cp -n "${fonts}/Tahoma.ttf" "${fonts}/tahoma.ttf" 2>/dev/null || true
|
||||
}
|
||||
|
||||
gog_wine_register_font_file() {
|
||||
local reg_name="$1"
|
||||
local ttf_file="$2"
|
||||
export WINEPREFIX="${BOTTLE_DIR}"
|
||||
"${WINE64}" reg add 'HKLM\Software\Microsoft\Windows NT\CurrentVersion\Fonts' \
|
||||
/v "${reg_name} (TrueType)" /t REG_SZ /d "${ttf_file}" /f >/dev/null 2>&1 || true
|
||||
}
|
||||
|
||||
gog_wine_register_all_fonts_dir() {
|
||||
local fonts="${BOTTLE_DIR}/drive_c/windows/Fonts"
|
||||
local f base reg
|
||||
for f in "${fonts}"/*; do
|
||||
[[ -f "${f}" ]] || continue
|
||||
[[ "${f}" == *.ttf || "${f}" == *.TTF ]] || continue
|
||||
base="$(basename "${f}")"
|
||||
reg="${base%.*}"
|
||||
gog_wine_register_font_file "${reg}" "${base}"
|
||||
done
|
||||
}
|
||||
|
||||
gog_wine_wineboot_fonts() {
|
||||
export WINEPREFIX="${BOTTLE_DIR}"
|
||||
export DYLD_LIBRARY_PATH="${WINE_LIB}:${DYLD_LIBRARY_PATH:-}"
|
||||
"${WINE64}" wineboot -u 2>/dev/null || true
|
||||
}
|
||||
|
||||
gog_wine_register_fonts_registry() {
|
||||
export WINEPREFIX="${BOTTLE_DIR}"
|
||||
local fonts="${BOTTLE_DIR}/drive_c/windows/Fonts"
|
||||
|
||||
gog_wine_register_font_file 'Arial' 'arial.ttf'
|
||||
gog_wine_register_font_file 'Tahoma' 'tahoma.ttf'
|
||||
gog_wine_register_font_file 'Verdana' 'verdana.ttf'
|
||||
gog_wine_register_font_file 'Times New Roman' 'Times New Roman.ttf'
|
||||
gog_wine_register_font_file 'Courier New' 'Courier New.ttf'
|
||||
gog_wine_register_font_file 'Microsoft Sans Serif' 'micross.ttf'
|
||||
|
||||
local sub='HKLM\Software\Microsoft\Windows NT\CurrentVersion\FontSubstitutes'
|
||||
"${WINE64}" reg add "${sub}" /v 'MS Shell Dlg' /t REG_SZ /d 'Tahoma' /f >/dev/null 2>&1 || true
|
||||
"${WINE64}" reg add "${sub}" /v 'MS Shell Dlg 2' /t REG_SZ /d 'Tahoma' /f >/dev/null 2>&1 || true
|
||||
"${WINE64}" reg add "${sub}" /v 'MS Sans Serif' /t REG_SZ /d 'Arial' /f >/dev/null 2>&1 || true
|
||||
"${WINE64}" reg add "${sub}" /v 'Segoe UI' /t REG_SZ /d 'Tahoma' /f >/dev/null 2>&1 || true
|
||||
|
||||
local rep='HKCU\Software\Wine\Fonts\Replacements'
|
||||
"${WINE64}" reg add "${rep}" /v '@@MS_SHELLDLG' /t REG_SZ /d 'Tahoma' /f >/dev/null 2>&1 || true
|
||||
"${WINE64}" reg add "${rep}" /v 'MS Shell Dlg' /t REG_SZ /d 'Tahoma' /f >/dev/null 2>&1 || true
|
||||
"${WINE64}" reg add "${rep}" /v 'Microsoft Sans Serif' /t REG_SZ /d 'Arial' /f >/dev/null 2>&1 || true
|
||||
"${WINE64}" reg add "${rep}" /v 'SansSerif' /t REG_SZ /d 'Arial' /f >/dev/null 2>&1 || true
|
||||
"${WINE64}" reg add "${sub}" /v 'SansSerif' /t REG_SZ /d 'Arial' /f >/dev/null 2>&1 || true
|
||||
|
||||
gog_wine_register_all_fonts_dir
|
||||
}
|
||||
|
||||
gog_wine_ensure_fonts() {
|
||||
local rebuild="${1:-0}"
|
||||
export_wine_env_gog
|
||||
gog_wine_install_fonts_mac
|
||||
gog_wine_register_fonts_registry
|
||||
if [[ "${rebuild}" == "1" ]]; then
|
||||
echo "wineboot -u (~30–60 с)…"
|
||||
gog_wine_wineboot_fonts
|
||||
fi
|
||||
local n
|
||||
n="$(ls "${BOTTLE_DIR}/drive_c/windows/Fonts" 2>/dev/null | wc -l | tr -d ' ')"
|
||||
echo "Шрифты (${BOTTLE_NAME}): ${n} файлов"
|
||||
}
|
||||
Reference in New Issue
Block a user