Files
audiogame-manager/audiogame-manager.sh
Hunter Jozwiak 825d74460b Fix things so that the global version of Wine isn't trampled over.
The specific version of wine can be set in the registry for each
app. Also, add fakejapanese to the Shadow Line installation, though it
is still shitting the bed.
2025-12-08 23:32:51 -05:00

710 lines
28 KiB
Bash
Executable File

#!/usr/bin/env bash
# Get script directory for relative paths
scriptDir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# Dialog accessibility
export DIALOGOPTS='--no-lines --visit-items'
# Wine32 version for SAPI compatibility
wineThirtyTwoVersion="9.0"
# Check and manage wine32 installation
check_wine32() {
local wine32Dir="${XDG_DATA_HOME:-$HOME/.local/share}/audiogame-manager/wine32"
local versionFile="$wine32Dir/VERSION"
local currentVersion=""
# Check current installed version
[[ -f "$versionFile" ]] && currentVersion=$(cat "$versionFile")
# If version mismatch or missing, install/update
if [[ "$currentVersion" != "$wineThirtyTwoVersion" ]]; then
# Remove old installation
rm -rf "$wine32Dir" 2>/dev/null
mkdir -p "$wine32Dir"
# Download wine32 using existing download function
local wineFile="PlayOnLinux-wine-${wineThirtyTwoVersion}-upstream-linux-x86.tar.gz"
local wineUrl="https://www.playonlinux.com/wine/binaries/phoenicis/upstream-linux-x86/${wineFile}"
# Use existing download function which handles progress
download "$wineUrl"
# Extract with progress feedback
{
echo "# Extracting Wine32 version $wineThirtyTwoVersion..."
if tar xf "${cache}/${wineFile}" -C "$wine32Dir" --strip-components=1; then
echo "$wineThirtyTwoVersion" > "$versionFile"
echo "# Wine32 setup complete."
else
echo "# Failed to extract wine32. SAPI games may not work properly."
rm -rf "$wine32Dir"
fi
} | agm_progressbox "Wine32 Setup" "Extracting Wine32 for SAPI compatibility..."
fi
# Export wine32 path for bottle creation
if [[ -f "$wine32Dir/bin/wine" ]]; then
export wine32="$wine32Dir/bin/wine"
export wine32server="$wine32Dir/bin/wineserver"
fi
}
# Ensure wine64 bottle exists with all dependencies (wine32 no longer needed!)
ensure_wine_bottles() {
local wine64Bottle="$HOME/.local/wine64"
# Create wine64 bottle if missing - now includes SAPI support via WINETRICKS_FORCE=1
if [[ ! -d "$wine64Bottle" ]] || [[ ! -f "$wine64Bottle/system.reg" ]]; then
{
echo "# Creating wine64 bottle for modern games..."
# Set up environment for wine64
export WINEPREFIX="$wine64Bottle"
export WINE="wine"
export WINESERVER="wineserver"
unset WINEARCH
# Initialize wine64 bottle
echo "# Initializing wine64 environment..."
DISPLAY="" wine wineboot -u
# Install mono and gecko
echo "# Installing .NET Framework..."
monoPath="$(find /usr/share/wine/ -maxdepth 1 -type d -name mono 2> /dev/null)"
if [[ -z "$monoPath" ]]; then
download 'http://dl.winehq.org/wine/wine-mono/6.0.0/wine-mono-6.0.0-x86.msi'
monoPath="${cache}/wine-mono-6.0.0-x86.msi"
fi
wine msiexec /i z:"$monoPath" /quiet
echo "# Installing web browser support..."
geckoPath="$(find /usr/share/wine/ -maxdepth 1 -type d -name "gecko" 2> /dev/null)"
if [[ -z "$geckoPath" ]]; then
download 'http://dl.winehq.org/wine/wine-gecko/2.40/wine_gecko-2.40-x86.msi'
geckoPath="${cache}/wine_gecko-2.40-x86.msi"
fi
wine msiexec /i z:"$geckoPath" /quiet
# Install common dependencies for modern games
echo "# Installing common dependencies..."
winetricks -q isolate_home corefonts vcrun2019 win10
# Install Speech SDK for SAPI compatibility (experimental - requires WINETRICKS_FORCE=1)
echo "# Installing Speech SDK for wine64 SAPI support..."
env WINE="$WINE" WINESERVER="$WINESERVER" DISPLAY="${DISPLAY:-:0}" WINETRICKS_FORCE=1 winetricks -q speechsdk
# Restore win10 after speechsdk (speechsdk sets winxp)
winetricks -q win10
# Initialize SAPI and set Microsoft Mike as default voice
echo "# Setting Microsoft Mike as default voice..."
mkdir -p "${WINEPREFIX}/drive_c/windows/temp"
cat << "EOF" > "${WINEPREFIX}/drive_c/windows/temp/init_sapi.vbs"
dim speechobject
set speechobject=createobject("sapi.spvoice")
speechobject.speak ""
EOF
wine cscript "c:\\windows\\temp\\init_sapi.vbs"
wine reg add "HKCU\\SOFTWARE\\Microsoft\\Speech\\Voices" /v "DefaultTokenId" /t REG_SZ /d "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Speech\\Voices\\Tokens\\MSMike" /f
wine reg add "HKCU\\SOFTWARE\\Microsoft\\Speech\\Voices" /v "DefaultTTSRate" /t REG_DWORD /d "7" /f
echo "Set Microsoft Mike as default voice for wine64"
# Setup nvda2speechd for accessibility
echo "# Setting up accessibility support..."
download "${nvda2speechdBinary}"
if [[ ! -f "${XDG_DATA_HOME:-$HOME/.local/share}/audiogame-manager/nvda2speechd" ]]; then
cp "${cache}/nvda2speechd" "${XDG_DATA_HOME:-$HOME/.local/share}/audiogame-manager/nvda2speechd"
chmod +x "${XDG_DATA_HOME:-$HOME/.local/share}/audiogame-manager/nvda2speechd"
fi
echo "# Wine64 bottle creation complete."
} | agm_progressbox "Wine Bottle Setup" "Creating unified wine64 bottle with SAPI support (this may take several minutes)..."
fi
}
# Install games
game_installer() {
export LANG="en_US.UTF-8"
# Get list of installed games from config file
mapfile -t installedGames < <(sed -e '/^$/d' -e '/^[[:space:]]*#/d' "${configFile}" 2> /dev/null | cut -d '|' -f3)
# Create the menu of available games by reading from .install directory
declare -a menuList
# Get all .sh files from .install directory, excluding those starting with # as first line.
mapfile -t sortedGames < <(for f in "${scriptDir}/.install/"*.sh; do
# Skip if first line starts with #
[[ $(head -n1 "$f") == "#"* ]] && continue
echo "${f##*/%.sh}"
done | sort)
for i in "${sortedGames[@]}"; do
local menuItem="${i%.sh}"
menuItem="${menuItem##*/}"
# Check if game is already installed
for j in "${installedGames[@]}"; do
if [[ "$j" == "$menuItem" ]]; then
unset menuItem
break
fi
done
# Add to menu if not installed
if [[ -n "$menuItem" ]]; then
menuList+=("$menuItem" "$menuItem")
fi
done
# If all games are installed, exit
if [[ ${#menuList[@]} -eq 0 ]]; then
agm_msgbox "Audio Game Installer" "" "All games are already installed."
exit 0
fi
menuList+=("Donate" "Donate")
menuList+=("Become a Patron" "Become a Patron")
# Show game selection dialog
game="$(agm_menu "Audio Game Installer" "Audio Game Installer" "Please select a game to install" "${menuList[@]}")"
[[ $? -ne 0 ]] && exit 0
# Handle selection
if [[ -n "$game" ]]; then
case "$game" in
"Donate")
open_url "https://ko-fi.com/stormux"
exit 0
;;
"Become a Patron")
open_url "https://patreon.com/stormux"
exit 0
;;
*)
# Convert game name to filename format
local installScript="${scriptDir}/.install/${game}.sh"
# Check if install script exists
if [[ -f "$installScript" ]]; then
# Source and execute the install script
source "$installScript"
# Show success message
agm_msgbox "Installation Complete" "Audio Game Installer" "Game \"${game}\" has been successfully installed."
else
agm_msgbox "Audio Game Installer" "Audio Game Installer" "Installation script not found for ${game}"
exit 1
fi
;;
esac
fi
}
# remove games
game_removal() {
source "${scriptDir}/.includes/bottle.sh"
# Modern wine is unified - no architecture-specific wine executables needed
mapfile -t lines < <(sed -e '/^$/d' -e '/^[[:space:]]*#/d' "${configFile}" 2> /dev/null)
if [[ ${#lines} -eq 0 ]]; then
agm_msgbox "Audio Game Removal" "" "No games found."
exit 0
fi
# Create the menu of installed games
declare -a menuList
for i in "${lines[@]}" ; do
IFS='|' read -ra gameInfo <<< "$i"
menuList+=("${gameInfo[0]}|${gameInfo[1]}" "${gameInfo[2]}")
done
menuList+=("Donate" "Donate")
menuList+=("Become a Patron" "Become a Patron")
local game
game="$(agm_menu "Audio Game Removal" "Audio Game Removal" "Please select a game to delete" "${menuList[@]}")"
if [[ ${#game} -gt 0 ]]; then
if [[ "$game" == "Donate" ]]; then
open_url "https://ko-fi.com/stormux"
exit 0
fi
if [[ "$game" == "Become a Patron" ]]; then
open_url "https://2mb.games/product/2mb-patron/"
exit 0
fi
# Parse game info before create_game_array overwrites $game
local selectedGame="$game"
local winePath="${game#*|}"
export winePath="${winePath%\\*.exe}"
local wineExec="${game#*|}"
wineExec="${wineExec%|*}"
wineExec="${wineExec##*\\}"
# 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
source "${scriptDir}/.includes/bottle.sh"
get_bottle "${game[0]}"
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
# Remove only the game's installation directory
if [[ -n "$winePath" ]]; then
local gameDir="$(winepath "$winePath")"
if [[ -d "$gameDir" ]]; then
rm -rfv "$gameDir" | agm_progressbox "Removing Game" "Removing \"${game[2]}\" files..."
else
agm_msgbox "Game Removal" "" "Game directory not found, skipping file removal."
fi
fi
fi
# remove the launcher using the original selected game info
gawk -i inplace -vLine="${selectedGame//\\/\\\\}" '!index($0,Line)' "$configFile"
agm_msgbox "Game Removal" "" "\"${game[2]}\" has been successfully removed."
fi
exit 0
}
# kill games that are stuck
kill_game() {
source "${scriptDir}/.includes/bottle.sh"
# Modern wine is unified - no architecture-specific wine executables needed
mapfile -t lines < <(sed '/^$/d' "${configFile}" 2> /dev/null)
if [[ ${#lines} -eq 0 ]]; then
agm_msgbox "Audio Game Killer" "" "No games found."
exit 0
fi
# Create the menu of installed games
declare -a menuList
for i in "${lines[@]}" ; do
IFS='|' read -ra gameInfo <<< "$i"
menuList+=("${gameInfo[0]}|${gameInfo[1]}" "${gameInfo[2]}")
done
menuList+=("Donate" "Donate")
menuList+=("Become a Patron" "Become a Patron")
local game="$(agm_menu "Audio Game Killer" "Audio Game Killer" "Please select a game to force stop" "${menuList[@]}")"
if [[ ${#game} -gt 0 ]]; then
if [[ "$game" == "Donate" ]]; then
open_url "https://ko-fi.com/stormux"
exit 0
fi
if [[ "$game" == "Become a Patron" ]]; then
open_url "https://2mb.games/product/2mb-patron/"
exit 0
fi
local winePath="${game#*|}"
winePath="${winePath%\\*.exe}"
local wineExec="${game#*|}"
wineExec="${wineExec%|*}"
wineExec="${wineExec##*\\}"
# kill the wine server.
get_bottle "${game%|*}"
wineserver -k
agm_msgbox "Audio Game Killer" "" "The selected game has been stopped."
fi
exit 0
}
# for games that require custom scripts before launch or custom launch parameters
custom_launch_parameters() {
if [[ "${game[2]}" == "Dragon Pong" ]]; then
"${scriptDir}/speech/speak_window_title.sh" DragonPong.exe &
pushd "$(winepath "$winePath")"
wine "$wineExec"
popd
exit 0
fi
if [[ "${game[2]}" == "Dreamland" ]]; then
"$WINE" "${game[1]}" &> /dev/null &
exit 0
fi
# executioner's-rage: DLL replacement now handled by update_nvda_dlls()
if [[ "${game[2]}" == "Laser Breakout" ]]; then
"${scriptDir}/speech/speak_window_title.sh" play.exe &
fi
if [[ "${game[2]}" == "Bokurano Daibouken 2" ]]; then
find "${WINEPREFIX}/drive_c/nyanchangame/bk2" -type f -name 'nvdaControllerClient.dll' -exec rm -v "{}" \;
"${scriptDir}/speech/clipboard_translator.sh" "play.exe" bokurano-daibouken2 &
fi
if [[ "${game[2]}" == "Bokurano Daibouken" ]]; then
find "${WINEPREFIX}/drive_c/nyanchangame/bk" -type f -name 'nvdaControllerClient.dll' -exec rm -v "{}" \;
"${scriptDir}/speech/clipboard_translator.sh" "play.exe" bokurano-daibouken &
fi
if [[ "${game[2]}" == "Bokurano Daibouken 3" ]]; then
dictPath="$(winepath "${winePath}")"
if [[ -r "${cache}/bk3-dict.dat" ]] && [[ ! -d "${dictPath}/dict" ]]; then
cp "${cache}/bk3-dict.dat" "${dictPath}/dict.dat"
fi
# DLL replacement now handled by update_nvda_dlls()
if [[ ! -d "${dictPath}/dict" ]] && [[ ! -r "${cache}/bk3-dict.dat" ]]; then
find "${WINEPREFIX}/drive_c/nyanchangame/bk3" -type f -name 'nvdaControllerClient.dll' -exec rm -v "{}" \;
"${scriptDir}/speech/clipboard_translator.sh" "play.exe" bokurano-daibouken3 &
fi
fi
if [[ "${game[2]}" == "Bop It Emulator" ]]; then
"${scriptDir}/speech/speak_window_title.sh" bop.exe &
fi
if [[ "${game[2]}" == "Road to Rage" ]]; then
"${scriptDir}/speech/speak_window_title.sh" trtr.exe &
fi
if [[ "${game[2]}" == "Sequence Storm" ]]; then
"${scriptDir}/speech/clipboard_reader.sh" SequenceStorm &
fi
#if [[ "${game[2]}" == "Shadow Line" ]]; then
#find "${WINEPREFIX}/drive_c/" -type f -name 'nvdaControllerClient.dll' -exec rm -v "{}" \;
#"${scriptDir}/speech/clipboard_translator.sh" play_sr.exe shadow-line &
#fi
# sketchbook: DLL replacement now handled by update_nvda_dlls()
if [[ "${game[2]}" == "Audiodisc" ]]; then
wine "$winePath\\$wineExec"
exit 0
fi
if [[ "${game[2]}" == "Audioquake" ]]; then
wine "$winePath\\$wineExec"
exit 0
fi
if [[ "${game[2]}" == "Screaming Strike 2" ]]; then
pushd "$(winepath "$winePath")"
wine "$wineExec"
popd
exit 0
fi
if [[ "${game[2]}" == "Warsim" ]]; then
pushd "$(winepath "${game[1]%\\*}")"
wine "${game[1]##*\\}"
popd
exit 0
fi
if [[ "${game[2]}" == "Interceptor" ]]; then
pushd "$(winepath "$winePath")"
wine "$wineExec"
popd
exit 0
fi
}
# Process game launcher flags
process_launcher_flags() {
flags=("${game[@]:3}")
for i in "${flags[@]}" ; do
if [[ "${i}" =~ ^export\ [a-zA-Z_][a-zA-Z0-9_]*=\'?.*\'?$ ]]; then
eval "${i}"
fi
done
}
create_game_array() {
# Game array 0 bottle, 1 path, 2 title, 3+ flags
game="$1"
for i in "${lines[@]}" ; do
# Only compare the launcher section
j="${game#*|}"
k="${i#*|}"
k="${k%%|*}"
if [[ "$j" == "$k" ]]; then
IFS='|' read -ra game <<< "$i"
break
fi
done
}
# Update NVDA controller client DLLs in wine bottles
update_nvda_dlls() {
# Ensure we have the replacement DLLs
source "${scriptDir}/.includes/functions.sh"
download "${nvdaControllerClientDll}" "${nvdaControllerClient64Dll}"
# Update wine64 bottle (most common)
if [[ -d "$HOME/.local/wine64" ]]; then
find "$HOME/.local/wine64" -type f \( -iname "nvdaControllerClient*.dll" \) -print0 | while IFS= read -r -d '' dllFile; do
local basename="${dllFile##*/}"
local replacement=""
case "${basename,,}" in
"nvdacontrollerclient32.dll")
replacement="${cache}/nvdaControllerClient32.dll"
;;
"nvdacontrollerclient64.dll")
replacement="${cache}/nvdaControllerClient64.dll"
;;
"nvdacontrollerclient.dll")
# Use file command to detect architecture
if file "$dllFile" | grep -q "PE32+"; then
replacement="${cache}/nvdaControllerClient64.dll"
elif file "$dllFile" | grep -q "PE32"; then
replacement="${cache}/nvdaControllerClient32.dll"
fi
;;
esac
if [[ -n "$replacement" ]] && [[ -f "$replacement" ]]; then
echo "Updating $dllFile with nvdaControllerClient"
cp "$replacement" "$dllFile"
fi
done
fi
# Note: 32-bit games running via WOW64 in wine64 bottle are handled above
# The 'file' command detects PE32 vs PE32+ and applies the correct DLL version
}
# launch games that are installed
game_launcher() {
# For use by update scripts that want to source functions in this file.
[[ "$agmNoLaunch" == "true" ]] && return
source "${scriptDir}/.includes/bottle.sh"
# Start nvda2speechd if available
if [[ -x ${XDG_DATA_HOME:-$HOME/.local/share}/audiogame-manager/nvda2speechd ]]; then
${XDG_DATA_HOME:-$HOME/.local/share}/audiogame-manager/nvda2speechd &> /dev/null &
fi
# Replace NVDA controller client DLLs in wine64 bottle
update_nvda_dlls
mapfile -t lines < <(sed -e '/^$/d' -e '/^ *#/d' "${configFile}" 2> /dev/null)
if [[ ${#lines} -eq 0 ]]; then
agm_msgbox "Audio Game Launcher" "" "Install some games first."
exit 0
fi
if [[ $# -eq 0 ]]; then
# Create the menu of installed games
declare -a menuList
for i in "${lines[@]}" ; do
IFS='|' read -ra gameInfo <<< "$i"
menuList+=("${gameInfo[0]}|${gameInfo[1]}" "${gameInfo[2]}")
done
menuList+=("Donate" "Donate")
menuList+=("Become a Patron" "Become a Patron")
local game=""
game="$(agm_menu "Audio Game Launcher" "Audio Game Launcher" "Please select a game to play" "${menuList[@]}")"
local menuCode=$?
if [[ $menuCode -eq 1 ]] || [[ $menuCode -eq 255 ]]; then
exit 0
elif [[ $menuCode -eq 3 ]]; then
source "${scriptDir}/.includes/help.sh" # Make available in this function
documentation "$game" "$(echo "$game" | cut -d '|' -f2)"
fi
# Safety check: don't proceed if game is empty
if [[ -z "$game" ]]; then
exit 0
fi
create_game_array "$game"
else
create_game_array "$game"
if [[ -z "$game" ]]; then
agm_msgbox "Audio Game Launcher" "" "Game $1 not found."
exit 1
fi
fi
if [[ ${#game[@]} -gt 0 ]]; then
if [[ "${game[0]}" == "Donate" ]]; then
open_url "https://ko-fi.com/stormux"
exit 0
fi
if [[ "${game[0]}" == "Become a Patron" ]]; then
open_url "https://2mb.games/product/2mb-patron/"
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
# launch the game
if command -v qjoypad &> /dev/null ; then
mkdir -p ~/.qjoypad3
touch "${HOME}/.qjoypad3/${game[2]}.lyt"
# A | separated list of games that should not start with qjoypad.
noQjoypadGames="A Hero's Call"
if [[ "${noqjoypad}" != "true" ]] && ! [[ "${game[2]}" =~ ${noQjoypadGames} ]]; then
if pgrep qjoypad &> /dev/null ; then
qjoypad -T "${game[2]}" 2> /dev/null
else
qjoypad -T "${game[2]}" 2> /dev/null &
fi
fi
fi
process_launcher_flags
custom_launch_parameters
if [[ "$debugGdb" == "1" ]]; then
# Change to game directory before launching
pushd "$(winepath "${game[1]%\\*}")" > /dev/null
winedbg --gdb "${game[1]##*\\}"
popd > /dev/null
else
wine start /d "${game[1]%\\*}" "${game[1]##*\\}" /realtime
fi
fi
exit 0
}
# main script
trap "exit 0" SIGINT
# Detect dialog interface type BEFORE potentially setting DISPLAY
# This must happen before we modify DISPLAY to preserve console detection
if [[ -z "$DISPLAY" ]]; then
dialogType="dialog"
elif command -v yad &> /dev/null; then
dialogType="yad"
else
dialogType="dialog"
fi
# Source dialog interface early for progress display
source "${scriptDir}/.includes/dialog-interface.sh"
# If display isn't set assume we are launching from console and an X environment is running using display :0
if [[ -z "$DISPLAY" ]]; then
export DISPLAY=":0"
fi
# Settings file
export cache="${XDG_CACHE_HOME:-$HOME/.cache}/audiogame-manager"
export configFile="${XDG_CONFIG_HOME:-$HOME/.config}/storm-games/audiogame-manager/games.conf"
mkdir -p "${cache}"
mkdir -p "${configFile%/*}"
# Create the path for AGM's helper programs.
# Originally this was only winetricks, thus the name, and I'm too lazy to change it now.
winetricksPath="${XDG_DATA_HOME:-$HOME/.local/share}/audiogame-manager"
mkdir -p "${winetricksPath}"
# Load any arguments from settings.conf file
if [[ -r "${configFile%/*}/settings.conf" ]]; then
source "${configFile%/*}/settings.conf"
fi
# Update the cache for older versions of audiogame-manager
if [[ -d "${configFile%/*}/cache" ]]; then
{ mv -v "${configFile%/*}/cache/"* "${cache}"
rmdir -v "${configFile%/*}/cache/"; } | agm_progressbox "Audiogame Manager" "Updating cache, please wait..."
fi
checkWinetricksUpdate="false"
# Turn off debug messages
export WINEDEBUG="${winedebug:--all}"
# During installation, you can set winVer to the versions available.
# To set winetricks arguments, such as virtual desktop, set the winetricksSettings variable.
# Example: winetricksSettings="vd=1024x768"
# Files are cached unless -N no cache is set.
unset noCache
# Manual installation is not default, make sure it's unset
unset manualInstall
unset version
# ipfs gateway
export ipfsGateway="${ipfsGateway:-https://ipfs.stormux.org}"
export nvdaControllerClientDll="${ipfsGateway}/ipfs/Qmd1JXdDoKJVnoaQssDiBgRpbgwKUwdJigiPw8iiYro3vt?filename=nvdaControllerClient32.dll"
export nvdaControllerClient64Dll="${ipfsGateway}/ipfs/QmcPoBTm6eCFF4R4uUc1of3rtrqMVx3HFN1U1jHosay8EX?filename=nvdaControllerClient64.dll"
export nvda2speechdBinary="${ipfsGateway}/ipfs/QmPxhoNsoFoJC7bCfioBBCcK8tEoSoYpm342z6u7KjFsVz?filename=nvda2speechd"
# nvda2speechd server startup is now handled in game_launcher()
# Source helper functions
source "${scriptDir}/.includes/bottle.sh" # Also sourced in functions that need it
source "${scriptDir}/.includes/desktop.sh"
# dialog-interface.sh already sourced earlier
source "${scriptDir}/.includes/functions.sh"
source "${scriptDir}/.includes/help.sh"
source "${scriptDir}/.includes/update.sh"
# Check minimum requirements
check_requirements || exit 1
# Wine32 no longer needed - all games use wine64 with SAPI support via WINETRICKS_FORCE=1
# check_wine32 # Disabled - wine32 eliminated 2025-12-06
# Ensure wine bottles exist with dependencies
ensure_wine_bottles
# Check for updates
update
# Get latest news if available
check_news
# With no arguments, open the game launcher.
if [[ $# -eq 0 ]]; then
game_launcher
fi
# Array of command line arguments
declare -A command=(
[c]="Check your system for necessary components."
[C]="Clear the cache. All game installers will be deleted."
[D]="Create desktop shortcut. You can launch audiogame-manager from the desktop or applications menu."
[d]="Debug mode, wine will be much more verbose when games are installed with this flag."
[g]="Debug with GDB. Launch game with winedbg --gdb for step-through debugging."
[h]="This help screen."
[i]="Install games."
[I:]="Noninteractive game installation."
[k]="Kill a running game that is stuck."
[L]="Display license information."
[l:]="Launch given game without interactive audiogame-manager menu specified by its wine bottle."
[N]="No cache, delete the installer after it has been extracted."
[n]="No RHVoice, do not install RHVoice when the game is installed."
[P]="Print a list of packages required by audiogame-manager."
[q]="No qjoypad. Does not launch qjoypad if it is detected."
[R]="Redownload. Removes old versions of packages from cache before installing."
[r]="Remove a game. This will delete all game data."
[S:]="Speech rate. Requires -V voice name, the default is 7. Values 0-9 or A."
[t]="Total games. Show how many games are currently available."
[v:]="Select the voice to be installed, default is Bdl. Options are alan, bdl, clb, or slt."
[V:]="Select the default voice for a bottle."
)
# Convert the keys of the associative array to a format usable by getopts
args="${!command[*]}"
args="${args//[[:space:]]/}"
while getopts "${args}" i ; do
case "$i" in
c) "${scriptDir}/.includes/checkup.sh";;
C) clear_cache;;
D) desktop_launcher;;
d)
unset WINEDEBUG
game_installer
;;
g)
debugGdb=1
game_launcher;;
h) help;;
i) game_installer;;
I)
export game="${OPTARG}"
export noninteractiveInstall="true"
break;;
k) kill_game;;
L) license;;
l) game_launcher "${OPTARG}";;
N) noCache="true";;
n) norh="true";;
P) checklist quiet;;
q)
noqjoypad="true"
game_launcher;;
R) redownload="true";;
r) game_removal;;
S) defaultRate="${OPTARG}";;
t)
gameCount=$(find "${scriptDir}/.install" -type f -iname "*.sh" | wc -l)
agm_infobox "Linux Game Manager" "Linux Game Manager" "There are currently ${gameCount} games available."
exit 0
;;
v) voiceName="${OPTARG}";;
V) defaultVoice="${OPTARG}";;
esac
done
# If agmNoLaunch is set, exit (script is being sourced)
[[ "$agmNoLaunch" == "true" ]] && exit 0
# Only proceed with noninteractive installation if explicitly requested
if [[ "$noninteractiveInstall" == "true" ]]; then
# If no game specified for noninteractive install, exit
[[ ${#game} -lt 1 ]] && exit 0
# Install the specified game noninteractively
if [[ -f "${scriptDir}/.install/${game}.sh" ]]; then
export LANG="en_US.UTF-8"
. "${scriptDir}/.install/${game}.sh"
# Show success message
agm_msgbox "Installation Complete" "Audio Game Installer" "Game \"${game}\" has been successfully installed."
else
agm_msgbox "Audio Game Installer" "" "Error: Game '${game}' not found in .install directory"
exit 1
fi
fi