mirror of
https://github.com/RetroPie/RetroPie-Setup.git
synced 2025-04-02 10:51:41 -04:00
774 lines
24 KiB
Bash
774 lines
24 KiB
Bash
#!/bin/bash
|
|
|
|
# This file is part of The RetroPie Project
|
|
#
|
|
# The RetroPie Project is the legal property of its developers, whose names are
|
|
# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.
|
|
#
|
|
# See the LICENSE.md file at the top-level directory of this distribution and
|
|
# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md
|
|
#
|
|
|
|
function printMsgs() {
|
|
local type="$1"
|
|
shift
|
|
if [[ "$__nodialog" == "1" && "$type" == "dialog" ]]; then
|
|
type="console"
|
|
fi
|
|
for msg in "$@"; do
|
|
[[ "$type" == "dialog" ]] && dialog --backtitle "$__backtitle" --cr-wrap --no-collapse --msgbox "$msg" 20 60 >/dev/tty
|
|
[[ "$type" == "console" ]] && echo -e "$msg"
|
|
[[ "$type" == "heading" ]] && echo -e "\n= = = = = = = = = = = = = = = = = = = = =\n$msg\n= = = = = = = = = = = = = = = = = = = = =\n"
|
|
done
|
|
}
|
|
|
|
function printHeading() {
|
|
printMsgs "heading" "$@"
|
|
}
|
|
|
|
function fatalError() {
|
|
printHeading "Error"
|
|
echo "$1"
|
|
exit 1
|
|
}
|
|
|
|
function fnExists() {
|
|
declare -f "$1" > /dev/null
|
|
return $?
|
|
}
|
|
|
|
function ask() {
|
|
echo -e -n "$@" '[y/n] ' ; read ans
|
|
case "$ans" in
|
|
y*|Y*) return 0 ;;
|
|
*) return 1 ;;
|
|
esac
|
|
}
|
|
|
|
function hasFlag() {
|
|
local string="$1"
|
|
local flag="$2"
|
|
[[ -z "$string" ]] || [[ -z "$flag" ]] && return 1
|
|
|
|
local re="(^| )$flag($| )"
|
|
if [[ $string =~ $re ]]; then
|
|
return 0
|
|
else
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
function isPlatform() {
|
|
local flag="$1"
|
|
if hasFlag "$__platform $__platform_flags" "$flag"; then
|
|
return 0
|
|
fi
|
|
return 1
|
|
}
|
|
|
|
function addLineToFile() {
|
|
if [[ -f "$2" ]]; then
|
|
cp -p "$2" "$2.bak"
|
|
fi
|
|
sed -i -e '$a\' "$2"
|
|
echo "$1" >> "$2"
|
|
echo "Added $1 to file $2"
|
|
}
|
|
|
|
function editFile() {
|
|
local file="$1"
|
|
local cmd=(dialog --backtitle "$__backtitle" --editbox "$file" 22 76)
|
|
local choice=$("${cmd[@]}" 2>&1 >/dev/tty)
|
|
[[ -n "$choice" ]] && echo "$choice" >"$file"
|
|
}
|
|
|
|
function hasPackage() {
|
|
local pkg="$1"
|
|
local req_ver="$2"
|
|
local comp="$3"
|
|
[[ -z "$comp" ]] && comp="ge"
|
|
local status=$(dpkg-query -W --showformat='${Status} ${Version}' $1 2>/dev/null)
|
|
if [[ $? -eq 0 ]]; then
|
|
local ver="${status##* }"
|
|
local status="${status% *}"
|
|
# if status doesn't contain "ok installed" package is not installed
|
|
if [[ "$status" == *"ok installed" ]]; then
|
|
# if we didn't request a version number, be happy with any
|
|
[[ -z "$req_ver" ]] && return 0
|
|
dpkg --compare-versions "$ver" "$comp" "$req_ver" && return 0
|
|
fi
|
|
fi
|
|
return 1
|
|
}
|
|
|
|
function aptUpdate() {
|
|
if [[ "$__apt_update" != "1" ]]; then
|
|
apt-get update
|
|
__apt_update="1"
|
|
fi
|
|
}
|
|
|
|
function aptInstall() {
|
|
aptUpdate
|
|
apt-get install -y "$@"
|
|
return $?
|
|
}
|
|
|
|
function aptRemove() {
|
|
aptUpdate
|
|
apt-get remove -y "$@"
|
|
return $?
|
|
}
|
|
|
|
function getDepends() {
|
|
local required
|
|
local packages=()
|
|
local failed=()
|
|
for required in $@; do
|
|
if [[ "$md_mode" == "install" ]]; then
|
|
# make sure we have our sdl1 / sdl2 installed
|
|
if [[ "$required" == "libsdl1.2-dev" ]] && ! hasPackage libsdl1.2-dev 1.2.15-$(get_ver_sdl1)rpi "eq"; then
|
|
packages+=("$required")
|
|
continue
|
|
fi
|
|
if ! isPlatform "x11" && [[ "$required" == "libsdl2-dev" ]] && ! hasPackage libsdl2-dev $(get_ver_sdl2) "eq"; then
|
|
packages+=("$required")
|
|
continue
|
|
fi
|
|
fi
|
|
if [[ "$required" == "libraspberrypi-dev" ]] && hasPackage rbp-bootloader-osmc; then
|
|
required="rbp-userland-dev-osmc"
|
|
fi
|
|
if [[ "$md_mode" == "remove" ]]; then
|
|
hasPackage "$required" && packages+=("$required")
|
|
else
|
|
hasPackage "$required" || packages+=("$required")
|
|
fi
|
|
done
|
|
if [[ ${#packages[@]} -ne 0 ]]; then
|
|
if [[ "$md_mode" == "remove" ]]; then
|
|
apt-get remove --purge -y "${packages[@]}"
|
|
apt-get autoremove --purge -y
|
|
return 0
|
|
fi
|
|
echo "Did not find needed package(s): ${packages[@]}. I am trying to install them now."
|
|
|
|
# workaround to force installation of our fixed libsdl1.2 and custom compiled libsdl2 for rpi
|
|
if isPlatform "rpi" || isPlatform "mali"; then
|
|
local temp=()
|
|
for required in ${packages[@]}; do
|
|
if isPlatform "rpi" && [[ "$required" == "libsdl1.2-dev" ]]; then
|
|
if [[ "$__has_binaries" -eq 1 ]]; then
|
|
rp_callModule sdl1 install_bin
|
|
else
|
|
rp_callModule sdl1
|
|
fi
|
|
elif [[ "$required" == "libsdl2-dev" ]]; then
|
|
if [[ "$__has_binaries" -eq 1 ]]; then
|
|
rp_callModule sdl2 install_bin
|
|
else
|
|
rp_callModule sdl2
|
|
fi
|
|
else
|
|
temp+=("$required")
|
|
fi
|
|
done
|
|
packages=("${temp[@]}")
|
|
fi
|
|
|
|
aptInstall --no-install-recommends "${packages[@]}"
|
|
|
|
# check the required packages again rather than return code of apt-get,
|
|
# as apt-get might fail for other reasons (eg other half installed packages)
|
|
for required in ${packages[@]}; do
|
|
if ! hasPackage "$required"; then
|
|
# workaround for installing samba in a chroot (fails due to failed smbd service restart)
|
|
# we replace the init.d script with an empty script so the install completes
|
|
if [[ "$required" == "samba" && "$__chroot" -eq 1 ]]; then
|
|
mv /etc/init.d/smbd /etc/init.d/smbd.old
|
|
echo "#!/bin/sh" >/etc/init.d/smbd
|
|
chmod u+x /etc/init.d/smbd
|
|
apt-get -f install
|
|
mv /etc/init.d/smbd.old /etc/init.d/smbd
|
|
else
|
|
failed+=("$required")
|
|
fi
|
|
fi
|
|
done
|
|
if [[ ${#failed[@]} -eq 0 ]]; then
|
|
printMsgs "console" "Successfully installed package(s): ${packages[*]}."
|
|
else
|
|
md_ret_errors+=("Could not install package(s): ${failed[*]}.")
|
|
return 1
|
|
fi
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
function rpSwap() {
|
|
local command=$1
|
|
local swapfile="$__swapdir/swap"
|
|
case $command in
|
|
on)
|
|
rpSwap off
|
|
local memory=$(free -t -m | awk '/^Total:/{print $2}')
|
|
local needed=$2
|
|
local size=$((needed - memory))
|
|
mkdir -p "$__swapdir/"
|
|
if [[ $size -ge 0 ]]; then
|
|
echo "Adding $size MB of additional swap"
|
|
fallocate -l ${size}M "$swapfile"
|
|
mkswap "$swapfile"
|
|
swapon "$swapfile"
|
|
fi
|
|
;;
|
|
off)
|
|
echo "Removing additional swap"
|
|
swapoff "$swapfile" 2>/dev/null
|
|
rm -f "$swapfile"
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# clones or updates the sources of a repository $2 into the directory $1
|
|
function gitPullOrClone() {
|
|
local dir="$1"
|
|
local repo="$2"
|
|
local branch="$3"
|
|
[[ -z "$branch" ]] && branch="master"
|
|
|
|
if [[ -d "$dir/.git" ]]; then
|
|
pushd "$dir" > /dev/null
|
|
git pull > /dev/null
|
|
popd > /dev/null
|
|
else
|
|
local git="git clone"
|
|
[[ "$repo" =~ github ]] && git+=" --depth 1"
|
|
[[ "$branch" != "master" ]] && git+=" --branch $branch"
|
|
echo "$git \"$repo\" \"$dir\""
|
|
$git "$repo" "$dir"
|
|
fi
|
|
}
|
|
|
|
function ensureRootdirExists() {
|
|
mkdir -p "$rootdir"
|
|
# make sure we have inifuncs.sh in place and that it is up to date
|
|
mkdir -p "$rootdir/lib"
|
|
if [[ ! -f "$rootdir/lib/inifuncs.sh" || "$rootdir/lib/inifuncs.sh" -ot "$scriptdir/scriptmodules/inifuncs.sh" ]]; then
|
|
cp --preserve=timestamps "$scriptdir/scriptmodules/inifuncs.sh" "$rootdir/lib/inifuncs.sh"
|
|
fi
|
|
mkUserDir "$datadir"
|
|
mkUserDir "$configdir"
|
|
mkUserDir "$configdir/all"
|
|
}
|
|
|
|
function rmDirExists() {
|
|
if [[ -d "$1" ]]; then
|
|
rm -rf "$1"
|
|
fi
|
|
}
|
|
|
|
function mkUserDir() {
|
|
mkdir -p "$1"
|
|
chown $user:$user "$1"
|
|
}
|
|
|
|
function mkRomDir() {
|
|
mkUserDir "$romdir/$1"
|
|
if [[ "$1" == "megadrive" ]]; then
|
|
pushd "$romdir"
|
|
ln -snf "$1" "genesis"
|
|
popd
|
|
fi
|
|
}
|
|
|
|
function moveConfigDir() {
|
|
local from="$1"
|
|
local to="$2"
|
|
|
|
# if we are in remove mode - remove the symlink
|
|
if [[ "$md_mode" == "remove" && -h "$from" ]]; then
|
|
rm -f "$from"
|
|
return
|
|
fi
|
|
|
|
mkUserDir "$to"
|
|
# move any old configs to the new location
|
|
if [[ -d "$from" && ! -h "$from" ]]; then
|
|
# also match hidden files
|
|
shopt -s dotglob
|
|
if [[ -n "$(ls -A $from)" ]]; then
|
|
mv -f "$from/"* "$to"
|
|
fi
|
|
shopt -u dotglob
|
|
rmdir "$from"
|
|
fi
|
|
ln -snf "$to" "$from"
|
|
# set ownership of the actual link to $user
|
|
chown -h $user:$user "$from"
|
|
}
|
|
|
|
function moveConfigFile() {
|
|
local from="$1"
|
|
local to="$2"
|
|
|
|
# if we are in remove mode - remove the symlink
|
|
if [[ "$md_mode" == "remove" && -h "$from" ]]; then
|
|
rm -f "$from"
|
|
return
|
|
fi
|
|
|
|
# move old file
|
|
if [[ -f "from" && ! -h "from" ]]; then
|
|
mv "from" "$to"
|
|
fi
|
|
ln -sf "$to" "$from"
|
|
# set ownership of the actual link to $user
|
|
chown -h $user:$user "$from"
|
|
}
|
|
|
|
function setDispmanx() {
|
|
isPlatform "rpi" || return
|
|
local mod_id="$1"
|
|
local status="$2"
|
|
mkUserDir "$configdir/all"
|
|
iniConfig "=" "\"" "$configdir/all/dispmanx.cfg"
|
|
iniSet $mod_id "$status"
|
|
chown $user:$user "$configdir/all/dispmanx.cfg"
|
|
}
|
|
|
|
function iniFileEditor() {
|
|
local delim="$1"
|
|
local quote="$2"
|
|
local config="$3"
|
|
[[ ! -f "$config" ]] && return
|
|
|
|
# disable globbing
|
|
set -f
|
|
|
|
iniConfig "$delim" "$quote" "$config"
|
|
local sel
|
|
local value
|
|
local option
|
|
local title
|
|
while true; do
|
|
local options=()
|
|
local params=()
|
|
local values=()
|
|
local keys=()
|
|
local i=0
|
|
|
|
# generate menu from options
|
|
for option in "${ini_options[@]}"; do
|
|
option=($option)
|
|
key="${option[0]}"
|
|
keys+=("$key")
|
|
params+=("${option[*]:1}")
|
|
|
|
# if the first parameter is _function_ we call the second parameter as a function
|
|
# so we can handle some options with a custom menu etc
|
|
if [[ "$key" == "_function_" ]]; then
|
|
value="$(${option[1]} get)"
|
|
else
|
|
# get current value
|
|
iniGet "$key"
|
|
if [[ -n "$ini_value" ]]; then
|
|
value="$ini_value"
|
|
else
|
|
value="unset"
|
|
fi
|
|
fi
|
|
|
|
values+=("$value")
|
|
|
|
# add the matching value to our id in _id_ lists
|
|
if [[ "${option[1]}" == "_id_" && "$value" != "unset" ]]; then
|
|
value+=" - ${option[value+2]}"
|
|
fi
|
|
|
|
# use custom title if provided
|
|
if [[ -n "${ini_titles[i]}" ]]; then
|
|
title="${ini_titles[i]}"
|
|
else
|
|
title="$key"
|
|
fi
|
|
|
|
options+=("$i" "$title ($value)" "${ini_descs[i]}")
|
|
|
|
((i++))
|
|
done
|
|
|
|
local cmd=(dialog --backtitle "$__backtitle" --default-item "$sel" --item-help --help-button --menu "Please choose the setting to modify in $config" 22 76 16)
|
|
sel=$("${cmd[@]}" "${options[@]}" 2>&1 >/dev/tty)
|
|
if [[ "${sel[@]:0:4}" == "HELP" ]]; then
|
|
printMsgs "dialog" "${sel[@]:5}"
|
|
continue
|
|
fi
|
|
|
|
[[ -z "$sel" ]] && break
|
|
|
|
# if the key is _function_ we handle the option with a custom function
|
|
if [[ "${keys[sel]}" == "_function_" ]]; then
|
|
"${params[sel]}" set "${values[sel]}"
|
|
continue
|
|
fi
|
|
|
|
# process the editing of the option
|
|
i=0
|
|
options=("U" "unset")
|
|
local default
|
|
|
|
params=(${params[sel]})
|
|
local mode="${params[0]}"
|
|
|
|
case "$mode" in
|
|
_string_)
|
|
options+=("E" "Edit (Currently ${values[sel]})")
|
|
;;
|
|
_file_)
|
|
local match="${params[1]}"
|
|
local path="${params[*]:2}"
|
|
local file
|
|
while read file; do
|
|
[[ "${values[sel]}" == "$file" ]] && default="$i"
|
|
file="${file//$path\//}"
|
|
options+=("$i" "$file")
|
|
((i++))
|
|
done < <(find "$path" -type f -name "$match" | sort)
|
|
;;
|
|
_id_|*)
|
|
[[ "$mode" == "_id_" ]] && params=("${params[@]:1}")
|
|
for option in "${params[@]}"; do
|
|
if [[ "$mode" == "_id_" ]]; then
|
|
[[ "${values[sel]}" == "$i" ]] && default="$i"
|
|
else
|
|
[[ "${values[sel]}" == "$option" ]] && default="$i"
|
|
fi
|
|
options+=("$i" "$option")
|
|
((i++))
|
|
done
|
|
;;
|
|
esac
|
|
[[ -z "$default" ]] && default="U"
|
|
# display values
|
|
cmd=(dialog --backtitle "$__backtitle" --default-item "$default" --menu "Please choose the value for ${keys[sel]}" 22 76 16)
|
|
local choice=$("${cmd[@]}" "${options[@]}" 2>&1 >/dev/tty)
|
|
|
|
# if it is a _string_ type we will open an inputbox dialog to get a manual value
|
|
if [[ -z "$choice" ]]; then
|
|
continue
|
|
elif [[ "$choice" == "E" ]]; then
|
|
[[ "${values[sel]}" == "unset" ]] && values[sel]=""
|
|
cmd=(dialog --backtitle "$__backtitle" --inputbox "Please enter the value for ${keys[sel]}" 10 60 "${values[sel]}")
|
|
value=$("${cmd[@]}" 2>&1 >/dev/tty)
|
|
elif [[ "$choice" == "U" ]]; then
|
|
value="$default"
|
|
else
|
|
if [[ "$mode" == "_id_" ]]; then
|
|
value="$choice"
|
|
else
|
|
# get the actual value from the options array
|
|
local index=$((choice*2+3))
|
|
if [[ "$mode" == "_file_" ]]; then
|
|
value="$path/${options[index]}"
|
|
else
|
|
value="${options[index]}"
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
# save the #include line and remove it, so we can add our ini values and re-add the include line(s) at the end
|
|
local include=$(grep "^#include" "$config")
|
|
sed -i "/^#include/d" "$config"
|
|
|
|
if [[ "$choice" == "U" ]]; then
|
|
iniUnset "${keys[sel]}" "$value"
|
|
else
|
|
iniSet "${keys[sel]}" "$value"
|
|
fi
|
|
|
|
# re-add the include line(s)
|
|
if [[ -n "$include" ]]; then
|
|
echo "$include" >>"$config"
|
|
fi
|
|
|
|
done
|
|
|
|
# enable globbing
|
|
set +f
|
|
}
|
|
|
|
function setESSystem() {
|
|
local fullname=$1
|
|
local name=$2
|
|
local path=$3
|
|
local extension=$4
|
|
local command=$5
|
|
local platform=$6
|
|
local theme=$7
|
|
|
|
local conf="/etc/emulationstation/es_systems.cfg"
|
|
mkdir -p "/etc/emulationstation"
|
|
if [[ ! -f "$conf" ]]; then
|
|
echo "<systemList />" >"$conf"
|
|
fi
|
|
|
|
cp "$conf" "$conf.bak"
|
|
if [[ $(xmlstarlet sel -t -v "count(/systemList/system[name='$name'])" "$conf") -eq 0 ]]; then
|
|
xmlstarlet ed -L -s "/systemList" -t elem -n "system" -v "" \
|
|
-s "/systemList/system[last()]" -t elem -n "name" -v "$name" \
|
|
-s "/systemList/system[last()]" -t elem -n "fullname" -v "$fullname" \
|
|
-s "/systemList/system[last()]" -t elem -n "path" -v "$path" \
|
|
-s "/systemList/system[last()]" -t elem -n "extension" -v "$extension" \
|
|
-s "/systemList/system[last()]" -t elem -n "command" -v "$command" \
|
|
-s "/systemList/system[last()]" -t elem -n "platform" -v "$platform" \
|
|
-s "/systemList/system[last()]" -t elem -n "theme" -v "$theme" \
|
|
"$conf"
|
|
else
|
|
xmlstarlet ed -L \
|
|
-u "/systemList/system[name='$name']/fullname" -v "$fullname" \
|
|
-u "/systemList/system[name='$name']/path" -v "$path" \
|
|
-u "/systemList/system[name='$name']/extension" -v "$extension" \
|
|
-u "/systemList/system[name='$name']/command" -v "$command" \
|
|
-u "/systemList/system[name='$name']/platform" -v "$platform" \
|
|
-u "/systemList/system[name='$name']/theme" -v "$theme" \
|
|
"$conf"
|
|
fi
|
|
|
|
sortESSystems "name"
|
|
}
|
|
|
|
function sortESSystems() {
|
|
local field="$1"
|
|
cp "/etc/emulationstation/es_systems.cfg" "/etc/emulationstation/es_systems.cfg.bak"
|
|
xmlstarlet sel -D -I \
|
|
-t -m "/" -e "systemList" \
|
|
-m "//system" -s A:T:U "$1" -c "." \
|
|
"/etc/emulationstation/es_systems.cfg.bak" >"/etc/emulationstation/es_systems.cfg"
|
|
}
|
|
|
|
function ensureSystemretroconfig {
|
|
local system="$1"
|
|
local shader="$2"
|
|
|
|
if [[ ! -d "$configdir/$system" ]]; then
|
|
mkUserDir "$configdir/$system"
|
|
fi
|
|
|
|
local include_comment="# Settings made here will only override settings in the global retroarch.cfg if placed above the #include line"
|
|
local include="#include \"$configdir/all/retroarch.cfg\""
|
|
|
|
local config="$configdir/$system/retroarch.cfg"
|
|
# if the user has an existing config we will not overwrite it, but instead create the
|
|
# default config as retroarch.cfg.rp-dist (apart from the very important #include addition)
|
|
if [[ -f "$config" ]]; then
|
|
if ! grep -q "$include" "$config"; then
|
|
sed -i "1i$include_comment\n" "$config"
|
|
echo -e "\n$include" >>"$config"
|
|
fi
|
|
config="$configdir/$system/retroarch.cfg.rp-dist"
|
|
rm -f "$config"
|
|
fi
|
|
|
|
# add the initial comment regarding include order
|
|
if [[ ! -f "$config" ]]; then
|
|
echo -e "$include_comment\n" >"$config"
|
|
fi
|
|
|
|
# add the per system default settings
|
|
iniConfig " = " '"' "$config"
|
|
iniSet "input_remapping_directory" "$configdir/$system/"
|
|
|
|
if [[ -n "$shader" ]]; then
|
|
iniUnset "video_smooth" "false"
|
|
iniSet "video_shader" "$emudir/retroarch/shader/$shader"
|
|
iniUnset "video_shader_enable" "true"
|
|
fi
|
|
|
|
# include the main retroarch config
|
|
echo -e "\n$include" >>"$config"
|
|
|
|
chown $user:$user "$config"
|
|
}
|
|
|
|
function setRetroArchCoreOption() {
|
|
local option="$1"
|
|
local value="$2"
|
|
iniConfig " = " "\"" "$configdir/all/retroarch-core-options.cfg"
|
|
iniSet "$option" "$value"
|
|
chown $user:$user "$configdir/all/retroarch-core-options.cfg"
|
|
}
|
|
|
|
# sets module config root to subfolder from $configdir - used for ports that are not actually in the ports etc
|
|
function setConfigRoot() {
|
|
local dir="$1"
|
|
md_conf_root="$configdir"
|
|
[[ -n "$dir" ]] && md_conf_root+="/$dir"
|
|
mkUserDir "$md_conf_root"
|
|
}
|
|
|
|
# add a framebuffer mode to /etc/fb.modes - useful for adding specific resolutions used by emulators so SDL
|
|
# can use them and utilise the rpi hardware scaling
|
|
# without a 320x240 mode in fb.modes many of the emulators that output to framebuffer (stella / snes9x / gngeo)
|
|
# would just show in a small area of the screen
|
|
function ensureFBMode() {
|
|
local res_x="$1"
|
|
local res_y="$2"
|
|
local res="${res_x}x${res_y}"
|
|
sed -i "/$res mode/,/endmode/d" /etc/fb.modes
|
|
|
|
cat >> /etc/fb.modes <<_EOF_
|
|
# added by RetroPie-Setup - $res mode for emulators
|
|
mode "$res"
|
|
geometry $res_x $res_y $res_x $res_y 16
|
|
timings 0 0 0 0 0 0 0
|
|
endmode
|
|
_EOF_
|
|
}
|
|
|
|
# arg 1: 0 or 1 to make the emulator default, arg 2: module id, arg 3: "system" or "system platform" or "system platform theme", arg 4: commandline, arg 5 (optional) fullname for es config, arg 6: extensions
|
|
function addSystem() {
|
|
local default="$1"
|
|
local id="$2"
|
|
local names=($3)
|
|
local cmd="$4"
|
|
local fullname="$5"
|
|
local exts=($6)
|
|
|
|
local system
|
|
local platform
|
|
local theme
|
|
|
|
# set system / platform / theme for configuration based on data in names field
|
|
if [[ -n "${names[2]}" ]]; then
|
|
system="${names[0]}"
|
|
platform="${names[1]}"
|
|
theme="${names[2]}"
|
|
elif [[ -n "${names[1]}" ]]; then
|
|
system="${names[0]}"
|
|
platform="${names[1]}"
|
|
theme="$system"
|
|
else
|
|
system="${names[0]}"
|
|
platform="$system"
|
|
theme="$system"
|
|
fi
|
|
|
|
# check if we are removing the system
|
|
if [[ "$md_mode" == "remove" ]]; then
|
|
delSystem "$id" "$system"
|
|
return
|
|
fi
|
|
|
|
# for the ports section, we will handle launching from a separate script and hardcode exts etc
|
|
local es_cmd="$rootdir/supplementary/runcommand/runcommand.sh 0 _SYS_ $system %ROM%"
|
|
local es_path="$romdir/$system"
|
|
local es_name="$system"
|
|
if [[ "$theme" == "ports" ]]; then
|
|
es_cmd="%ROM%"
|
|
es_path="$romdir/ports"
|
|
es_name="ports"
|
|
exts=(".sh")
|
|
fullname="Ports"
|
|
else
|
|
local conf=""
|
|
if [[ -f "$configdir/all/platforms.cfg" ]]; then
|
|
conf="$configdir/all/platforms.cfg"
|
|
else
|
|
conf="$scriptdir/platforms.cfg"
|
|
fi
|
|
|
|
# get extensions to show
|
|
iniConfig "=" '"' "$conf"
|
|
iniGet "${system}_fullname"
|
|
[[ -n "$ini_value" ]] && fullname="$ini_value"
|
|
iniGet "${system}_exts"
|
|
[[ -n "$ini_value" ]] && exts+=($ini_value)
|
|
|
|
# automatically add parameters for libretro modules
|
|
if [[ "$id" =~ ^lr- ]]; then
|
|
cmd="$emudir/retroarch/bin/retroarch -L $cmd --config $md_conf_root/$system/retroarch.cfg %ROM%"
|
|
fi
|
|
fi
|
|
|
|
exts="${exts[@]}"
|
|
# add the extensions again as uppercase
|
|
exts+=" ${exts^^}"
|
|
|
|
# create a config folder for the system / port
|
|
mkUserDir "$md_conf_root/$system"
|
|
|
|
# add the emulator to the $conf_dir/emulators.cfg if a commandline exists (not used for some ports)
|
|
if [[ -n "$cmd" ]]; then
|
|
iniConfig "=" '"' "$md_conf_root/$system/emulators.cfg"
|
|
iniSet "$id" "$cmd"
|
|
# set a default unless there is one already set
|
|
iniGet "default"
|
|
if [[ -z "$ini_value" && "$default" -eq 1 ]]; then
|
|
iniSet "default" "$id"
|
|
fi
|
|
chown $user:$user "$md_conf_root/$system/emulators.cfg"
|
|
fi
|
|
|
|
setESSystem "$fullname" "$es_name" "$es_path" "$exts" "$es_cmd" "$platform" "$theme"
|
|
}
|
|
|
|
function delSystem() {
|
|
local id="$1"
|
|
local system="$2"
|
|
local config="$md_conf_root/$system/emulators.cfg"
|
|
# remove from apps list for system
|
|
if [[ -f "$config" && -n "$id" ]]; then
|
|
# delete emulator entry
|
|
iniConfig "=" '"' "$config"
|
|
iniDel "$id"
|
|
# if it is the default - remove it - runcommand will prompt to select a new default
|
|
iniGet "default"
|
|
[[ "$ini_value" == "$id" ]] && iniDel "default"
|
|
# if we no longer have any entries in the emulators.cfg file we can remove it
|
|
grep -q "=" "$config" || rm -f "$config"
|
|
fi
|
|
|
|
# if we don't have an emulators.cfg we can remove the system from emulation station
|
|
if [[ ! -f "$config" ]]; then
|
|
xmlstarlet ed -L -P -d "/systemList/system[name='$system']" /etc/emulationstation/es_systems.cfg
|
|
fi
|
|
}
|
|
|
|
function addPort() {
|
|
local id="$1"
|
|
local port="$2"
|
|
local file="$romdir/ports/$3.sh"
|
|
local cmd="$4"
|
|
|
|
mkUserDir "$romdir/ports"
|
|
|
|
# move configurations from old ports location
|
|
if [[ -d "$configdir/$port" ]]; then
|
|
mv "$configdir/$port" "$md_conf_root/"
|
|
fi
|
|
|
|
if [ -t 0 ]; then
|
|
cat >"$file" << _EOF_
|
|
#!/bin/bash
|
|
"$rootdir/supplementary/runcommand/runcommand.sh" 0 _PORT_ $port
|
|
_EOF_
|
|
else
|
|
cat >"$file"
|
|
fi
|
|
|
|
chown $user:$user "$file"
|
|
chmod +x "$file"
|
|
|
|
# remove the ports launch script if in remove mode
|
|
if [[ "$md_mode" == "remove" ]]; then
|
|
rm -f "$file"
|
|
# if there are no more port launch scripts we can remove ports from emulation station
|
|
if [[ "$(ls -1 "$romdir/ports/*.sh" 2>/dev/null | wc -l)" -eq 0 ]]; then
|
|
delSystem "$id" "ports"
|
|
fi
|
|
else
|
|
addSystem 1 "$id" "$port pc ports" "$cmd"
|
|
fi
|
|
}
|
|
|