Compare commits
9 Commits
f9394f90c9
...
testing
| Author | SHA1 | Date | |
|---|---|---|---|
| 92745d8af8 | |||
| 1f977bb1f4 | |||
| 53d8c10645 | |||
| b58681964c | |||
| 2abf445637 | |||
| c0e6c37f1a | |||
| 856415c22f | |||
| 7ddd7cbac4 | |||
| 951fa7c1ba |
@@ -1,3 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
declare -a errorList
|
||||
declare -a packageList
|
||||
if [[ $# -eq 0 ]]; then
|
||||
@@ -10,6 +12,12 @@ else
|
||||
errorList+=("Critical: Wine is not installed. You will not be able to play any games.")
|
||||
fi
|
||||
packageList+=("wine")
|
||||
if command -v umu-run &> /dev/null ; then
|
||||
[[ $# -eq 0 ]] && echo "umu-launcher is installed."
|
||||
else
|
||||
errorList+=("Warning: umu-launcher is not installed. Games that require Proton/UMU will not install or launch.")
|
||||
fi
|
||||
packageList+=("umu-launcher")
|
||||
if command -v curl &> /dev/null ; then
|
||||
[[ $# -eq 0 ]] && echo "Curl is installed."
|
||||
else
|
||||
|
||||
+24
-8
@@ -1,13 +1,31 @@
|
||||
#!/usr/bin/env bash
|
||||
# shellcheck disable=SC2034,SC2154 # sourced by audiogame-manager with shared globals and exported state
|
||||
|
||||
# Source IPFS game URLs
|
||||
source "${BASH_SOURCE[0]%/*}/ipfs.sh"
|
||||
|
||||
# Alerts, for when user needs to read something.
|
||||
alert() {
|
||||
local title="Alert"
|
||||
local backTitle=""
|
||||
local message="Press OK to continue."
|
||||
|
||||
if [[ $# -eq 1 ]]; then
|
||||
message="$1"
|
||||
elif [[ $# -eq 2 ]]; then
|
||||
title="$1"
|
||||
backTitle="$1"
|
||||
message="$2"
|
||||
elif [[ $# -ge 3 ]]; then
|
||||
title="$1"
|
||||
backTitle="$2"
|
||||
shift 2
|
||||
message="$*"
|
||||
fi
|
||||
|
||||
play -qnV0 synth 3 pluck D3 pluck A3 pluck D4 pluck F4 pluck A4 delay 0 .1 .2 .3 .4 remix - chorus 0.9 0.9 38 0.75 0.3 0.5 -t
|
||||
echo
|
||||
agm_msgbox "Alert" "" "Press OK to continue."
|
||||
agm_msgbox "${title}" "${backTitle}" "${message}"
|
||||
}
|
||||
|
||||
check_requirements() {
|
||||
@@ -54,7 +72,7 @@ clear_cache() {
|
||||
}
|
||||
|
||||
download() {
|
||||
local source=($@)
|
||||
local source=("$@")
|
||||
for i in "${source[@]}" ; do
|
||||
local dest="${i##*/}"
|
||||
dest="${dest//%20/ }"
|
||||
@@ -120,8 +138,7 @@ download() {
|
||||
esac
|
||||
if [[ $downloadError -ne 0 ]]; then
|
||||
rm -fv "${cache}/${dest}"
|
||||
agm_infobox "Audio Game Manager" "Audio Game Manager" "Error downloading \"${dest}\". Installation cannot continue."
|
||||
alert
|
||||
alert "Audio Game Manager" "Audio Game Manager" "Error downloading \"${dest}\". Installation cannot continue."
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
@@ -142,10 +159,10 @@ get_installer() {
|
||||
if echo "$2" | xclip -selection clipboard 2> /dev/null ; then
|
||||
message+="\n\nThe URL has been copied to the clipboard."
|
||||
fi
|
||||
agm_msgbox "Audiogame Manager" "Audiogame Manager" "$message"
|
||||
alert "Audiogame Manager" "Audiogame Manager" "$message"
|
||||
# Search the Desktop and Downloads directories for the installation file
|
||||
for i in ~/Downloads ~/Desktop ; do
|
||||
find $i -type f -name "$1" -exec cp -v {} "${cache}/" \;
|
||||
find "$i" -type f -name "$1" -exec cp -v {} "${cache}/" \;
|
||||
done
|
||||
# If the file is still not available abort.
|
||||
if [[ ! -f "${cache}/$1" ]]; then
|
||||
@@ -157,8 +174,7 @@ get_installer() {
|
||||
get_steam() {
|
||||
# Arguments: $1 id of item for download, $2 url for game
|
||||
trap "exit 0" SIGINT
|
||||
echo "manual intervention required."
|
||||
alert
|
||||
alert "Audiogame Manager" "Audiogame Manager" "Manual intervention required."
|
||||
agm_yesno "Audiogame Manager" "Audiogame Manager" "To install the game manually, place files in \"${WINEPREFIX}/drive_c/Program Files/${game}\". Continue with Steam installation?"
|
||||
case $? in
|
||||
0) echo "The next steps will install through steamcmd." ;;
|
||||
|
||||
+28
-2
@@ -1,3 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
# shellcheck disable=SC2154 # Sourced by audiogame-manager with shared globals.
|
||||
|
||||
documentation() {
|
||||
if [[ "$2" == "Become a Patron" ]]; then
|
||||
return
|
||||
@@ -8,13 +11,36 @@ documentation() {
|
||||
|
||||
# Extract architecture from first parameter (format: "win64|path")
|
||||
local wineArch="${1%%|*}"
|
||||
get_bottle "$wineArch"
|
||||
if [[ "$wineArch" == "umu" ]]; then
|
||||
local launcherLine=""
|
||||
local docFlag=""
|
||||
local umuGameId=""
|
||||
local -a documentationGame=()
|
||||
launcherLine="$(grep -F -m1 "${1}|" "$configFile" 2> /dev/null || true)"
|
||||
IFS='|' read -ra documentationGame <<< "$launcherLine"
|
||||
for docFlag in "${documentationGame[@]:3}" ; do
|
||||
if [[ "$docFlag" =~ ^export\ [a-zA-Z_][a-zA-Z0-9_]*=\'?.*\'?$ ]]; then
|
||||
eval "$docFlag"
|
||||
fi
|
||||
done
|
||||
if [[ -z "$umuGameId" ]]; then
|
||||
echo "Unable to find UMU game id for documentation lookup."
|
||||
return
|
||||
fi
|
||||
get_umu_bottle "$umuGameId"
|
||||
else
|
||||
get_bottle "$wineArch"
|
||||
fi
|
||||
|
||||
echo "Loading documentation, please wait..."
|
||||
|
||||
# Try to find documentation based on common naming conventions.
|
||||
local gamePath
|
||||
gamePath="$(winepath -u "$2" 2> /dev/null)"
|
||||
if [[ "$wineArch" == "umu" ]]; then
|
||||
gamePath="$(umu_windows_path_to_unix "$2")"
|
||||
else
|
||||
gamePath="$(winepath -u "$2" 2> /dev/null)"
|
||||
fi
|
||||
gamePath="${gamePath%/*}"
|
||||
local gameDoc=""
|
||||
local isUrl="false"
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
#!/usr/bin/env bash
|
||||
# shellcheck disable=SC2034,SC2154 # Sourced by audiogame-manager and installers with shared globals.
|
||||
|
||||
require_umu() {
|
||||
if command -v umu-run &> /dev/null; then
|
||||
return 0
|
||||
fi
|
||||
local message="This game requires umu-launcher. Please install umu-launcher and try again."
|
||||
if declare -F agm_msgbox &> /dev/null; then
|
||||
agm_msgbox "Audio Game Manager" "Audio Game Manager" "$message"
|
||||
else
|
||||
echo "$message" >&2
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
get_umu_bottle() {
|
||||
local gameId="$1"
|
||||
if [[ -z "$gameId" ]]; then
|
||||
echo "get_umu_bottle requires a game id." >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
export umuGameId="$gameId"
|
||||
export WINEPREFIX="${XDG_DATA_HOME:-$HOME/.local/share}/audiogame-manager/protonBottles/${gameId}"
|
||||
export GAMEID="$gameId"
|
||||
export STORE="${umuStore:-none}"
|
||||
export DISPLAY="${DISPLAY:-:0}"
|
||||
mkdir -p "$WINEPREFIX"
|
||||
}
|
||||
|
||||
install_proton_bottle() {
|
||||
local gameId="$1"
|
||||
shift || true
|
||||
require_umu || return 1
|
||||
get_umu_bottle "$gameId" || return 1
|
||||
|
||||
if [[ ! -f "${WINEPREFIX}/system.reg" ]]; then
|
||||
umu-run ""
|
||||
fi
|
||||
|
||||
if [[ $# -gt 0 ]]; then
|
||||
umu-run winetricks "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
umu_windows_path_to_unix() {
|
||||
local windowsPath="$1"
|
||||
local relativePath=""
|
||||
if [[ "$windowsPath" =~ ^[cC]:\\ ]]; then
|
||||
relativePath="${windowsPath:3}"
|
||||
relativePath="${relativePath//\\//}"
|
||||
printf '%s/drive_c/%s\n' "$WINEPREFIX" "$relativePath"
|
||||
return 0
|
||||
fi
|
||||
winepath -u "$windowsPath"
|
||||
}
|
||||
|
||||
run_umu_game() {
|
||||
local windowsPath="$1"
|
||||
local exePath=""
|
||||
require_umu || return 1
|
||||
if [[ -z "${umuGameId:-}" ]]; then
|
||||
echo "UMU game id is not set for ${game[2]:-selected game}." >&2
|
||||
return 1
|
||||
fi
|
||||
get_umu_bottle "$umuGameId" || return 1
|
||||
exePath="$(umu_windows_path_to_unix "$windowsPath")"
|
||||
if [[ ! -f "$exePath" ]]; then
|
||||
echo "UMU executable not found: $exePath" >&2
|
||||
return 1
|
||||
fi
|
||||
pushd "${exePath%/*}" > /dev/null || return 1
|
||||
umu-run "$exePath"
|
||||
popd > /dev/null || return 1
|
||||
}
|
||||
|
||||
add_umu_launcher() {
|
||||
local gameId="$1"
|
||||
local windowsPath="$2"
|
||||
shift 2
|
||||
local launchSettings="umu|${windowsPath}|${game}|export umuGameId=${gameId}"
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
launchSettings+="|$1"
|
||||
shift
|
||||
done
|
||||
|
||||
if ! grep -F -q -x "$launchSettings" "$configFile" 2> /dev/null; then
|
||||
echo "$launchSettings" >> "$configFile"
|
||||
sort -t '|' -k3,3f -o "$configFile" "$configFile"
|
||||
fi
|
||||
}
|
||||
|
||||
set_umu_reg_value() {
|
||||
local key="$1"
|
||||
local valueName="$2"
|
||||
local valueData="$3"
|
||||
wine reg add "$key" /v "$valueName" /t REG_SZ /d "$valueData" /f
|
||||
}
|
||||
|
||||
set_umu_app_winver() {
|
||||
local exeName="$1"
|
||||
local winVersion="$2"
|
||||
set_umu_reg_value "HKCU\\Software\\Wine\\AppDefaults\\${exeName}" "Version" "$winVersion"
|
||||
}
|
||||
|
||||
install_crlf_file() {
|
||||
local sourceFile="$1"
|
||||
local destFile="$2"
|
||||
mkdir -p "${destFile%/*}"
|
||||
perl -pe 's/\r?\n/\r\n/' "$sourceFile" > "$destFile"
|
||||
}
|
||||
|
||||
stop_umu_bottle() {
|
||||
if command -v wineserver &> /dev/null; then
|
||||
wineserver -k 2> /dev/null || true
|
||||
fi
|
||||
}
|
||||
@@ -1,9 +1,8 @@
|
||||
# shellcheck shell=bash disable=SC2154 # cache and WINEPREFIX are set by audiogame-manager
|
||||
download "https://github.com/matatk/agrip/releases/download/2020.0-beta1/AudioQuake+LDL_2020.0-beta1_Windows.zip" "https://stormgames.wolfe.casa/downloads/quake.zip"
|
||||
export winVer="win7"
|
||||
install_wine_bottle
|
||||
install_with_progress unzip "Extracting game files..." -d "$WINEPREFIX/drive_c/Program Files" "${cache}/AudioQuake+LDL_2020.0-beta1_Windows.zip"
|
||||
install_with_progress unzip "Extracting game files..." -d "$WINEPREFIX/drive_c/Program Files/AudioQuake/id1" "${cache}/quake.zip"
|
||||
add_launcher "c:\Program Files\AudioQuake\AudioQuake.exe"
|
||||
echo
|
||||
echo "After you launch the game, press tab then enter and it should begin speaking."
|
||||
alert
|
||||
alert "After you launch the game, press tab then enter and it should begin speaking."
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# shellcheck shell=bash disable=SC2154 # cache, WINEPREFIX, and game are set by audiogame-manager
|
||||
gameVersion=2.4.1
|
||||
download "https://dl.tweesecake.app/rage/rage${gameVersion}.zip"
|
||||
export WINEARCH=win64
|
||||
@@ -6,9 +7,8 @@ install_wine_bottle
|
||||
install_with_progress unzip "Extracting game files..." -d "$WINEPREFIX/drive_c/Program Files/" "${cache}/rage${gameVersion}.zip"
|
||||
add_launcher "c:\Program Files\rage\rage.exe"
|
||||
url="https://techcake.games/games/executioners-rage/"
|
||||
echo "Before you can login, you need to create an account at:"
|
||||
echo "$url"
|
||||
message="Before you can login, you need to create an account at:\n${url}"
|
||||
if echo "$url" | xclip -selection clipboard 2> /dev/null ; then
|
||||
message+="\n\nThe URL has been copied to the clipboard."
|
||||
fi
|
||||
alert
|
||||
alert "Executioner's Rage" "Executioner's Rage" "$message"
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
# shellcheck shell=bash disable=SC2154 # cache and WINEPREFIX are set by audiogame-manager
|
||||
get_installer "Galactic Strike 1.2.zip" "https://fusion-forged-games.itch.io/galactic-strike"
|
||||
export winVer="win10"
|
||||
install_wine_bottle
|
||||
install_with_progress unzip "Extracting game files..." -d "$WINEPREFIX/drive_c/Program Files/Galactic Strike" "${cache}/Galactic Strike 1.2.zip"
|
||||
add_launcher "c:\Program Files\Galactic Strike\Galactic Strike.exe"
|
||||
echo "Use controls wasd to movi and navigate the menu."
|
||||
echo "Use m to fire and select items from the menu."
|
||||
alert
|
||||
alert "Use controls wasd to movi and navigate the menu.\nUse m to fire and select items from the menu."
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# shellcheck shell=bash disable=SC2154 # cache and WINEPREFIX are set by audiogame-manager
|
||||
download "https://stormgames.wolfe.casa/downloads/grizzly-gulch.zip"
|
||||
install_wine_bottle vb6run mfc42
|
||||
install_with_progress unzip "Extracting game files..." -d "$WINEPREFIX/drive_c/Program Files" "$cache/grizzly-gulch.zip"
|
||||
add_launcher "c:\Program Files\grizzly-gulch\Grizzly Gulch.exe"
|
||||
echo "If the combat sequences happen too slow for your tastes, while in the town square, you can use f12 to turn up the combat speed and f11 to lower it."
|
||||
alert
|
||||
alert "If the combat sequences happen too slow for your tastes, while in the town square, you can use f12 to turn up the combat speed and f11 to lower it."
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
download "http://files.l-works.net/judgmentdayfullsetup.exe"
|
||||
# shellcheck shell=bash disable=SC2154 # cache is set by audiogame-manager
|
||||
download "https://www.l-works.net/files/judgmentdayfullsetup.exe"
|
||||
install_wine_bottle vb6run dx8vb quartz
|
||||
wine "${cache}/judgmentdayfullsetup.exe" /silent
|
||||
cat << EOF > /tmp/judgementday.reg
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# shellcheck shell=bash disable=SC2154 # cache and WINEPREFIX are set by audiogame-manager
|
||||
export WINEARCH="win64" # Migrated to wine64 with WINETRICKS_FORCE=1
|
||||
export winVer="win7"
|
||||
export winetricksSettings="vd=1024x768"
|
||||
@@ -6,5 +7,4 @@ install_wine_bottle sapi vb6run dx8vb quartz
|
||||
install_with_progress unzip "Extracting game files..." -d "$WINEPREFIX/drive_c/Program Files/lunimals" "${cache}/lunimals.zip"
|
||||
wine 'c:\Program Files\lunimals\checkup.exe' /verysilent
|
||||
add_launcher "c:\Program Files\lunimals\Lunimals.exe"
|
||||
echo "Note: Lunimals installed. Once you start the game, you must press tab until you hear sapi on to get speech." >&2
|
||||
alert
|
||||
alert "Note: Lunimals installed. Once you start the game, you must press tab until you hear sapi on to get speech."
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
export WINEARCH=win64
|
||||
# shellcheck disable=SC2154 # installer is sourced by audiogame-manager with shared globals
|
||||
export winVer="win10"
|
||||
game="${game:-Magic: The Gathering Arena}"
|
||||
|
||||
mtgaVersionUrl="https://mtgarena.downloads.wizards.com/Live/Windows32/version"
|
||||
accessibleArenaDllUrl="https://github.com/JeanStiletto/AccessibleArena/releases/latest/download/AccessibleArena.dll"
|
||||
melonLoaderZipUrl="https://github.com/LavaGang/MelonLoader/releases/latest/download/MelonLoader.x64.zip"
|
||||
tolkDllUrl="https://stormgames.wolfe.casa/downloads/Tolk.dll"
|
||||
|
||||
get_mtga_installer_url() {
|
||||
local versionJson=""
|
||||
local installerUrl=""
|
||||
|
||||
if ! versionJson="$(curl -fsSL "$mtgaVersionUrl")"; then
|
||||
alert "Magic: The Gathering Arena" "Magic: The Gathering Arena" "Could not fetch the current MTG Arena installer URL."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
installerUrl="$(sed -n 's/.*"CurrentInstallerURL"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' <<< "$versionJson" | head -n1)"
|
||||
if [[ -z "$installerUrl" ]]; then
|
||||
alert "Magic: The Gathering Arena" "Magic: The Gathering Arena" "Could not parse the current MTG Arena installer URL."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
printf '%s\n' "$installerUrl"
|
||||
}
|
||||
|
||||
download_mtga_installer() {
|
||||
local installerUrl="$1"
|
||||
local installerFile="${installerUrl##*/}"
|
||||
installerFile="${installerFile%%\?*}"
|
||||
[[ -n "$installerFile" ]] || installerFile="MTGAInstaller.msi"
|
||||
|
||||
# shellcheck disable=SC2154 # cache is set by audiogame-manager before installers are sourced
|
||||
if [[ "${redownload:-}" == "true" ]] || [[ ! -s "${cache}/${installerFile}" ]]; then
|
||||
if ! curl -L4 -C - --retry 10 --output "${cache}/${installerFile}" "$installerUrl" 2>&1 | agm_progressbox "Magic: The Gathering Arena" "Downloading MTG Arena installer..."; then
|
||||
alert "Magic: The Gathering Arena" "Magic: The Gathering Arena" "Could not download the MTG Arena installer."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
mtgaInstallerPath="${cache}/${installerFile}"
|
||||
}
|
||||
|
||||
configure_accessible_arena_loader() {
|
||||
local mtgaRoot="$1"
|
||||
local userDataPath="${mtgaRoot}/UserData"
|
||||
local loaderConfig="${userDataPath}/Loader.cfg"
|
||||
|
||||
mkdir -p "$userDataPath"
|
||||
if [[ -f "$loaderConfig" ]]; then
|
||||
if grep -Fq "hide_console = false" "$loaderConfig"; then
|
||||
sed -i 's/hide_console = false/hide_console = true/g' "$loaderConfig"
|
||||
elif ! grep -Fq "hide_console" "$loaderConfig"; then
|
||||
printf '\n[console]\nhide_console = true\n' >> "$loaderConfig"
|
||||
fi
|
||||
else
|
||||
printf '[console]\nhide_console = true\n' > "$loaderConfig"
|
||||
fi
|
||||
}
|
||||
|
||||
install_accessible_arena_support() {
|
||||
local mtgaRoot="$1"
|
||||
|
||||
if [[ -z "${nvdaControllerClient64Dll:-}" ]]; then
|
||||
# shellcheck disable=SC2154 # ipfs is sourced through audiogame-manager helpers
|
||||
nvdaControllerClient64Dll="${ipfs[nvdaControllerClient64]}"
|
||||
fi
|
||||
|
||||
download "$accessibleArenaDllUrl" "$melonLoaderZipUrl" "$tolkDllUrl" "$nvdaControllerClient64Dll"
|
||||
|
||||
install_with_progress unzip "Installing MelonLoader..." -d "$mtgaRoot" "${cache}/MelonLoader.x64.zip"
|
||||
mkdir -p "${mtgaRoot}/Mods"
|
||||
install_with_progress cp "Installing Accessible Arena..." "${cache}/AccessibleArena.dll" "${mtgaRoot}/Mods/AccessibleArena.dll"
|
||||
install_with_progress cp "Installing screen reader support DLLs..." "${cache}/Tolk.dll" "${cache}/nvdaControllerClient64.dll" "$mtgaRoot"
|
||||
configure_accessible_arena_loader "$mtgaRoot"
|
||||
}
|
||||
|
||||
install_wine_bottle dxvk
|
||||
winetricks -q $winVer
|
||||
|
||||
mtgaRoot="${WINEPREFIX}/drive_c/Program Files (x86)/Wizards of the Coast/MTGA"
|
||||
mtgaInstallerUrl="$(get_mtga_installer_url)"
|
||||
download_mtga_installer "$mtgaInstallerUrl"
|
||||
|
||||
wine msiexec /i "$mtgaInstallerPath" /q
|
||||
|
||||
if [[ ! -f "${mtgaRoot}/MTGA.exe" ]]; then
|
||||
alert "Magic: The Gathering Arena" "Magic: The Gathering Arena" "MTG Arena installation did not finish at the expected location: ${mtgaRoot}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
install_accessible_arena_support "$mtgaRoot"
|
||||
add_launcher 'c:\Program Files (x86)\Wizards of the Coast\MTGA\MTGA.exe' 'export WINEDLLOVERRIDES=version=n,b'
|
||||
+2
-10
@@ -1,3 +1,4 @@
|
||||
# shellcheck shell=bash disable=SC2154 # cache and WINEPREFIX are set by audiogame-manager
|
||||
export WINEARCH="win64" # Migrated to wine64
|
||||
export winVer="win7"
|
||||
|
||||
@@ -8,13 +9,4 @@ sed -i 's/1024m/768m/g' "$WINEPREFIX/drive_c/Program Files/Mist World/mw.exe.vmo
|
||||
cp "$WINEPREFIX/drive_c/Program Files/Mist World/"{mw.exe.vmoptions,update.exe.vmoptions}
|
||||
mkdir "$WINEPREFIX/drive_c/Program Files/Mist World/"{user,users}
|
||||
add_launcher 'c:\Program Files\Mist World\mw.exe'
|
||||
echo
|
||||
echo "If you do not have an account, There is a script in game-scripts to help."
|
||||
echo "Launch the game, press enter on create account, then drop into a console so the game window does not lose focus."
|
||||
echo "Change to the game-scripts directory and run"
|
||||
echo "./mist_world_account_creator.sh and follow the prompts."
|
||||
echo
|
||||
echo "To login, type your email address, press tab, and type your password."
|
||||
echo "If you want to enable automatic login, press tab two times followed by space, then tab and enter."
|
||||
echo "If you do not want to auto login, you can just press enter after typing your password."
|
||||
alert
|
||||
alert "If you do not have an account, There is a script in game-scripts to help.\nLaunch the game, press enter on create account, then drop into a console so the game window does not lose focus.\nChange to the game-scripts directory and run\n./mist_world_account_creator.sh and follow the prompts.\n\nTo login, type your email address, press tab, and type your password.\nIf you want to enable automatic login, press tab two times followed by space, then tab and enter.\nIf you do not want to auto login, you can just press enter after typing your password."
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
# shellcheck shell=bash disable=SC2154 # cache and WINEPREFIX are set by audiogame-manager
|
||||
# shellcheck disable=SC2034 # consumed by shared bottle setup
|
||||
winetricksSettings="vd=1024x768"
|
||||
export winVer="win7"
|
||||
download "https://stevend.net/downloads/scramble_win32.zip"
|
||||
install_wine_bottle
|
||||
install_with_progress unzip "Extracting game files..." -d "$WINEPREFIX/drive_c/Program Files/" "${cache}/scramble_win32.zip"
|
||||
echo "Note: When you first start the game, it will say that tts initialization failed. Please answer that you do not want to attempt initialization of tts when the game starts to allow easy speech through speech dispatcher."
|
||||
alert
|
||||
alert "Note: When you first start the game, it will say that tts initialization failed. Please answer that you do not want to attempt initialization of tts when the game starts to allow easy speech through speech dispatcher."
|
||||
add_launcher "c:\Program Files\scramble_win32\scramble.exe"
|
||||
|
||||
+35
-25
@@ -1,28 +1,38 @@
|
||||
#//Disable since it's not working
|
||||
download "https://www.mm-galabo.com/sr/Download_files_srfv/shadowrine_fullvoice3.171.exe" "https://raw.githubusercontent.com/LordLuceus/sr-english-localization/master/language_en.dat"
|
||||
export WINEARCH="win64" # Migrated to wine64 with WINETRICKS_FORCE=1
|
||||
export winVer="win8"
|
||||
install_wine_bottle fakejapanese
|
||||
# Add bcrypt DLL override required for Shadow Line to run
|
||||
cat > /tmp/bcrypt_override.reg << 'EOF'
|
||||
[HKEY_CURRENT_USER\Software\Wine\DllOverrides]
|
||||
"bcryptprimitives"="native,builtin"
|
||||
EOF
|
||||
wine regedit /tmp/bcrypt_override.reg
|
||||
rm /tmp/bcrypt_override.reg
|
||||
# shellcheck shell=bash disable=SC2154 # cache, game, and helper functions are set by audiogame-manager.
|
||||
|
||||
export game="Shadow Line"
|
||||
shadowLineGameId="shadow-line"
|
||||
shadowLinePath='c:\Program Files (x86)\GalaxyLaboratory\ShadowRine_FullVoice\play_sr.exe'
|
||||
|
||||
download "https://www.mm-galabo.com/sr/Download_files_srfv/shadowrine_fullvoice3.171.exe" \
|
||||
"https://raw.githubusercontent.com/LordLuceus/sr-english-localization/master/language_en.dat" \
|
||||
"${nvdaControllerClient32Dll}" \
|
||||
"${nvdaControllerClient64Dll}"
|
||||
|
||||
install_proton_bottle "$shadowLineGameId" fakejapanese
|
||||
shadowLineInstallDir="${WINEPREFIX}/drive_c/Program Files (x86)/GalaxyLaboratory/ShadowRine_FullVoice"
|
||||
|
||||
set_umu_reg_value "HKCU\\Software\\Wine\\DllOverrides" "bcryptprimitives" "native,builtin"
|
||||
set_umu_app_winver "play_sr.exe" "win8"
|
||||
|
||||
{
|
||||
echo "# Installing Shadow Line..."
|
||||
timeout 300 wine "${cache}/shadowrine_fullvoice3.171.exe" /sp- /VERYSILENT /SUPPRESSMSGBOXES 2>&1 || true
|
||||
timeout 300 umu-run "${cache}/shadowrine_fullvoice3.171.exe" /sp- /VERYSILENT /SUPPRESSMSGBOXES 2>&1 || true
|
||||
echo "# Installation complete"
|
||||
} | agm_progressbox "Installing Game" "Installing Shadow Line (this may take a few minutes)..."
|
||||
# Kill any auto-launched game processes (installer lacks skipifsilent flag)
|
||||
wineserver -k 2>/dev/null || true
|
||||
mv -v "${cache}/language_en.dat" "${WINEPREFIX}/drive_c/Program Files (x86)/GalaxyLaboratory/ShadowRine_FullVoice/SystemData/language_en.dat"
|
||||
add_launcher "c:\Program Files (x86)\GalaxyLaboratory\ShadowRine_FullVoice\play_sr.exe"
|
||||
echo "Please set the language to English when the game opens."
|
||||
echo "Go to options and press enter."
|
||||
echo "Press down arrow 5 times and press enter."
|
||||
echo "Press down arrow 1 time and press enter."
|
||||
echo "Press up arrow 2 times and press enter."
|
||||
echo "If everything worked as expected you should be back on the game menu and speech should work."
|
||||
alert
|
||||
} | agm_progressbox "Installing Game" "Installing Shadow Line with UMU/Proton (this may take a few minutes)..."
|
||||
|
||||
stop_umu_bottle
|
||||
|
||||
if [[ ! -f "${shadowLineInstallDir}/play_sr.exe" ]]; then
|
||||
agm_msgbox "Shadow Line" "Shadow Line" "Shadow Line did not install to the expected location: ${shadowLineInstallDir}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
install_crlf_file "${cache}/language_en.dat" "${shadowLineInstallDir}/SystemData/language_en.dat"
|
||||
|
||||
find "$shadowLineInstallDir" -type f -iname 'nvdaControllerClient32.dll' -exec cp -v "${cache}/nvdaControllerClient32.dll" "{}" \;
|
||||
find "$shadowLineInstallDir" -type f -iname 'nvdaControllerClient64.dll' -exec cp -v "${cache}/nvdaControllerClient64.dll" "{}" \;
|
||||
find "$shadowLineInstallDir" -type f -iname 'nvdaControllerClient.dll' -exec cp -v "${cache}/nvdaControllerClient32.dll" "{}" \;
|
||||
|
||||
add_umu_launcher "$shadowLineGameId" "$shadowLinePath"
|
||||
alert "Shadow Line" "Shadow Line" "Please set the language to English when the game opens.\nGo to options and press enter.\nPress down arrow 5 times and press enter.\nPress down arrow 1 time and press enter.\nPress up arrow 2 times and press enter.\nIf everything worked as expected you should be back on the game menu and speech should work."
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# shellcheck shell=bash disable=SC2154 # cache and WINEPREFIX are set by audiogame-manager
|
||||
download "http://www.danielzingaro.com/superdeekout_setup.exe" "http://www.danielzingaro.com/sd_full.exe"
|
||||
install_wine_bottle vb6run dx8vb
|
||||
wine "${cache}/superdeekout_setup.exe" &
|
||||
@@ -13,8 +14,7 @@ xdotool sleep 15 key --delay 250 alt+f 2> /dev/null
|
||||
xdotool sleep 3 key --delay 250 n 2> /dev/null
|
||||
wineserver -k
|
||||
install_with_progress 7z "Extracting game files..." x -y -o"$WINEPREFIX/drive_c/Program Files/Super Deekout" "${cache}/sd_full.exe"
|
||||
echo "Super Deekout needs some information before it will run:"
|
||||
alert
|
||||
alert "Super Deekout needs some information before it will run."
|
||||
read -erp "Please enter your first name: " fname
|
||||
read -erp "Please enter your last name: " lname
|
||||
read -erp "Please enter your email address: " email
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# shellcheck shell=bash disable=SC2154 # cache and WINEPREFIX are set by audiogame-manager
|
||||
get_installer "theyll-come-from-the-moon-windows.zip" "https://soundrascal.itch.io/theyll-come-from-the-moon"
|
||||
export WINEARCH=win64
|
||||
export winVer="win8"
|
||||
@@ -7,5 +8,4 @@ install_with_progress unzip "Extracting game files..." -d "$WINEPREFIX/drive_c/P
|
||||
winetricks -q usetakefocus=y
|
||||
winetricks -q usetakefocus=n
|
||||
add_launcher "c:\Program Files\tcftm\They'll Come from the Moon!.exe"
|
||||
echo "When the game launches, press the enter key to load the game which will begin to speak."
|
||||
alert
|
||||
alert "When the game launches, press the enter key to load the game which will begin to speak."
|
||||
|
||||
+2
-6
@@ -1,12 +1,8 @@
|
||||
# shellcheck shell=bash disable=SC2154 # cache and WINEPREFIX are set by audiogame-manager
|
||||
export WINEARCH="win64" # Migrated to wine64 with WINETRICKS_FORCE=1
|
||||
export winVer="win7"
|
||||
install_wine_bottle sapi vb6run dx8vb
|
||||
wine "${cache}/vipmud20016.exe" /silent
|
||||
mkdir -p "${HOME}/.local/wine/vip-mud/drive_c/users/${USER}/Documents/VIP Mud"
|
||||
add_launcher "c:\Program Files (x86)\VIPMud 2.0\vipmud2.exe"
|
||||
echo
|
||||
echo "When you first launch VIP Mud You will be presented with several inaccessible dialogs."
|
||||
echo "To bypass these dialogs, press alt+o, then press enter until speech starts."
|
||||
echo "To be sure that each new dialog has had time to complete, wait a second between each press of enter."
|
||||
echo "In each subsequent launch, you will need to hit enter a couple times before it starts speaking."
|
||||
alert
|
||||
alert "When you first launch VIP Mud You will be presented with several inaccessible dialogs.\nTo bypass these dialogs, press alt+o, then press enter until speech starts.\nTo be sure that each new dialog has had time to complete, wait a second between each press of enter.\nIn each subsequent launch, you will need to hit enter a couple times before it starts speaking."
|
||||
|
||||
+42
-14
@@ -469,23 +469,36 @@ game_removal() {
|
||||
# With shared bottles, always remove only the game files, never the entire bottle
|
||||
create_game_array "$selectedGame"
|
||||
if [[ ${#game[@]} -gt 0 ]]; then
|
||||
# Set up wine environment for this game
|
||||
# shellcheck source=.includes/bottle.sh
|
||||
source "${scriptDir}/.includes/bottle.sh"
|
||||
get_bottle "${game[0]}"
|
||||
process_launcher_flags
|
||||
if [[ "${game[0]}" == "umu" ]]; then
|
||||
get_umu_bottle "$umuGameId"
|
||||
else
|
||||
# Set up wine environment for this game
|
||||
# shellcheck source=.includes/bottle.sh
|
||||
source "${scriptDir}/.includes/bottle.sh"
|
||||
get_bottle "${game[0]}"
|
||||
fi
|
||||
|
||||
if ! agm_yesno "Confirm Removal" "Audio Game Removal" "Are you sure you want to remove \"${game[2]}\"?"; then
|
||||
agm_msgbox "Audio Game Removal" "" "Removal cancelled."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# kill any previous existing wineservers for this prefix in case they didn't shut down properly.
|
||||
wineserver -k
|
||||
# kill any previous existing servers for this prefix in case they didn't shut down properly.
|
||||
if [[ "${game[0]}" == "umu" ]]; then
|
||||
stop_umu_bottle
|
||||
else
|
||||
wineserver -k
|
||||
fi
|
||||
|
||||
# Remove only the game's installation directory
|
||||
if [[ -n "$winePath" ]]; then
|
||||
local gameDir
|
||||
gameDir="$(winepath "$winePath")"
|
||||
if [[ "${game[0]}" == "umu" ]]; then
|
||||
gameDir="$(umu_windows_path_to_unix "$winePath")"
|
||||
else
|
||||
gameDir="$(winepath "$winePath")"
|
||||
fi
|
||||
if [[ -d "$gameDir" ]]; then
|
||||
rm -rfv "$gameDir" | agm_progressbox "Removing Game" "Removing \"${game[2]}\" files..."
|
||||
else
|
||||
@@ -534,9 +547,16 @@ kill_game() {
|
||||
local wineExec="${game#*|}"
|
||||
wineExec="${wineExec%|*}"
|
||||
wineExec="${wineExec##*\\}"
|
||||
# kill the wine server.
|
||||
get_bottle "${game%|*}"
|
||||
wineserver -k
|
||||
create_game_array "$game"
|
||||
if [[ "${game[0]}" == "umu" ]]; then
|
||||
process_launcher_flags
|
||||
get_umu_bottle "$umuGameId"
|
||||
stop_umu_bottle
|
||||
else
|
||||
# kill the wine server.
|
||||
get_bottle "${game[0]}"
|
||||
wineserver -k
|
||||
fi
|
||||
agm_msgbox "Audio Game Killer" "" "The selected game has been stopped."
|
||||
fi
|
||||
exit 0
|
||||
@@ -790,14 +810,21 @@ game_launcher() {
|
||||
open_url "https://2mb.games/product/2mb-patron/"
|
||||
exit 0
|
||||
fi
|
||||
# Set default path/exec for custom launch handlers.
|
||||
winePath="${game[1]%\\*.exe}"
|
||||
wineExec="${game[1]##*\\}"
|
||||
process_launcher_flags
|
||||
if [[ "${game[0]}" == "umu" ]]; then
|
||||
echo "launching with umu"
|
||||
start_nvda2speechd
|
||||
run_umu_game "${game[1]}"
|
||||
exit 0
|
||||
fi
|
||||
get_bottle "${game[0]}"
|
||||
echo -n "launching "
|
||||
wine --version
|
||||
# kill any previous existing wineservers for this prefix in case they didn't shut down properly.
|
||||
wineserver -k
|
||||
# Set default path/exec for custom launch handlers.
|
||||
winePath="${game[1]%\\*.exe}"
|
||||
wineExec="${game[1]##*\\}"
|
||||
# launch the game
|
||||
if command -v qjoypad &> /dev/null ; then
|
||||
mkdir -p ~/.qjoypad3
|
||||
@@ -812,7 +839,6 @@ game_launcher() {
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
process_launcher_flags
|
||||
apply_executioners_rage_focus_workaround
|
||||
customLaunchHandled="false"
|
||||
custom_launch_parameters
|
||||
@@ -901,6 +927,8 @@ export ipfsGateway="${ipfsGateway:-https://ipfs.stormux.org}"
|
||||
# Source helper functions
|
||||
# shellcheck source=.includes/bottle.sh
|
||||
source "${scriptDir}/.includes/bottle.sh" # Also sourced in functions that need it
|
||||
# shellcheck source=.includes/proton.sh
|
||||
source "${scriptDir}/.includes/proton.sh"
|
||||
# shellcheck source=.includes/desktop.sh
|
||||
source "${scriptDir}/.includes/desktop.sh"
|
||||
# dialog-interface.sh already sourced earlier
|
||||
|
||||
@@ -0,0 +1,525 @@
|
||||
# UMU Proton Backend Implementation Plan
|
||||
|
||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** Add a reusable UMU/Proton backend and migrate Shadow Line to it with English localization and NVDA controller DLL replacement.
|
||||
|
||||
**Architecture:** Keep the existing Wine backend intact and add UMU as a new launcher backend value in `games.conf`. Put generic UMU behavior in a focused include file, keep Shadow Line-specific install work in `.install/Shadow Line.sh`, and route launch/removal/kill behavior through backend-aware branches.
|
||||
|
||||
**Tech Stack:** Bash, `umu-run`, Wine/Proton prefixes, existing AGM dialog/progress helpers, `shellcheck`.
|
||||
|
||||
---
|
||||
|
||||
## File Structure
|
||||
|
||||
- Create: `.includes/proton.sh`
|
||||
- Owns UMU dependency checks, prefix selection, UMU launch environment, Windows path conversion, UMU installer/launch helpers, and UMU launcher registration.
|
||||
- Create: `tests/umu_backend_tests.sh`
|
||||
- Self-contained shell tests with temporary HOME/config/cache paths and stubbed external commands.
|
||||
- Modify: `audiogame-manager.sh`
|
||||
- Source `.includes/proton.sh`, skip Wine-only DLL scanning for UMU prefixes, launch UMU entries through `run_umu_game`, and handle UMU kill/remove paths safely.
|
||||
- Modify: `.includes/checkup.sh`
|
||||
- Report `umu-run` as required for Proton-backed games and include `umu-launcher` in package output.
|
||||
- Modify: `.install/Shadow Line.sh`
|
||||
- Use `install_proton_bottle`, run installer via UMU, apply registry settings, copy English language file, replace NVDA controller DLLs, register with `add_umu_launcher`, and show first-run English instructions.
|
||||
|
||||
## Task 1: Add UMU Backend Tests
|
||||
|
||||
**Files:**
|
||||
- Create: `tests/umu_backend_tests.sh`
|
||||
|
||||
- [ ] **Step 1: Write failing shell tests**
|
||||
|
||||
Create `tests/umu_backend_tests.sh`:
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
repoRoot="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
testRoot="$(mktemp -d)"
|
||||
trap 'rm -rf "$testRoot"' EXIT
|
||||
|
||||
export HOME="${testRoot}/home"
|
||||
export XDG_DATA_HOME="${HOME}/.local/share"
|
||||
export XDG_CONFIG_HOME="${HOME}/.config"
|
||||
export XDG_CACHE_HOME="${HOME}/.cache"
|
||||
export DISPLAY=""
|
||||
export cache="${XDG_CACHE_HOME}/audiogame-manager"
|
||||
export configFile="${XDG_CONFIG_HOME}/storm-games/audiogame-manager/games.conf"
|
||||
export scriptDir="$repoRoot"
|
||||
mkdir -p "$cache" "${configFile%/*}" "${testRoot}/bin"
|
||||
touch "$configFile"
|
||||
|
||||
cat > "${testRoot}/bin/umu-run" <<'STUB'
|
||||
#!/usr/bin/env bash
|
||||
printf '%s|%s|%s|%s\n' "$WINEPREFIX" "$GAMEID" "${STORE:-}" "$*" >> "$UMU_STUB_LOG"
|
||||
if [[ "${1:-}" == "" ]]; then
|
||||
mkdir -p "$WINEPREFIX/drive_c"
|
||||
fi
|
||||
STUB
|
||||
chmod +x "${testRoot}/bin/umu-run"
|
||||
|
||||
cat > "${testRoot}/bin/wine" <<'STUB'
|
||||
#!/usr/bin/env bash
|
||||
if [[ "${1:-}" == "winepath" || "${1:-}" == "winepath.exe" ]]; then
|
||||
shift
|
||||
fi
|
||||
if [[ "${1:-}" == "-u" ]]; then
|
||||
input="$2"
|
||||
path="${input#c:\\}"
|
||||
path="${path//\\//}"
|
||||
printf '%s/drive_c/%s\n' "$WINEPREFIX" "$path"
|
||||
exit 0
|
||||
fi
|
||||
printf 'wine %s\n' "$*" >> "$WINE_STUB_LOG"
|
||||
STUB
|
||||
chmod +x "${testRoot}/bin/wine"
|
||||
|
||||
cat > "${testRoot}/bin/wineserver" <<'STUB'
|
||||
#!/usr/bin/env bash
|
||||
printf 'wineserver %s\n' "$*" >> "$WINE_STUB_LOG"
|
||||
STUB
|
||||
chmod +x "${testRoot}/bin/wineserver"
|
||||
|
||||
export PATH="${testRoot}/bin:$PATH"
|
||||
export UMU_STUB_LOG="${testRoot}/umu.log"
|
||||
export WINE_STUB_LOG="${testRoot}/wine.log"
|
||||
|
||||
# shellcheck source=.includes/proton.sh
|
||||
source "${repoRoot}/.includes/proton.sh"
|
||||
|
||||
assert_equals() {
|
||||
local expected="$1"
|
||||
local actual="$2"
|
||||
local message="$3"
|
||||
if [[ "$expected" != "$actual" ]]; then
|
||||
printf 'FAIL: %s\nexpected: %s\nactual: %s\n' "$message" "$expected" "$actual" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
assert_file_contains() {
|
||||
local file="$1"
|
||||
local pattern="$2"
|
||||
local message="$3"
|
||||
if ! grep -Fq "$pattern" "$file"; then
|
||||
printf 'FAIL: %s\nmissing pattern: %s\nfile contents:\n' "$message" "$pattern" >&2
|
||||
cat "$file" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
test_get_umu_bottle_sets_environment() {
|
||||
get_umu_bottle "shadow-line"
|
||||
assert_equals "${XDG_DATA_HOME}/audiogame-manager/protonBottles/shadow-line" "$WINEPREFIX" "WINEPREFIX points at AGM proton bottle"
|
||||
assert_equals "shadow-line" "$GAMEID" "GAMEID is exported"
|
||||
assert_equals "none" "$STORE" "STORE defaults to none"
|
||||
assert_equals ":0" "$DISPLAY" "DISPLAY defaults to :0"
|
||||
}
|
||||
|
||||
test_add_umu_launcher_records_backend_and_game_id() {
|
||||
get_umu_bottle "shadow-line"
|
||||
add_umu_launcher "shadow-line" 'c:\Program Files (x86)\GalaxyLaboratory\ShadowRine_FullVoice\play_sr.exe'
|
||||
assert_file_contains "$configFile" 'umu|c:\Program Files (x86)\GalaxyLaboratory\ShadowRine_FullVoice\play_sr.exe|Shadow Line|export umuGameId=shadow-line' "UMU launcher entry is recorded"
|
||||
}
|
||||
|
||||
test_run_umu_game_uses_converted_path() {
|
||||
get_umu_bottle "shadow-line"
|
||||
mkdir -p "${WINEPREFIX}/drive_c/Program Files (x86)/GalaxyLaboratory/ShadowRine_FullVoice"
|
||||
touch "${WINEPREFIX}/drive_c/Program Files (x86)/GalaxyLaboratory/ShadowRine_FullVoice/play_sr.exe"
|
||||
run_umu_game 'c:\Program Files (x86)\GalaxyLaboratory\ShadowRine_FullVoice\play_sr.exe'
|
||||
assert_file_contains "$UMU_STUB_LOG" "${WINEPREFIX}|shadow-line|none|${WINEPREFIX}/drive_c/Program Files (x86)/GalaxyLaboratory/ShadowRine_FullVoice/play_sr.exe" "UMU launches converted exe path"
|
||||
}
|
||||
|
||||
test_get_umu_bottle_sets_environment
|
||||
test_add_umu_launcher_records_backend_and_game_id
|
||||
test_run_umu_game_uses_converted_path
|
||||
printf 'UMU backend tests passed\n'
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Run tests and verify they fail because `.includes/proton.sh` is missing**
|
||||
|
||||
Run: `bash tests/umu_backend_tests.sh`
|
||||
|
||||
Expected: FAIL with a message that `.includes/proton.sh` cannot be sourced.
|
||||
|
||||
## Task 2: Implement Generic UMU Helpers
|
||||
|
||||
**Files:**
|
||||
- Create: `.includes/proton.sh`
|
||||
- Test: `tests/umu_backend_tests.sh`
|
||||
|
||||
- [ ] **Step 1: Implement `.includes/proton.sh`**
|
||||
|
||||
Create `.includes/proton.sh`:
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
# shellcheck disable=SC2034,SC2154 # sourced by audiogame-manager and installers with shared globals
|
||||
|
||||
require_umu() {
|
||||
if command -v umu-run &> /dev/null; then
|
||||
return 0
|
||||
fi
|
||||
local message="This game requires umu-launcher. Please install umu-launcher and try again."
|
||||
if declare -F agm_msgbox &> /dev/null; then
|
||||
agm_msgbox "Audio Game Manager" "Audio Game Manager" "$message"
|
||||
else
|
||||
echo "$message" >&2
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
get_umu_bottle() {
|
||||
local gameId="$1"
|
||||
if [[ -z "$gameId" ]]; then
|
||||
echo "get_umu_bottle requires a game id." >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
export umuGameId="$gameId"
|
||||
export WINEPREFIX="${XDG_DATA_HOME:-$HOME/.local/share}/audiogame-manager/protonBottles/${gameId}"
|
||||
export GAMEID="$gameId"
|
||||
export STORE="${umuStore:-none}"
|
||||
export DISPLAY="${DISPLAY:-:0}"
|
||||
export UMU_RUNTIME_UPDATE="${UMU_RUNTIME_UPDATE:-0}"
|
||||
mkdir -p "$WINEPREFIX"
|
||||
}
|
||||
|
||||
install_proton_bottle() {
|
||||
local gameId="$1"
|
||||
shift || true
|
||||
require_umu || return 1
|
||||
get_umu_bottle "$gameId" || return 1
|
||||
|
||||
if [[ ! -f "${WINEPREFIX}/system.reg" ]]; then
|
||||
umu-run ""
|
||||
fi
|
||||
|
||||
if [[ $# -gt 0 ]]; then
|
||||
umu-run winetricks "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
umu_windows_path_to_unix() {
|
||||
local windowsPath="$1"
|
||||
wine winepath -u "$windowsPath"
|
||||
}
|
||||
|
||||
run_umu_game() {
|
||||
local windowsPath="$1"
|
||||
local exePath=""
|
||||
require_umu || return 1
|
||||
if [[ -z "${umuGameId:-}" ]]; then
|
||||
echo "UMU game id is not set for ${game[2]:-selected game}." >&2
|
||||
return 1
|
||||
fi
|
||||
get_umu_bottle "$umuGameId" || return 1
|
||||
exePath="$(umu_windows_path_to_unix "$windowsPath")"
|
||||
if [[ ! -f "$exePath" ]]; then
|
||||
echo "UMU executable not found: $exePath" >&2
|
||||
return 1
|
||||
fi
|
||||
pushd "${exePath%/*}" > /dev/null || return 1
|
||||
umu-run "$exePath"
|
||||
popd > /dev/null || return 1
|
||||
}
|
||||
|
||||
add_umu_launcher() {
|
||||
local gameId="$1"
|
||||
local windowsPath="$2"
|
||||
shift 2
|
||||
local launchSettings="umu|${windowsPath}|${game}|export umuGameId=${gameId}"
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
launchSettings+="|$1"
|
||||
shift
|
||||
done
|
||||
|
||||
if ! grep -F -q -x "$launchSettings" "$configFile" 2> /dev/null; then
|
||||
echo "$launchSettings" >> "$configFile"
|
||||
sort -t '|' -k3,3f -o "$configFile" "$configFile"
|
||||
fi
|
||||
}
|
||||
|
||||
set_umu_reg_value() {
|
||||
local key="$1"
|
||||
local valueName="$2"
|
||||
local valueData="$3"
|
||||
wine reg add "$key" /v "$valueName" /t REG_SZ /d "$valueData" /f
|
||||
}
|
||||
|
||||
set_umu_app_winver() {
|
||||
local exeName="$1"
|
||||
local winVersion="$2"
|
||||
set_umu_reg_value "HKCU\\Software\\Wine\\AppDefaults\\${exeName}" "Version" "$winVersion"
|
||||
}
|
||||
|
||||
stop_umu_bottle() {
|
||||
if command -v wineserver &> /dev/null; then
|
||||
wineserver -k 2> /dev/null || true
|
||||
fi
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Run UMU backend tests and verify they pass**
|
||||
|
||||
Run: `bash tests/umu_backend_tests.sh`
|
||||
|
||||
Expected: PASS with `UMU backend tests passed`.
|
||||
|
||||
- [ ] **Step 3: Run shellcheck on new files**
|
||||
|
||||
Run: `shellcheck .includes/proton.sh tests/umu_backend_tests.sh`
|
||||
|
||||
Expected: no output and exit code 0.
|
||||
|
||||
## Task 3: Wire UMU Backend Into AGM Launch, Kill, and Removal
|
||||
|
||||
**Files:**
|
||||
- Modify: `audiogame-manager.sh`
|
||||
- Test: `tests/umu_backend_tests.sh`
|
||||
|
||||
- [ ] **Step 1: Source proton helpers**
|
||||
|
||||
In `audiogame-manager.sh`, after sourcing `.includes/bottle.sh`, add:
|
||||
|
||||
```bash
|
||||
# shellcheck source=.includes/proton.sh
|
||||
source "${scriptDir}/.includes/proton.sh"
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Make removal backend-aware**
|
||||
|
||||
In `remove_game`, after `create_game_array "$selectedGame"` and before Wine-only setup, branch on `game[0]`:
|
||||
|
||||
```bash
|
||||
if [[ "${game[0]}" == "umu" ]]; then
|
||||
process_launcher_flags
|
||||
get_umu_bottle "$umuGameId"
|
||||
else
|
||||
source "${scriptDir}/.includes/bottle.sh"
|
||||
get_bottle "${game[0]}"
|
||||
fi
|
||||
```
|
||||
|
||||
For directory conversion, replace the Wine-only `winepath` call with:
|
||||
|
||||
```bash
|
||||
if [[ "${game[0]}" == "umu" ]]; then
|
||||
gameDir="$(umu_windows_path_to_unix "$winePath")"
|
||||
else
|
||||
gameDir="$(winepath "$winePath")"
|
||||
fi
|
||||
```
|
||||
|
||||
For stopping processes, use:
|
||||
|
||||
```bash
|
||||
if [[ "${game[0]}" == "umu" ]]; then
|
||||
stop_umu_bottle
|
||||
else
|
||||
wineserver -k
|
||||
fi
|
||||
```
|
||||
|
||||
- [ ] **Step 3: Make kill backend-aware**
|
||||
|
||||
In `kill_game`, after `create_game_array` or parsing the selected line, ensure UMU entries process launcher flags and call `stop_umu_bottle`:
|
||||
|
||||
```bash
|
||||
if [[ "${game[0]}" == "umu" ]]; then
|
||||
process_launcher_flags
|
||||
get_umu_bottle "$umuGameId"
|
||||
stop_umu_bottle
|
||||
else
|
||||
get_bottle "${game%|*}"
|
||||
wineserver -k
|
||||
fi
|
||||
```
|
||||
|
||||
- [ ] **Step 4: Launch UMU entries through `run_umu_game`**
|
||||
|
||||
In `game_launcher`, after `process_launcher_flags` and before Wine-only qjoypad/path work is used, add:
|
||||
|
||||
```bash
|
||||
if [[ "${game[0]}" == "umu" ]]; then
|
||||
echo "launching with umu"
|
||||
start_nvda2speechd
|
||||
run_umu_game "${game[1]}"
|
||||
exit 0
|
||||
fi
|
||||
```
|
||||
|
||||
Keep Wine launch behavior unchanged for non-UMU entries.
|
||||
|
||||
- [ ] **Step 5: Run syntax checks**
|
||||
|
||||
Run: `bash -n audiogame-manager.sh`
|
||||
|
||||
Expected: no output and exit code 0.
|
||||
|
||||
- [ ] **Step 6: Run shellcheck on touched shell files**
|
||||
|
||||
Run: `shellcheck audiogame-manager.sh .includes/proton.sh tests/umu_backend_tests.sh`
|
||||
|
||||
Expected: no new actionable errors. Existing intentional warnings may be suppressed locally only if they are not real bugs.
|
||||
|
||||
## Task 4: Update Dependency Reporting
|
||||
|
||||
**Files:**
|
||||
- Modify: `.includes/checkup.sh`
|
||||
|
||||
- [ ] **Step 1: Add UMU check to `.includes/checkup.sh`**
|
||||
|
||||
After the Wine check, add:
|
||||
|
||||
```bash
|
||||
if command -v umu-run &> /dev/null; then
|
||||
[[ $# -eq 0 ]] && echo "umu-launcher is installed."
|
||||
else
|
||||
errorList+=("Warning: umu-launcher is not installed. Games that require Proton/UMU will not install or launch.")
|
||||
fi
|
||||
packageList+=("umu-launcher")
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Run syntax and shellcheck**
|
||||
|
||||
Run: `bash -n .includes/checkup.sh`
|
||||
|
||||
Expected: no output and exit code 0.
|
||||
|
||||
Run: `shellcheck .includes/checkup.sh`
|
||||
|
||||
Expected: no output and exit code 0, or only pre-existing intentional warnings.
|
||||
|
||||
## Task 5: Migrate Shadow Line Installer to UMU
|
||||
|
||||
**Files:**
|
||||
- Modify: `.install/Shadow Line.sh`
|
||||
|
||||
- [ ] **Step 1: Replace installer body**
|
||||
|
||||
Update `.install/Shadow Line.sh` to:
|
||||
|
||||
```bash
|
||||
# shellcheck shell=bash disable=SC2154 # cache, game, and helper functions are set by audiogame-manager
|
||||
download "https://www.mm-galabo.com/sr/Download_files_srfv/shadowrine_fullvoice3.171.exe" \
|
||||
"https://raw.githubusercontent.com/LordLuceus/sr-english-localization/master/language_en.dat" \
|
||||
"${nvdaControllerClient32Dll}" \
|
||||
"${nvdaControllerClient64Dll}"
|
||||
|
||||
export game="Shadow Line"
|
||||
shadowLineGameId="shadow-line"
|
||||
shadowLinePath='c:\Program Files (x86)\GalaxyLaboratory\ShadowRine_FullVoice\play_sr.exe'
|
||||
shadowLineInstallDir="${WINEPREFIX}/drive_c/Program Files (x86)/GalaxyLaboratory/ShadowRine_FullVoice"
|
||||
|
||||
install_proton_bottle "$shadowLineGameId" fakejapanese
|
||||
shadowLineInstallDir="${WINEPREFIX}/drive_c/Program Files (x86)/GalaxyLaboratory/ShadowRine_FullVoice"
|
||||
|
||||
set_umu_reg_value "HKCU\\Software\\Wine\\DllOverrides" "bcryptprimitives" "native,builtin"
|
||||
set_umu_app_winver "play_sr.exe" "win8"
|
||||
|
||||
{
|
||||
echo "# Installing Shadow Line..."
|
||||
timeout 300 umu-run "${cache}/shadowrine_fullvoice3.171.exe" /sp- /VERYSILENT /SUPPRESSMSGBOXES 2>&1 || true
|
||||
echo "# Installation complete"
|
||||
} | agm_progressbox "Installing Game" "Installing Shadow Line with UMU/Proton (this may take a few minutes)..."
|
||||
|
||||
stop_umu_bottle
|
||||
|
||||
if [[ ! -f "${shadowLineInstallDir}/play_sr.exe" ]]; then
|
||||
agm_msgbox "Shadow Line" "Shadow Line" "Shadow Line did not install to the expected location: ${shadowLineInstallDir}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
install -m 0644 "${cache}/language_en.dat" "${shadowLineInstallDir}/SystemData/language_en.dat"
|
||||
|
||||
find "$shadowLineInstallDir" -type f -iname 'nvdaControllerClient32.dll' -exec cp -v "${cache}/nvdaControllerClient32.dll" "{}" \;
|
||||
find "$shadowLineInstallDir" -type f -iname 'nvdaControllerClient64.dll' -exec cp -v "${cache}/nvdaControllerClient64.dll" "{}" \;
|
||||
find "$shadowLineInstallDir" -type f -iname 'nvdaControllerClient.dll' -exec cp -v "${cache}/nvdaControllerClient32.dll" "{}" \;
|
||||
|
||||
add_umu_launcher "$shadowLineGameId" "$shadowLinePath"
|
||||
alert "Shadow Line" "Shadow Line" "Please set the language to English when the game opens.\nGo to options and press enter.\nPress down arrow 5 times and press enter.\nPress down arrow 1 time and press enter.\nPress up arrow 2 times and press enter.\nIf everything worked as expected you should be back on the game menu and speech should work."
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Run syntax check**
|
||||
|
||||
Run: `bash -n ".install/Shadow Line.sh"`
|
||||
|
||||
Expected: no output and exit code 0.
|
||||
|
||||
- [ ] **Step 3: Run shellcheck on Shadow Line installer**
|
||||
|
||||
Run: `shellcheck ".install/Shadow Line.sh"`
|
||||
|
||||
Expected: no output and exit code 0, or only intentional sourced-global warnings suppressed by the file header.
|
||||
|
||||
## Task 6: End-to-End Verification
|
||||
|
||||
**Files:**
|
||||
- Modify as needed based on verification findings.
|
||||
|
||||
- [ ] **Step 1: Run focused unit tests**
|
||||
|
||||
Run: `bash tests/umu_backend_tests.sh`
|
||||
|
||||
Expected: PASS with `UMU backend tests passed`.
|
||||
|
||||
- [ ] **Step 2: Run syntax checks for all touched scripts**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
bash -n audiogame-manager.sh
|
||||
bash -n .includes/proton.sh
|
||||
bash -n .includes/checkup.sh
|
||||
bash -n ".install/Shadow Line.sh"
|
||||
bash -n tests/umu_backend_tests.sh
|
||||
```
|
||||
|
||||
Expected: all commands exit 0.
|
||||
|
||||
- [ ] **Step 3: Run shellcheck for all touched Bash files**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
shellcheck audiogame-manager.sh .includes/proton.sh .includes/checkup.sh ".install/Shadow Line.sh" tests/umu_backend_tests.sh
|
||||
```
|
||||
|
||||
Expected: no actionable warnings.
|
||||
|
||||
- [ ] **Step 4: Optional live install verification**
|
||||
|
||||
If the user approves running the live installer, run:
|
||||
|
||||
```bash
|
||||
DISPLAY=:0 ./audiogame-manager.sh -I "Shadow Line"
|
||||
```
|
||||
|
||||
Expected:
|
||||
|
||||
- Shadow Line installs into `${XDG_DATA_HOME:-$HOME/.local/share}/audiogame-manager/protonBottles/shadow-line`.
|
||||
- `games.conf` contains `umu|...|Shadow Line|export umuGameId=shadow-line`.
|
||||
- `play_sr.exe` exists under the Shadow Line Proton prefix.
|
||||
- `SystemData/language_en.dat` exists.
|
||||
- `user.reg` contains `bcryptprimitives` and `AppDefaults\\play_sr.exe` with `Version=win8`.
|
||||
|
||||
- [ ] **Step 5: Commit implementation**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
git add .includes/proton.sh .includes/checkup.sh ".install/Shadow Line.sh" audiogame-manager.sh tests/umu_backend_tests.sh docs/superpowers/plans/2026-05-05-umu-proton-backend.md
|
||||
git commit -m "Add UMU Proton backend for Shadow Line"
|
||||
```
|
||||
|
||||
Expected: commit succeeds and unrelated pre-existing dirty files remain unstaged.
|
||||
|
||||
## Self-Review
|
||||
|
||||
- Spec coverage: generic UMU helpers, Shadow Line migration, dependency checks, error handling, and verification are each covered by tasks.
|
||||
- Placeholder scan: no TODO/TBD placeholders remain.
|
||||
- Type consistency: helper names are consistent across tests, implementation, installer, and launcher tasks.
|
||||
@@ -0,0 +1,64 @@
|
||||
# UMU Proton Backend Design
|
||||
|
||||
## Goal
|
||||
|
||||
Add a general UMU/Proton backend to audiogame-manager so selected games can install and launch through `umu-run` with AGM-managed Proton prefixes. Shadow Line is the first supported game and should be installable, launchable, translated to English, and speech-capable without changing the existing Wine backend for other games.
|
||||
|
||||
## Scope
|
||||
|
||||
This change introduces generic UMU helpers and wires Shadow Line to use them. It does not migrate existing Wine games, add proton-voices, or reimplement `umu-launcher`. AGM depends on `umu-run` for Proton/runtime management because UMU handles Proton selection, Steam Runtime setup, prefix creation, protonfixes, and Proton winetricks routing.
|
||||
|
||||
## Architecture
|
||||
|
||||
Launcher entries gain a new backend value in the first `games.conf` field:
|
||||
|
||||
```text
|
||||
umu|c:\Program Files (x86)\GalaxyLaboratory\ShadowRine_FullVoice\play_sr.exe|Shadow Line|...
|
||||
```
|
||||
|
||||
The existing Wine values (`win64`, `win32`) continue to behave as they do now. When the backend is `umu`, launch setup uses a dedicated Proton prefix under:
|
||||
|
||||
```text
|
||||
${XDG_DATA_HOME:-$HOME/.local/share}/audiogame-manager/protonBottles/<game-id>
|
||||
```
|
||||
|
||||
The game id is supplied by the installer and stored in launcher flags, for example `export umuGameId=shadow-line`. Helpers will centralize backend behavior:
|
||||
|
||||
- `install_proton_bottle <game-id> [winetricks verbs...]`: create and select a UMU prefix, initialize it with `umu-run ""`, and install optional Proton winetricks verbs with `umu-run winetricks`.
|
||||
- `get_umu_bottle <game-id>`: export `WINEPREFIX`, `GAMEID`, `STORE`, and `DISPLAY`.
|
||||
- `run_umu_game <windows-path>`: convert the Windows path to a Unix executable path in the UMU prefix and run it through `umu-run`.
|
||||
- `add_umu_launcher <game-id> <windows-path> [flags...]`: append a `umu|...` launcher line.
|
||||
|
||||
## Shadow Line
|
||||
|
||||
Shadow Line uses the generic UMU backend with `umuGameId=shadow-line`. Its installer will:
|
||||
|
||||
1. Require `umu-run`.
|
||||
2. Download `shadowrine_fullvoice3.171.exe` and `language_en.dat`.
|
||||
3. Create/select the Shadow Line UMU prefix.
|
||||
4. Apply `bcryptprimitives=native,builtin`.
|
||||
5. Apply per-app `win8` for `play_sr.exe`.
|
||||
6. Run the installer silently with UMU.
|
||||
7. Stop any leftover Wine/Proton processes for the prefix.
|
||||
8. Copy `language_en.dat` into `SystemData`.
|
||||
9. Copy AGM's `nvdaControllerClient32.dll` and/or `nvdaControllerClient64.dll` over any matching game DLLs found in the Shadow Line install.
|
||||
10. Register the UMU launcher and show the first-run instructions for switching the game language to English.
|
||||
|
||||
Clipboard translation will not be used for Shadow Line in this implementation.
|
||||
|
||||
## Dependency Checks
|
||||
|
||||
`check_requirements` remains focused on core AGM dependencies, but UMU installers call a targeted `require_umu` helper so the error is clear at install time. The `-c` checkup report will also list `umu-run`: missing UMU is reported as required for Proton-backed games, not as a blocker for every Wine game.
|
||||
|
||||
## Error Handling
|
||||
|
||||
UMU helper functions fail fast with clear messages when `umu-run` is missing, prefix initialization fails, the installer does not produce the expected executable, or the translation file cannot be copied. Shadow Line should not be added to `games.conf` unless the expected executable exists.
|
||||
|
||||
## Verification
|
||||
|
||||
Verification will include:
|
||||
|
||||
- `bash -n` on changed shell scripts.
|
||||
- `shellcheck` on changed Bash files.
|
||||
- A focused install-path dry run where possible without launching the interactive game.
|
||||
- Confirmation that Shadow Line creates a `umu|...|Shadow Line` launcher entry and that the UMU prefix contains `play_sr.exe`, `language_en.dat`, registry settings, and replacement NVDA DLLs when matching DLLs exist.
|
||||
+112
@@ -0,0 +1,112 @@
|
||||
#!/usr/bin/env bash
|
||||
# shellcheck disable=SC1091,SC2034,SC2154
|
||||
|
||||
export game="Magic: The Gathering Arena"
|
||||
export WINEARCH=win64
|
||||
export winVer="win10"
|
||||
export DIALOGOPTS='--no-lines --visit-items'
|
||||
export ipfsGateway="${ipfsGateway:-https://ipfs.stormux.org}"
|
||||
|
||||
cache="${XDG_CACHE_HOME:-$HOME/.cache}/audiogame-manager"
|
||||
winetricksPath="${XDG_DATA_HOME:-$HOME/.local/share}/audiogame-manager"
|
||||
mkdir -p "$cache" "$winetricksPath"
|
||||
|
||||
if [[ -z "$DISPLAY" ]]; then
|
||||
dialogType="dialog"
|
||||
export DISPLAY=":0"
|
||||
elif command -v yad &> /dev/null; then
|
||||
dialogType="yad"
|
||||
else
|
||||
dialogType="dialog"
|
||||
fi
|
||||
|
||||
source "${0%/*}/../.includes/dialog-interface.sh"
|
||||
source "${0%/*}/../.includes/functions.sh"
|
||||
source "${0%/*}/../.includes/bottle.sh"
|
||||
|
||||
export nvdaControllerClient64Dll="${ipfs[nvdaControllerClient64]}"
|
||||
|
||||
mtgaVersionUrl="https://mtgarena.downloads.wizards.com/Live/Windows32/version"
|
||||
accessibleArenaDllUrl="https://github.com/JeanStiletto/AccessibleArena/releases/latest/download/AccessibleArena.dll"
|
||||
melonLoaderZipUrl="https://github.com/LavaGang/MelonLoader/releases/latest/download/MelonLoader.x64.zip"
|
||||
tolkDllUrl="https://stormgames.wolfe.casa/downloads/Tolk.dll"
|
||||
|
||||
get_mtga_installer_url() {
|
||||
local versionJson=""
|
||||
local installerUrl=""
|
||||
|
||||
if ! versionJson="$(curl -fsSL "$mtgaVersionUrl")"; then
|
||||
alert "Magic: The Gathering Arena" "Magic: The Gathering Arena" "Could not fetch the current MTG Arena installer URL."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
installerUrl="$(sed -n 's/.*"CurrentInstallerURL"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' <<< "$versionJson" | head -n1)"
|
||||
if [[ -z "$installerUrl" ]]; then
|
||||
alert "Magic: The Gathering Arena" "Magic: The Gathering Arena" "Could not parse the current MTG Arena installer URL."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
printf '%s\n' "$installerUrl"
|
||||
}
|
||||
|
||||
download_mtga_installer() {
|
||||
local installerUrl="$1"
|
||||
local installerFile="${installerUrl##*/}"
|
||||
installerFile="${installerFile%%\?*}"
|
||||
[[ -n "$installerFile" ]] || installerFile="MTGAInstaller.msi"
|
||||
|
||||
rm -f "${cache}/${installerFile}" 2> /dev/null
|
||||
if ! curl -L4 -C - --retry 10 --output "${cache}/${installerFile}" "$installerUrl" 2>&1 | agm_progressbox "Magic: The Gathering Arena Update" "Downloading MTG Arena update..."; then
|
||||
alert "Magic: The Gathering Arena" "Magic: The Gathering Arena" "Could not download the MTG Arena update."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mtgaInstallerPath="${cache}/${installerFile}"
|
||||
}
|
||||
|
||||
configure_accessible_arena_loader() {
|
||||
local mtgaRoot="$1"
|
||||
local userDataPath="${mtgaRoot}/UserData"
|
||||
local loaderConfig="${userDataPath}/Loader.cfg"
|
||||
|
||||
mkdir -p "$userDataPath"
|
||||
if [[ -f "$loaderConfig" ]]; then
|
||||
if grep -Fq "hide_console = false" "$loaderConfig"; then
|
||||
sed -i 's/hide_console = false/hide_console = true/g' "$loaderConfig"
|
||||
elif ! grep -Fq "hide_console" "$loaderConfig"; then
|
||||
printf '\n[console]\nhide_console = true\n' >> "$loaderConfig"
|
||||
fi
|
||||
else
|
||||
printf '[console]\nhide_console = true\n' > "$loaderConfig"
|
||||
fi
|
||||
}
|
||||
|
||||
install_accessible_arena_support() {
|
||||
local mtgaRoot="$1"
|
||||
|
||||
download "$accessibleArenaDllUrl" "$melonLoaderZipUrl" "$tolkDllUrl" "$nvdaControllerClient64Dll"
|
||||
|
||||
install_with_progress unzip "Reinstalling MelonLoader..." -d "$mtgaRoot" "${cache}/MelonLoader.x64.zip"
|
||||
mkdir -p "${mtgaRoot}/Mods"
|
||||
install_with_progress cp "Installing Accessible Arena..." "${cache}/AccessibleArena.dll" "${mtgaRoot}/Mods/AccessibleArena.dll"
|
||||
install_with_progress cp "Installing screen reader support DLLs..." "${cache}/Tolk.dll" "${cache}/nvdaControllerClient64.dll" "$mtgaRoot"
|
||||
configure_accessible_arena_loader "$mtgaRoot"
|
||||
}
|
||||
|
||||
check_requirements || exit 1
|
||||
install_wine_bottle dxvk
|
||||
winetricks -q $winVer
|
||||
|
||||
mtgaRoot="${WINEPREFIX}/drive_c/Program Files (x86)/Wizards of the Coast/MTGA"
|
||||
mtgaInstallerUrl="$(get_mtga_installer_url)"
|
||||
download_mtga_installer "$mtgaInstallerUrl"
|
||||
|
||||
wine msiexec /i "$mtgaInstallerPath" /q
|
||||
|
||||
if [[ ! -f "${mtgaRoot}/MTGA.exe" ]]; then
|
||||
alert "Magic: The Gathering Arena" "Magic: The Gathering Arena" "MTG Arena was not found at the expected location: ${mtgaRoot}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
install_accessible_arena_support "$mtgaRoot"
|
||||
agm_msgbox "Magic: The Gathering Arena Update" "Magic: The Gathering Arena Update" "Magic: The Gathering Arena and Accessible Arena have been updated."
|
||||
@@ -0,0 +1,120 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
repoRoot="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
testRoot="$(mktemp -d)"
|
||||
trap 'rm -rf "$testRoot"' EXIT
|
||||
|
||||
export HOME="${testRoot}/home"
|
||||
export XDG_DATA_HOME="${HOME}/.local/share"
|
||||
export XDG_CONFIG_HOME="${HOME}/.config"
|
||||
export XDG_CACHE_HOME="${HOME}/.cache"
|
||||
export DISPLAY=""
|
||||
export cache="${XDG_CACHE_HOME}/audiogame-manager"
|
||||
export configFile="${XDG_CONFIG_HOME}/storm-games/audiogame-manager/games.conf"
|
||||
export game="Shadow Line"
|
||||
export scriptDir="$repoRoot"
|
||||
mkdir -p "$cache" "${configFile%/*}" "${testRoot}/bin"
|
||||
touch "$configFile"
|
||||
|
||||
cat > "${testRoot}/bin/umu-run" <<'STUB'
|
||||
#!/usr/bin/env bash
|
||||
printf '%s|%s|%s|%s\n' "$WINEPREFIX" "$GAMEID" "${STORE:-}" "$*" >> "$UMU_STUB_LOG"
|
||||
if [[ "${1:-}" == "" ]]; then
|
||||
mkdir -p "$WINEPREFIX/drive_c"
|
||||
fi
|
||||
STUB
|
||||
chmod +x "${testRoot}/bin/umu-run"
|
||||
|
||||
cat > "${testRoot}/bin/wine" <<'STUB'
|
||||
#!/usr/bin/env bash
|
||||
if [[ "${1:-}" == "winepath" || "${1:-}" == "winepath.exe" ]]; then
|
||||
shift
|
||||
fi
|
||||
if [[ "${1:-}" == "-u" ]]; then
|
||||
input="$2"
|
||||
path="${input#c:\\}"
|
||||
path="${path//\\//}"
|
||||
printf '%s/drive_c/%s\n' "$WINEPREFIX" "$path"
|
||||
exit 0
|
||||
fi
|
||||
printf 'wine %s\n' "$*" >> "$WINE_STUB_LOG"
|
||||
STUB
|
||||
chmod +x "${testRoot}/bin/wine"
|
||||
|
||||
cat > "${testRoot}/bin/wineserver" <<'STUB'
|
||||
#!/usr/bin/env bash
|
||||
printf 'wineserver %s\n' "$*" >> "$WINE_STUB_LOG"
|
||||
STUB
|
||||
chmod +x "${testRoot}/bin/wineserver"
|
||||
|
||||
export PATH="${testRoot}/bin:$PATH"
|
||||
export UMU_STUB_LOG="${testRoot}/umu.log"
|
||||
export WINE_STUB_LOG="${testRoot}/wine.log"
|
||||
|
||||
# shellcheck source=.includes/proton.sh
|
||||
source "${repoRoot}/.includes/proton.sh"
|
||||
|
||||
assert_equals() {
|
||||
local expected="$1"
|
||||
local actual="$2"
|
||||
local message="$3"
|
||||
if [[ "$expected" != "$actual" ]]; then
|
||||
printf 'FAIL: %s\nexpected: %s\nactual: %s\n' "$message" "$expected" "$actual" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
assert_file_contains() {
|
||||
local file="$1"
|
||||
local pattern="$2"
|
||||
local message="$3"
|
||||
if ! grep -Fq "$pattern" "$file"; then
|
||||
printf 'FAIL: %s\nmissing pattern: %s\nfile contents:\n' "$message" "$pattern" >&2
|
||||
cat "$file" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
test_get_umu_bottle_sets_environment() {
|
||||
get_umu_bottle "shadow-line"
|
||||
assert_equals "${XDG_DATA_HOME}/audiogame-manager/protonBottles/shadow-line" "$WINEPREFIX" "WINEPREFIX points at AGM proton bottle"
|
||||
assert_equals "shadow-line" "$GAMEID" "GAMEID is exported"
|
||||
assert_equals "none" "$STORE" "STORE defaults to none"
|
||||
assert_equals ":0" "$DISPLAY" "DISPLAY defaults to :0"
|
||||
}
|
||||
|
||||
test_add_umu_launcher_records_backend_and_game_id() {
|
||||
get_umu_bottle "shadow-line"
|
||||
add_umu_launcher "shadow-line" 'c:\Program Files (x86)\GalaxyLaboratory\ShadowRine_FullVoice\play_sr.exe'
|
||||
assert_file_contains "$configFile" 'umu|c:\Program Files (x86)\GalaxyLaboratory\ShadowRine_FullVoice\play_sr.exe|Shadow Line|export umuGameId=shadow-line' "UMU launcher entry is recorded"
|
||||
}
|
||||
|
||||
test_run_umu_game_uses_converted_path() {
|
||||
get_umu_bottle "shadow-line"
|
||||
mkdir -p "${WINEPREFIX}/drive_c/Program Files (x86)/GalaxyLaboratory/ShadowRine_FullVoice"
|
||||
touch "${WINEPREFIX}/drive_c/Program Files (x86)/GalaxyLaboratory/ShadowRine_FullVoice/play_sr.exe"
|
||||
run_umu_game 'c:\Program Files (x86)\GalaxyLaboratory\ShadowRine_FullVoice\play_sr.exe'
|
||||
assert_file_contains "$UMU_STUB_LOG" "${WINEPREFIX}|shadow-line|none|${WINEPREFIX}/drive_c/Program Files (x86)/GalaxyLaboratory/ShadowRine_FullVoice/play_sr.exe" "UMU launches converted exe path"
|
||||
}
|
||||
|
||||
test_install_crlf_file_normalizes_line_endings() {
|
||||
local sourceFile="${testRoot}/language_en.dat"
|
||||
local destFile="${testRoot}/installed/language_en.dat"
|
||||
local expectedFile="${testRoot}/expected-language_en.dat"
|
||||
printf 'line one\nline two\n' > "$sourceFile"
|
||||
printf 'line one\r\nline two\r\n' > "$expectedFile"
|
||||
|
||||
install_crlf_file "$sourceFile" "$destFile"
|
||||
|
||||
if ! cmp -s "$expectedFile" "$destFile"; then
|
||||
printf 'FAIL: Translation file is installed with CRLF line endings\n' >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
test_get_umu_bottle_sets_environment
|
||||
test_add_umu_launcher_records_backend_and_game_id
|
||||
test_run_umu_game_uses_converted_path
|
||||
test_install_crlf_file_normalizes_line_endings
|
||||
printf 'UMU backend tests passed\n'
|
||||
Reference in New Issue
Block a user