#!/usr/bin/env bash
# shellcheck source=/dev/null

### project ###

PREFIX="/usr"
PROGNAME="SteamTinkerLaunch"
NICEPROGNAME="Steam Tinker Launch"
PROGVERS="v9.2"
PROGCMD="${0##*/}"
SHOSTL="stl"
GHURL="https://github.com"
PROJECTPAGE="$GHURL/frostworx/${PROGNAME,,}"
PPW="$PROJECTPAGE/wiki"
CURWIKI="$PPW"
STARTDEBUG=0

### internal dependencies ###
#STARTINTDEPS
GIT="git"
PGREP="pgrep"
PIDOF="pidof"
PKILL="pkill"
TAR="tar"
UNZIP="unzip"
WGET="wget"
XDO="xdotool"
XPROP="xprop"
XRANDR="xrandr"
XWININFO="xwininfo"
XXD="xxd"
#ENDINTDEPS

### (optionally) used programs ###
GAMEMODERUN="gamemoderun"
GAMESCOPE="gamescope"
NYRNA="nyrna"
STEAM="steam"
RECO="resetcollections"
STERECO="$STEAM ${STEAM}://${RECO}"
STRACE="strace"
WINECFG="winecfg"
WICO="wineconsole"
SYSWINETRICKS="winetricks"
REPLAY="replay-sorcery"
INNOEXTRACT="innoextract"
LSUSB="lsusb"
JQ="jq"
CONVERT="convert"
IDENTIFY="identify"
RSYNC="rsync"
CONTY="conty.sh"
SEVZA="7za"
PELDD="peldd"
PEPACK="pepack"
PERES="peres"
PESCAN="pescan"
PESEC="pesec"
PESTR="pestr"
READPE="readpe"
GDB="gdb"

CHECKHMD=1
X32D="x32dbg"
X64D="x64dbg"
FACO="favorites.conf"
MENSO="menusort.conf"
MENUBLOCK="menublock.conf"
DSHM="/dev/shm"
STLSHM="$DSHM/${PROGNAME,,}"
MTEMP="$STLSHM/menutemp"
STLICON="$STLSHM/${PROGNAME,,}-steam-checked.png"
NOICON="$STLSHM/empty.png"
FAVPIC="$STLSHM/fav.jpg"
DFDIR="$STLSHM/desktopfiles"
CLOSETMP="$STLSHM/${PROGNAME,,}-closing.tmp"
PROTBUMPTEMP="$STLSHM/protonbump.tmp"
KILLSWITCH="$STLSHM/KillSwitch"
TEMPLOG="$STLSHM/${PROGNAME,,}.log"
PRELOG="$STLSHM/prelog.log"
APPMALOG="$STLSHM/listAppManifests.log"
GGDLOG="$STLSHM/getGameData.log"
WINRESLOG="$STLSHM/winres.log"
SHADLOG="$STLSHM/shaderupdate.log"
GWIDFILE="$STLSHM/${PROGNAME,,}-sbsgwid"
PIDLOCK="$STLSHM/pid.lock"
GDBGAMERUN="$STLSHM/gdbgamerun.sh"
GDBRUN="$STLSHM/gdbrun.sh"
VRINITLOCK="$STLSHM/vrinit.lock"
IGCSINITLOCK="$STLSHM/igcsinit.lock"
VRINITRESULT="$STLSHM/vrinit.conf"
VWRUN="$STLSHM/vwrun.txt"
UUUPATCH="${PROGNAME,,}-uuu-patch"
UUUPATCHCOMMAND="$STLSHM/${UUUPATCH}.sh"
GCD="GameCfgDiffers"
OVFS="openvr_fsr"
OVRA="openvr_api.dll"
OVRMOD="openvr_mod.cfg"
GWXTEMP="$STLSHM/gamewinXID.txt"
TRAYCUSC="$STLSHM/customscript"
TEMPGPIDFILE="$STLSHM/gamepid.txt"
STLSETENTRIES="$STLSHM/setentries.txt"
STLRAWENTRIES="$STLSHM/rawentries.txt"
STLNOBLOCKENTRIES="$STLSHM/noblockentries.txt"
STLCATSORTENTRIES="$STLSHM/catsortentries.txt"
UPWINTMPL="$STLSHM/upwintmpl.txt"
STLMINWIN="$STLSHM/minwin.txt"
STLMENUVALBLOCKCFG="$STLSHM/$MENUBLOCK"
VARSIN="$STLSHM/vars-in.txt"
FUPDATE="$STLSHM/fupdate.txt"
STPAVARS="$STLSHM/steampaths.txt"
PROTONCSV="$STLSHM/ProtonCSV.txt"
NON="none"
NOPE="nope"
TMPL="template"
DLWINEVERSION="$NON"
GAMENAME="$NON"
EARLYUSEWINE=0
FAVMENU="$MTEMP/favmenu"
GAMEMENU="$MTEMP/gamemenu"
GAMETEMPMENU="$MTEMP/gametemplmenu"
GLOBALMENU="$MTEMP/globalmenu"
GAMMENU="Game Menu"
SETMENU="Settings Menu"
FAVOMENU="Favorite Menu"
LOSE="Local Settings"
APDA="Application Data"
APD="AppData"
ADRO="$APD/Roaming"
ADLO="$APD/Local"
ADLOLO="$APD/LocalLow"
EAGA="EA Games"
LAGA="Larian Studios"
BIOW="BioWare"
SAGE="Saved Games"
CDPR="CD Projekt Red"
LSAD="$LOSE/$APDA"
RUNCONTY="$NON"
WINX="800"
WINY="600"
F1ACTION="bash -c OpenWiki"
F1ACTIONCG="bash -c setColGui"
BTS="backup-timestamp"
DUMMYBIN="echo"
STLAIDSIZE="12"

### default vars ###

if [ -z "$XDG_CONFIG_HOME" ]; then
	STLCFGDIR="$HOME/.config/${PROGNAME,,}"													# either hardcoded config dir
else
	STLCFGDIR="$XDG_CONFIG_HOME/${PROGNAME,,}"												# or in XDG_CONFIG_HOME if the user set the variable
fi

SYSTEMSTLCFGDIR="$PREFIX/share/${PROGNAME,,}"												# systemwide config dir
BASELOGDIR="$STLCFGDIR/logs"																# base logfile dir
DEFLOGDIR="$BASELOGDIR/${PROGNAME,,}"																# default logfile dir

if [ -z "$LOGDIR" ]; then
	LOGDIR="$DEFLOGDIR"
fi

LOGDIRID="$LOGDIR/id"

LOGDIRTI="$LOGDIR/title"
STLPROTONLOGDIR="$BASELOGDIR/proton"														# proton logfile dir
STLPROTONIDLOGDIR="$STLPROTONLOGDIR/id"														# proton id logfile dir
STLPROTONTILOGDIR="$STLPROTONLOGDIR/title"													# proton title logfile dir
STLDXVKLOGDIR="$BASELOGDIR/dxvk"
STLWINELOGDIR="$BASELOGDIR/wine"															# wine logfile dir
STLVKD3DLOGDIR="$BASELOGDIR/vkd3d"
STLPVLOGDIR="$BASELOGDIR/pv"																# pressure vessel logfile dir
PLAYTIMELOGDIR="$BASELOGDIR/playtime"
STLGAMEDIR="$STLCFGDIR/gamecfgs"															# default basedir for game the gamespecific configs
STLGUIDIR="$STLCFGDIR/guicfgs"
STLGAMEDIRID="$STLGAMEDIR/id"
STLGAMEDIRTI="$STLGAMEDIR/title"
STLCATEGORYDIR="$STLCFGDIR/categories"														# the directory holding config files with preconfigured settings for games in specific steamcategories
STLREGDIR="$STLCFGDIR/regs"																	# the directory holding registry files
STLDLDIR="$STLCFGDIR/downloads"																# the directory holding optional downloads
STLBACKDIR="$STLCFGDIR/backup"
BACKEX="$STLBACKDIR/exclude"
HIDEDIR="$STLCFGDIR/hide"
CODA="compatdata"
STLCOMPDAT="$STLCFGDIR/$CODA"
METADIR="$STLCFGDIR/meta"
GEMETA="$METADIR/id/general"
CUMETA="$METADIR/id/custom"
EVMETAID="$METADIR/eval/id"
EVMETASKIPID="$EVMETAID/skip"
EVMETACUSTOMID="$EVMETAID/custom"
EVMETAADDONID="$EVMETAID/addon"
EVMETATITLE="$METADIR/eval/title"
EVMETAOLD="$METADIR/eval/old"
EVALSC="evaluatorscript"
GECUST="get-current-step"
ISCRI="iscriptevaluator"
LIINPA="linux_install_path"
STEWOS="Steamworks Shared"
LECO="legacycompat"
FRSTATE="$STLSHM/firuState.txt"
TIGEMETA="$METADIR/title/general"
TICUMETA="$METADIR/title/custom"
DRC="drive_c"
DRCU="$DRC/users"
DRCW="$DRC/windows"
STUS="steamuser"
SUBADIR="$STLBACKDIR/$STUS"
SUBADIRID="$SUBADIR/id"
SUBADIRTI="$SUBADIR/title"
RSSUB="reshade-shaders"
WTDLDIR="$STLDLDIR/winetricks"
DLWT="$WTDLDIR/src/winetricks"
STLSHADDIR="$STLDLDIR/shaders"
SHADREPOLIST="$STLSHADDIR/repolist.txt"
SHADERREPOBLOCKLIST="$STLSHADDIR/repoblocklist.txt"
TWEAKDIR="$STLCFGDIR/tweaks"																# the parent directory for all user tweakfiles
USERTWEAKDIR="$TWEAKDIR/user"																# the place for the users own main tweakfiles
TWEAKCMDDIR="$TWEAKDIR/cmd"																	# dir for scriptfiles used by tweakfiles
SBSTWEAKDIR="$TWEAKDIR/sbs"																	# directory for optional config overrides for easier side-by-side VR gaming
CEDLDIR="$STLDLDIR/cheatengine"
MO2DLDIR="$STLDLDIR/mo2"
CONTYDLDIR="$STLDLDIR/conty"
X64DBGDLDIR="$STLDLDIR/$X64D"
CUSTOMFALLBACKPIC="$STLDLDIR/custom-fallback.png"
STLCEDIR="$STLCFGDIR/cheatengine"
VTX="vortex"
VOGAT="${VTX}games.txt"
STLVORTEXDIR="$STLCFGDIR/$VTX"
VORTEXDLDIR="$STLDLDIR/$VTX"
VORTSETCMD="$STLSHM/vortset.cmd"
VTST="$STLSHM/vsetup.txt"
DEFDOTNETPROTON="Proton-6.17-STL-1"
SPEK="SpecialK"
SPEKDLDIR="$STLDLDIR/${SPEK,,}"
FWS="FlawlessWidescreen"
FWSDLDIR="$STLDLDIR/${FWS,,}"
YADAIDLDIR="$STLDLDIR/yadappimage"
DISC="discord"
DOTN="dotnet"
MO2="mo2"
STLMO2DIR="$STLCFGDIR/$MO2"
MO="ModOrganizer"
MORDIR="$DRC/Modding"
MOERPATH="$MORDIR/MO2/${MO}.exe"
DOCS="Documents"
MYDOCS="My $DOCS"
MYGAMES="My Games"
PLACEHOLDERAID="31337"
PLACEHOLDERGN="Placeholder"
DPRS="Depressurizer"
DPRSDLDIR="$STLDLDIR/${DPRS,}"
DEPS="Dependencies"
DEPSGE="${DEPS}Gui.exe"
DEPSDLDIR="$STLDLDIR/${DEPS,}"
DEPSLATDIR="$DEPSDLDIR/latest"
DEPSL64="$DEPSLATDIR/64/$DEPSGE"
DEPSL32="$DEPSLATDIR/32/$DEPSGE"
MAHU="mangohud"
MAHUCFGDIR="$STLCFGDIR/$MAHU"
MAHUCID="$MAHUCFGDIR/id"
MAHUCTI="$MAHUCFGDIR/title"
MAHUTMPL="$MAHUCFGDIR/$MAHU-${PROGNAME,,}-template.conf"
MAHULOGDIR="$BASELOGDIR/$MAHU"
MAHULID="$MAHULOGDIR/id"
MAHULTI="$MAHULOGDIR/title"
PFX86="Program Files (x86)"
PFX86S="$PFX86/Steam"
APIN="appinfo"
SLO="Steam Launch Option"
SOMEPOPULARWINEPAKS="dotnet4 quartz xact"
SOMEWINEDEBUGOPTIONS="-all,+steam,+vrclient,+vulkan"
SGDBDIMOPTS="600x900,342x482,660x930"
SGDBSTYOPTS="alternate,blurred,white_logo,material,no_logo"
GETSTAID="99[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]99"

STLGAMES="$STLCFGDIR/games"
STLGDESKD="$STLGAMES/desktop"
STLIDFD="$STLGAMES/desktopfiles"
STLISLDFD="$STLGAMES/sldesktopfiles"
STLAPPINFOIDDIR="$STLGAMES/$APIN"
STLGHEADD="$STLGAMES/header"
STLGSAD="$STLGAMES/standalone"
STLGICONS="$STLGAMES/icons"
STLGICO="$STLGICONS/ico"
STLGZIP="$STLGICONS/zip"
STLGPNG="$STLGICONS/png"
STLGSAPD="$STLGSAD/titles"
STLGSACD="$STLGSAD/$CODA"
STLGPEVKD="$STLGAMES/pev"

#STLGSCPTD="$STLGAMES/scripts"
NOGAMES=",70_2260196511,228980,858280,961940,1054830,1070560,1113280,1245040,1391110,1420170,"

#PROTON37="858280"
#PROTON316="961940"
#PROTON42="1054830"
#PROTON411="1113280"
#PROTON50="1245040"
#PROTON513="1420170"

function setGNID {
	# only keep alphabet chars
	INGN="$(tr -cd '[:alnum:]' <<< "${1^^}")"
	INGN="${INGN//[[:digit:]]/}"
	MIDNUMSIZE=$((STLAIDSIZE -4))

	if [ "${#INGN}" -gt "$MIDNUMSIZE" ]; then
		INGN="${INGN:0:MIDNUMSIZE}"
	fi

	while [ "${#INGN}" -lt "$MIDNUMSIZE" ]; do
		INGN="${INGN}A"
	done

	ALPHARR=(A B C D E F G H I J K L M N O P Q R S T U V W X Y Z)

	function numberOut {
		for n in "${!ALPHARR[@]}"; do
			if [ "${ALPHARR[$n]}" == "$1" ]; then
				NUM="$((n +1))"
				if [ "$NUM" -gt 9 ]; then
					printf "%s" "${NUM:1:1}"
				else
					printf "%s" "${NUM:0:1}"
				fi
			fi
		done
	}

	function outNum {
		i=0
		while [ "$i" -lt "${#1}" ]; do
			numberOut "${1:$i:1}"
			i=$((i+1))
		done
		printf "\n"
	}

	MIDNUM="$(outNum "$INGN")"
	echo "99${MIDNUM}99"
}

function initAID {
	STLPLAY=0
	if [ -n "$STEAM_COMPAT_APP_ID" ]; then
		AID="$STEAM_COMPAT_APP_ID"
		writelog "INFO" "${FUNCNAME[0]} - Set AID from STEAM_COMPAT_APP_ID to '$AID'" "P"
	fi

	if [ -z "$AID" ] || [ "$AID" -eq "0" ]; then
		# shellcheck disable=SC2154		# SteamAppId comes from Steam

		if [ -z "$SteamAppId" ]; then
			if grep -q "^play" <<< "$@" && [ -n "$2" ] && [ -z "$3" ] && [ "$2" != "gui" ] && [ "$2" != "ed" ]; then
				STLPLAY=1
				if [ "$2" -eq "$2" ] 2>/dev/null ; then
					AID="$2"
				elif [ -f "$2" ]; then
					GN="${2##*/}"
					AID="$(setGNID "$GN")"
				fi
				writelog "INFO" "${FUNCNAME[0]} - Set AID to '$PROGCMD' ID '$AID'" "P"
			elif grep -q "^play" <<< "$@" && [ -f "$3" ]; then
				STLPLAY=1
				GN="${3##*/}"
				AID="$2"	

				writelog "INFO" "${FUNCNAME[0]} - Set AID to '$PROGCMD' ID '$AID'" "P"
			else
				AID="$PLACEHOLDERAID"
				writelog "INFO" "${FUNCNAME[0]} - Set AID to PLACEHOLDERAID '$AID'" "P"
			fi
		else
			if [ "$SteamAppId" -eq "0" ]; then
				AID="${STEAM_COMPAT_DATA_PATH##*/}"
				writelog "INFO" "${FUNCNAME[0]} - Set AID from STEAM_COMPAT_DATA_PATH '$STEAM_COMPAT_DATA_PATH' to '${STEAM_COMPAT_DATA_PATH##*/}', because SteamAppId is '$SteamAppId'" "P"
			else
				AID="$SteamAppId"
				writelog "INFO" "${FUNCNAME[0]} - Set AID to SteamAppId '$SteamAppId' coming from Steam" "P"
			fi
		fi
	fi

	if [ -n "$STEAM_COMPAT_DATA_PATH" ]; then
		OSCDP="$STEAM_COMPAT_DATA_PATH"
		writelog "INFO" "${FUNCNAME[0]} - Set OSCDP to STEAM_COMPAT_DATA_PATH '$STEAM_COMPAT_DATA_PATH'" "P"
	fi
}

STLFAVMENUCFG="$STLCFGDIR/$FACO"															# optional config (in fact just a list with variables) which holds all entries for the individual favorites menu
STLMENUSORTCFG="$STLCFGDIR/$MENSO"															# holds the category sort order for all menus
STLMENUBLOCKCFG="$STLCFGDIR/$MENUBLOCK"
#STARTEDITORCFGLIST
STLDEFGLOBALCFG="$STLCFGDIR/global.conf"													# global config
STLDEFGAMECFG="$STLCFGDIR/default_template.conf"											# the default config template used to create new per game configs - will be auto created if not found

function setAIDCfgs {
STLGAMECFG="$STLGAMEDIRID/$AID.conf"														# the game specific config file which is used by the launched game - created from $STLDEFGAMECFG if not found
TWEAKCFG="$USERTWEAKDIR/$AID.conf"															# the game specific shareable config tweak overrides
SBSTWEAKCFG="$SBSTWEAKDIR/$AID.conf"														# the game specific shareable config sbs tweak overrides
LOGFILE="$LOGDIRID/$AID.log"																	
}
STLURLCFG="$STLCFGDIR/url.conf"																# url config
CUSTOMPROTONLIST="$STLCFGDIR/protonlist.txt"												# plain textfile with additional user proton versions
VORTEXSTAGELIST="$STLVORTEXDIR/stages.txt"													# plain textfile with Vortex Stage directories - one per Steam Library partition
SEENVORTEXGAMES="$STLVORTEXDIR/$CODA/seen$VOGAT"
EXGLOB="$BACKEX/exclude-global.txt"
#ENDEDITORCFGLIST

STLLANGDIR="$STLCFGDIR/lang"
STLDEFLANG="english"

STLDXVKDIR="$STLCFGDIR/dxvk"																# base dxvk config dir from where default per game configs are automatically parsed
ISGAME=0																					# 1=game was launched, 2=windows game, 3=linux game
WFEAR="waitforexitandrun"
SA="steamapps"
SAC="$SA/common"
L2EA="link2ea"
CTD="compatibilitytools.d"
USS="/usr/share/steam"
SYSSTEAMCOMPATOOLS="$USS/$CTD"
SLR="SteamLinuxRuntime"
STERU="steam-runtime"
BIWI="bin/wine"
DBW="dist/$BIWI"
FBW="files/$BIWI"
STLPROTDIR="$STLCFGDIR/proton"
STLPROTCOMPDATDIR="$STLPROTDIR/$CODA"
STLPROTSTUSDIR="$STLPROTDIR/$STUS"
STLEARLYPROTCONF="$STLPROTDIR/earlyproton.conf"
PROCU="proton/custom"
CTVDF="compatibilitytool.vdf"
LIFOVDF="libraryfolders.vdf"
SCV="sharedconfig.vdf"
AIVDF="$APIN.vdf"
AITXT="$APIN.txt"
AAVDF="appcache/$AIVDF"
APVDF="appcache/packageinfo.vdf"
USDA="userdata"
SCVDF="shortcuts.vdf"
SRSCV="7/remote/$SCV"
LCV="localconfig.vdf"
COCOV="config/config.vdf"
SCSHVDF="screenshots.vdf"
SCRSH="760/$SCSHVDF"
LASTRUN="$LOGDIR/lastrun.txt"
SAIT="steam_appid.txt"
DXGI="dxgi.dll"
D3D9="d3d9.dll"
D3D47="d3dcompiler_47.dll"
OGL32="opengl32.dll"
D3D47DLDIR="$STLDLDIR/${D3D47%.*}"
SOMEWINEDLLOVERRIDES="dxgi=n,b;d3d9=n,b;${D3D47//.dll}=n,b"
RS_DX_DEST="$DXGI"
RS_D9_DEST="$D3D9"
RESH="ReShade"
RSSU="${RESH}_Setup"
RSINI="${RESH}.ini"
RSTXT="${RESH}.txt"
IGCS="IGCSInjector"
UUU="UniversalUE4Unlocker"
LFM="launchFavMenu"
LGAM="launchGameMenu"
LGATM="launchGameTemplateMenu"
LGLM="launchGlobalMenu"
LCM="launchCategoryMenu"
CE="Cheat Engine"
HEADLINEFONT="larger"
FONTSIZES="!xx-small!x-small!small!smaller!medium!large!larger!!x-large!xx-large!"
HAVEINNO="1"
SREG="system.reg"
NSGA="non-steam game"
BTVP="$DRC/Program Files/Black Tree Gaming Ltd/${VTX^}"
VTXRAA="resources/app.asar"
RABP="${VTXRAA}.unpacked/bundledPlugins"

# make SC happy:
GUI_GAMCON=""
GUI_CUSTOMCMD=""
################

function setSteamPath {
	HSR="$HOME/.steam/root"
	HSS="$HOME/.steam/steam"

	if [ -z "${!1}" ]; then
		if [ -e "${HSR}/${2}" ]; then
			# readlink might be better in both STPAs here to be distribution independant, possible side effects not tested!
			STPA="$(readlink -f "${HSR}/${2}")"
			export "$1"="$STPA"
			echo "$1=\"$STPA\"" >> "$STPAVARS"
			writelog "INFO" "${FUNCNAME[0]} - Set '$1' to '$STPA'"
		elif [ -e "${HSS}/${2}" ]; then
			STPA="$(readlink -f "${HSS}/${2}")"
			export "$1"="$STPA"
			echo "$1=\"$STPA\"" >> "$STPAVARS"
			writelog "INFO" "${FUNCNAME[0]} - Set '$1' to '$STPA'"
		else
			writelog "WARN" "${FUNCNAME[0]} - '$2' not found for variable '$1' in '$HSR' or '$HSS'!"
		fi	
	else
		writelog "SKIP" "${FUNCNAME[0]} - '$1' already defined as '${!1}'"
		echo "$1=\"${!1}\"" >> "$STPAVARS"
	fi
}

function setSteamPaths {
	if [ -f "$STPAVARS" ] && grep -q "^SUSDA" "$STPAVARS" ; then
		writelog "INFO" "${FUNCNAME[0]} - Reading Steam Path variables from '$STPAVARS'"
		loadCfg "$STPAVARS" X
	else
		setSteamPath "SROOT"
		mkProjDir "$SROOT/$CTD"
		setSteamPath "SUSDA" "$USDA"
		setSteamPath "DEFSTEAMAPPS" "$SA"
		setSteamPath "DEFSTEAMAPPSCOMMON" "$SAC"
		setSteamPath "CFGVDF" "$COCOV"
		setSteamPath "LFVDF" "$SA/$LIFOVDF"
		setSteamPath "FAIVDF" "$AAVDF"
		setSteamPath "PIVDF" "$APVDF"
		setSteamPath "STEAMCOMPATOOLS" "$CTD"
		setSteamPath "ICODIR" "steam/games"

		if [ -z "$STEAM_COMPAT_CLIENT_INSTALL_PATH" ]; then
			export STEAM_COMPAT_CLIENT_INSTALL_PATH="$SROOT"
			echo "STEAM_COMPAT_CLIENT_INSTALL_PATH=\"$SROOT\"" >> "$STPAVARS"
		fi

		if [ -f "$STLDEFGLOBALCFG" ] && grep -q "^STEAMUSERID=" "$STLDEFGLOBALCFG" ; then
			STEAMUSERID="$(grep "^STEAMUSERID=" "$STLDEFGLOBALCFG" | grep -o "[[:digit:]]*")"
			STUIDPATH="$SUSDA/$STEAMUSERID"
		else
			if [ -d "$SUSDA" ]; then
			# this works for 99% of all users, because most do have 1 steamuser on their system
				STUIDPATH="$(find "$SUSDA" -maxdepth 1 -type d -name "[1-9]*" | head -n1)"
				STEAMUSERID="${STUIDPATH##*/}"
			else
				writelog "WARN" "${FUNCNAME[0]} - Steam '$USDA' directory not found, other variables depend on it - Expect problems" "E"
			fi
		fi

		SUIC="$STUIDPATH/config"
		FLCV="$SUIC/$LCV"

		{
		echo "STUIDPATH=\"$STUIDPATH\""
		echo "STEAMUSERID=\"$STEAMUSERID\""
		echo "SUIC=\"$SUIC\""
		echo "FLCV=\"$FLCV\""
		} >> "$STPAVARS"

		writelog "INFO" "${FUNCNAME[0]} - Found SteamUserId '$STEAMUSERID'"
	fi
}

function setAwkBin {
	if [ -z "$AWKBIN" ];then
		if [ -x "$(command -v "gawk")" ]; then
			AWKBIN="gawk"
			if [ -z "$1" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Found '$AWKBIN' as an 'awk' variant. It should work without any issues, because 'gawk' was tested completely"
			fi
		elif [ -x "$(command -v "mawk")" ]; then
			AWKBIN="mawk"
			if [ -z "$1" ]; then
				writelog "WARN" "${FUNCNAME[0]} - Only found '$AWKBIN' as an 'awk' variant. It might be incompatible in several functions, as only 'gawk' was tested completely!"
			fi
		elif [ -x "$(command -v "awk")" ]; then
			AWKBIN="mawk"
			if [ -z "$1" ]; then
				writelog "WARN" "${FUNCNAME[0]} - Only found '$AWKBIN' as an 'awk' variant. It might be incompatible in several functions, as only 'gawk' was tested completely!"
			fi
		fi	
		
		if [ -z "$AWKBIN" ];then
			writelog "ERROR" "${FUNCNAME[0]} - No 'awk' variant found, but at least one is required (best would be 'gawk') - Can't continue" "E"
			exit
		else
			export AWKBIN="$AWKBIN"
		fi
	fi
}

function awk {
	if [ -z "$AWKBIN" ];then
		setAwkBin "X"
	fi
	"$AWKBIN" "$@"
}

function OpenWikiPage {
	if [ -n "$1" ]; then
		if grep -q "$PPW" <<< "$1"; then
			WIKURL="$1"
		else
			WIKURL="$PPW/$1"
		fi
	else
		if [ -n "$CURWIKI" ]; then
			WIKURL="$CURWIKI"
		fi
	fi
	
	if [ -n "$WIKURL" ]; then
		TITLE="${PROGNAME}-Wiki"
		pollWinRes "$TITLE"
		"$YAD" --window-icon="$STLICON" --title="$TITLE" --on-top --center "$WINDECO" --html --uri="$WIKURL" "$GEOM" >/dev/null 2>/dev/null	
	fi
}

function OpenWiki {
	"${PROGCMD}" wiki "$CURWIKI"
}

export -f OpenWiki

function StatusWindow {
	YAD=yad
    TITLE="${PROGNAME}-$3"
    pollWinRes "$TITLE"
	writelog "INFO" "${FUNCNAME[0]} - for '$1'"

    RUNFUNC="$2"
    $RUNFUNC |
    while read -r line; do
		echo "# ${line}";
	done | "$YAD" --window-icon="$STLICON" --title="$TITLE" --on-top --progress --progress-text="$1..." --pulsate --center --no-buttons --auto-close "$WINDECO" "$GEOM"
}

function setColGui {
	HAVCOL=0
	if grep -q "^COLCOUNT" "$CURGUICFG"; then
		CCR="$(grep "^COLCOUNT" "$CURGUICFG" | cut -d '=' -f2)"
		CURCOL="${CCR//\"}"
		HAVCOL=1
	else
		CURCOL=1
	fi

	export CURWIKI="$PPW/Gui-Columns"

	TITLE="${FUNCNAME[0]}"
	WTR="${CURGUICFG##*/}"
	WINTITLE="${WTR//.conf}"
	SELCOL="$("$YAD" --f1-action="$F1ACTION" --center --form --separator="\n" --field="Columns in $WINTITLE":NUM "$CURCOL" --title="$TITLE" "$GEOM")"
	
	if [ -z "$SELCOL" ] || [ "$SELCOL" -eq 0 ]; then
		SELCOL=1
	fi

	if [ "$HAVCOL" -eq 0 ]; then
		echo "COLCOUNT=\"$SELCOL\"" >> "$CURGUICFG"
	else
		if [ "$CURCOL" -ne "$SELCOL" ]; then
			sed "s:COLCOUNT=\"$CURCOL\":COLCOUNT=\"$SELCOL\":g" -i "$CURGUICFG"
		fi
	fi
}
export -f setColGui

function dlCheck {
	function chkFile {
		if [ "$FLCHK" == "stat" ]; then
			ISCHK="$("$FLCHK" -c%s "$DLDST" | cut -d ' ' -f1)"
		else
			ISCHK="$("$FLCHK" "$DLDST" | cut -d ' ' -f1)"
		fi
		CHKTXT="$(strFix "$NOTY_CHK" "$FLCHK" "$DLDST")"
		writelog "INFO" "${FUNCNAME[0]} - $CHKTXT"
		notiShow "$CHKTXT" "S"

		if [ "$ISCHK" == "$INCHK" ];then
			CHKTXT="$(strFix "$NOTY_CHKOK" "$FLCHK" "${DLDST##*/}" "$ISCHK")"
			writelog "INFO" "${FUNCNAME[0]} - $CHKTXT"
			notiShow "$CHKTXT" "S"
		else
			CHKTXT="$(strFix "$NOTY_CHKNOK" "${DLDST##*/}" "$ISCHK" "$INCHK")"
			writelog "WARN" "${FUNCNAME[0]} - $CHKTXT"
			notiShow "$CHKTXT" "S"
		fi
		sleep 2
	}

	DLSRC="$1"
	DLDST="$2"
	FLCHK="$3"
	DLTITLE="$4"
	INCHK="$5"

	if [ "$FLCHK" != "C" ]; then
		if [ -f "$DLDST" ] && [ "$FLCHK" != "X" ]; then
			chkFile
		else
			if [ "$DLTITLE" != "$NON" ]; then
				writelog "INFO" "${FUNCNAME[0]} - $DLTITLE"
				notiShow "$(strFix "$NOTY_DLCUSTOMPROTON" "$DLDST")" "S"
				writelog "INFO" "${FUNCNAME[0]} - '$WGET -q --show-progress $DLSRC -O $DLDST'"
				"$WGET" -q --show-progress "$DLSRC" -O "$DLDST" 2>&1 | sed -u -e "s:\.::g;s:.*K::g;s:^[[:space:]]*::g"
			else
				"$WGET" -q "$DLSRC" -O "$DLDST" 1>/dev/null 2>&1 
			fi
		fi
	else
		FLCHK="$1"
		DLDST="$2"
		INCHK="$4"
		writelog "INFO" "${FUNCNAME[0]} - Only checking already downloaded file '$DLDST'"
		chkFile
	fi

	if [ -n "$INCHK" ] && [ "$INCHK" != "$NON" ]; then
		if [ "$FLCHK" == "X" ]; then
			notiShow "$(strFix "$NOTY_DLCUSTOMPROTON2" "$DLDST")" "S"
			writelog "INFO" "${FUNCNAME[0]} - $(strFix "$NOTY_DLCUSTOMPROTON2" "$DLDST")"
		elif [ "$FLCHK" != "C" ]; then
			chkFile
		fi
	fi
}

function getGamePic {
	if [ "$DLGAMEDATA" -eq 1 ] && [ "$STLPLAY" -eq 0 ]; then
		DLPIC="$1"
		if [ ! -f "$DLPIC" ] && [ "$STLPLAY" -eq 0 ]; then
			DLTITLE="Downloading picture for game '$(basename "${1//.jpg/}")'"
			dlCheck "$2" "$DLPIC" "X" "$DLTITLE"
		fi
	fi
}

function getGameName {
	if [ -n "$GN" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Using 'GN' as Game Name: '$GN'"
		GNRAW="$GN"
	elif [ -f "$STLGAMEDIRID/$1.conf" ]; then
		GNRAW="$(grep "#GAMENAME" "$STLGAMEDIRID/$1.conf" | cut -d '=' -f2)"
		writelog "INFO" "${FUNCNAME[0]} - Found Game Name '$GNRAW' in '$STLGAMEDIRID/$1.conf'"
	elif grep -q "_${1}\." <<< "$(listAppManifests)" ; then
		APPMA="$(grep "_${1}\." <<< "$(listAppManifests)")"
		if [ -f "$APPMA" ]; then
			GNRAW1="$(grep "\"name\"" "$APPMA" | awk -F '"name"' '{print $NF}')"
			GNRAW="$(awk '{$1=$1};1' <<< "$GNRAW1")"
			writelog "INFO" "${FUNCNAME[0]} - Found Game Name '$GNRAW' in '$APPMA'"
		else
			writelog "SKIP" "${FUNCNAME[0]} - file '$APPMA' not found"
		fi
	elif [ -f "$STLAPPINFOIDDIR/${1}.bin" ]; then
		GNRAW="$(getAppInfoData "$AID" "name")"
		writelog "INFO" "${FUNCNAME[0]} - Found Game Name '$GNRAW' in '$STLAPPINFOIDDIR/${1}.bin'"
	else
		if [ "$DLGAMEDATA" -eq 1 ]; then
			APIURL="https://api.steampowered.com/ISteamApps/GetAppList/v2"
			APIDL="$STLDLDIR/SteamApps.json"
			MAXAGE=1440
			writelog "INFO" "${FUNCNAME[0]} - Downloading gamedata for '$1'"

			if [ ! -f "$APIDL" ] || test "$(find "$APIDL" -mmin +"$MAXAGE")"; then
				dlCheck	"$APIURL" "$APIDL" "X" "Downloading $APIDL"
			fi
		fi

		if [ -f "$APIDL" ]; then
			if [ ! -x "$(command -v "$JQ")" ]; then
				writelog "WARN" "${FUNCNAME[0]} - Can't get data from '$APIDL' because '$JQ' is not installed"
			else
				writelog "INFO" "${FUNCNAME[0]} - Searching Game Name for '$1' in $APIDL"
				GNRAW="$("$JQ" ".applist.apps[] | select (.appid==$1) | .name" "$APIDL")"
				
				if [ -n "$GNRAW" ]; then
					writelog "INFO" "${FUNCNAME[0]} - Found Game Name '$GNRAW' in $APIDL"
				fi
			fi
		else
			writelog "SKIP" "${FUNCNAME[0]} - file '$APIDL' not found"
		fi
	fi
	writelog "INFO" "${FUNCNAME[0]} - Outgoing game name is '${GNRAW//\"/}'"

	GAMENAME="${GNRAW//\"/}"
}

function writeDesktopFile {
	DESTDTF="$2"
	DESTPIC="$3"

	if [ -f "$DESTDTF" ]; then
		writelog "SKIP" "${FUNCNAME[0]} - $DESTDTF already exists"
	else
		getGameName "$1"
		if [ -z "$GAMENAME" ]; then
			writelog "SKIP" "${FUNCNAME[0]} - Could not find gamename for game id '$1'"
		elif [ -n "$GAMENAME" ] && [ "$GAMENAME" != "$NON" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Creating '$DESTDTF' for '$GAMENAME' ($1)"
			{
				echo "[Desktop Entry]"
				echo "Name=${GAMENAME//\"/}"
				echo "Comment=$DF_COMMENT"
				echo "Exec=steam steam://rungameid/$1"
				echo "Icon=$DESTPIC"
				echo "Terminal=false"
				echo "Type=Application"
				echo "Categories=Game;"
			} >> "$DESTDTF"
		fi
	fi
}

function createDesktopIconFile {
	
	if [ "$1" -eq "$1" ] 2>/dev/null; then
		AID="$1"
	else
		AID="$(getIDFromTitle "$1")"
	fi

	WANTGPNG="$STLGPNG/${AID}.png"

	if [ "$STLPLAY" -eq 1 ]; then
		mkProjDir "$STLISLDFD"
		INTDTFILE="$STLISLDFD/$AID.desktop"
	else
		mkProjDir "$STLIDFD"
		INTDTFILE="$STLIDFD/$AID.desktop"
	fi

	if [ -f "$INTDTFILE" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Already have an internal desktop file '$INTDTFILE'"
	else
		if [ -n "$AID" ] && [ ! -f "$WANTGPNG" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Don't have a desktop icon yet - trying to create it"
			if [ "$STLPLAY" -eq 1 ]; then
				if [ -n "$4" ]; then
					GAMENAME="$3"
					HAVEPA="$4"
					standaloneGameIcon "$WANTGPNG" "$AID" "$GAMENAME" "$HAVEPA"
				else
					writelog "WARN" "${FUNCNAME[0]} - Not enough arguments passes to create an icon - got '$*'"
				fi
			else
				getGameIcon
			fi
		fi

		# create desktop file internally for optionally using it on the desktop
		if [ -f "$WANTGPNG" ] && [ ! -f "$INTDTFILE" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Creating $INTDTFILE"
			if [ "$STLPLAY" -eq 1 ]; then
				if [ -n "$4" ]; then
					GAMENAME="$3"
					HAVPA="$4"
					standaloneDesktopFile "$INTDTFILE" "$WANTGPNG" "$AID" "$GAMENAME" "$HAVEPA"
				else
					writelog "WARN" "${FUNCNAME[0]} - Not enough arguments passes to create a desktopfile - got '$*'"
				fi
			else
				writeDesktopFile "$AID" "$INTDTFILE" "$WANTGPNG"
			fi
		fi
	fi

	# set desktop file mode from command line:
	if [ -f "$INTDTFILE" ] && [ "$CREATEDESKTOPICON" -eq 0 ] && [ -n "$2" ]; then
		CREATEDESKTOPICON="$2"
	fi

	# copy the desktop file to the system
	if [ -f "$INTDTFILE" ] && [ "$CREATEDESKTOPICON" -ne 0 ]; then
		if [ "$CREATEDESKTOPICON" -eq "1" ] || [ "$CREATEDESKTOPICON" -eq "3" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Creating desktop icon for '$AID' on the desktop"
			cp "$INTDTFILE" "$HOME/Desktop/" 2>/dev/null
		fi

		if [ "$CREATEDESKTOPICON" -eq "2" ] || [ "$CREATEDESKTOPICON" -eq "3" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Creating desktop icon for '$AID' for the desktop application menu"
			cp "$INTDTFILE" "$HOME/.local/share/applications/" 2>/dev/null	
		fi	
	fi
}

function getOwnedHexAids {
	if [ -z "$PIVDF" ]; then
		setSteamPaths
	fi

	if [ -f "$PIVDF" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Searching in '$PIVDF' for HexAids"
		HAIDS="61707069647300023000"
		"$XXD" -c "$(wc -c "$PIVDF")" -p "$PIVDF" | sed -E "s:$HAIDS:\n$HAIDS:g" | grep -o "$HAIDS.\{0,6\}" | sed "s:$HAIDS::"
	else
		writelog "SKIP" "${FUNCNAME[0]} - '$PIVDF' not found"
	fi	
}

function getOwnedAids {
	mkProjDir "$STLSHM"
	OAIDLIST="$STLSHM/owned-aids.txt"
	if [ ! -f "$OAIDLIST" ]; then
		while read -r line; do
			getAidFromHexAid "$line" >> "$OAIDLIST"
		done <<< "$(getOwnedHexAids)"
		
		sort -n -u "$OAIDLIST" -o "$OAIDLIST"
	fi
	
	if [ -f "$OAIDLIST" ]; then
		cat "$OAIDLIST"
	fi
}

function getAidFromHexAid {
	unset REVAID
	while read -r line; do
		REVAID="$REVAID${line}"
	done <<< "$(fold -2 <<< "$1" | tac)"
	printf "%d\n" "0x$REVAID"
}

function getHexAidForAid {
	unset HEXAID
	if [ -f "$GEMETA/$1.conf" ]; then
		loadCfg "$GEMETA/$1.conf" X
	fi
		
	if [ -n "$HEXAID" ]; then
		if [ -z "$2" ]; then
			echo "$HEXAID"
		fi
	else
		HXTST="$(printf '%x\n' "$1" | fold -w2 | tail -n1)"

		if [ "${#HXTST}" -eq 1 ]; then
			SHEX1="$(printf '0%x\n' "$1" | fold -w2 | tac)";
		else
			SHEX1="$(printf '%x\n' "$1" | fold -w2 | tac)";
		fi

		while read -r line; do
			HEXAID="$HEXAID${line}"
		done <<< "$SHEX1"
		
		if [ -z "$2" ]; then
			echo "$HEXAID"
		fi
		touch "$FUPDATE"
		touch "$GEMETA/$1.conf"
		updateConfigEntry "HEXAID" "$HEXAID" "$GEMETA/$1.conf"
	fi
}

function getRawAppIDInfo {
	AIIDRAW="$STLAPPINFOIDDIR/${1}.bin"

	if [ -z "$FAIVDF" ]; then
		setSteamPaths
	fi
	
	if [ -z "$LOGRAWINFO" ]; then
		LOGRAWINFO=1
	fi
	
	if [ -s "$AIIDRAW" ] && [ -z "$2" ]; then
		if [ -z "$LOGRAWINFO" ]; then
			LOGRAWINFO=1
		fi

		if [ "$LOGRAWINFO" -eq 1 ]; then
			writelog "INFO" "${FUNCNAME[0]} - Found raw $APIN file '$AIIDRAW'"
		fi
	else
		if [ -n "$2" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Updating raw $APIN file '$AIIDRAW'"
		fi

		if [ ! -s "$AIIDRAW" ]; then
			rm "$AIIDRAW" 2>/dev/null
		fi

		HEXAID="$(getHexAidForAid "$1")"
		HAID="02617070696400"
	
		SHMAIVDF="$STLSHM/${AIVDF//\.vdf/\.hex}"
		if [ ! -f "$SHMAIVDF" ]; then
			"$XXD" -c "$(wc -c "$FAIVDF")" -p "$FAIVDF" "$SHMAIVDF"
		fi
		sed -E "s:$HAID:\n$HAID:g" "$SHMAIVDF" | grep "^${HAID}${HEXAID}00" | "$XXD" -r -p - "$AIIDRAW"
	fi
}

function getAppInfoData {
	# $1=AID; $2=category; optional $3=skip stdout; optional $4=force writing metadata again
	if [ -n "$2" ] && [ "$STLPLAY" -eq 0 ]; then
		AILIST="$GLOBALMISCDIR/$AITXT"

		if grep -q "$2" "$AILIST"; then

			UPDAT="${2^^}"
			unset "$UPDAT"

			if [ -f "$GEMETA/$1.conf" ]; then
				loadCfg "$GEMETA/$1.conf" X
			fi
			
			if [ -n "${!UPDAT}" ] && [ -z "$4" ]; then
				if [ -z "$3" ]; then
					writelog "INFO" "${FUNCNAME[0]} - Got value '${!UPDAT}' for '$UPDAT' from '$GEMETA/$1.conf'"
					echo "${!UPDAT}"
				fi
			else
				LOGRAWINFO=0
				getRawAppIDInfo "$1"
				SRCHEX="$STLAPPINFOIDDIR/$1.bin"

				if [ -f "$SRCHEX" ]; then
					if [ -z "$3" ]; then
						writelog "INFO" "${FUNCNAME[0]} - Retrieving data for '$2' from '$SRCHEX'"
					fi

					HVAR="$(echo -n "$2" | "$XXD" -ps)"
					unset HXOUT

					if [ "$2" == "metacritic_score" ]; then
						UPVALHX="$("$XXD" -c "$(wc -c "$SRCHEX")" -p "$SRCHEX" | sed -E "s:$HVAR:\n$HVAR:g" | grep "^$HVAR" | head -c "$(( $(wc -c <<< "$HVAR") + 3))" | tail -c2)"
						if [ -n "$UPVALHX" ]; then
							UPVAL="$((16#$UPVALHX))"
						fi
					else
						OCOUNT=0
						ZCOUNT=0
						while read -r line; do
							if [ "$line" == "01" ]; then
								OCOUNT=$((OCOUNT+1))
								if [[ "$OCOUNT" -eq 2 ]]; then
									break
								fi
							elif [ "$line" == "00" ] ; then
								ZCOUNT=$((ZCOUNT+1))
								if [[ "$ZCOUNT" -eq 2 ]]; then
									break
								fi
							else
								HXOUT="$HXOUT$line"
							fi
						done <<< "$("$XXD" -c "$(wc -c "$SRCHEX")" -p "$SRCHEX" | sed -E "s:01$HVAR:\n01$HVAR:g" | grep "^01$HVAR" | fold -2)"
						UPVALHX="${HXOUT//${HVAR}00/}"
						UPVALHX1="${UPVALHX//${HVAR}/}"
						UPVALHXO="${UPVALHX1%*00}"				
						
						UPVAL="$("$XXD" -r -p - <<< "$UPVALHXO")"
					fi

					if [ -n "$UPVAL" ]; then
						touch "$FUPDATE"
						touch "$GEMETA/$1.conf"
						updateConfigEntry "$UPDAT" "$UPVAL" "$GEMETA/$1.conf"
						if [ -z "$3" ]; then
							echo "$UPVAL"
						fi
					fi
				fi
			fi
		else
			writelog "SKIP" "${FUNCNAME[0]} - '$2' is not in '$AILIST'"
		fi
	fi
}

function writeAllAIMeta {
	if [ -n "$1" ] && [ "$1" -eq "$1" ]; then
		if [ -n "$2" ]; then
			rm "$STLAPPINFOIDDIR/${1}.bin" 2>/dev/null
		fi
		AILIST="$GLOBALMISCDIR/$AITXT"
		while read -r line; do
		 	getAppInfoData "$1" "$line" X "$2"
		done < "$GLOBALMISCDIR/$AITXT"
	else
		writelog "SKIP" "${FUNCNAME[0]} - need SteamAppId as arg 1"
	fi
}

function getGameIcon {
	function IcotoPng {
		if [ -x "$(command -v "$CONVERT" 2>/dev/null)" ]; then
			if [ -x "$(command -v "$IDENTIFY" 2>/dev/null)" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Determining largest ico in '$WANTGICO' using '$IDENTIFY'"
				LICO="$("$IDENTIFY" "$WANTGICO" | sort -n -k3 | tail -n1 | grep -oP '\[\K[^\]]+')"
			else
				writelog "INFO" "${FUNCNAME[0]} - Command '$IDENTIFY' not found, using first ico in '$WANTGICO'"
				LICO="0"
			fi

			if [ -z "$LICO" ] || [ "$LICO" -ne "$LICO" ] 2>/dev/null; then
				writelog "INFO" "${FUNCNAME[0]} - No specific ico found using the first one in '$WANTGICO'"
				LICO="0"		
			fi

			if [ "$LICO" -eq "$LICO" ] 2>/dev/null; then
				writelog "INFO" "${FUNCNAME[0]} - Converting ico '$LICO' in '$WANTGICO' to '$WANTGPNG' using command: $CONVERT ${WANTGICO}[${LICO}] $WANTGPNG"
				"$CONVERT" "${WANTGICO}[${LICO}]" "$WANTGPNG"
			fi
		else
			writelog "SKIP" "${FUNCNAME[0]} - Command '$CONVERT' not found, so converting '$WANTGICO' to '$WANTGPNG' is not possible - skipping"
		fi	
	}

	function getIco {
		WANTGICO="$STLGICO/${AID}.ico"
		if [ -f "$WANTGICO" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Already have game ico '$WANTGICO'"
			IcotoPng
		else
			ICONAME="$(getAppInfoData "$AID" "clienticon")"
			if [ -n "$ICONAME" ]; then
				ICOPATH="$ICODIR/${ICONAME}.ico"
				if [ -f "$ICOPATH" ]; then
					writelog "INFO" "${FUNCNAME[0]} - Found ico for '$AID' under '$ICOPATH'"
					cp "$ICOPATH" "$WANTGICO"
					IcotoPng
				else
					writelog "SKIP" "${FUNCNAME[0]} - Absolute path for Steam ico '$ICONAME' not valid - skipping"
				fi
			else
				writelog "SKIP" "${FUNCNAME[0]} - Could not find the icon name for '$AID' in $APIN - skipping"
			fi
		fi		
	}
	
	function extractGZip {
		BIGGESTPNG="$("$UNZIP" -l "$WANTGZIP" | grep "\.png" | sort -n | tail -n1 | awk -F ':[0-9][0-9]   ' '{print $NF}')" # weak 'awk' might break here(?)
		if [ -n "$BIGGESTPNG" ];then
			writelog "INFO" "${FUNCNAME[0]} - Extracting biggest png file '$BIGGESTPNG' in archive '$WANTGZIP' to '$WANTGPNG'"
			writelog "INFO" "${FUNCNAME[0]} - $UNZIP -dqq ${WANTGPNG//.png} $WANTGZIP $BIGGESTPNG"
			"$UNZIP" -q -d "${WANTGPNG//.png}" "$WANTGZIP" "$BIGGESTPNG"
			mv "${WANTGPNG//.png}/$BIGGESTPNG" "$WANTGPNG"
			rm -rf "${WANTGPNG//.png}"
		else
			writelog "SKIP" "${FUNCNAME[0]} - Could not determine the biggest png file in archive '$WANTGZIP'- skipping"
		fi
	}

	if [ -z "$AID" ]; then
		writelog "SKIP" "${FUNCNAME[0]} - Don't have a Steam gameid - skipping"
	else
		WANTGPNG="$STLGPNG/${AID}.png"
		if [ -f "$WANTGPNG" ]; then
			writelog "Info" "${FUNCNAME[0]} - Already have game icon png '$WANTGPNG' - nothing to to"
		else
			if [ -z "$ICODIR" ]; then
				setSteamPaths
			fi
			
			if [ ! -d "$ICODIR" ]; then
				writelog "SKIP" "${FUNCNAME[0]} - Steam ico directory not found - skipping"
			else
				WANTGZIP="$STLGZIP/${AID}.zip"
				if [ -f "$WANTGZIP" ]; then
					writelog "INFO" "${FUNCNAME[0]} - Already have game icon zip '$WANTGZIP' - extracting"
					extractGZip "$WANTGZIP" "$WANTGPNG"
				else
					writelog "INFO" "${FUNCNAME[0]} - Looking for icon hash in $APIN"
					
					LICONZIP="$(getAppInfoData "$AID" "linuxclienticon")"
					if [ -n "$LICONZIP" ]; then
						LICONPATH="$ICODIR/${LICONZIP}.zip"
						if [ -f "$LICONPATH" ]; then
							writelog "INFO" "${FUNCNAME[0]} - Found icon zip for '$AID' under '$LICONPATH'"
							cp "$LICONPATH" "$WANTGZIP"
							extractGZip "$WANTGZIP" "$WANTGPNG"
						else
							writelog "INFO" "${FUNCNAME[0]} - Absolute path for Steam icon zip '$LICONZIP' not valid - trying to find ico instead"
							getIco
						fi
					else
						writelog "SKIP" "${FUNCNAME[0]} - Could not find the icon zip for '$AID' in $APIN - trying to find ico instead"
						getIco
					fi
				fi
			fi
		fi
	fi
}

function getGameData {
	if ! grep -q ",${1}," <<< "$NOGAMES" && [ "$STLPLAY" -eq 0 ]; then
		DLPIC="$STLGHEADD/$1.jpg"
		if [ ! -f "$DLPIC" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Downloading picture '$DLPIC' from '$STASSURL/$1/header.jpg'" "X" "$GGDLOG"
			getGamePic "$DLPIC" "$STASSURL/$1/header.jpg"
		fi

		DESTDTF="$STLGDESKD/$1.desktop"
		if [ ! -f "$DESTDTF" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Creating desktopfile '$DESTDTF'" "X" "$GGDLOG"
			writeDesktopFile "$1" "$DESTDTF" "$DLPIC"
		fi
	fi
}

function getParsableGameList {
	if [ -z "$SUSDA" ] || [ -z "$STUIDPATH" ]; then
		setSteamPaths
	fi
	if [ -d "$SUSDA" ]; then
		SC="$STUIDPATH/$SRSCV"
		APPI="Apps"
		APPO="StartMenuShortcutCheck"
		LIST="$(awk "/$APPI/,/$APPO/" "$SC" | grep -v "$APPI\|$APPO" | awk '{printf "%s+",$0} END {print ""}' | sed 's/"[0-9][0-9]/\n&/g')"
		LISTCNT="$(wc -l <<< "$LIST")"
		writelog "INFO" "${FUNCNAME[0]} - Found '$LISTCNT' parsable Game Entries in '$SC'"
		if [ "$LISTCNT" -eq 0 ]; then
			writelog "SKIP" "${FUNCNAME[0]} - No game found in any Steam category"
		fi
		echo "$LIST"
	else
		writelog "SKIP" "${FUNCNAME[0]} - '$SUSDA' not found - this should not happen! - skipping"
	fi
}

function getInstalledGamesFromCategory {
	CAT="$1"

	if [ -n "$CAT" ]; then
		while read -r CATAID; do
		echo "$CATAID"
		done <<< "$(getParsableGameList | grep "\"$CAT\"" | sed "s:\"::g" | sort -n | cut -d '+' -f1)"
	fi
}

function listInstalledGameIDs {
	while read -r APPMA; do
		grep -Eo "[[:digit:]]*" <<< "${APPMA##*/}"
	done <<< "$(listAppManifests)"
}

function getGameDataForInstalledGames {
	if [ "$(listInstalledGameIDs | wc -l)" -eq 0 ]; then
		writelog "SKIP" "${FUNCNAME[0]} - No installed games found!"
	else
		while read -r CATAID; do
			if [ -n "$CATAID" ]; then
				getGameData "$CATAID"
			fi
		done <<< "$(listInstalledGameIDs)"
	fi
}

function checkSGDbApi {
	if [ -z "$SGDBAPIKEY" ] || [ "$SGDBAPIKEY" == "$NON" ]; then
		writelog "SKIP" "${FUNCNAME[0]} - No SteamGrid Api Key found - Get one at '${STEAMGRIDDBAPI}'"
		writelog "SKIP" "${FUNCNAME[0]} - and save it in the Global Config ('SGDBAPIKEY')"
		return 1
	else
		return 0
	fi	
}

# Takes a list of appids separated by newlines
function getGrids {
	if checkSGDbApi && [ "$STLPLAY" -eq 0 ]; then

		# Split into batches of 100 games - too many and cloudflare blocks requests because of a too big header file
		while mapfile -t -n 100 ary && ((${#ary[@]})); do
			PART=$(printf '%s\n' "${ary[@]}")

			# If the whole batch has no grids we get a 404 and wget gives an error. --content-on-error ensures we still get the response json and the following logic still works
			RESPONSE="$("$WGET" --content-on-error --header="Authorization: Bearer $SGDBAPIKEY" -q "${STEAMGRIDDBAPI}/$(echo "$PART" | awk '{print $1}' | paste -s -d, -)?styles=${SGDBSTYLES}&dimensions=${SGDBDIMS}&types=${SGDBTYPES}&nsfw=${SGDBNSFW}&humor=${SGDBHUMOR}" -O - 2> >(grep -v "SSL_INIT"))"

			if ! "$JQ" -e '.success' 1> /dev/null <<< "$RESPONSE"; then
				writelog "INFO" "${FUNCNAME[0]} - The server response wasn't 'success' for this batch of requested games."
				continue
			fi

			RESPONSE_LENGTH=$("$JQ" '.data | length' <<< "$RESPONSE")

			# catch single grid without downloads
			if [ "$RESPONSE_LENGTH" = 0 ]; then
				writelog "INFO" "${FUNCNAME[0]} - No grid found to download - maybe loosen filters?"
				continue
			fi

			# TODO: This could be handled by the http return value - 200 is single-part - 207 is multi-part
			# Rewrite response object to fit the following loop if the response isn't multi-part
			if "$JQ" -e ".data[0].url" 1> /dev/null <<< "$RESPONSE"; then
				RESPONSE="{\"success\":true,\"data\":[$RESPONSE]}"
				RESPONSE_LENGTH=1
			fi

			for i in $(seq 0 $(("$RESPONSE_LENGTH" - 1))); do

				# match the current json array member against the appid list
				# this assumes we get the same order back we put in before
				APPID=$(sed "$((i + 1))q;d" <<< "$PART")

				if ! "$JQ" -e ".data[$i].success" 1> /dev/null <<< "$RESPONSE"; then
					writelog "INFO" "${FUNCNAME[0]} - The server response for '$APPID' wasn't 'success'"
					continue
				fi

				if ! URLSTR=$("$JQ" -e -r ".data[$i].data[0].url" <<< "$RESPONSE"); then
					writelog "INFO" "${FUNCNAME[0]} - No grid found to download for '$APPID' - maybe loosen filters?"
					continue
				fi

				GRIDDLURL="${URLSTR//\"}"
				if grep -q "^https" <<< "$GRIDDLURL"; then
					DLSRC="${GRIDDLURL//\"}"

					if [ "$SGDBDLTOSTEAM" -eq 1 ]; then
						if [ -z "$SUSDA" ]; then
							setSteamPaths
						fi

						if [ -d "$SUIC" ]; then
							GRIDDLDIR="${SUIC}/grid"
						fi
					else
						GRIDDLDIR="$STLDLDIR/steamgriddb"
					fi

					mkProjDir "$GRIDDLDIR"
			
					DLDST="$GRIDDLDIR/${APPID}p.${GRIDDLURL##*.}"
					STARTDL=1
					
					if [ -f "$DLDST" ]; then
						if [ "$SGDBHASFILE" == "skip" ]; then
							writelog "INFO" "${FUNCNAME[0]} - Download of existing file is set to '$SGDBHASFILE' - doing nothing"
							STARTDL=0
						elif [ "$SGDBHASFILE" == "backup" ]; then
							BACKDIR="${GRIDDLDIR}/backup"
							mkProjDir "$BACKDIR"
							writelog "INFO" "${FUNCNAME[0]} - Backup existing file into '$BACKDIR', because SGDBHASFILE is set to '$SGDBHASFILE'"
							mv "$DLDST" "$BACKDIR"
						elif [ "$SGDBHASFILE" == "replace" ]; then
							writelog "INFO" "${FUNCNAME[0]} - Replacing existing file '$DLDST', because SGDBHASFILE is set to '$SGDBHASFILE'"
							rm "$DLDST" 2>/dev/null
						fi
					fi
					
					if [ "$STARTDL" -eq 1 ]; then
						dlCheck "$DLSRC" "$DLDST" "X" "Downloading '$DLSRC' to '$DLDST'"
					fi
				else
					writelog "INFO" "${FUNCNAME[0]} - No grid found to download for '$APPID' - maybe loosen filters?"
				fi
			done
		done <<< "${1}"
	fi
}

function getGridsForOwnedGames {
	if checkSGDbApi; then
		getGrids "$(getOwnedAids)"
	fi
}

function getGridsForInstalledGames {
	if checkSGDbApi; then
		if [ "$(listInstalledGameIDs | wc -l)" -eq 0 ]; then
			writelog "SKIP" "${FUNCNAME[0]} - No installed games found!"
		else
			getGrids "$(listInstalledGameIDs)"
		fi
	fi
}

function getDataForAllGamesinSharedConfig {
	while read -r CATAID; do
		getGameData "$CATAID"
	done <<< "$(getParsableGameList | cut -d '+' -f1 | sed "s:\"::g" | grep "[0-9]" | sort -n)"
}

# replaced by getOwnedAids which is more complete - useful for something else?
#function getAllOwnedGames {
# shellcheck disable=SC2016
#	sed -n '/"Apps"/,${p;/"LastPlayedTimesSyncTime"/q}' "$FLCV" | grep "{" -B1 | grep "[0-9]" | tr -cd '[[:digit:]]\n' | sort -n
#}

function getActiveSteamCategories {
	getParsableGameList | grep "\"tags\"" | awk -F '{+' '{print $NF}' | sed 's/\"/'$'\\\n/g' | sort -u | grep -i "^[a-z]"
}

function createCategoryMenus {
	# create launcher menu for all installed games
	DFIDIR="$DFDIR/installed"
	mkProjDir "$DFIDIR"

	if [ "$(listInstalledGameIDs | wc -l)" -eq 0 ]; then
		writelog "SKIP" "${FUNCNAME[0]} - No installed games found!"
	else
		while read -r CATGAME; do
			if [ -n "$CATGAME" ] && [ ! -h "$DFIDIR/$CATGAME.desktop" ] && [ -f "$STLGDESKD/$CATGAME.desktop" ]; then
				ln -s "$STLGDESKD/$CATGAME.desktop" "$DFIDIR"
			fi
		done <<< "$(listInstalledGameIDs)"
	fi

	# create launcher menu for all category '$1'
	if [ -n "$1" ] && [ "$1" == "update" ] && [ "$(find "$DFDIR" -name "*.desktop" | wc -l)" -gt 0 ]; then
		find "$DFDIR" -name "*.desktop" -exec rm {} \;
	fi
	
	if [ "$(find "$DFDIR" -name "*.desktop" | wc -l)" -eq 0 ]; then
		while read -r CAT; do
			DFCDIR="$DFDIR/$CAT"
			mkProjDir "$DFCDIR"
			while read -r CATGAME; do
				if [ -f "$STLGDESKD/$CATGAME.desktop" ]; then
					if [ ! -h "$DFCDIR/$CATGAME.desktop" ]; then
						ln -s "$STLGDESKD/$CATGAME.desktop" "$DFCDIR"
					fi
				fi
			done <<< "$(getInstalledGamesFromCategory "$CAT")"
		done < <(getActiveSteamCategories)
	fi
}

function listAppManifests {
	function findAppMa {
		if [ -d "$1" ]; then
			find "$1" -mindepth 1 -maxdepth 1 -type f -name "appmanifest_*.acf"
		fi
	}

	# getBIF takes a string containing a BaseInstallFolder or path and returns the 
	function getBIF {
		# REGEX needs to be a variable, quoted string literals are not treated as regexps by test
		# BASH_REMATCH[1] will be the key (BaseInstallFolder* or path)
		# BASH_REMATCH[2] will be the value (the actual steam library folder)
		local REGEX='"(BaseInstallFolder[^"]*|path)"\s+"(.*)"\s*$'
		in="$1"

		# Test the regex against input, then print the extracted path to stdout
		if [[ $in =~ $REGEX ]] && [ -n "${BASH_REMATCH[2]}" ]; then
			echo "${BASH_REMATCH[2]}/$SA"
		else
			writelog "WARN" "${FUNCNAME[0]} - Failed to parse Base Install Folder from '$in'"
		fi
	}


	function listAllAppMas {
		if [ -d "$DEFSTEAMAPPS" ]; then
			findAppMa "$DEFSTEAMAPPS"
		else
			writelog "SKIP" "${FUNCNAME[0]} - '$DEFSTEAMAPPS' not found - this should not happen! - skipping"
		fi

		if [ -f "$CFGVDF" ] || [ -f "$LFVDF" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Searching appmanifest files in '$CFGVDF' and '$LFVDF'" "X" "$APPMALOG"
			while read -r BIF; do
				findAppMa "$(getBIF "$BIF")"
			done <<< "$(grep "\"BaseInstallFolder\|\"path\"" "$CFGVDF" "$LFVDF" 2>/dev/null)" | sort -u
		else
			writelog "SKIP" "${FUNCNAME[0]} - Neither file CFGVDF '$CFGVDF' nor file LFVDF '$LFVDF' found - this should not happen! - skipping"
		fi
	}
	
	listAllAppMas | sort -u
}

function createCategoriesList {
	function listCAT {
		while read -r CATMENU; do
			echo "${CATMENU##*/}"
		done <<< "$(find "$DFDIR" -mindepth 1 -maxdepth 1 -type d)"
	}
	CATLIST="$(listCAT | sort -u | tr '\n' '!' | sed "s:^!::" | sed "s:!$::")"
} 

function setGeom {
	GEOM="--geometry=${WINX}x${WINY}+${POSX}+${POSY}"
}

function pollWinRes {
	TITLE="$1"
	POSX=0
	POSY=0
	unset COLCOUNT

	SCREENRES="$(getScreenRes r)"

	if [ -z "$SCREENRES" ]; then
		SCREENRES="any"
	fi
	TEMPL="template"
	GAMEGUICFG="$STLGUIDIR/$SCREENRES/${AID}/${TITLE}.conf"
	TEMPLGUICFG="$STLGUIDIR/$SCREENRES/${TEMPL}/${TITLE}.conf"
	GLOBTEMPLGUICFG="$GLOBALSTLGUIDIR/$SCREENRES/${TEMPL}/${TITLE}.conf"

	mkProjDir "${GAMEGUICFG%/*}"
	mkProjDir "${TEMPLGUICFG%/*}"
	
	if [ -f "$TEMPLGUICFG" ] && [ ! -f "$GAMEGUICFG" ]; then
		loadCfg "$TEMPLGUICFG" X
		setGeom
		writelog "INFO" "${FUNCNAME[0]} - Using GEOM '$GEOM' from '$TEMPLGUICFG'" "$WINRESLOG"
	elif [ -f "$GLOBTEMPLGUICFG" ] && [ ! -f "$GAMEGUICFG" ]; then
		loadCfg "$GLOBTEMPLGUICFG" X
		setGeom
		writelog "INFO" "${FUNCNAME[0]} - Using GEOM '$GEOM' from '$GLOBTEMPLGUICFG'" "$WINRESLOG"
	elif [ -f "$GAMEGUICFG" ]; then
		loadCfg "$GAMEGUICFG" X
		setGeom
		writelog "INFO" "${FUNCNAME[0]} - Using GEOM '$GEOM' from '$GAMEGUICFG'" "$WINRESLOG"
	else
		touch "$GAMEGUICFG"
		echo "WINX=\"$WINX\"" > "$GAMEGUICFG"
		echo "WINY=\"$WINY\"" >> "$GAMEGUICFG"

		if [ -z "$GEOM" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Using harmless '--center' as variable 'GEOM', because there are multiple side-effects in yad if the string is empty"
			GEOM="--center"
		fi

		writelog "INFO" "${FUNCNAME[0]} - Creating initial '$GAMEGUICFG' with unused default values" "$WINRESLOG"
	fi
	
	if [ -n "$2" ]; then
		DEFCOL="$2"
	else
		DEFCOL=1
	fi
	
	if [ -z "$COLCOUNT" ]; then
		updateConfigEntry "COLCOUNT" "$DEFCOL" "$GAMEGUICFG"
		COLCOUNT="$DEFCOL"
	fi
	
	CURGUICFG="$GAMEGUICFG"
	export CURGUICFG="$CURGUICFG"
	
	updateWinRes "$TITLE" "$GAMEGUICFG" "$TEMPLGUICFG" &
}

function openGameLauncher {
	function GLgui {
		LISTDIR="$DFDIR/$1"
		if [ -d "$LISTDIR" ] && [ "$(find "$LISTDIR" -name "*.desktop" | wc -l)" -ge 1 ]; then
			"$YAD" --f1-action="$F1ACTION" --icons --window-icon="$STLICON" --read-dir="$LISTDIR" "$WINDECO" --title="$TITLE" --single-click --keep-icon-size --center --compact --sort-by-name "$GEOM"
		else
			writelog "SKIP" "${FUNCNAME[0]} - No games found in '$LISTDIR' or directory itself not found"
		fi
	}

	if grep -q "update" <<< "$@"; then
		createCategoryMenus "update"
	else
		createCategoryMenus "dummy"
	fi

	if [ "$(find "$DFDIR" -name "*.desktop" | wc -l)" -eq 0 ]; then
		writelog "INFO" "${FUNCNAME[0]} - No desktop file found in '$DFDIR'"
		if [ "$1" == "auto" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Found argument 'auto'. Automatically creating/downloading required data for all installed games found"
			getGameDataForInstalledGames
			if [ -n "$2" ] && [ "$2" == "update" ]; then
				createCategoryMenus "$2"
			else
				createCategoryMenus "dummy"
			fi
		else
			writelog "INFO" "${FUNCNAME[0]} - Either add argument 'auto' to automatically create/download required data or check '$PROGCMD --help'"
			exit
		fi
	fi

	export CURWIKI="$PPW/Game-Launcher"
	TITLE="${PROGNAME}-Launcher"
	pollWinRes "$TITLE" 

	if [ -z "$1" ] || [ "$1" == "auto" ] || [ "$1" == "update" ]; then
		GLgui "installed"
	else
		if [ "$1" == "menu" ]; then
			createCategoriesList
			CATMENU="$("$YAD" --f1-action="$F1ACTION" --window-icon="$STLICON" --center "$WINDECO" --form --scroll --separator="\n" --quoted-output \
			--text="$(spanFont "$GUI_CHOOSECAT" "H")" \
			--field="$GUI_CHOOSECATS":CB "$(cleanDropDown "installed" "$CATLIST")" \
			--title="$TITLE" "$GEOM"
			)"
			
			if [ -n "${CATMENU//\'}" ]; then
				GLgui "${CATMENU//\'}"
			fi
		elif [ "$1" == "last" ]; then
			if [ -f "$LASTRUN" ]; then
				PREVAID="$(grep "^PREVAID" "$LASTRUN" | cut -d '=' -f2)"
				if [ -n "$PREVAID" ]; then
					AID="${PREVAID//\"}"
					if [ -f "$STLGDESKD/$AID.desktop" ]; then
						writelog "INFO" "${FUNCNAME[0]} - '$1' selected, so opening splash for '$STLGDESKD/$AID.desktop'"
						DFCDIR="$DFDIR/last"
						mkProjDir "$DFCDIR"
						cp "$STLGDESKD/$AID.desktop" "$DFCDIR"
						GLgui "$1"
					else
						writelog "SKIP" "${FUNCNAME[0]} - '$1' selected, but file '$STLGDESKD/$AID.desktop' not found"
					fi
				fi
			fi
		elif [ -d "$DFDIR/$1" ]; then
			GLgui "$1"
		else
			writelog "SKIP" "${FUNCNAME[0]} - Steam Category '$1' not found in '$DFDIR'"
			writelog "SKIP" "${FUNCNAME[0]} - Only found '$(ls "$DFDIR")'"
		fi
	fi
}

function DBGMS {
	echo "$(date) - $1" >> "$STLSHM/DBGMS.txt"
}

function resetAID {
	if [ -n "$1" ]; then
		if [ -n "${1##*[!0-9]*}" ]; then
			AID="$1"
		else
			if [ "$1" == "last" ]; then
				if [ -f "$LASTRUN" ]; then
					PREVAID="$(grep "^PREVAID" "$LASTRUN" | cut -d '=' -f2)"
					if [ -n "$PREVAID" ]; then
						AID="${PREVAID//\"}"
						PREVGAME="$(grep "^PREVGAME" "$LASTRUN" | cut -d '=' -f2)"
						if [ -n "$PREVGAME" ]; then
							GN="${PREVGAME//\"}"
						fi
					fi
				else
					AID="$PLACEHOLDERAID"
				fi
			fi
		fi
	fi
	# should not happen, but just in case it is still empty, set the placeholders
	if [ -z "$AID" ]; then
		AID="$PLACEHOLDERAID"
	fi

	if [ "$AID" == "$PLACEHOLDERAID" ]; then
		GN="$PLACEHOLDERGN"
	fi
	setAIDCfgs
}

function setGN {
	if [ -z "$GN" ]; then
		getGameName "$1"
		GN="$GAMENAME"
	fi
}

function createSymLink {
	if [ ! -L "$3" ] && [ -e "$2" ]; then
		ln -s "$2" "$3"
		writelog "INFO" "$1 - Set symlink from '$2' to '$3'"
	else
		if [ -L "$3" ] && [ -z "$4" ]; then
			writelog "INFO" "$1 - Symlink '$3' already exists"
		fi

		if [ ! -e "$2" ]; then
			writelog "INFO" "$1 - '$2' does not exists"
		fi
	fi
}

function linkLog {
	if [ -z "$GN" ]; then
		writelog "SKIP" "${FUNCNAME[0]} - Skipping symlinking logfile - no valid game name found"
	else
		createSymLink "${FUNCNAME[0]}" "$LOGFILE" "$LOGDIRTI/$GN.log"
	fi
}

function setGlobalAIDCfgs {
	GLOBALSBSTWEAKCFG="$GLOBALSBSTWEAKS/$AID.conf"
	GLOBALTWEAKCFG="$GLOBALTWEAKS/$AID.conf"
}

function setCompatDataTitle {
	if [ "$STORECOMPDATTITLE" -eq 1 ] && [ -n "$OSCDP" ]; then
		mkProjDir "$STLCOMPDAT"
		COMPDATTITLE="$STLCOMPDAT/$GN"
		if readlink "$COMPDATTITLE" >/dev/null ; then
			writelog "INFO" "${FUNCNAME[0]} - Symlink $COMPDATTITLE already exists"
			if [ "$(readlink "$COMPDATTITLE")" == "$OSCDP" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Symlink '$COMPDATTITLE' already points to the correct directory '$OSCDP'"
			else
				writelog "INFO" "${FUNCNAME[0]} - Symlink '$COMPDATTITLE' points to '$(readlink "$COMPDATTITLE")' which is not the correct directory '$OSCDP' - renewing!"
				rm "$COMPDATTITLE"
				createSymLink "${FUNCNAME[0]}" "$OSCDP" "$COMPDATTITLE"
			fi
		else
			createSymLink "${FUNCNAME[0]}" "$OSCDP" "$COMPDATTITLE"
		fi
	fi
}

function setGameVars {
	getGameOS "$@"
	# common
	if [ -n "$STEAM_COMPAT_INSTALL_PATH" ]; then
		EFD="$STEAM_COMPAT_INSTALL_PATH"
	else
		EFD="$(dirname "$GP")"
	fi

	GFD="$(awk -F 'common' '{print $1}' <<< "$EFD")common/$(awk -F 'common' '{print $NF}' <<< "$EFD" | cut -d'/' -f2)" # f.e. used for vortex symlinks
	GN="$(grep -oE 'common/[^\/]+' <<< "$EFD" | awk -F 'common/' '{print $NF}')"				# THIS is hopefully the proper game name

	if [ -z "$STEAM_COMPAT_TOOL_PATHS" ] || [ "$STEAM_COMPAT_TOOL_PATHS" == "" ]; then
		HAVESCTP=0
	else
		HAVESCTP=1
		ORG_STEAM_COMPAT_TOOL_PATHS="$STEAM_COMPAT_TOOL_PATHS"
	fi

	if [ -n "$STEAM_COMPAT_INSTALL_PATH" ]; then
		STECOSHAPA="$STEAM_COMPAT_SHADER_PATH"
	fi

	if [ -n "$STEAM_COMPAT_LIBRARY_PATHS" ]; then
		APPMAFE="${STEAM_COMPAT_LIBRARY_PATHS}/appmanifest_${AID}.acf"
	fi

	REAPSESTR="reaper SteamLaunch"

	if grep -q "$REAPSESTR" <<< "$@"; then
		HAVEREAP=1
	else
		HAVEREAP=0
	fi
	
	if grep -q "$SLR" <<< "$@"; then
		HAVESLR=1
	else
		HAVESLR=0
	fi

	INSTLSTR="${PROGNAME}/${PROGCMD}"
	if grep -q "$INSTLSTR" <<< "$@"; then
		HAVEINSTL=1
	else
		HAVEINSTL=0
	fi

	# first put the initial command line into an array - who knows if we need it again
	while read -r INGARG; do
		mapfile -t -O "${#INGCMD[@]}" INGCMD <<< "$INGARG"
	done <<< "$(printf "%s\n" "$@")"

	# then put the reaper command into an array, as it is the first command in the line
	if [ "$HAVEREAP" -eq 1 ]; then
		FOUNDREAP=0
		while read -r INGARG; do
			if [ "$FOUNDREAP" -eq 0 ]; then
				mapfile -t -O "${#REAPCMD[@]}" REAPCMD <<< "$INGARG"
				if [ "$INGARG" == "--" ]; then
					FOUNDREAP=1
				fi
			else
				mapfile -t -O "${#WIPAGCMD[@]}" WIPAGCMD <<< "$INGARG"
			fi
		done <<< "$(printf "%s\n" "${INGCMD[@]}")"
	else
		while read -r INGARG; do
			mapfile -t -O "${#WIPAGCMD[@]}" WIPAGCMD <<< "$INGARG"
		done <<< "$(printf "%s\n" "${INGCMD[@]}")"
	fi
	THISREAP="${REAPCMD[*]}"
	THISREAP="${THISREAP% SteamLaunch*}"
	if [ -z "$LASTREAP" ] || { [ -n "$LASTREAP" ] && [ "$LASTREAP" != "$THISREAP" ];}; then
		updateConfigEntry "LASTREAP" "$THISREAP" "$STLDEFGLOBALCFG"
	fi

	# if the SLR is called from command line put it into an array as well
	if [ "$HAVESLR" -eq 1 ]; then
		FOUNDSLR=0
		while read -r ORGARG; do
			if [ "$FOUNDSLR" -eq 0 ]; then
				mapfile -t -O "${#RUNSLR[@]}" RUNSLR <<< "$ORGARG"
				if [ "$ORGARG" == "--" ]; then
					FOUNDSLR=1
				fi
			else
				mapfile -t -O "${#WIPBGCMD[@]}" WIPBGCMD <<< "$ORGARG"
			fi
		done <<< "$(printf "%s\n" "${WIPAGCMD[@]}")"
	else
		while read -r ORGARG; do
			mapfile -t -O "${#WIPBGCMD[@]}" WIPBGCMD <<< "$ORGARG"
		done <<< "$(printf "%s\n" "${WIPAGCMD[@]}")"	
	fi

	if [ -z "$LASTSLR" ] || { [ -n "$LASTSLR" ] && [ "$LASTSLR" != "${RUNSLR[*]}" ];}; then
		updateConfigEntry "LASTSLR" "${RUNSLR[*]}" "$STLDEFGLOBALCFG"
	fi

	# put the proton path into an array as well if provided from command line
	if [ "$HAVEINPROTON" -eq 1 ]; then
		FOUNDIPRO=0
		while read -r ORGARG; do
			if [ "$FOUNDIPRO" -eq 0 ]; then
				mapfile -t -O "${#INPROTCMD[@]}" INPROTCMD <<< "$ORGARG"
				if [ "$ORGARG" == "$WFEAR" ]; then
					FOUNDIPRO=1
				fi
			else
				mapfile -t -O "${#WIPCGCMD[@]}" WIPCGCMD <<< "$ORGARG"
			fi
		done <<< "$(printf "%s\n" "${WIPBGCMD[@]}")"
			
		if [ "${INPROTCMD[-1]}" == "$WFEAR" ]; then
			# removing last INPROTCMD element as it is '$WFEAR'
			unset "INPROTCMD[-1]"
		fi

		INPROTV="$(setProtonPathVersion "${INPROTCMD[*]}")"
	else
		while read -r ORGARG; do
			mapfile -t -O "${#WIPCGCMD[@]}" WIPCGCMD <<< "$ORGARG"
		done <<< "$(printf "%s\n" "${WIPBGCMD[@]}")"	
	fi

	# put the own $PROGCMD command into an array if provided from command line
	if [ "$HAVEINSTL" -eq 1 ]; then
		FOUNDINSTL=0
		while read -r ORGARG; do
			if [ "$FOUNDINSTL" -eq 0 ]; then
				mapfile -t -O "${#INSTLCMD[@]}" INSTLCMD <<< "$ORGARG"
				if [[ "$ORGARG" =~ $INSTLSTR ]]; then
					FOUNDINSTL=1
				fi
			else
				mapfile -t -O "${#WIPDGCMD[@]}" WIPDGCMD <<< "$ORGARG"
			fi
		done <<< "$(printf "%s\n" "${WIPCGCMD[@]}")"
	else
		while read -r ORGARG; do
			mapfile -t -O "${#WIPDGCMD[@]}" WIPDGCMD <<< "$ORGARG"
		done <<< "$(printf "%s\n" "${WIPCGCMD[@]}")"	
	fi

	if grep -q "$SLR" <<< "${WIPDGCMD[@]}"; then
		HAVESLRCT=1
	else
		HAVESLRCT=0
	fi
	
	if [ "$HAVESLRCT" -eq 1 ]; then
		FOUNDSLR=0
		while read -r ORGARG; do
			if [ "$FOUNDSLR" -eq 0 ]; then
				mapfile -t -O "${#RUNSLRCT[@]}" RUNSLRCT <<< "$ORGARG"
				if [ "$ORGARG" == "--" ]; then
					FOUNDSLR=1
				fi
			else
				mapfile -t -O "${#ORGFGCMD[@]}" ORGFGCMD <<< "$ORGARG"
			fi
		done <<< "$(printf "%s\n" "${WIPDGCMD[@]}")"
	else
		while read -r ORGARG; do
			mapfile -t -O "${#ORGFGCMD[@]}" ORGFGCMD <<< "$ORGARG"
		done <<< "$(printf "%s\n" "${WIPDGCMD[@]}")"	
	fi
	
	# what is left now is the game executable and its command line arguments - splitting

	FOUNDORGGCMD=0
	while read -r ORGARG; do
		if [ "$FOUNDORGGCMD" -eq 0 ]; then
			mapfile -t -O "${#ORGGCMD[@]}" ORGGCMD <<< "$ORGARG"
			if [[ "$ORGARG" =~ $GP ]]; then
				FOUNDORGGCMD=1
			fi
		else
			mapfile -t -O "${#ORGCMDARGS[@]}" ORGCMDARGS <<< "$ORGARG"
		fi
	done <<< "$(printf "%s\n" "${ORGFGCMD[@]}")"

	if [ "${ORGGCMD[0]}" == "$WFEAR" ]; then
		# removing first ORGGCMD element as it is '$WFEAR'
		unset "ORGGCMD[0]"
	fi

	if [ -z "$GAMEEXE" ]; then
		GAMEEXE1="${ORGGCMD[*]}"
		GAMEEXE="${GAMEEXE1##*/}"
	fi

}

function getGameOS {
	function setLin {
		if [ -f "$OSCHECKGAMEEXE" ]; then
			GP="$OSCHECKGAMEEXE"
		else
			GPRAW="$(printf "%s\n" "$@" | grep -m1 "$SAC")"
			if grep -q "/./" <<< "$GPRAW"; then
				GP="${GPRAW//\/.\//\/}"
			else
				GP="$GPRAW"
			fi
		fi
		GE="${GP##*/}"																			# the game executable
		ISGAME=3																				# no STEAM_COMPAT_DATA_PATH, so it is no windows game		
	}

	function setWin {
		if [ -f "$OSCHECKGAMEEXE" ]; then
			GP="$OSCHECKGAMEEXE"
		else
			GP="$(printf "%s\n" "$@" | grep -v "proton\|$SLR" | grep -m1 "$SAC")"				# the absolute game path of the windows game exe
		fi
		GPFX="$STEAM_COMPAT_DATA_PATH/pfx"														# currently used WINEPREFIX
		GE="$(awk -F '.exe' '{print $1}' <<< "${GP##*/}")"										# just the windows game exe name
		writelog "INFO" "${FUNCNAME[0]} - '$GE' determined to be a Windows Game"
		ISGAME=2		
	}
	if [ "$STLPLAY" -eq 0 ]; then
		if [ "$ISGAME" -eq 0 ]; then 
			writelog "INFO" "${FUNCNAME[0]} - Starting game OS detection"

			while read -r INGARG; do
				if grep -q "$STEAM_COMPAT_INSTALL_PATH" <<< "$INGARG"; then
					OSCHECKGAMEEXE="$INGARG"
				fi
				mapfile -t -O "${#OSCHECKINGCMD[@]}" OSCHECKINGCMD <<< "$INGARG"
			done <<< "$(printf "%s\n" "$@")"

			if [ -n "$STEAM_COMPAT_DATA_PATH" ]; then
				writelog "INFO" "${FUNCNAME[0]} - STEAM_COMPAT_DATA_PATH is defined - This is no longer necessarily a reliable indication that this is a Windows game."
				if [ -f "$OSCHECKGAMEEXE" ]; then
					writelog "INFO" "${FUNCNAME[0]} - Making some more checks on '$OSCHECKGAMEEXE' to determine the OS version of the game"
					if grep -q "shell script" <<< "$(file "$(realpath "$OSCHECKGAMEEXE")")" || grep -q "ELF.*.LSB" <<< "$(file "$(realpath "$OSCHECKGAMEEXE")")" ; then
						writelog "INFO" "${FUNCNAME[0]} - Looks like this is a Linux game!"
						setLin "$@"
					elif grep -q "PE32" <<< "$(file "$OSCHECKGAMEEXE")"; then
						writelog "INFO" "${FUNCNAME[0]} - Looks like this is a Windows game!"
						setWin "$@"
					else
						writelog "WARN" "${FUNCNAME[0]} - Could not determine OS version of '$OSCHECKGAMEEXE' (add check?), so assuming this is a Windows game"
						setWin "$@"
					fi
				else
					writelog "WARN" "${FUNCNAME[0]} - Could not extract the full game binary path from the incoming game launch command, so assuming this is a Windows game!"
					setWin "$@"
				fi
			else
				writelog "INFO" "${FUNCNAME[0]} - STEAM_COMPAT_DATA_PATH is dot defined, so this is either a Linux Game or no game was started at all"
				setLin "$@"
			fi
		else
			writelog "SKIP" "${FUNCNAME[0]} - ISGAME is already set to '$ISGAME' - nothing to determine"
		fi
	fi
}

function setCustomGameVars {
	# there doesn't seem to be a possibility to distinguish game platform based on given variables, so using at least a basic arch check on the exe:
	GP="$(printf "%s\n" "$@" | grep -v "$WFEAR" | head -n1)"

	getGameOS "$@"

	GE="$(awk -F '.exe' '{print $1}' <<< "${GP##*/}")"
	EFD="$(dirname "$GP")"
	# need to just guess here, because of missing fix strings
	GFD="$EFD"
	GN="$GE"															

	while read -r ORGARG; do
		mapfile -t -O "${#ORGGCMD[@]}" ORGGCMD <<< "$ORGARG"
	done <<< "$(printf "%s\n" "$@")"	
}

function prepareGUI {
	WINDECO="--undecorated"

	if [ -n "$USEWINDECO" ]; then
		if [ "$USEWINDECO" -eq 1 ]; then
			WINDECO="--decorated"
		fi
	fi
}

function createLanguageList {
	function listLANG {
		while read -r RSPF; do
			TLANG="${RSPF//.txt/}"
			TLANG="${TLANG##*/}"
			printf '%s!' "$TLANG"
		done <<< "$(find "$STLLANGDIR" -name "*.txt")"

		while read -r RSPF; do
			TLANG="${RSPF//.txt/}"
			TLANG="${TLANG##*/}"
			printf '%s!' "$TLANG"
		done <<< "$(find "$GLOBALSTLLANGDIR" -name "*.txt")"
	}
	LANGYADLIST="$(listLANG)"
}

function loadLangFile {
	if [ -n "$1" ]; then
		LANGFILENAME="$1"
		if [ -z "$GLOBALSTLLANGDIR" ]; then
			GLOBLANG="$SYSTEMSTLCFGDIR/lang/"
		else
			GLOBLANG="$GLOBALSTLLANGDIR"
		fi

		if [ -f "$LANGFILENAME" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Loading commandline langfile" "P"
			source "$LANGFILENAME"
			STLLANG="$(cut -d '.' -f1 <<< "${LANGFILENAME##*/}")"
			LAFI="$STLLANGDIR/${STLLANG}.txt"
			if [ ! -f "$LAFI" ]; then
				mkProjDir "$STLLANGDIR"
				cp "$LANGFILENAME" "$LAFI"
			fi
		else
			LAFI="$STLLANGDIR/${LANGFILENAME}.txt"

			if [ -f "$LAFI" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Loading user-installed $LAFI" "P"
				source "$LAFI"
			else
				LAFI="$GLOBLANG/${LANGFILENAME}.txt"

				if [ -f "$LAFI" ]; then
					writelog "INFO" "${FUNCNAME[0]} - Loading system wide $LAFI" "P"
					source "$LAFI"
				else
					writelog "ERROR" "${FUNCNAME[0]} - Language file '$LAFI' missing" "P"
				fi
			fi
		fi
	fi
}

function loadLanguage {
#	if [ ! -f "$STLSHM/lola-$AID.txt" ] ;then
		writelog "INFO" "${FUNCNAME[0]} - First load the default language to make sure all variables are filled"
		loadLangFile "$STLDEFLANG"

		saveCfg "$STLDEFGLOBALCFG" X
		loadCfg "$STLDEFGLOBALCFG" X

		if [ -f "$STLDEFGLOBALCFG" ]; then
			STLLRAW="$(grep "^STLLANG" "$STLDEFGLOBALCFG" | cut -d '=' -f2)"
			STLLANG="${STLLRAW//\"/}"
		else
			ARGSLANG="$(awk -F 'lang=' '{print $2}' <<< "$@" | cut -d ' ' -f1)"
			if [ -n "$ARGSLANG" ]; then
				STLLANG="$ARGSLANG"
			fi
		fi

		if [ -n "$STLLANG" ] && [ "$STLLANG" != "$STLDEFLANG" ]; then 
			writelog "INFO" "${FUNCNAME[0]} - Now load the language file '$STLLANG'"
			loadLangFile "$STLLANG"
		fi
		
#		touch "$STLSHM/lola-$AID.txt"
		
		if [ -z "$DESC_STLLANG" ]; then 
			writelog "ERROR" "${FUNCNAME[0]} - ###############################" "E"
			writelog "ERROR" "${FUNCNAME[0]} - No language file could be loaded! For the initial setup at least one file (default english) is required" "E"
			writelog "ERROR" "${FUNCNAME[0]} - You can ether copy a valid file to '$STLLANGDIR' or '$SYSTEMSTLCFGDIR/lang' or provide an absolute path via command line using the lang= option" "E"
			writelog "ERROR" "${FUNCNAME[0]} - ###############################" "E"
			exit
		fi
#	fi
}

function setProtonPathVersion {
	if [ -n "$INPROTV" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Using directly known '$INPROTV' as Proton Version for '$1'"
		echo "$INPROTV"
	else
		if [ -n "$1" ]; then
			PRTPATH="$1"
			CTVDF="$(dirname "$PRTPATH")/$CTVDF"
			PPV="$(dirname "$PRTPATH")/version"
			if [ -f "$CTVDF" ]; then
				PROTVOUT="$(grep "display_name" "$CTVDF" | grep -v "e.g." | sed "s:\" \":\";\":g" | cut -d ';' -f2)"
			elif [ -f "$PPV" ]; then
				PROTVOUT="$(awk '{print $2}' < "$PPV")"
			fi

			if [ -z "$PROTVOUT" ]; then
				# if no useful version was provided - hardcode it here:
				if grep -q "Proton 3.7" <<<"$PRTPATH"; then
					PROTVOUT="proton-3.7-8"
				else
				# fallback if everything fails - in the rare cases where this unknown proton version is used this might cause problems
				# if you need it open an issue and it will get a hardcoded entry as well
					PROTVOUT="proton-unknown-$((900 + RANDOM % 100))"
				fi
			fi

			#writelog "INFO" "${FUNCNAME[0]} - Setting the Proton Version for '$1' to '${PROTVOUT//\"/}'"	# checking $PROTONCSV should be enough

			echo "${PROTVOUT//\"/}"
		fi
	fi
}

function fillProtonCSV {
	if [ -n "$1" ]; then
		protonfileV="$1"
	else
		protonfileV="$(setProtonPathVersion "$PROTBIN")"
	fi
	if [ -n "$protonfileV" ]; then
		PCSV="\"${protonfileV//\"/}\";\"$(readlink -f "$PROTBIN")\""
#		writelog "INFO" "${FUNCNAME[0]} - Adding Proton '${PCSV//\"}'" # too much info, $PCSV can always be read if interested
		if [[ ! " ${ProtonCSV[*]} " =~ $PCSV ]]; then
			mapfile -t -O "${#ProtonCSV[@]}" ProtonCSV <<< "$PCSV"
		else
			writelog "SKIP" "${FUNCNAME[0]} - '$PCSV' is already in the Proton array"
		fi
	fi
}

function printProtonArr {
	printf "%s\n" "${ProtonCSV[@]//\"/}"
}

function delEmptyFile {
	if [ -f "$1" ]; then
		if [ "$(wc -l < "$1")" -le 1 ]; then
			rm "$1" 2>/dev/null
		fi
	fi
}

function rmDupLines {
	if grep -q "gawk" <<< "$AWKBIN"; then
		gawk -i inplace '!visited[$0]++' "$1"
	else
		awk '!seen[$0]++' "$1" > "$STLSHM/${FUNCNAME[0]}"
		cp "$STLSHM/${FUNCNAME[0]}" "$1"
		rm "$STLSHM/${FUNCNAME[0]}" 2>/dev/null
	fi
}

function getAvailableProtonVersions {
	# skip this function if a linux game was started
	if [ "$ISGAME" -eq 2 ] || [ -n "$2" ]; then
		# ...and if USEWINE is enabled	
		if [ -n "$USEWINE" ] && [ "$USEWINE" -eq 1 ]; then
			writelog "SKIP" "${FUNCNAME[0]} - USEWINE is enabled - skipping this function"
		elif [ -f "$STLGAMECFG" ] && grep -q "USEWINE=\"1\"" "$STLGAMECFG" ; then
			writelog "SKIP" "${FUNCNAME[0]} - USEWINE is enabled in the to-be-loaded gameconfig '$STLGAMECFG' - skipping this function"
			# could still be enabled via steamcategory, but this would be an overkill here, as ${FUNCNAME[0]} is non-fatal
		else
			delEmptyFile "$PROTONCSV"
			if [ ! -f "$PROTONCSV" ] || { [ -n "$1" ] && [ "$1" = "up" ]; } || [ "$1" == "F" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Initially creating an array with available Proton versions"

				# following symlinks (find -L) and using maxdepth 2 to avoid duplicates caused by _(user created)_ symlinks

				# user installed compatibilitytool:
				if [ -d "$STEAMCOMPATOOLS" ]; then
					writelog "INFO" "${FUNCNAME[0]} - Adding Proton versions found in STEAMCOMPATOOLS '$STEAMCOMPATOOLS'"
					while read -r PROTBIN; do
						fillProtonCSV
					done <<< "$(find -L "$STEAMCOMPATOOLS" -mindepth 2 -maxdepth 2 -type f -name "proton")"	
				else
					writelog "SKIP" "${FUNCNAME[0]} - Directory STEAMCOMPATOOLS '$STEAMCOMPATOOLS' not found - skipping"
				fi
				
				if [ -d "$SYSSTEAMCOMPATOOLS" ]; then
					writelog "INFO" "${FUNCNAME[0]} - Adding Proton versions found in SYSSTEAMCOMPATOOLS '$SYSSTEAMCOMPATOOLS'"
					while read -r PROTBIN; do
						fillProtonCSV
					done <<< "$(find -L "$SYSSTEAMCOMPATOOLS" -mindepth 2 -maxdepth 2 -type f -name "proton")"
				else
					writelog "SKIP" "${FUNCNAME[0]} - Directory SYSSTEAMCOMPATOOLS '$SYSSTEAMCOMPATOOLS' not found - skipping"
				fi
			
				# official proton versions installed via Steam in default SteamLibrary 
				if ! grep -q "\"path\".*.\"$SROOT\"" "$LFVDF"; then
					if [ -d "$DEFSTEAMAPPSCOMMON" ]; then
						writelog "INFO" "${FUNCNAME[0]} - Adding Proton versions found in DEFSTEAMAPPSCOMMON '$DEFSTEAMAPPSCOMMON'"
						while read -r protondir; do
							PROTBIN="$protondir/proton"
							if [ -f "$PROTBIN" ]; then
								fillProtonCSV
							fi
						done <<< "$(find -L "$DEFSTEAMAPPSCOMMON" -mindepth 2 -maxdepth 2 -type f -name "proton")"	
					else
						writelog "SKIP" "${FUNCNAME[0]} - Directory DEFSTEAMAPPSCOMMON '$DEFSTEAMAPPSCOMMON' not found - this should not happen! - skipping"
					fi
				fi

				# official proton versions installed via Steam in additional SteamLibrary Paths
				if [ -f "$CFGVDF" ] || [ -f "$LFVDF" ]; then
					if ! grep -q "BaseInstallFolder\|\"path\"" "$CFGVDF" "$LFVDF" 2>/dev/null; then
						writelog "INFO" "${FUNCNAME[0]} - No additional Steam Libraries configured in '$CFGVDF' or '$LFVDF' - so no need to search in there"
					else
						writelog "INFO" "${FUNCNAME[0]} - Adding Proton versions found in additional SteamLibrary Paths"
						while read -r protondir; do
							PROTBIN="$protondir/proton"
							if [ -f "$PROTBIN" ]; then
								fillProtonCSV
							fi
						done <<< "$(while read -r SLP; do if [ -d "${SLP//\"/}/$SAC" ]; then find "${SLP//\"/}/$SAC" -mindepth 1 -maxdepth 1 -type d -name "Proton*"; fi; done <<< "$(grep "BaseInstallFolder\|\"path\"" "$CFGVDF" "$LFVDF" 2>/dev/null | awk '{print $3}' | sort -u)")"
					fi
				else
					writelog "SKIP" "${FUNCNAME[0]} - Neither file CFGVDF '$CFGVDF' nor file LFVDF '$LFVDF' found - this should not happen! - skipping"
				fi

				# custom Proton List:
				if [ -f "$CUSTOMPROTONLIST" ]; then
					writelog "INFO" "${FUNCNAME[0]} - Adding Proton versions found in CUSTOMPROTONLIST '$CUSTOMPROTONLIST'"

					rmDupLines "$CUSTOMPROTONLIST"

					while read -r PROTLINE; do
						writelog "INFO" "${FUNCNAME[0]} - Checking line '$PROTLINE' in '$CUSTOMPROTONLIST'"

						if grep -q ";" <<< "$PROTLINE"; then
							PROTBIN="$(cut -d ';' -f2 <<< "$PROTLINE")"
							PROTVERS="$(cut -d ';' -f1 <<< "$PROTLINE")"
							writelog "INFO" "${FUNCNAME[0]} - Adding '$PROTVERS' to the list"
							fillProtonCSV "$PROTVERS"
						elif [ -f "$PROTLINE" ]; then
							writelog "INFO" "${FUNCNAME[0]} - File '$PROTLINE' exists - adding it to the list"
							PROTBIN="$PROTLINE"
							fillProtonCSV
						else
							writelog "INFO" "${FUNCNAME[0]} - Removing invalid line '$PROTLINE' from '$CUSTOMPROTONLIST'"
							mapfile -t -O "${#ProtonMissing[@]}" ProtonMissing <<< "$PROTLINE"
						fi
					done <<< "$(grep -v "^#" "$CUSTOMPROTONLIST")"

					# remove files from custom list which do not exist (anymore)
					if [ -n "${ProtonMissing[0]}" ]; then
						while read -r NOPROT; do
							sed "/${NOPROT//\//\\/}/d" -i "$CUSTOMPROTONLIST"
						done <<< "$(printf "%s\n" "${ProtonMissing[@]}")"
						unset ProtonMissing
					fi
				fi
			else
				writelog "INFO" "${FUNCNAME[0]} - Creating an array with available Proton versions using the file '$PROTONCSV' which was created during a previous run"
				mapfile -t -O "${#ProtonCSV[@]}" ProtonCSV < "$PROTONCSV"
			fi
			printProtonArr > "$PROTONCSV"
			rmDupLines "$PROTONCSV"
		fi
	fi
}

function setDefaultCfgValues {

	function setDefaultCfgValuesurl {
		if [ -z "$PROJECTPAGE" ]						; then	PROJECTPAGE="$GHURL/frostworx/steamtinkerlaunch"; fi
		if [ -z "$CP_PROTONTKG" ]						; then	CP_PROTONTKG="$GHURL/Frogging-Family/wine-tkg-git/releases"; fi
		if [ -z "$CP_PROTONGE" ]						; then	CP_PROTONGE="$GHURL/GloriousEggroll/proton-ge-custom/releases"; fi
		if [ -z "$CP_PROTONSTL" ]						; then	CP_PROTONSTL="$GHURL/frostworx/steamtinkerlaunch-tweaks/releases"; fi
		if [ -z "$DL_D3D47_64" ]						; then	DL_D3D47_64="https://lutris.net/files/tools/dll/$D3D47"; fi
		if [ -z "$DL_D3D47_32" ]						; then	DL_D3D47_32="http://dege.freeweb.hu/dgVoodoo2/bin/D3DCompiler_47.zip"; fi
		if [ -z "$RESHADEDLURL" ]						; then	RESHADEDLURL="https://reshade.me/downloads"; fi
		if [ -z "$VORTEXRELURL" ]						; then	VORTEXRELURL="$GHURL/Nexus-Mods/${VTX^}/releases"; fi
		if [ -z "$DXVKURL" ]							; then	DXVKURL="$GHURL/doitsujin/dxvk"; fi
		if [ -z "$XLIVEURL" ]							; then	XLIVEURL="$GHURL/ThirteenAG/Ultimate-ASI-Loader/releases/download/v4.61/Ultimate-ASI-Loader.zip"; fi
		if [ -z "$STASSURL" ]							; then	STASSURL="https://steamcdn-a.akamaihd.net/steam/apps"; fi
		if [ -z "$WINETRICKSURL" ]						; then	WINETRICKSURL="$GHURL/Winetricks/winetricks"; fi
		if [ -z "$CHEATENGINEURL" ]						; then	CHEATENGINEURL="$GHURL/cheat-engine/cheat-engine/releases";fi
		if [ -z "$X64DBGURL" ]							; then	X64DBGURL="$GHURL/x64dbg/x64dbg/releases/tag/snapshot";fi
		if [ -z "$STEAMGRIDDBAPI" ]						; then	STEAMGRIDDBAPI="https://www.steamgriddb.com/api/v2/grids/steam";fi
		if [ -z "$CONTYRELURL" ]						; then	CONTYRELURL="$GHURL/Kron4ek/Conty/releases"; fi
		if [ -z "$MO2DLURL" ]							; then	MO2DLURL="$GHURL/ModOrganizer2/modorganizer/releases"; fi
		if [ -z "$CW_KRON4EK" ]							; then	CW_KRON4EK="$GHURL/Kron4ek/Wine-Builds/releases"; fi
		if [ -z "$IGCSZIP" ]							; then	IGCSZIP="$GHURL/FransBouma/InjectableGenericCameraSystem/releases/download/IGCSInjector_102/IGCSInjector_v102.zip"; fi
		if [ -z "$UUUURL" ]								; then	UUUURL="https://framedsc.github.io/GeneralGuides/universal_ue4_consoleunlocker.htm#downloading-the-uuu"; fi
		if [ -z "$OVRFSRURL" ]							; then	OVRFSRURL="$GHURL/fholger/$OVFS/releases"; fi
		if [ -z "$DPRSRELURL" ]							; then	DPRSRELURL="$GHURL/${DPRS}/${DPRS}/releases"; fi
		if [ -z "$DEPURL" ]								; then	DEPURL="$GHURL/lucasg/${DEPS}/releases";fi
		if [ -z "$SPEKOLDDLURL" ]						; then	SPEKOLDDLURL="https://github.com/Kaldaien/SpecialK/releases/download/sk_0_8_50/SpecialK_0_8_66.7z";fi
		if [ -z "$SPEKURL" ]							; then	SPEKURL="https://sk-data.special-k.info/";fi
		if [ -z "$SPEKCOMPURL" ]						; then	SPEKCOMPURL="https://www.pcgamingwiki.com/wiki/List_of_games_compatible_with_Special_K#Compatibility_list";fi
		if [ -z "$FWSURL" ]								; then	FWSURL="https://www.${FWS,,}.org/fws";fi
		if [ -z "$YAIURL" ]								; then	YAIURL="$GHURL/frostworx/steamtinkerlaunch-tweaks/releases/download"; fi
		if [ -z "$WINERELOADURL" ]						; then	WINERELOADURL="https://gist.githubusercontent.com/rbernon/cdbdc1b0e892f91e7449fcf3dda80bb7/raw/d8cf549bf751d99ed0fe515e36f99ff5c01b7287"; fi
		if [ -z "$CEWAYBACKURL" ]						; then	CEWAYBACKURL="https://web.archive.org/web/20210118065254if_"; fi
	}

	function setDefaultCfgValuesglobal {
		if [ -z "$STLLANG" ]							; then	STLLANG="$STLDEFLANG"; fi
		if [ -z "$SKIPINTDEPCHECK" ]					; then	SKIPINTDEPCHECK="0"; fi
		if [ -z "$STRACEDIR" ]							; then	STRACEDIR="$LOGDIR"; fi
		if [ -z "$LOGDIR" ]								; then	LOGDIR="$DEFLOGDIR"; fi
		if [ -z "$LOGLEVEL" ]							; then	LOGLEVEL="2"; fi
		if [ -z "$RESETLOG" ]							; then	RESETLOG="1"; fi
		if [ -z "$STLEDITOR" ]							; then	STLEDITOR="$(command -v "geany")"; fi
		if [ -z "$MAXASK" ]								; then	MAXASK="3"; fi
		if [ -z "$BROWSER" ]							; then	BROWSER="$(command -v "firefox")"; fi
		if [ -z "$NOTY" ]								; then	NOTY="$(command -v "notify-send")"; fi
		if [ -z "$NOTYARGS" ]							; then	NOTYARGS="-i $STLICON -a $PROGNAME"; fi
		if [ -z "$USENOTIFIER" ]						; then	USENOTIFIER="1"; fi
		if [ -z "$NETMON" ]								; then	NETMON="$(command -v "netstat")"; fi
		if [ -z "$NETOPTS" ]							; then	NETOPTS="-taucp -W"; fi
		if [ -z "$NETMONDIR" ]							; then	NETMONDIR="$LOGDIR"; fi
		if [ -z "$VRVIDEOPLAYER" ]						; then	VRVIDEOPLAYER="$(command -v "vr-video-player")"; fi
		if [ -z "$GAMCON" ]								; then	GAMCON="/usr/share/gameconqueror/GameConqueror.py"; fi
		if [ -z "$GLOBALCATEGORYDIR" ]					; then	GLOBALCATEGORYDIR="$SYSTEMSTLCFGDIR/categories"; fi
		if [ -z "$GLOBALMISCDIR" ]						; then	GLOBALMISCDIR="$SYSTEMSTLCFGDIR/misc"; fi
		if [ -z "$GLOBALSBSTWEAKS" ]					; then	GLOBALSBSTWEAKS="$SYSTEMSTLCFGDIR/misc/sbstweaks"; fi
		if [ -z "$GLOBALTWEAKS" ]						; then	GLOBALTWEAKS="$SYSTEMSTLCFGDIR/tweaks"; fi
		if [ -z "$GLOBALEVALDIR" ]						; then	GLOBALEVALDIR="$SYSTEMSTLCFGDIR/eval"; fi
		if [ -z "$GLOBALSTLLANGDIR" ]					; then	GLOBALSTLLANGDIR="$SYSTEMSTLCFGDIR/lang"; fi
		if [ -z "$GLOBALSTLGUIDIR" ]					; then	GLOBALSTLGUIDIR="$SYSTEMSTLCFGDIR/guicfgs"; fi
		if [ -z "$BOXTRONCMD" ]							; then	BOXTRONCMD="/usr/share/boxtron/run-dosbox"; fi
		if [ -z "$BOXTRONARGS" ]						; then	BOXTRONARGS="--wait-before-run"; fi
		if [ -z "$ROBERTACMD" ]							; then	ROBERTACMD="$STEAMCOMPATOOLS/roberta/run-vm"; fi
		if [ -z "$ROBERTAARGS" ]						; then	ROBERTAARGS="--wait-before-run"; fi
		if [ -z "$LUXTORPEDACMD" ]						; then	LUXTORPEDACMD="$STEAMCOMPATOOLS/luxtorpeda/luxtorpeda"; fi
		if [ -z "$LUXTORPEDAARGS" ]						; then	LUXTORPEDAARGS="wait-before-run"; fi
		if [ -z "$RSVERS" ]								; then	RSVERS="5.0.0"; fi
		if [ -z "$DOWNLOAD_RESHADE" ]					; then	DOWNLOAD_RESHADE="1"; fi
		if [ -z "$RESHADESRCDIR" ]						; then	RESHADESRCDIR="$STLDLDIR/reshade"; fi
		if [ -z "$D3D47_64" ]							; then	D3D47_64="${D3D47//./_64.}"; fi
		if [ -z "$D3D47_32" ]							; then	D3D47_32="${D3D47//./_32.}"; fi
		if [ -z "$RS_64" ]								; then	RS_64="ReShade64.dll"; fi
		if [ -z "$RS_32" ]								; then	RS_32="ReShade32.dll"; fi
		if [ -z "$DLSHADER" ]							; then	DLSHADER="1"; fi
		if [ -z "$SAVESETSIZE" ]						; then	SAVESETSIZE="1"; fi
		if [ -z "$STARTMENU" ]							; then	STARTMENU="Menu"; fi
		if [ -z "$USEWINDECO" ]							; then	USEWINDECO="1"; fi
		if [ -z "$HEADLINEFONT" ]						; then	HEADLINEFONT="larger"; fi
		if [ -z "$USETRAYICON" ]						; then	USETRAYICON="1"; fi
		if [ -z "$USEGAMEPICS" ]						; then	USEGAMEPICS="1"; fi
		if [ -z "$USECUSTOMFALLBACKPIC" ]				; then	USECUSTOMFALLBACKPIC="0"; fi
		if [ -z "$GITHUBUSER" ]							; then	GITHUBUSER="$NON"; fi
		if [ -z "$DLGAMEDATA" ]							; then	DLGAMEDATA="1"; fi
		if [ -z "$USEPDBRATING" ]						; then	USEPDBRATING="1"; fi
		if [ -z "$PDBRATINGCACHE" ]						; then	PDBRATINGCACHE="1"; fi
		if [ -z "$DLWINETRICKS" ]						; then	DLWINETRICKS="0"; fi
		if [ -z "$AUTOLASTPROTON" ]						; then	AUTOLASTPROTON="1"; fi
		if [ -z "$AUTOPULLPROTON" ]						; then	AUTOPULLPROTON="1"; fi
		if [ -z "$CUSTPROTDLDIR" ]						; then	CUSTPROTDLDIR="$STLDLDIR/$PROCU"; fi
		if [ -z "$CUSTPROTEXTDIR" ]						; then	CUSTPROTEXTDIR="$STLCFGDIR/$PROCU"; fi
		if [ -z "$CUPROTOCOMPAT" ]						; then	CUPROTOCOMPAT="0"; fi
		if [ -z "$WINEDLDIR" ]							; then	WINEDLDIR="$STLDLDIR/wine"; fi
		if [ -z "$WINEEXTDIR" ]							; then	WINEEXTDIR="$STLCFGDIR/wine"; fi
		if [ -z "$USEVORTEXPROTON" ]					; then	USEVORTEXPROTON="$DEFDOTNETPROTON"; fi
		if [ -z "$VORTEXCOMPDATA" ]						; then	VORTEXCOMPDATA="$STLVORTEXDIR/$CODA"; fi
		if [ -z "$VORTEXDOWNLOADPATH" ]					; then	VORTEXDOWNLOADPATH="$STLVORTEXDIR/downloads"; fi
		if [ -z "$USEVORTEXPRERELEASE" ]				; then	USEVORTEXPRERELEASE="0"; fi
		if [ -z "$DISABLE_AUTOSTAGES" ]					; then	DISABLE_AUTOSTAGES="0"; fi
		if [ -z "$CHEATENGINEVERSION" ]					; then	CHEATENGINEVERSION="7.2"; fi
		if [ -z "$CHEATENGINEMD5SUM" ]					; then	CHEATENGINEMD5SUM="8ce5de1b284bc9f865865902fea09489"; fi
		if [ -z "$NOSTEAMSTLDEF" ]						; then	NOSTEAMSTLDEF="0"; fi
		if [ -z "$SGDBAPIKEY" ]							; then	SGDBAPIKEY="$NON"; fi
		if [ -z "$SGDBSTYLES" ]							; then	SGDBSTYLES="$SGDBSTYOPTS"; fi
		if [ -z "$SGDBDIMS" ]							; then	SGDBDIMS="$SGDBDIMOPTS"; fi
		if [ -z "$SGDBTYPES" ]							; then	SGDBTYPES="animated,static"; fi
		if [ -z "$SGDBNSFW" ]							; then	SGDBNSFW="any"; fi
		if [ -z "$SGDBHUMOR" ]							; then	SGDBHUMOR="any"; fi
		if [ -z "$SGDBDLTOSTEAM" ]						; then	SGDBDLTOSTEAM="0"; fi
		if [ -z "$SGDBHASFILE" ]						; then	SGDBHASFILE="skip"; fi
		if [ -z "$SGDBAUTODL" ]							; then	SGDBAUTODL="$NON"; fi
		if [ -z "$STORECOMPDATTITLE" ]					; then	STORECOMPDATTITLE="1"; fi
		if [ -z "$CUSTCONTY" ]							; then	CUSTCONTY="$NON"; fi
		if [ -z "$UPDATECONTY" ]						; then	UPDATECONTY="1"; fi
		if [ -z "$LOGPLAYTIME" ]						; then	LOGPLAYTIME="1"; fi
		if [ -z "$YAD" ]								; then	YAD="$(command -v "yad")"; fi
		if [ -z "$DPRSCOMPDATA" ]						; then	DPRSCOMPDATA="$STLCFGDIR/${DPRS,}/$CODA"; fi
		if [ -z "$USEDPRSPROTON" ]						; then	USEDPRSPROTON="$NON"; fi
		if [ -z "$DPRSUSEVDFSYMLINKS" ]					; then	DPRSUSEVDFSYMLINKS="0"; fi
		if [ -z "$DPRSPAUTOUP" ]						; then	DPRSPAUTOUP="0"; fi
		if [ -z "$DEPSAUTOUP" ]							; then	DEPSAUTOUP="0"; fi
		if [ -z "$MO2COMPDATA" ]						; then	MO2COMPDATA="$STLMO2DIR/$CODA"; fi
		if [ -z "$USEMO2PROTON" ]						; then	USEMO2PROTON="$DEFDOTNETPROTON"; fi
		if [ -z "$USETERM" ]							; then	USETERM="$(command -v "xterm")"; fi
		if [ -z "$TERMARGS" ]							; then	TERMARGS="-e"; fi
	}

	function setDefaultCfgValuesdefault_template {
		if [ -z "$USESLR" ]								; then	USESLR="1"; fi
		if [ -z "$FORCESLR" ]							; then	FORCESLR="0"; fi
		if [ -z "$USEREAP" ]							; then	USEREAP="1"; fi
		if [ -z "$FORCEREAP" ]							; then	FORCEREAP="0"; fi
		if [ -z "$USEPROTON" ]							; then	USEPROTON="$(getDefaultProton)"; fi
		if [ -z "$REDIRCOMPDATA" ]						; then	REDIRCOMPDATA="disabled"; fi
		if [ -z "$REDIRSTEAMUSER" ]						; then	REDIRSTEAMUSER="disabled"; fi
		if [ -z "$AUTOBUMPGE" ]							; then	AUTOBUMPGE="0"; fi
		if [ -z "$USECUSTOMCMD" ]						; then	USECUSTOMCMD="0"; fi
		if [ -z "$CUSTOMCMD" ]							; then	CUSTOMCMD="$DUMMYBIN"; fi
		if [ -z "$CUSTOMCMD_ARGS" ]						; then	CUSTOMCMD_ARGS="$NON"; fi
		if [ -z "$ONLY_CUSTOMCMD" ]						; then	ONLY_CUSTOMCMD="0";	fi
		if [ -z "$FORK_CUSTOMCMD" ]						; then	FORK_CUSTOMCMD="0";	fi
		if [ -z "$INJECT_CUSTOMCMD" ]					; then	INJECT_CUSTOMCMD="0"; fi
		if [ -z "$INJECTWAIT" ]							; then	INJECTWAIT="0";	fi
		if [ -z "$USEIGCS" ]							; then	USEIGCS="0"; fi
		if [ -z "$UUUSEIGCS" ]							; then	UUUSEIGCS="0"; fi
		if [ -z "$IGCSWAIT" ]							; then	IGCSWAIT="0"; fi
		if [ -z "$UUUSEPATCH" ]							; then	UUUSEPATCH="0"; fi
		if [ -z "$UUUPATCHWAIT" ]						; then	UUUPATCHWAIT="0"; fi
		if [ -z "$UUUSEVR" ]							; then	UUUSEVR="0"; fi
		if [ -z "$GAMEARGS" ]							; then	GAMEARGS="$NON"; fi
		if [ -z "$HARDARGS" ]							; then	HARDARGS="$NOPE"; fi
		if [ -z "$USEGAMEMODERUN" ]						; then	USEGAMEMODERUN="0";	fi
		if [ -z "$USEGAMESCOPE" ]						; then	USEGAMESCOPE="0"; fi
		if [ -z "$GAMESCOPE_ARGS" ]						; then	GAMESCOPE_ARGS="--"; fi
		if [ -z "$TOGSTEAMWEBHELPER" ]					; then	TOGSTEAMWEBHELPER="0"; fi
		if [ -z "$MANGOHUD" ]							; then	MANGOHUD="0";	fi
		if [ -z "$ENABLE_VKBASALT" ]					; then	ENABLE_VKBASALT="0"; fi
		if [ -z "$RUN_NYRNA" ]							; then	RUN_NYRNA="0"; fi
		if [ -z "$RUN_REPLAY" ]							; then	RUN_REPLAY="0";	fi
		if [ -z "$RUN_GAMCON" ]							; then	RUN_GAMCON="0";	fi
		if [ -z "$RUN_CHEATENGINE" ]					; then	RUN_CHEATENGINE="0"; fi
		if [ -z "$GAMCONWAITEXE" ]						; then	GAMCONWAITEXE="$DUMMYBIN"; fi
		if [ -z "$RUN_X64DBG" ]							; then	RUN_X64DBG="0";	fi
		if [ -z "$RUN_GDB" ]							; then	RUN_GDB="0";	fi
		if [ -z "$USEVORTEX" ]							; then	USEVORTEX="0"; fi
		if [ -z "$WAITVORTEX" ]							; then	WAITVORTEX="2"; fi
		if [ -z "$RUN_VORTEX_WINETRICKS" ]				; then	RUN_VORTEX_WINETRICKS="0"; fi
		if [ -z "$RUN_VORTEX_WINECFG" ]					; then	RUN_VORTEX_WINECFG="0";fi
		if [ -z "$CHANGE_PULSE_LATENCY" ] 				; then	CHANGE_PULSE_LATENCY="0"; fi
		if [ -z "$STL_PULSE_LATENCY_MSEC" ]				; then	STL_PULSE_LATENCY_MSEC="60"; fi
		if [ -z "$TOGGLEWINDOWS" ]						; then	TOGGLEWINDOWS="0"; fi
		if [ -z "$RUN_WINETRICKS" ]						; then	RUN_WINETRICKS="0"; fi
		if [ -z "$WINETRICKSPAKS" ]						; then	WINETRICKSPAKS="$NON"; fi
		if [ -z "$RUN_WINECFG" ]						; then	RUN_WINECFG="0"; fi
		if [ -z "$USEWINE" ]							; then	USEWINE="0"; fi
		if [ -z "$WINEVERSION" ]						; then	WINEVERSION="$DUMMYBIN"; fi
		if [ -z "$WINEDEFAULT" ]						; then	WINEDEFAULT="$DUMMYBIN"; fi
		if [ -z "$USEWICO" ]							; then	USEWICO="0"; fi
		if [ -z "$VIRTUALDESKTOP" ]						; then	VIRTUALDESKTOP="0"; fi
		if [ -z "$VDRES" ]								; then	VDRES="$NON"; fi
		if [ -z "$USEBOXTRON" ]							; then	USEBOXTRON="0"; fi
		if [ -z "$USEROBERTA" ]							; then	USEROBERTA="0"; fi
		if [ -z "$USELUXTORPEDA" ]						; then	USELUXTORPEDA="0"; fi
		if [ -z "$REGEDIT" ]							; then	REGEDIT="0"; fi
		if [ -z "$INSTALL_RESHADE" ]					; then	INSTALL_RESHADE="0"; fi
		if [ -z "$RESHADE_DEPTH3D" ]					; then	RESHADE_DEPTH3D="0"; fi
		if [ -z "$USERESHADE" ]							; then	USERESHADE="0"; fi
		if [ -z "$RESHADEUPDATE" ]						; then	RESHADEUPDATE="0"; fi
		if [ -z "$CHOOSESHADERS" ]						; then	CHOOSESHADERS="0"; fi
		if [ -z "$ALTEXEPATH" ]							; then	ALTEXEPATH="/tmp"; fi
		if [ -z "$ARCHALTEXE" ]							; then	ARCHALTEXE="$DUMMYBIN"; fi
		if [ -z "$USEOPENVRFSR" ]						; then	USEOPENVRFSR="0"; fi
		if [ -z "$RUNSBSVR" ]							; then	RUNSBSVR="0"; fi
		if [ -z "$VRVIDEOPLAYERARGS" ]					; then	VRVIDEOPLAYERARGS="--flat"; fi
		if [ -z "$SBSZOOM" ]							; then	SBSZOOM="1.0"; fi
		if [ -z "$SBSVRRS" ]							; then	SBSVRRS="0"; fi
		if [ -z "$MINVRWINH" ] 							; then	MINVRWINH="640"; fi
		if [ -z "$WAITFORTHISPID" ]						; then	WAITFORTHISPID="$NON"; fi
		if [ -z "$WAITEDITOR" ]							; then	WAITEDITOR="2"; fi
		if [ -z "$HELPURL" ]							; then	HELPURL="$NON"; fi
		if [ -z "$CREATEDESKTOPICON" ]					; then	CREATEDESKTOPICON="0"; fi
		if [ -z "$STEAMAPPIDFILE" ]						; then	STEAMAPPIDFILE="0"; fi
		if [ -z "$CHECKCATEGORIES" ]					; then	CHECKCATEGORIES="1"; fi
		if [ -z "$BACKUPSTEAMUSER" ]					; then	BACKUPSTEAMUSER="0"; fi
		if [ -z "$RESTORESTEAMUSER" ]					; then	RESTORESTEAMUSER="$NON"; fi
		if [ -z "$USESUSYM" ]							; then	USESUSYM="0"; fi
		if [ -z "$USEGLOBSUSYM" ]						; then	USEGLOBSUSYM="0"; fi
		if [ -z "$STRACERUN" ]							; then	STRACERUN="0"; fi
		if [ -z "$STRACEOPTS" ]							; then	STRACEOPTS="-f -t -e trace=file"; fi
		if [ -z "$USENETMON" ]							; then	USENETMON="0"; fi
		if [ -z "$BLOCKINTERNET" ]						; then	BLOCKINTERNET="0"; fi
		if [ -z "$DXVK_HUD" ]							; then	DXVK_HUD="0"; fi
		if [ -z "$DXVK_LOG_LEVEL" ]						; then	DXVK_LOG_LEVEL="$NON"; fi
		if [ -z "$DXVK_LOG_PATH" ]						; then	DXVK_LOG_PATH="$STLDXVKLOGDIR"; fi
		if [ -z "$DXVK_SCALE" ]							; then	DXVK_SCALE="1.0"; fi
		if [ -z "$PROTON_LOG" ]							; then	PROTON_LOG="0"; fi
		if [ -z "$PROTON_LOG_DIR" ]						; then	PROTON_LOG_DIR="$STLPROTONIDLOGDIR"; fi
		if [ -z "$USEWINEDEBUGPROTON" ]					; then	USEWINEDEBUGPROTON="0"; fi
		if [ -z "$WINE_LOG_DIR" ]						; then	WINE_LOG_DIR="$STLWINELOGDIR"; fi
		if [ -z "$PROTON_DEBUG_DIR" ]					; then	PROTON_DEBUG_DIR="/tmp"; fi
		if [ -z "$PROTON_USE_WINED3D" ]					; then	PROTON_USE_WINED3D="0"; fi
		if [ -z "$PROTON_NO_D3D11" ]					; then	PROTON_NO_D3D11="0"; fi
		if [ -z "$PROTON_NO_D3D10" ]					; then	PROTON_NO_D3D10="0"; fi
		if [ -z "$PROTON_NO_ESYNC" ]					; then	PROTON_NO_ESYNC="0"; fi
		if [ -z "$PROTON_NO_FSYNC" ]					; then	PROTON_NO_FSYNC="0"; fi
		if [ -z "$PROTON_ENABLE_NVAPI" ]				; then	PROTON_ENABLE_NVAPI="0"; fi
		if [ -z "$PROTON_HIDE_NVIDIA_GPU" ]				; then	PROTON_HIDE_NVIDIA_GPU="1"; fi
		if [ -z "$STL_VKD3D_CONFIG" ]					; then	STL_VKD3D_CONFIG="$NON"; fi
		if [ -z "$STL_VKD3D_DEBUG" ]					; then	STL_VKD3D_DEBUG="$NON"; fi
		if [ -z "$STL_VKD3D_SHADER_DEBUG" ]				; then	STL_VKD3D_SHADER_DEBUG="$NON"; fi
		if [ -z "$STL_VKD3D_LOG_FILE" ]					; then	STL_VKD3D_LOG_FILE="$NON"; fi
		if [ -z "$STL_VKD3D_VULKAN_DEVICE" ]			; then	STL_VKD3D_VULKAN_DEVICE="$NON"; fi
		if [ -z "$STL_VKD3D_FILTER_DEVICE_NAME" ]		; then	STL_VKD3D_FILTER_DEVICE_NAME="$NON"; fi
		if [ -z "$STL_VKD3D_DISABLE_EXTENSIONS" ]		; then	STL_VKD3D_DISABLE_EXTENSIONS="$NON"; fi
		if [ -z "$STL_VKD3D_TEST_DEBUG" ]				; then	STL_VKD3D_TEST_DEBUG="0"; fi
		if [ -z "$STL_VKD3D_TEST_FILTER" ]				; then	STL_VKD3D_TEST_FILTER="$NON"; fi
		if [ -z "$STL_VKD3D_TEST_EXCLUDE" ]				; then	STL_VKD3D_TEST_EXCLUDE="$NON"; fi
		if [ -z "$STL_VKD3D_TEST_PLATFORM" ]			; then	STL_VKD3D_TEST_PLATFORM="$NON"; fi
		if [ -z "$STL_VKD3D_TEST_BUG" ]					; then	STL_VKD3D_TEST_BUG="$NON"; fi
		if [ -z "$STL_VKD3D_PROFILE_PATH" ]				; then	STL_VKD3D_PROFILE_PATH="$NON"; fi
		if [ -z "$USEDLSS" ]							; then	USEDLSS="0"; fi
		if [ -z "$USERAYTRACING" ]						; then	USERAYTRACING="0"; fi
		if [ -z "$PROTON_FORCE_LARGE_ADDRESS_AWARE" ]	; then	PROTON_FORCE_LARGE_ADDRESS_AWARE="1"; fi
		if [ -z "$PROTON_DUMP_DEBUG_COMMANDS" ]			; then	PROTON_DUMP_DEBUG_COMMANDS="0"; fi
		if [ -z "$CLEANPROTONTEMP" ]					; then	CLEANPROTONTEMP="0"; fi
		if [ -z "$WINE_FULLSCREEN_INTEGER_SCALING" ]	; then	WINE_FULLSCREEN_INTEGER_SCALING="0"; fi
		if [ -z "$WINE_FULLSCREEN_FSR" ]				; then	WINE_FULLSCREEN_FSR="0"; fi
		if [ -z "$WINE_FULLSCREEN_FSR_STRENGTH" ]		; then	WINE_FULLSCREEN_FSR_STRENGTH="5"; fi
		if [ -z "$STLWINEDEBUG" ]						; then	STLWINEDEBUG="-all"; fi
		if [ -z "$STLWINEDLLOVERRIDES" ]				; then	STLWINEDLLOVERRIDES="$NON"; fi
		if [ -z "$USERSTART" ]							; then	USERSTART="$DUMMYBIN"; fi
		if [ -z "$USERSTOP" ]							; then	USERSTOP="$DUMMYBIN"; fi	
		if [ -z "$STL_PV_VERBOSE" ]						; then	STL_PV_VERBOSE="0"; fi
		if [ -z "$STL_PV_SHELL" ]						; then	STL_PV_SHELL="$NON"; fi
		if [ -z "$STL_PV_TERMINAL" ]					; then	STL_PV_TERMINAL="$NON"; fi
		if [ -z "$AUTOCONTY" ]							; then	AUTOCONTY="0"; fi
		if [ -z "$USECONTY" ]							; then	USECONTY="0"; fi
		if [ -z "$CRASHGUESS" ]							; then	CRASHGUESS="60"; fi
		if [ -z "$ONLYWICO" ]							; then	ONLYWICO="0"; fi
		if [ -z "$GAMESCREENRES" ]						; then	GAMESCREENRES="$NON"; fi
		if [ -z "$FIXSYMLINKS" ]						; then	FIXSYMLINKS="0"; fi
		if [ -z "$UNSYMLINK" ]							; then	UNSYMLINK="0"; fi
		if [ -z "$DELPFX" ]								; then	DELPFX="0"; fi
		if [ -z "$RUN_DEPS" ]							; then	RUN_DEPS="0"; fi
		if [ -z "$SORTGARGS" ]							; then	SORTGARGS="0"; fi
		if [ -z "$MO2MODE" ]							; then	MO2MODE="disabled"; fi
		if [ -z "$WAITMO2" ]							; then	WAITMO2="2"; fi
		if [ -z "$USEMANGOHUDSTLCFG" ]					; then	USEMANGOHUDSTLCFG="0";	fi
		if [ -z "$USESPECIALK" ]						; then	USESPECIALK="0"; fi
		if [ -z "$SPEKVERS" ]							; then	SPEKVERS="old"; fi
		if [ -z "$USEFWS" ]								; then	USEFWS="0"; fi
		if [ -z "$USEPEV_PELDD" ]						; then	USEPEV_PELDD="0"; fi
		if [ -z "$USEPEV_PEPACK" ]						; then	USEPEV_PEPACK="0"; fi
		if [ -z "$USEPEV_PERES" ]						; then	USEPEV_PERES="0"; fi
		if [ -z "$USEPEV_PESCAN" ]						; then	USEPEV_PESCAN="0"; fi
		if [ -z "$USEPEV_PESEC" ]						; then	USEPEV_PESEC="0"; fi
		if [ -z "$USEPEV_PESTR" ]						; then	USEPEV_PESTR="0"; fi
		if [ -z "$USEPEV_READPE" ]						; then	USEPEV_READPE="0"; fi
	}
	
	"${FUNCNAME[0]}$1"
}

function saveCfg {

	function saveCfgurl {

		setDefaultCfgValues "$2"
		
		if [ -f "$1" ]; then
			updateConfigFile "$1" "${FUNCNAME[0]}" "$3"
		else
			#STARTsaveCfgurl
			{
			echo "## config Version: $PROGVERS"
			echo "##########################"
			echo "## Url Config:"
			echo "##########################"
			echo "PROJECTPAGE=\"$PROJECTPAGE\""
			echo "##########################"
			echo "## Proton GE DL URL"
			echo "CP_PROTONGE=\"$CP_PROTONGE\""
			echo "## Proton TKG DL URL"
			echo "CP_PROTONTKG=\"$CP_PROTONTKG\""
			echo "## Proton STL DL URL"
			echo "CP_PROTONSTL=\"$CP_PROTONSTL\""
			echo "## Wine Kron4ek URL"
			echo "CW_KRON4EK=\"$CW_KRON4EK\""
			echo "## d3d47 64bit DL URL "
			echo "DL_D3D47_64=\"$DL_D3D47_64\""
			echo "## d3d47 32bit DL URL"
			echo "DL_D3D47_32=\"$DL_D3D47_32\""
			echo "## Dxvk Project URL"
			echo "DXVKURL=\"$DXVKURL\""				
			echo "## ${RESH} DL URL"
			echo "RESHADEDLURL=\"$RESHADEDLURL\""
			echo "## ${VTX^} DL URL"
			echo "VORTEXRELURL=\"$VORTEXRELURL\""
			echo "## Xlive DL URL"
			echo "XLIVEURL=\"$XLIVEURL\""
			echo "## Steam Asset URL"
			echo "STASSURL=\"$STASSURL\""
			echo "## winetricks URL"
			echo "WINETRICKSURL=\"$WINETRICKSURL\""
			echo "## Cheat Engine URL"
			echo "CHEATENGINEURL=\"$CHEATENGINEURL\""
			echo "## x64dbg URL"
			echo "X64DBGURL=\"$X64DBGURL\""
			echo "## SteamGridDB Api URL"
			echo "STEAMGRIDDBAPI=\"$STEAMGRIDDBAPI\""
			echo "## Conty DL URL"
			echo "CONTYRELURL=\"$CONTYRELURL\""
			echo "## Mod Organizer 2 DL URL"
			echo "MO2DLURL=\"$MO2DLURL\""
			echo "## $DPRS DL URL"
			echo "DPRSRELURL=\"$DPRSRELURL\""
			echo "## $DEPS URL"
			echo "DEPURL=\"$DEPURL\""
			echo "## $SPEK old DLL URL"
			echo "SPEKOLDDLURL=\"$SPEKOLDDLURL\""
			echo "## $SPEK URL"
			echo "SPEKURL=\"$SPEKURL\""
			echo "## $SPEK compatibility URL"
			echo "SPEKCOMPURL=\"$SPEKCOMPURL\""
			echo "## $FWS DL URL"
			echo "FWSURL=\"$FWSURL\""
			echo "## $YAD appimage url"
			echo "YAIURL=\"$YAIURL\""
			} >> "$1"
			#ENDsaveCfgurl
		fi
	}
	
	function saveCfggui {

		setDefaultCfgValues "$2"
		
		if [ -f "$1" ]; then
			updateConfigFile "$1" "${FUNCNAME[0]}" "$3"
		else
			#STARTsaveCfggui
			{
			echo "## config Version: $PROGVERS"
			echo "##########################"
			echo "## Settings Selection GUI:"
			echo "WINX=\"$WINX\""
			echo "WINY=\"$WINY\""
			echo "POSX=\"$POSX\""
			echo "POSY=\"$POSY\""		
			} >> "$1"
			#ENDsaveCfggui
		fi
	}

	function saveCfgglobal {

		setDefaultCfgValues "$2"

		if [ -f "$1" ]; then
			updateConfigFile "$1" "${FUNCNAME[0]}" "$3"
		else
			#STARTsaveCfgglobal
			{
			echo "## config Version: $PROGVERS"
			echo "##########################"
			echo "## $DESC_STLLANG"
			echo "STLLANG=\"$STLLANG\""
			echo "## $DESC_SKIPINTDEPCHECK"
			echo "SKIPINTDEPCHECK=\"$SKIPINTDEPCHECK\""
			echo "## $DESC_YAD"
			echo "YAD=\"$YAD\""
			echo "## $DESC_CUSTPROTDLDIR"
			echo "CUSTPROTDLDIR=\"$CUSTPROTDLDIR\""
			echo "## $DESC_CUSTPROTEXTDIR"
			echo "CUSTPROTEXTDIR=\"$CUSTPROTEXTDIR\""
			echo "## $DESC_CUPROTOCOMPAT"
			echo "CUPROTOCOMPAT=\"$CUPROTOCOMPAT\""
			echo "## $DESC_WINEDLDIR"
			echo "WINEDLDIR=\"$WINEDLDIR\""
			echo "## $DESC_WINEEXTDIR"
			echo "WINEEXTDIR=\"$WINEEXTDIR\""			
			echo "## $DESC_AUTOLASTPROTON"
			echo "AUTOLASTPROTON=\"$AUTOLASTPROTON\""
			echo "## $DESC_STRACEDIR"
			echo "STRACEDIR=\"$STRACEDIR\""
			echo "## $(strFix "$DESC_LOGDIR" "$PROGNAME")"
			echo "LOGDIR=\"$LOGDIR\""
			echo "## $DESC_LOGLEVEL"
			echo "LOGLEVEL=\"$LOGLEVEL\""
			echo "## $DESC_RESETLOG"
			echo "RESETLOG=\"$RESETLOG\""
			echo "## $DESC_STLEDITOR"
			echo "STLEDITOR=\"$STLEDITOR\""
			echo "## $DESC_MAXASK"
			echo "MAXASK=\"$MAXASK\""
			echo "## $DESC_BROWSER"
			echo "BROWSER=\"$BROWSER\""
			echo "## $DESC_USENOTIFIER"
			echo "USENOTIFIER=\"$USENOTIFIER\""
			echo "## $DESC_NOTY"
			echo "NOTY=\"$NOTY\""
			echo "## $DESC_NOTYARGS"
			echo "NOTYARGS=\"$NOTYARGS\""
			echo "## $DESC_NETMON"
			echo "NETMON=\"$NETMON\""
			echo "## $DESC_NETOPTS"
			echo "NETOPTS=\"$NETOPTS\""
			echo "## $DESC_NETMONDIR"
			echo "NETMONDIR=\"$NETMONDIR\""
			echo "## $DESC_VRVIDEOPLAYER"
			echo "VRVIDEOPLAYER=\"$VRVIDEOPLAYER\""
			echo "## $DESC_GAMCON"
			echo "GAMCON=\"$GAMCON\""
			echo "## $DESC_GLOBALSBSTWEAKS"
			echo "GLOBALSBSTWEAKS=\"$GLOBALSBSTWEAKS\""
			echo "## $DESC_GLOBALTWEAKS"
			echo "GLOBALTWEAKS=\"$GLOBALTWEAKS\""
			echo "## $DESC_GLOBALCATEGORYDIR"
			echo "GLOBALCATEGORYDIR=\"$GLOBALCATEGORYDIR\""
			echo "## $DESC_GLOBALMISCDIR"
			echo "GLOBALMISCDIR=\"$GLOBALMISCDIR\""
			echo "## $DESC_GLOBALEVALDIR"
			echo "GLOBALEVALDIR=\"$GLOBALEVALDIR\""
			echo "## $DESC_GLOBALSTLLANGDIR"
			echo "GLOBALSTLLANGDIR=\"$GLOBALSTLLANGDIR\""
			echo "## $DESC_GLOBALSTLGUIDIR"
			echo "GLOBALSTLGUIDIR=\"$GLOBALSTLGUIDIR\""
			echo "## $DESC_BOXTRONCMD"
			echo "BOXTRONCMD=\"$BOXTRONCMD\""
			echo "## $DESC_BOXTRONARGS"
			echo "BOXTRONARGS=\"$BOXTRONARGS\""
			echo "## $DESC_ROBERTACMD"
			echo "ROBERTACMD=\"$ROBERTACMD\""
			echo "## $DESC_ROBERTAARGS"
			echo "ROBERTAARGS=\"$ROBERTAARGS\""
			echo "## $DESC_LUXTORPEDACMD"
			echo "LUXTORPEDACMD=\"$LUXTORPEDACMD\""
			echo "## $DESC_LUXTORPEDAARGS"
			echo "LUXTORPEDAARGS=\"$LUXTORPEDAARGS\""
			echo "## $DESC_DOWNLOAD_RESHADE"
			echo "DOWNLOAD_RESHADE=\"$DOWNLOAD_RESHADE\""
			echo "## $DESC_RSVERS"
			echo "RSVERS=\"$RSVERS\""
			echo "## $DESC_RESHADESRCDIR"
			echo "RESHADESRCDIR=\"$RESHADESRCDIR\""
			echo "## $DESC_D3D47_64"
			echo "D3D47_64=\"$D3D47_64\""
			echo "## $DESC_D3D47_32"
			echo "D3D47_32=\"$D3D47_32\""
			echo "## $DESC_RS_64"
			echo "RS_64=\"$RS_64\""
			echo "## $DESC_RS_32"
			echo "RS_32=\"$RS_32\""
			echo "## $DESC_DLSHADER"
			echo "DLSHADER=\"$DLSHADER\""
			echo "## $DESC_SAVESETSIZE"
			echo "SAVESETSIZE=\"$SAVESETSIZE\""
			echo "## $DESC_STARTMENU"
			echo "STARTMENU=\"$STARTMENU\""
			echo "## $DESC_HEADLINEFONT"
			echo "HEADLINEFONT=\"$HEADLINEFONT\""
			echo "## $DESC_USEWINDECO"
			echo "USEWINDECO=\"$USEWINDECO\""
			echo "## $DESC_USETRAYICON"
			echo "USETRAYICON=\"$USETRAYICON\""
			echo "## $DESC_USEGAMEPICS"
			echo "USEGAMEPICS=\"$USEGAMEPICS\""
			echo "## $DESC_USECUSTOMFALLBACKPIC"
			echo "USECUSTOMFALLBACKPIC=\"$USECUSTOMFALLBACKPIC\""
			echo "## $DESC_GITHUBUSER"
			echo "GITHUBUSER=\"$GITHUBUSER\""
			echo "## $DESC_DLGAMEDATA"
			echo "DLGAMEDATA=\"$DLGAMEDATA\""
			echo "## $DESC_USEPDBRATING"
			echo "USEPDBRATING=\"$USEPDBRATING\""
			echo "## $DESC_PDBRATINGCACHE"
			echo "PDBRATINGCACHE=\"$PDBRATINGCACHE\""
			echo "## $DESC_DLWINETRICKS"
			echo "DLWINETRICKS=\"$DLWINETRICKS\""
			echo "## $DESC_USEVORTEXPROTON"
			echo "USEVORTEXPROTON=\"$USEVORTEXPROTON\""
			echo "## $DESC_VORTEXCOMPDATA"
			echo "VORTEXCOMPDATA=\"$VORTEXCOMPDATA\""
			echo "## $DESC_VORTEXDOWNLOADPATH"
			echo "VORTEXDOWNLOADPATH=\"$VORTEXDOWNLOADPATH\""
			echo "## $DESC_USEVORTEXPRERELEASE"
			echo "USEVORTEXPRERELEASE=\"$USEVORTEXPRERELEASE\""
			echo "## $(strFix "$DESC_DISABLE_AUTOSTAGES" "$PROGNAME")"
			echo "DISABLE_AUTOSTAGES=\"$DISABLE_AUTOSTAGES\""
			echo "## $DESC_CHEATENGINEVERSION"
			echo "CHEATENGINEVERSION=\"$CHEATENGINEVERSION\""
			echo "## $DESC_CHEATENGINEMD5SUM"
			echo "CHEATENGINEMD5SUM=\"$CHEATENGINEMD5SUM\""
			echo "## $DESC_NOSTEAMSTLDEF"
			echo "NOSTEAMSTLDEF=\"$NOSTEAMSTLDEF\""
			echo "## $DESC_SGDBAPIKEY"
			echo "SGDBAPIKEY=\"$SGDBAPIKEY\""
			echo "## $DESC_SGDBSTYLES"
			echo "SGDBSTYLES=\"$SGDBSTYLES\""
			echo "## $DESC_SGDBDIMS"
			echo "SGDBDIMS=\"$SGDBDIMS\""
			echo "## $DESC_SGDBTYPES"
			echo "SGDBTYPES=\"$SGDBTYPES\""
			echo "## $DESC_SGDBNSFW"
			echo "SGDBNSFW=\"$SGDBNSFW\""
			echo "## $DESC_SGDBHUMOR"
			echo "SGDBHUMOR=\"$SGDBHUMOR\""
			echo "## $DESC_SGDBDLTOSTEAM"
			echo "SGDBDLTOSTEAM=\"$SGDBDLTOSTEAM\""
			echo "## $DESC_SGDBHASFILE"
			echo "SGDBHASFILE=\"$SGDBHASFILE\""
			echo "## $DESC_SGDBAUTODL"
			echo "SGDBAUTODL=\"$SGDBAUTODL\""
			echo "## $DESC_STORECOMPDATTITLE"
			echo "STORECOMPDATTITLE=\"$STORECOMPDATTITLE\""
			echo "## $DESC_CUSTCONTY"
			echo "CUSTCONTY=\"$CUSTCONTY\""
			echo "## $DESC_UPDATECONTY"
			echo "UPDATECONTY=\"$UPDATECONTY\""
			echo "## $DESC_LOGPLAYTIME"
			echo "LOGPLAYTIME=\"$LOGPLAYTIME\""
			echo "## $DESC_DPRSCOMPDATA"
			echo "DPRSCOMPDATA=\"$DPRSCOMPDATA\""
			echo "## $DESC_USEDPRSPROTON"
			echo "USEDPRSPROTON=\"$USEDPRSPROTON\""
			echo "## $DESC_DPRSUSEVDFSYMLINKS"
			echo "DPRSUSEVDFSYMLINKS=\"$DPRSUSEVDFSYMLINKS\""
			echo "## $DESC_DPRSPAUTOUP"
			echo "DPRSPAUTOUP=\"$DPRSPAUTOUP\""
			echo "## $DESC_DEPSAUTOUP"
			echo "DEPSAUTOUP=\"$DEPSAUTOUP\""
			echo "## $DESC_MO2COMPDATA"
			echo "MO2COMPDATA=\"$MO2COMPDATA\""
			echo "## $DESC_USEMO2PROTON"
			echo "USEMO2PROTON=\"$USEMO2PROTON\""
			echo "## $DESC_USETERM"
			echo "USETERM=\"$USETERM\""
			echo "## $DESC_TERMARGS"
			echo "TERMARGS=\"$TERMARGS\""

			} >> "$1"
			#ENDsaveCfgglobal
		fi
		updateEditor "$1"
	}

	function saveCfgdefault_template {

		setDefaultCfgValues "$2"

		if [ -f "$1" ]; then
			updateConfigFile "$1" "${FUNCNAME[0]}" "$3"
		else
			#STARTsaveCfgdefault_template
			{
			echo "## config Version: $PROGVERS"
			echo "##########################"
			echo "## $DESC_USESLR"
			echo "USESLR=\"$USESLR\""
			echo "## $DESC_FORCESLR"
			echo "FORCESLR=\"$FORCESLR\""
			echo "## $DESC_USEREAP"
			echo "USEREAP=\"$USEREAP\""
			echo "## $DESC_FORCEREAP"
			echo "FORCEREAP=\"$FORCEREAP\""
			echo "## $DESC_USEPROTON"
			echo "USEPROTON=\"$USEPROTON\""
			echo "## $DESC_REDIRCOMPDATA"
			echo "REDIRCOMPDATA=\"$REDIRCOMPDATA\""
			echo "## $DESC_REDIRSTEAMUSER"
			echo "REDIRSTEAMUSER=\"$REDIRSTEAMUSER\""
			echo "## $DESC_AUTOBUMPGE"
			echo "AUTOBUMPGE=\"$AUTOBUMPGE\""
			echo "## $DESC_USECUSTOMCMD"
			echo "USECUSTOMCMD=\"$USECUSTOMCMD\""
			echo "## $DESC_CUSTOMCMD"
			echo "CUSTOMCMD=\"$CUSTOMCMD\""
			echo "## $DESC_CUSTOMCMD_ARGS"
			echo "CUSTOMCMD_ARGS=\"$CUSTOMCMD_ARGS\""
			echo "## $DESC_ONLY_CUSTOMCMD"
			echo "ONLY_CUSTOMCMD=\"$ONLY_CUSTOMCMD\""
			echo "## $DESC_FORK_CUSTOMCMD"
			echo "FORK_CUSTOMCMD=\"$FORK_CUSTOMCMD\""
			echo "## $DESC_INJECT_CUSTOMCMD"
			echo "INJECT_CUSTOMCMD=\"$INJECT_CUSTOMCMD\""
			echo "## $DESC_INJECTWAIT"
			echo "INJECTWAIT=\"$INJECTWAIT\""
			echo "## $DESC_USEIGCS"
			echo "USEIGCS=\"$USEIGCS\""
			echo "## $DESC_UUUSEIGCS"
			echo "UUUSEIGCS=\"$UUUSEIGCS\""
			echo "## $DESC_IGCSWAIT"
			echo "IGCSWAIT=\"$IGCSWAIT\""
			echo "## $DESC_UUUSEPATCH"
			echo "UUUSEPATCH=\"$UUUSEPATCH\""
			echo "## $DESC_UUUPATCHWAIT"
			echo "UUUPATCHWAIT=\"$UUUPATCHWAIT\""
			echo "## $DESC_UUUSEVR"
			echo "UUUSEVR=\"$UUUSEVR\""
			echo "## $DESC_GAMEARGS"
			echo "GAMEARGS=\"$GAMEARGS\""
			echo "## $DESC_HARDARGS"
			echo "HARDARGS=\"$HARDARGS\""
			echo "## $DESC_USEGAMEMODERUN"
			echo "USEGAMEMODERUN=\"$USEGAMEMODERUN\""
			echo "## $DESC_USEGAMESCOPE"
			echo "USEGAMESCOPE=\"$USEGAMESCOPE\""
			echo "## $DESC_GAMESCOPE_ARGS"
			echo "GAMESCOPE_ARGS=\"$GAMESCOPE_ARGS\""
			echo "## $DESC_TOGSTEAMWEBHELPER"
			echo "TOGSTEAMWEBHELPER=\"$TOGSTEAMWEBHELPER\""
			echo "## $DESC_MANGOHUD"
			echo "MANGOHUD=\"$MANGOHUD\""
			echo "## $DESC_ENABLE_VKBASALT"
			echo "ENABLE_VKBASALT=\"$ENABLE_VKBASALT\""
			echo "## $DESC_RUN_NYRNA"
			echo "RUN_NYRNA=\"$RUN_NYRNA\""
			echo "## $DESC_RUN_REPLAY"
			echo "RUN_REPLAY=\"$RUN_REPLAY\""
			echo "## $DESC_RUN_GAMCON"
			echo "RUN_GAMCON=\"$RUN_GAMCON\""
			echo "## $DESC_RUN_CHEATENGINE"
			echo "RUN_CHEATENGINE=\"$RUN_CHEATENGINE\""
			echo "## $DESC_GAMCONWAITEXE"
			echo "GAMCONWAITEXE=\"$GAMCONWAITEXE\""
			echo "## $DESC_RUN_X64DBG"
			echo "RUN_X64DBG=\"$RUN_X64DBG\""
			echo "## $DESC_RUN_GDB"
			echo "RUN_GDB=\"$RUN_GDB\""
			echo "## $DESC_USEVORTEX"
			echo "USEVORTEX=\"$USEVORTEX\""
			echo "## $DESC_WAITVORTEX"
			echo "WAITVORTEX=\"$WAITVORTEX\""
			echo "## $DESC_RUN_VORTEX_WINETRICKS"
			echo "RUN_VORTEX_WINETRICKS=\"$RUN_VORTEX_WINETRICKS\""
			echo "## $DESC_RUN_VORTEX_WINECFG"
			echo "RUN_VORTEX_WINECFG=\"$RUN_VORTEX_WINECFG\""
			echo "## $DESC_CHANGE_PULSE_LATENCY"
			echo "CHANGE_PULSE_LATENCY=\"$CHANGE_PULSE_LATENCY\""
			echo "## $DESC_STL_PULSE_LATENCY_MSEC"
			echo "STL_PULSE_LATENCY_MSEC=\"$STL_PULSE_LATENCY_MSEC\""
			echo "## $DESC_TOGGLEWINDOWS"
			echo "TOGGLEWINDOWS=\"$TOGGLEWINDOWS\""
			echo "## $DESC_RUN_WINETRICKS"
			echo "RUN_WINETRICKS=\"$RUN_WINETRICKS\""
			echo "## $DESC_WINETRICKSPAKS"
			echo "WINETRICKSPAKS=\"$WINETRICKSPAKS\""
			echo "## $DESC_RUN_WINECFG"
			echo "RUN_WINECFG=\"$RUN_WINECFG\""
			echo "## $DESC_USEWINE"
			echo "USEWINE=\"$USEWINE\""
			echo "## $DESC_USEWICO"
			echo "USEWICO=\"$USEWICO\""
			echo "## $DESC_WINEVERSION"
			echo "WINEVERSION=\"$WINEVERSION\""
			echo "## $DESC_WINEDEFAULT"
			echo "WINEDEFAULT=\"$WINEDEFAULT\""
			echo "## $DESC_VIRTUALDESKTOP"
			echo "VIRTUALDESKTOP=\"$VIRTUALDESKTOP\""
			echo "## $DESC_VDRES"
			echo "VDRES=\"$VDRES\""
			echo "## $DESC_USEBOXTRON"
			echo "USEBOXTRON=\"$USEBOXTRON\""
			echo "## $DESC_USEROBERTA"
			echo "USEROBERTA=\"$USEROBERTA\""
			echo "## $DESC_USELUXTORPEDA"
			echo "USELUXTORPEDA=\"0\""
			echo "## $DESC_REGEDIT"
			echo "REGEDIT=\"$REGEDIT\""
			echo "## $DESC_INSTALL_RESHADE"
			echo "INSTALL_RESHADE=\"$INSTALL_RESHADE\""
			echo "## $DESC_RESHADE_DEPTH3D"
			echo "RESHADE_DEPTH3D=\"$RESHADE_DEPTH3D\""
			echo "## $DESC_USERESHADE"
			echo "USERESHADE=\"$USERESHADE\""
			echo "## $DESC_RESHADEUPDATE"
			echo "RESHADEUPDATE=\"$RESHADEUPDATE\""
			echo "## $DESC_CHOOSESHADERS"
			echo "CHOOSESHADERS=\"$CHOOSESHADERS\""
			echo "## $DESC_ALTEXEPATH"
			echo "ALTEXEPATH=\"$ALTEXEPATH\""
			echo "## $DESC_ARCHALTEXE"
			echo "ARCHALTEXE=\"$ARCHALTEXE\""
			echo "## $DESC_USEOPENVRFSR"
			echo "USEOPENVRFSR=\"$USEOPENVRFSR\""
			echo "## $DESC_RUNSBSVR"
			echo "RUNSBSVR=\"$RUNSBSVR\""
			echo "## $DESC_VRVIDEOPLAYERARGS"
			echo "VRVIDEOPLAYERARGS=\"$VRVIDEOPLAYERARGS\""
			echo "## $DESC_SBSZOOM"
			echo "SBSZOOM=\"$SBSZOOM\""
			echo "## $DESC_SBSVRRS"
			echo "SBSVRRS=\"$SBSVRRS\""
			echo "## $DESC_MINVRWINH"
			echo "MINVRWINH=\"$MINVRWINH\""
			echo "## $DESC_WAITFORTHISPID"
			echo "WAITFORTHISPID=\"$WAITFORTHISPID\""
			echo "## $DESC_WAITEDITOR"
			echo "WAITEDITOR=\"$WAITEDITOR\""
			echo "## $DESC_STEAMAPPIDFILE"
			echo "STEAMAPPIDFILE=\"$STEAMAPPIDFILE\""
			echo "## $DESC_CHECKCATEGORIES"
			echo "CHECKCATEGORIES=\"$CHECKCATEGORIES\""
			echo "## $DESC_BACKUPSTEAMUSER"
			echo "BACKUPSTEAMUSER=\"$BACKUPSTEAMUSER\""
			echo "## $DESC_RESTORESTEAMUSER"
			echo "RESTORESTEAMUSER=\"$RESTORESTEAMUSER\""
			echo "## $DESC_USESUSYM"
			echo "USESUSYM=\"$USESUSYM\""
			echo "## $DESC_USEGLOBSUSYM"
			echo "USEGLOBSUSYM=\"$USEGLOBSUSYM\""
			echo "## $(strFix "$DESC_DXVKVARS" "$DXVKURL")"
			echo "DXVK_HUD=\"$DXVK_HUD\""
			echo "## $DESC_DXVK_LOG_LEVEL"
			echo "DXVK_LOG_LEVEL=\"$DXVK_LOG_LEVEL\""
			echo "## $DESC_DXVK_LOG_PATH"
			echo "DXVK_LOG_PATH=\"$DXVK_LOG_PATH\""
			echo "## $DESC_DXVK_SCALE"
			echo "DXVK_SCALE=\"$DXVK_SCALE\""
			echo "## $DESC_STRACERUN"
			echo "STRACERUN=\"$STRACERUN\""
			echo "## $DESC_STRACEOPTS"
			echo "STRACEOPTS=\"$STRACEOPTS\""
			echo "## $DESC_USENETMON"
			echo "USENETMON=\"$USENETMON\""
			echo "## $DESC_BLOCKINTERNET"
			echo "BLOCKINTERNET=\"$BLOCKINTERNET\""
			echo "## $DESC_PROTON_LOG"
			echo "PROTON_LOG=\"$PROTON_LOG\""
			echo "## $DESC_PROTON_LOG_DIR"
			echo "PROTON_LOG_DIR=\"$PROTON_LOG_DIR\""
			echo "## $DESC_USEWINEDEBUGPROTON"
			echo "USEWINEDEBUGPROTON=\"$USEWINEDEBUGPROTON\""
			echo "## $DESC_PROTON_DUMP_DEBUG_COMMANDS"
			echo "PROTON_DUMP_DEBUG_COMMANDS=\"$PROTON_DUMP_DEBUG_COMMANDS\""
			echo "## $DESC_PROTON_DEBUG_DIR"
			echo "PROTON_DEBUG_DIR=\"$PROTON_DEBUG_DIR\""
			echo "## $DESC_PROTON_USE_WINED3D"
			echo "PROTON_USE_WINED3D=\"$PROTON_USE_WINED3D\""
			echo "## $DESC_PROTON_NO_D3D11"
			echo "PROTON_NO_D3D11=\"$PROTON_NO_D3D11\""
			echo "## $DESC_PROTON_NO_D3D10"
			echo "PROTON_NO_D3D10=\"$PROTON_NO_D3D10\""
			echo "## $DESC_PROTON_NO_ESYNC"
			echo "PROTON_NO_ESYNC=\"$PROTON_NO_ESYNC\""
			echo "## $DESC_PROTON_NO_FSYNC"
			echo "PROTON_NO_FSYNC=\"$PROTON_NO_FSYNC\""
			echo "## $DESC_PROTON_ENABLE_NVAPI"
			echo "PROTON_ENABLE_NVAPI=\"$PROTON_ENABLE_NVAPI\""
			echo "## $DESC_PROTON_HIDE_NVIDIA_GPU"
			echo "PROTON_HIDE_NVIDIA_GPU=\"$PROTON_HIDE_NVIDIA_GPU\""
			echo "## $DESC_USEDLSS"
			echo "USEDLSS=\"$USEDLSS\""
			echo "## $DESC_USERAYTRACING"
			echo "USERAYTRACING=\"$USERAYTRACING\""
			echo "## $DESC_PROTON_FORCE_LARGE_ADDRESS_AWARE"
			echo "PROTON_FORCE_LARGE_ADDRESS_AWARE=\"$PROTON_FORCE_LARGE_ADDRESS_AWARE\""
			echo "## $DESC_WINE_FULLSCREEN_INTEGER_SCALING"
			echo "WINE_FULLSCREEN_INTEGER_SCALING=\"$WINE_FULLSCREEN_INTEGER_SCALING\""
			echo "## $DESC_WINE_FULLSCREEN_FSR"
			echo "WINE_FULLSCREEN_FSR=\"$WINE_FULLSCREEN_FSR\""
			echo "## $DESC_WINE_FULLSCREEN_FSR_STRENGTH"
			echo "WINE_FULLSCREEN_FSR_STRENGTH=\"$WINE_FULLSCREEN_FSR_STRENGTH\""
			echo "## $DESC_CLEANPROTONTEMP"
			echo "CLEANPROTONTEMP=\"$CLEANPROTONTEMP\""
			echo "## $DESC_STLWINEDEBUG"
			echo "STLWINEDEBUG=\"$STLWINEDEBUG\""
			echo "## $DESC_STLWINEDLLOVERRIDES"
			echo "STLWINEDLLOVERRIDES=\"$STLWINEDLLOVERRIDES\""
			echo "## $DESC_WINE_LOG_DIR"
			echo "WINE_LOG_DIR=\"$WINE_LOG_DIR\""
			echo "## $DESC_USERSTART"
			echo "USERSTART=\"$USERSTART\""
			echo "## $DESC_USERSTOP"
			echo "USERSTOP=\"$USERSTOP\""
			echo "## $DESC_STL_PV_VERBOSE"
			echo "STL_PV_VERBOSE=\"$STL_PV_VERBOSE\""
			echo "## $DESC_STL_PV_SHELL"
			echo "STL_PV_SHELL=\"$STL_PV_SHELL\""
			echo "## $DESC_STL_PV_TERMINAL"
			echo "STL_PV_TERMINAL=\"$STL_PV_TERMINAL\""
			echo "## $DESC_AUTOCONTY"
			echo "AUTOCONTY=\"$AUTOCONTY\""
			echo "## $DESC_USECONTY"
			echo "USECONTY=\"$USECONTY\""
			echo "## $DESC_CRASHGUESS"
			echo "CRASHGUESS=\"$CRASHGUESS\""
			echo "## $DESC_ONLYWICO"
			echo "ONLYWICO=\"$ONLYWICO\""
			echo "## $DESC_GAMESCREENRES"
			echo "GAMESCREENRES=\"$GAMESCREENRES\""
			echo "## Default Help URL"
			echo "HELPURL=\"$HELPURL\""
			echo "## Desktop Icon Mode"
			echo "CREATEDESKTOPICON=\"$CREATEDESKTOPICON\""
			echo "## $DESC_FIXSYMLINKS"
			echo "FIXSYMLINKS=\"$FIXSYMLINKS\""
			echo "## $DESC_UNSYMLINK"
			echo "UNSYMLINK=\"$UNSYMLINK\""
			echo "## $DESC_DELPFX"
			echo "DELPFX=\"$DELPFX\""
			echo "## $DESC_RUN_DEPS"
			echo "RUN_DEPS=\"$RUN_DEPS\""
			echo "## $DESC_SORTGARGS"
			echo "SORTGARGS=\"$SORTGARGS\""
			echo "## $DESC_WAITMO2"
			echo "WAITMO2=\"$WAITMO2\""
			echo "## $DESC_MO2MODE"
			echo "MO2MODE=\"$MO2MODE\""
			echo "## $DESC_USEMANGOHUDSTLCFG"
			echo "USEMANGOHUDSTLCFG=\"$USEMANGOHUDSTLCFG\""
			echo "## $DESC_USESPECIALK"
			echo "USESPECIALK=\"$USESPECIALK\""
			echo "## $DESC_SPEKVERS"
			echo "SPEKVERS=\"$SPEKVERS\""
			echo "## $DESC_USEFWS"
			echo "USEFWS=\"$USEFWS\""
			echo "## $(strFix "$DESC_USEPEV" "$PELDD")"
			echo "USEPEV_PELDD=\"$USEPEV_PELDD\""
			echo "## $(strFix "$DESC_USEPEV" "$PEPACK")"
			echo "USEPEV_PEPACK=\"$USEPEV_PEPACK\""
			echo "## $(strFix "$DESC_USEPEV" "$PERES")"
			echo "USEPEV_PERES=\"$USEPEV_PERES\""
			echo "## $(strFix "$DESC_USEPEV" "$PESCAN")"
			echo "USEPEV_PESCAN=\"$USEPEV_PESCAN\""
			echo "## $(strFix "$DESC_USEPEV" "$PESEC")"
			echo "USEPEV_PESEC=\"$USEPEV_PESEC\""
			echo "## $(strFix "$DESC_USEPEV" "$PESTR")"
			echo "USEPEV_PESTR=\"$USEPEV_PESTR\""
			echo "## $(strFix "$DESC_USEPEV" "$READPE")"
			echo "USEPEV_READPE=\"$USEPEV_READPE\""
			echo "## $DESC_STL_VKD3D_CONFIG"
			echo "STL_VKD3D_CONFIG=\"$STL_VKD3D_CONFIG\""
			echo "## $DESC_STL_VKD3D_DEBUG"
			echo "STL_VKD3D_DEBUG=\"$STL_VKD3D_DEBUG\""
			echo "## $DESC_STL_VKD3D_SHADER_DEBUG"
			echo "STL_VKD3D_SHADER_DEBUG=\"$STL_VKD3D_SHADER_DEBUG\""
			echo "## $DESC_STL_VKD3D_LOG_FILE"
			echo "STL_VKD3D_LOG_FILE=\"$STL_VKD3D_LOG_FILE\""
			echo "## $DESC_STL_VKD3D_VULKAN_DEVICE"
			echo "STL_VKD3D_VULKAN_DEVICE=\"$STL_VKD3D_VULKAN_DEVICE\""
			echo "## $DESC_STL_VKD3D_FILTER_DEVICE_NAME"
			echo "STL_VKD3D_FILTER_DEVICE_NAME=\"$STL_VKD3D_FILTER_DEVICE_NAME\""
			echo "## $DESC_STL_VKD3D_DISABLE_EXTENSIONS"
			echo "STL_VKD3D_DISABLE_EXTENSIONS=\"$STL_VKD3D_DISABLE_EXTENSIONS\""
			echo "## $DESC_STL_VKD3D_TEST_DEBUG"
			echo "STL_VKD3D_TEST_DEBUG=\"$STL_VKD3D_TEST_DEBUG\""
			echo "## $DESC_STL_VKD3D_TEST_FILTER"
			echo "STL_VKD3D_TEST_FILTER=\"$STL_VKD3D_TEST_FILTER\""
			echo "## $DESC_STL_VKD3D_TEST_EXCLUDE"
			echo "STL_VKD3D_TEST_EXCLUDE=\"$STL_VKD3D_TEST_EXCLUDE\""
			echo "## $DESC_STL_VKD3D_TEST_PLATFORM"
			echo "STL_VKD3D_TEST_PLATFORM=\"$STL_VKD3D_TEST_PLATFORM\""
			echo "## $DESC_STL_VKD3D_TEST_BUG"
			echo "STL_VKD3D_TEST_BUG=\"$STL_VKD3D_TEST_BUG\""
			echo "## $DESC_STL_VKD3D_PROFILE_PATH"
			echo "STL_VKD3D_PROFILE_PATH=\"$STL_VKD3D_PROFILE_PATH\""	
			} >> "$1"

			#ENDsaveCfgdefault_template
		fi
	}

	SCFG="$(basename "${1//.conf/}")"
	"${FUNCNAME[0]}$SCFG" "$1" "$SCFG" "$2"

	if grep "$STLCFGDIR" "$1" >/dev/null ; then
		writelog "UPDATE" "${FUNCNAME[0]} - Replacing '$STLCFGDIR' with 'STLCFGDIR' in '$1'"
		sed "s:$STLCFGDIR:STLCFGDIR:g" -i "$1"
	fi
}

function notiShow {
	if [ -n "$2" ] && [ "$2" == "X" ]; then
		if [ -z "$NOTY" ]; then
			NOTY="$(command -v "notify-send")"
		fi
	fi

	if [ -n "$USENOTIFIER" ] && [ "$USENOTIFIER" -eq 1 ] && { [ -z "$2" ] || { [ -n "$2" ] && [ "$2" != "S" ]; };} || { [ -n "$2" ] && [ "$2" == "X" ]; }; then

		if [ -x "$(command -v "$NOTY")" ]; then
			if [ -z "${NOTYARGSARR[0]}" ]; then
				mapfile -d " " -t -O "${#NOTYARGSARR[@]}" NOTYARGSARR < <(printf '%s' "$NOTYARGS")
			fi
			"$NOTY" "${NOTYARGSARR[@]}" "$1"
		else
			writelog "INFO" "${FUNCNAME[0]} - Warning - '$NOTY' not found - disabling notifier"
			USENOTIFIER=0
		fi
	fi
	
	if [ -n "$2" ] && [ "$2" == "S" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Message '$1' should go to StatusWindow"
		echo "$1"
	fi
}

function strFix {
	STRIN="$1"

	if [ -z "$2" ]; then
		echo "$STRIN"
	else
		STRIN2="${STRIN//XXX/$2}"
		STRIN3="${STRIN2//YYY/$3}"
		STRIN4="${STRIN3//ZZZ/$4}"
		echo "${STRIN4//QQQ/$5}"
	fi
}

function getProtPathFromCSV {
	delEmptyFile "$PROTONCSV"
	if [ ! -f "$PROTONCSV" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Creating '$PROTONCSV'"
		getAvailableProtonVersions "up" X
	fi

	if [ -f "$PROTONCSV" ]; then
		grep "^$1" "$PROTONCSV" | sort -nr | head -n1 | cut -d ';' -f2
	fi
}

function setRunWineServer {
	if [ "$ISGAME" -eq 2 ]; then
		writelog "INFO" "${FUNCNAME[0]} - Initiated from '$1'"

		if [ -n "$USEPROTON" ] && [ ! -f "$(getProtPathFromCSV "$USEPROTON")" ] && [ "$HAVEINPROTON" -eq 0 ]; then
			fixProtonVersionMismatch "USEPROTON" "$STLGAMECFG"
		fi
		
		if [ -z "$RUNPROTON" ] && [ "$HAVEINPROTON" -eq 1 ]; then
			RUNPROTON="${INPROTCMD[*]}"
		fi

		if [ -z "$RUNPROTON" ]; then
			setRunProtonFromUseProton
		fi

		CHECKWINED="$(dirname "$RUNPROTON")/$DBW"
		CHECKWINEF="$(dirname "$RUNPROTON")/$FBW"
		if [ -f "$CHECKWINED" ]; then
			RUNWINE="$CHECKWINED"
			RUNWINESERVER="${RUNWINE}server"
			writelog "INFO" "${FUNCNAME[0]} - Set the wine binary for proton in path '$RUNPROTON'"	
			writelog "INFO" "${FUNCNAME[0]} - to '$RUNWINE'"	
			writelog "INFO" "${FUNCNAME[0]} - and wineserver to '$RUNWINESERVER'"	
		elif [ -f "$CHECKWINEF" ]; then
			RUNWINE="$CHECKWINEF"
			RUNWINESERVER="${RUNWINE}server"
			writelog "INFO" "${FUNCNAME[0]} - Set the wine binary for proton in path '$RUNPROTON'"	
			writelog "INFO" "${FUNCNAME[0]} - to '$RUNWINE'"	
			writelog "INFO" "${FUNCNAME[0]} - and wineserver to '$RUNWINESERVER'"
		else
			writelog "WARN" "${FUNCNAME[0]} - Couldn't find the wine binary for the proton in path '$RUNPROTON' - falling back to 'wine' for plain RUNWINE and 'wineserver' for RUNWINESERVER"
		fi
	fi
}

function setNewProtVars {
	if [ "$ISGAME" -eq 2 ] && [ "$USEWINE" -eq 0 ]; then
		if [ "$HAVEINPROTON" -eq 1 ]; then
			if [ -z "$RUNWINESERVER" ]; then
				setRunWineServer "${FUNCNAME[0]}"
			fi
		else
			# arg1 is absolute proton path
			if [ "$HAVEINPROTON" -eq 0 ]; then
				writelog "INFO" "${FUNCNAME[0]} - Setting new Proton Variables based on '$1'"
				RUNPROTON="$1"
				CHECKWINED="$(dirname "$RUNPROTON")/$DBW"
				CHECKWINEF="$(dirname "$RUNPROTON")/$FBW"

				writelog "INFO" "${FUNCNAME[0]} - Continuing with RUNPROTON='$RUNPROTON'"

				PDTGZ="proton_dist.tar.gz"
				
				if [ ! -f "$CHECKWINED" ] && [ ! -f "$CHECKWINEF" ] && [ -f "$(dirname "$RUNPROTON")/$PDTGZ" ]; then
					writelog "INFO" "${FUNCNAME[0]} - Wine binary not found, but a proton archive '$PDTGZ' - extracting now"
					mkProjDir "$(dirname "$RUNPROTON")/dist"
					"$TAR" xf "$(dirname "$RUNPROTON")/$PDTGZ" -C "$(dirname "$RUNPROTON")/dist" 2>/dev/null
				fi

				setRunWineServer "${FUNCNAME[0]}"
				
				PROTONVERSION="$(setProtonPathVersion "$RUNPROTON")"
				USEPROTON="$PROTONVERSION"
			else
				writelog "SKIP" "${FUNCNAME[0]} - Using Steam Proton '$FIRSTUSEPROTON' instead of ${PROGNAME,,} Proton '$USEPROTON', because '$PROGCMD' was used as '$SLO'"
				notiShow "$(strFix "$NOTY_SETNEWPROTVARS" "$FIRSTUSEPROTON")"
			fi
		fi

		if [ "$USEWINEDEBUGPROTON" -eq 1 ]; then
			writelog "INFO" "${FUNCNAME[0]} - Using '$STLWINEDEBUG' as Proton 'WINEDEBUG' parameters, because 'USEWINEDEBUGPROTON' is enabled"
			export WINEDEBUG="$STLWINEDEBUG"
		fi

		if [ -n "$STLWINEDLLOVERRIDES" ] && [ "$STLWINEDLLOVERRIDES" != "$NON" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Using '$STLWINEDLLOVERRIDES' as 'WINEDLLOVERRIDES' parameter"
			export WINEDLLOVERRIDES="$WINEDLLOVERRIDES;$STLWINEDLLOVERRIDES"
		fi
	fi
}

# in case you wonder NOP='Newest Official Proton'
function getNOP {
	createProtonList
	NEWESTPROTRAW="$(printProtonArr | grep "^proton-[0-9]." | sort -nr | head -n1)"
	
	if [ "$1" == "p" ]; then
		cut -d ';' -f2 <<< "$NEWESTPROTRAW"
	elif [ "$1" == "v" ]; then
		cut -d ';' -f1 <<< "$NEWESTPROTRAW"
	fi
}

function setNOP {
	writelog "INFO" "${FUNCNAME[0]} - Selecting newest official Proton available"
	NOPPATH="$(getNOP "p")"
	if [ -n "$NOPPATH" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Selected '$NOPPATH'"
		setNewProtVars "$NOPPATH"
	else
		writelog "SKIP" "${FUNCNAME[0]} - Haven't found anything"
	fi
}

function needNewProton {
	if [ "$HAVEINPROTON" -eq 0 ]; then
		getAvailableProtonVersions "up"
		export CURWIKI="$PPW/Proton-Versions"
		TITLE="${PROGNAME}-NeedNewProtonVersion"
		pollWinRes "$TITLE"
		writelog "INFO" "${FUNCNAME[0]} - No Proton Version was found - opening a requester to choose from one"
		createProtonList
		
		PICKPROTON="$("$YAD" --f1-action="$F1ACTION" --window-icon="$STLICON" --center $WINDECO --form --scroll --separator="\n" --quoted-output \
		--text="$(spanFont "$GUI_NEEDNEWPROTON" "H")" \
		--field="$GUI_NEEDNEWPROTON2":CB "$(cleanDropDown "${USEPROTON/#-/ -}" "$PROTYADLIST")" \
		--title="$TITLE" "$GEOM")"

		if [ -n "$PICKPROTON" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Selected Proton Version $PICKPROTON"
			setNewProtVars "$(getProtPathFromCSV "$PICKPROTON")"
		else
			writelog "INFO" "${FUNCNAME[0]} - No Proton Version was selected - try again"
			"${FUNCNAME[0]}"
		fi
	fi
}

function dlCustomProton {
	if [ "$CUPROTOCOMPAT" -eq 1 ]; then
		CUPROEXTDIR="$STEAMCOMPATOOLS"
	else
		CUPROEXTDIR="$CUSTPROTEXTDIR"
	fi

	CPURL="${1//\"/}"
	CPURLFILE="${CPURL##*/}"
	DSTDL="$CUSTPROTDLDIR/$CPURLFILE"
	if [ ! -f "$DSTDL" ]; then
		notiShow "$(strFix "$NOTY_DLCUSTOMPROTON" "$CPURL")" "S"
		DLCHK="X"
		INCHK="$NON"
		# only "-STL" and "-GE" proton have a sha512sum
		if grep -q "\-GE" <<< "$CPURLFILE" || grep -q "\-STL" <<< "$CPURLFILE"; then
			DLCHK="sha512sum"
			INCHK="$("$WGET" -q "${CPURL%%.tar*}.${DLCHK}" -O - 2> >(grep -v "SSL_INIT") | cut -d ' ' -f1)"
		fi
		dlCheck "$CPURL" "$DSTDL" "$DLCHK" "Downloading '$CPURL' to '$CUSTPROTDLDIR'" "$INCHK"
	else
		writelog "INFO" "${FUNCNAME[0]} - File '$DSTDL' already exists - nothing to download"
		if [ -z "$2" ]; then
			notiShow "$(strFix "$NOTY_DLCUSTOMPROTON4" "$CPURLFILE")"
		fi
	fi
	
	PROTNAMERAW="${CPURLFILE%%.tar*}"
	PROTNAME="${PROTNAMERAW//.zip/}"

	if [ -d "$CUPROEXTDIR/$PROTNAME" ]; then
		writelog "INFO" "${FUNCNAME[0]} - directory '$CUPROEXTDIR/$PROTNAME' already exists - nothing to extract"
	else
		# only "-STL" and "-GE" proton have a sha512sum
		if grep -q "\-GE" <<< "$CPURLFILE" || grep -q "\-STL" <<< "$CPURLFILE"; then
			DLCHK="sha512sum"
			writelog "INFO" "${FUNCNAME[0]} - checking if the checksum of the already downloaded file is correct '${CPURL%%.tar*}.${DLCHK}'"
			INCHK="$("$WGET" -q "${CPURL%%.tar*}.${DLCHK}" -O - 2> >(grep -v "SSL_INIT") | cut -d ' ' -f1)"
			dlCheck "$DLCHK" "$DSTDL" "C" "$INCHK"
		fi

		if grep -q "\.tar\." <<< "$DSTDL"; then
			notiShow "$(strFix "$NOTY_DLCUSTOMPROTON5" "$CPURLFILE")" "S"

			PROTRELPATH="$("$TAR" -tf "$DSTDL" 2>/dev/null | grep "proton$" 2>/dev/null )"
			if [ -n "$PROTRELPATH" ]; then
				if grep -q "^proton$" <<< "$PROTRELPATH"; then
					EXTDEST="$CUPROEXTDIR/$PROTNAME"
					PROTFULLPATH="$EXTDEST/$PROTRELPATH"
					writelog "INFO" "${FUNCNAME[0]} - Archive is a tarbomb - creating parent directory '$EXTDEST' as extract dest dir"
					mkProjDir "$EXTDEST"
				else
					writelog "INFO" "${FUNCNAME[0]} - Archive contains proton in subdirectory '$PROTRELPATH'"
					PROTFULLPATH="$CUPROEXTDIR/$PROTRELPATH"
					EXTDEST="$CUPROEXTDIR"
				fi

				if [ -f "$PROTFULLPATH" ]; then
					writelog "SKIP" "${FUNCNAME[0]} - The destination path '$PROTFULLPATH' already exists - looks like '$DSTDL' was already extracted before"
				else
					notiShow "$(strFix "$NOTY_DLCUSTOMPROTON3" "$CPURL")" "S"
					"$TAR" xf "$DSTDL" -C "$EXTDEST" 2>/dev/null
					getAvailableProtonVersions "up"
					touch "$PROTBUMPTEMP"
				fi
			else
				notiShow "$(strFix "$NOTY_DLCUSTOMPROTON6" "$DSTDL")" "S"
				writelog "SKIP" "${FUNCNAME[0]} - Archive doesn't seem to contain a 'proton' file"
			fi
		elif grep -q "\.zip$" <<< "$DSTDL"; then
			if grep -q "proton$" <<< "$("$UNZIP" -l "$DSTDL" 2>/dev/null)"; then
				writelog "INFO" "${FUNCNAME[0]} - Archive contains proton"
				SUBDIR="$(basename "${DSTDL//.zip/}")"
				PROTRELPATH="$SUBDIR/proton"
				PROTFULLPATH="$CUPROEXTDIR/$PROTRELPATH"
				if [ -f "$PROTFULLPATH" ]; then
					writelog "SKIP" "${FUNCNAME[0]} - The destination path '$PROTFULLPATH' already exists - looks like '$DSTDL' was already extracted before"
				else
					notiShow "$(strFix "$NOTY_DLCUSTOMPROTON3" "$CPURL")" "S"
					"$UNZIP" "$DSTDL" -d "$CUPROEXTDIR/$SUBDIR" 2>/dev/null
					getAvailableProtonVersions "up"
					touch "$PROTBUMPTEMP"
					notiShow "$GUI_DONE" "S"
				fi
			else
				notiShow "$(strFix "$NOTY_DLCUSTOMPROTON6" "$CPURL")" "S"
				writelog "SKIP" "${FUNCNAME[0]} - Archive doesn't seem to contain a 'proton' file"
			fi
		else
			writelog "SKIP" "${FUNCNAME[0]} - Don't know how to extract "
		fi
	fi
	
	rm "$PROTONCSV" 2>/dev/null
	
	if [ -f "$PROTFULLPATH" ]; then
		addCustomProtonToList "$PROTFULLPATH"
	fi
}

function createDLProtList {
	writelog "INFO" "${FUNCNAME[0]} - Generating list of online available custom Proton builds"

	PROTDLLIST="$STLSHM/ProtonDL.txt"
	MAXAGE=360

	if [ ! -f "$PROTDLLIST" ] || test "$(find "$PROTDLLIST" -mmin +"$MAXAGE")"; then
		rm "$PROTDLLIST" 2>/dev/null
		while read -r CPURL; do
			if grep -q "$GHURL" <<< "${!CPURL}"; then
				"$WGET" -q "${!CPURL}" -O - 2> >(grep -v "SSL_INIT") | grep "tar.gz\|zip\|tar.xz" | grep "releases" | grep -oE '\"/[^\\"]+' | sed "s|^\"|$GHURL|g" >> "$PROTDLLIST"
			fi
		done <<< "$(grep "^CP_" "$STLURLCFG" | cut -d '=' -f1)"
	fi

	unset ProtonDLList
	unset ProtonDLDispList

	while read -r CPVERS; do
		mapfile -t -O "${#ProtonDLList[@]}" ProtonDLList <<< "$CPVERS"
		mapfile -t -O "${#ProtonDLDispList[@]}" ProtonDLDispList <<< "${CPVERS##*/}"
	done < "$PROTDLLIST"
}

function dlCustomProtonGUI {

	createDLProtList

	writelog "INFO" "${FUNCNAME[0]} - Opening dialog to choose a download"

	DLPROTLIST="$(printf "!%s\n" "${ProtonDLDispList[@]//\"/}" | tr -d '\n' | sed "s:^!::" | sed "s:!$::")"
	export CURWIKI="$PPW/Download-Custom-Proton"
	TITLE="${PROGNAME}-DownloadCustomProton"
	pollWinRes "$TITLE"

	if [ -z "$DLPROTON" ]; then
		DLPROTON="${ProtonDLDispList[0]}"
	fi

	DLDISPCUSTPROT="$("$YAD" --f1-action="$F1ACTION" --window-icon="$STLICON" --form --center --on-top $WINDECO \
	--title="$TITLE" \
	--text="$(spanFont "$GUI_DLCUSTPROTTEXT" "H")" \
	--field=" ":LBL " " --separator="" \
	--field="$GUI_DLCUSTPROTTEXT2!$GUI_DLCUSTPROTTEXT":CBE "$(cleanDropDown "${DLPROTON/#-/ -}" "$DLPROTLIST")" \
	"$GEOM"
	)"
	
	if [ -n "${DLDISPCUSTPROT}" ]; then
		if grep -q "^http" <<< "${DLDISPCUSTPROT}"; then
			writelog "INFO" "${FUNCNAME[0]} - The URL '$DLDISPCUSTPROT' was entered manually - downloading directly"
			StatusWindow "$GUI_DLCUSTPROT" "dlCustomProton ${DLDISPCUSTPROT}" "DownloadCustomProtonStatus"
		else
			DLURL="$(printf "%s\n" "${ProtonDLList[@]}" | grep -m1 "${DLDISPCUSTPROT}")"
			writelog "INFO" "${FUNCNAME[0]} - '${DLDISPCUSTPROT}' was selected - downloading '$DLURL'"
			StatusWindow "$GUI_DLCUSTPROT" "dlCustomProton ${DLURL}" "DownloadCustomProtonStatus"
		fi

		createProtonList
	fi
}

function CustomFallbackPicture {
	if [ "$USECUSTOMFALLBACKPIC" -eq 1 ]; then
		writelog "INFO" "${FUNCNAME[0]} - Using custom fallback picture if possible and required"

		if [ ! -f "$CUSTOMFALLBACKPIC" ]; then
			if [ -n "$GITHUBUSER" ] && [ "$GITHUBUSER" != "$NON" ]; then
				dlCheck "$GHURL/${GITHUBUSER}.png" "$CUSTOMFALLBACKPIC" "X" "Downloading github avatar for user '$GITHUBUSER' to use as custom fallback picture"
			fi
		fi

		if [ -f "$CUSTOMFALLBACKPIC" ]; then
			SHOWPIC="$CUSTOMFALLBACKPIC"
			writelog "INFO" "${FUNCNAME[0]} - Using '$SHOWPIC' as custom fallback picture"
		else
			writelog "INFO" "${FUNCNAME[0]} - No custom fallback picture found - using internal picture instead"
		fi
	fi	
}

function setShowPic {
	if [ "$STLPLAY" -eq 1 ] && [ -f "$STLGPNG/${AID}.png" ]; then
		SHOWPIC="$STLGPNG/${AID}.png"
	elif [ "$USEGAMEPICS" -eq 1 ]; then
		writelog "INFO" "${FUNCNAME[0]} - Determining game picture"
		if [ -s "$STLGHEADD/$AID.jpg" ]; then
			SHOWPIC="$STLGHEADD/$AID.jpg"
			writelog "INFO" "${FUNCNAME[0]} - Using '$SHOWPIC' as game picture"
		else
			SHOWPIC="$STLICON"
			CustomFallbackPicture

			if [ ! -f "$STLGHEADD/$AID.jpg" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Using '$SHOWPIC' as fallback picture, because '$STLGHEADD/$AID.jpg' doesn't exist"
			elif [ ! -s "$STLGHEADD/$AID.jpg" ]; then
				if [ -z "$SUSDA" ] || [ -z "$STUIDPATH" ]; then
					setSteamPaths
				fi
				CUSTPIC="$STUIDPATH/config/grid/${AID}_hero.png"
				if [ -f "$CUSTPIC" ]; then
					writelog "INFO" "${FUNCNAME[0]} - Found custom game picture under '$CUSTPIC'"
					if [ -x "$(command -v "$CONVERT" 2>/dev/null)" ]; then
						writelog "INFO" "${FUNCNAME[0]} - Replacing the empty '$STLGHEADD/$AID.jpg' file with a scaled down version and using that"
						"$CONVERT" "$CUSTPIC" -resize "460x215!" "$STLGHEADD/$AID.jpg"
						SHOWPIC="$STLGHEADD/$AID.jpg"
					else
						writelog "SKIP" "${FUNCNAME[0]} - Command '$CONVERT' not found, so scaling the custom game picture is not possible - skipping"
					fi
				else
					writelog "INFO" "${FUNCNAME[0]} - Using '$SHOWPIC' as fallback picture, because '$STLGHEADD/$AID.jpg' has zero bytes"
					writelog "INFO" "${FUNCNAME[0]} - Leaving '$STLGHEADD/$AID.jpg' as is to avoid another download attempt"
					writelog "INFO" "${FUNCNAME[0]} - Feel free to replace it with a custom picture"
				fi
			fi
		fi
	else
		SHOWPIC="$NOICON"
		writelog "INFO" "${FUNCNAME[0]} - Using '$SHOWPIC' as invisible picture"
	fi	
}

function addCustomProtonToList {
	if [ -f "$1" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Received directly the file as argument"
		if [ -n "$2" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Received '$2' as Proton Version"
			OUTNEWCUSTPROT="$2;$1"
		else
			OUTNEWCUSTPROT="$1"
		fi
	else
		NEWCUSTPROT="$1"

		if grep -q "||" <<< "$NEWCUSTPROT"; then
			if grep -q "|http" <<< "$NEWCUSTPROT"; then
				CPURLWIP="$(tr '|' '"' <<< "$NEWCUSTPROT" | sed "s:\"http:\";\"http:g")"
				CPURL="$(cut -d ';' -f2 <<< "$CPURLWIP")"
				StatusWindow "$GUI_DLCUSTPROT" "dlCustomProton ${CPURL}" "DownloadCustomProtonStatus"
			else
				CPWIP="$(tr -s '|' <<< "$NEWCUSTPROT" | tr '|' '"')"
				if [ -f "${CPWIP//\"/}" ]; then
					OUTNEWCUSTPROT="$CPWIP"
				fi
			fi
		else
			if grep -q "|http" <<< "$NEWCUSTPROT"; then
				CPURLWIP="$(tr '|' '"' <<< "$NEWCUSTPROT" | sed "s:\"http:\";\"http:g")"
				CPURL="$(cut -d ';' -f2 <<< "$CPURLWIP")"
				StatusWindow "$GUI_DLCUSTPROT" "dlCustomProton ${CPURL}" "DownloadCustomProtonStatus"
			else
				CPWIP="$(tr '|' '"' <<< "$NEWCUSTPROT" | sed "s:\"/:\";\"/:g")"
				CPWIPF="$(cut -d ';' -f2 <<< "$CPWIP")"
				if [ -f "${CPWIPF//\"/}" ]; then
					OUTNEWCUSTPROT="$CPWIP"
				fi
			fi
		fi
	fi

	if [ -n "$OUTNEWCUSTPROT" ] ; then
		writelog "INFO" "${FUNCNAME[0]} - Adding '$OUTNEWCUSTPROT' to '$CUSTOMPROTONLIST'"
		echo "$OUTNEWCUSTPROT" >> "$CUSTOMPROTONLIST"
		writelog "INFO" "${FUNCNAME[0]} - (Re-)creating the internal List of available Proton-Versions"
		getAvailableProtonVersions "up"
	fi
}

function dlLatestGE {
	createDLProtList
	if [ "$1" == "latestge" ] || [ "$1" == "lge" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Downloading latest Proton GE"
	else
		writelog "INFO" "${FUNCNAME[0]} - Downloading latest custom Proton ${ProtonDLDispList[0]//\"/}"
	fi
	StatusWindow "$GUI_DLCUSTPROT" "dlCustomProton ${ProtonDLList[0]//\"/} $2" "DownloadCustomProtonStatus"
}

function dlCustomProtonGate {
	if [ -z "$1" ]; then
		dlCustomProtonGUI
	else
		if grep -q "^http" <<< "$1"; then
			writelog "INFO" "${FUNCNAME[0]} - '$1' is an URL - sending directly to dlCustomProton"
			StatusWindow "$GUI_DLCUSTPROT" "dlCustomProton $1" "DownloadCustomProtonStatus"
		else
			if [ "$1" == "latest" ] || [ "$1" == "l" ] || [ "$1" == "latestge" ] || [ "$1" == "lge" ]; then
				dlLatestGE "$1"
			elif [ "$1" == "latesttkg" ] || [ "$1" == "ltkg" ]; then
				createDLProtList
				writelog "INFO" "${FUNCNAME[0]} - Downloading latest Proton TKG"
				StatusWindow "$GUI_DLCUSTPROT" "dlCustomProton $(printf "%s\n" "${ProtonDLList[@]}" | grep -im1 "tkg")" "DownloadCustomProtonStatus"
			else
				writelog "SKIP" "${FUNCNAME[0]} - Don't know what to do with argument '$1'"
			fi
		fi
	fi
}

function addCustomProton {
	if [ -z "$1" ]; then
		if [ ! -f "$CUSTOMPROTONLIST" ]; then 
			{
			echo "# List of custom proton paths, which are not stored in the usual default locations (see README)"
			echo "# (optionally with identifying name (f.e. proton version) as field one)"
			echo "# Files can be added by using the '$PROGCMD' command line or the GUI (or manually of course)"
			echo "# Two valid examples:"
			echo "# \"Proton-47.11-FWX-3\";\"/random/path/to/a/custom/binary/proton\""
			echo "# \"/random/path/to/a/custom/binary/proton\""
			echo "# (In the first example \"Proton-47.11-FWX-3\" will be used as identifying proton version"
			echo "# in the second example the identifying proton version will be searched in '$CTVDF'"
			echo "# and 'version' files in the besides the given proton binary."
			echo "# When no proton version could be found, the selected file will be marked as invalid and removed at once)"
			echo "################################################"
			} > "$CUSTOMPROTONLIST"
		fi
		export CURWIKI="$PPW/Custom-Proton-Autoupdate"
		TITLE="${PROGNAME}-AddCustomProton"
		pollWinRes "$TITLE"

		NEWCUSTPROT="$("$YAD" --f1-action="$F1ACTION" --window-icon="$STLICON" --form --center --on-top $WINDECO \
		--title="$TITLE" \
		--text="$(spanFont "$GUI_ADDCUSTOMBINARY" "H")" \
		--field=" ":LBL " " \
		--field="$GUI_PROTONVERSIONNAME!$DESC_PROTONVERSIONNAME" "Proton-" \
		--field="$GUI_CUSTOMPROTONBINARY":FL "proton" --file-filter="$GUI_PROTONFILES (proton)| proton" \
		"$GEOM"
		)"

		addCustomProtonToList "$NEWCUSTPROT"
	else
		if grep -q "proton$" <<< "$1"; then
			if [ -f "$1" ]; then
				writelog "INFO" "${FUNCNAME[0]} - '$1' is a path to an existing 'proton' file - adding to the Custom Proton List"
				addCustomProtonToList "$@"
			else
			writelog "SKIP" "${FUNCNAME[0]} - File '$1' does not exist - skipping"
			fi
		fi
	fi
}

function saveMenuEntries {

	SAVMENUCAT="$1"
	writelog "INFO" "${FUNCNAME[0]} - Saving changed Settings"
	writelog "INFO" "${FUNCNAME[0]} - Clearing Results array with '${#Results[@]}' elements"
	writelog "INFO" "${FUNCNAME[0]} - Pulling values from tempfile '$MKCFG' $(ls -la "$MKCFG")"
	unset Results
	mapfile -t -O "${#Results[@]}" Results < "$MKCFG"

	for i in "${!Results[@]}"; do
		ONUM="$((i +1))"
		VAL="${Results[$i]}"

		RAWENT="$(sed "${ONUM}q;d" "${SAVMENUCAT}-${TMPL}")"
		VAR="$(grep -oP "\('\K[^\')]+" <<< "$RAWENT")"

		if [ -n "$VAL" ]; then
				if grep -q "MENU_GAME" <<< "$RAWENT"; then
					if [ "$SAVMENUCAT" == "$GAMETEMPMENU" ]; then
						SAVECFG="$STLDEFGAMECFG"
					else
						SAVECFG="$STLGAMECFG"
					fi
				elif grep -q "MENU_URL" <<< "$RAWENT"; then
					SAVECFG="$STLURLCFG"
				elif grep -q "MENU_GLOBAL" <<< "$RAWENT"; then
					SAVECFG="$STLDEFGLOBALCFG"
				else
					writelog "SKIP" "${FUNCNAME[0]} - No valid configfile determined for VAR='$VAR' WRITEVAL='$WRITEVAL' - this is an error!"
				fi
			VALUNQ="${VAL//\'/}"
			WRITEVAL="${VALUNQ/# -/-}"
			
			if [ -n "$VAR" ] && [ -z "$WRITEVAL" ] && [ -n "$SAVECFG" ]; then
				WRITEVAL="$NON"
				writelog "INFO" "${FUNCNAME[0]} - Value for '$VAR' is empty - automatically setting '$NON'"
			fi
			
			if [ -n "$VAR" ] && [ -n "$WRITEVAL" ] && [ -n "$SAVECFG" ]; then
				updateConfigEntry "$VAR" "$WRITEVAL" "$SAVECFG"
			fi
		fi
	done
	writelog "INFO" "${FUNCNAME[0]} - Done with Saving changed Settings"
}

function saveNewRes {
	if [ "$SAVESETSIZE" -eq 1 ] && [ -n "$3" ]; then
		SNEWW="$1"
		SNEWH="$2"
		CFG="$3"
		touch "$CFG"
		updateConfigEntry "WINX" "$SNEWW" "$CFG"
		updateConfigEntry "WINY" "$SNEWH" "$CFG"
		writelog "INFO" "${FUNCNAME[0]} - Saved new resolution '${SNEWW}x${SNEWH}' in '$CFG'" "$WINRESLOG"
	fi
}

function updateThisWinTemplate {
	if [ -f "$UPWINTMPL" ] && [ -f "$2" ]; then
		cp "$2" "$STLGUIDIR/$SCREENRES/${TEMPL}/${1}.conf"
		rm "$UPWINTMPL"
		writelog "INFO" "${FUNCNAME[0]} - Updated Window Template '$STLGUIDIR/$SCREENRES/${TEMPL}/${1}.conf' with '$2'" "$WINRESLOG"
		notiShow "$(strFix "$NOTY_TEMPLUP" "$1")"
	fi
}

function updateWinRes {
	if [ -z "$SAVESETSIZE" ]; then
		SAVESETSIZE=0
	fi
	
	if [ "$SAVESETSIZE" -eq 1 ] ; then
		WNAM="$1"
		CFG="$2"
		TEMPLGUICFG="$3"

		writelog "INFO" "${FUNCNAME[0]} - Starting resolution-poll for '$GAMEGUICFG' with incoming '${WINX}x${WINY}'" "$WINRESLOG"

		ORGW="${WINX}"
		ORGH="${WINY}"	
		NEWW="${WINX}"
		NEWH="${WINY}"

		MAXWAIT=3
		COUNTER=0

		while ! "$XWININFO" -name "$WNAM" -stats >/dev/null 2>/dev/null; do
			if [ -f "$CLOSETMP" ]; then
				writelog "WAIT" "${FUNCNAME[0]} - ${PROGNAME,,} is just closing - leaving loop" "$WINRESLOG"
				break
			fi
			if [[ "$COUNTER" -ge "$MAXWAIT" ]]; then
				writelog "SKIP" "${FUNCNAME[0]} - Timeout waiting for Window '$WNAM'" "$WINRESLOG"
				return 
			fi

			writelog "INFO" "${FUNCNAME[0]} - Waiting for Window '$WNAM'" "$WINRESLOG"
			COUNTER=$((COUNTER+1))
			sleep 1
		done

		writelog "INFO" "${FUNCNAME[0]} - Window '$WNAM' is running - polling the resolution" "$WINRESLOG"

		while true; do
			SRES="$("$XWININFO" -name "$WNAM" -stats 2>/dev/null | awk '$1=="-geometry" {print $2}' | cut -d '+' -f1)"
			if grep -q "x" <<< "$SRES"; then
				PREVW="$NEWW"
				PREVH="$NEWH"
			
				TNEWW1="${SRES%x*}"
				TNEWW="${TNEWW1%%-*}"

				TNEWH1="${SRES#*x}"
				TNEWH="${TNEWH1%%-*}"

				if [ "$TNEWW" -ne "$ORGW" ] || [ "$TNEWH" -ne "$ORGH" ]; then
					if [ "$TNEWW" != "$PREVW" ] || [ "$TNEWH" != "$PREVH" ]; then
						if [ -n "${TNEWW##*[!0-9]*}" ] && [ -n "${TNEWH##*[!0-9]*}" ]; then
							NEWW="$TNEWW"
							NEWH="$TNEWH"
							writelog "INFO" "${FUNCNAME[0]} - Found new Window Resolution '${NEWW}x${NEWH}' for Window '$WNAM'" "$WINRESLOG"
						else
							writelog "SKIP" "${FUNCNAME[0]} - Skipping found false-positive size '${NEWW}x${NEWH}'"	"$WINRESLOG"
						fi
					fi
				fi
				sleep 1
			else
				if [ "$NEWW" -ne "$ORGW" ] || [ "$NEWH" -ne "$ORGH" ]; then
					writelog "INFO" "${FUNCNAME[0]} - The Window '$WNAM' was closed - saving the last seen resolution '${NEWW}x${NEWH}' into config '$CFG'" "$WINRESLOG"
					saveNewRes "$NEWW" "$NEWH" "$CFG"
					if [ ! -f "$TEMPLGUICFG" ]; then
						writelog "INFO" "${FUNCNAME[0]} - Creating template '$TEMPLGUICFG' with the same resolution '${NEWW}x${NEWH}'" "$WINRESLOG"
						cp "$CFG" "$TEMPLGUICFG"
					fi
				else
					writelog "INFO" "${FUNCNAME[0]} - The Window '$WNAM' was closed - the resolution didn't change - nothing to do" "$WINRESLOG"
				fi

				updateThisWinTemplate "$TITLE" "$CFG"
				
				return
			fi
		done
	fi	
}

function updateEditor {
	CFG="$1"
	XDGO="xdg-open"

	loadCfg "$CFG" X
	if grep -q "$XDGO" <<< "$STLEDITOR" || [ ! -f "$STLEDITOR" ] ; then
		writelog "WARN" "${FUNCNAME[0]} - '$XDGO' selected as editor or configured editor not found - trying to find an installed editor installed"
		XDGED="$(command -v "$(xdg-mime query default text/plain | cut -d '.' -f1)" 2>/dev/null)"
		if [ -x "$XDGED" ]; then
			writelog "INFO" "${FUNCNAME[0]} - xdg-mime points to '$XDGED', which also exists"
			FOUNDEDITOR="$XDGED"
		elif [ -x "$(command -v "geany")" ]; then
			FOUNDEDITOR="$(command -v "geany")"
		elif [ -x "$(command -v "gedit")" ]; then
			FOUNDEDITOR="$(command -v "gedit")"
		elif [ -x "$(command -v "leafpad")" ]; then
			FOUNDEDITOR="$(command -v "leafpad")"
		elif [ -x "$(command -v "kwrite")" ]; then
			FOUNDEDITOR="$(command -v "kwrite")"
		else
			writelog "SKIP" "${FUNCNAME[0]} - No valid editor found - leaving '$XDGO'"
		fi

		if [ -n "$FOUNDEDITOR" ]; then
			writelog "INFO" "${FUNCNAME[0]} -changing STLEDITOR to '$FOUNDEDITOR' in '$CFG'"
			updateConfigEntry "STLEDITOR" "$FOUNDEDITOR" "$CFG"
			loadCfg "$CFG"
		fi
	fi
}

function setGPfxFromAppMa {
	if [ -n "$2" ] && [ -f "$2" ]; then
		echo "${2%/*}/$CODA/$1/pfx"
	else
		if [ -z "$GPFX" ]; then
			APPMAFE="$(listAppManifests | grep -m1 "${1}.acf")"
			if [ -n "$APPMAFE" ]; then
				if [ ! -d "$APPMAFE" ]; then
					writelog "ERROR" "${FUNCNAME[0]} - '$APPMAFE' is no valid directory - probably function 'listAppManifests' requires a fix here!"
				else
					AMF="${APPMAFE##*/}"
					GPFX="${APPMAFE%/*}/$CODA/$1/pfx"
					writelog "INFO" "${FUNCNAME[0]} - Found WINEPREFIX '$GPFX' in '$AMF'"
				fi
			fi
		fi
	fi
	if [ -z "$GPFX" ] && [ -n "$AMF" ] && [ -z "$2" ]; then
		writelog "SKIP" "${FUNCNAME[0]} - Could not retrieve WINEPREFIX from '$AMF'"
	fi
}

function getGameTextFiles {
	setGPfxFromAppMa "$AID"
	unset GameTxtFiles

	if [ -d "$GPFX/$DRCU/$STUS" ]; then
		# an option to parse user-contributed per game config lists with the actual config files instead of searching for any textfile would be easy
		EXID="$HIDEDIR/hide-${AID}.txt"
		touch "$EXID"
		SKIPGTF=0
		
		if [ -n "$1" ]; then	
			writelog "INFO" "${FUNCNAME[0]} - Searching for at least one editable textfile in '$GPFX/$DRCU/$STUS'"
			find "$GPFX/$DRCU/$STUS" -type f -exec grep -Iq . {} \; -print -quit >/dev/null
		else
			while read -r gtxtfile; do
				while read -r skip; do
					if grep -q "$skip" <<< "$gtxtfile"; then
						SKIPGTF=1
					fi
				done < "$EXID"
						
				if [ "$SKIPGTF" -eq 0 ]; then
					GameTxtFiles+=("$gtxtfile")
				else
					SKIPGTF=0
				fi
			done <<< "$(find "$GPFX/$DRCU/$STUS" -type f -exec grep -Iq . {} \; -print)"	
		fi
	fi
}

function getAvailableCfgs {
	unset CfgFiles
	while read -r cfgfile; do
		if [ -f "${!cfgfile}" ]; then
			CfgFiles+=("${!cfgfile}")
		fi
	done <<< "$(sed -n "/^#STARTEDITORCFGLIST/,/^#ENDEDITORCFGLIST/p;/^#ENDEDITORCFGLIST/q" "$0" | grep -v "^#" | grep -v "LOGFILE" | grep "=" | cut -d '=' -f1)"	

	getGameTextFiles "X"
}

function confirmReq {
	QUESTION="$2"
	TITLE="${PROGNAME}-$1"
	pollWinRes "$TITLE"
	setShowPic
	
	"$YAD" --image "$SHOWPIC" --image-on-top --window-icon="$STLICON" --center --on-top "$WINDECO" --title="$TITLE" --text="$(spanFont "$QUESTION" "H")" "$GEOM"
	echo "$?"
}

function EditorDialog {
	writelog "INFO" "${FUNCNAME[0]} - Opening Editor Dialog"

	resetAID "$1"
	
	loadCfg "$STLGAMECFG" X

	getAvailableCfgs
	
	if [ "$BACKUPSTEAMUSER" -eq 1 ]; then
		EXID="$BACKEX/exclude-${AID}.txt"
		if [ -f "$EXID" ]; then
			CfgFiles+=("$EXID")
		fi
	fi

	HIDEID="$HIDEDIR/hide-${AID}.txt"
	if [ -f "$HIDEID" ]; then
		CfgFiles+=("$HIDEID")
	fi

	if [ -f "$MAHUTMPL" ]; then
		CfgFiles+=("$MAHUTMPL")
	fi

	MHIC="$MAHUCID/${AID}.conf"
	if [ -f "$MHIC" ]; then
		CfgFiles+=("$MHIC")
	fi
	
	getGameTextFiles
	CfgFiles+=("${GameTxtFiles[@]}")

	if [ -f "$LOGFILE" ]; then
		CfgFiles+=("$LOGFILE")
	fi

	REVALSC="$EVMETAID/${EVALSC}_${AID}.vdf"
	CEVALSC="$EVMETACUSTOMID/${EVALSC}_${AID}.vdf"
	AEVALSC="$EVMETAADDONID/${EVALSC}_${AID}.vdf"
	
	if [ -f "$REVALSC" ]; then
		CfgFiles+=("$REVALSC")
	fi

	if [ -f "$CEVALSC" ]; then
		CfgFiles+=("$CEVALSC")
	fi
	
	if [ "$UUUSEIGCS" -eq 1 ] || [ "$USEIGCS" -eq 1 ]; then
		IGCSINI="$EFD/${IGCS}.ini"
		if	 [ -f "$IGCSINI" ]; then
			CfgFiles+=("$IGCSINI")
		fi
	fi
	
	if [ "$UUUSEPATCH" -eq 1 ] || [ "$UUUSEVR" -eq 1 ]; then
		UUUPATCHFILE="$(find "$MEGAMEDIR" -name "$UUUPATCH")"
		if	[ -f "$UUUPATCHFILE" ]; then
			CfgFiles+=("$UUUPATCHFILE")
		fi
	fi

	if [ "$USERESHADE" -eq 1 ] || [ "$USESPECIALK" -eq 1 ]; then
		setFullGameExePath "FGEP"
		while read -r inifile; do
			if [ -f "$inifile" ]; then
				CfgFiles+=("$inifile")
			fi
		done <<< "$(find "$FGEP" -mindepth 1 -maxdepth 1 -type f -name "*.ini")"
	fi

	if [ "$USEOPENVRFSR" -eq 1 ]; then
		OVRFP="$EFD/${OVFS}-${SHOSTL}-enabled.txt"
		if [ -f "$OVRFP" ]; then
			OVRMODF="$EFD/$(grep "$OVRMOD" "$OVRFP")"
			if [ -f "$OVRMODF" ]; then
				CfgFiles+=("$OVRMODF")
			fi
		fi
	fi
	
	if [ -f "$AEVALSC" ]; then
		CfgFiles+=("$AEVALSC")
	fi
	
	if [ -f "$STLPROTONIDLOGDIR/steam-${AID}.log" ]; then
		CfgFiles+=("$STLPROTONIDLOGDIR/steam-${AID}.log")
	fi

	if [ -f "$STLDXVKLOGDIR/${GE}_d3d11.log" ]; then
		CfgFiles+=("$STLDXVKLOGDIR/${GE}_d3d11.log")
	fi

	if [ -f "$STLDXVKLOGDIR/${GE}_dxgi.log" ]; then
		CfgFiles+=("$STLDXVKLOGDIR/${GE}_dxgi.log")
	fi

	writelog "INFO" "${FUNCNAME[0]} - Found ${#CfgFiles[@]} available Config Files - opening Checklist"
	export CURWIKI="$PPW/Editor-Menu"
	TITLE="${PROGNAME}-Editor"
	pollWinRes "$TITLE"

	setShowPic

	EDFILES="$(while read -r f; do	echo "FALSE"; echo "$f"; done <<< "$(printf "%s\n" "${CfgFiles[@]}" | sort -u)" | \
	"$YAD" --f1-action="$F1ACTION" --image "$SHOWPIC" --image-on-top --window-icon="$STLICON" --center $WINDECO --list --checklist --column=Edit --column=ConfigFile --separator="\n" --print-column="2" \
	--text="$(spanFont "$(strFix "$GUI_EDITORDIALOG" "$SGNAID")" "H")" --title="$TITLE" --button="$BUT_EDIT":0 --button="$BUT_HIDE":2 --button="$BUT_OD":4 --button="$BUT_DEL":6 --button="$BUT_CAN":8 "$GEOM")"
	case $? in
		0)  {
				if [ -n "$EDFILES" ]; then
					if [ -n "$HELPURL" ] && [ "$HELPURL" != "$NON" ]; then 
						writelog "INFO" "${FUNCNAME[0]} - Opening the url '$HELPURL' in the browser"
						checkHelpUrl "$HELPURL"
					fi
	
					writelog "INFO" "${FUNCNAME[0]} - Opening Editor '$STLEDITOR' with selected Config Files"
					mapfile -t -O "${#EdArr[@]}" EdArr <<< "$EDFILES"
					"$STLEDITOR" "${EdArr[@]}"
					unset EdArr
					# kill browser if it was opened with the editor:
					if [ -n "$KILLBROWSER" ]; then
						if [ "$KILLBROWSER" -eq 1 ]; then
							"$PKILL" -f "$BROWSER"
						fi
					fi
				fi
			}
		;;
		2)  {
		writelog "INFO" "${FUNCNAME[0]} - Selected HIDE 1"
				if [ -n "$EDFILES" ]; then
					HIDELIST="$HIDEDIR/hide-${AID}.txt"
					writelog "INFO" "${FUNCNAME[0]} - Selected HIDE - Hiding all selected files from the EditorList by adding them to the Exclude list '$HIDELIST'"
					echo "$EDFILES"	 >> "$HIDELIST"
					sort -u"$HIDELIST" -o "$HIDELIST"
					sed "/^ *$/d" -i "$HIDELIST"
				fi
			}
		;;
		4)  writelog "INFO" "${FUNCNAME[0]} - Selected Open Directory - Opening the directory containing the first selected file using '$XDGO'"
			mapfile -t -O "${#EdArr[@]}" EdArr <<< "$EDFILES"
			"$XDGO" "$(dirname "${EdArr[0]}")"
			unset EdArr
		;;
		6)  writelog "INFO" "${FUNCNAME[0]} - Selected Delete"
			RSEL="$(confirmReq "Ask_Delete_Selected_Files" "$GUI_DELSEL")"
			if [ "$RSEL" -eq 0 ]; then
			{
				writelog "INFO" "${FUNCNAME[0]} - Confirmed deletion of all selected files"
				mapfile -t -O "${#EdArr[@]}" EdArr <<< "$EDFILES"
				rm "${EdArr[@]}" 2>/dev/null
				unset EdArr
			}
			else
				writelog "INFO" "${FUNCNAME[0]} - Selected CANCEL - Not deleting the files"
			fi
		;;
		8)  writelog "INFO" "${FUNCNAME[0]} - Selected CANCEL"
		;;
	esac

	goBackToPrevFunction "${FUNCNAME[0]}" "$2"
}

function goBackToPrevFunction {
	IAM="$1"
	PREV="$2"
	
	if [ "$IAM" != "$PREV" ]; then
		if [ -z "$3" ]; then
			MYGOBACK=1
		else
			MYGOBACK="$3"
		fi

		if [ -z "$PREV" ]; then
			writelog "INFO" "${FUNCNAME[0]} - '$IAM' closed"
		else
			if [ "$PREV" != "$NON" ] && [ "$MYGOBACK" -eq 1 ]; then
				writelog "INFO" "${FUNCNAME[0]} - '$IAM' closed - Going back to the '$PREV'"
				"$PREV" "$AID" "$IAM"
			else
				writelog "INFO" "${FUNCNAME[0]} - '$IAM' closed"
			fi
		fi
	else
		writelog "SKIP" "${FUNCNAME[0]} - Took a wrong road somewhere - '$IAM' and '$PREV' - leaving"
	fi
}

function closeTrayIcon {
	notiShow "$(strFix "$NOTY_CLOSETRAY" "$YADTRAYPID")"
	writelog "INFO" "${FUNCNAME[0]} - Closing TrayIcon '$YADTRAYPID'"
	kill "$YADTRAYPID" 2>/dev/null
}

function cleanYadLeftOvers {
	closeTrayIcon
}

function GETALTEXEPATH {
	if [ -n "$ALTEXEPATH" ] && [ "$ALTEXEPATH" != "/tmp" ]; then
		if [ -d "$ALTEXEPATH" ]; then
			echo "$ALTEXEPATH"
		elif [ -d "$EFD/$ALTEXEPATH" ]; then
			echo "$EFD/$ALTEXEPATH"
		fi
	fi
}

#STARTIEX
function TrayIconExports {
	export XWI="$XWININFO"
	export XDO="$XDO"
	export PROGCMD="$PROGCMD"

	export -f writelog
	export AID="$AID"

	export GPFX="$GPFX"
	export KILLSWITCH="$KILLSWITCH"
	export -f killProtonGame
	export -f PauseGame
	export EFD="$EFD"
	export GAMEWINDOW="$GAMEWINDOW"
	export UPWINTMPL="$UPWINTMPL"
	export TRAYCUSC="$TRAYCUSC"

	if [ -n "$(GETALTEXEPATH)" ]; then
		SHADDESTDIR="$(GETALTEXEPATH)"
	fi

	export SHADDESTDIR="$SHADDESTDIR"

	KPFX="$GPFX"
	if [ "$USEWINE" -eq 1 ]; then
		setWineVars
		KPFX="$GWFX"
	fi

	if [ ! -f "$RUNWINE" ]; then
		setRunWineServer "${FUNCNAME[0]}"
	fi

	export RUNWINESERVER="$RUNWINESERVER"

	if [ -n "$KPFX" ]; then
		echo "WINEPREFIX=\"$KPFX\" \"$RUNWINESERVER\" -k" > "$KILLSWITCH"
		echo "touch $CLOSETMP" >> "$KILLSWITCH"
		chmod +x "$KILLSWITCH"
	fi

	export SHADDESTDIR="$SHADDESTDIR"
	export -f TrayShaderMenu
	export -f TrayVR
	export -f TrayPickWin
	export -f TraySRC
	export -f TrayUWT
	export -f TrayLCS
	export -f TrayGameFiles
	export -f TrayMO2
}
#ENDIEX

function openTrayIcon {
	setShadDestDir

	if [ -z "$1" ]; then
		# loading gameconfig here, as some vars might have to be exported
		writelog "INFO" "${FUNCNAME[0]} - LoadCfg: $STLGAMECFG"
		loadCfg "$STLGAMECFG"
	fi
	
	if [ -z "$YADTRAYPID" ] && [ "$USETRAYICON" -eq 1 ]; then
		writelog "INFO" "${FUNCNAME[0]} - Opening trayIcon:" "X"

		# variables and functions used by exported functions below

		# functions for the trayIcon Menu
		function killProtonGame {
			"$KILLSWITCH"
		}

		function PauseGame {
			GAMEPID="$(sleep 5 && "$XDO" getactivewindow getwindowpid)"
			# idea taken with friendly permission from $GHURL/Ilazki:
			GAMESTATE="$(ps -q "$GAMEPID" -o state --no-headers)"
			GAMESIG="-STOP"

			if [ "$GAMESTATE" = "T" ] ; then
				GAMESIG="-CONT"
			fi

			kill "$GAMESIG" "$GAMEPID"
		}

		function TrayShaderMenu {
			"$PROGCMD" update gameshaders "$SHADDESTDIR"
		}

		function TrayVR {
			if [ -z "$GAMEWINDOW" ]; then
				GAMEWINDOW="$(sleep 2 && "$XWI" -stats | grep ^"$XWI" | tail -n1 | cut -d '"' -f2)";
			fi

			if [ -n "$GAMEWINDOW" ]; then
				writelog "INFO" "${FUNCNAME[0]} - TrayIcon: picked '$PICKWINDOWNAME'"
				"$PROGCMD" "vr" "$PICKWINDOWNAME" "$AID" "s"
			else
				writelog "SKIP" "${FUNCNAME[0]} - TrayIcon: Didn't find a game window name to open in vr"
			fi
		}
			
		function TrayPickWin {
			writelog "INFO" "${FUNCNAME[0]} - TrayIcon: Executing Window Pick command for game '$GN '$AID'"
			"$PROGCMD" "pw" "$AID" "$GN"
		}	

		function TraySRC {
			writelog "INFO" "${FUNCNAME[0]} - TrayIcon: Executing command '$STEAM ${STEAM}://${RECO}'"
			"$PROGCMD" "src"
		}

		function TrayUWT {
			writelog "INFO" "${FUNCNAME[0]} - TrayIcon: Triggering Window Template Update"
			touch "$UPWINTMPL"
		}

		function TrayLCS {
			writelog "INFO" "${FUNCNAME[0]} - TrayIcon: Triggering Launch custom script"
			"$TRAYCUSC"
		}

		function TrayGameFiles {
			writelog "INFO" "${FUNCNAME[0]} - TrayIcon: Executing Game Files command for game '$GN '$AID'"
			"$PROGCMD" "gf" "$AID"
		}	
		
		function TrayMO2 {
			writelog "INFO" "${FUNCNAME[0]} - TrayIcon: Starting standalone $MO instance"
			"$PROGCMD" "mo2" "start"
		}	
			
		TrayIconExports
		
		# actually open the actual trayIcon	
		"$YAD" --image="$STLICON" --notification --item-separator=","\
		--menu="$TRAY_KILLSWITCH,bash -c killProtonGame \
		|$TRAY_PAUSE,bash -c PauseGame \
		|$TRAY_SHADER,bash -c TrayShaderMenu \
		|$TRAY_VR,bash -c TrayVR \
		|$TRAY_PICKWINDOW,bash -c TrayPickWin \
		|$TRAY_SRC,bash -c TraySRC \
		|$TRAY_UWT,bash -c TrayUWT \
		|$TRAY_LCS,bash -c TrayLCS \
		|$GUI_GAFI,bash -c TrayGameFiles \
		|$FBUT_GUISET_MO,bash -c TrayMO2 " \
		--text="$TRAY_TOOLTIP" >/dev/null 2>/dev/null &
		YADTRAYPID="$!"
	fi
}

function createProtonList {
	delEmptyFile "$PROTONCSV"
	if [ ! -f "$PROTONCSV" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Looking for available Proton versions"
		getAvailableProtonVersions "up" X
	fi

	if [ "$ISGAME" -eq 2 ] || [ -n "$1" ] ; then
		PROTYADLIST="$(printf "!%s\n" "${ProtonCSV[@]//\"/}" | sort -u | cut -d ';' -f1 | tr -d '\n' | sed "s:^!::" | sed "s:!$::")"
	fi
}

function createDropdownLists {
	createProtonList
	createWineList
	createLanguageList
}

function favoritesMenuEntries {
	if [ -f "$STLFAVMENUCFG" ]; then
		unset FavSel
		mapfile -t -O "${#FavSel[@]}" FavSel < "$STLFAVMENUCFG"
	else
		FAVMENUCFG="$GLOBALMISCDIR/$FACO"

		if [ -f "$FAVMENUCFG" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Using global favorites preset for preselecting some entries"
			mapfile -t -O "${#FavSel[@]}" FavSel < "$FAVMENUCFG"
		else
			writelog "INFO" "${FUNCNAME[0]} - Global favorites preset '$FAVMENUCFG' not found - starting with zero preselection"
			declare -a FavSel
		fi
	fi
	
	while read -r ENTRY; do
		GE="GUI_${ENTRY}"
		DE="DESC_${ENTRY}"
		if [ -z "${!GE}" ]; then
			GEOUT="no description"
		else
			GEOUT="${!GE}"
		fi

		if [ -z "${!DE}" ]; then
			DEOUT="no description"
		else
			DEOUT="${!DE}"
		fi

		if grep -q "^$ENTRY$" <<< "$(printf "%s\n" "${FavSel[@]}")"; then 
			echo TRUE
			echo "$GEOUT"
			echo "$ENTRY"
			echo "$DEOUT"
		else
			echo FALSE
			echo "$GEOUT"
			echo "$ENTRY"
			echo "$DEOUT"
		fi
	done <<< "$(sort "$STLSETENTRIES")"
}

function favoritesMenu {
	if [ -z "$2" ]; then
		BACKFUNC="$NON"
	else
		if [ "$2" == "setGuiFavoritesSelection" ]; then
			BACKFUNC="MainMenu"
		else
			BACKFUNC="$2"
		fi
	fi

	if [ -f "${FAVMENU}-${TMPL}" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Found an autoconfigured favorites menu template '${FAVMENU}-${TMPL}' - using it directly"
		openCustMenu "$1" "$BACKFUNC" "Favorites" "$FAVMENU" "$LFM"
	else
		if [ ! -f "$STLFAVMENUCFG" ]; then
			writelog "INFO" "${FUNCNAME[0]} - No Favorites defined yet - opening Favorites Selection"
			rm "${FAVMENU}-${TMPL}" 2>/dev/null
			setGuiFavoritesSelection "$AID" "${FUNCNAME[0]}"
		fi

		if [ -f "$STLFAVMENUCFG" ]; then
			TEMPF="${FAVMENU}-${TMPL}_w1"
			touch "$TEMPF"
			while read -r savfav; do
				SAVCAT="CAT_$(grep "'$savfav'" "$STLRAWENTRIES" | grep -oP '#CAT_\K[^`]+')"
				FAVHEADL="$(grep "#HEAD" "$STLRAWENTRIES" | grep "$SAVCAT")"
				FAVHEAD="HEAD_$(grep -oP '#HEAD_\K[^`]+' <<< "$FAVHEADL")"
				if ! grep -q "$FAVHEAD" "$TEMPF" && [ "$SAVCAT" != "CAT_" ]; then
					echo "$FAVHEADL" >> "$TEMPF"
				fi

				grep "'$savfav'" "$STLRAWENTRIES" >> "$TEMPF"
			done < "$STLFAVMENUCFG"

			getFilteredEntries "$TEMPF" >> "${FAVMENU}-${TMPL}"

			rm "$TEMPF" 2>/dev/null

			writelog "INFO" "${FUNCNAME[0]} - Found '$(wc -l < "${FAVMENU}-${TMPL}")' selected Favorites - opening the Menu now"
			openCustMenu "$1" "$BACKFUNC" "Favorites" "$FAVMENU" "$LFM"
		else
			writelog "SKIP" "${FUNCNAME[0]} - Still no Favorites defined - skipping"
		fi
	fi
}

function listAllSettingsEntries {

	if [ -f "$STLSETENTRIES" ]; then
		writelog "INFO" "${FUNCNAME[0]} - '$STLSETENTRIES' already exists - nothing to do"
	else
		writelog "INFO" "${FUNCNAME[0]} - Creating '$STLSETENTRIES'"
		while read -r ENTRY; do
			echo "$ENTRY" | tee -a "$STLRAWENTRIES" >/dev/null
			grep -oP "\('\K[^\')]+" <<< "$ENTRY" | tee -a "$STLSETENTRIES" >/dev/null
		done <<< "$(sed -n "/^#STARTSETENTRIES/,/^#ENDSETENTRIES/p;/^#ENDSETENTRIES/q" "$0" | grep "\-\-field")"
	fi
}

function spanFont {
	STRIN="$1"

	if [ "$2" == "H" ]; then
		FOSI="$HEADLINEFONT"
		FOWE="bold"
	fi

	SPIN="<span font_size='$FOSI' font_weight='$FOWE'>"
	SPOUT="</span>"
	echo "$SPIN$STRIN$SPOUT"
}

function AllSettingsEntriesDummyFunction {
#STARTSETENTRIES
	echo \
--field="$(spanFont "$GUI_OPTSGUI" "H")":LBL "SKIP" `#CAT_Gui` `#HEAD_Gui` `#MENU_GAME` `#MENU_GLOBAL` \
--field="     $GUI_STLLANG!$DESC_STLLANG ('STLLANG')":CB "$(cleanDropDown "${STLLANG/#-/ -}" "$LANGYADLIST")" `#CAT_Gui` `#MENU_GLOBAL` \
--field="     $GUI_STARTMENU!$DESC_STARTMENU ('STARTMENU')":CB "$(cleanDropDown "${STARTMENU/#-/ -}" "Editor!Favorites!Game!Menu")" `#CAT_Gui` `#MENU_GLOBAL` \
--field="     $GUI_WAITEDITOR!$DESC_WAITEDITOR ('WAITEDITOR')":NUM "${WAITEDITOR/#-/ -}" `#CAT_Gui` `#MENU_GAME` \
--field="     $GUI_MAXASK!$DESC_MAXASK ('MAXASK')":NUM "${MAXASK/#-/ -}" `#CAT_Gui` `#MENU_GLOBAL` \
--field="     $GUI_SAVESETSIZE!$DESC_SAVESETSIZE ('SAVESETSIZE')":CHK "${SAVESETSIZE/#-/ -}" `#CAT_Gui` `#SUB_Checkbox` `#MENU_GLOBAL` \
--field="     $GUI_TOGGLEWINDOWS!$DESC_TOGGLEWINDOWS ('TOGGLEWINDOWS')":CHK "${TOGGLEWINDOWS/#-/ -}" `#CAT_Gui` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_USETRAYICON!$DESC_USETRAYICON ('USETRAYICON')":CHK "${USETRAYICON/#-/ -}" `#CAT_Gui` `#SUB_Checkbox` `#MENU_GLOBAL` \
--field="     $GUI_USENOTIFIER!$DESC_USENOTIFIER ('USENOTIFIER')":CHK "${USENOTIFIER/#-/ -}" `#CAT_Gui` `#SUB_Checkbox` `#MENU_GLOBAL` \
--field="     $GUI_HEADLINEFONT!$DESC_HEADLINEFONT ('HEADLINEFONT')":CB "$(cleanDropDown "${HEADLINEFONT/#-/ -}" "$FONTSIZES")" `#CAT_Gui` `#MENU_GLOBAL` \
--field="     $GUI_USEWINDECO!$DESC_USEWINDECO ('USEWINDECO')":CHK "${USEWINDECO/#-/ -}" `#CAT_Gui` `#SUB_Checkbox` `#MENU_GLOBAL` \
--field="     $GUI_DLGAMEDATA!$DESC_DLGAMEDATA ('DLGAMEDATA')":CHK "${DLGAMEDATA/#-/ -}" `#CAT_Gui` `#SUB_Checkbox` `#MENU_GLOBAL` \
--field="     $GUI_USEGAMEPICS!$DESC_USEGAMEPICS ('USEGAMEPICS')":CHK "${USEGAMEPICS/#-/ -}" `#CAT_Gui` `#SUB_Checkbox` `#MENU_GLOBAL` \
--field="     $GUI_USECUSTOMFALLBACKPIC!$DESC_USECUSTOMFALLBACKPIC ('USECUSTOMFALLBACKPIC')":CHK "${USECUSTOMFALLBACKPIC/#-/ -}" `#CAT_Gui` `#SUB_Checkbox` `#MENU_GLOBAL` \
--field="     $GUI_GITHUBUSER!$DESC_GITHUBUSER ('GITHUBUSER')":CBE "${GITHUBUSER/#-/ -}" `#CAT_Gui` `#MENU_GLOBAL` \
--field="     $GUI_CHECKCATEGORIES!$DESC_CHECKCATEGORIES ('CHECKCATEGORIES')":CHK "${CHECKCATEGORIES/#-/ -}" `#CAT_Gui` `#SUB_Checkbox` `#MENU_GAME` \
--field="$(spanFont "$GUI_OPTSGRID" "H")":LBL "SKIP" `#CAT_SteamGridDB` `#HEAD_SteamGridDB` `#MENU_GLOBAL` \
--field="     $GUI_SGDBDLTOSTEAM!$DESC_SGDBDLTOSTEAM ('SGDBDLTOSTEAM')":CHK "${SGDBDLTOSTEAM/#-/ -}" `#CAT_SteamGridDB` `#SUB_Checkbox` `#MENU_GLOBAL` \
--field="     $GUI_SGDBAPIKEY!$DESC_SGDBAPIKEY ('SGDBAPIKEY')":CBE "${SGDBAPIKEY/#-/ -}" `#CAT_SteamGridDB` `#MENU_GLOBAL` \
--field="     $GUI_SGDBHASFILE!$DESC_SGDBHASFILE ('SGDBHASFILE')":CB "$(cleanDropDown "${SGDBHASFILE/#-/ -}" "skip!backup!replace")" `#CAT_SteamGridDB` `#MENU_GLOBAL` \
--field="     $GUI_SGDBAUTODL!$DESC_SGDBAUTODL ('SGDBAUTODL')":CB "$(cleanDropDown  "${SGDBAUTODL/#-/ -}" "$NON!after_game!before_game!no_meta")" `#CAT_SteamGridDB` `#MENU_GLOBAL` \
--field="     $GUI_SGDBSTYLES!$DESC_SGDBSTYLES ('SGDBSTYLES')":CBE "$(cleanDropDown "${SGDBSTYLES/#-/ -}" "${SGDBSTYOPTS//,/\!}")" `#CAT_SteamGridDB` `#MENU_GLOBAL` \
--field="     $GUI_SGDBDIMS!$DESC_SGDBDIMS ('SGDBDIMS')":CBE "$(cleanDropDown "${SGDBDIMS/#-/ -}" "${SGDBDIMOPTS//,/\!}")" `#CAT_SteamGridDB` `#MENU_GLOBAL` \
--field="     $GUI_SGDBTYPES!$DESC_SGDBTYPES ('SGDBTYPES')":CBE "$(cleanDropDown "${SGDBTYPES/#-/ -}" "animated!static!animated,static!static,animated")" `#CAT_SteamGridDB` `#MENU_GLOBAL` \
--field="     $GUI_SGDBNSFW!$DESC_SGDBNSFW ('SGDBNSFW')":CBE "$(cleanDropDown "${SGDBNSFW/#-/ -}" "any!false!true")" `#CAT_SteamGridDB` `#MENU_GLOBAL` \
--field="     $GUI_SGDBHUMOR!$DESC_SGDBHUMOR ('SGDBHUMOR')":CBE "$(cleanDropDown "${SGDBHUMOR/#-/ -}" "any!false!true")" `#CAT_SteamGridDB` `#MENU_GLOBAL` \
--field="$(spanFont "$GUI_OPTSMISC" "H")":LBL "SKIP" `#CAT_Misc` `#HEAD_Misc` `#MENU_GAME` `#MENU_GLOBAL`  \
--field="     $GUI_USECUSTOMCMD!$DESC_USECUSTOMCMD ('USECUSTOMCMD')":CHK "${USECUSTOMCMD/#-/ -}" `#CAT_Misc` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_CUSTOMCMD!$DESC_CUSTOMCMD $GUI_ECHOPLAC ('CUSTOMCMD')":FL "${OPCUSTPATH/#-/ -}" `#CAT_Misc` `#MENU_GAME` \
--field="     $GUI_CUSTOMCMD_ARGS!$DESC_CUSTOMCMD_ARGS ('CUSTOMCMD_ARGS')" "${CUSTOMCMD_ARGS/#-/ -}" `#CAT_Misc` `#MENU_GAME` \
--field="     $GUI_FORK_CUSTOMCMD!$DESC_FORK_CUSTOMCMD ('FORK_CUSTOMCMD')":CHK "${FORK_CUSTOMCMD/#-/ -}" `#CAT_Misc` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_ONLY_CUSTOMCMD!$DESC_ONLY_CUSTOMCMD ('ONLY_CUSTOMCMD')":CHK "${ONLY_CUSTOMCMD/#-/ -}" `#CAT_Misc` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_INJECT_CUSTOMCMD!$DESC_INJECT_CUSTOMCMD ('INJECT_CUSTOMCMD')":CHK "${INJECT_CUSTOMCMD/#-/ -}" `#CAT_Misc` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_INJECTWAIT!$DESC_INJECTWAIT ('INJECTWAIT')":NUM "${INJECTWAIT/#-/ -}" `#CAT_Misc` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_USEIGCS!$DESC_USEIGCS ('USEIGCS')":CHK "${USEIGCS/#-/ -}" `#CAT_Misc` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_UUUSEIGCS!$DESC_UUUSEIGCS ('UUUSEIGCS')":CHK "${UUUSEIGCS/#-/ -}" `#CAT_Misc` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_IGCSWAIT!$DESC_IGCSWAIT ('IGCSWAIT')":NUM "${IGCSWAIT/#-/ -}" `#CAT_Misc` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_UUUSEPATCH!$DESC_UUUSEPATCH ('UUUSEPATCH')":CHK "${UUUSEPATCH/#-/ -}" `#CAT_Misc` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_UUUPATCHWAIT!$DESC_UUUPATCHWAIT ('UUUPATCHWAIT')":NUM "${UUUPATCHWAIT/#-/ -}" `#CAT_Misc` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_USERSTART!$DESC_USERSTART $GUI_ECHOPLAC ('USERSTART')":FL "${USERSTART/#-/ -}" `#CAT_Misc` `#MENU_GAME` \
--field="     $GUI_USERSTOP!$DESC_USERSTOP $GUI_ECHOPLAC ('USERSTOP')":FL "${USERSTOP/#-/ -}" `#CAT_Misc` `#MENU_GAME` \
--field="     $GUI_GAMEARGS!$DESC_GAMEARGS ('GAMEARGS')" "${GAMEARGS/#-/ -}" `#CAT_Misc` `#MENU_GAME` \
--field="     $GUI_SORTGARGS!$DESC_SORTGARGS ('SORTGARGS')":CHK "${SORTGARGS/#-/ -}" `#CAT_Misc` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_HARDARGS!$DESC_HARDARGS ('HARDARGS')":CBE "$(cleanDropDown "${HARDARGS/#-/ -}" "$ARGUMENTS")" `#CAT_Misc` `#MENU_GAME` \
--field="     $GUI_SLOARGS!$DESC_SLOARGS ('SLOARGS')":RO "${SLOARGS/#-/ -}" `#CAT_Misc` `#MENU_GAME` \
--field="     $GUI_CHANGE_PULSE_LATENCY!$DESC_CHANGE_PULSE_LATENCY ('CHANGE_PULSE_LATENCY')":CHK "${CHANGE_PULSE_LATENCY/#-/ -}" `#CAT_Misc` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_STL_PULSE_LATENCY_MSEC!$DESC_STL_PULSE_LATENCY_MSEC ('STL_PULSE_LATENCY_MSEC')":NUM "${STL_PULSE_LATENCY_MSEC/#-/ -}" `#CAT_Misc` `#MENU_GAME` \
--field="     $GUI_LOGLEVEL!$DESC_LOGLEVEL ('LOGLEVEL')":CB "$(cleanDropDown "${LOGLEVEL/#-/ -}" "0!1!2")" `#CAT_Misc` `#MENU_GLOBAL` \
--field="     $GUI_RESETLOG!$DESC_RESETLOG ('RESETLOG')":CHK "${RESETLOG/#-/ -}" `#CAT_Misc` `#SUB_Checkbox` `#MENU_GLOBAL` \
--field="     $GUI_STEAMAPPIDFILE!$DESC_STEAMAPPIDFILE ('STEAMAPPIDFILE')":CHK "${STEAMAPPIDFILE/#-/ -}" `#CAT_Misc` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_SKIPINTDEPCHECK!$DESC_SKIPINTDEPCHECK ('SKIPINTDEPCHECK')":CHK "${SKIPINTDEPCHECK/#-/ -}" `#CAT_Misc` `#SUB_Checkbox` `#MENU_GLOBAL` \
--field="     $GUI_NOSTEAMSTLDEF!$DESC_NOSTEAMSTLDEF ('NOSTEAMSTLDEF')":CHK "${NOSTEAMSTLDEF/#-/ -}" `#CAT_Misc` `#SUB_Checkbox` `#MENU_GLOBAL` \
--field="     $GUI_STORECOMPDATTITLE!$DESC_STORECOMPDATTITLE ('STORECOMPDATTITLE')":CHK "${STORECOMPDATTITLE/#-/ -}" `#CAT_Misc` `#SUB_Checkbox` `#MENU_GLOBAL` \
--field="     $GUI_LOGPLAYTIME!$DESC_LOGPLAYTIME ('LOGPLAYTIME')":CHK "${LOGPLAYTIME/#-/ -}" `#CAT_Misc` `#SUB_Checkbox` `#MENU_GLOBAL` \
--field="     $GUI_CRASHGUESS!$DESC_CRASHGUESS ('CRASHGUESS')":NUM "${CRASHGUESS/#-/ -}" `#CAT_Misc` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_HELPURL!$DESC_HELPURL ('HELPURL')":CB "$(cleanDropDown "${HELPURL}" "${HUYLIST}${NON}")" `#CAT_Misc` `#MENU_GAME` \
--field="     $GUI_CREATEDESKTOPICON!$DESC_CREATEDESKTOPICON ('CREATEDESKTOPICON')":NUM "${CREATEDESKTOPICON}!0..3" `#CAT_Misc` `#MENU_GAME` \
--field="     $GUI_GAMESCREENRES!$DESC_GAMESCREENRES ('GAMESCREENRES')":CBE "$(cleanDropDown "${GAMESCREENRES/#-/ -}" "$(printf "%s\n" "$(listScreenRes | tr '\n' '!')")$NON")" `#CAT_Misc` `#MENU_GAME` \
--field="     $GUI_TOGSTEAMWEBHELPER!$DESC_TOGSTEAMWEBHELPER ('TOGSTEAMWEBHELPER')":CHK "${TOGSTEAMWEBHELPER/#-/ -}" `#CAT_Misc` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_STL_PV_VERBOSE!$DESC_STL_PV_VERBOSE ('STL_PV_VERBOSE')":CHK "${STL_PV_VERBOSE/#-/ -}" `#CAT_Misc` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_STL_PV_SHELL!$DESC_STL_PV_SHELL ('STL_PV_SHELL')":CB "$(cleanDropDown "${STL_PV_SHELL/#-/ -}" "none!after!fail!instead")" `#CAT_Misc` `#MENU_GAME` \
--field="     $GUI_STL_PV_TERMINAL!$DESC_STL_PV_TERMINAL ('STL_PV_TERMINAL')":CB "$(cleanDropDown "${STL_PV_TERMINAL/#-/ -}" "none!auto!tty!xterm")" `#CAT_Misc` `#MENU_GAME` \
--field="     $GUI_USESPECIALK!$DESC_USESPECIALK ('USESPECIALK')":CHK "${USESPECIALK/#-/ -}" `#CAT_Misc` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_SPEKVERS!$DESC_SPEKVERS ('SPEKVERS')":CB "$(cleanDropDown "${SPEKVERS/#-/ -}" "test!stable!old!$DISC")" `#CAT_Misc` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_USEFWS!$DESC_USEFWS ('USEFWS')":CHK "${USEFWS/#-/ -}" `#CAT_Misc` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_USETERM!$DESC_USETERM ('USETERM')":FL "${USETERM/#-/ -}" `#CAT_Misc` `#SUB_Checkbox` `#MENU_GLOBAL` \
--field="     $GUI_TERMARGS!$DESC_TERMARGS ('TERMARGS')" "${TERMARGS/#-/ -}" `#CAT_Misc` `#SUB_Checkbox` `#MENU_GLOBAL` \
--field="$(spanFont "$GUI_OPTSPROTON" "H")":LBL "SKIP" `#CAT_Proton` `#HEAD_Proton` `#MENU_GAME` `#MENU_GLOBAL` \
--field="     $GUI_USEPROTON!$DESC_USEPROTON ('USEPROTON')":CB "$(cleanDropDown  "${USEPROTON/#-/ -}" "$PROTYADLIST")" `#CAT_Proton` `#MENU_GAME` \
--field="     $GUI_USESLR!$DESC_USESLR ('USESLR')":CHK "${USESLR/#-/ -}" `#CAT_Proton` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_FORCESLR!$DESC_FORCESLR ('FORCESLR')":CHK "${FORCESLR/#-/ -}" `#CAT_Proton` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_USEREAP!$DESC_USEREAP ('USEREAP')":CHK "${USEREAP/#-/ -}" `#CAT_Proton` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_FORCEREAP!$DESC_FORCEREAP ('FORCEREAP')":CHK "${FORCEREAP/#-/ -}" `#CAT_Proton` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_AUTOLASTPROTON!$DESC_AUTOLASTPROTON ('AUTOLASTPROTON')":CHK "${AUTOLASTPROTON/#-/ -}" `#CAT_Proton` `#SUB_Checkbox` `#MENU_GLOBAL` \
--field="     $GUI_REDIRCOMPDATA!$DESC_REDIRCOMPDATA ('REDIRCOMPDATA')":CB "$(cleanDropDown "${REDIRCOMPDATA/#-/ -}" "disabled!single-proton!global-proton")" `#CAT_Proton` `#MENU_GAME` \
--field="     $GUI_REDIRSTEAMUSER!$DESC_REDIRSTEAMUSER ('REDIRSTEAMUSER')":CB "$(cleanDropDown "${REDIRSTEAMUSER/#-/ -}" "disabled!symlink!restore-backup")" `#CAT_Proton` `#MENU_GAME` \
--field="     $GUI_AUTOBUMPGE!$DESC_AUTOBUMPGE ('AUTOBUMPGE')":CHK "${AUTOBUMPGE/#-/ -}" `#CAT_Proton` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_PROTON_LOG!$DESC_PROTON_LOG $HOME/steam-$AID.log ('PROTON_LOG')":CHK "${PROTON_LOG/#-/ -}" `#CAT_Proton` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_PROTON_LOG_DIR!$DESC_PROTON_LOG_DIR ('PROTON_LOG_DIR')":DIR "${PROTON_LOG_DIR/#-/ -}" `#CAT_Proton` `#SUB_Directories` `#MENU_GAME` \
--field="     $GUI_USEWINEDEBUGPROTON!$DESC_USEWINEDEBUGPROTON ('USEWINEDEBUGPROTON')":CHK "${USEWINEDEBUGPROTON/#-/ -}" `#CAT_Proton` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_PROTON_NO_D3D10!$DESC_PROTON_NO_D3D10 ('PROTON_NO_D3D10')":CHK "${PROTON_NO_D3D10/#-/ -}" `#CAT_Proton` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_PROTON_NO_D3D11!$DESC_PROTON_NO_D3D11 ('PROTON_NO_D3D11')":CHK "${PROTON_NO_D3D11/#-/ -}" `#CAT_Proton` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_PROTON_NO_ESYNC!$DESC_PROTON_NO_ESYNC ('PROTON_NO_ESYNC')":CHK "${PROTON_NO_ESYNC/#-/ -}" `#CAT_Proton` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_PROTON_NO_FSYNC!$DESC_PROTON_NO_FSYNC ('PROTON_NO_FSYNC')":CHK "${PROTON_NO_FSYNC/#-/ -}" `#CAT_Proton` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_PROTON_ENABLE_NVAPI!$DESC_PROTON_ENABLE_NVAPI ('PROTON_ENABLE_NVAPI')":CHK "${PROTON_ENABLE_NVAPI/#-/ -}" `#CAT_Proton` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_PROTON_PROTON_HIDE_NVIDIA_GPU!$DESC_PROTON_HIDE_NVIDIA_GPU ('PROTON_HIDE_NVIDIA_GPU')":CHK "${PROTON_HIDE_NVIDIA_GPU/#-/ -}" `#CAT_Proton` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_USEDLSS!$DESC_USEDLSS ('USEDLSS')":CHK "${USEDLSS/#-/ -}" `#CAT_Proton` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_PROTON_USE_WINED3D!$DESC_PROTON_USE_WINED3D ('PROTON_USE_WINED3D')":CHK "${PROTON_USE_WINED3D/#-/ -}" `#CAT_Proton` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_PROTON_DEBUG_DIR!$DESC_PROTON_DEBUG_DIR ('PROTON_DEBUG_DIR')":DIR "${PROTON_DEBUG_DIR/#-/ -}" `#CAT_Proton` `#SUB_Directories` `#MENU_GAME` \
--field="     $GUI_PROTON_DUMP_DEBUG_COMMANDS!$DESC_PROTON_DUMP_DEBUG_COMMANDS ('PROTON_DUMP_DEBUG_COMMANDS')":CHK "${PROTON_DUMP_DEBUG_COMMANDS/#-/ -}" `#CAT_Proton` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_PROTON_FORCE_LARGE_ADDRESS_AWARE!$DESC_PROTON_FORCE_LARGE_ADDRESS_AWARE ('PROTON_FORCE_LARGE_ADDRESS_AWARE')":CHK "${PROTON_FORCE_LARGE_ADDRESS_AWARE/#-/ -}" `#CAT_Proton` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_DXVK_HUD!$DESC_DXVK_HUD ('DXVK_HUD')":CBE "$(cleanDropDown "${DXVK_HUD/#-/ -}" "0!1")" `#CAT_Proton` `#SUB_Dxvk` `#MENU_GAME` \
--field="     $GUI_DXVK_LOG_LEVEL!$DESC_DXVK_LOG_LEVEL ('DXVK_LOG_LEVEL')":CB "$(cleanDropDown "${DXVK_LOG_LEVEL/#-/ -}" "none!error!warn!info!debug")" `#CAT_Proton` `#SUB_Dxvk` `#MENU_GAME` \
--field="     $GUI_DXVK_LOG_PATH!$DESC_DXVK_LOG_PATH ('DXVK_LOG_PATH')":DIR "${DXVK_LOG_PATH/#-/ -}" `#CAT_Proton` `#SUB_Directories` `#MENU_GAME` \
--field="     $GUI_DXVK_SCALE!$DESC_DXVK_SCALE ('DXVK_SCALE')" "${DXVK_SCALE/#-/ -}" `#CAT_Proton` `#MENU_GAME` \
--field="     $GUI_CUSTPROTDLDIR!$DESC_CUSTPROTDLDIR ('CUSTPROTDLDIR')":DIR "${CUSTPROTDLDIR/#-/ -}" `#CAT_Proton` `#SUB_Directories` `#MENU_GLOBAL` \
--field="     $GUI_CUSTPROTEXTDIR!$DESC_CUSTPROTEXTDIR ('CUSTPROTEXTDIR')":DIR "${CUSTPROTEXTDIR/#-/ -}" `#CAT_Proton` `#SUB_Directories` `#MENU_GLOBAL` \
--field="     $GUI_CUPROTOCOMPAT!$DESC_CUPROTOCOMPAT ('CUPROTOCOMPAT')":CHK "${CUPROTOCOMPAT/#-/ -}" `#CAT_Proton` `#SUB_Checkbox` `#MENU_GLOBAL` \
--field="     $GUI_USESUSYM!$DESC_USESUSYM ('USESUSYM')":CHK "${USESUSYM/#-/ -}" `#CAT_Proton` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_USEGLOBSUSYM!$DESC_USEGLOBSUSYM ('USEGLOBSUSYM')":CHK "${USEGLOBSUSYM/#-/ -}" `#CAT_Proton` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_FIXSYMLINKS!$DESC_FIXSYMLINKS ('FIXSYMLINKS')":CHK "${FIXSYMLINKS/#-/ -}" `#CAT_Proton` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_UNSYMLINK!$DESC_UNSYMLINK ('UNSYMLINK')":CHK "${UNSYMLINK/#-/ -}" `#CAT_Proton` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_DELPFX!$DESC_DELPFX ('DELPFX')":CHK "${DELPFX/#-/ -}" `#CAT_Proton` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_BACKUPSTEAMUSER!$DESC_BACKUPSTEAMUSER ('BACKUPSTEAMUSER')":CHK "${BACKUPSTEAMUSER/#-/ -}" `#CAT_Proton` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_RESTORESTEAMUSER!$DESC_RESTORESTEAMUSER ('RESTORESTEAMUSER')":CB "$(cleanDropDown "${RESTORESTEAMUSER/#-/ -}" "$NON!ask-always!ask-if-dst-has-no-backup-timestamp!ask-if-unsure!restore-always!restore-if-backup-timestamp-is-newer!restore-if-dst-has-no-backup-timestamp!restore-if-dst-is-empty")" `#CAT_Proton` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_CLEANPROTONTEMP!$DESC_CLEANPROTONTEMP ('CLEANPROTONTEMP')":CHK "${CLEANPROTONTEMP/#-/ -}" `#CAT_Proton` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_USEPDBRATING!$DESC_USEPDBRATING ('USEPDBRATING')":CHK "${USEPDBRATING/#-/ -}" `#CAT_Proton` `#SUB_Checkbox` `#MENU_GLOBAL` \
--field="     $GUI_PDBRATINGCACHE!$DESC_PDBRATINGCACHE ('PDBRATINGCACHE')":NUM "${PDBRATINGCACHE/#-/ -}" `#CAT_Proton` `#SUB_Checkbox` `#MENU_GLOBAL` \
--field="$(spanFont "$GUI_OPTSVKD3D" "H")":LBL "SKIP" `#CAT_VKD3D` `#HEAD_VKD3D` `#MENU_GAME` \
--field="     $GUI_USERAYTRACING!$DESC_USERAYTRACING ('USERAYTRACING')":CHK "${USERAYTRACING/#-/ -}" `#CAT_VKD3D` `#MENU_GAME` \
--field="     $GUI_STL_VKD3D_CONFIG!$DESC_STL_VKD3D_CONFIG ('STL_VKD3D_CONFIG')":CB "$(cleanDropDown "${STL_VKD3D_CONFIG/#-/ -}" "$NON!vk_debug!skip_application_workarounds!dxr!dxr11!force_static_cbv!single_queue!no_upload_hvv!force_host_cached!no_invariant_position")" `#CAT_VKD3D` `#MENU_GAME` \
--field="     $GUI_STL_VKD3D_DEBUG!$DESC_STL_VKD3D_DEBUG ('STL_VKD3D_DEBUG')":CB "$(cleanDropDown "${STL_VKD3D_DEBUG/#-/ -}" "$NON!err!info!fixme!warn!trace")" `#CAT_VKD3D` `#MENU_GAME` \
--field="     $GUI_STL_VKD3D_SHADER_DEBUG!$DESC_STL_VKD3D_SHADER_DEBUG ('STL_VKD3D_SHADER_DEBUG')":CB "$(cleanDropDown "${STL_VKD3D_SHADER_DEBUG/#-/ -}" "$NON!err!info!fixme!warn!trace")" `#CAT_VKD3D` `#MENU_GAME` \
--field="     $GUI_STL_VKD3D_LOG_FILE!$DESC_STL_VKD3D_LOG_FILE ('STL_VKD3D_LOG_FILE')":CBE "$(cleanDropDown "${STL_VKD3D_LOG_FILE/#-/ -}" "$NON!$STLVKD3DLOGDIR")" `#CAT_VKD3D` `#MENU_GAME` \
--field="     $GUI_STL_VKD3D_VULKAN_DEVICE!$DESC_STL_VKD3D_VULKAN_DEVICE ('STL_VKD3D_VULKAN_DEVICE')":CBE "$(cleanDropDown "${STL_VKD3D_VULKAN_DEVICE/#-/ -}")" `#CAT_VKD3D` `#MENU_GAME` \
--field="     $GUI_STL_VKD3D_FILTER_DEVICE_NAME!$DESC_STL_VKD3D_FILTER_DEVICE_NAME ('STL_VKD3D_FILTER_DEVICE_NAME')":CBE "$(cleanDropDown "${STL_VKD3D_FILTER_DEVICE_NAME/#-/ -}")" `#CAT_VKD3D` `#MENU_GLOBAL` \
--field="     $GUI_STL_VKD3D_DISABLE_EXTENSIONS!$DESC_STL_VKD3D_DISABLE_EXTENSIONS ('STL_VKD3D_DISABLE_EXTENSIONS')":CBE "$(cleanDropDown "${STL_VKD3D_DISABLE_EXTENSIONS/#-/ -}")" `#CAT_VKD3D` `#MENU_GAME` \
--field="     $GUI_STL_VKD3D_TEST_DEBUG!$DESC_STL_VKD3D_TEST_DEBUG ('STL_VKD3D_TEST_DEBUG')":NUM "${STL_VKD3D_TEST_DEBUG}!0..2" `#CAT_VKD3D` `#MENU_GAME` \
--field="     $GUI_STL_VKD3D_TEST_FILTER!$DESC_STL_VKD3D_TEST_FILTER ('STL_VKD3D_TEST_FILTER')":CB "$(cleanDropDown "${STL_VKD3D_TEST_FILTER/#-/ -}" "$NON!clear_render_target")" `#CAT_VKD3D` `#MENU_GAME` \
--field="     $GUI_STL_VKD3D_TEST_EXCLUDE!$DESC_STL_VKD3D_TEST_EXCLUDE ('STL_VKD3D_TEST_EXCLUDE')":CB "$(cleanDropDown "${STL_VKD3D_TEST_EXCLUDE/#-/ -}" "$NON!test_root_signature_priority,test_conservative_rasterization_dxil")" `#CAT_VKD3D` `#MENU_GAME` \
--field="     $GUI_STL_VKD3D_TEST_PLATFORM!$DESC_STL_VKD3D_TEST_PLATFORM ('STL_VKD3D_TEST_PLATFORM')":CB "$(cleanDropDown "${STL_VKD3D_TEST_PLATFORM/#-/ -}" "$NON!wine!windows!other")" `#CAT_VKD3D` `#MENU_GAME` \
--field="     $GUI_STL_VKD3D_TEST_BUG!$DESC_STL_VKD3D_TEST_BUG ('STL_VKD3D_TEST_BUG')":CBE "$(cleanDropDown "${STL_VKD3D_TEST_BUG/#-/ -}" "$NON!0")" `#CAT_VKD3D` `#MENU_GAME` \
--field="     $GUI_STL_VKD3D_PROFILE_PATH!$DESC_STL_VKD3D_PROFILE_PATH ('STL_VKD3D_PROFILE_PATH')":DIR "${STL_VKD3D_PROFILE_PATH/#-/ -}" `#CAT_VKD3D` `#MENU_GAME` \
--field="$(spanFont "$GUI_OPTSSHADER" "H")":LBL "SKIP" `#CAT_Shader` `#HEAD_Shader` `#MENU_GAME` `#MENU_GLOBAL` \
--field="     $GUI_USERESHADE!$DESC_USERESHADE ('USERESHADE')":CHK "${USERESHADE/#-/ -}" `#CAT_Shader` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_DOWNLOAD_RESHADE!$DESC_DOWNLOAD_RESHADE ('DOWNLOAD_RESHADE')":CHK "${DOWNLOAD_RESHADE/#-/ -}" `#CAT_Shader` `#SUB_ReShade` `#SUB_Checkbox` `#MENU_GLOBAL` \
--field="     $GUI_INSTALL_RESHADE!$DESC_INSTALL_RESHADE ('INSTALL_RESHADE')":CHK "${INSTALL_RESHADE/#-/ -}" `#CAT_Shader` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_RESHADEUPDATE!$DESC_RESHADEUPDATE ('RESHADEUPDATE')":CHK "${RESHADEUPDATE/#-/ -}" `#CAT_Shader` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_RSVERS!$DESC_RSVERS ('RSVERS')" "${RSVERS/#-/ -}" `#CAT_Shader` `#SUB_ReShade` `#MENU_GLOBAL` \
--field="     $GUI_RS_32!$DESC_RS_32 ('RS_32')" "${RS_32/#-/ -}" `#CAT_Shader` `#SUB_ReShade` `#MENU_GLOBAL` \
--field="     $GUI_RS_64!$DESC_RS_64 ('RS_64')" "${RS_64/#-/ -}" `#CAT_Shader` `#SUB_ReShade` `#MENU_GLOBAL` \
--field="     $GUI_D3D47_32!$DESC_D3D47_32 ('D3D47_32')" "${D3D47_32/#-/ -}" `#CAT_Shader` `#SUB_ReShade` `#MENU_GLOBAL` \
--field="     $GUI_D3D47_64!$DESC_D3D47_64 ('D3D47_64')" "${D3D47_64/#-/ -}" `#CAT_Shader` `#SUB_ReShade` `#MENU_GLOBAL` \
--field="     $GUI_ARCHALTEXE!$DESC_ARCHALTEXE ('ARCHALTEXE')":FL "${ARCHALTEXE/#-/ -}" `#CAT_Shader` `#SUB_ReShade` `#MENU_GAME` \
--field="     $GUI_ALTEXEPATH!$DESC_ALTEXEPATH ('ALTEXEPATH')":DIR "${ALTEXEPATH/#-/ -}" `#CAT_Shader` `#SUB_Directories` `#MENU_GAME` \
--field="     $GUI_RESHADESRCDIR!$DESC_RESHADESRCDIR ('RESHADESRCDIR')":DIR "${RESHADESRCDIR/#-/ -}" `#CAT_Shader` `#SUB_ReShade` `#SUB_Directories` `#MENU_GLOBAL` \
--field="     $GUI_RESHADE_DEPTH3D!$DESC_RESHADE_DEPTH3D ('RESHADE_DEPTH3D')":CHK "${RESHADE_DEPTH3D/#-/ -}" `#CAT_Shader` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_DLSHADER!$DESC_DLSHADER ('DLSHADER')":CHK "${DLSHADER/#-/ -}" `#CAT_Shader` `#SUB_Checkbox` `#MENU_GLOBAL`  \
--field="     $GUI_CHOOSESHADERS!$DESC_CHOOSESHADERS ('CHOOSESHADERS')":CHK "${CHOOSESHADERS/#-/ -}" `#CAT_Shader` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_ENABLE_VKBASALT!$DESC_ENABLE_VKBASALT ('ENABLE_VKBASALT')":CHK "${ENABLE_VKBASALT/#-/ -}" `#CAT_Shader` `#SUB_Checkbox` `#MENU_GAME` \
--field="$(spanFont "$PROGNAME $GUI_PATHS" "H")":LBL "SKIP" `#CAT_Paths` `#HEAD_Stl` `#MENU_GLOBAL`  \
--field="     $GUI_GLOBALCATEGORYDIR!$DESC_GLOBALCATEGORYDIR ('GLOBALCATEGORYDIR')":DIR "${GLOBALCATEGORYDIR/#-/ -}" `#CAT_Paths` `#SUB_Directories` `#MENU_GLOBAL` \
--field="     $GUI_GLOBALMISCDIR!$DESC_GLOBALMISCDIR ('GLOBALMISCDIR')":DIR "${GLOBALMISCDIR/#-/ -}" `#CAT_Paths` `#SUB_Directories` `#MENU_GLOBAL` \
--field="     $GUI_GLOBALSBSTWEAKS!$DESC_GLOBALSBSTWEAKS ('GLOBALSBSTWEAKS')":DIR "${GLOBALSBSTWEAKS/#-/ -}" `#CAT_Paths` `#SUB_Directories` `#MENU_GLOBAL` \
--field="     $GUI_GLOBALTWEAKS!$DESC_GLOBALTWEAKS ('GLOBALTWEAKS')":DIR "${GLOBALTWEAKS/#-/ -}" `#CAT_Paths` `#SUB_Directories` `#MENU_GLOBAL` \
--field="     $GUI_GLOBALSTLLANGDIR!$DESC_GLOBALSTLLANGDIR ('GLOBALSTLLANGDIR')":DIR "${GLOBALSTLLANGDIR/#-/ -}" `#CAT_Paths` `#SUB_Directories` `#MENU_GLOBAL` \
--field="     $GUI_GLOBALEVALDIR!$DESC_GLOBALEVALDIR ('GLOBALEVALDIR')":DIR "${GLOBALEVALDIR/#-/ -}" `#CAT_Paths` `#SUB_Directories` `#MENU_GLOBAL` \
--field="     $GUI_GLOBALSTLGUIDIR!$DESC_GLOBALSTLGUIDIR ('GLOBALSTLGUIDIR')":DIR "${GLOBALSTLGUIDIR/#-/ -}" `#CAT_Paths` `#SUB_Directories` `#MENU_GLOBAL` \
--field="     $PROGNAME $GUI_LOGDIR!$(strFix "$DESC_LOGDIR" "$PROGNAME") ('LOGDIR')":DIR "${LOGDIR/#-/ -}" `#CAT_Paths` `#SUB_Directories` `#MENU_GLOBAL` \
--field="$(spanFont "$GUI_OPTSTOOLS" "H")":LBL "SKIP" `#CAT_Tools` `#HEAD_Tools` `#MENU_GAME` `#MENU_GLOBAL`  \
--field="     $GUI_USEGAMEMODERUN!$DESC_USEGAMEMODERUN ('USEGAMEMODERUN')":CHK "${USEGAMEMODERUN/#-/ -}" `#CAT_Tools` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_MANGOHUD!$DESC_MANGOHUD ('MANGOHUD')":CHK "${MANGOHUD/#-/ -}" `#CAT_Tools` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_USEMANGOHUDSTLCFG!$DESC_USEMANGOHUDSTLCFG ('USEMANGOHUDSTLCFG')":CHK "${USEMANGOHUDSTLCFG/#-/ -}" `#CAT_Tools` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_USEGAMESCOPE!$DESC_USEGAMESCOPE ('USEGAMESCOPE')":CHK "${USEGAMESCOPE/#-/ -}" `#CAT_Tools` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_GAMESCOPE_ARGS!$DESC_GAMESCOPE_ARGS ('GAMESCOPE_ARGS')":CBE "${GAMESCOPE_ARGS/#-/ -}!--" `#CAT_Tools` `#MENU_GAME` \
--field="     $GUI_RUN_NYRNA!$DESC_RUN_NYRNA ('RUN_NYRNA')":CHK "${RUN_NYRNA/#-/ -}" `#CAT_Tools` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_RUN_REPLAY!$DESC_RUN_REPLAY ('RUN_REPLAY')":CHK "${RUN_REPLAY/#-/ -}" `#CAT_Tools` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_RUN_GAMCON!$DESC_RUN_GAMCON ('RUN_GAMCON')":CHK "${RUN_GAMCON/#-/ -}" `#CAT_Tools` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_RUN_CHEATENGINE!$DESC_RUN_CHEATENGINE ('RUN_CHEATENGINE')":CHK "${RUN_CHEATENGINE/#-/ -}" `#CAT_Tools` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_GAMCON!$DESC_GAMCON ('GAMCON')":FL "${GAMCON/#-/ -}" `#CAT_Tools` `#MENU_GLOBAL` \
--field="     $GUI_GAMCONWAITEXE!$DESC_GAMCONWAITEXE $GUI_ECHOPLAC ('GAMCONWAITEXE')":FL "${GAMCONWAITEXE/#-/ -}" `#CAT_Tools` `#MENU_GAME` \
--field="     $GUI_USEBOXTRON!$DESC_USEBOXTRON ('USEBOXTRON')":CHK "${USEBOXTRON/#-/ -}" `#CAT_Tools` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_BOXTRONCMD!$DESC_BOXTRONCMD ('BOXTRONCMD')":FL "${BOXTRONCMD/#-/ -}" `#CAT_Tools` `#MENU_GLOBAL` \
--field="     $GUI_BOXTRONARGS!$DESC_BOXTRONARGS ('BOXTRONARGS')" "${BOXTRONARGS/#-/ -}" `#CAT_Tools` `#MENU_GLOBAL` \
--field="     $GUI_USEROBERTA!$DESC_USEROBERTA ('USEROBERTA')":CHK "${USEROBERTA/#-/ -}" `#CAT_Tools` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_ROBERTACMD!$DESC_ROBERTACMD ('ROBERTACMD')":FL "${ROBERTACMD/#-/ -}" `#CAT_Tools` `#MENU_GLOBAL` \
--field="     $GUI_ROBERTAARGS!$DESC_ROBERTAARGS ('ROBERTAARGS')" "${ROBERTAARGS/#-/ -}" `#CAT_Tools` `#MENU_GLOBAL` \
--field="     $GUI_USELUXTORPEDA!$DESC_USELUXTORPEDA ('USELUXTORPEDA')":CHK "${USELUXTORPEDA/#-/ -}" `#CAT_Tools` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_LUXTORPEDACMD!$DESC_LUXTORPEDACMD ('LUXTORPEDACMD')":FL "${LUXTORPEDACMD/#-/ -}" `#CAT_Tools` `#MENU_GLOBAL` \
--field="     $GUI_LUXTORPEDAARGS!$DESC_LUXTORPEDAARGS ('LUXTORPEDAARGS')" "${LUXTORPEDAARGS/#-/ -}" `#CAT_Tools` `#MENU_GLOBAL` \
--field="     $GUI_STLEDITOR!$DESC_STLEDITOR ('STLEDITOR')":FL "${STLEDITOR/#-/ -}" `#CAT_Tools` `#MENU_GLOBAL` \
--field="     $GUI_BROWSER!$DESC_BROWSER ('BROWSER')":FL "${BROWSER/#-/ -}" `#CAT_Tools` `#MENU_GLOBAL` \
--field="     $GUI_NOTY!$DESC_NOTY ('NOTY')":FL "${NOTY/#-/ -}" `#CAT_Tools` `#MENU_GLOBAL` \
--field="     $GUI_NOTYARGS!$DESC_NOTYARGS ('NOTYARGS')" "${NOTYARGS/#-/ -}" `#CAT_Tools` `#MENU_GLOBAL` \
--field="     $GUI_USENETMON!$DESC_USENETMON ('USENETMON')":CHK "${USENETMON/#-/ -}" `#CAT_Tools` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_NETMON!$DESC_NETMON ('NETMON')":FL "${NETMON/#-/ -}" `#CAT_Tools` `#MENU_GLOBAL` \
--field="     $GUI_NETOPTS!$DESC_NETOPTS ('NETOPTS')" "${NETOPTS/#-/ -}" `#CAT_Tools` `#MENU_GLOBAL` \
--field="     $GUI_NETMONDIR!$DESC_NETMONDIR ('NETMONDIR')":DIR "${NETMONDIR/#-/ -}" `#CAT_Tools` `#SUB_Directories` `#MENU_GLOBAL` \
--field="     $GUI_BLOCKINTERNET!$DESC_BLOCKINTERNET ('BLOCKINTERNET')":CHK "${BLOCKINTERNET/#-/ -}" `#CAT_Tools` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_STRACERUN!$DESC_STRACERUN ('STRACERUN')":CHK "${STRACERUN/#-/ -}" `#CAT_Tools` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_STRACEDIR!$DESC_STRACEDIR ('STRACEDIR')":DIR "${STRACEDIR/#-/ -}" `#CAT_Tools` `#SUB_Directories` `#MENU_GLOBAL` \
--field="     $GUI_STRACEOPTS!$DESC_STRACEOPTS ('STRACEOPTS')" "${STRACEOPTS/#-/ -}" `#CAT_Tools` `#MENU_GAME` \
--field="     $GUI_CHEATENGINEVERSION!$DESC_CHEATENGINEVERSION ('CHEATENGINEVERSION')" "${CHEATENGINEVERSION/#-/ -}" `#CAT_Tools``#MENU_GLOBAL`  \
--field="     $GUI_CHEATENGINEMD5SUM!$DESC_CHEATENGINEMD5SUM ('CHEATENGINEMD5SUM')" "${CHEATENGINEMD5SUM/#-/ -}" `#CAT_Tools``#MENU_GLOBAL`  \
--field="     $GUI_AUTOCONTY!$DESC_AUTOCONTY ('AUTOCONTY')":CHK "${AUTOCONTY/#-/ -}" `#CAT_Tools` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_USECONTY!$DESC_USECONTY ('USECONTY')":CHK "${USECONTY/#-/ -}" `#CAT_Tools` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_CUSTCONTY!$DESC_CUSTCONTY ('CUSTCONTY')":FL "${CUSTCONTY/#-/ -}" `#CAT_Tools` `#MENU_GLOBAL` \
--field="     $GUI_UPDATECONTY!$DESC_UPDATECONTY ('UPDATECONTY')":CHK "${UPDATECONTY/#-/ -}" `#CAT_Tools` `#SUB_Checkbox` `#MENU_GLOBAL` \
--field="     $GUI_RUN_X64DBG!$DESC_RUN_X64DBG ('RUN_X64DBG')":CHK "${RUN_X64DBG/#-/ -}" `#CAT_Tools` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_RUN_GDB!$DESC_RUN_GDB ('RUN_GDB')":CHK "${RUN_GDB/#-/ -}" `#CAT_Tools` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_DPRSCOMPDATA!$DESC_DPRSCOMPDATA ('DPRSCOMPDATA')":DIR "${DPRSCOMPDATA/#-/ -}" `#CAT_Tools` `#SUB_Directories` `#MENU_GLOBAL` \
--field="     $GUI_USEDPRSPROTON!$DESC_USEDPRSPROTON ('USEDPRSPROTON')":CB "$(cleanDropDown "${USEDPRSPROTON/#-/ -}" "$PROTYADLIST")" `#CAT_Tools` `#MENU_GLOBAL` \
--field="     $GUI_DPRSUSEVDFSYMLINKS!$DESC_DPRSUSEVDFSYMLINKS ('DPRSUSEVDFSYMLINKS')":CHK "${DPRSUSEVDFSYMLINKS/#-/ -}" `#CAT_Tools` `#SUB_Checkbox` `#MENU_GLOBAL` \
--field="     $GUI_DPRSPAUTOUP!$DESC_DPRSPAUTOUP ('DPRSPAUTOUP')":CHK "${DPRSPAUTOUP/#-/ -}" `#CAT_Tools` `#SUB_Checkbox` `#MENU_GLOBAL` \
--field="     $GUI_RUN_DEPS!$DESC_RUN_DEPS ('RUN_DEPS')":CHK "${RUN_DEPS/#-/ -}" `#CAT_Tools` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_DEPSAUTOUP!$DESC_DEPSAUTOUP ('DEPSAUTOUP')":CHK "${DEPSAUTOUP/#-/ -}" `#CAT_Tools` `#SUB_Checkbox` `#MENU_GLOBAL` \
--field="     $(strFix "$GUI_USEPEV" "$PELDD")!$(strFix "$DESC_USEPEV" "$PELDD") ('USEPEV_PELDD')":CHK "${USEPEV_PELDD/#-/ -}" `#CAT_Tools` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $(strFix "$GUI_USEPEV" "$PEPACK")!$(strFix "$DESC_USEPEV" "$PEPACK") ('USEPEV_PEPACK')":CHK "${USEPEV_PEPACK/#-/ -}" `#CAT_Tools` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $(strFix "$GUI_USEPEV" "$PERES")!$(strFix "$DESC_USEPEV" "$PERES") ('USEPEV_PERES')":CHK "${USEPEV_PERES/#-/ -}" `#CAT_Tools` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $(strFix "$GUI_USEPEV" "$PESCAN")!$(strFix "$DESC_USEPEV" "$PESCAN") ('USEPEV_PESCAN')":CHK "${USEPEV_PESCAN/#-/ -}" `#CAT_Tools` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $(strFix "$GUI_USEPEV" "$PESEC")!$(strFix "$DESC_USEPEV" "$PESEC") ('USEPEV_PESEC')":CHK "${USEPEV_PESEC/#-/ -}" `#CAT_Tools` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $(strFix "$GUI_USEPEV" "$PESTR")!$(strFix "$DESC_USEPEV" "$PESTR") ('USEPEV_PESTR')":CHK "${USEPEV_PESTR/#-/ -}" `#CAT_Tools` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $(strFix "$GUI_USEPEV" "$READPE")!$(strFix "$DESC_USEPEV" "$READPE") ('USEPEV_READPE')":CHK "${USEPEV_READPE/#-/ -}" `#CAT_Tools` `#SUB_Checkbox` `#MENU_GAME` \
--field="$(spanFont "$GUI_OPTSURLS" "H")":LBL "SKIP" `#CAT_Urls` `#HEAD_Urls` `#MENU_URL` \
--field="     $GUI_PROJECTPAGE!$(strFix "$DESC_PROJECTPAGE" "$PROGNAME") ('PROJECTPAGE')" "${PROJECTPAGE/#-/ -}" `#CAT_Urls` `#MENU_URL` \
--field="     $GUI_CP_PROTONTKG!$DESC_CP_PROTONTKG ('CP_PROTONTKG')" "${CP_PROTONTKG/#-/ -}" `#CAT_Urls` `#MENU_URL` \
--field="     $GUI_CP_PROTONGE!$DESC_CP_PROTONGE ('CP_PROTONGE')" "${CP_PROTONGE/#-/ -}" `#CAT_Urls` `#MENU_URL` \
--field="     $GUI_CP_PROTONSTL!$DESC_CP_PROTONSTL ('CP_PROTONSTL')" "${CP_PROTONSTL/#-/ -}" `#CAT_Urls` `#MENU_URL` \
--field="     $GUI_CW_KRON4EK!$DESC_CW_KRON4EK ('CW_KRON4EK')" "${CW_KRON4EK/#-/ -}" `#CAT_Urls` `#MENU_URL` \
--field="     $GUI_DL_D3D47_64!$DESC_DL_D3D47_64 ('DL_D3D47_64')" "${DL_D3D47_64/#-/ -}" `#CAT_Urls` `#MENU_URL` \
--field="     $GUI_DL_D3D47_32!$DESC_DL_D3D47_32 ('DL_D3D47_32')" "${DL_D3D47_32/#-/ -}" `#CAT_Urls` `#MENU_URL` \
--field="     $GUI_RESHADEDLURL!$DESC_RESHADEDLURL ('RESHADEDLURL')" "${RESHADEDLURL/#-/ -}" `#CAT_Urls` `#MENU_URL` \
--field="     $GUI_VORTEXRELURL!$DESC_VORTEXRELURL ('VORTEXRELURL')" "${VORTEXRELURL/#-/ -}" `#CAT_Urls` `#MENU_URL` \
--field="     $GUI_DXVKURL!$DESC_DXVKURL ('DXVKURL')" "${DXVKURL/#-/ -}" `#CAT_Urls` `#MENU_URL` \
--field="     $GUI_XLIVEURL!$DESC_XLIVEURL ('XLIVEURL')" "${XLIVEURL/#-/ -}" `#CAT_Urls` `#MENU_URL` \
--field="     $GUI_STASSURL!$DESC_STASSURL ('STASSURL')" "${STASSURL/#-/ -}" `#CAT_Urls` `#MENU_URL` \
--field="     $GUI_WINETRICKSURL!$DESC_WINETRICKSURL ('WINETRICKSURL')" "${WINETRICKSURL/#-/ -}" `#CAT_Urls` `#MENU_URL` \
--field="     $GUI_CHEATENGINEURL!$DESC_CHEATENGINEURL ('CHEATENGINEURL')" "${CHEATENGINEURL/#-/ -}" `#CAT_Urls` `#MENU_URL` \
--field="     $GUI_X64DBGURL!$DESC_X64DBGURL ('X64DBGURL')" "${X64DBGURL/#-/ -}" `#CAT_Urls` `#MENU_URL` \
--field="     $GUI_STEAMGRIDDBAPI!$DESC_STEAMGRIDDBAPI ('STEAMGRIDDBAPI')" "${STEAMGRIDDBAPI/#-/ -}" `#CAT_Urls` `#MENU_URL` \
--field="     $GUI_CONTYRELURL!$DESC_CONTYRELURL ('CONTYRELURL')" "${CONTYRELURL/#-/ -}" `#CAT_Urls` `#MENU_URL` \
--field="     $GUI_MO2DLURL!$DESC_MO2DLURL ('MO2DLURL')" "${MO2DLURL/#-/ -}" `#CAT_Urls` `#MENU_URL` \
--field="     $GUI_DPRSRELURL!$DESC_DPRSRELURL ('DPRSRELURL')" "${DPRSRELURL/#-/ -}" `#CAT_Urls` `#MENU_URL` \
--field="     $GUI_DEPURL!$DESC_DEPURL ('DEPURL')" "${DEPURL/#-/ -}" `#CAT_Urls` `#MENU_URL` \
--field="$(spanFont "$GUI_OPTSVR" "H")":LBL "SKIP" `#CAT_VR` `#HEAD_VR` `#MENU_GAME` `#MENU_GLOBAL`  \
--field="     $GUI_SBSVRRS!$DESC_SBSVRRS ('SBSVRRS')":CHK "${SBSVRRS/#-/ -}" `#CAT_VR` `#SUB_Checkbox` `#SUB_ReShade` `#MENU_GAME` \
--field="     $GUI_RUNSBSVR!$DESC_RUNSBSVR ('RUNSBSVR')":CHK "${RUNSBSVR/#-/ -}" `#CAT_VR` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_SBSZOOM!$DESC_SBSZOOM ('SBSZOOM')" "${SBSZOOM/#-/ -}" `#CAT_VR` `#MENU_GAME` \
--field="     $GUI_MINVRWINH!$DESC_MINVRWINH ('MINVRWINH')":NUM "${MINVRWINH/#-/ -}" `#CAT_VR` `#MENU_GAME` \
--field="     $GUI_VRVIDEOPLAYER!$DESC_VRVIDEOPLAYER ('VRVIDEOPLAYER')":FL "${VRVIDEOPLAYER/#-/ -}" `#CAT_VR` `#MENU_GLOBAL` \
--field="     $GUI_VRVIDEOPLAYERARGS!$DESC_VRVIDEOPLAYERARGS ('VRVIDEOPLAYERARGS')" "${VRVIDEOPLAYERARGS/#-/ -}" `#CAT_VR` `#MENU_GAME` \
--field="     $GUI_WAITFORTHISPID!$DESC_WAITFORTHISPID ('WAITFORTHISPID')" "${WAITFORTHISPID/#-/ -}" `#CAT_VR` `#MENU_GAME` \
--field="     $GUI_UUUSEVR!$DESC_UUUSEVR ('UUUSEVR')":CHK "${UUUSEVR/#-/ -}" `#CAT_VR` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_USEOPENVRFSR!$DESC_USEOPENVRFSR ('USEOPENVRFSR')":CHK "${USEOPENVRFSR/#-/ -}" `#CAT_VR` `#SUB_Checkbox` `#MENU_GAME` \
--field="$(spanFont "$GUI_OPTSVORTEX" "H")":LBL "SKIP" `#CAT_Vortex` `#HEAD_Vortex` `#MENU_GAME` `#MENU_GLOBAL` \
--field="     $GUI_USEVORTEX!$DESC_USEVORTEX ('USEVORTEX')":CHK "${USEVORTEX/#-/ -}" `#CAT_Vortex` `#MENU_GAME` \
--field="     $GUI_WAITVORTEX!$DESC_WAITVORTEX ('WAITVORTEX')":NUM "${WAITVORTEX/#-/ -}" `#CAT_Vortex` `#MENU_GAME` \
--field="     $GUI_RUN_VORTEX_WINETRICKS!$DESC_RUN_VORTEX_WINETRICKS ('RUN_VORTEX_WINETRICKS')":CHK "${RUN_VORTEX_WINETRICKS/#-/ -}" `#CAT_Vortex` `#MENU_GAME` \
--field="     $GUI_RUN_VORTEX_WINECFG!$DESC_RUN_VORTEX_WINECFG ('RUN_VORTEX_WINECFG')":CHK "${RUN_VORTEX_WINECFG/#-/ -}" `#CAT_Vortex` `#MENU_GAME` \
--field="     $GUI_USEVORTEXPRERELEASE!$DESCUSEVORTEXPRERELEASE ('USEVORTEXPRERELEASE')":CHK "${USEVORTEXPRERELEASE/#-/ -}" `#CAT_Vortex` `#SUB_Checkbox` `#MENU_GLOBAL`  \
--field="     $GUI_VORTEXDOWNLOADPATH!$DESC_VORTEXDOWNLOADPATH ('VORTEXDOWNLOADPATH')":DIR "${VORTEXDOWNLOADPATH/#-/ -}" `#CAT_Vortex` `#SUB_Directories` `#MENU_GLOBAL` \
--field="     $GUI_VORTEXCOMPDATA!$DESC_VORTEXCOMPDATA ('VORTEXCOMPDATA')":DIR "${VORTEXCOMPDATA/#-/ -}" `#CAT_Vortex` `#SUB_Directories` `#MENU_GLOBAL` \
--field="     $GUI_USEVORTEXPROTON!$DESC_USEVORTEXPROTON ('USEVORTEXPROTON')":CB "$(cleanDropDown "${USEVORTEXPROTON/#-/ -}" "$PROTYADLIST")" `#CAT_Vortex` `#MENU_GLOBAL` \
--field="     $GUI_DISABLE_AUTOSTAGES!$(strFix "$DESC_DISABLE_AUTOSTAGES" "$PROGNAME") ('DISABLE_AUTOSTAGES')":CHK "${DISABLE_AUTOSTAGES/#-/ -}" `#CAT_Vortex` `#SUB_Checkbox` `#MENU_GLOBAL` \
--field="$(spanFont "$GUI_OPTSWINE" "H")":LBL "SKIP" `#CAT_Wine` `#HEAD_Wine` `#MENU_GAME` `#MENU_GLOBAL` \
--field="     $GUI_USEWINE!$DESC_USEWINE ('USEWINE')":CHK "${USEWINE/#-/ -}" `#CAT_Wine` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_WINEVERSION!$DESC_WINEVERSION ('WINEVERSION')":CBE "$(cleanDropDown "${WINEVERSION/#-/ -}" "$WINEYADLIST")" `#CAT_Wine` `#MENU_GAME` \
--field="     $GUI_WINEDEFAULT!$DESC_WINEDEFAULT ('WINEDEFAULT')":CBE "$(cleanDropDown "${WINEDEFAULT/#-/ -}" "$WINEYADLIST")" `#CAT_Wine` `#MENU_GAME` \
--field="     $GUI_RUN_WINETRICKS!$DESC_RUN_WINETRICKS ('RUN_WINETRICKS')":CHK "${RUN_WINETRICKS/#-/ -}" `#CAT_Wine` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_DLWINETRICKS!$DESC_DLWINETRICKS ('DLWINETRICKS')":CHK "${DLWINETRICKS/#-/ -}" `#CAT_Wine` `#SUB_Checkbox` `#MENU_GLOBAL` \
--field="     $GUI_WINETRICKSPAKS!$DESC_WINETRICKSPAKS ('WINETRICKSPAKS')":CBE "$(cleanDropDown "${WINETRICKSPAKS/#-/ -}" "$SOMEPOPULARWINEPAKS")" `#CAT_Wine` `#MENU_GAME` \
--field="     $GUI_RUN_WINECFG!$DESC_RUN_WINECFG ('RUN_WINECFG')":CHK "${RUN_WINECFG/#-/ -}" `#CAT_Wine` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_REGEDIT!$DESC_REGEDIT ('REGEDIT')":CHK "${REGEDIT/#-/ -}" `#CAT_Wine` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_VIRTUALDESKTOP!$DESC_VIRTUALDESKTOP ('VIRTUALDESKTOP')":CHK "${VIRTUALDESKTOP/#-/ -}" `#CAT_Wine` `#SUB_Checkbox` `#MENU_GAME`  \
--field="     $GUI_VDRES!$DESC_VDRES ('VDRES')":CBE "$(cleanDropDown "${VDRES/#-/ -}" "$(printf "%s\n" "$(listScreenRes | tr '\n' '!')")$NON")" `#CAT_Wine` `#MENU_GAME` \
--field="     $GUI_USEWICO!$DESC_USEWICO ('USEWICO')":CHK "${USEWICO/#-/ -}" `#CAT_Wine` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_STLWINEDEBUG!$DESC_STLWINEDEBUG ('STLWINEDEBUG')":CBE "$(cleanDropDown "${STLWINEDEBUG/#-/ -}" "$SOMEWINEDEBUGOPTIONS")" `#CAT_Wine` `#MENU_GAME` \
--field="     $GUI_STLWINEDLLOVERRIDES!$DESC_STLWINEDLLOVERRIDES ('STLWINEDLLOVERRIDES')":CBE "$(cleanDropDown "${STLWINEDLLOVERRIDES/#-/ -}" "$SOMEWINEDLLOVERRIDES")" `#CAT_Wine` `#MENU_GAME` \
--field="     $GUI_WINE_FULLSCREEN_INTEGER_SCALING!$DESC_WINE_FULLSCREEN_INTEGER_SCALING ('WINE_FULLSCREEN_INTEGER_SCALING')":CHK "${WINE_FULLSCREEN_INTEGER_SCALING/#-/ -}" `#CAT_Wine` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_WINE_FULLSCREEN_FSR!$DESC_WINE_FULLSCREEN_FSR ('WINE_FULLSCREEN_FSR')":CHK "${WINE_FULLSCREEN_FSR/#-/ -}" `#CAT_Wine` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_WINE_FULLSCREEN_FSR_STRENGTH!$DESC_WINE_FULLSCREEN_FSR_STRENGTH ('WINE_FULLSCREEN_FSR_STRENGTH')":NUM "${WINE_FULLSCREEN_FSR_STRENGTH/#-/ -}!0..5" `#CAT_Wine` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_WINEDLDIR!$DESC_WINEDLDIR ('WINEDLDIR')":DIR "${WINEDLDIR/#-/ -}" `#CAT_Wine` `#SUB_Directories` `#MENU_GLOBAL` \
--field="     $GUI_WINEEXTDIR!$DESC_WINEEXTDIR ('WINEEXTDIR')":DIR "${WINEEXTDIR/#-/ -}" `#CAT_Wine` `#SUB_Directories` `#MENU_GLOBAL` \
--field="     $GUI_WINE_LOG_DIR!$DESC_WINE_LOG_DIR ('WINE_LOG_DIR')":DIR "${WINE_LOG_DIR/#-/ -}" `#CAT_Wine` `#SUB_Directories` `#MENU_GAME` \
--field="     $GUI_ONLYWICO!$DESC_ONLYWICO ('ONLYWICO')":CHK "${ONLYWICO/#-/ -}" `#CAT_Wine` `#SUB_Checkbox` `#MENU_GAME` \
--field="$(spanFont "$GUI_OPTSMO2" "H")":LBL "SKIP" `#CAT_MO2` `#HEAD_Vortex` `#MENU_GAME` `#MENU_GLOBAL` \
--field="     $GUI_MO2COMPDATA!$DESC_MO2COMPDATA ('MO2COMPDATA')":DIR "${MO2COMPDATA/#-/ -}" `#CAT_MO2` `#SUB_Directories` `#MENU_GLOBAL` \
--field="     $GUI_USEMO2PROTON!$DESC_USEMO2PROTON ('USEMO2PROTON')":CB "$(cleanDropDown "${USEMO2PROTON/#-/ -}" "$PROTYADLIST")" `#CAT_MO2` `#MENU_GLOBAL` \
--field="     $GUI_MO2MODE!$DESC_MO2MODE ('MO2MODE')":CB "$(cleanDropDown "${MO2MODE/#-/ -}" "disabled!gui")" `#CAT_MO2` `#MENU_GAME` \
--field="     $GUI_WAITMO2!$DESC_WAITMO2 ('WAITMO2')":NUM "${WAITMO2/#-/ -}" `#CAT_MO2` `#MENU_GAME` \
#ENDSETENTRIES
}

function rmCfgTemp {
	if [ -n "$MKCFG" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Deleting and resetting MKCFG '$MKCFG' - triggered from '$1'"
		rm "$MKCFG" 2>/dev/null
		unset "MKCFG"
	fi
}

function mkCfgTemp {
	rmCfgTemp "${FUNCNAME[0]}"
	MKCFG="$(mktemp "$STLSHM/menu.XXXXXXXX")"
}

function prepareMenu {
	writelog "INFO" "${FUNCNAME[0]} - Opening Menu"
	GOBACK=1

	loadCfg "$STLDEFGLOBALCFG"
	loadCfg "$STLGAMECFG"
	loadCfg "$STLURLCFG"

	resetAID "$1"
	createGameCfg
	setGN "$1"

	if [ -z "$GN" ]; then
		writelog "ERROR" "${FUNCNAME[0]} - No game name found for '$AID' - this should not happen"
		exit
	fi
	createDropdownLists
	getAvailableCfgs	
}

function openGameMenu {
	prepareMenu "$@"
	if [ -z "$2" ]; then
		FUNC="$NON"
	else
		FUNC="$2"
	fi
	PARGUI="${FUNCNAME[0]}"
	openMenu "$AID" "$FUNC" "$STLGAMECFG" "0" "$GAMEMENU" "$LGAM" "$SHOWPIC" "EMPTY" "EMPTY" "$(strFix "$GUI_SETHEAD1" "$SGNAID")" "MENU_GAME"
}

function openGameDefaultMenu {
	prepareMenu "$@"
	if [ -z "$2" ]; then
		FUNC="$NON"
	else
		FUNC="$2"
	fi
	PARGUI="${FUNCNAME[0]}"
	openMenu "$AID" "$FUNC" "$STLDEFGAMECFG" "0" "$GAMETEMPMENU" "$LGATM" "$NOICON" "EMPTY" "EMPTY" "$GUI_SETHEAD2" "MENU_GAME"
}

function openGlobalMenu {
	prepareMenu "$@"
	if [ -z "$2" ]; then
		FUNC="$NON"
	else
		FUNC="$2"
	fi
	PARGUI="${FUNCNAME[0]}"
	openMenu "$AID" "$FUNC" "$STLDEFGLOBALCFG" "0" "$GLOBALMENU" "$LGLM" "$NOICON" "EMPTY" "EMPTY" "$GUI_SETHEAD3" "MENU_GLOBAL"
}

function startSteamGame {
	if [ "$ISGAME" -ge 1 ]; then
		writelog "INFO" "${FUNCNAME[0]} - Starting game"
	else
		if [ "$ISGAME" -ne 1 ] && [ "$AID" != "$PLACEHOLDERAID" ]; then
			STEAMARGS=(-applaunch "$AID")
			writelog "INFO" "${FUNCNAME[0]} - -------- starting game $AID in steam --------" "E"
			startGame "$STEAM" "${STEAMARGS[@]}" 2>/dev/null >/dev/null &
		fi
	fi	
}

function startWineGame {
	writelog "INFO" "${FUNCNAME[0]} - Starting game '$GN' ($AID)' using Wine"
	extWine64Run "$@" "$RUNWINE" "${FINGAMECMD[*]}" &> "$WINE_LOG_DIR/${AID}.log" 
	WINEPID="$!"
}

function openCustMenu {
	MYCAT="$3"
	MYMENU="$4"
	MYFUNC="$5"

	prepareMenu "$@"

	createGameCfg
	createDropdownLists

	TITLE="${PROGNAME}-${MYCAT}"
	pollWinRes "$TITLE" 1

	setShowPic
	cp "$SHOWPIC" "$FAVPIC"

	mkCfgTemp "${FUNCNAME[0]}"

	if [ "$2" == "$NON" ]; then
		BUT0="$BUT_EXIT"
		GOTO="Exit"
	else
		BUT0="$BUT_BACK"
		GOTO="$2"
	fi

	BUT2="$BUT_MAINMENU"
	BUT4="$BUT_RELOAD"
	BUT6="$BUT_SAVERELOAD"
	BUT8="$BUT_SAVEPLAY"
	BUT10="$BUT_PLAY"
	
	MYTMPL="${MYMENU}-${TMPL}"

	if [ "$MYCAT" == "Favorites" ]; then
		MYTEXT="$(strFix "$GUI_FAVORITESMENU" "$SGNAID")"
	else
		MYTEXT="$(strFix "$GUI_CATMENU" "$SGNAID" "$MYCAT")"
		if [ ! -f "$MYTMPL" ]; then
			grep "CAT_${MYCAT}" "$STLRAWENTRIES" > "$MYTMPL"
		fi
	fi

	# shellcheck disable=SC2028 # doesn't like the newline seperator, but it is valid
	{
		echo "function $MYFUNC {"
		echo "\"$YAD\" --columns=\"$COLCOUNT\" --f1-action=\"$F1ACTIONCG\" --text=\"$(spanFont "$MYTEXT" "H")\" \\"
		echo "--title=\"$TITLE\" --image \"$FAVPIC\" --image-on-top --window-icon=\"$STLICON\" --center $WINDECO --form --separator=\"\\n\" --quoted-output \\"
		echo "--button=\"$BUT0\":0 --button=\"$BUT2\":2 --button=\"$BUT4\":4 --button=\"$BUT6\":6 --button=\"$BUT8\":8 --button=\"$BUT10\":10 $GEOM \\"
		cat "$MYTMPL"
		echo "--scroll"
		echo "}"
	} >"$MYMENU"
	
	source "$MYMENU"
	"$MYFUNC" > "$MKCFG"
	case $? in
	0)  {
			clickInfo "${FUNCNAME[0]}" "$?" "$BUT0" "Category '$MYCAT' Menu" "$GOTO"
			if [ "$GOTO" == "Exit" ]; then
				GOBACK=0
				closeSTL " ######### STOP EARLY $PROGNAME $PROGVERS #########"
				exit
			else
				rmCfgTemp "${FUNCNAME[0]}"
			fi
		}
	;;
	2) 	{
			clickInfo "${FUNCNAME[0]}" "$?" "$BUT2" "Category '$MYCAT' Menu" "$SETMENU"
			MainMenu "$AID" "${FUNCNAME[0]}"
		}
	;;
	4) 	{
			clickInfo "${FUNCNAME[0]}" "$?" "$BUT4" "Category '$MYCAT' Menu" "restart Menu"
			GOBACK=0
			writelog "INFO" "${FUNCNAME[0]} - Reload Configs and restart Category '$MYCAT' Menu"
			if [ "$SAVESETSIZE" -eq 1 ] ; then	sleep 1;	fi
			"${FUNCNAME[0]}" "$@"
		}
	;;
	6) {
			clickInfo "${FUNCNAME[0]}" "$?" "$BUT6" "Category '$MYCAT' Menu" "restart Menu"
			GOBACK=0
			saveMenuEntries "$MYMENU"
			if [ "$SAVESETSIZE" -eq 1 ] ; then	sleep 1;	fi
			
			if [ "$MYCAT" == "$GCD" ];then
				setGameCfgDiffs
			fi
			"${FUNCNAME[0]}" "$@"
		}
	;;
	8) 	{
			clickInfo "${FUNCNAME[0]}" "$?" "$BUT8" "Category '$MYCAT' Menu" "Game Start"
			GOBACK=0
			saveMenuEntries "$MYMENU"
			startSteamGame
		}
	;;
	10)	{
			clickInfo "${FUNCNAME[0]}" "$?" "$BUT10" "Category '$MYCAT' Menu" "Game Start"
			GOBACK=0
			startSteamGame
		}
	;;
	esac

	rmCfgTemp "${FUNCNAME[0]}"
	goBackToPrevFunction "${FUNCNAME[0]}" "$2" "$GOBACK"

}

function setGuiSortOrder {
	if [ ! -f "$STLMENUSORTCFG" ]; then
		writelog "INFO" "${FUNCNAME[0]} - '$STLMENUSORTCFG' missing"
		getCatsFromCode > "$STLMENUSORTCFG" 2>/dev/null
	fi
	export CURWIKI="$PPW/Gui-Sort-Order"
	TITLE="${PROGNAME}-SortCategories"
	pollWinRes "$TITLE"

	NEWSORT="$("$YAD" --f1-action="$F1ACTION" --window-icon="$STLICON" --center --on-top "$WINDECO" \
		--list --editable --column "Category" --separator="" --print-all \
		--title="$TITLE" --text="$(spanFont "$GUI_SORTCAT" "H")" $GEOM < "$STLMENUSORTCFG")"
	case $? in
		0) 	{
				writelog "INFO" "${FUNCNAME[0]} - Clicked OK - Saving new sortorder into '$STLMENUSORTCFG'"
				echo "$NEWSORT" > "$STLMENUSORTCFG"
			}
		;;
		1)	{
				writelog "INFO" "${FUNCNAME[0]} - Clicked Cancel"
			}
		;;
	esac
}

function setGuiFavoritesSelection {
	export CURWIKI="$PPW/Favorites-Menu"
	TITLE="${PROGNAME}-FavoritesSelection"
	pollWinRes "$TITLE"

	setShowPic

	FAVENTRIES="$(favoritesMenuEntries | \
	"$YAD" --f1-action="$F1ACTION" --image "$SHOWPIC" --image-on-top --window-icon="$STLICON" --center $WINDECO --list --checklist \
	--column="$GUI_ADD" --column="$GUI_DESC" --column="$GUI_VAR" --column="LongDesc" --separator="\n" --print-column="3" --tooltip-column 4 --hide-column 4 \
	--text="$(spanFont "$GUI_FAVORITESSEL" "H")" --title="$TITLE" "$GEOM")"
	case $? in
		0)  {
				if [ -n "$FAVENTRIES" ]; then
					writelog "INFO" "${FUNCNAME[0]} - Updating '$STLFAVMENUCFG' with selected Favorites"
					echo "${FAVENTRIES[@]}" > "$STLFAVMENUCFG"
					sort -u "$STLFAVMENUCFG" -o "$STLFAVMENUCFG"
					rm "${FAVMENU}-${TMPL}" 2>/dev/null
				else
					writelog "INFO" "${FUNCNAME[0]} - Nothing selected"
				fi
			}
		;;
		1)  {
				writelog "INFO" "${FUNCNAME[0]} - Selected CANCEL - creating empty '$STLFAVMENUCFG' to skip asking again"
				touch "$STLFAVMENUCFG"
			}
		;;
	esac

	goBackToPrevFunction "${FUNCNAME[0]}" "$2"
}

function setGuiBlockSelection {
	export CURWIKI="$PPW/Gui-Hide-Categories"
	TITLE="${PROGNAME}-EntryBlockSelection"
	pollWinRes "$TITLE"

	BLENTRIES="$(createBlockYadList | \
	"$YAD" --f1-action="$F1ACTION" --window-icon="$STLICON" --center --list --checklist \
	--column="$GUI_HIDE" --column="$GUI_DESC" --separator=" " --print-column="2" \
	--text="$(spanFont "$GUI_BLOCKSEL" "H")" --title="$TITLE" "$GEOM")"
	case $? in
		0)  {
				writelog "INFO" "${FUNCNAME[0]} - Updating '$STLMENUBLOCKCFG' with selected blocks"
				while read -r blentry; do
					if grep -q "$blentry" <<< "$(printf '%s\n' "$BLENTRIES")"; then
						updateConfigEntry "$blentry" "TRUE" "$STLMENUBLOCKCFG"
					else
						updateConfigEntry "$blentry" "FALSE" "$STLMENUBLOCKCFG"
					fi
				done <<< "$(grep -v "^#" "$STLMENUBLOCKCFG" | cut -d '=' -f1)"

				checkEntryBlocklist
			}
		;;
		1)  writelog "INFO" "${FUNCNAME[0]} - Selected CANCEL"
		;;
	esac

	goBackToPrevFunction "${FUNCNAME[0]}" "$2"
}

function setGameCfgDiffs {
	writelog "INFO" "${FUNCNAME[0]} - Getting changes between game config and default"
	CHTEMP="$STLSHM/${AID}_cfgchanges.txt"
	comm -13 <(grep -v "^#" "$STLDEFGAMECFG" | grep "=" | sort -u) <(grep -v "^#" "$STLGAMECFG" | grep "=" | sort -u) > "$CHTEMP"
	rm "$MTEMP/$GCD" "$MTEMP/$GCD-${TMPL}" 2>/dev/null

	while read -r change; do
		GVAR="${change%=*}"
		TVAL="$(grep "^${GVAR}=" "$STLDEFGAMECFG" | cut -d '=' -f2)"
		TVALO="${TVAL//\"/}"
		if [ -n "$TVAL" ];then
			FRLI="$(sed -n "/^#STARTSETENTRIES/,/^#ENDSETENTRIES/p;/^#ENDSETENTRIES/q" "$0" | grep "'$GVAR'")"
			FRL1="${FRLI//\')/\') - $GUI_TEMPVAL $TVALO}"
			echo "$FRL1" >> "$MTEMP/$GCD-${TMPL}"
		fi
	done < "$CHTEMP"
	sed '/^$/d' -i "$MTEMP/$GCD-${TMPL}"
}

function setGuiCategoryMenuSel {
	export CURWIKI="$PPW/Category-Menus"
	TITLE="${PROGNAME}-CategorySelection"
	pollWinRes "$TITLE"

	setShowPic
	
	CATDD="$(cleanDropDown "${GCD}" "$(getCatsFromCode | tr '\n' '!' | sed "s:^!::" | sed "s:!$::")")"

	SELECTCAT="$("$YAD" --f1-action="$F1ACTION" --image "$SHOWPIC" --image-on-top --window-icon="$STLICON" --center $WINDECO --form --separator="\n" \
	--text="$(spanFont "$(strFix "$GUI_CATSEL" "$PROGNAME")" "H")" \
	--title="$TITLE" --field=" $GUI_CAT!$(strFix "$GUI_CATSEL" "$PROGNAME")":CB "$CATDD" "$GEOM")"
	case $? in
		0)  {
				if [ "$SELECTCAT" == "$GCD" ]; then
					setGameCfgDiffs
				fi

				writelog "INFO" "${FUNCNAME[0]} - Selected '$SELECTCAT' - Opening Category Menu"
				openCustMenu "$AID" "${FUNCNAME[0]}" "$SELECTCAT" "$MTEMP/$SELECTCAT" "$LCM"
			}
		;;
		1)  {
				writelog "INFO" "${FUNCNAME[0]} - Nothing selected - going to the $SETMENU"
				MainMenu "$AID" "${FUNCNAME[0]}"
			}
		;;
	esac
}

function clickInfo {
	writelog "INFO" "$1 - Clicked '$2' - '$3'"
	writelog "INFO" "$1 - exiting '$4' and opening '$5'"
}

function getLaPl {
	if [ -f "$PLAYTIMELOGDIR/$GN.log" ]; then
		echo "$GUI_LASTPLAYED $(tail -n1 "$PLAYTIMELOGDIR/${GN}.log")"
	fi	
}

function fixShowGnAid {
	if [ -n "$GN" ]; then
		SGNAID="$GN ($AID)"
		SGNAID="${SGNAID//&/+}"
	else
		SGNAID="$PLACEHOLDERGN ($PLACEHOLDERAID)"
	fi
}

function fixShow {
	echo "${1//&/+}"
}

function setShadDestDir {
	autoCategorySettings

	if [ "$USESPECIALK" -eq 1 ] && [ "$USERESHADE" -eq 1 ]; then
	writelog "INFO" "${FUNCNAME[0]} - Both '$SPEK' and '$RESH' are enabled." "E"
	writelog "INFO" "${FUNCNAME[0]} - Unfortunately the game currently crashes using Proton when both are enabled"
	writelog "INFO" "${FUNCNAME[0]} - therefore $RESH path redirect to the $SPEK directory is disabled" "E"

#		SPEKRESHDIR="My Mods/${SPEK}/Plugins/ThirdParty/${RESH}"
#		SHADDESTDIR="$GPFX/$DRCU/$STUS/$DOCS/$SPEKRESHDIR"
#	else
	fi
		setFullGameExePath "SHADDESTDIR"
#	fi
}

function refreshProtList {
	if [ -f "$PROTBUMPTEMP" ]; then
		rm "$PROTONCSV" 2>/dev/null
		unset ProtonCSV
		rm "$PROTBUMPTEMP" 2>/dev/null
		createProtonList X
	fi	
}

function MainMenu {
	prepareMenu "$@"

	setShowPic
	
	setHuyList
	setOPCustPath

	export CURWIKI="$PPW/Main-Menu"
	TITLE="${PROGNAME}-MainMenu"
	pollWinRes "$TITLE" 4
	fixShowGnAid

	LAPL="$(getLaPl)"
	SETHEAD="$(spanFont "${PROGNAME} (${PROGNAME,,}) - ${PROGVERS} \n \n$SGNAID" "H")\n<span font=\"italic\">$LAPL\n(${#CfgFiles[@]} $GUI_EDITABLECFGS)\n($GUI_EDITABLEGAMECFGS)\n</span>"

	TT_OPENURL="Help Url Gui"

	fixCustomMeta "$CUMETA/$AID.conf" # will be removed again later
	loadCfg "$CUMETA/$AID.conf" X
	loadCfg "$GEMETA/$AID.conf" X

	if [ -n "$DEVELOPER" ]; then
		SETHEAD="$SETHEAD \n ${GUI_DEV}: '$DEVELOPER'"
	fi

	if [ -n "$PUBLISHER" ]; then
		SETHEAD="$SETHEAD \n ${GUI_PUB}: '$PUBLISHER'"
	fi

	prepareProtonDBRating
	getGameFiles "$AID"
	setGameFilesArray
	TT_GAFI="$(for i in "${!GamFiles[@]}"; do printf "%s: %s\n" "${GamDesc[$i]}" "${GamFiles[$i]}"; done)"

	if [ -n "$METACRITIC_SCORE" ] && ! grep -q "^${GUI_MCS}" "$PDBRAINFO"; then
		echo "${GUI_MCS}: $METACRITIC_SCORE" >> "$PDBRAINFO"
	fi
	
	if [ -n "$OSLIST" ] && ! grep -q "^${GUI_OSL}" "$PDBRAINFO"; then
		echo "${GUI_OSL}: $OSLIST" >> "$PDBRAINFO"
	fi
	
	if [ -f "$PDBRAINFO" ] && grep -q "[0-9]" "$PDBRAINFO" ;then
		SETHEAD="$SETHEAD \n $(cat "$PDBRASINF")"
		TT_OPENURL="$(cat "$PDBRAINFO")"
	fi

	if [ -L "$GPFX/$DRCU/$STUS" ]; then
		SETHEAD="$SETHEAD \n ${GUI_SSU}: symlink to '$(readlink "$GPFX/$DRCU/$STUS")'"
	fi

	if [ -n "$GAMEWINDOW" ] && [ "$GAMEWINDOW" != "$NON" ]; then
		SETHEAD="$SETHEAD \n ${GUI_SGW}: '$(fixShow "$GAMEWINDOW")'"
	fi

	if [ -n "$GAMEEXE" ]; then
		SETHEAD="$SETHEAD \n ${GUI_SGE}: '$GAMEEXE'"
	fi

	if [ "${#ORGCMDARGS[@]}" -ge 1 ]; then
		SETHEAD="$SETHEAD \n ${GUI_SGA}: '${ORGCMDARGS[*]}'"
	fi
	
	# filter html incompatible chars here
	#SETHEAD="${SETHEAD//&/+}"
	
	createProtonList X

	"$YAD" --f1-action="$F1ACTION" --image "$SHOWPIC" --image-on-top --center --window-icon="$STLICON" --form --center "$WINDECO" --title="$TITLE" \
	--text="$SETHEAD" \
	--columns="$COLCOUNT" --f1-action="$F1ACTIONCG" --separator="" \
	--field="$FBUT_GUISET_DCP":FBTN "$PROGCMD dcp" \
	--field="$FBUT_GUISET_DW":FBTN "$PROGCMD dw" \
	--field="$FBUT_GUISET_RECREATEPFX":FBTN "$PROGCMD ccd \"$AID\" \"s\"" \
	--field="$FBUT_GUISET_WDC":FBTN "$PROGCMD wdc \"$AID\"" \
	--field="$FBUT_GUISET_WTSEL":FBTN "$PROGCMD wt \"$AID\"" \
	--field="$FBUT_GUISET_ADDNSGA":FBTN "$PROGCMD ansg" \
	--field="$FBUT_GUISET_CREATEEVALSC":FBTN "$PROGCMD cfi \"$AID\"" \
	--field="$FBUT_GUISET_OTR":FBTN "$PROGCMD otr \"$AID\"" \
	--field="$FBUT_GUISET_DXHSEL":FBTN "$PROGCMD dxh \"$AID\"" \
	--field="$FBUT_GUISET_SHADERREPOS":FBTN "$PROGCMD update shaders repos" \
	--field="$FBUT_GUISET_UPSHADER":FBTN "$PROGCMD update gameshaders \"$SHADDESTDIR\"" \
	--field="$FBUT_GUISET_FAVSEL":FBTN "$PROGCMD fav \"$AID\" set"\
	--field="$FBUT_GUISET_BLOCKCAT":FBTN "$PROGCMD block" \
	--field="$FBUT_GUISET_SORTCAT":FBTN "$PROGCMD sort" \
	--field="$FBUT_GUISET_OPURL!$TT_OPENURL":FBTN "$PROGCMD hu \"$AID\" X" \
	--field="$FBUT_GUISET_GASCO":FBTN "$PROGCMD gs \"$AID\" \"$GN\"" \
	--field="$FBUT_GUISET_VORTEX":FBTN "$PROGCMD vortex gui" \
	--field="$FBUT_GUISET_MO":FBTN "$PROGCMD mo2 start" \
	--field="$FBUT_GUISET_WIKI":FBTN "$PROGCMD wiki" \
	--field="$GUI_GAFI!$TT_GAFI":FBTN "$PROGCMD gf \"$AID\"" \
	--button="$BUT_EXIT":0 \
	--button="$BUT_GUISET_CATMENUSHORT":4 \
	--button="$BUT_GM":6 \
	--button="$BUT_DGM":8 \
	--button="$BUT_GLM":10 \
	--button="$BUT_FAV":12 \
	--button="$BUT_EDITORMENU":14 \
	--button="$BUT_PLAY":16 \
	"$GEOM"
	case $? in
	0)  {
			clickInfo "${FUNCNAME[0]}" "$?" "$BUT_EXIT" "$SETMENU" "Exit"
			GOBACK=0
			closeSTL " ######### STOP EARLY $PROGNAME $PROGVERS #########"
			exit
		}
	;;
	4) 	{
			clickInfo "${FUNCNAME[0]}" "$?" "$BUT_GUISET_CATMENUSHORT" "$SETMENU" "Category Menu Selection"
			refreshProtList
			setGuiCategoryMenuSel "$AID" "${FUNCNAME[0]}"
		}
	;;
	6) 	{
			clickInfo "${FUNCNAME[0]}" "$?" "$BUT_GM" "$SETMENU" "$GAMMENU"
			refreshProtList
			openGameMenu "$AID" "${FUNCNAME[0]}"
		}
	;;
	8) 	{
			clickInfo "${FUNCNAME[0]}" "$?" "$BUT_DGM" "$SETMENU" "Game Default Menu"
			refreshProtList
			openGameDefaultMenu "$AID" "${FUNCNAME[0]}"
		}
	;;
	10) 	{
			clickInfo "${FUNCNAME[0]}" "$?" "$BUT_GLM" "$SETMENU" "Global Menu"
			refreshProtList
			openGlobalMenu "$AID" "${FUNCNAME[0]}" "1"
		}
	;;
	12) 	{
			clickInfo "${FUNCNAME[0]}" "$?" "$BUT_FAV" "$SETMENU" "Favorites"
			refreshProtList
			favoritesMenu "$AID" "${FUNCNAME[0]}"
		}
	;;
	14) 	{
			clickInfo "${FUNCNAME[0]}" "$?" "$BUT_EDITORMENU" "$SETMENU" "EditorDialog"
			EditorDialog "$AID" "${FUNCNAME[0]}"
		}
	;;
	16) 	{
			clickInfo "${FUNCNAME[0]}" "$?" "$BUT_PLAY" "$SETMENU" "Game"
			GOBACK=0
			startSteamGame
		}
	;;
	esac 

	goBackToPrevFunction "${FUNCNAME[0]}" "$2" "$GOBACK"
}

function createBlockYadList {
	checkEntryBlocklist
	while read -r block; do
		BLCAT="${block%=*}"
		BLVALR="${block#*=}"
		BLVAL="${BLVALR//\"/}"
		if [ "$BLVAL" -eq 1 ] ; then
			echo TRUE
			echo "$BLCAT"
		else
			echo FALSE
			echo "$BLCAT"
		fi
	done <<< "$(grep -v "^#" "$STLMENUBLOCKCFG" | grep "=")"
}

function getCatsFromCode {
	sed "s:CAT_:\nCAT_:g" "$STLRAWENTRIES" | grep "^CAT_" | cut -d '`' -f1 | cut -d '_' -f2 | sort -u
}

function updateMenuSortFile {
	if [ -f "$STLMENUSORTCFG" ] && [ -s "$STLMENUSORTCFG" ]; then
		while read -r catent; do
			if ! grep -q "^$catent" "$STLMENUSORTCFG"; then
				writelog "INFO" "${FUNCNAME[0]} - Adding missing Category '$catent' to '$STLMENUSORTCFG'"
				echo "$catent" >> "$STLMENUSORTCFG"
			fi
		done <<< "$(getCatsFromCode)"
	fi
}

function checkEntryBlocklist {
	# create blocklist with disabled categories
	if [ ! -f "$STLMENUBLOCKCFG" ]; then
		echo "#All enabled categories will be hidden in the menus" >"$STLMENUBLOCKCFG"
		while read -r block; do
			echo "${block}=\"0\"" >> "$STLMENUBLOCKCFG"
		done <<< "$(getCatsFromCode)"
	fi

	if [ -f "$STLMENUBLOCKCFG" ]; then
		# autoadding new (commented out) categories
		while read -r block; do
			if ! grep -q "^${block}" "$STLMENUBLOCKCFG"; then
				echo "${block}=\"0\"" >> "$STLMENUBLOCKCFG"
			fi
		done <<< "$(getCatsFromCode)"
		
		# create validity check file
		if [ ! -f "$STLMENUVALBLOCKCFG" ]; then
			cp "$STLMENUBLOCKCFG" "$STLMENUVALBLOCKCFG"
		fi
		
		# if validity check file differs - remove temporary menu files
		if ! cmp -s "$STLMENUBLOCKCFG" "$STLMENUVALBLOCKCFG"; then
			writelog "INFO" "${FUNCNAME[0]} - Removing temp menufiles in '$STLSHM'"
			find "$MTEMP" -maxdepth 1 -type f -name "*menu*" -exec rm {} \;
			cp "$STLMENUBLOCKCFG" "$STLMENUVALBLOCKCFG"
		fi
	fi
}

function getFilteredEntries {
	if [ -z "$1" ]; then
		INLIST="$STLRAWENTRIES"
	else
		INLIST="$1"
	fi

	# first remove blocked entries
	if grep -q "=\"1\"" "$STLMENUBLOCKCFG"; then
		writelog "INFO" "${FUNCNAME[0]} - Excluding blocked elements from '$STLMENUBLOCKCFG'"
		unset BlockCats
		while read -r line; do
			mapfile -t -O "${#BlockCats[@]}" BlockCats <<< "CAT_${line}"
		done <<< "$(grep "=\"1\"" "$STLMENUBLOCKCFG" | cut -d '=' -f1)"

		while read -r outline; do
			INCAT="CAT_$(grep -oP '#CAT_\K[^`]+' <<< "${outline}")"
			if [[ ! "${BlockCats[*]}" =~ $INCAT ]]; then
				echo "$outline" >> "$STLNOBLOCKENTRIES"
			fi
		done < "$INLIST"
	else
		writelog "INFO" "${FUNCNAME[0]} - No blocked elements found in '$STLMENUBLOCKCFG' - working with '$INLIST'"
		cp "$INLIST" "$STLNOBLOCKENTRIES"
	fi

	# now the sort order
	if [ ! -f "$STLMENUSORTCFG" ]; then
		writelog "INFO" "${FUNCNAME[0]} - '$STLMENUSORTCFG' missing - creating a default one"
		getCatsFromCode > "$STLMENUSORTCFG" 2>/dev/null
	fi
	
	writelog "INFO" "${FUNCNAME[0]} - Sort config '$STLMENUSORTCFG' found - sorting"

	while read -r line; do
		if [ -n "$line" ]; then
			grep "\`#CAT_${line}\`" "$STLNOBLOCKENTRIES" >> "$STLCATSORTENTRIES"
		fi
	done < "$STLMENUSORTCFG"
	cat "$STLCATSORTENTRIES"
	rm "$STLNOBLOCKENTRIES" 2>/dev/null
	rm "$STLCATSORTENTRIES" 2>/dev/null
}

function splitMenu {
	ARGSPLIT="$1"
	MYTMPL="$2"
	if [ "$ARGSPLIT" -gt 0 ]; then
		FUCO="$(wc -l < "$MYTMPL")"
		CUTCO=$((FUCO / 2 ))
		RESTCO=$((FUCO - CUTCO))
		head -n "$CUTCO" "$MYTMPL" > "${MYTMPL}_${ARGSPLIT}"

		if [ "$ARGSPLIT" -eq 1 ]; then
			writelog "INFO" "${FUNCNAME[0]} - ARGSPLIT is set to '$ARGSPLIT' - so using first half of '$MYTMPL' for the menu"
			head -n "$CUTCO" "$MYTMPL" > "${MYTMPL}_${ARGSPLIT}"
			mv "${MYTMPL}_${ARGSPLIT}" "$MYTMPL"
		elif [ "$ARGSPLIT" -eq 2 ]; then
			writelog "INFO" "${FUNCNAME[0]} - ARGSPLIT is set to '$ARGSPLIT' - so using second half of '$MYTMPL' for the menu"
			head -n "$CUTCO" "$MYTMPL" | grep "#HEAD" | tail -n 1 > "${MYTMPL}_${ARGSPLIT}"
			tail -n "$RESTCO" "$MYTMPL" >> "${MYTMPL}_${ARGSPLIT}"
			mv "${MYTMPL}_${ARGSPLIT}" "$MYTMPL"
		else
			writelog "INFO" "${FUNCNAME[0]} - ARGSPLIT is set to '$ARGSPLIT' - so using the whole '$MYTMPL' for the menu"
		fi
	fi
}

function createMenu {
	ARGSPLIT="$1"
	ARGMENU="$2"
	ARGFUNC="$3"
	ARGPIC="$4"
	UNUSED="$5"
	ARGCOLS="$6"
	ARGTITLE="$7"
	ARGPCMD="$8"
	ARGSPAT="$9"

	NEEDARG="9"

	MYTMPL="${ARGMENU}-${TMPL}"

	if [ "$#" -ne "$NEEDARG" ]; then
		writelog "ERROR" "${FUNCNAME[0]} - Need $NEEDARG arguments and got '$#':"
		writelog "ERROR" "${FUNCNAME[0]} - '$*'"
	else
		writelog "INFO" "${FUNCNAME[0]} - got '$#' elements: '$*'"
	fi
	
	if [ ! -f "$MYTMPL" ] || [ ! -s "$MYTMPL" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Creating menu template '$MYTMPL'"
		getFilteredEntries "$STLRAWENTRIES" | grep "$ARGSPAT" > "$MYTMPL"
		rmDupLines "$MYTMPL"
		splitMenu "$ARGSPLIT" "$MYTMPL"
	fi

	if [ "$ARGPCMD" == "$NON" ]; then
		QBUT0="$BUT_EXIT"
	else
		QBUT0="$BUT_BACK"
	fi

	TITLE="${PROGNAME}-$ARGFUNC"

	echo "" >"$ARGMENU"
	# shellcheck disable=SC2028 # doesn't like the newline seperator, but it is valid
	{
		echo "function $ARGFUNC {"
		echo "\"$YAD\" --columns=\"$COLCOUNT\" --f1-action=\"$F1ACTIONCG\" --text=\"$(spanFont "$ARGTITLE" "H")\" \\"
		echo "--title=\"$TITLE\" --image \"$ARGPIC\" --image-on-top --window-icon=\"$STLICON\" --center \"$WINDECO\" --form --separator=\"\\n\" --quoted-output \\"
		echo "--button=\"$QBUT0\":0 --button=\"$BUT_MAINMENU\":2 --button=\"$BUT_RELOAD\":4 --button=\"$BUT_SAVERELOAD\":6 --button=\"$BUT_SAVEPLAY\":8 --button=\"$BUT_PLAY\":10 $GEOM \\"
		cat "$MYTMPL"
		echo "--scroll"
		echo "}"
	} >>"$ARGMENU"
}

function openMenu {
	ARGID="$1"
	ARGPCMD="$2"		# "$9"
	ARGLOADCFG="$3"
	# most args for createMenu:
	ARGSPLIT="$4"
	ARGMENU="$5"
	ARGFUNC="$6"
	ARGPIC="$7"
	UNUSED="$8"
	ARGCOLS="$9"
	ARGTITLE="${10}"
	ARGSPAT="${11}"
	 
	resetAID "$ARGID"
	createGameCfg
	setGN "$ARGID"
	createDropdownLists

	mkCfgTemp "${FUNCNAME[0]}"
	
	if [ "$LOADCFG" == "$STLGAMECFG" ] ; then
		setShowPic
	fi

	loadCfg "$ARGLOADCFG" X

	TITLE="${PROGNAME}-$ARGFUNC"
	pollWinRes "$TITLE"
	
	writelog "INFO" "${FUNCNAME[0]} - Starting createMenu \"$ARGMENU\" \"$ARGFUNC\" \"$ARGPIC\" \"$UNUSED\" \"$ARGCOLS\" \"$ARGTITLE\" \"$ARGPCMD\" \"$ARGSPAT\""
	createMenu "$ARGSPLIT" "$ARGMENU" "$ARGFUNC" "$ARGPIC" "$UNUSED" "$ARGCOLS" "$ARGTITLE" "$ARGPCMD" "$ARGSPAT"

	source "$ARGMENU"
	writelog "INFO" "${FUNCNAME[0]} - Currently used tempfile is '$MKCFG'"
	"$ARGFUNC" > "$MKCFG"
	
	case $? in
	0) 	{
			if [ "$ARGPCMD" == "$NON" ]; then
				clickInfo "${FUNCNAME[0]}" "$?" "$QBUT0" "$GAMMENU" "Exit"
				GOBACK=0
				closeSTL " ######### STOP EARLY $PROGNAME $PROGVERS #########"
				exit
			else
				clickInfo "${FUNCNAME[0]}" "$?" "$QBUT0" "$GAMMENU" "$ARGPCMD"
				"$ARGPCMD" "$AID" "${FUNCNAME[0]}"
			fi
		}
	;;
	2)  {
			clickInfo "${FUNCNAME[0]}" "$?" "$BUT_MAINMENU" "$FAVOMENU" "$SETMENU"
			MainMenu "$AID" "${FUNCNAME[0]}"
		}
	;;
	4) 	{
			GOBACK=0
			clickInfo "${FUNCNAME[0]}" "$?" "$BUT_RELOAD" "$FAVOMENU" "$PARGUI"
			if [ "$SAVESETSIZE" -eq 1 ] ; then	sleep 1;	fi
			"$PARGUI" "$AID" "$ARGPCMD" "$ARGSPLIT"
		}
	;;
	6) 	{
			clickInfo "${FUNCNAME[0]}" "$?" "$BUT_SAVERELOAD" "$FAVOMENU" "$PARGUI"
			GOBACK=0
			writelog "INFO" "${FUNCNAME[0]} - Saving config '$ARGLOADCFG' and restart '$PARGUI' GUI"
			saveMenuEntries "$ARGMENU"
			if [ "$SAVESETSIZE" -eq 1 ] ; then	sleep 1;	fi
			"$PARGUI" "$AID" "$ARGPCMD" "$ARGSPLIT"
		}
	;;
	8)  {
			clickInfo "${FUNCNAME[0]}" "$?" "$BUT_SAVEPLAY" "$FAVOMENU" "Game Start"
			GOBACK=0
			writelog "INFO" "${FUNCNAME[0]} - Saving config '$ARGLOADCFG' and starting the game"
			saveMenuEntries "$ARGMENU"
			startSteamGame
		}
	;;
	10)	{
			clickInfo "${FUNCNAME[0]}" "$?" "$BUT_PLAY" "$FAVOMENU" "Game Start"
			GOBACK=0
			startSteamGame
		}
	;;
	esac
}

function writelog {
#DBGMS "IN - $2"
# LOGLEVEL=0: disable log

# LOGLEVEL=1: log only:
LOGONE="404,ERROR,SKIP,WARN,CREATE"

# LOGLEVEL=2: log also - including:
#LOGTWO="HACK,INFO,NEW,UPDATE,WAIT"

	if [ -n "$4" ] && [ "$3" == "X" ] && grep -q ".log" <<< "$4"; then
		echo "$(date) $1 - $2" | tee -a "$4" >/dev/null
	else
		if [ -z "$LOGLEVEL" ]; then
			LOGLEVEL=2
		fi

		if [ "$LOGLEVEL" -eq 1 ]; then
			if grep -q "$1" <<< "$LOGONE"; then
				if [ -z "$LOGFILE" ]; then
					echo "$(date) $1 - $2" | tee -a "$TEMPLOG" >/dev/null
				else
					echo "$(date) $1 - $2" | tee -a "$TEMPLOG" "$LOGFILE" >/dev/null
				fi
			fi
		fi

		if [ "$LOGLEVEL" -eq 2 ]; then
			if [ -z "$LOGFILE" ]; then
				echo "$(date) $1 - $2" | tee -a "$TEMPLOG" >/dev/null
			else
				echo "$(date) $1 - $2" | tee -a "$TEMPLOG" "$LOGFILE" >/dev/null
			fi
		fi

		if [ -n "$3" ]; then
			if [ "$3" == "E" ]; then
				echo "$(date) $1 - $2"
			elif [ "$3" == "P" ] && [ -f "$PRELOG" ]; then
				echo "$(date) $1 - $2" | tee -a "$PRELOG" >/dev/null
			elif grep -q ".log" <<< "$3"; then
				echo "$(date) $1 - $2" | tee -a "$3" >/dev/null
			fi
		fi
	fi
#DBGMS "OUT - $2"
}

# generic git clone/pull function
function gitUpdate {
	GITDIR="$1"
	GITURL="$2"
	if [ -d "$GITDIR/.git" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Pulling '$GITURL' update in '$GITDIR'"
		"$GIT" --work-tree="$GITDIR" --git-dir="$GITDIR/.git" pull --rebase=false
	else
		mkProjDir "$GITDIR"
		writelog "INFO" "${FUNCNAME[0]} - Cloning '$GITURL' in '$GITDIR'"
		"$GIT" clone "$GITURL" "$GITDIR"
	fi
}

function loadCfg {
	CFGFILE="$1"

	if [ -f "$CFGFILE" ]; then

		# disable logging here when the program just started (cosmetics)
		if [ -z "$2" ]; then
			writelog "INFO" "${FUNCNAME[0]} - '$CFGFILE' START"
		fi

		if [ "$CFGFILE" == "$STLGAMECFG" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Loading game config '$CFGFILE'"
		fi

		while read -r line; do
			if [ -n "$line" ]; then
				EXPORTLINE="${line//\"/}"
				EXPORTLINE="${EXPORTLINE//STLCFGDIR/$STLCFGDIR}"
				export "${EXPORTLINE?}"
			fi
		done <<< "$(grep -v "^#\|^$" "$CFGFILE")"

		# disable logging here when the program just started (cosmetics)
		if [ -z "$2" ]; then
			writelog "INFO" "${FUNCNAME[0]} - '$CFGFILE' STOP"
		fi
	fi
}

function extWine64Run {
	if [ "$USEWINE" -eq 0 ]; then
		writelog "INFO" "${FUNCNAME[0]} - Command in Proton WINEPREFIX is: WINE=\"$RUNWINE\" WINEARCH=win64 WINEDEBUG=\"$STLWINEDEBUG\" WINEPREFIX=\"$GPFX\" $*"
		WINE="$RUNWINE" WINEARCH=win64 WINEDEBUG="$STLWINEDEBUG" WINEPREFIX="$GPFX" "$@"
	else
		writelog "INFO" "${FUNCNAME[0]} - Command in Wine WINEPREFIX is: WINE=\"$RUNWINE\" WINEARCH=\"$RUNWINEARCH\" WINEDEBUG=\"$STLWINEDEBUG\" WINEPREFIX=\"$GWFX\" $*"
		WINE="$RUNWINE" WINEARCH="$RUNWINEARCH" WINEDEBUG="$STLWINEDEBUG" WINEPREFIX="$GWFX" "$@"
	fi
}

function extProtonRun {
	MODE="$1"
	PROGRAM="$2"
	PROGARGS="$3"
	EXTWINERUN=0

	if [ "$USEWINE" -eq 1 ] && [[ ! "$WINEVERSION" =~ ${DUMMYBIN}$ ]] && [ "$WINEVERSION" != "$NON" ]; then
		EXTWINERUN=1
	fi

	setRunProtonFromUseProton

	# could help here:
	if [ ! -f "${RUNPROTON//\"/}" ]; then
		writelog "WARN" "${FUNCNAME[0]} - '$USEPROTON' seems outdated as the executable ${RUNPROTON//\"/} wasn't found"
		fixProtonVersionMismatch "USEPROTON" "$STLGAMECFG"
	fi

	writelog "INFO" "${FUNCNAME[0]} - Continuing with RUNPROTON='$RUNPROTON'"

	if [ ! -f "$RUNPROTON" ]; then
		writelog "ERROR" "${FUNCNAME[0]} - When this error occurs, probably the configured Proton (or a similar) version is no longer available."
		writelog "ERROR" "${FUNCNAME[0]} - Because the RUNPROTON '$RUNPROTON' isn't ready here yet - please open an issue when you made sure it is set to an existing one and the error persists"
	else
		if [ -z "$PROGARGS" ] || [ "$PROGARGS" == "$NON" ]; then
			RUNPROGARGS=""
		else
			mapfile -d " " -t -O "${#RUNPROGARGS[@]}" RUNPROGARGS < <(printf '%s' "$PROGARGS")
		fi

		if [ "$MODE" == "F" ]; then
			if [ -n "${RUNPROGARGS[0]}" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Starting '$PROGRAM' with arguments '${RUNPROGARGS[*]}' forked into the background"
				restoreOrgVars
				if [ "$EXTWINERUN" -eq 1 ]; then
					(extWine64Run "$PROGRAM" "${RUNPROGARGS[@]}") &
				else
					("$RUNPROTON" run "$PROGRAM" "${RUNPROGARGS[@]}") &
				fi
				emptyVars "O" "X"
			else
				writelog "INFO" "${FUNCNAME[0]} - Starting '$PROGRAM' forked into the background"
				restoreOrgVars
				if [ "$EXTWINERUN" -eq 1 ]; then
					(sleep 2; extWine64Run "$PROGRAM") &
				else
					(sleep 2; "$RUNPROTON" run "$PROGRAM") &
				fi
				emptyVars "O" "X"
			fi
		elif [ "$MODE" == "FC" ]; then
			if [ -n "${RUNPROGARGS[0]}" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Starting '$WICO $PROGRAM' with arguments '${RUNPROGARGS[*]}' forked into the background"
				restoreOrgVars
				if [ "$EXTWINERUN" -eq 1 ]; then
					(extWine64Run "$RUNWICO" "$PROGRAM" "${RUNPROGARGS[@]}") &
				else
					("$RUNPROTON" run "$WICO" "$PROGRAM" "${RUNPROGARGS[@]}") &
				fi
				emptyVars "O" "X"
			else
				writelog "INFO" "${FUNCNAME[0]} - Starting '$WICO $PROGRAM' forked into the background"
				restoreOrgVars
				if [ "$EXTWINERUN" -eq 1 ]; then
					(extWine64Run "$RUNWICO" "$PROGRAM") &
				else
					(sleep 2; "$RUNPROTON" run "$WICO" "$PROGRAM") &
				fi
				emptyVars "O" "X"
			fi
		elif [ "$MODE" == "R" ]; then
			if [ -n "${RUNPROGARGS[0]}" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Starting '$PROGRAM' with arguments '${RUNPROGARGS[*]}' regularly"
				restoreOrgVars
				if [ "$EXTWINERUN" -eq 1 ]; then
					extWine64Run "$PROGRAM" "${RUNPROGARGS[@]}"
				else
					"$RUNPROTON" run "$PROGRAM" "${RUNPROGARGS[@]}"
				fi
				emptyVars "O" "X"
			else
				writelog "INFO" "${FUNCNAME[0]} - Starting '$PROGRAM' regularly"
				restoreOrgVars
				if [ "$EXTWINERUN" -eq 1 ]; then
					extWine64Run "$PROGRAM"
				else
					writelog "INFO" "${FUNCNAME[0]} - Starting with launch command '$RUNPROTON run $PROGRAM'"
					"$RUNPROTON" run "$PROGRAM"
				fi
				emptyVars "O" "X"
			fi
		elif [ "$MODE" == "RC" ]; then
			if [ -n "${RUNPROGARGS[0]}" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Starting '$WICO $PROGRAM' with arguments '${RUNPROGARGS[*]}' regularly"
				restoreOrgVars
				if [ "$EXTWINERUN" -eq 1 ]; then
					extWine64Run "$RUNWICO" "$PROGRAM" "${RUNPROGARGS[@]}"
				else
					"$RUNPROTON" run "$WICO" "$PROGRAM" "${RUNPROGARGS[@]}"
				fi
				emptyVars "O" "X"
			else
				writelog "INFO" "${FUNCNAME[0]} - Starting '$WICO $PROGRAM' regularly"
				restoreOrgVars
				if [ "$EXTWINERUN" -eq 1 ]; then
					extWine64Run "$RUNWICO" "$PROGRAM"
				else
					"$RUNPROTON" run "$WICO" "$PROGRAM"
				fi
				emptyVars "O" "X"
			fi
		fi
	fi
}

function getWindowHeight {
	WINID="$1"
	"$XWININFO" -id "$WINID" -stats | awk '$1=="-geometry" {print $2}' | cut -d '+' -f1 | cut -d 'x' -f2
}

function initSteamVR {
	if [ "$RUNSBSVR" -eq 1 ]; then
		SVRJUSTSTARTED=0
		STEAMVRARGS=(-applaunch 250820)

		if "$PGREP" -a "vrcompositor" >/dev/null ; then
			writelog "INFO" "${FUNCNAME[0]} - Looks like SteamVR is already running - skipping this function"
		else
			writelog "WARN" "${FUNCNAME[0]} - This function might be removed as it blocks exiting the launched game"

			if ! "$PGREP" -a "vrcompositor" >/dev/null ; then
				writelog "INFO" "${FUNCNAME[0]} - Vrcompositor not running, so starting SteamVR now:"
				if ! "$STEAM" "${STEAMVRARGS[@]}" 2>/dev/null >/dev/null ; then
					writelog "SKIP" "${FUNCNAME[0]} - Starting SteamVR FAILED - skipping SBS-VR"
					echo "RUNSBSVR=\"0\"" > "$VRINITLOCK"
				else
					writelog "INFO" "${FUNCNAME[0]} - Started SteamVR"
					SVRJUSTSTARTED=1
				fi
			fi

			if ! "$PGREP" -a "vrstartup" >/dev/null ; then
				writelog "INFO" "${FUNCNAME[0]} - No vrstartup process running"
			else
				if [ "$SVRJUSTSTARTED" -eq 1 ]; then
					writelog "INFO" "${FUNCNAME[0]} - SteamVR initializing"
					while true; do
						writelog "INFO" "${FUNCNAME[0]} - Waiting for end of vrstartup"
						if ! "$PGREP" -a "vrstartup" >/dev/null ; then
							break
						fi
						if [ -f "$CLOSETMP" ]; then
							writelog "WAIT" "${FUNCNAME[0]} - ${PROGNAME,,} is just closing - leaving loop"
							break
						fi
					done
				else
					writelog "SKIP" "${FUNCNAME[0]} - Vrstartup found, but we didn't start SteamVR before! - skipping SBS-VR - just in case"
					echo "RUNSBSVR=\"0\"" > "$VRINITLOCK"
				fi
			fi

			if [ "$SVRJUSTSTARTED" -eq 1 ]; then
				while true; do
					if ! "$PGREP" -a "vrstartup" >/dev/null ; then
						writelog "WAIT" "${FUNCNAME[0]} - No vrstartup instance running"
						break
					fi
					if [ -f "$CLOSETMP" ]; then
						writelog "WAIT" "${FUNCNAME[0]} - ${PROGNAME,,} is just closing - leaving loop"
						break
					fi
					writelog "WAIT" "${FUNCNAME[0]} - Waiting for end of vrstartup"
				done
			fi

			if [ "$SVRJUSTSTARTED" -eq 1 ]; then
			MAXWAIT=10
			COUNTER=0
				while ! "$PGREP" -a "vrcompositor" >/dev/null; do
					if [ -f "$CLOSETMP" ]; then
						writelog "WAIT" "${FUNCNAME[0]} - ${PROGNAME,,} is just closing - leaving loop"
						break
					fi
					if [[ "$COUNTER" -ge "$MAXWAIT" ]]; then
						writelog "SKIP" "${FUNCNAME[0]} - ERROR - timeout waiting for SteamVR - exit"
						"$PKILL" -f "$VRVIDEOPLAYER"
						echo "RUNSBSVR=\"0\"" > "$VRINITLOCK"
						exit 1
					fi
					writelog "WAIT" "${FUNCNAME[0]} - Sec $COUNTER/$MAXWAIT waiting for vrcompositor"
					COUNTER=$((COUNTER+1))
					sleep 1
				done
			else
				writelog "INFO" "${FUNCNAME[0]} - we didn't start SteamVR before so no need to wait for vrcompositor"
			fi

			if "$PGREP" -a "vrcompositor" >/dev/null ; then
				while true; do
					if ! "$PGREP" -a "vrstartup" >/dev/null ; then
						writelog "WAIT" "${FUNCNAME[0]} - No vrstartup instance running - looks good"
						break
					fi
					sleep 1
					writelog "WAIT" "${FUNCNAME[0]} - Waiting for end of vrstartup"
				done

				writelog "INFO" "${FUNCNAME[0]} - Success - SteamVR running"
				sleep 1 # better safe than sorry
				
			else
				writelog "SKIP" "${FUNCNAME[0]} - SteamVR start failed - vrcompositor still not running - skipping SBS-VR!"
				echo "RUNSBSVR=\"0\"" > "$VRINITLOCK"
			fi
		fi
	fi
}

function dlOvrFSR {
	function getLatestOVRFSR {
		basename "$("$WGET" -q "$OVRFSRURL" -O - 2> >(grep -v "SSL_INIT") | grep -E 'releases.*download.*zip' | cut -d '"' -f2 | head -n1)"
	}

	DLDST="$STLDLDIR/$OVFS"
	mkProjDir "$DLDST"
	OVRFSRZIP="$(getLatestOVRFSR)"
	FSR1="${OVRFSRZIP//openvr_}"
	FSRV="${FSR1%.*}"

	if [ ! -f "$DLDST/$OVRFSRZIP" ]; then
		notiShow "$(strFix "$NOTY_DLCUSTOMPROTON" "$OVRFSRZIP")" "S"
		dlCheck "${OVRFSRURL}/download/$FSRV/$OVRFSRZIP" "$DLDST/$OVRFSRZIP" "X" "Downloading '$OVRFSRZIP'"
		notiShow "$(strFix "$NOTY_DLCUSTOMPROTON2" "$OVRFSRZIP")" "S"
	fi

	if [ ! -s "$DLDST/$OVRFSRZIP" ]; then
		writelog "SKIP" "${FUNCNAME[0]} - Downloaded file '$DLDST/$OVRFSRZIP' is empty - removing"
		rm "$DLDST/$OVRFSRZIP" 2>/dev/null
	else
		notiShow "$(strFix "$NOTY_DLCUSTOMPROTON3" "$OVRFSRZIP")" "S"
		writelog "INFO" "${FUNCNAME[0]} - Download of '$OVRFSRZIP' to '$DLDST' was successful"
	 	OMSRC="$DLDST/$OVRMOD"
	 	if [ -f "$OMSRC" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Removing old '$OMSRC'"
			rm "$OMSRC" 2>/dev/null
	 	fi
	 	OASRC="$DLDST/$OVRA"
	 	if [ -f "$OASRC" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Removing old '$OASRC'"
			rm "$OASRC" 2>/dev/null
	 	fi
	 	
	 	"$UNZIP" -q "$DLDST/$OVRFSRZIP" -d "$DLDST" 2>/dev/null
		writelog "INFO" "${FUNCNAME[0]} - Extracted '$OVRFSRZIP' to '$DLDST'"
	fi
}

function checkOpenVRFSR {
	OVRFSENA="${OVFS}-${PROGNAME,,}-enabled.txt"
	OVRFP="$EFD/$OVRFSENA"
	OVRAO="openvr_api.orig.dll"

	if [ "$USEOPENVRFSR" -eq 1 ]; then
		OVRPATH="$(find "$EFD" -name "*$OVRA" | head -n1)"
		if [ -f "$OVRPATH" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Found '$OVRA' under '$OVRPATH'"
			OVRASRC="$STLDLDIR/$OVFS/$OVRA"
			if [ ! -f "$OVRASRC" ]; then
				writelog "INFO" "${FUNCNAME[0]} - No $OVFS source dll found under '$OVRASRC' - Trying automatic download"
				StatusWindow "$(strFix "$NOTY_DLCUSTOMPROTON" "$OVRFSRZIP")" "dlOvrFSR" "DownloadOvrFSRStatus"
			fi

			if [ ! -f "$OVRASRC" ]; then
				writelog "SKIP" "${FUNCNAME[0]} - Still no $OVFS source dll found under '$OVRASRC' - automatic download failed!"
			else	
				OVRDIR="${OVRPATH%/*}"
				writelog "INFO" "${FUNCNAME[0]} - Moving original '$OVRPATH' to $OVRDIR/$OVRAO"
				mv "$OVRPATH" "$OVRDIR/$OVRAO"
				writelog "INFO" "${FUNCNAME[0]} - Copying '$OVRASRC' to '$OVRPATH'"
				cp "$OVRASRC" "$OVRPATH"
				echo "${OVRPATH//$EFD/}" > "$OVRFP"
				
				OVRMODSRC="$STLDLDIR/$OVFS/$OVRMOD"
				if [ -f "$OVRMODSRC" ]; then
					if [ ! -f "$OVRFP" ]; then
						writelog "WARN" "${FUNCNAME[0]} - No install 'log' found - should not happen here!"
					else
						OVRMODDST="${OVRPATH%/*}/$OVRMOD"
						if [ -f "$OVRMODDST" ]; then
							writelog "INFO" "${FUNCNAME[0]} - Moving '$OVRMODDST' to '${OVRMODDST}_old'"
							mv "$OVRMODDST" "${OVRMODDST}_old"
						fi
						writelog "INFO" "${FUNCNAME[0]} - Copying '$OVRMODSRC' to '$OVRMODDST'"
						cp "$OVRMODSRC" "$OVRMODDST"
						echo "${OVRMODDST//$EFD/}" >> "$OVRFP"
					fi
				fi
				
				if [ -f "$OVRFP" ]; then
					writelog "INFO" "${FUNCNAME[0]} - '$OVFS' installation (hopefully) succeeded!"
				fi
			fi
		else
			writelog "SKIP" "${FUNCNAME[0]} - USEOPENVRFSR is enabled, but no OVRA found in '$EFD'"
		fi
	else
		if [ -f "$OVRFP" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Found old '$OVFS' installation in '$EFD' - Removing"
			while read -r line; do
				if grep -q "$OVRA" <<< "$line"; then
					OVRAOP="$EFD/${line//$OVRA/$OVRAO}"
				if [ -f "$OVRAOP" ]; then
						writelog "INFO" "${FUNCNAME[0]} - Restoring original $OVRA from '$OVRAOP'"
						mv "$OVRAOP" "$EFD/$line" 2>/dev/null
					else
						writelog "SKIP" "${FUNCNAME[0]} - No '$OVRAOP' found to restore"
					fi
				else
					writelog "INFO" "${FUNCNAME[0]} - Removing '$EFD/$line'"
					rm "$EDF/$line" 2>/dev/null
				fi
			done < "$OVRFP"
			rm "$OVRFP" 2>/dev/null
		fi
	fi
}

function getGamePidFromFile {
	if [ -z "$GAMEWINPID" ] && [ -f "$TEMPGPIDFILE" ]; then
		loadCfg "$TEMPGPIDFILE"
		rm "$TEMPGPIDFILE"
		writelog "INFO" "${FUNCNAME[0]} - Got GAMEWINPID '$GAMEWINPID' from temp file"
	fi
}

function getGamePidFromWindowName {
	if [ -n "$GAMEWINDOW" ] && [ "$GAMEWINDOW" != "$NON" ]; then
		# xdotool at least doesn't like '(' and ')', so cutting them out as a partial match should be enough
		#CHECKWINDOWNAME="${GAMEWINDOW//(*}"
		writelog "INFO" "${FUNCNAME[0]} - Trying to get the PID of the window '$GAMEWINDOW'"
		# TESTPID="$("$XDO" getwindowpid "$("$XDO" search --name "$CHECKWINDOWNAME")" 2>/dev/null)"
		TESTPID="$("$XWININFO" -name "${GAMEWINDOW//\"/}" -wm | grep "Process id:" | awk -F 'Process id: ' '{print $2}' | cut -d ' ' -f1)"
		if [ -n "$TESTPID" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Found the PID '$TESTPID' for the window '$GAMEWINDOW'"
			echo "$TESTPID"
		fi
	fi
}

function GAMEPID {
	if	[ "$USECUSTOMCMD" -eq 1 ] && [ "$ONLY_CUSTOMCMD" -eq 1 ]; then
#		"$PGREP" -a "$CUSTOMCMD" | cut -d ' ' -f1 | tail -n1
		"$PGREP" -a "" | grep "${CUSTOMCMD##*/}" | grep "Z:" | grep "\.exe" | grep -v "CrashHandler" | cut -d ' ' -f1 | tail -n1
	else
		if [ -n "$WAITFORTHISPID" ] && [ "$WAITFORTHISPID" != "$NON" ]; then
			GAMPI="$("$PIDOF" "$WAITFORTHISPID" | cut -d ' ' -f1)"
		else
			if [ -n "$GAMEWINDOW" ] && [ "$GAMEWINDOW" != "$NON" ]; then
				GAMPI="$("$XWININFO" -name "${GAMEWINDOW//\"/}" -wm | grep "Process id:" | awk -F 'Process id: ' '{print $2}' | cut -d ' ' -f1)"
				writelog "INFO" "${FUNCNAME[0]} - Found gamewindow '$GAMEWINDOW' PID $GAMPI"
			else
				# very likely this needs to be improved/changed
				GAMPI="$("$PGREP" -a "" | grep "$GE" | grep "Z:" | grep "\.exe" | grep -v "CrashHandler" | cut -d ' ' -f1 | tail -n1)"
			fi
		fi
		echo "$GAMPI"
	fi
}

function waitForGamePid {
	if [ -n "$WAITFORTHISPID" ] && [ "$WAITFORTHISPID" != "$NON" ]; then
		writelog "WAIT" "${FUNCNAME[0]} - Waiting for alternative process WAITFORTHISPID '$WAITFORTHISPID'"
	elif [ "$USECUSTOMCMD" -eq 1 ] && [ "$ONLY_CUSTOMCMD" -eq 1 ]; then
		writelog "WAIT" "${FUNCNAME[0]} - Waiting for custom process CUSTOMCMD '$CUSTOMCMD'"
	fi

	while [ -z "$(GAMEPID)" ]; do 
		writelog "WAIT" "${FUNCNAME[0]} - Waiting for game process $(GAMEPID)"
		sleep 1
	done
	writelog "INFO" "${FUNCNAME[0]} - Game process found at $(GAMEPID)"
}

function getGameWinXIDFromPid {
	GPID="$1"
	while read -r WINS; do
		if [ "$("$XPROP" -id "$(printf 0x%x'\n' "$WINS")" | grep "_NET_WM_STATE(ATOM)" -c)" -ge 1 ]; then
			writelog "INFO" "${FUNCNAME[0]} - Found a controllable windowid"
			WSIZ="$(getWindowHeight "$WINS")"
			if [ "$WSIZ" -lt "$MINVRWINH" ]; then
				writelog "SKIP" "${FUNCNAME[0]} - '$(printf 0x%x'\n' "$WINS")' height is less than $MINVRWINH - this is very likely not the game window - skipping"
			else
				writelog "INFO" "${FUNCNAME[0]} Found window id $(printf 0x%x'\n' "$WINS") for '$GE' running with PID '$GPID'"
				echo "$WINS"
				break
			fi
		fi
	done <<< "$("$XDO" search --pid "$GPID")"	
}

function getGameWinNameFromXid {
	"$XDO" getwindowname "$1"
}

function getGameWindowPID {
	if [ "$MO2MODE" == "gui" ]; then
		writelog "SKIP" "${FUNCNAME[0]} - Skipping check for window pid, because MO2MODE is '$MO2MODE'"
	else
		if [ -n "$GAMEWINPID" ]; then
			writelog "SKIP" "${FUNCNAME[0]} - Already have the GAMEWINPID '$GAMEWINPID'"
			echo "$GAMEWINPID"
		else
			MAXWAIT=20
			COUNTER=0
			TESTPID="$NON"
			WASCLOSED=0

			touch "$PIDLOCK"
			
			while [ "$COUNTER" -lt "$MAXWAIT" ]; do
				if [ -f "$CLOSETMP" ]; then
					writelog "WAIT" "${FUNCNAME[0]} - ${PROGNAME,,} is just closing - leaving loop"
					WASCLOSED=1
					break
				fi
				TESTPID="$("$XDO" getactivewindow getwindowpid)"
				SYMCWD="$(readlink "/proc/$TESTPID/cwd")"
				SYMEXE="$(readlink "/proc/$TESTPID/exe")"
				
				if [ -z "$TESTPID" ]; then
					break;
				else
					if [ -n "$HAVPA" ]; then
						writelog "WAIT" "${FUNCNAME[0]} - Found PID '$TESTPID' for game 'HAVPA' '$HAVPA' - leaving loop"
						FOUNDWIN="$YES"
						break;
					elif [ -n "$EXECUTABLE" ] && [ "$EXECUTABLE" == "$(cat "/proc/$TESTPID/comm")" ]; then
						writelog "WAIT" "${FUNCNAME[0]} - Found PID '$TESTPID' for game 'EXECUTABLE' '$EXECUTABLE' - leaving loop"
						FOUNDWIN="$YES"
						break;
					elif [ -n "$GE" ] && [ "$GE" == "$(cut -d '.' -f1 < "/proc/$TESTPID/comm")" ]; then
						writelog "WAIT" "${FUNCNAME[0]} - Found PID '$TESTPID' for game executable 'GE' '$GE' - leaving loop"
						FOUNDWIN="$YES"
						break;
					else
						# might not even be required anymore - maybe remove later:
						if [[ "$SYMCWD" == "$EFD" ]] && [[ "$SYMEXE" != *"$YAD"* ]]; then
							writelog "WAIT" "${FUNCNAME[0]} - Found PID '$TESTPID' for CWD '$SYMCWD' with EXE '$SYMEXE' - leaving loop"
							FOUNDWIN="$YES"
							break;
						fi
						if [ -n "$STEAM_COMPAT_CLIENT_INSTALL_PATH" ] && [[ "$SYMCWD" == "$STEAM_COMPAT_CLIENT_INSTALL_PATH" ]] && [[ "$SYMEXE" != *"$YAD"* ]]; then
							writelog "WAIT" "${FUNCNAME[0]} - Found PID '$TESTPID' for STEAM_COMPAT_CLIENT_INSTALL_PATH '$SYMCWD' with EXE '$SYMEXE' - leaving loop"
							FOUNDWIN="$YES"
							break;
						fi
					fi
				fi
				writelog "WAIT" "${FUNCNAME[0]} - Sec $COUNTER/$MAXWAIT Game Window with pwd '$EFD' not yet in front"
				COUNTER=$((COUNTER+1))
				sleep 1
			done

			rm "$PIDLOCK" 2>/dev/null
			
			if [ "$FOUNDWIN" == "$YES" ]; then
				if [ "$TESTPID" == "$NON" ]; then
					writelog "SKIP" "${FUNCNAME[0]} - FAIL - Found PID returned but it is empty: '$TESTPID'"
				fi
				writelog "INFO" "${FUNCNAME[0]} - Found PID '$TESTPID' for running exe '$(readlink "/proc/$TESTPID/exe")'"
				echo "$TESTPID"
			else
				if [ "$WASCLOSED" -eq 0 ]; then
					writelog "SKIP" "${FUNCNAME[0]} - ERROR - timeout waiting for '$EFD' window"
					echo "$NON"
				fi
			fi
		fi
	fi
}

function storeGameWindowNameMeta {
	GAMEWINDOW="$1"
	if [ -n "$GAMEWINDOW" ] && [ "$GAMEWINDOW" != "$NON" ] && [ "$STLPLAY" -eq 0 ]; then
		writelog "INFO" "${FUNCNAME[0]} - Found game window name '$GAMEWINDOW' - saving into metadata file '$GEMETA/$AID.conf' for game '$MGNA ($AID)'"
		touch "$FUPDATE"
		touch "$GEMETA/$AID.conf"
		updateConfigEntry "GAMEWINDOW" "$GAMEWINDOW" "$GEMETA/$AID.conf"
	fi	
}

function pickGameWindowNameMeta {
	if [ -n "$1" ]; then
		AID="$1"
	fi
	if [ -n "$2" ]; then
		GN="$2"
	fi
	fixShowGnAid
	writelog "INFO" "${FUNCNAME[0]} - Picking 'GAMEWINDOW' for '$SGNAID'"

	GAMEWINXID="$(printf 0x%x'\n' "$("$XDO" selectwindow)")"
	GAMEWINDOW="$("$XDO" getwindowname "$GAMEWINXID")"
	storeGameWindowNameMeta "$GAMEWINDOW"
	if [ -n "$AID" ]; then
		notiShow "$(strFix "$NOTY_PICKWINS" "$GAMEWINDOW" "$GN" "$AID")"
		writelog "INFO" "${FUNCNAME[0]} - Picked 'GAMEWINDOW $GAMEWINDOW' for '$SGNAID'"
	else
		notiShow "$(strFix "$NOTY_PICKWINN" "$GAMEWINDOW")"
	fi
}

function getIDFromTitle {
	if [ -z "$1" ]; then
		echo "A Game Title (part of it might be enough) is required as argument"
	else
		grep -Rhi -B1 "^GAMENAME=.*.$1" "$GEMETA" | head -n1 | grep -o -E '[0-9]+'
	fi	
}

function getTitleFromID {
	if [ -z "$1" ]; then
		echo "A Game ID is required as argument"
	else
		if [ -f "$GEMETA/${1}.conf" ]; then
			if grep -q "^GAMENAME" "$GEMETA/${1}.conf"; then
				grep "^GAMENAME" "$GEMETA/${1}.conf" | cut -d '=' -f2
			else
				getAppInfoData "$1" "name"
			fi
		else
			echo "No Title found for '$1'"
		fi
	fi
}

function getExeFromID {
	if [ -z "$1" ]; then
		echo "A Game ID is required as argument"
	else
		if [ -f "$GEMETA/${1}.conf" ]; then
			grep "^GAMEEXE" "$GEMETA/${1}.conf" | cut -d '=' -f2
		else
			echo "No Title found for '$1'"
		fi
	fi
}

function getCompatData {
	if [ -z "$1" ]; then
		echo "A Game ID or Game Title is required as argument"
	else
		if [ -d "$STLCOMPDAT" ]; then
			unset FCOMPDAT
			if [ "$1" -eq "$1" ] 2>/dev/null; then
				while read -r "complink"; do
				TEST="$(readlink "$complink" | grep "/$1$")"
				if [ -d "$TEST" ]; then
					FCOMPDAT="${complink##*/};$TEST"
				fi
				done <<< "$(find "$STLCOMPDAT")"
			else
				TEST="$(find "$STLCOMPDAT" -iname "*${1}*" | head -n1)"
				if [ -n "$TEST" ]; then
					FCOMPDAT="${TEST##*/};$(readlink "$TEST")"
				fi
			fi

			if [ -n "$FCOMPDAT" ]; then
				echo "$FCOMPDAT"
			else
				echo "No $CODA dir found for '$1'"
			fi
		else
			echo "No $CODA dir found for '$1'"
		fi
	fi
}

function getGameDir {
	if [ -z "$1" ]; then
		echo "A Game ID or Game Title is required as argument"
	else
			unset FGDIR
			if [ "$1" -eq "$1" ] 2>/dev/null; then
				if [ -d "$CUMETA" ]; then
					TEST="$(find "$CUMETA" | grep "$1")"
					if [ -f "$TEST" ]; then
						source "$TEST"
						FGDIR="$(basename "${TEST//.conf/}");$MEGAMEDIR"
					fi
				else
					echo "No Game Dir found for '$1'"
				fi
			else
				if [ -d "$TICUMETA" ]; then
					TEST="$(find "$TICUMETA" | grep "$1")"
					if [ -f "$TEST" ]; then
						source "$TEST"
						FGDIR="$(basename "${TEST//.conf/}");$MEGAMEDIR"
					fi
				else
					echo "No Game Dir found for '$1'"
				fi
			fi

			if [ -n "$FGDIR" ]; then
				echo "$FGDIR"
			else
				echo "No Game Dir found for '$1'"
			fi
	fi
}

function getGameWindowName {
	if [ -n "$GAMEWINDOW" ] && [ "$GAMEWINDOW" != "$NON" ]; then
		writelog "SKIP" "${FUNCNAME[0]} - Already have the gamewindow name: '$GAMEWINDOW' - skipping"
		rm "$PIDLOCK" 2>/dev/null
	else
		rm "$TEMPGPIDFILE" 2>/dev/null
		
		if [ -n "$GPFX" ]; then
			SYSREG="$GPFX/$SREG"
			if [ ! -f "$SYSREG" ] ; then
				writelog "WAIT" "${FUNCNAME[0]} - Waiting for the pfx '$GPFX' to be full created"
			fi

			while [ ! -f "$SYSREG" ]; do
				if [ -f "$CLOSETMP" ]; then
					break
				fi
				sleep 1
			done
		fi

		writelog "INFO" "${FUNCNAME[0]} - No gamewindow name stored in metadata '$GEMETA/$AID.conf' yet. Trying to find it now"
		FOUNDWIN="$NON"
		GAMEWINPID="$(getGameWindowPID)"
		if [ -n "$GAMEWINPID" ] ; then
			if [[ "$GAMEWINPID" == "$NON" ]] ; then
				writelog "SKIP" "${FUNCNAME[0]} - No valid game window PID found"
			else
				writelog "INFO" "${FUNCNAME[0]} - Found valid game window PID '$GAMEWINPID'"
				echo "GAMEWINPID=\"$GAMEWINPID\"" > "$TEMPGPIDFILE"

				GAMEWINXID="$(getGameWinXIDFromPid "$GAMEWINPID")"
				if [ -n "$GAMEWINXID" ]; then
					writelog "INFO" "${FUNCNAME[0]} - Found game window XID '$GAMEWINXID'"
					storeGameWindowNameMeta "$(getGameWinNameFromXid "$GAMEWINXID")"
				fi
			fi
		fi
	fi
}

function getCfgHeader {
	echo "#########"
	echo "#GAMENAME=\"$GAMENAME\""
	echo "#GAMEEXE=\"$GAMEEXE\""
	echo "#GAMEID=\"$AID\""
	echo "#PROTONVERSION=\"$PROTONVERSION\""
	echo "#########"	
}

function SBSrunVRVideoPlayer {
	SBSVRWINNAME="vr-video-player"

	if [ "$RUNSBSVR" -eq 1 ]; then
		if [ -z "$GAMEWINXID" ]; then
			writelog "SKIP" "${FUNCNAME[0]} - ERROR - GAMEWINXID is empty"
			writelog "SKIP" "${FUNCNAME[0]} - ERROR - forcefully killing game with $PKILL -9 '$GAMEWINPID' - should exit this script as well"
			getGamePidFromFile
			"$PKILL" -9 "$GAMEWINPID"
		else
			if [ -z "$VRVIDEOPLAYERARGS" ];	then
				writelog "SKIP" "${FUNCNAME[0]} - ERROR - no VRVIDEOPLAYERARGS '$VRVIDEOPLAYERARGS'"
			fi

			mapfile -d " " -t -O "${#RUNVRVIDEOPLAYERARGS[@]}" RUNVRVIDEOPLAYERARGS < <(printf '%s' "$VRVIDEOPLAYERARGS")

			writelog "INFO" "${FUNCNAME[0]} - Starting '$VRVIDEOPLAYER' with args '${RUNVRVIDEOPLAYERARGS[*]}' for windowid '$GAMEWINXID'"

			GWIDDEC="$(("$GAMEWINXID"))"
			echo "GWIDDEC=$GWIDDEC" > "$GWIDFILE"

			sleep 1	# ugly, but it might need a bit...
			
			if [ -z "$SBSZOOM" ]; then
				"$VRVIDEOPLAYER" "${RUNVRVIDEOPLAYERARGS[@]}" "$GAMEWINXID" 2>/dev/null &
			else
				"$VRVIDEOPLAYER" "${RUNVRVIDEOPLAYERARGS[@]}" --zoom "$SBSZOOM" "$GAMEWINXID" 2>/dev/null &
			fi

			writelog "INFO" "${FUNCNAME[0]} - Waiting for '$VRVIDEOPLAYER' window '$SBSVRWINNAME' for GAMEWINXID '$GAMEWINXID'"

			MAXWAIT=20
			COUNTER=0
			
			while ! "$XWININFO" -name "$SBSVRWINNAME" -stats >/dev/null 2>/dev/null; do
				if [ -f "$CLOSETMP" ]; then
					writelog "WAIT" "${FUNCNAME[0]} - ${PROGNAME,,} is just closing - leaving loop"
					break
				fi
				if [[ "$COUNTER" -ge "$MAXWAIT" ]]; then
					writelog "SKIP" "${FUNCNAME[0]} - ERROR - timeout waiting for '$VRVIDEOPLAYER' - exit"
					"$PKILL" -f "$VRVIDEOPLAYER"
					RUNSBSVR=0
					exit 1
				fi
				if ! "$PGREP" -f "$VRVIDEOPLAYER" ; then
					if [ "$COUNTER" -ge 3 ]; then
						writelog "SKIP" "${FUNCNAME[0]} - ERROR - '$VRVIDEOPLAYER' not running (crashed?) no need to wait for its window to appear - exit"
						RUNSBSVR=0
						exit 1
					else
						writelog "WARN" "${FUNCNAME[0]} - '$VRVIDEOPLAYER' not running yet - waiting a bit longer"
					fi
				fi

				writelog "WAIT" "${FUNCNAME[0]} - WAIT - '$COUNTER/$MAXWAIT' sec waiting for '$VRVIDEOPLAYER' window '$SBSVRWINNAME'"
				COUNTER=$((COUNTER+1))
				sleep 1
			done

			# player windowid:
			SBSVRWID=$("$XWININFO" -name "$SBSVRWINNAME" -stats | grep "^$XWININFO" | awk -F 'id: ' '{print $2}' | cut -d ' ' -f1)
				
			if [ -n "$SBSVRWID" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Pressing w in '$VRVIDEOPLAYER' window '$SBSVRWINNAME' to adjust view: '$XDO windowactivate --sync $SBSVRWID key w'"
				"$XDO" windowactivate --sync "$SBSVRWID" key w

				writelog "INFO" "${FUNCNAME[0]} - Activating game window with id '$GAMEWINXID' for input"
				"$XDO" windowactivate --sync "$GAMEWINXID" click 1
			else
				writelog "SKIP" "${FUNCNAME[0]} - WARN - SBSVRWID '$SBSVRWID' is empty!"
			fi
		fi
	else
		writelog "SKIP" "${FUNCNAME[0]} - Skipping because RUNSBSVR was set to 0"
	fi
}

function SBSinitVRVideoPlayer {
	if [ "$RUNSBSVR" -eq 1 ]; then
		if [ -n "$GAMEWINXID" ]; then
			if [ "$GAMEWINXID" == "0x0" ]; then
				writelog "SKIP" "${FUNCNAME[0]} GAMEWINXID '$GAMEWINXID' is invalid - skipping VR"
				RUNSBSVR=0
			else
				writelog "INFO" "${FUNCNAME[0]} Using the gamewindow id '$GAMEWINXID' for stereoscopic 3D VR"
				SBSrunVRVideoPlayer	"$GAMEWINXID" 2>/dev/null &
			fi
		fi
	else
		writelog "SKIP" "${FUNCNAME[0]} - Skipping because RUNSBSVR was set to 0"
	fi
}

function SBSstopVRVideoPlayer {
	if [ "$RUNSBSVR" -eq 1 ]; then

		MAXWAIT=20
		COUNTER=0
		while [ -z "$GAMEWINPID" ]; do
			if [ -f "$CLOSETMP" ]; then
				writelog "WAIT" "${FUNCNAME[0]} - ${PROGNAME,,} is just closing - leaving loop"
				break
			fi
			if [[ "$COUNTER" -ge "$MAXWAIT" ]]; then
				writelog "SKIP" "${FUNCNAME[0]} - ERROR - timeout waiting for Game process - exit"
				break
			fi

			writelog "INFO" "${FUNCNAME[0]} - Don't have a Game process GAMEWINPID yet - waiting"
			getGamePidFromFile
			GAMEWINPID="$(getGamePidFromWindowName)"
			COUNTER=$((COUNTER+1))
			sleep 1
		done
		
		writelog "INFO" "${FUNCNAME[0]} - Waiting for game process '$GAMEWINPID' to finish..."

		if ! "$PGREP" -a "vrcompositor" >/dev/null ; then
			writelog "SKIP" "${FUNCNAME[0]} - ERROR - vrcompositor not running but it should - bailing out DRYRUN"
		fi

		tail --pid="$GAMEWINPID" -f /dev/null
		writelog "INFO" "${FUNCNAME[0]} - Game process '$GAMEWINPID' finished - closing '$VRVIDEOPLAYER'"

		if [ -f "$GWIDFILE" ]; then
			source "$GWIDFILE"
			GWIDTXT="/tmp/${VRVIDEOPLAYER##*/}_${GWIDDEC}"

			if [ -f "$GWIDTXT" ]; then
				writelog "INFO" "${FUNCNAME[0]} - '$GWIDTXT' found"
				updateConfigEntry "SBSZOOM" "$(cat "$GWIDTXT")" "$SBSTWEAKCFG"
				rm "$GWIDTXT" >/dev/null 2>/dev/null
			else
				writelog "SKIP" "${FUNCNAME[0]} - GWIDTXT '$GWIDTXT' not found - skipping"
			fi
			rm "$GWIDFILE" >/dev/null 2>/dev/null
		else
			writelog "SKIP" "${FUNCNAME[0]} - GWIDFILE '$GWIDFILE' not found - skipping"
		fi

		"$PKILL" -f "$VRVIDEOPLAYER"

		writelog "INFO" "${FUNCNAME[0]} - -------- finished SBS-VR --------"
	else
		writelog "SKIP" "${FUNCNAME[0]} - Skipping because RUNSBSVR was set to 0"
	fi
}

function waitForGameWindowName {
	if [ -n "$GAMEWINDOW" ] && [ "$GAMEWINDOW" != "$NON" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Already have a Game Window '$GAMEWINDOW'"
	else
		MAXWAIT=20
		COUNTER=0
		writelog "INFO" "${FUNCNAME[0]} - Waiting for parallel process to find the Game Window"

		while [ -f "$PIDLOCK" ]; do
			if [ -f "$CLOSETMP" ] || [[ "$COUNTER" -ge "$MAXWAIT" ]]; then
				break
			fi
			COUNTER=$((COUNTER+1))
			sleep 1
		done

		COUNTER=0

		while ! grep -q "^GAMEWINDOW" "$GEMETA/$AID.conf"; do
			if [ -f "$CLOSETMP" ]; then
				writelog "WAIT" "${FUNCNAME[0]} - ${PROGNAME,,} is just closing - leaving loop"
				break
			fi
			if [[ "$COUNTER" -ge "$MAXWAIT" ]]; then
				writelog "SKIP" "${FUNCNAME[0]} - Giving up waiting for GAMEWINDOW to appear in the game metadata '$GEMETA/$AID.conf'"
				break
			fi

			writelog "WAIT" "${FUNCNAME[0]} - WAIT - '$COUNTER/$MAXWAIT' sec waiting for GAMEWINDOW to appear in game metadata '$GEMETA/$AID.conf'"
			COUNTER=$((COUNTER+1))
			sleep 1
		done
		loadCfg "$GEMETA/$AID.conf" X

		if [ -n "$GAMEWINDOW" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Parallel process found Game Window '$GAMEWINDOW'"
		else
			writelog "SKIP" "${FUNCNAME[0]} - Parallel process didn't find a Game Window GAMEWINDOW"
		fi
	fi
}

function getGameWindowXID {
	if [ -n "$GAMEWINXID" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Already have the windowid '$GAMEWINXID'"
	else	
		if [ -n "$GAMEWINDOW" ] && [ "$GAMEWINDOW" != "$NON" ]; then
			GAMEWINXID="$("$XWININFO" -name "${GAMEWINDOW//\"/}" -stats | grep "^$XWININFO" | awk -F 'id: ' '{print $2}' | cut -d ' ' -f1)"
			if [ -n "$GAMEWINXID" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Found windowid '$GAMEWINXID' for the windowname '$GAMEWINDOW'"
			fi
		fi
		if [ -z "$GAMEWINXID" ]; then
			if [ -n "$GAMEWINPID" ]; then
				GAMEWINXID="$(getGameWinXIDFromPid "$GAMEWINPID")"
			else
				writelog "SKIP" "${FUNCNAME[0]} - Don't have a game pid '$GAMEWINPID' to detect the windowid GAMEWINXID"
			fi
			if [ -n "$GAMEWINXID" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Found windowid '$GAMEWINXID' for the game pid '$GAMEWINPID'"
			fi
		fi
	fi
	if [ -n "$GAMEWINPID" ]; then
		echo "$GAMEWINPID"
	else
		writelog "SKIP" "${FUNCNAME[0]} - Failed to detect the windowid GAMEWINXID"
	fi
}

function waitForGameWindowXid {
	if [ -n "$GAMEWINXID" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Already have the game window XID '$GAMEWINXID'"
	else
		if [ -n "$GAMEWINDOW" ] && [ "$GAMEWINDOW" != "$NON" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Waiting for a window GAMEWINXID of the game window '$GAMEWINDOW'"
			MAXWAIT=20
			COUNTER=0
			while ! "$XWININFO" -name "${GAMEWINDOW//\"/}"; do
				if [ -f "$CLOSETMP" ]; then
					writelog "WAIT" "${FUNCNAME[0]} - ${PROGNAME,,} is just closing - leaving loop"
					break
				fi
				if [[ "$COUNTER" -ge "$MAXWAIT" ]]; then
					writelog "SKIP" "${FUNCNAME[0]} - Giving up waiting for GAMEWINXID"
					break
				fi

				writelog "WAIT" "${FUNCNAME[0]} - WAIT '$COUNTER/$MAXWAIT'"
				sleep 1
				COUNTER=$((COUNTER+1))
			done
		elif [ -n "$GAMEWINPID" ]; then
			GAMEWINXID="$(getGameWinXIDFromPid "$GAMEWINPID")"
		else
			writelog "SKIP" "${FUNCNAME[0]} - Can't wait for the windowid GAMEWINXID without either a valid GAMEWINDOW or GAMEWINPID"
		fi

		GAMEWINXID="$("$XWININFO" -name "${GAMEWINDOW//\"/}" -stats | grep "^$XWININFO" | awk -F 'id: ' '{print $2}' | cut -d ' ' -f1)"

		if [ -n "$GAMEWINXID" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Found the game window id '$GAMEWINXID'"
		else
			writelog "SKIP" "${FUNCNAME[0]} - Didn't find a game window id GAMEWINXID"
		fi
	fi
}

function initSBSVR {
	if [ "$RUNSBSVR" -eq 1 ]; then
		writelog "INFO" "${FUNCNAME[0]} - Checking if VR is available"
		touch "$VRINITLOCK"
		checkHMDPresent
		initSteamVR
		mv "$VRINITLOCK" "$VRINITRESULT"
	fi
}

function startSBSVR {
	if [ "$RUNSBSVR" -eq 1 ]; then
		MAXWAIT=20
		COUNTER=0
		
		writelog "INFO" "${FUNCNAME[0]} - Waiting for parallel process to detect VR HMD presence"

		while [ -f "$VRINITLOCK" ]; do
			if [ -f "$CLOSETMP" ] || [[ "$COUNTER" -ge "$MAXWAIT" ]]; then
				break
			fi
			COUNTER=$((COUNTER+1))
			sleep 1
		done
		
		loadCfg "$VRINITRESULT"
		rm "$VRINITRESULT"
		
		if [ "$RUNSBSVR" -eq 1 ]; then
			if [ -f "$SBSTWEAKCFG" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Loading SBS configfile '$SBSTWEAKCFG' to get current values"
				loadCfg "$SBSTWEAKCFG"
			fi
			writelog "INFO" "${FUNCNAME[0]} - Preparing VR launch for '$AID'"
			waitForGameWindowName
			waitForGameWindowXid
			SBSinitVRVideoPlayer
			SBSstopVRVideoPlayer
		else
			writelog "SKIP" "${FUNCNAME[0]} - VR mode was cancelled, because the parallel process could not initialize VR"
		fi
	fi
}

function checkHMDPresent {
	if "$PGREP" -a "vrcompositor" >/dev/null ; then
		writelog "INFO" "${FUNCNAME[0]} - Looks like SteamVR is already running - skipping this function"
	else
		if [ "$CHECKHMD" -eq 1 ]; then
			UUDEV="/lib/udev/rules.d"
			EUDEV="/etc/udev/rules.d"
			SVR="steam-vr"
			NOVRP="1142"
			FOUNDHMD=0

			SVRRULE="$(find "$UUDEV" -name "*$SVR*")"
			if [ -z "$SVRRULE" ]; then
				SVRRULE="$(find "$EUDEV" -name "*$SVR*")"
			fi

			if [ -n "$SVRRULE" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Found $SVR udev rule - trying to find one of the VR devices before starting SteamVR"

				while read -r line; do
					IDV="$(cut -d ',' -f3 <<< "$line" | grep -oP '"\K[^"]+')"
					IDP="$(cut -d ',' -f4 <<< "$line" | grep -v "$NOVRP" | grep -oP '"\K[^"]+')"
					if [ -n "$IDV" ] && [ -n "$IDP" ]; then
						IDVP="$IDV:$IDP"
						if "$LSUSB" | grep -q "$IDVP"; then
							FOUNDHMD=1
						fi
					fi
				done < "$SVRRULE"
			else
				echo "no $SVR udev rule found"
				writelog "WARN" "${FUNCNAME[0]} - No $SVR udev rule found. As it might be stored under a different name, this is just a warning"
			fi

			if [ "$FOUNDHMD" -eq 1 ]; then
				writelog "INFO" "${FUNCNAME[0]} - Found $SVR hardware using '$LSUSB' - continuing"
			else
				writelog "SKIP" "${FUNCNAME[0]} - No $SVR hardware found using '$LSUSB' - cancelling the SteamVR start"
				RUNSBSVR=0
				echo "RUNSBSVR=\"0\"" > "$VRINITLOCK"
			fi
		else
			writelog "SKIP" "${FUNCNAME[0]} - Skipping, as '$LSUSB' was not found"
		fi
	fi
}

# start game in side-by-side VR:
function checkSBSVRLaunch {
	if [ "$1" != "$NON" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Incoming gamewindow name is '$1'"
		RUNSBSVR=1
	fi

	if [ -n "$RUNSBSVR" ]; then
		if [ "$RUNSBSVR" -eq 1 ]; then
		# override game configs with a sbs-tweak config if available:
		
		# first look for a global tweak:
			if [ -f "$GLOBALSBSTWEAKCFG" ]; then
				writelog "INFO" "${FUNCNAME[0]} - VR using overrides found in '$GLOBALSBSTWEAKCFG'"
				loadCfg "$GLOBALSBSTWEAKCFG"
			fi

		# then for a user tweak - (overriding the global one):
			if [ -f "$SBSTWEAKCFG" ]; then
				writelog "INFO" "${FUNCNAME[0]} - VR using overrides found in '$SBSTWEAKCFG'"
				loadCfg "$SBSTWEAKCFG"
			fi

		# start the whole side-by-side process:
			if [ "$1" != "$NON" ]; then
				writelog "INFO" "${FUNCNAME[0]} - ${FUNCNAME[0]} - Using argument 1 as GAMEWINDOW '$GAMEWINDOW'"
				export GAMEWINDOW="$1"
			fi

			writelog "INFO" "${FUNCNAME[0]} - ${FUNCNAME[0]} - Starting VRlaunch for '$AID'"
			if [ "$RUNSBSVR" -eq 1 ]; then
				initSBSVR &
			else
				writelog "SKIP" "${FUNCNAME[0]} - ERROR - RUNSBSVR is '$RUNSBSVR' which is invalid - setting to 0"
				RUNSBSVR=0
			fi
		fi
	fi
}

function dld3d47 {
	function dld3d4732 {
		dlCheck "$DL_D3D47_32" "$D3D47DLDIR/${D3D47//.dll/.zip}" "X" "Downloading '$D3D47_32' into '$D3D47DLDIR'"
		find "$DLDST" -size 0 -delete
		"$UNZIP" "$DLDST" -d "$D3D47DLDIR" 2>/dev/null
		mv "$D3D47DLDIR/$D3D47" "$D3D47DLDIR/$D3D47_32" 2>/dev/null
	}
	
	function dld3d4764 {
		if [ ! -f "$D3D47DLDIR/$D3D47_64" ]; then
			dlCheck "$DL_D3D47_64" "$D3D47DLDIR/$D3D47_64" "X" "Downloading '$D3D47_64' into '$D3D47DLDIR'"
			find "$D3D47DLDIR/$D3D47_64" -size 0 -delete
		fi
	}
	mkProjDir "$D3D47DLDIR"
	dld3d47"$1"
}

function installd3d47dll {
	if [ ! -f "$2/$D3D47" ]; then
		if [ ! -f "$D3D47DLDIR/$1" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Sourcefile '$D3D47DLDIR/$1' missing - trying to download" 
			dld3d47 "32"
			dld3d47 "64"
		fi
	
		if [ ! -f "$D3D47DLDIR/$1" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Sourcefile '$D3D47DLDIR/$1' still missing - skipping this file" 	
		else
			cp "$D3D47DLDIR/$1" "$2/$D3D47" >/dev/null 2>/dev/null
			writelog "INFO" "${FUNCNAME[0]} - Copied '$D3D47DLDIR/$1' to '$2/$D3D47'"
			if [ "$USESPECIALK" -eq 1 ]; then
				echo "$2/$D3D47" >> "$SPEKENA"
			else
				echo "$D3D47" >> "$2/$RSTXT"
				sort "$2/$RSTXT" -u -o "$2/$RSTXT"
			fi
		fi
	else
		writelog "SKIP" "${FUNCNAME[0]} - Destfile '$2/$D3D47' already exists - skipping this file" 
	fi
}

function dlReShade {
	if [ -z "$1" ]; then
		DLVERS="$RSVERS"
	else
		DLVERS="$1"
	fi
	rm "$RESHADESRCDIR/$RS_64" 2>/dev/null
	rm "$RESHADESRCDIR/$RS_32" 2>/dev/null
	rm "$RESHADESRCDIR/${RS_64//.dll/.json}" 2>/dev/null
	rm "$RESHADESRCDIR/${RS_32//.dll/.json}" 2>/dev/null

	DLDST="${RESHADESRCDIR}/${RSSU}.exe"
	DLDSTV="${RESHADESRCDIR}/${RSSU}_${DLVERS}.exe"

	RSSETUP="${RESHADEDLURL}/${RSSU}_${DLVERS}.exe"

	dlCheck "$RSSETUP" "$DLDST" "X" "Downloading $RSSU"
	if [ ! -f "$DLDSTV" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Creating backup '${RSSU}_${DLVERS}.exe'"
		cp "$DLDST" "$DLDSTV"
	fi

	echo "$DLVERS" > "${DLDST//.exe/.log}"

	if [ ! -s "$DLDST" ]; then
		writelog "SKIP" "${FUNCNAME[0]} - Downloaded file '$DLDST' is empty - removing"
		rm "$DLDST" 2>/dev/null
	else
		"$UNZIP" -q "$DLDST" -d "$RESHADESRCDIR" 2>/dev/null
		writelog "INFO" "${FUNCNAME[0]} - Downloaded and extracted ${RESH}-v${DLVERS} file '$DLDST'"
	fi
}

# prepare reshade files if not found:
function prepareReshadeFiles {
	if [ "$DOWNLOAD_RESHADE" -eq 1 ]; then
		writelog "INFO" "${FUNCNAME[0]} - DOWNLOAD_RESHADE enabled"

		if [ -n "$RESHADESRCDIR" ]; then
			if [ ! -f "$RESHADESRCDIR/$D3D47_32" ]; then
				writelog "404" "${FUNCNAME[0]} - '$RESHADESRCDIR/$D3D47_32' missing - downloading"

				if [ ! -d "$RESHADESRCDIR" ]; then
					writelog "404" "${FUNCNAME[0]} - '$RESHADESRCDIR' does not exist - trying to create it" 
					mkProjDir "$RESHADESRCDIR"
				fi
			fi
			dld3d47 "32"
			dld3d47 "64"

			if [ ! -f "$RESHADESRCDIR/$RS_64" ] || [ ! -f "$RESHADESRCDIR/$RS_32" ]; then
				writelog "404" "${FUNCNAME[0]} - '$RESHADESRCDIR/$RS_64' and/or '$RS_32' missing - downloading"
				dlReShade
			fi

			if [ "$RESHADEUPDATE" -eq 1 ]; then
				if [ -f "${RESHADESRCDIR}/${RSSU}.log" ]; then
					writelog "INFO" "${FUNCNAME[0]} - Found ${RESH} download log '${RESHADESRCDIR}/${RSSU}.log'"
					if [ "$RSVERS" != "$(cat "${RESHADESRCDIR}/${RSSU}.log")" ]; then
						writelog "INFO" "${FUNCNAME[0]} - Last downloaded is ${RESH} version '$(cat "${RESHADESRCDIR}/${RSSU}.log")' is not equal to the latest available ${RESH} version '$RSVERS' - updating"
						dlReShade
					fi
				fi
			fi
		fi
	fi
	
	# make sure Depth3D is even wanted
	if [ "$RESHADE_DEPTH3D" -eq 1 ]; then
		writelog "INFO" "${FUNCNAME[0]} - RESHADE_DEPTH3D enabled"
		StatusWindow "$GUI_DLSHADER" "dlShaders depth3d" "DownloadShadersStatus"
	fi	
}

function SHADSRC {
	echo "$STLSHADDIR/${1,,}"
}

function createShaderRepoList {
	SHADREPOURL="https://www.pcgamingwiki.com/wiki/${RESH}"
	MAXAGE=1440

	if [ ! -f "$SHADREPOLIST" ] || test "$(find "$SHADREPOLIST" -mmin +"$MAXAGE")"; then	
		# if this breaks, we'll use bundled static url list instead
		"$WGET" -q "$SHADREPOURL" -O - 2> >(grep -v "SSL_INIT") | sed -n '/Repository</,/table>/p' | grep "^<td>" | awk 'ORS=NR%3?FS:RS' | grep -v "https://blues" | sed "s:<td><a rel=\"nofollow\" class=\"external text\" href=::; s:</a></td> <td>:;:; s:</td> <td>:;:; s:\">:\";:; s:<br />: :; s: ;:;:; s:/tree/master::; s:/reshade/Shaders::" > "$SHADREPOLIST"
	fi

	RCL="repocustomlist.txt"
	SHADREPOCUSTOMLIST="$STLSHADDIR/$RCL"

	if [ ! -f "$SHADREPOCUSTOMLIST" ]; then
		cp "$GLOBALMISCDIR/$RCL" "$SHADREPOCUSTOMLIST"
	fi

	if [ -f "$SHADREPOCUSTOMLIST" ]; then
		cat "$SHADREPOCUSTOMLIST" >> "$SHADREPOLIST"
		sort -u "$SHADREPOLIST" -o "$SHADREPOLIST"
	fi
	
	sed '/^$/d' -i "$SHADREPOLIST"
}

function dlShaders {
	createShaderRepoList
	touch "$SHADERREPOBLOCKLIST"

	if [ -z "$1" ]; then
		if [ "$DLSHADER" -eq 1 ]; then
			while read -r SHADLINE; do
				SHADURL="$(cut -d ';' -f1 <<< "$SHADLINE")"
				SHADNAM="$(cut -d ';' -f2 <<< "$SHADLINE")"
				if ! grep -qi "$SHADNAM" "$SHADERREPOBLOCKLIST"; then
					writelog "INFO" "${FUNCNAME[0]} - Updating $SHADNAM" 
					notiShow "$(strFix "$NOTY_DLSHADERS" "$SHADNAM")" "S"
					gitUpdate "$(SHADSRC "$SHADNAM")" "${SHADURL//\"/}"
				else
					writelog "SKIP" "${FUNCNAME[0]} - Skipping $SHADNAM"
				fi
			done < "$SHADREPOLIST"
			notiShow "$GUI_DONE" "S"
		fi
	else
		if [ "$1" == "list" ]; then
			while read -r SHADLINE; do
				SHADNAM="$(cut -d ';' -f2 <<< "$SHADLINE")"
				echo "\"${SHADNAM,,}\""
			done < "$SHADREPOLIST" | sort
		elif [ "$1" == "repos" ]; then
			ShaderRepoDialog
		else
			SHADURL="$(grep -i ";$1;" "$SHADREPOLIST" | cut -d ';' -f1)"
			if [ -n "$SHADURL" ]; then
				gitUpdate "$(SHADSRC "$1")" "${SHADURL//\"/}"
			else
				writelog "SKIP" "${FUNCNAME[0]} - Invalid shader $1"
			fi
		fi
	fi
}

function ShaderRepoDialog {
	createShaderRepoList
	fixShowGnAid
	export CURWIKI="$PPW/Shader-Repositories"
	TITLE="${PROGNAME}-${FUNCNAME[0]}"
	pollWinRes "$TITLE"

	setShowPic

	REPOPICKS="$(
	while read -r SHADLINE; do
		SHADURL="$(cut -d ';' -f1 <<< "$SHADLINE")"
		SHADNAM="$(cut -d ';' -f2 <<< "$SHADLINE")"
		SHADAUT="$(cut -d ';' -f3 <<< "$SHADLINE")"
		SHADDES="$(cut -d ';' -f4 <<< "$SHADLINE")"

		if grep -qi "$SHADNAM" "$SHADERREPOBLOCKLIST"; then
			echo FALSE
		else
			echo TRUE
		fi

		echo "$SHADURL"
		echo "$SHADNAM"
		echo "$SHADAUT"
		echo "$SHADDES"
	done < "$SHADREPOLIST" | \
	"$YAD" --f1-action="$F1ACTION" --image "$SHOWPIC" --image-on-top --window-icon="$STLICON" --center "$WINDECO" --list --checklist --column="$GUI_USE" --column="$GUI_URL" --column="$GUI_NAME" --column="$GUI_AUTH" --column="$GUI_DESC" --separator="" --print-column="3" \
	--text="$(spanFont "$(strFix "$GUI_SHADREPDIALOG" "$SGNAID")" "H")" --title="$TITLE" --button="$BUT_CAN:0" --button="$BUT_SELECT:2" "$GEOM")"
	case $? in
		0)	{
				writelog "INFO" "${FUNCNAME[0]} - Selected '$BUT_CAN' - Cancelling selection"
			}
		;;
		2)	{
				writelog "INFO" "${FUNCNAME[0]} - Selected '$BUT_SELECT' - Saving Selection"

				if [ -z "$REPOPICKS" ]; then
					writelog "INFO" "${FUNCNAME[0]} - Nothing selected"
					REPOPICKS=""
				else
					rm "$SHADERREPOBLOCKLIST" 2>/dev/null
					while read -r SHADLINE; do
						SHADNAM="$(cut -d ';' -f2 <<< "$SHADLINE")"
						if ! grep -q "$SHADNAM" <<< "$REPOPICKS"; then
							echo "${SHADNAM,,}" >> "$SHADERREPOBLOCKLIST"
						fi
					done < "$SHADREPOLIST"
					touch "$SHADERREPOBLOCKLIST"
					sort -u "$SHADERREPOBLOCKLIST" -o "$SHADERREPOBLOCKLIST"
				fi
			}
		;;
	esac
}

function setFullGameExePath {
	if [ "$USECUSTOMCMD" -eq 1 ] && [ -f "$CUSTOMCMD" ]; then
		FGEP="${CUSTOMCMD%/*}"
		writelog "INFO" "${FUNCNAME[0]} - Using the directory '$FGEP' of the used custom command as absolute game exe path"
		export "$1"="$FGEP"
	else
		loadCfg "$GEMETA/$AID.conf" X
		if [ -n "$EXECUTABLE" ] && grep -q "\\\\" <<< "$EXECUTABLE"; then
			RELEX="${EXECUTABLE//\\//}"
			FGEP="${EFD}/${RELEX%/*}"
			if [ ! -d "$FGEP" ] && [ -d "$EFD" ]; then
				if grep -q "/" <<< "${RELEX%/*}"; then
					FGEP="${EFD}"
					while read -r subdir; do
						FGEP="$(find "$FGEP" -iname "$subdir")"
					done <<< "$(tr '/' '\n' <<< "${RELEX%/*}")"
				else
					FGEP="$(find "${EFD}" -iname "${RELEX%/*}")"
				fi
			fi
			
			if [ -d "$FGEP" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Using '$FGEP' as absolute game exe path"
				export "$1"="$FGEP"	
			fi
		else
			writelog "INFO" "${FUNCNAME[0]} - Using the base game directory '$EFD' as absolute game exe path"
			export "$1"="$EFD"
		fi
	fi
}

function setShaderDest {
	if [ -n "$(GETALTEXEPATH)" ]; then
		SHADDESTDIR="$(GETALTEXEPATH)"
		writelog "INFO" "${FUNCNAME[0]} - Overriding SHADDESTDIR to '$SHADDESTDIR' because ALTEXEPATH is set to '$ALTEXEPATH'"
	fi

	if [ -z "$SHADDESTDIR" ]; then
		if [ -z "$1" ]; then		
			if [ ! -d "$SHADDESTDIR" ]; then
				resetAID "last"
				if [ -f "$LASTRUN" ] && grep -q "$AID" "$LASTRUN"; then
					PREVEFD="$(grep "^PREVEFD" "$LASTRUN" | cut -d '=' -f2)"
					if [ -d "${PREVEFD//\"/}" ]; then
						 SHADDESTDIR="${PREVEFD//\"/}"
					fi
				fi
			fi
		else
			if [ "$1" == "last" ]; then
				resetAID "last"
				if [ -f "$LASTRUN" ] && grep -q "$AID" "$LASTRUN"; then
					PREVEFD="$(grep "^PREVEFD" "$LASTRUN" | cut -d '=' -f2)"
					if [ -d "${PREVEFD//\"/}" ]; then
						 SHADDESTDIR="${PREVEFD//\"/}"
					fi
				else
					notiShow "$NOTY_NOAIDNOPREV"
				fi
			else
				if [ -f "$1" ]; then
					SHADDESTDIR="$(dirname "$1")"
				else 
					SHADDESTDIR="$1"
				fi
			fi
		fi

		if [ -n "$SHADDESTDIR" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Using Shader destination directory '$SHADDESTDIR'"
		fi
	fi	
}

function disableThisGameShaderRepo {
	RMREP="$1"
	if [ -n "$2" ]; then
		SHADDESTDIR="$2"
	else
		setShaderDest
	fi

	if [ -z "$RSDSTS" ]; then
		RSDST="$SHADDESTDIR/$RSSUB"
		RSDSTS="$RSDST/Shaders"
		RSDSTT="$RSDST/Textures"
		RSDSTE="$RSDST/enabled"
	fi

	if [ -n "$RMREP" ] && [ -f "$RSDSTE/$RMREP" ]; then
		notiShow "$(strFix "$NOTY_SHADDIS" "$RMREP")"

		# removed disabled shaders
		if [ -d "$RSDSTS" ]; then
			while read -r syml; do
				if [[ "$(readlink "$syml")" =~ $RMREP ]]; then
					writelog "INFO" "${FUNCNAME[0]} - Removing shader symlink '$syml' from deactivated repo '$RMREP'" "X" "$SHADLOG"
					rm "$syml"
				fi
			done <<< "$(find -L "$RSDSTS")"
		fi
		# removed disabled textures
		if [ -d "$RSDSTT" ]; then
			while read -r syml; do
				if [[ "$(readlink "$syml")" =~ $RMREP ]]; then
					writelog "INFO" "${FUNCNAME[0]} - Removing texture symlink '$syml' from deactivated repo '$RMREP'" "X" "$SHADLOG"
					rm "$syml"
				fi
			done <<< "$(find -L "$RSDSTT")"
		fi
		rm "$RSDSTE/$RMREP" 
	fi
}

function enableThisGameShaderRepo {
	SELREPO="$1"
	REPDIR="$STLSHADDIR/$SELREPO"

	if grep -q "^${SELREPO}$" "$SHADERREPOBLOCKLIST"; then
		writelog "SKIP" "${FUNCNAME[0]} - The selected repo '$SELREPO' is in the block list '$SHADERREPOBLOCKLIST'" "X" "$SHADLOG"
	else
		if [ -n "$2" ]; then
			SHADDESTDIR="$2"
		else
			setShaderDest
		fi

		if [ ! -d "$REPDIR" ]; then
			writelog "SKIP" "${FUNCNAME[0]} - The directory '$REPDIR' for the selected repo '$SELREPO' does not exist" "X" "$SHADLOG"
		else
			if [ -z "$RSDSTS" ]; then
				RSDST="$SHADDESTDIR/$RSSUB"
				RSDSTS="$RSDST/Shaders"
				RSDSTT="$RSDST/Textures"
				RSDSTE="$RSDST/enabled"

				mkProjDir "$RSDSTS"
				mkProjDir "$RSDSTT"
				mkProjDir "$RSDSTE"
			fi

			if [ -f "$RSDSTE/$SELREPO" ]; then
				writelog "SKIP" "${FUNCNAME[0]} - Repo '$SELREPO' is already activated for the game" "X" "$SHADLOG"
			else
				notiShow "$(strFix "$NOTY_SHADENA" "$SELREPO")"
				# updating shaders
				writelog "INFO" "${FUNCNAME[0]} - Updating shaders for activated repo '$SELREPO'" "X" "$SHADLOG"
				SHADERSRC="$(find "$REPDIR" -type d -iname "Shaders")"
				if [ -n "$SHADERSRC" ]; then
					while read -r shaderfile; do
						writelog "INFO" "${FUNCNAME[0]} - Creating symlink '$RSDSTS/${shaderfile##*/}' for shader '$shaderfile'" "X" "$SHADLOG"
						ln -s "$shaderfile" "$RSDSTS/${shaderfile##*/}" 2>/dev/null
					done <<< "$(find "$SHADERSRC" -mindepth 1 -maxdepth 1)"
					touch "$RSDSTE/$SELREPO"
				fi

				# updating textures
				writelog "INFO" "${FUNCNAME[0]} - Updating textures for activated repo '$SELREPO'" "X" "$SHADLOG"
				TEXTURESRC="$(find "$REPDIR" -type d -iname "Textures")"			
				if [ -n "$TEXTURESRC" ]; then
					while read -r texfile; do
						writelog "INFO" "${FUNCNAME[0]} - Creating symlink '$RSDSTT/${texfile##*/}' for texture '$texfile'" "X" "$SHADLOG"
						ln -s "$texfile" "$RSDSTT/${texfile##*/}" 2>/dev/null
					done <<< "$(find "$TEXTURESRC" -mindepth 1 -maxdepth 1)"		
				fi
			fi
		fi
	fi
}

function GameShaderDialog {
	touch "$SHADERREPOBLOCKLIST"

	setShaderDest "$1"

	RSDST="$SHADDESTDIR/$RSSUB"
	RSDSTS="$RSDST/Shaders"
	RSDSTT="$RSDST/Textures"
	RSDSTE="$RSDST/enabled"

	if [ -f "$SHADLOG" ]; then
		rm "$SHADLOG" 2>/dev/null
	fi

	if [ "$SHADDESTDIR" != "$NON" ]; then
		mkProjDir "$RSDSTS"
		mkProjDir "$RSDSTT"
		mkProjDir "$RSDSTE"
	fi

	if [ -d "$RSDST" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Opening Shader Selection Dialog for dir '$RSDST'"

		SHADDLLAST="$STLSHADDIR/lastdl.txt"
		MAXAGE=1440

		if [ ! -f "$SHADDLLAST" ] || test "$(find "$SHADDLLAST" -mmin +"$MAXAGE")"; then
			StatusWindow "$GUI_DLSHADER" "dlShaders" "DownloadShadersStatus"
			echo "$(date) - ${FUNCNAME[0]}" > "$SHADDLLAST"
		fi

		export CURWIKI="$PPW/Shader-Management"
		TITLE="${PROGNAME}-Shader"
		pollWinRes "$TITLE"

		setShowPic

		unset AVAILREPOS
		unset SELREPOS
		unset UNSELREPOS

		# appending a ';' to the reponames to prevent cutting the wrong, similar filename
		mapfile -d "|" -t -O "${#AVAILREPOS[@]}" AVAILREPOS <<< "$(find "$STLSHADDIR" -mindepth 1 -maxdepth 1 -not -empty -type d -printf "%p;\n")"

		SELREPOS="$(while read -r repo; do REPONAME="${repo##*/}"; if [ -f "$RSDSTE/${REPONAME//;}" ]; then	echo TRUE ; echo "${REPONAME//;}"; else echo FALSE ; echo "${REPONAME//;}" ;fi ; done <<< "$(printf "%s\n" "${AVAILREPOS[@]}")" | \
		"$YAD" --f1-action="$F1ACTION" --image "$SHOWPIC" --image-on-top --window-icon="$STLICON" --center "$WINDECO" --list --checklist --column="$GUI_ADD" --column=Shader-Repo --separator=" " --print-column="2" \
		--text="$(spanFont "$(strFix "$GUI_SHADERDIALOG" "${RSDST##*/}")" "H")" --title="$TITLE" "$GEOM")"
		case $? in
			0)  {
					UNSELREPO=( "${AVAILREPOS[@]}" )
									
					if [ -n "${SELREPOS[0]}" ]; then
						writelog "INFO" "${FUNCNAME[0]} - At least one repo was enabled, so automatically enabling required repo '$RSSUB'" "X" "$SHADLOG"
						SELREPOS=( "${SELREPOS[@]}" "$RSSUB" )

						writelog "INFO" "${FUNCNAME[0]} - Activating shaders for enabled repos" "X" "$SHADLOG"

						while read -r SELREPO; do
							writelog "INFO" "${FUNCNAME[0]} - Enabled: $SELREPO" "X" "$SHADLOG"
							unset REPDIR
							enableThisGameShaderRepo "$SELREPO"
							REPDIR="$STLSHADDIR/${SELREPO};"
							UNSELREPO=( "${UNSELREPO[@]/$REPDIR}" )

						done <<< "$(printf "%s\n" "${SELREPOS[@]}")"
					fi

					writelog "INFO" "${FUNCNAME[0]} - Deactivating shaders for disabled repos" "X" "$SHADLOG"

					while read -r UNSEL; do
						if [ -n "$UNSEL" ] && [ "$UNSEL" != ";" ]; then
							unset RMREP
							RMREP="${UNSEL//;}"
							RMREP="${RMREP##*/}"
							if [ "$RMREP" != "$RSSUB" ]; then
								writelog "INFO" "${FUNCNAME[0]} - Disabled: $RMREP" "X" "$SHADLOG"
								disableThisGameShaderRepo "$RMREP"
							fi
						fi
					done <<< "$(printf "%s\n" "${UNSELREPO[@]}")"

					if [ -z "${SELREPOS[0]}" ] && [ -f "$RSDSTE/$RSSUB" ]; then
						writelog "INFO" "${FUNCNAME[0]} - No repo was enabled, so also disabling the repo '$RSSUB'" "X" "$SHADLOG"
						disableThisGameShaderRepo "$RSSUB"
					fi

					writelog "INFO" "${FUNCNAME[0]} - Deactivating shaders for blocked repos" "X" "$SHADLOG"
					while read -r BLOCKREP; do
						disableThisGameShaderRepo "$BLOCKREP"
					done < "$SHADERREPOBLOCKLIST"
				}
			;;
			1)  writelog "INFO" "${FUNCNAME[0]} - Selected CANCEL"
			;;
		esac
	else
		writelog "SKIP" "${FUNCNAME[0]} - Dest Dir '$SHADDESTDIR' does not exist and could not be created - skipping"
		if [ -z "$SHADDESTDIR" ]; then
			SHADDESTDIR="$NON"
		fi 
		notiShow "$(strFix "$NOTY_MISSDIR" "$SHADDESTDIR")"
	fi

	if [ -n "$2" ];	then "$2";	fi
}

function getArch {
	# maybe remove reduntant lines later
	if [ "$(file "$1" | grep -c "PE32 ")" -eq 1 ]; then
		writelog "INFO" "${FUNCNAME[0]} - Architecture for '$1' is 32bit"
		echo "32"
	elif [ "$(file "$1" | grep -c "PE32+ ")" -eq 1 ]; then
		writelog "INFO" "${FUNCNAME[0]} - Architecture for '$1' is 64bit"
		echo "64"
	else
		if [ "$(find "$(dirname "$1")" -name "*.exe" | wc -l)" -ge 0 ]; then
			TESTEXE="$(find "$(dirname "$1")" -name "*.exe" | head -n1)"
			if [ "$(file "$TESTEXE" | grep -c "PE32 ")" -eq 1 ]; then
				writelog "INFO" "${FUNCNAME[0]} - Architecture for bundled '$TESTEXE' for '$1' is 32bit"
				echo "32"
			elif [ "$(file "$TESTEXE" | grep -c "PE32+ ")" -eq 1 ]; then
				writelog "INFO" "${FUNCNAME[0]} - Architecture for bundled '$TESTEXE' for '$1' is 64bit"
				echo "64"
			fi
		elif [ "$(find "$(dirname "$1")" -name "*.dll" | wc -l)" -ge 0 ]; then
			TESTDLL="$(find "$(dirname "$1")" -name "*.dll" | head -n1)"
			if [ "$(file "$TESTDLL" | grep -c "PE32 ")" -eq 1 ]; then
				writelog "INFO" "${FUNCNAME[0]} - Architecture for bundled '$TESTDLL' for '$1' is 32bit"
				echo "32"
			elif [ "$(file "$TESTDLL" | grep -c "PE32+ ")" -eq 1 ]; then
				writelog "INFO" "${FUNCNAME[0]} - Architecture for bundled '$TESTDLL' for '$1' is 64bit"
				echo "64"
			fi
		else
			writelog "SKIP" "${FUNCNAME[0]} - Could not detect architecture for '$1' directly or indirectly"
		fi
	fi
}

function chooseShaders {
	if [ "$CHOOSESHADERS" -eq 1 ]; then
		setShadDestDir
		writelog "INFO" "${FUNCNAME[0]} - Opening Shader Menu - shader destination path is '$SHADDESTDIR'"
		GameShaderDialog "$SHADDESTDIR"
	fi
}

function installRSdll {
	if [ ! -f "$INSTDESTDIR/$1" ] || [ "$1" == "F" ]; then
		if [ -n "$2" ] && [ "$2" -eq 1 ]; then
			writelog "SKIP" "${FUNCNAME[0]} - Skipping installation of $1 because 'NOD3D9' is enabled"
		else
			if [ ! -f "$RESHADESRCDIR/$3" ]; then
				writelog "SKIP" "${FUNCNAME[0]} - Sourcefile '$RESHADESRCDIR/$3' missing - skipping this file" 
			else
				cp "$RESHADESRCDIR/$3" "$INSTDESTDIR/$1" >/dev/null 2>/dev/null
				echo "$1" >> "$INSTDESTDIR/$RSTXT"
				sort "$INSTDESTDIR/$RSTXT" -u -o "$INSTDESTDIR/$RSTXT"
				writelog "INFO" "${FUNCNAME[0]} - Copied '$RESHADESRCDIR/$3' to '$INSTDESTDIR/$1'" 
			fi
		fi
	else
		if [ "$RESHADEUPDATE" -eq 0 ]; then
			writelog "SKIP" "${FUNCNAME[0]} - Destfile '$INSTDESTDIR/$1' already exists, but not checking the installed version, because RESHADEUPDATE is '$RESHADEUPDATE'" 
		else
			if grep -q "$RSVERS" <<< "$(strings "$INSTDESTDIR/$1" | grep "^Initializing")"; then
				writelog "SKIP" "${FUNCNAME[0]} - Destfile '$INSTDESTDIR/$1' already exists in the same version '$RSVERS' - skipping this file" 
			else
				writelog "INFO" "${FUNCNAME[0]} - Destfile '$INSTDESTDIR/$1' already exists, but has a different version - updating"
				cp "$RESHADESRCDIR/$3" "$INSTDESTDIR/$1" >/dev/null 2>/dev/null
			fi
		fi
	fi
}

# install reshade:
function installReshade {
	if [ "$INSTALL_RESHADE" -eq 1 ]; then

		prepareReshadeFiles
		setShadDestDir

		if [ -n "$(GETALTEXEPATH)" ]; then
			INSTDESTDIR="$(GETALTEXEPATH)"
		else
			INSTDESTDIR="$SHADDESTDIR"
		fi

		function maybedrop { # TODO remove?
		# checking for previous dll conficts between $D3D47 and $RS_D9_DEST
		if [ -f "$INSTDESTDIR/${RS_DX_DEST//.dll/.log}" ]; then
			if grep -q "Another ${RESH} instance was already loaded" "$INSTDESTDIR/${RS_DX_DEST//.dll/.log}"; then
				writelog "INFO" "${FUNCNAME[0]} - Found $RS_DX_DEST conflict with $RS_D9_DEST"
				if [ -f "$INSTDESTDIR/$RS_D9_DEST" ]; then
					writelog "INFO" "${FUNCNAME[0]} - Removing $RS_D9_DEST"
					rm "$INSTDESTDIR/$RS_D9_DEST"
				else
					writelog "SKIP" "${FUNCNAME[0]} - $RS_D9_DEST not found"
				fi
				
				if [ -z "$NOD3D9" ]; then
					writelog "INFO" "${FUNCNAME[0]} - Blocking re-installation of '$RS_D9_DEST' by setting NOD3D9=1 in '$STLGAMECFG'"
					updateConfigEntry "NOD3D9" "1" "$STLGAMECFG"
					export NOD3D9=1
				fi
			else
				writelog "INFO" "${FUNCNAME[0]} - No conflict found in old logfile ${RS_DX_DEST//.dll/.log}"
			fi				
		else
			writelog "INFO" "${FUNCNAME[0]} - No old logfile ${RS_DX_DEST//.dll/.log} found"
		fi
		}

		if [ -n "$ARCHALTEXE" ] && [[ ! "$ARCHALTEXE" =~ ${DUMMYBIN}$ ]]; then
			CHARCH="$ARCHALTEXE"
		else
			CHARCH="$GP"
		fi

		if [ -d "$INSTDESTDIR" ]; then
			#32bit:
			if [ "$(getArch "$CHARCH")" == "32" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Installing 32bit ${RESH} as '$CHARCH' is 32bit" 
				#d3d47
				installd3d47dll "$D3D47_32" "$INSTDESTDIR"
				#dxgi:
				installRSdll "$RS_DX_DEST" "0" "$RS_32"
				#d3d9:
				installRSdll "$RS_D9_DEST" "$NOD3D9" "$RS_32"

			# 64bit:
			elif [ "$(getArch "$CHARCH")" == "64" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Installing 64bit ${RESH} as '$CHARCH' is 64bit" 
				#d3d47
				installd3d47dll "$D3D47_64" "$INSTDESTDIR"
				#dxgi:
				installRSdll "$RS_DX_DEST" "0" "$RS_64"
				#d3d9:
				installRSdll "$RS_D9_DEST" "$NOD3D9" "$RS_64"
			else
				writelog "SKIP" "${FUNCNAME[0]} - ERROR in ${RESH} installation - no file information detected for '$CHARCH' or any 'neighbor file' - setting USERESHADE=0 for this session"
				export USERESHADE=0
			fi
		else
			writelog "SKIP" "${FUNCNAME[0]} - INSTDESTDIR '$INSTDESTDIR' not found" 
		fi
	fi
}

function installDepth3DReshade {
	SHADERPOOL="depth3d"
	
	if [ "$RESHADE_DEPTH3D" -eq 1 ]; then
		StatusWindow "$GUI_DLSHADER" "dlShaders $SHADERPOOL" "DownloadCustomProtonStatus"
		setShadDestDir
		enableThisGameShaderRepo "$SHADERPOOL"
	fi
}

function checkReshade {
	setShadDestDir
	RSLIST="$SHADDESTDIR/$RSTXT"
	RSOLIST="${RSLIST}_off"
	FRSINI="$SHADDESTDIR/$RSINI"
	FRSOINI="$SHADDESTDIR/${RSINI}_off"

	# TODO remove later:
	RSENABLED="${RESH}-${PROGNAME,,}-enabled.txt"
	RSDISABLED="${RESH}-${PROGNAME,,}-disabled.txt"
	# this doesn't cover all migration constellations, but better than nothing
	if [ "$USERESHADE" -eq 1 ] && [ -f "$SHADDESTDIR/$RSENABLED" ]; then
		mv "$SHADDESTDIR/$RSENABLED" "$RSLIST"
		if [ -f "$SHADDESTDIR/$RS_DX_DEST" ] && grep -q "$RESH" "$SHADDESTDIR/$RS_DX_DEST"; then
			echo "$RS_DX_DEST" >> "$RSLIST"
		fi

		if [ -f "$SHADDESTDIR/$RS_D9_DEST" ] && grep -q "$RESH" "$SHADDESTDIR/$RS_D9_DEST"; then
			echo "$RS_D9_DEST" >> "$RSLIST"
		fi
		sort "$RSLIST" -u -o "$RSLIST"
	elif [ "$USERESHADE" -eq 1 ] && [ -f "$SHADDESTDIR/$RSDISABLED" ]; then
		mv "$SHADDESTDIR/$RSDISABLED" "$RSOLIST"
		if [ -f "$SHADDESTDIR/$RS_DX_DEST" ] && grep -q "$RESH" "$SHADDESTDIR/$RS_DX_DEST"; then
			echo "$RS_DX_DEST" >> "$RSOLIST"
		fi

		if [ -f "$SHADDESTDIR/$RS_D9_DEST" ] && grep -q "$RESH" "$SHADDESTDIR/$RS_D9_DEST"; then
			echo "$RS_D9_DEST" >> "$RSOLIST"
		fi
		sort "$RSOLIST" -u -o "$RSOLIST"
	fi
	#
	
	if [ "$USERESHADE" -eq 1 ]; then
		if [ -f "$FRSINI" ]; then
			if grep -q "EffectSearchPaths=.\$RSSUB\Shaders" "$FRSINI"; then
				writelog "SKIP" "${FUNCNAME[0]} - Already have '$FRSINI' with default paths pointing to '$RSSUB'"
			else
				writelog "SKIP" "${FUNCNAME[0]} - Found a '$FRSINI' without default paths pointing to '$RSSUB' - not touching it"
			fi
		else
			if [ -f "$FRSOINI" ] && grep -q "EffectSearchPaths=.*$RSSUB.*Shaders" "$FRSOINI"; then
				writelog "INFO" "${FUNCNAME[0]} - Re-enabling previously disabled '$FRSOINI'"
				mv "$FRSOINI" "$FRSINI"
			else
				writelog "INFO" "${FUNCNAME[0]} - Creating initial '$FRSINI' with default paths pointing to '$RSSUB'"
				{
					echo "[GENERAL]"
					echo "EffectSearchPaths=.\\$RSSUB\Shaders"
					echo "TextureSearchPaths=.\\$RSSUB\Textures"
					echo "PreprocessorDefinitions=RESHADE_DEPTH_LINEARIZATION_FAR_PLANE=1000.0,RESHADE_DEPTH_INPUT_IS_UPSIDE_DOWN=0,RESHADE_DEPTH_INPUT_IS_REVERSED=1,RESHADE_DEPTH_INPUT_IS_LOGARITHMIC=0"
				} > "$FRSINI"
			fi
		fi

#XXXXXXXXXXXXX
		if [ "$USESPECIALK" -eq 1 ]; then
			writelog "INFO" "${FUNCNAME[0]} - Both '$SPEK' and '$RESH' are enabled." "E"
			writelog "INFO" "${FUNCNAME[0]} - Unfortunately the game currently crashes using Proton when both are enabled"
			writelog "INFO" "${FUNCNAME[0]} - therefore the $RESH install to the $SPEK directory redirect is disabled" "E"

#			writelog "INFO" "${FUNCNAME[0]} - Using ${RESH} and $SPEK together"
#			mkProjDir "$SHADDESTDIR"
#			if [ ! -f "$SHADDESTDIR/$RS_64" ]; then
#				writelog "INFO" "${FUNCNAME[0]} - Copying '$RESHADESRCDIR/$RS_64' and friends to '$SHADDESTDIR'"
#				cp "$RESHADESRCDIR/$RS_64" "$SHADDESTDIR"
#				cp "$RESHADESRCDIR/$RS_32" "$SHADDESTDIR"
#				cp "$RESHADESRCDIR/${RS_64//.dll/.json}" "$SHADDESTDIR"
#				cp "$RESHADESRCDIR/${RS_32//.dll/.json}" "$SHADDESTDIR"
#			else
#				writelog "SKIP" "${FUNCNAME[0]} - Already have '$RS_64' in '$SHADDESTDIR'"
#			fi
		fi

#		else
			if [ -f "$RSOLIST" ]; then
				writelog "INFO" "${FUNCNAME[0]} - ${RESH} has been disabled previously using '${PROGNAME,,}' - enabling it now"
				while read -r rsdll; do
					if [ -f "$SHADDESTDIR/${rsdll}_off" ]; then
						mv "$SHADDESTDIR/${rsdll}_off" "$SHADDESTDIR/$rsdll"
					else
						writelog "WARN" "${FUNCNAME[0]} - '$SHADDESTDIR/${rsdll}_off' was supposed to be reenabled, but the file is missing"
					fi
				done < "$SHADDESTDIR/${RSTXT}_off"
				mv "$RSOLIST" "$RSLIST"
			fi

			if [ ! -f "$SHADDESTDIR/$D3D47" ]; then
				writelog "INFO" "${FUNCNAME[0]} - USERESHADE is '$USERESHADE' - looks like ${RESH} is not yet installed in '$SHADDESTDIR' - installing because USERESHADE is enabled"
				INSTALL_RESHADE=1 installReshade
			fi

			if [ -f "$FRSINI" ] && [ ! -f "$RSLIST" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Looks like ${RESH} was installed previously using '${PROGNAME,,}' without creating '$RSLIST' - recreating it now"
				INSTALL_RESHADE=1 installReshade F
			fi

			writelog "INFO" "${FUNCNAME[0]} - Setting WINEDLLOVERRIDES for ${RESH}: dxgi=n,b;d3d9=n,b;${D3D47//.dll}=n,b"
			export WINEDLLOVERRIDES="$WINEDLLOVERRIDES;dxgi=n,b;d3d9=n,b;${D3D47//.dll}=n,b"
#		fi
	else	
		if [ -f "$FRSINI" ]; then
			writelog "INFO" "${FUNCNAME[0]} - ${RESH} has been disabled by the user, so renaming '$FRSINI' to '$FRSOINI'"
			mv "$FRSINI" "$FRSOINI"
		fi

		if [ -f "$RSLIST" ]; then
			writelog "INFO" "${FUNCNAME[0]} - ${RESH} has been installed previously with '${PROGNAME,,}' - disabling it now"
			while read -r rsdll; do
				if [ -f "$SHADDESTDIR/${rsdll}" ]; then
					mv "$SHADDESTDIR/$rsdll" "$SHADDESTDIR/${rsdll}_off"
				else
					writelog "WARN" "${FUNCNAME[0]} - '$SHADDESTDIR/${rsdll}' was supposed to be disabled, but the file is already missing"
				fi
			done < "$RSLIST"
			mv "$RSLIST" "$RSOLIST"
		fi
		
		if [ "$USESPECIALK" -eq 0 ]; then
			if [ -f "$SHADDESTDIR/$RS_DX_DEST" ] && grep -q "$RESH" "$SHADDESTDIR/$RS_DX_DEST"; then
				writelog "WARN" "${FUNCNAME[0]} - Found unknown '$RESH' dll '$RS_DX_DEST' in '$SHADDESTDIR'"
			fi

			if [ -f "$SHADDESTDIR/$RS_D9_DEST" ] && grep -q "$RESH" "$SHADDESTDIR/$RS_D9_DEST"; then
				writelog "WARN" "${FUNCNAME[0]} - Found unknown '$RESH' dll '$RS_D9_DEST' in '$SHADDESTDIR'"
			fi
		fi
	fi
}

function extSpek {
	SRCARCH="$1"
	SPEXT64="$SPEKDLDIR/$SPEKVERS/${SPEK}64.dll"

	if [ -f "$SPEXT64" ]; then
		writelog "SKIP" "${FUNCNAME[0]} - Already have '$SPEXT64' - skipping extraction" "E"
	else
		if [ ! -f "$SRCARCH" ]; then
			SRCARCH="${SRCARCH//lK/l_K}"
		fi
		if [ -f "$SRCARCH" ]; then
			if [ -x "$(command -v "$SEVZA")" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Extracting '$SRCARCH' to '$SPEKDLDIR/$SPEKVERS'" "E"
				"$SEVZA" x "$SRCARCH" -o"$SPEKDLDIR/$SPEKVERS" 2>/dev/null
			else
				writelog "SKIP" "${FUNCNAME[0]} - Can't extract '$SRCARCH', because '$SEVZA' wasn't found!" "E"
			fi
		fi
	fi
}

function dlSpecialK {

	if [ -n "$1" ]; then
		SPEKVERS="$1"
	fi

	if [ "$SPEKVERS" == "test" ]; then
		SPEKARC="${SPEK}-${SPEKVERS}.7z"
	else
		SPEKARC="${SPEK}.7z"
	fi
	mkProjDir "$SPEKDLDIR/$SPEKVERS"
	mkProjDir "$SPEKDLDIR/$DISC"
	SPEKDISCSRC="$SPEKDLDIR/$DISC/$SPEKARC"

	if [ -f "$SPEKDISCSRC" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Found the '$DISC' package under '$SPEKDISCSRC'" "E"
		if [ "$SPEKVERS" != "$DISC" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Continuing using that instead of '$SPEKVERS'" "E"
			SPEKVERS="$DISC"
		fi
	fi

	SPEKDL="$SPEKDLDIR/$SPEKVERS/$SPEKARC"
	SPEKDLURL="$SPEKURL/$SPEKARC"

	if [ "$SPEKVERS" == "old" ]; then
		SPEKDLURL="$SPEKOLDDLURL"
	fi

	if [ ! -f "$SPEKDL" ]; then
		if [ "$SPEKVERS" == "$DISC" ]; then
			if [ -f "${SPEKDL//lK/l_K}" ]; then
				SPEKDL="${SPEKDL//lK/l_K}"
				writelog "INFO" "${FUNCNAME[0]} - Already have the archive '$SPEKDL'" "E"
			else
				writelog "INFO" "${FUNCNAME[0]} - The $SPEKVERS package needs to be downloaded manually to '$SPEKDL'" "E"
			fi
		else
			notiShow "$(strFix "$NOTY_DLCUSTOMPROTON" "$SPEK")"
			dlCheck "$SPEKDLURL" "$SPEKDL" "X" "Downloading '$SPEKARC' from '$SPEKURL' to '$SPEKDLDIR'"
			extSpek "$SPEKDL"
		fi
	else
		writelog "INFO" "${FUNCNAME[0]} - Already have the archive '${SPEKDL}'" "E"
	fi
	
	if [ -f "$SPEKDL" ] && [ "$SPEKVERS" == "$DISC" ]; then
		extSpek "$SPEKDL"
	fi

	SPEK32SRC="$SPEKDLDIR/$SPEKVERS/${SPEK}32.dll"
	SPEK64SRC="$SPEKDLDIR/$SPEKVERS/${SPEK}64.dll"

	if [ -f "$SPEK32SRC" ]; then
		writelog "INFO" "${FUNCNAME[0]} - '$SPEK32SRC' is ready" "E"
	else
		writelog "SKIP" "${FUNCNAME[0]} - '$SPEK32SRC' is missing!" "E"
	fi

	if [ -f "$SPEK64SRC" ]; then
		writelog "INFO" "${FUNCNAME[0]} - '$SPEK64SRC' is ready" "E"
	else
		writelog "SKIP" "${FUNCNAME[0]} - '$SPEK64SRC' is missing!" "E"
	fi
}

function getSpecialKGameRenderApi {
	SPEKCOMP="$SPEKDLDIR/${SPEK}_compat.html"
	MAXAGE=1440
	if [ ! -f "$SPEKCOMP" ] || test "$(find "$SPEKCOMP" -mmin +"$MAXAGE")"; then
		dlCheck "$SPEKCOMPURL" "$SPEKCOMP" "X" "Downloading '$SPEKCOMP'"
	fi
	writelog "INFO" "${FUNCNAME[0]} - Searching Render Api for '$GN' in '$SPEKCOMP'"
	RAPI="$(sed -n "/id=\"Compatibility_list\"/,$ p" "$SPEKCOMP" | grep -A1 "${GN// /\*.\*}" | tail -n1 | cut -d '>' -f2 | cut -d '<' -f1)"
	if [ -n "$RAPI" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Found Render Api '$RAPI'"
		if [ "$RAPI" == "Direct3D 11" ]; then
			SPEKDST="$SPEKDDIR/$DXGI"
		elif [ "$RAPI" == "Direct3D 9" ]; then
			SPEKDST="$SPEKDDIR/$D3D9"
		elif [ "$RAPI" == "OpenGL" ]; then
			SPEKDST="$SPEKDDIR/$OGL32"
		else
			writelog "INFO" "${FUNCNAME[0]} - Unknown Render Api '$RAPI' - assuming 'Direct3D 11'"
			SPEKDST="$SPEKDDIR/$DXGI"
		fi
	else
		writelog "INFO" "${FUNCNAME[0]} - Could not find Render Api - assuming 'Direct3D 11'"
		SPEKDST="$SPEKDDIR/$DXGI"
	fi	
}

function prepareSpecialKReshade {
	if [ "$USERESHADE" -eq 1 ]; then
		writelog "INFO" "${FUNCNAME[0]} - Both '$SPEK' and '$RESH' are enabled." "E"
		writelog "INFO" "${FUNCNAME[0]} - Unfortunately the game currently crashes using Proton when both are enabled"
		writelog "INFO" "${FUNCNAME[0]} - therefore the auto-apply $RESH to the $SPEK config is not implemented" "E"
		# XXXXXXXXXXXXX
		# maybe later:
		# "[Import.ReShade64]"
		# "Architecture=x64"
		# "Role=ThirdParty"
		# "When=PlugIn"
		# "When=Early"
		# "Filename=C:\users\steamuser\Documents\My Mods\SpecialK\PlugIns\ThirdParty\ReShade\ReShade64.dll"
	fi
}

function prepareDiscordSpecialK {
	SPEKARC="${SPEK}.7z"
	SPEKDISCSRC="$SPEKDLDIR/$DISC/$SPEKARC"
	FOUNDNEWSPEC=0

	if [ "$SPEKVERS" != "$DISC" ]; then
		if [ -f "$SPEKDISCSRC" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Found the '$DISC' package under '$SPEKDISCSRC'" "E"
			writelog "INFO" "${FUNCNAME[0]} - Continuing using '$DISC' instead of '$SPEKVERS'" "E"
			SPEKVERS="$DISC"
		fi
		if [ -f "${SPEKDISCSRC//lK/l_K}" ]; then
			SPEKDISCSRC="${SPEKDISCSRC//lK/l_K}"	
			writelog "INFO" "${FUNCNAME[0]} - Found an archive with the a new name under '$SPEKDISCSRC' - using that" "E"
			SPEKVERS="$DISC"
			FOUNDNEWSPEC=1
		fi
	fi

	if [ "$SPEKVERS" == "$DISC" ]; then
		if [ "$FOUNDNEWSPEC" -eq 0 ] && [ -f "${SPEKDISCSRC//lK/l_K}" ]; then
			SPEKDISCSRC="${SPEKDISCSRC//lK/l_K}"
			writelog "INFO" "${FUNCNAME[0]} - Found an archive with the a new name under '$SPEKDISCSRC' - using that" "E"
		fi

		mkProjDir "$SPEKDLDIR/$DISC"

		if [ ! -f "$SPEKDISCSRC" ]; then
			writelog "INFO" "${FUNCNAME[0]} - The $SPEKVERS package needs to be downloaded manually to '$SPEKDL'" "E"
		else
			extSpek "$SPEKDISCSRC"
		fi

		UWI="UsingWINE"
		UWIT="$UWI=true"

		if [ -f "$SPEKDDIR/$DXGI" ]; then
			FOUNDRAPI="$SPEKDDIR/$DXGI"
		elif [ -f "$SPEKDDIR/$D3D9" ]; then
			FOUNDRAPI="$SPEKDDIR/$D3D9"
		elif [ -f "$SPEKDDIR/$OGL32" ]; then
			FOUNDRAPI="$SPEKDDIR/$D3D9"
		else
			getSpecialKGameRenderApi
			FOUNDRAPI="$SPEKDST"
		fi

		if [ -z "$SPEKINI" ]; then
			SPEKINI="${FOUNDRAPI//.dll/.ini}"
		fi
		
		COGE="Compatibility.General"

		if [ "$SPEKVERS" == "$DISC" ] && [ -n "$SPEKINI" ]; then
			if [ -f "$SPEKINI" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Found the ini file '$SPEKINI' - enabling '$UWI' function" "E"
				if grep -q "$UWIT" "$SPEKINI"; then
					writelog "SKIP" "${FUNCNAME[0]} - nothing to do - '$UWI' is already enabled" "E"
				elif grep -q "$UWI=false" "$SPEKINI"; then
					writelog "INFO" "${FUNCNAME[0]} - Enabling '$UWI' in the config" "E"
					sed "s:$UWI=false:$UWIT:" -i "$SPEKINI"
				else
					writelog "INFO" "${FUNCNAME[0]} - Adding a new entry '$UWI' in the ini, because it is missing" "E"
					if grep -q "$COGE" "$SPEKINI"; then
						sed "/\[$COGE\]/a $UWIT" -i "$SPEKINI"
					else
						sed "1 i $UWIT" -i "$SPEKINI"
						sed "1 i \[$COGE\]" -i "$SPEKINI"
					fi
				fi

			else
				writelog "INFO" "${FUNCNAME[0]} - Creating a minimal ini file '$SPEKINI' with enabled '$UWI' function" "E"
				{
					echo "[$COGE]"
					echo "$UWIT"
				} >> "$SPEKINI"
			fi
		fi
	fi	
}

function useSpecialK {
	function installSpekDll {
		SPEKSRC="$1"
		if [ -f "$SPEKDST" ] && [ "$(stat -c %s "$SPEKSRC")" -eq "$(stat -c %s "$SPEKDST")" ]; then
			writelog "SKIP" "${FUNCNAME[0]} - Nothing to update - '$SPEKDST' corresponds to '$SPEKSRC'" "E"
		else
			writelog "INFO" "${FUNCNAME[0]} - Installing '${SPEKSRC##*/}' as '$GP' is $2-bit" "E"
			cp "$SPEKSRC" "$SPEKDST"
			if [ -f "${SPEKSRC//dll/pdb}" ]; then
				SPEKPDB="${SPEKSRC##*/}"
				SPEKPDB="${SPEKPDB//dll/pdb}"
				writelog "INFO" "${FUNCNAME[0]} - Also installing debugging '$SPEKPDB'" "E"
				cp "${SPEKSRC//dll/pdb}" "$SPEKDDIR"
				echo "$SPEKDDIR/$SPEKPDB" >> "$SPEKENA"
			fi
		fi

		IPAK="vcrun2019-$3"
		if [ -f "$GPFX/${IPAK}_installed.txt" ]; then
			writelog "SKIP" "${FUNCNAME[0]} - Skipping '$IPAK' - already installed" "E"
		else
			installSteWoShPak "$IPAK" "$GPFX" "$RUNWINE"
			echo "$IPAK" > "$GPFX/${IPAK}_installed.txt"
		fi
		installd3d47dll "$4" "$SPEKDDIR"
	}

	function installSpekArchDll {
		if [ "$USECUSTOMCMD" -eq 1 ] && [ -f "$CUSTOMCMD" ]; then
			ARCHEXE="$CUSTOMCMD"
		else
			ARCHEXE="$GP"
		fi
		
		if [ "$(getArch "$ARCHEXE")" == "32" ]; then
			installSpekDll "$SPEK32SRC" "32" "x86" "$D3D47_32"
		elif [ "$(getArch "$ARCHEXE")" == "64" ]; then
			installSpekDll "$SPEK64SRC" "64" "x64" "$D3D47_64"
		else
			writelog "SKIP" "${FUNCNAME[0]} - Could not determine the architecture of '$GP' - not installing '$SPEK'" "E"
		fi
	}
	
	SPEKDDIR="$EFD"
	setFullGameExePath "SPEKDDIR"	
	SPEKENA="$SPEKDDIR/${SPEK}_enabled.txt"

	if [ "$USESPECIALK" -eq 1 ]; then
		REQDLL="api-ms-win-crt-string-l1-1-0.dll"
		if [ -d "$GPFX/$DRCW" ] && [ ! -f "$GPFX/$DRCW/system32/$REQDLL" ]; then # the directory check exists for skipping the warning if the pfx does not exist yet _(not nice, but )_ - PR if you care
			writelog "SKIP" "${FUNCNAME[0]} - '$SPEK' requires '$REQDLL', which is not available in the WINEPREFIX currently running with '$USEPROTON'" "E"
			notiShow "$(strFix "$NOTY_MISSDLL" "$SPEK" "$REQDLL" "$USEPROTON")"
		else
			prepareDiscordSpecialK
			prepareSpecialKReshade
			UPSPEK=1
			if [ -f "$SPEKENA" ]; then
				if [ "$SPEKVERS" != "$DISC" ]; then
					writelog "SKIP" "${FUNCNAME[0]} - ${SPEK} is already configured - nothing to do"
					UPSPEK=0
				else
					if grep -q "$(stat -c %s "$(grep -v "${SPEK}\|${D3D47}" "$SPEKENA")")" <<< "$(find . -name "$SPEK*.dll" -exec stat -c %s {} \;)"; then
						writelog "SKIP" "${FUNCNAME[0]} - The installed ${SPEKVERS} dll is identical to the available one"
						UPSPEK=0
					else
						writelog "INFO" "${FUNCNAME[0]} - Updating the '$SPEKVERS' dll"
						UPSPEK=1
					fi
				fi
			fi
			
			if [ "$UPSPEK" -eq 1 ]; then
				writelog "INFO" "${FUNCNAME[0]} - ${SPEK} is enabled - Installing dlls if required"
				dlSpecialK

				getSpecialKGameRenderApi
				
				#DISABLED XXXXXXXXX stable and testing versions are currently broken in proton - see wiki
				if [ "$SPEKVERS" == "test" ] || [ "$SPEKVERS" == "stable" ]; then
					writelog "INFO" "${FUNCNAME[0]} - Disabling '$SPEKDST', because '${SPEK}-${SPEKVERS}' is currently broken in Proton - see wiki"
					SPEKDST="${SPEKDST}_DISABLED"
				fi
				writelog "INFO" "${FUNCNAME[0]} - Using '$SPEKDST' as $SPEK destination dll"

				if [ -f "$GPFX/$DRCW/DirectX.log" ]; then
					writelog "SKIP" "${FUNCNAME[0]} - Skipping 'dxsetup' - already installed" "E"
				else
					notiShow "$(strFix "$NOTY_INSTSTART" "dxsetup")"
					installSteWoShPak "dxsetup" "$GPFX" "$RUNWINE"
					notiShow "$(strFix "$NOTY_INSTSTOP" "dxsetup")"
				fi

				echo "$SPEKDST" > "$SPEKENA"

				if [ -f "$SPEKDST" ]; then
					if [ "$SPEKVERS" != "$DISC" ]; then
						writelog "SKIP" "${FUNCNAME[0]} - Already have a '${SPEKDST##*/}' in '$SPEKDDIR' - not installing '$SPEK'" "E"
					else
						installSpekArchDll
					fi
				else
					installSpekArchDll
				fi
			fi
		fi
	else
		if [ -f "$SPEKENA" ]; then
			writelog "INFO" "${FUNCNAME[0]} - ${SPEK} was enabled before, removing existing $SPEK dlls"
			while read -r spekdll; do
				rm "$spekdll" 2>/dev/null
			done < "$SPEKENA"
			rm "$SPEKENA" 2>/dev/null
		fi
	fi
}

function getUsedVars {
	while read -r line; do 
		if grep -q -v "^#" <<< "$line"; then
			awk -F '=' '{print $1}' <<< "$line" 
		fi
	done <"$1"
}

function getScreenRes {
	function widthList {
		"$XRANDR" --verbose | grep "\*" -A2 | grep -oP 'width\K[^start]+'
	}

	function heightList {
		"$XRANDR" --verbose | grep "\*" -A2 | grep -oP 'height\K[^start]+'	
	}

	function getRes {
		if grep -q "^[0-9]*$" <<< "$FOUNDW" && grep -q "^[0-9]*$" <<< "$FOUNDH"; then
			FOUNDRES="${FOUNDW}x${FOUNDH}"
			writelog "INFO" "${FUNCNAME[0]} - Detected screen resolution '$FOUNDRES'" "X"
			echo "$FOUNDRES"
		else
			writelog "INFO" "${FUNCNAME[0]} - Screen resolution for width '$FOUNDW' and height '$FOUNDH' is invalid" "X"
		fi		
	}

	HCNT="$(wc -l <<< "$(widthList)")"
	if [ "$HCNT" -eq 1 ] || [ "$HCNT" -gt 2 ]; then
		FOUNDW="$(widthList | head -n1 | tr -dc '0-9')"
		FOUNDH="$(heightList | head -n1 | tr -dc '0-9')"
	else
		XCUT="$("$XRANDR" --listactivemonitors | grep -Eo "\+[1-9][[:digit:]]*\+" | grep -Eo "[[:digit:]]*")"
		MPOS="$("$XDO" getmouselocation --shell | head -n1 | cut -d '=' -f2)"
		if [ "$MPOS" -gt "$XCUT" ]; then
			FOUNDW="$(widthList | tail -n1 | tr -dc '0-9')"
			FOUNDH="$(heightList | tail -n1 | tr -dc '0-9')"
		else
			FOUNDW="$(widthList | head -n1 | tr -dc '0-9')"
			FOUNDH="$(heightList | head -n1 | tr -dc '0-9')"
		fi
	fi

	if [ "$1" == "w" ]; then
		if grep -q "^[0-9]*$" <<< "$FOUNDW"; then
			writelog "INFO" "${FUNCNAME[0]} - Found screen width '$FOUNDW'" "X"
			echo "$FOUNDW"
		else
			writelog "INFO" "${FUNCNAME[0]} - Screen width '$FOUNDW' is invalid" "X"
		fi
	elif [ "$1" == "h" ]; then
		if grep -q "^[0-9]*$" <<< "$FOUNDH"; then
			writelog "INFO" "${FUNCNAME[0]} - Found screen height '$FOUNDH'" "X"
			echo "$FOUNDH"
		else
			writelog "INFO" "${FUNCNAME[0]} - Screen height '$FOUNDH' is invalid" "X"
		fi		
	else
		getRes
	fi
}

function listScreenRes {
	while read -r lres; do
		echo "${lres%*[[:blank:]]}" | cut -d ' ' -f1
	done <<< "$("$XRANDR" --verbose | grep "+VSync$")" | sort -nur
}

function setInitWinXY {
	DEFRESSHM="$STLSHM/defres.txt"
	if [ -f "$DEFRESSHM" ] ; then
		loadCfg "$DEFRESSHM" X
		writelog "INFO" "${FUNCNAME[0]} - Using '${WINX}x${WINY}' from config '$DEFRESSHM'"
	else
		SCRW="$(getScreenRes w)"
		SCRH="$(getScreenRes h)"
		
		WINX=$(( SCRW * 3 / 4))
		WINY=$(( SCRH * 3 / 4))
		{
		echo "WINX=\"$WINX\""
		echo "WINY=\"$WINY\""
		} >> "$DEFRESSHM"
		writelog "INFO" "${FUNCNAME[0]} - Using '${WINX}x${WINY}' as default resolution for all windows without a configured resolution"
	fi
}

function setNewRes {
	SCREENRES="$(getScreenRes r)"
	if [ "$GAMESCREENRES" != "$NON" ] && [ "$GAMESCREENRES" != "$SCREENRES" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Setting screen resolution to '$GAMESCREENRES' using '$XRANDR'" "X"
		"$XRANDR" -s "$GAMESCREENRES"
	fi
}

function setPrevRes {
	if [ "$GAMESCREENRES" != "$NON" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Returning to previous screen resolution via '$XRANDR -s 0'" "X"
		"$XRANDR" -s 0
	fi
}

function customUserScriptStart {
	if [ -n "$USERSTART" ] && [[ ! "$USERSTART" =~ ${DUMMYBIN}$ ]]; then
		if [ -x "$USERSTART" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Starting custom user startscript '$USERSTART'"
			if [ "$USEWINE" -eq 0 ]; then
				"$USERSTART" "1" "$AID" "$GP" "$GPFX" &
			else
				"$USERSTART" "1" "$AID" "$GP" "$GWFX" &
			fi
		else
			writelog "SKIP" "${FUNCNAME[0]} - Custom user startscript '$USERSTART' not found or not executable"
		fi
	fi
}

function customUserScriptStop {
	if [ -n "$USERSTOP" ] && [[ ! "$USERSTOP" =~ ${DUMMYBIN}$ ]]; then
		if [ -x "$USERSTOP" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Starting custom user stopscript '$USERSTOP'"
			if [ "$USEWINE" -eq 0 ]; then
				"$USERSTOP" "0" "$AID" "$GP" "$GPFX" &
			else
				"$USERSTOP" "0" "$AID" "$GP" "$GWFX" &
			fi
		else
			writelog "SKIP" "${FUNCNAME[0]} - Custom user stopscript '$USERSTOP' not found or not executable"
		fi
	fi
}

function editorSkipped {
	if [ -z "$MAXASK" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Maximal editor requester count MAXASK not defined - skipping"
	else
		if ! grep -q "^ASKCNT" "$STLGAMECFG"; then
			SETASKCNT=1
			updateConfigEntry "ASKCNT" "$SETASKCNT" "$STLGAMECFG"
		else
			SETASKCNT=$(($(grep "ASKCNT" "$STLGAMECFG" | cut -d '=' -f2 | sed 's/\"//g') +1))
			updateConfigEntry "ASKCNT" "$SETASKCNT" "$STLGAMECFG"
		fi

		ASKCNT="$SETASKCNT"

		if [ "$ASKCNT" -ge "$MAXASK" ]; then
			notiShow "$(strFix "$NOTY_CANCELREQ1" "$MAXASK" "$GN" "$AID")"
			writelog "INFO" "${FUNCNAME[0]} - 'ASKCNT $ASKCNT' reached 'MAXASK $MAXASK' - disabling requester and resetting counter"
			updateConfigEntry "WAITEDITOR" "0" "$STLGAMECFG"
			updateConfigEntry "ASKCNT" "0" "$STLGAMECFG"
		elif [ "$ASKCNT" -lt "$MAXASK" ]; then
			notiShow "$(strFix "$NOTY_CANCELREQ2" "$ASKCNT" $((MAXASK - ASKCNT)) "$GN" "$AID")"
		fi
	fi
}

function askSettings {
	if ! grep -q "^WAITEDITOR=\"0\"" "$STLGAMECFG"; then
		# open editor requester 
		if grep -q "^WAITEDITOR" "$STLGAMECFG"; then
			WEDGAME="$(grep "^WAITEDITOR" "$STLGAMECFG"| cut -d '=' -f2)"
			WAITEDITOR="${WEDGAME//\"/}"
			writelog "INFO" "${FUNCNAME[0]} - Using game specific requester timeout '$WAITEDITOR'"
		fi

		writeAllAIMeta "$AID" &

		if [ "$WAITEDITOR" -gt 0 ]; then
			writelog "INFO" "${FUNCNAME[0]} - Opening Requester with timeout '$WAITEDITOR'"

			getAvailableCfgs
			fixShowGnAid
			export CURWIKI="$PPW/Wait-Requester"
			TITLE="${PROGNAME}-OpenSettings"
			pollWinRes "$TITLE"

			setShowPic

			if [ "$STARTMENU" == "Editor" ]; then
				REQQEST="$GUI_ASKOPENED"
				REQBUT="$BUT_EDITORMENU"
				LAUNCHMENU="EditorDialog"
			elif [ "$STARTMENU" == "Favorites" ]; then
				REQQEST="$GUI_ASKOPENFAV"
				REQBUT="$BUT_FAV"
				LAUNCHMENU="favoritesMenu"
			elif [ "$STARTMENU" == "Game" ]; then
				REQQEST="$GUI_ASKOPENGAM"
				REQBUT="$BUT_GM"	
				LAUNCHMENU="openGameMenu"
			else
				REQQEST="$GUI_ASKOPENSET"
				REQBUT="$BUT_MAINMENU"
				LAUNCHMENU="MainMenu"
			fi
		
			LAPL="$(getLaPl)"

			PDBROUT=""
			prepareProtonDBRating
			if [ -f "$PDBRASINF" ];then
				PDBROUT="$(cat "$PDBRASINF")"
			fi
	
			"$YAD" --f1-action="$F1ACTION" --image "$SHOWPIC" --image-on-top --window-icon="$STLICON" --form --center --on-top "$WINDECO" \
			--title="$TITLE" \
			--text="$(spanFont "$SGNAID - $REQQEST" "H")" \
			--field="<span font=\"italic\">$PDBROUT</span>":LBL \
			--field="<span font=\"italic\">$LAPL</span>":LBL \
			--field="<span font=\"italic\">(${#CfgFiles[@]} $GUI_EDITABLECFGS)</span>":LBL \
			--field="<span font=\"italic\">($GUI_EDITABLEGAMECFGS)</span>":LBL \
			--button="$REQBUT":0 \
			--button="$BUT_CAN":1 \
			--timeout="$WAITEDITOR" \
			--timeout-indicator=top \
			"$GEOM"

			case $? in
				0)  {
					"$LAUNCHMENU" "$AID"
					}
				;;
				1)  writelog "INFO" "${FUNCNAME[0]} - Selected CANCEL - Starting game without opening the $SETMENU"
					editorSkipped
				;;
				70) writelog "INFO" "${FUNCNAME[0]} - TIMEOUT - Starting game without opening the $SETMENU"
				;;
			esac
		fi
	fi
}

# create project dir $1 - no idea what the former arg2 was good for :)
function mkProjDir {
	mkdir -p "$1" 2>/dev/null >/dev/null
}

# create project dirs
function createProjectDirs {
	mkProjDir "$STLCFGDIR"
	mkProjDir "$STLLANGDIR"
	mkProjDir "$LOGDIRID"
	mkProjDir "$LOGDIRTI"
	mkProjDir "$STLPROTONIDLOGDIR"
	mkProjDir "$STLPROTONTILOGDIR"
	mkProjDir "$STLDXVKLOGDIR"
	mkProjDir "$STLWINELOGDIR"
	mkProjDir "$STLPVLOGDIR"
	mkProjDir "$STLGAMEDIRID"
	mkProjDir "$STLGAMEDIRTI"
	mkProjDir "$STLCATEGORYDIR"
	mkProjDir "$TWEAKDIR"
	mkProjDir "$USERTWEAKDIR"
	mkProjDir "$TWEAKCMDDIR"
	mkProjDir "$SBSTWEAKDIR"
	mkProjDir "$STLDLDIR"
	mkProjDir "$STLSHADDIR"
	mkProjDir "$STLVORTEXDIR"
	mkProjDir "${STLVORTEXDIR}/downloads"
	mkProjDir "$RESHADESRCDIR"
	mkProjDir "$CUSTPROTDLDIR"
	mkProjDir "$CUSTPROTEXTDIR"
	mkProjDir "$WINEDLDIR"
	mkProjDir "$WINEEXTDIR"
	mkProjDir "$STLGAMES"
	mkProjDir "$STLGDESKD"
	mkProjDir "$STLIDFD"
	mkProjDir "$STLGHEADD"
	mkProjDir "$STLGICO"
	mkProjDir "$STLGZIP"
	mkProjDir "$STLGPNG"
	mkProjDir "$STLAPPINFOIDDIR"
	mkProjDir "$CEDLDIR"
	mkProjDir "$HIDEDIR"
	mkProjDir "$VORTEXCOMPDATA"
	mkProjDir "$GEMETA"
	mkProjDir "$MO2COMPDATA"
	mkProjDir "$STLVKD3DLOGDIR"
	mkProjDir "$GEMETA"
	mkProjDir "$CUMETA"
	mkProjDir "$TIGEMETA"
	mkProjDir "$TICUMETA"
}

# add missing config entries to configfile $1 using seperator $2:
function updateConfigFile {

	if [ -z "$1" ]; then
		writelog "SKIP" "${FUNCNAME[0]} - Expected configfile as argument 1"
	else
		CFGFILE="$1"
		SEP="$2"

		# disable logging temporarily when the program just started (cosmetics)
		if [ -n "$3" ]; then
			ORGLOGLEVEL="$LOGLEVEL"
			LOGLEVEL=0
		fi

		if grep "$STLCFGDIR" "$CFGFILE" >/dev/null ; then
			writelog "UPDATE" "${FUNCNAME[0]} - Replacing '$STLCFGDIR' with 'STLCFGDIR' in '$CFGFILE'"
			sed "s:$STLCFGDIR:STLCFGDIR:g" -i "$CFGFILE"
		fi
		
		if grep -q "config Version: $PROGVERS" "$CFGFILE"; then
			writelog "SKIP" "${FUNCNAME[0]} - Config file '$CFGFILE' already at version '$PROGVERS'"
		else
			OLDVERS="$(grep "config Version" "$CFGFILE" | awk -F ': ' '{print $2}')"

			if [ -n "$OLDVERS" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Updating '$CFGFILE' from '$OLDVERS' to '$PROGVERS'"
				sed "s/config Version: $OLDVERS/config Version: $PROGVERS/" -i "$CFGFILE"
			else
				writelog "INFO" "${FUNCNAME[0]} - Updating '$CFGFILE' to '$PROGVERS'"
				sed "1s/^/##########################\n/" -i "$CFGFILE"
				sed "1s/^/## config Version: $PROGVERS\n/" -i "$CFGFILE"
			fi

			UPFROMTMPL=0
			if [ "$CFGFILE" == "$STLGAMECFG" ] && [ -f "$STLDEFGAMECFG" ]; then
				UPFROMTMPL=1
			fi

			while read -r RAWLINE; do
				LCAT="$(cut -d '=' -f1 <<< "$RAWLINE")"
				LVAL="$(cut -d '=' -f2 <<< "$RAWLINE")"
				if ! grep "^${LCAT}=" "$CFGFILE" >/dev/null ; then
					writelog "UPDATE" "${FUNCNAME[0]} - Entry '$LCAT' is missing in '$CFGFILE' - adding it now!"
					if [ "$UPFROMTMPL" -eq 1 ]; then
						OUTVAL="$(grep "^${LCAT}=" "$STLDEFGAMECFG" | cut -d '=' -f2)"
						OUTVAL="${OUTVAL//\"}"
					else
						if grep -q "\\$" <<< "$LVAL"; then
							if grep -q "WINX$\|WINY\|POSX\|POSY$" <<< "$LVAL"; then
								VARNAM=${LVAL//\$/DEF}
							else
								VARNAM=${LVAL//\$/}
#								VARNAM=${VARNAM//\\} # the formatting of the lines the incoming sed command reads needs to be 100% correct (f.e. no trainling whitespace)
#								so maybe rewrite it here later
							fi
							OUTVAL=${!VARNAM}
						else
							OUTVAL="$LVAL"
						fi
					fi
					OUTVAL="${OUTVAL//$STLCFGDIR/STLCFGDIR}"
					ADDLINE="$LCAT=\"$OUTVAL\""
					writelog "UPDATE" "${FUNCNAME[0]} - Adding line '$ADDLINE'"
					echo "$ADDLINE" >> "$CFGFILE"
				fi
			done <<< "$(sed -n "/#START$SEP/,/#END$SEP/p;/#END$SEP/q" "$0" | awk -F 'echo ' '{print $2}' | grep -v "\"##" | awk '{$1=$1};1' | sed '/^[[:space:]]*$/d'| sed 's/\"//g' | sed 's/=\\/=/g' | sed 's/\\$//g')"
		fi

		# re-enable logging
		if [ -n "$3" ]; then
			LOGLEVEL="$ORGLOGLEVEL"
		fi
	fi
}

function linkGameCfg {
	if [ -z "$GN" ]; then
		writelog "SKIP" "${FUNCNAME[0]} - Skipping symlinking config - no valid game name found"
	else
		createSymLink "${FUNCNAME[0]}" "$STLGAMECFG" "${STLGAMEDIRTI}/${GN}.conf"
	fi
}

# create game configs:
function createGameCfg {	

	if [ -f "$STLGAMECFG" ]; then
		# add missing config entries in the default global config:
		updateConfigFile "$STLGAMECFG" "saveCfgdefault_template"
	else
		updateConfigEntry "CUSTOMCMD" "$DUMMYBIN" "$STLDEFGAMECFG"
		getGameName "$AID"
		if [ -n "$GAMENAME" ] && [ "$GAMENAME" != "$NON" ]; then
		{
		echo "## config Version: $PROGVERS"
		echo "##########################"
		echo "#########"
		echo "#$PROGNAME $PROGVERS"
		echo "#########"
		getCfgHeader
		echo "## set the default config file for DXVK_CONFIG_FILE which is used when found - defaults to config found in $STLDXVKDIR"
		echo "#STLDXVKCFG=\"$STLDXVKDIR/$AID.conf\""
		grep -v "config Version" "$STLDEFGAMECFG"
		} >> "$STLGAMECFG"
		else
			writelog "SKIP" "${FUNCNAME[0]} - No game name found for '$AID' - does the game exist?"
		fi
	fi
	linkGameCfg
}

# override game configs with a tweak config if available:
function checkTweakLaunch {
	if [ -z "$TWEAKCMD" ]; then
		TWEAKCMD=""
	fi

	if [ -f "$GLOBALTWEAKCFG" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Using overrides found in '$GLOBALTWEAKCFG'"
		notiShow "$(strFix "$NOTY_GLOBALTWEAK" "$GLOBALTWEAKCFG")"
		loadCfg "$GLOBALTWEAKCFG"
	fi

	# then user config - (overriding the global one)
	if [ -f "$TWEAKCFG" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Using overrides found in '$TWEAKCFG'"
		loadCfg "$TWEAKCFG"
	fi

	if [ -n "$TWEAKCMD" ]; then
		# tweak command defined
		if [ -f "$TWEAKCMD" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Found TWEAKCMD '$TWEAKCMD'"
			RUNTWEAK="$TWEAKCMD"
		elif [ -f "$TWEAKCMDDIR/$TWEAKCMD" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Found TWEAKCMD '$TWEAKCMD' in '$TWEAKCMDDIR'"
			RUNTWEAK="$TWEAKCMDDIR/$TWEAKCMD"
		elif [ -f "$GFD/$TWEAKCMD" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Found TWEAKCMD '$TWEAKCMD' in '$GFD'"
			RUNTWEAK="$GFD/$TWEAKCMD"
		fi
		# tweak command found

		if [ -n "$RUNTWEAK" ]; then

			if grep -q "^TWEAKFILE" "$RUNTWEAK"; then
				# dependency for tweak command defined
				writelog "INFO" "${FUNCNAME[0]} - TWEAKFILE configured in $RUNTWEAK as dependency - checking if the file exists in gamedir - relative to the gameexe"
				TWEAKFILE="$(grep "^TWEAKFILE" "$RUNTWEAK" | awk -F 'TWEAKFILE=' '{print $2}')"
				if [ -f "$EFD/$TWEAKFILE" ]; then
					# dependency for tweak command found
					writelog "INFO" "${FUNCNAME[0]} - Found tweakcmd dependency in $EFD/$TWEAKFILE - starting the tweakcmd now"
					# start tweak command
					"$RUNTWEAK"
					writelog "INFO" "${FUNCNAME[0]} - $RUNTWEAK finished"
				else
					# dependency for tweak command not found
					writelog "SKIP" "${FUNCNAME[0]} - Configured TWEAKFILE $TWEAKFILE not found - skipping launch of the tweakcmd $TWEAKCMD"
				fi
			else
				# start tweak command
				writelog "INFO" "${FUNCNAME[0]} - No TWEAKFILE configured in $RUNTWEAK as dependency - starting the tweakcmd regularly now"
				"$RUNTWEAK"
				writelog "INFO" "${FUNCNAME[0]} - $RUNTWEAK finished"
			fi
		else
			writelog "SKIP" "${FUNCNAME[0]} - Configured TWEAKCMD $TWEAKCMD not found - can't start it"
		fi
	fi
}

function genDefIcon {
	if [ ! -f "$STLICON" ]; then
		base64 -d <<< "iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAAZlBMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcHByAgIAAAAD///8AAACfn5+AgIC/v78QEBDv7+9gYGBQUFCvr6/Pz88wMDAgICDf399wcHBAQECPj4/mYUh/AAAAEXRSTlMAYICf778gj3DfUEAwz48gEPfJjAsAAAKXSURBVFjDnZfpetsgFEQtW17jtGVAgNBi9/1fsiDz5dbBTKLMH286xwgBFzaSa7Pdbi+Hzc9y+NXikffmJ/wp4pM3xvQWOF9X8zugH1yIgqD0BDSreRucsUixxvloWMsP8wiMsQXpZdDrDMfIqwljp1K6CdaVhsv2VZaL3oBBqVvv1CPOT059NjR4nbf42xlGlckG4dO/qKF7yoh9asCkVM0gvLFWq0/xAK6xB26KGDKv1WCR7lLieowex80enWKGzC+A/SsKbeFdF+8BUIoaMh8TJlivuxjtLWyIXwFJQA3Cx+gROaN2SgTMsPCSOZiYMMe3WdDCEYNPfD0ObezEQFrAeRViJ57gOc/icdocgJnw80z4GTikudjXed6GHru0mLUwhCcGg/awzFRAV3li0MBFxnqVFwOfbZrwgGa8GEpeDJQXQ8mPoxgIL4ay/+RdjRdDwUPFQAwVXgzClwJowovhmYd3zkMMVV4MwuNmeizpzS0bCC+rvw5IWcb3HTH3ZdQuCZlnRVZHakm3cNnUAYsr8bsqnnuBtUAjpqF8TKUPpIcayseUT0H4L55iTjkOhOfjSAyFIPN8JEuKuSA8nUsSmY0Fz2ZzaSh4sp5UDMLzFa1mEL5muJB1V/j6qix1oYwWvlYXpDLR6kQq0wGg5W9OPKmNUp1JG2h13iOs4cv9QQvHec93KCv2SEXW7tK4gO8TieC7O9XX6bD/9l75ZW44frVb54YJ8Xz2DkN4ajDY5xPLc7t64alhAN4+zkwq3B+dOd9hhWeGweIopzZlgN4E0yN+4Kuu8Lv/z43KfNQSX1v3vZKED15OrtoYo52e6pVn0hkfemC3+ux8PQO2jxf5CWhPzz/+3p6/cXpv3vHIefsnf/UP3QHUzgWHsSYAAAAASUVORK5CYII=" > "$STLICON"
	fi

	if [ ! -f "$NOICON" ]; then
		base64 -d <<< "R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" > "$NOICON"
	fi
}

function createDefaultCfgs {
	writelog "INFO" "${FUNCNAME[0]} - START"

	createProjectDirs

	loadLanguage "$@"

	writelog "INFO" "${FUNCNAME[0]} - setSteamPaths:"
	setSteamPaths

	saveCfg "$STLDEFGLOBALCFG" X
	loadCfg "$STLDEFGLOBALCFG" X
	saveCfg "$STLURLCFG" X
	loadCfg "$STLURLCFG" X
	prepareGUI
	genDefIcon

	createProjectDirs
	getGameOS "$@"
	delEmptyFile "$PROTONCSV"

	if [ "$HAVEINPROTON" -eq 0 ]; then
		if [ "$ISGAME" -eq 2 ] || [ ! -f "$PROTONCSV" ]; then
			writelog "INFO" "${FUNCNAME[0]} - createProtonList:"
			createProtonList X
			writelog "INFO" "${FUNCNAME[0]} - createProtonList end"
		elif [ "$ISGAME" -ne 2 ] && [ -f "$PROTONCSV" ]; then
			mapfile -t -O "${#ProtonCSV[@]}" ProtonCSV < "$PROTONCSV"
		fi
	fi

	checkStartMode
	saveCfg "$STLDEFGAMECFG" X
	createProjectDirs
	setGlobalAIDCfgs
	listAllSettingsEntries
	checkEntryBlocklist
	updateMenuSortFile
	writelog "INFO" "${FUNCNAME[0]} - STOP"
}

# updates or creates option $1 with value $2 in configfile $3:
function updateConfigEntry {

	CFGCAT="$1"
	CFGVALUE="$2"
	CFGFILE="$3"
	
	if [ "$CFGCAT" == "CUSTOMCMD" ] && [ "$CFGFILE" == "$STLDEFGAMECFG" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Emptying '$CFGCAT' for '$STLDEFGAMECFG'"
		CFGVALUE="$DUMMYBIN"
	fi

	if [ -z "$3" ]; then
		writelog "SKIP" "${FUNCNAME[0]} - Expected 3 arguments - only got $*"
	else
#		if [ "$AID" -ne "$PLACEHOLDERAID" ]; then
			if [ ! -f "$CFGFILE" ]; then
				writelog "SKIP" "${FUNCNAME[0]} - Configfile '$CFGFILE' does not exist - skipping config update"
			else
				if [ -n "$CFGVALUE" ]; then
					if [ "$CFGVALUE" == "TRUE" ]; then
						CFGVALUE="1"
					elif [ "$CFGVALUE" == "FALSE" ]; then
						CFGVALUE="0"
					fi	
			
					if [ "$CFGVALUE" == "DUMMY" ]; then
						CFGVALUE=""
					fi

					# only save value if it changed
					if { [ "${!CFGCAT}" != "$CFGVALUE" ] && [ "${!CFGCAT}" != "${CFGVALUE//$STLCFGDIR/STLCFGDIR}" ];} || [ -f "$FUPDATE" ]; then
						CFGVALUE="${CFGVALUE//$STLCFGDIR/STLCFGDIR}"
						if [ "$(grep -c "#${CFGCAT}=" "$CFGFILE")" -eq 1 ]; then
							writelog "INFO" "${FUNCNAME[0]} - Option '$CFGCAT' commented out in config '${CFGFILE##*/}' - activating it with the new value '$CFGVALUE'"
							sed -i "/^#${CFGCAT}=/c$CFGCAT=\"$CFGVALUE\"" "$CFGFILE"
						elif [ "$(grep -c "^${CFGCAT}=" "$CFGFILE")" -eq 0 ]; then
							writelog "INFO" "${FUNCNAME[0]} - '$CFGCAT' option missing in config '${CFGFILE##*/}' - adding a new line"
							echo "$CFGCAT=\"$CFGVALUE\"" >> "$CFGFILE"
						else
							writelog "INFO" "${FUNCNAME[0]} - Option '$CFGCAT' is updated with the new value '$CFGVALUE' in config '${CFGFILE##*/}'"
							sed -i "/^${CFGCAT}=/c$CFGCAT=\"$CFGVALUE\"" "$CFGFILE"
						fi
						rm "$FUPDATE" 2>/dev/null
					fi
				fi
			fi
#		fi
	fi

	CFGCAT=""
	CFGVALUE=""
	CFGFILE=""
}

# autoapply configuration settings based on the steam categories the game is in:
function autoCategorySettings {
	if [ "$CHECKCATEGORIES" -eq 1 ] && [ "$STLPLAY" -eq 0 ]; then
		if [ -z "$SUSDA" ] || [ -z "$STUIDPATH" ]; then
			setSteamPaths
		fi
		if [ -d "$SUSDA" ]; then
			SC="$STUIDPATH/$SRSCV"

			if [ ! -f "$SC" ]; then
				writelog "SKIP" "${FUNCNAME[0]} - File '${SC##*/}' not found in steam userid dir - skipping"
			else
				writelog "INFO" "${FUNCNAME[0]} - Searching categories for game '$AID' in '${SC##*/}'"

				while read -r SCAT; do
					GLOBALSCATCONF="$GLOBALCATEGORYDIR/$SCAT.conf"

					if [ -f "$GLOBALSCATCONF" ]; then
						writelog "INFO" "${FUNCNAME[0]} - Config '$GLOBALSCATCONF' found - loading its settings"
						loadCfg "$GLOBALSCATCONF"
					else
						writelog "SKIP" "${FUNCNAME[0]} - Config '$GLOBALSCATCONF' not found - skipping"
					fi

					SCATCONF="$STLCATEGORYDIR/$SCAT.conf"
					if [ -f "$SCATCONF" ]; then
						writelog "INFO" "${FUNCNAME[0]} - Config '$SCATCONF' found - loading its settings"
						loadCfg "$SCATCONF"
					else
						writelog "SKIP" "${FUNCNAME[0]} - Config '$SCATCONF' not found - skipping"
					fi
					
					SCATCMD="$TWEAKCMDDIR/$SCAT.sh"
					if [ -f "$SCATCMD" ]; then
						writelog "INFO" "${FUNCNAME[0]} - Steam-Category user command '$SCATCMD' found - executing"
						if [ "$USEWINE" -eq 0 ]; then
							"$SCATCMD" "$AID" "$EFD" "$GPFX"
						else
							"$SCATCMD" "$AID" "$EFD" "$GWFX"
						fi
					fi
				done <<< "$(sed -n "/\"$AID\"/,/}/p;" "$SC" | sed -n "/\"tags\"/,/}/p" | sed -n "/{/,/}/p" | grep -v '{\|}' | awk '{print $2}' | sed "s:\"::g")"
			fi
		else
			writelog "SKIP" "${FUNCNAME[0]} - '$SUSDA' not found - this should not happen! - skipping"
		fi
	fi
}
	
function stracerun {
	writelog "INFO" "${FUNCNAME[0]} - Starting stracerun"
	waitForGamePid
	writelog "INFO" "${FUNCNAME[0]} - $STRACE -p $(GAMEPID) $STRACEOPTS -o $STRACEDIR/$AID.log"
	mapfile -d " " -t -O "${#RUNSTRACEOPTS[@]}" RUNSTRACEOPTS < <(printf '%s' "$STRACEOPTS")
	"$STRACE" -p "$(GAMEPID)" "${RUNSTRACEOPTS[@]}" -o "$STRACEDIR/$AID.log"
}

function checkStraceLaunch {
	if [ -n "$STRACERUN" ]; then
		if [ "$STRACERUN" -eq 1 ]; then
			stracerun &
		fi
	fi
}

function netrun {
	writelog "INFO" "${FUNCNAME[0]} - Starting network traffic monitor"

	waitForGamePid

	if [ -n "$NETMONDIR" ]; then
		if [ ! -d "$NETMONDIR" ]; then
			writelog "INFO" "${FUNCNAME[0]} - $NETMON dest directory $NETMONDIR does not exist - trying to create it"
			mkProjDir "$NETMONDIR"
		fi

		if [ -d "$NETMONDIR" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Writing network traffic for $AID int dest directory $NETMONDIR"
			if [ -f "$NETMONDIR/$AID-$NETMON.log" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Removing old $NETMONDIR/$AID-$NETMON.log"
				rm "$NETMONDIR/$AID-$NETMON.log"
			fi
			mapfile -d " " -t -O "${#RUNNETOPTS[@]}" RUNNETOPTS < <(printf '%s' "$NETOPTS")
			"$NETMON" "${RUNNETOPTS[@]}" | grep "wineserver" | grep -v "localhost\|0.0.0.0" >> "$NETMONDIR/$AID-$NETMON.log"
		else
			writelog "SKIP" "${FUNCNAME[0]} - $NETMON dest directory $NETMONDIR still does not exist - skipping"
		fi
	else
		writelog "SKIP" "${FUNCNAME[0]} - $NETMON dest directory variable NETMONDIR is empty"
	fi
}

function checkNetMonLaunch {
	if [ "$USENETMON" -eq 1 ]; then
		if [ -n "$NETMON" ]; then
			netrun &
		fi
	fi
}

function checkXliveless {
	if [ -n "$NOGFWL" ]; then
		if [ "$NOGFWL" -eq 1 ]; then
			rm -rf "$GPFX/$DRC/$PFX86/Microsoft Games for Windows - LIVE"
			rm -rf "$GPFX/$DRC/Program Files/Common Files/Microsoft Shared/Windows Live"
			# option for USEWINE probably not really required
			WLID="WLIDSvcM.exe"
			if "$PGREP" "$WLID" >/dev/null; then
				writelog "INFO" "${FUNCNAME[0]} - GFWL starts '$WLID' directly after installation and it never exists - killing it now"
				"$PKILL" -9 "$WLID"
			fi

			XLIVEDLL="xlive.dll"
			XLDL="$STLDLDIR/xlive/"
			XLDST="$XLDL/$XLIVEDLL"
			mkProjDir "$XLDL"

			writelog "INFO" "${FUNCNAME[0]} - Game '$SGNAID' needs '$XLIVEDLL' - checking"
			if [ -f "$EFD/$XLIVEDLL" ]; then
				writelog "SKIP" "${FUNCNAME[0]} - Found '$XLIVEDLL' in dir $EFD - nothing to do"
			else
				writelog "INFO" "${FUNCNAME[0]} - '$XLIVEDLL' not found in gamedir '$EFD'"
				if [ ! -f "$XLDST" ]; then
					dlCheck "$XLIVEURL" "$XLDST" "X" "'$XLDST' not found - downloading automatically from '$XLIVEURL'"
					"$UNZIP" "$XLDL/${DLURL##*/}" -d "$XLDL"
					if [ -f "$XLDL/dinput8.dll" ]; then
						mv "$XLDL/dinput8.dll" "$XLDST"
					fi
				fi
				if [ -f "$XLDST" ]; then
					writelog "INFO" "${FUNCNAME[0]} - Found '$XLIVEDLL' in '$XLDL' - copying into gamedir '$EFD'"
					cp "$XLDST" "$EFD"
				fi
			fi
		fi
	fi
}

function GameScopeGui {
	if [ -n "$1" ]; then
		AID="$1"
		setAIDCfgs
	fi
	
	if [ -n "$2" ]; then
		GN="$2"
		fixShowGnAid
	fi
	
	loadCfg "$STLGAMECFG"
	export CURWIKI="$PPW/GameScope"
	TITLE="${PROGNAME}-${FUNCNAME[0]}"
	pollWinRes "$TITLE"
	setShowPic
	UL="unlimited"

	if [ -z "$GSSHWRES" ]; then
		if ! grep -q "\-w" <<< "$GAMESCOPE_ARGS" || ! grep -q "\-h" <<< "$GAMESCOPE_ARGS"; then
			GSSHWRES="1280x720"
		else
			GSSHWRES="$(tr ' ' '\n' <<< "$GAMESCOPE_ARGS" | grep -A1 "\-W" | tail -n1)x$(tr ' ' '\n' <<< "$GAMESCOPE_ARGS" | grep -A1 "\-H" | tail -n1)"
		fi
	fi
	
	if [ -z "$GSINTRES" ]; then
		if ! grep -q "\-w" <<< "$GAMESCOPE_ARGS" || ! grep -q "\-h" <<< "$GAMESCOPE_ARGS"; then
			GSINTRES="1280x720"
		else
			GSINTRES="$(tr ' ' '\n' <<< "$GAMESCOPE_ARGS" | grep -A1 "\-w" | tail -n1)x$(tr ' ' '\n' <<< "$GAMESCOPE_ARGS" | grep -A1 "\-h" | tail -n1)"
		fi
	fi
	
	if [ -z "$GSINTRES" ]; then
		GSINTRES="$NON"
	fi

	if [ -z "$GSSHWRES" ]; then
		GSSHWRES="$NON"
	fi

	if [ -z "$GSFLR" ]; then
		if ! grep -q "\-r" <<< "$GAMESCOPE_ARGS"; then
			GSFLR="$UL"
		else
			GSFLR="$(tr ' ' '\n' <<< "$GAMESCOPE_ARGS" | grep -A1 "\-r" | tail -n1)"
		fi
	fi

	if [ -z "$GSFLU" ]; then
		if ! grep -q "\-o" <<< "$GAMESCOPE_ARGS"; then
			GSFLU="$UL"
		else
			GSFLU="$(tr ' ' '\n' <<< "$GAMESCOPE_ARGS" | grep -A1 "\-o" | tail -n1)"
		fi
	fi

	if [ -z "$GSIS" ]; then
		if grep -q "\-n" <<< "$GAMESCOPE_ARGS"; then
			GSIS="1"
		else
			GSIS="0"
		fi
	fi

	if [ -z "$GSFS" ]; then
		if grep -q "\-f" <<< "$GAMESCOPE_ARGS"; then
			GSFS="1"
		else
			GSFS="0"
		fi
	fi

	if [ -z "$GSBW" ]; then
		if grep -q "\-b" <<< "$GAMESCOPE_ARGS"; then
			GSBW="1"
		else
			GSBW="0"
		fi
	fi

	GASCOS="$("$YAD" --f1-action="$F1ACTION" --image "$SHOWPIC" --image-on-top --window-icon="$STLICON" --form --center --on-top $WINDECO \
			--title="$TITLE" --separator="|" \
			--text="$(spanFont "$(strFix "$GUI_GASCOSET" "$SGNAID")" "H")" \
			--field="$GUI_GSINTRES!$DESC_GSINTRES ('GSINTRES')":CBE "$(cleanDropDown "${GSINTRES//\"}" "$(printf "%s\n" "$("$XRANDR" --current | grep "[0-9]x" | awk '{print $1}' | grep "^[0-9]" | tr '\n' '!')")")" \
			--field="$GUI_GSSHWRES!$DESC_GSSHWRES ('GSSHWRES')":CBE "$(cleanDropDown "${GSSHWRES//\"}" "$(printf "%s\n" "$("$XRANDR" --current | grep "[0-9]x" | awk '{print $1}' | grep "^[0-9]" | tr '\n' '!')")")" \
			--field="$GUI_GSFLR!$DESC_GSFLR ('GSFLR')":CBE "$(cleanDropDown "${GSFLR//\"}" "30!60!90!120!$UL")" \
			--field="$GUI_GSFLU!$DESC_GSFLU ('GSFLU')":CBE "$(cleanDropDown "${GSFLU//\"}" "30!60!90!120!$UL")" \
			--field="$GUI_GSIS!$DESC_GSIS ('GSIS')":CHK "$GSIS" \
			--field="$GUI_GSFS!$DESC_GSFS ('GSFS')":CHK "$GSFS" \
			--field="$GUI_GSBW!$DESC_GSBW ('GSBW')":CHK "$GSBW" \
			--field="$GUI_USEGAMESCOPE!$DESC_USEGAMESCOPE ('USEGAMESCOPE')":CHK "${USEGAMESCOPE/#-/ -}" \
			--button="$BUT_CAN:0" --button="$BUT_DONE:2" "$GEOM"
			)"
			case $? in
				0)	{
						writelog "INFO" "${FUNCNAME[0]} - Selected '$BUT_CAN' - Exiting"
					}
				;;
				2)	{
						mapfile -d "|" -t -O "${#GSARR[@]}" GSARR < <(printf '%s' "$GASCOS")
						GSINTRES="${GSARR[0]}"
						GSSHWRES="${GSARR[1]}"
						GSFLR="${GSARR[2]}"
						GSFLU="${GSARR[3]}"
						GSIS="${GSARR[4]}"
						GSFS="${GSARR[5]}"
						GSBW="${GSARR[6]}"
						USEGAMESCOPE="${GSARR[7]}"

						unset GAMESCOPE_ARGS
						GSINTW1="${GSINTRES%x*}"
						GSINTW="${GSINTW1%%-*}"
						GSINTH1="${GSINTRES#*x}"
						GSINTH="${GSINTH1%%-*}"

						GAMESCOPE_ARGS="-w ${GSINTW} -h ${GSINTH}"

						GSSHWW1="${GSSHWRES%x*}"
						GSSHWW="${GSSHWW1%%-*}"
						GSSHWH1="${GSSHWRES#*x}"
						GSSHWH="${GSSHWH1%%-*}"

						GAMESCOPE_ARGS="${GAMESCOPE_ARGS} -W ${GSSHWW} -H ${GSSHWH}"
						if [ "$GSFLR" -eq "$GSFLR" ] 2>/dev/null; then
							GAMESCOPE_ARGS="${GAMESCOPE_ARGS} -r ${GSFLR}"
						fi

						if [ "$GSFLU" -eq "$GSFLU" ] 2>/dev/null; then
							GAMESCOPE_ARGS="${GAMESCOPE_ARGS} -o ${GSFLU}"
						fi	

						if [ "$GSIS" == "TRUE" ]; then
							GAMESCOPE_ARGS="${GAMESCOPE_ARGS} -n"
						fi

						if [ "$GSFS" == "TRUE" ]; then
							GAMESCOPE_ARGS="${GAMESCOPE_ARGS} -f"
						fi

						if [ "$GSBW" == "TRUE" ]; then
							GAMESCOPE_ARGS="${GAMESCOPE_ARGS} -b"
						fi

						GAMESCOPE_ARGS="${GAMESCOPE_ARGS} --"
			
						writelog "INFO" "${FUNCNAME[0]} - Saving configured GAMESCOPE_ARGS '$GAMESCOPE_ARGS' into '$STLGAMECFG'"
						touch "$FUPDATE"
						updateConfigEntry "GAMESCOPE_ARGS" "$GAMESCOPE_ARGS" "$STLGAMECFG"						
						touch "$FUPDATE"
						updateConfigEntry "USEGAMESCOPE" "$USEGAMESCOPE" "$STLGAMECFG"						
					}
				;;	
			esac
}

function StandaloneProtonGame {
	function SapRun {
		if [ "$SAPRUN" == "TRUE" ]; then
			RUNSAPPROTON="$(getProtPathFromCSV "$SAPPROTON")"
			if [ ! -f "$RUNSAPPROTON" ]; then
				RUNSAPPROTON="$(fixProtonVersionMismatch "SAPPROTON" "$STLGAMECFG" X)"
			fi

			if [ ! -f "$RUNSAPPROTON" ]; then
				writelog "SKIP" "${FUNCNAME[0]} - No executable for selected Proton '$SAPPROTON' found"
			elif [ ! -f "$SAPEXE" ]; then
				writelog "SKIP" "${FUNCNAME[0]} - No executable found"
			elif [ ! -d "$SAP_COMPAT_DATA_PATH" ]; then
				writelog "SKIP" "${FUNCNAME[0]} - No $CODA dir found"
			else
				if [ -z "$SAPARGS" ]; then
					RUNSAPARGS=""
				else
					mapfile -d " " -t -O "${#RUNSAPARGS[@]}" RUNSAPARGS < <(printf '%s' "$SAPARGS")
				fi
				
				writelog "INFO" "${FUNCNAME[0]} - Starting '$SAPEXE' with '$SAPPROTON' with STEAM_COMPAT_DATA_PATH '$SAP_COMPAT_DATA_PATH'"
				STEAM_COMPAT_DATA_PATH="$SAP_COMPAT_DATA_PATH" "$RUNSAPPROTON" run "$SAPEXE" "${RUNSAPARGS[@]}"
			fi
		fi
	}

	function SapGui {
		export CURWIKI="$PPW/Standalone-Proton"
		TITLE="${PROGNAME}-StandaloneProtonGame"
		pollWinRes "$TITLE"

		SAPGAMELIST="$(find "$STLGSAPD" -type f -exec basename {} .conf \; | tr '\n' '!')"

		if [ -z "$SAP_COMPAT_DATA_PATH" ]; then
			SAP_COMPAT_DATA_PATH="$STLGSACD/${PROGNAME,,}-$((10000 + RANDOM % 10000))"
			mkProjDir "$SAP_COMPAT_DATA_PATH"
			IN_SAP_COMPAT_DATA_PATH="$SAP_COMPAT_DATA_PATH"
		fi

		PROTPARTS="$("$YAD" --f1-action="$F1ACTION" --window-icon="$STLICON" --form --center --on-top $WINDECO \
		--title="$TITLE" \
		--text="$(spanFont "$GUI_SAPTEXT" "H")" \
		--field=" ":LBL " " --separator="|" \
		--field="$GUI_SAPGAME!$DESC_SAPGAME":CBE "$(cleanDropDown "${SAPGAME}" "$SAPGAMELIST")" \
		--field="$GUI_SAPPROTON!$DESC_SAPPROTON":CB "$(cleanDropDown "${SAPPROTON//\"}" "$PROTYADLIST")" \
		--field="$GUI_SAP_COMPAT_DATA_PATH!$DESC_SAP_COMPAT_DATA_PATH":DIR "${SAP_COMPAT_DATA_PATH//\"}" \
		--field="$GUI_SAPEXE!$DESC_SAPEXE":FL "${SAPEXE//\"}" \
		--field="$GUI_SAPARGS!$DESC_SAPARGS" "${SAPARGS//\"}"\
		--field="$GUI_SAPRUN!$DESC_SAPRUN":CHK "$SAPRUN" \
		--button="$BUT_CAN:0" --button="$BUT_LOAD:2" --button="$BUT_RUN:4" "$GEOM"
		)"
		case $? in
			0)	{
					writelog "INFO" "${FUNCNAME[0]} - Selected '$BUT_CAN' - Exiting"
					if [ -d "$IN_SAP_COMPAT_DATA_PATH" ]; then
						rmdir "$IN_SAP_COMPAT_DATA_PATH"
					fi
				}
			;;
			2)	{
					writelog "INFO" "${FUNCNAME[0]} - Selected '$BUT_LOAD'"
					mapfile -d "|" -t -O "${#SAPARR[@]}" SAPARR < <(printf '%s' "$PROTPARTS")
					SAPGAME="${SAPARR[1]}"
					writelog "INFO" "Loading '${STLGSAPD}/${SAPGAME}.conf' and starting the gui ${FUNCNAME[0]}"
					loadCfg "${STLGSAPD}/${SAPGAME}.conf"

					if [ "$IN_SAP_COMPAT_DATA_PATH" != "$SAP_COMPAT_DATA_PATH" ]; then
						if [ -d "$IN_SAP_COMPAT_DATA_PATH" ]; then
							writelog "INFO" "${FUNCNAME[0]} - User chose an own COMPAT_DATA_PATH, removing autocreated '$IN_SAP_COMPAT_DATA_PATH'"
							rmdir "$IN_SAP_COMPAT_DATA_PATH"
						fi
					fi

					"${FUNCNAME[0]}"
				}
			;;
			4)	{
					writelog "INFO" "${FUNCNAME[0]} - Selected '$BUT_RUN' - Exiting"
					unset SAPARR
					mapfile -d "|" -t -O "${#SAPARR[@]}" SAPARR < <(printf '%s' "$PROTPARTS")
					SAPGAME="${SAPARR[1]}"
					SAPPROTON="${SAPARR[2]}"
					SAP_COMPAT_DATA_PATH="${SAPARR[3]}"
					SAPEXE="${SAPARR[4]}"
					SAPARGS="${SAPARR[5]}"
					SAPRUN="${SAPARR[6]}"
					
					if [ "$IN_SAP_COMPAT_DATA_PATH" != "$SAP_COMPAT_DATA_PATH" ]; then
						if [ -d "$IN_SAP_COMPAT_DATA_PATH" ]; then
							writelog "INFO" "${FUNCNAME[0]} - User chose an own COMPAT_DATA_PATH, removing autocreated '$IN_SAP_COMPAT_DATA_PATH'"
							rmdir "$IN_SAP_COMPAT_DATA_PATH"
						fi
					fi

					if [ -n "$SAPGAME" ];then
						SAPCFG="${STLGSAPD}/${SAPGAME}.conf"
				
						touch "$FUPDATE" "$SAPCFG"
						updateConfigEntry "SAPGAME" "$SAPGAME" "$SAPCFG"

						if [ -n "$SAPPROTON" ];then
							touch "$FUPDATE"
							updateConfigEntry "SAPPROTON" "$SAPPROTON" "$SAPCFG"
						fi

						if [ -n "$SAP_COMPAT_DATA_PATH" ];then
							touch "$FUPDATE"
							updateConfigEntry "SAP_COMPAT_DATA_PATH" "$SAP_COMPAT_DATA_PATH" "$SAPCFG"
						fi

						if [ -n "$SAPEXE" ];then
							touch "$FUPDATE"
							updateConfigEntry "SAPEXE" "$SAPEXE" "$SAPCFG"
						fi

						if [ -n "$SAPARGS" ];then
							touch "$FUPDATE"
							updateConfigEntry "SAPARGS" "$SAPARGS" "$SAPCFG"
						fi

						if [ -n "$SAPRUN" ];then
							touch "$FUPDATE"
							updateConfigEntry "SAPARGS" "$SAPARGS" "$SAPCFG"
						fi
					fi
					SapRun
				}
			;;
		esac
	}

	createProtonList X

	mkProjDir "$STLGSAPD"
	SAPGUI=1
	SAPRUN="TRUE"

	if [ -n "$1" ] && [ -z "$2" ] && [ -f "${STLGSAPD}/${1}.conf" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Loading '${STLGSAPD}/${1}.conf' silently"
		loadCfg "${STLGSAPD}/${1}.conf"
		SAPGUI=0
		SapRun
	elif [ -n "$1" ] && [ ! -f "${STLGSAPD}/${1}.conf" ]; then
		if [ "$1" == "list" ]; then
			find "$STLGSAPD" -type f -exec basename {} .conf \;
			SAPGUI=0
			SAPRUN="FALSE"
		else
			writelog "INFO" "${FUNCNAME[0]} - Using '$1' as game title"
			SAPGAME="$1"
		fi
	elif [ -n "$1" ] && [ -n "$2" ] && [ -f "${STLGSAPD}/${1}.conf" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Loading '${STLGSAPD}/${1}.conf' and starting the gui"
		loadCfg "${STLGSAPD}/${1}.conf"
		SAPGUI=1
	elif [ -z "$1" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Only starting plain gui"
	fi

	if [ "$SAPGUI" -eq 1 ]; then
		SapGui
	fi
}

function OneTimeRunGui {
	if [ -n "$1" ]; then
		AID="$1"
		setAIDCfgs
	fi
	loadCfg "$STLGAMECFG"

	if [ -z "$STEAM_COMPAT_DATA_PATH" ]; then
		METCFG="$CUMETA/${AID}.conf"
		if [ -f "$METCFG" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Loading Metadata '$METCFG'"
			fixCustomMeta "$METCFG" # will be removed again later
			loadCfg "$METCFG"
		fi
		if [ -n "$WINEPREFIX" ]; then
			STEAM_COMPAT_DATA_PATH="${WINEPREFIX%/*}"
			writelog "INFO" "${FUNCNAME[0]} - Found STEAM_COMPAT_DATA_PATH '$STEAM_COMPAT_DATA_PATH'"
		fi
	fi

	if [ -z "$STEAM_COMPAT_DATA_PATH" ]; then
		writelog "ERROR" "${FUNCNAME[0]} - STEAM_COMPAT_DATA_PATH could not be determined"
	else
		createProtonList X
		export CURWIKI="$PPW/One-Time-Run"
		TITLE="${PROGNAME}-${FUNCNAME[0]}"
		pollWinRes "$TITLE"
		setShowPic
		if [ -z "$OTPROTON" ]; then
			OTPROTON="$USEPROTON"
		fi

		OTCMDS="$("$YAD" --f1-action="$F1ACTION" --image "$SHOWPIC" --image-on-top --window-icon="$STLICON" --form --center --on-top $WINDECO \
			--title="$TITLE" --separator="|" \
			--text="$(spanFont "$GUI_ONETIMERUN" "H")" \
			--field="$GUI_OTPROTON!$DESC_OTPROTON":CB "$(cleanDropDown "${OTPROTON//\"}" "$PROTYADLIST")" \
			--field="$GUI_OTEXE!$DESC_OTEXE":FL "${OTEXE//\"}" \
			--field="$GUI_OTARGS!$DESC_OTARGS" "${OTARGS//\"}"\
			--field="$GUI_OTSAVE!$DESC_OTSAVE":CHK "FALSE" \
			--button="$BUT_CAN:0" --button="$BUT_RUN:2" "$GEOM"
			)"
			case $? in
				0)	{
						writelog "INFO" "${FUNCNAME[0]} - Selected '$BUT_CAN' - Exiting"
					}
				;;
				2)	{
						mapfile -d "|" -t -O "${#OTARR[@]}" OTARR < <(printf '%s' "$OTCMDS")
						OTPROTON="${OTARR[0]}"
						OTEXE="${OTARR[1]}"
						OTARGS="${OTARR[2]}"
						OTSAVE="${OTARR[3]}"					

						RUNOTPROTON="$(getProtPathFromCSV "$OTPROTON")"
						if [ ! -f "$RUNOTPROTON" ]; then
							RUNOTPROTON="$(fixProtonVersionMismatch "OTPROTON" "$STLGAMECFG" X)"
						fi
		
						if [ ! -f "$RUNOTPROTON" ]; then
							writelog "SKIP" "${FUNCNAME[0]} - No executable for selected Proton '$OTPROTON' found"
						elif [ ! -f "$OTEXE" ]; then
							writelog "SKIP" "${FUNCNAME[0]} - No executable found"
						else
							if [ -z "$OTARGS" ]; then
								RUNOTARGS=""
							else
								mapfile -d " " -t -O "${#RUNOTARGS[@]}" RUNOTARGS < <(printf '%s' "$OTARGS")
							fi
							
							if [ "$OTSAVE" == "TRUE" ];then
								writelog "INFO" "${FUNCNAME[0]} - Saving One time run settings into '$STLGAMECFG'"
								touch "$FUPDATE"
								updateConfigEntry "OTPROTON" "$OTPROTON" "$STLGAMECFG"
								touch "$FUPDATE"
								updateConfigEntry "OTEXE" "$OTEXE" "$STLGAMECFG"
								touch "$FUPDATE"
								updateConfigEntry "OTARGS" "$OTARGS" "$STLGAMECFG"
							fi

							writelog "INFO" "${FUNCNAME[0]} - Starting '$OTEXE' with '$OTPROTON' with STEAM_COMPAT_DATA_PATH '$STEAM_COMPAT_DATA_PATH'"
							STEAM_COMPAT_DATA_PATH="$STEAM_COMPAT_DATA_PATH" "$RUNOTPROTON" run "$OTEXE" "${RUNOTARGS[@]}"
						fi
					}
				;;	
			esac
	fi
}

function setOPCustPath {
	if [ -z "$CUSTOMCMD" ] || [[ "$CUSTOMCMD" =~ ${DUMMYBIN}$ ]]; then
		OPCUSTPATH="$GP"
	fi
	
	if [ -z "$OPCUSTPATH" ]; then
		OPCUSTPATH="$CUSTOMCMD"
	fi
	
	if [ -n "$OPCUSTPATH" ]; then
		export OPCUSTPATH="$OPCUSTPATH"
		writelog "INFO" "${FUNCNAME[0]} - Default path for custom exe file requester is '$OPCUSTPATH'"
	fi
}

function launchCustomProg {
	if [ -n "$1" ]; then
		CUSTOMCMD="$WICO"
	fi
	
	if [ -z "$CUSTOMCMD" ] || [[ "$CUSTOMCMD" =~ ${DUMMYBIN}$ ]]; then

		writelog "INFO" "${FUNCNAME[0]} - CUSTOMCMD variable is empty - opening file requester"
		fixShowGnAid

		export CURWIKI="$PPW/Custom-Program"
		TITLE="${PROGNAME}-OpenCustomProgram"
		pollWinRes "$TITLE"

		ZCUST="$("$YAD" --f1-action="$F1ACTION" --window-icon="$STLICON" --form --center --on-top "$WINDECO" \
		--title="$TITLE" \
		--text="$(spanFont "$SGNAID - $GUI_SELECTCUSTOMEXE" "H")" \
		--field=" ":LBL " " \
		--field="$GUI_SELECTEXE":FL "${OPCUSTPATH/#-/ -}" "$GEOM")"

		if [ -n "$ZCUST" ]; then
			writelog "INFO" "${FUNCNAME[0]} - '${ZCUST//|/}' selected for CUSTOMCMD - updating configfile '$STLGAMECFG'"
			updateConfigEntry "CUSTOMCMD" "${ZCUST//|/}" "$STLGAMECFG"

			CUSTOMCMD="${ZCUST//|/}"
		else
			writelog "SKIP" "${FUNCNAME[0]} - Nothing selected for CUSTOMCMD - skipping"
			if [ "$ONLY_CUSTOMCMD" -eq 1 ]; then
				writelog "SKIP" "${FUNCNAME[0]} - ONLY_CUSTOMCMD is enabled - bailing out here"
				closeSTL " ######### STOP EARLY '$PROGNAME $PROGVERS' #########"
				exit
			else
				writelog "SKIP" "${FUNCNAME[0]} - Continuing with the main game"
				return
			fi
		fi
	fi
	
	if [ -z "$CUSTOMCMD" ]; then
		writelog "ERROR" "${FUNCNAME[0]} - CUSTOMCMD variable is empty - but it shouldn't be empty here!"
	fi	
	
	CHCUSTDIR=0
	if [ -n "$1" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Using '$WICO' as custom command"
		LACO="$WICO"
		CUSTCOM="$WICO"
	elif [ -x "$(command -v "$CUSTOMCMD")" ]; then
		writelog "INFO" "${FUNCNAME[0]} - '$CUSTOMCMD' found"
		LACO="$CUSTOMCMD"
		CUSTCOM="$(command -v "$CUSTOMCMD")"
		CHCUSTDIR=1
	else
		writelog "INFO" "${FUNCNAME[0]} - '$CUSTOMCMD' not found - searching in gamedir"

		if [ -f "$EFD/$CUSTOMCMD" ]; then
			writelog "INFO" "${FUNCNAME[0]} - '$CUSTOMCMD' was found in gamedir '$EFD'"
			LACO="$EFD/$CUSTOMCMD"
			CUSTCOM="$EFD/$CUSTOMCMD"
		else
			writelog "INFO" "${FUNCNAME[0]} - '$CUSTOMCMD' also not in '$EFD/$CUSTOMCMD' - checking if absolute path was provided"

			if [ -f "$CUSTOMCMD" ]; then
				writelog "INFO" "${FUNCNAME[0]} - '$CUSTOMCMD' is absolute path"
				LACO="$CUSTOMCMD"
				CUSTCOM="$CUSTOMCMD"
				CHCUSTDIR=1
			else
				writelog "INFO" "${FUNCNAME[0]} - CUSTOMCMD file '$CUSTOMCMD' not found - opening file requester"
				fixShowGnAid
				export CURWIKI="$PPW/Custom-Program"
				TITLE="${PROGNAME}-OpenCustomProgram"
				pollWinRes "$TITLE"
				
				ZCUST="$("$YAD" --f1-action="$F1ACTION" --window-icon="$STLICON" --form --center --on-top "$WINDECO" \
				--title="$TITLE" \
				--text="$(spanFont "$SGNAID - $GUI_SELECTCUSTOMEXE" "H")" \
				--field=" ":LBL " " \
				--field="$GUI_SELECTEXE":FL "${OPCUSTPATH/#-/ -}" "$GEOM")"		
				
				if [ -n "$ZCUST" ]; then
					writelog "INFO" "${FUNCNAME[0]} - '${ZCUST//|/}' selected for CUSTOMCMD - updating configfile '$STLGAMECFG'"
					updateConfigEntry "CUSTOMCMD" "${ZCUST//|/}" "$STLGAMECFG"
					LACO="${ZCUST//|/}"
					CUSTCOM="${ZCUST//|/}"
					CUSTOMCMD="${ZCUST//|/}"
					CHCUSTDIR=1
				else
					writelog "SKIP" "${FUNCNAME[0]} - Nothing selected for CUSTOMCMD - skipping"
					if [ "$ONLY_CUSTOMCMD" -eq 1 ]; then
						writelog "SKIP" "${FUNCNAME[0]} - ONLY_CUSTOMCMD is enabled - bailing out here"
						closeSTL " ######### STOP EARLY $PROGNAME $PROGVERS #########"
						exit
					else
						writelog "SKIP" "${FUNCNAME[0]} - Continuing with the main game"
						return
					fi
				fi
			fi
		fi
	fi

	if [ -z "$LACO" ]; then
		writelog "SKIP" "${FUNCNAME[0]} - ERROR - launch command empty- skipping launch"
	else
		startSBSVR &

		if [ "$CHCUSTDIR" -eq 1 ]; then
			CUSTDIR="$(dirname "$CUSTOMCMD")"
			cd "$CUSTDIR" >/dev/null || return
			writelog "INFO" "${FUNCNAME[0]} - Changed pwd into the custom directory '$PWD'"
		fi
	
		if [ "$(file "$CUSTCOM" | grep -c "PE32")" -eq 1 ] || grep -q ".bat" <<< "$CUSTCOM"; then
			writelog "INFO" "${FUNCNAME[0]} - '$CUSTCOM' seems to be a MS Windows program - starting through proton"
			if [ "$USEWICO" -eq 1 ] && [ "$(file "$CUSTCOM" | grep -c "(console)")" -eq 1 ]; then
				writelog "INFO" "${FUNCNAME[0]} - '$CUSTCOM' seems to be a MS console program - starting using '$WICO'"
				if [ "$FORK_CUSTOMCMD" -eq 1 ]; then	
					writelog "INFO" "${FUNCNAME[0]} - FORK_CUSTOMCMD is set to 1 - forking the custom program in background and continue"
					extProtonRun "FC" "$LACO" "$CUSTOMCMD_ARGS"
				else
					extProtonRun "RC" "$LACO" "$CUSTOMCMD_ARGS"
				fi
			else
				writelog "INFO" "${FUNCNAME[0]} - '$CUSTCOM' seems to be a MS gui program - starting regularly"

				if [ "$FORK_CUSTOMCMD" -eq 1 ]; then	
					writelog "INFO" "${FUNCNAME[0]} - FORK_CUSTOMCMD is set to 1 - forking the custom program in background and continue"
					extProtonRun "F" "$LACO" "$CUSTOMCMD_ARGS"
				else
					extProtonRun "R" "$LACO" "$CUSTOMCMD_ARGS"
				fi
			fi
		else
			if [ -z "$CUSTOMCMD_ARGS" ] || [ "$CUSTOMCMD_ARGS" == "$NON" ]; then
				RUNCUSTOMCMD_ARGS=""
			else
				writelog "INFO" "${FUNCNAME[0]} - Starting the custom program '$CUSTOMCMD' with args: '$CUSTOMCMD_ARGS'"
				mapfile -d " " -t -O "${#RUNCUSTOMCMD_ARGS[@]}" RUNCUSTOMCMD_ARGS < <(printf '%s' "$CUSTOMCMD_ARGS")
			fi

			if [ -n "$1" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Starting only the '$WICO' with command: '$LACO'"
				"$LACO"
				writelog "STOP" "######### CLEANUP #########"
				closeSTL "######### DONE - $PROGNAME $PROGVERS #########"
				exit
			else
				writelog "INFO" "${FUNCNAME[0]} - '$CUSTCOM' doesn't seem to be a MS Windows exe - regular start (without further analysing)"
				if [ "$FORK_CUSTOMCMD" -eq 1 ]; then	
					writelog "INFO" "${FUNCNAME[0]} - FORK_CUSTOMCMD is set to 1 - forking the custom program in background and continue"
					"$LACO" "${RUNCUSTOMCMD_ARGS[@]}" &
				else
					"$LACO" "${RUNCUSTOMCMD_ARGS[@]}"
				fi
			fi
		fi
		if [ "$CHCUSTDIR" -eq 1 ]; then
			writelog "INFO" "${FUNCNAME[0]} - Changing pwd into previous directory"
			cd - >/dev/null || return
		fi
	fi
}

function getGameFiles {
	AID="$1"

	if [ -z "$APPMAFE" ]; then
		APPMAFE="$(listAppManifests | grep -m1 "${AID}.acf")"
	fi

	if [ -f "$APPMAFE" ]; then
		if [ -z "$GPFX" ]; then
			GPFX="$(dirname "$APPMAFE")/$CODA/$1/pfx"
		fi

		if [ -z "$EFD" ]; then
			EFD="$(getGameDirFromAM "$APPMAFE")"
		fi

		if [ -z "$STECOSHAPA" ]; then
			STECOSHAPA="${APPMAFE%/*}/shadercache/$AID"
		fi
	fi
}

function setGameFilesArray {
	unset GamDesc
	unset GamFiles
	if [ "$EFD" != "." ] && [ -d "$EFD" ]; then
		GamDesc+=("$GUI_GD")
		GamFiles+=("$EFD")
	fi

	if [ -d "$GPFX" ]; then
		GamDesc+=("$GUI_WP")
		GamFiles+=("$GPFX")
	fi

	if [ -f "$APPMAFE" ]; then
		GamDesc+=("$GUI_AM")
		GamFiles+=("$APPMAFE")
	fi

	if [ -d "$STECOSHAPA" ]; then
		GamDesc+=("$GUI_SP")
		GamFiles+=("$STECOSHAPA")
	fi
}

function GameFilesMenu {
	if [ -n "$1" ]; then
		getGameFiles "$1"
	else
		setGameVars
	fi

	fixShowGnAid

	setGameFilesArray
		
	if [ "${#GamFiles[@]}" -ge 1 ]; then	
		writelog "INFO" "${FUNCNAME[0]} - Found ${#GamFiles[@]} available game files and directories - opening menu"
		export CURWIKI="$PPW/Game-Files"
		TITLE="${PROGNAME}-Game-Files"
		pollWinRes "$TITLE"

		setShowPic
		OPFILES="$(for i in "${!GamFiles[@]}"; do printf "FALSE\n%s\n%s\n" "${GamDesc[$i]}" "${GamFiles[$i]}"; done | \
		"$YAD" --f1-action="$F1ACTION" --image "$SHOWPIC" --image-on-top --window-icon="$STLICON" --center $WINDECO --list --checklist --column=Open --column=Description --column=Path --separator="\n" --print-column="3" \
		--text="$(spanFont "$(strFix "$GUI_GAFIDIALOG" "$SGNAID")" "H")" --title="$TITLE" --button="$BUT_CAN:0" --button="$BUT_SELECT:2" "$GEOM")"
		case $? in
			0) writelog "INFO" "${FUNCNAME[0]} - Selected '$BUT_CAN' - Cancelling selection"
			;;
			2) writelog "INFO" "${FUNCNAME[0]} - Selected Open - Opening selected files and directories using '$XDGO'"
				mapfile -t -O "${#OpArr[@]}" OpArr <<< "$OPFILES"
				if [ "${#OpArr[@]}" -ge 1 ]; then
					while read -r gafi; do
						if [ -n "$gafi" ]; then
							"$XDGO" "$gafi"
						fi
					done <<< "$(printf "%s\n" "${OpArr[@]}")"
					unset OpArr
				else
					writelog "SKIP" "${FUNCNAME[0]} - Nothing selected"
				fi
			;;
		esac
	else
		writelog "SKIP" "${FUNCNAME[0]} - Could not find any game files"
	fi
}

function DxvkHudPick {
	if [ -n "$1" ]; then
		AID="$1"
		setAIDCfgs
	fi

	if [ ! -f "$STLGAMECFG" ]; then
		writelog "ERROR" "${FUNCNAME[0]} - Game config '$STLGAMECFG' not found - exiting"
	else
		DXVKHUDLIST="0,1,devinfo,fps,frametimes,submissions,drawcalls,pipelines,memory,gpuload,version,api,compiler,samplers,full"

		unset CURDXH

		if [ "$DXVK_HUD" == "0" ]; then
			declare -a CURDXH
		else
			mapfile -d " " -t -O "${#CURDXH[@]}" CURDXH <<< "$(printf '%s\n' "$DXVK_HUD")"
		fi
		fixShowGnAid
		export CURWIKI="$PPW/Dxvk-Hud-Options"
		TITLE="${PROGNAME}-DXVK-Hud-Options"
		pollWinRes "$TITLE"

		setShowPic

		DXHUDOPTS="$(
		while read -r dxline; do
			if [[ "${CURDXH[*]}" =~ $dxline ]]; then
				echo TRUE
			else
				echo FALSE
			fi
			echo "$dxline"
		done <<< "$(tr ',' '\n' <<< "$DXVKHUDLIST")"	 | \
		"$YAD" --f1-action="$F1ACTION" --image "$SHOWPIC" --image-on-top --window-icon="$STLICON" --center "$WINDECO" --list --checklist --column="$GUI_ADD" --column="$GUI_DXH" --separator="" --print-column="2" \
		--text="$(spanFont "$(strFix "$GUI_DXHDIALOG" "$SGNAID")" "H")" --title="$TITLE" "$GEOM")"

		if [ -n "$DXHUDOPTS" ]; then
			unset DXVK_HUD
			while read -r line; do
				DXVK_HUD="${DXVK_HUD},$line"
			done <<< "$DXHUDOPTS"
			DXVK_HUD="${DXVK_HUD#*[[:blank:]]}"
			DXVK_HUD="${DXVK_HUD#*,}"
			DXVK_HUD="${DXVK_HUD%*[[:blank:]]}"
			touch "$FUPDATE"
			updateConfigEntry "DXVK_HUD" "$DXVK_HUD" "$STLGAMECFG"

		else
			writelog "INFO" "${FUNCNAME[0]} - Nothing selected"
		fi

		if [ -n "$2" ]; then
			"$2" "$AID" "${FUNCNAME[0]}"
		fi
	fi
}

function symlinkSteamUser {

	SteamUserDir="$GPFX/$DRCU/$STUS"

	if [ "$1" -eq 1 ]; then
		mkProjDir "$STLPROTSTUSDIR"

		if [ "$USEGLOBSUSYM" -eq 1 ]; then
			SUSYD="$STLPROTSTUSDIR/global"
		else
			SUSYD="$STLPROTSTUSDIR/$AID"
		fi

		writelog "INFO" "${FUNCNAME[0]} - Testing if creating a symlink '$SteamUserDir' pointing to '$SUSYD' is required"
		
		if [ ! -d "$SUSYD" ]; then
			writelog "INFO" "${FUNCNAME[0]} - '$SUSYD' does not yet exists"
			if [ -d "$SteamUserDir" ]; then
				mv "$SteamUserDir" "$SUSYD"
			else
				mkProjDir "$SUSYD"
			fi
		else
			writelog "INFO" "${FUNCNAME[0]} - '$SUSYD' does already exists"
		fi 

		if [ -L "$SteamUserDir" ]; then
			if [ "$(readlink "$SteamUserDir")" == "$SUSYD" ]; then
				writelog "INFO" "${FUNCNAME[0]} - '$SteamUserDir' is already a symlink pointing to '$SUSYD' - nothing to do"
			else
				writelog "INFO" "${FUNCNAME[0]} - '$SteamUserDir' is already a symlink pointing to the unexpected directory '$(readlink "$SteamUserDir")' instead of '$SUSYD' - nothing to do"
			fi
		else
			if [ -d "$SteamUserDir" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Syncing files from '$SteamUserDir' to '$SUSYD'"
				"$RSYNC" -amu "$SteamUserDir" "$SUSYD"
				BACKSUD="${SteamUserDir}_${PROGNAME,,}_$((900 + RANDOM % 100))"
				mv "$SteamUserDir" "$BACKSUD"
				writelog "INFO" "${FUNCNAME[0]} - Backing up '$SteamUserDir' to '$BACKSUD'"
			fi

			if [ ! -d "$SteamUserDir" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Creating '$SteamUserDir' symlink pointing to '$SUSYD' using command:"
				writelog "INFO" "${FUNCNAME[0]} - 'ln -s \"$SUSYD\" \"$SteamUserDir\"'"

				ln -s "$SUSYD" "$SteamUserDir"
			else
				writelog "SKIP" "${FUNCNAME[0]} - '$SteamUserDir' still exists - can't create a symlink pointing to '$SUSYD'"
			fi
		fi

		if [ "$(readlink "$SteamUserDir")" == "$SUSYD" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Pulling files from backup if existing and '$SteamUserDir' is empty and a symlink to '$SUSYD'"
			restoreSteamUser "restore-if-dst-is-empty"
		fi
	else
		writelog "SKIP" "${FUNCNAME[0]} - Symlinking $STUS is disabled - Checking if a symlink needs to be reverted"
		
		if [ -L "$SteamUserDir" ]; then
			SUSYD="$(readlink "$SteamUserDir")"
			writelog "INFO" "${FUNCNAME[0]} - '$SteamUserDir' points to '$SUSYD'"
			if [ -d "$SUSYD" ]; then
				rm "$SteamUserDir"
				mkProjDir "$SteamUserDir"
				if grep -q "$AID" <<< "$SUSYD"; then
					writelog "INFO" "${FUNCNAME[0]} - The directory '$SUSYD' where the symlink '$SteamUserDir' points to is game specific - "
					writelog "INFO" "${FUNCNAME[0]} - Migrating all files into the freshly created '$SteamUserDir' from it"
					"$RSYNC" -amu "$SUSYD" "$SteamUserDir"
				else
					writelog "INFO" "${FUNCNAME[0]} - The directory '$SUSYD' where the symlink '$SteamUserDir' points to is not game specific - "
					writelog "INFO" "${FUNCNAME[0]} - Not migrating any files into the freshly created '$SteamUserDir' from it - "
					writelog "INFO" "${FUNCNAME[0]} - Pulling files from backup if existing instead"
					restoreSteamUser "restore-if-dst-is-empty"	
				fi
			fi
		else
			writelog "SKIP" "${FUNCNAME[0]} - '$SteamUserDir' is no symlink - nothing to do"
		fi
	fi
}

function redirectSCDP {
	function checkCompatdataSteamUser {
		if [ "$REDIRSTEAMUSER" == "symlink" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Checking creation of a '$STUS' symlink, as REDIRSTEAMUSER is '$REDIRSTEAMUSER'"
			symlinkSteamUser 1
		elif [ "$REDIRSTEAMUSER" == "restore-backup" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Calling restoreSteamUser to migrate '$STUS', as REDIRSTEAMUSER is '$REDIRSTEAMUSER'"
			restoreSteamUser
		else
			writelog "INFO" "${FUNCNAME[0]} - Leaving '$STUS' directory untouched, as REDIRSTEAMUSER is '$REDIRSTEAMUSER'"
		fi
	}
	
	function SetCompatdataSymlink {
		DIR="$1"
		SYM="$2"
		writelog "INFO" "${FUNCNAME[0]} - Using '$DIR' as new $CODA dir and '$SYM' as symlink pointing to it"

		if [ ! -f "${DIR}/version" ]; then
			writelog "INFO" "${FUNCNAME[0]} - New $CODA '$DIR' does not exist yet"
			if [ -d "${STEAM_COMPAT_DATA_PATH}_SAC" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Moving found backed autocloud $CODA '${STEAM_COMPAT_DATA_PATH}_SAC' to '$DIR'"
				mkProjDir "${DIR%/*}"
				mv "${STEAM_COMPAT_DATA_PATH}_SAC" "$DIR"
			else
				writelog "INFO" "${FUNCNAME[0]} - Creating new $CODA dir '$DIR'"
				mkProjDir "$DIR"
			fi
		else
			writelog "INFO" "${FUNCNAME[0]} - Using existing $CODA '$DIR'"
			if [ -d "${STEAM_COMPAT_DATA_PATH}_SAC" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Found backed autocloud $CODA '${STEAM_COMPAT_DATA_PATH}_SAC'"
			fi
		fi
		
		if [ -L "$SYM" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Removing old symlink '$SYM'"
			rm "$SYM" 2>/dev/null #remove old symlink
		elif [ -d "$SYM" ]; then
			BACKSCDP="${SYM}-BAK$((100 + RANDOM % 100))"
			writelog "WARN" "${FUNCNAME[0]} - '$SYM' does still exist as directory - renaming to '$BACKSCDP'"
			mv "$SYM" "$BACKSCDP"		
		fi
		
		writelog "INFO" "${FUNCNAME[0]} - Creating symlink via 'ln -s \"$DIR\" \"$SYM\"'"
		ln -s "$DIR" "$SYM"
		notiShow "$(strFix "$NOTY_GLOBALTWEAK" "$DIR")"

		SPVF="$STEAM_COMPAT_DATA_PATH/${SHOSTL}-version"
		if [ ! -f "$SPVF" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Creating '$SPVF' with version '$DESTPROT'"
			echo "$DESTPROT" > "$SPVF"
		else
			SCDPSPV="$(cat "$SPVF")"
			if [ "$SCDPSPV" == "$DESTPROT" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Found '$SPVF' with version '$DESTPROT'"
			else
				writelog "INFO" "${FUNCNAME[0]} - Proton version '$SCDPSPV' in '$SPVF' doesn't match expected version '$DESTPROT' DEBUG"
			fi
		fi

		if [ "$REDIRCOMPDATA" == "global-proton" ]; then
			UBAID="${STEAM_COMPAT_DATA_PATH}/used_by-$AID"
			if [ ! -f "$UBAID" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Creating '$UBAID'" # and trying to trigger Steam First Time Setup"
				touch "$UBAID"
#				reCreateCompatdata "ccd" "$AID" - probably requires a rewrite if possible at all
			fi
		fi
		
		checkCompatdataSteamUser
	}
	
	function checkCompatdataSymlink {
		if [ -L "$STEAM_COMPAT_DATA_PATH" ] || [ -d "$STEAM_COMPAT_DATA_PATH" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Using $CODA '$REDIRCOMPDATA' mode"

			PVF="$STEAM_COMPAT_DATA_PATH/version"
			SCDPPV="$(cat "$PVF")"
			
			SPVF="$STEAM_COMPAT_DATA_PATH/${PROGNAME,,}-version"
			SCDPSPV="$(cat "$SPVF")"
			
			if [ -f "$SPVF" ]; then
				if [ "$SCDPSPV" == "$DESTPROT" ]; then
					writelog "INFO" "${FUNCNAME[0]} - Proton version '$SCDPSPV' in '$SPVF' matches expected version '$DESTPROT' (allowing minor version mismatch)"
					CDPVOK=1
				else
					writelog "INFO" "${FUNCNAME[0]} - Proton version '$SCDPSPV' in '$SPVF' is not the expected version '$DESTPROT'"
					CDPVOK=0
				fi
			else
				if [ ! -f "$PVF" ] && [ -d "$STEAM_COMPAT_DATA_PATH" ]; then
					writelog "INFO" "${FUNCNAME[0]} - STEAM_COMPAT_DATA_PATH doesn't have a proton version file '$PVF'"
					writelog "INFO" "${FUNCNAME[0]} - Steam probably just re-created the $CODA by creating the steam_autocloud.vdf"
					writelog "INFO" "${FUNCNAME[0]} - Moving the $CODA out of the way"
					mv "$STEAM_COMPAT_DATA_PATH" "${STEAM_COMPAT_DATA_PATH}_SAC"
					SCDPPV=0
				elif [ ! -f "$PVF" ] && [ -L "$STEAM_COMPAT_DATA_PATH" ]; then
					writelog "INFO" "${FUNCNAME[0]} - STEAM_COMPAT_DATA_PATH is a symlink - it should have a '$PVF' though - $(ls -la "$PVF") DEBUG"
					SCDPPV=0
				fi
				
				if [ "$SCDPPV" == "$DESTPROT" ] || [ "$SCDPPV" == "${ORGUSEPROTON//proton-}" ]; then
					writelog "INFO" "${FUNCNAME[0]} - Proton in $CODA '$STEAM_COMPAT_DATA_PATH' matches the expected version '$DESTPROT' (allowing minor version mismatch)"
					CDPVOK=1
				else
					writelog "INFO" "${FUNCNAME[0]} - Proton in $CODA '$STEAM_COMPAT_DATA_PATH' has not the expected version '$DESTPROT' but '$SCDPPV'"
					CDPVOK=0
				fi
			fi
		fi

		if [ -L "$STEAM_COMPAT_DATA_PATH" ]; then
			writelog "INFO" "${FUNCNAME[0]} - '$STEAM_COMPAT_DATA_PATH' is already a symbolic link - comparing versions"

			if [ "$(readlink "$STEAM_COMPAT_DATA_PATH")" == "$DESTCOMPDATA" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Symlink '$STEAM_COMPAT_DATA_PATH' points correctly to the expected directory '$DESTCOMPDATA'"
				CDSYMOK=1
			else
				writelog "WARN" "${FUNCNAME[0]} - Symlink '$STEAM_COMPAT_DATA_PATH' does not point correctly to the expected directory '$DESTCOMPDATA', but instead to '$(readlink "$STEAM_COMPAT_DATA_PATH")'"
				CDSYMOK=0
			fi

			if [ "$CDSYMOK" -eq 1 ] && [ "$CDPVOK" -eq 1 ]; then
				writelog "INFO" "${FUNCNAME[0]} - Both $CODA symlink '$STEAM_COMPAT_DATA_PATH' and Proton version are correct - nothing to do here"
			elif [ "$CDSYMOK" -eq 1 ] && [ "$CDPVOK" -eq 0 ]; then
				writelog "INFO" "${FUNCNAME[0]} - $CODA symlink '$STEAM_COMPAT_DATA_PATH' is correct, but Proton version is not - this is unusual but continuing anyway"
			elif [ "$CDSYMOK" -eq 0 ] && [ "$CDPVOK" -eq 1 ]; then
				writelog "INFO" "${FUNCNAME[0]} - $CODA symlink '$STEAM_COMPAT_DATA_PATH' is not the expected one, but Proton version matches - assuming manual configuration from the user and using it"
			elif [ "$CDSYMOK" -eq 0 ] && [ "$CDPVOK" -eq 0 ]; then
				writelog "INFO" "${FUNCNAME[0]} - $CODA symlink '$STEAM_COMPAT_DATA_PATH' is not the expected one and Proton version doesn't match as well, assuming the Proton version was changed - redirecting $CODA to '$DESTCOMPDATA'"
				SetCompatdataSymlink "$DESTCOMPDATA" "$STEAM_COMPAT_DATA_PATH"
			fi				
		elif [ -d "$STEAM_COMPAT_DATA_PATH" ]; then		
			writelog "INFO" "${FUNCNAME[0]} - '$STEAM_COMPAT_DATA_PATH' is the original directory"
			if [ -d "$DESTCOMPDATA" ]; then # probably not worth to check the proton version in $DESTCOMPDATA here as well(?)
				BACKSCDP="${STEAM_COMPAT_DATA_PATH}-BAK$((100 + RANDOM % 100))"
				writelog "INFO" "${FUNCNAME[0]} - '$DESTCOMPDATA' does already exist - moving '$STEAM_COMPAT_DATA_PATH' to '$BACKSCDP' and setting symlink"
				mv "$STEAM_COMPAT_DATA_PATH" "$BACKSCDP"
				SetCompatdataSymlink "$DESTCOMPDATA" "$STEAM_COMPAT_DATA_PATH"
			else
				if [ "$CDPVOK" -eq 1 ]; then
					writelog "INFO" "${FUNCNAME[0]} - '$DESTCOMPDATA' does not yet exist, moving '$STEAM_COMPAT_DATA_PATH' as the Proton version is correct and creating symlink"
					mv "$STEAM_COMPAT_DATA_PATH" "$DESTCOMPDATA"
					SetCompatdataSymlink "$DESTCOMPDATA" "$STEAM_COMPAT_DATA_PATH"
				else
					writelog "INFO" "${FUNCNAME[0]} - '$DESTCOMPDATA' does not yet exist, creating a new one, because '$STEAM_COMPAT_DATA_PATH' uses an incorrect Proton version"
					BACKSCDP="${STEAM_COMPAT_DATA_PATH}-BAK$((100 + RANDOM % 100))"
					writelog "INFO" "${FUNCNAME[0]} - Renaming '$STEAM_COMPAT_DATA_PATH' to '$BACKSCDP' and setting symlink"
					mv "$STEAM_COMPAT_DATA_PATH" "$BACKSCDP"
					SetCompatdataSymlink "$DESTCOMPDATA" "$STEAM_COMPAT_DATA_PATH"
				fi
			fi
		else
			writelog "INFO" "${FUNCNAME[0]} - '$STEAM_COMPAT_DATA_PATH' is neither a directory nor a symbolic link - creating it"
			SetCompatdataSymlink "$DESTCOMPDATA" "$STEAM_COMPAT_DATA_PATH"
		fi		
	}

	function fixDestCompat {
		DESTCOMPDATA2="${DESTCOMPDATA//--/-}"
		if [ -d "$DESTCOMPDATA" ] && [ ! -d "$DESTCOMPDATA2" ] && [ "$DESTCOMPDATA" != "$DESTCOMPDATA2" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Renaming old '${DESTCOMPDATA##*/}' to '${DESTCOMPDATA2##*/}'"
			mv "$DESTCOMPDATA" "$DESTCOMPDATA2"
			DESTCOMPDATA="$DESTCOMPDATA2"
		fi		
	}

	if [ -n "$STEAM_COMPAT_DATA_PATH" ]; then # should be enough
		VERSFIX="$(grep "${USEPROTON%-*}" "$PROTONCSV" | cut -d ';' -f1 | sort -nr | head -n1)"
		if [ -n "$VERSFIX" ]; then
			DESTPROT1="${VERSFIX//proton-}"
			writelog "INFO" "${FUNCNAME[0]} - Using Proton version with minor version fix '$DESTPROT1' for $CODA directory name"
		else
			DESTPROT1="${USEPROTON//proton-}"
			writelog "INFO" "${FUNCNAME[0]} - Using Proton version '$DESTPROT1' for '$CODA' directory name"
		fi

		DESTPROT="${DESTPROT1//Proton}"
		# above might have to be expanded later, depending on proton names
		
		if [ "$REDIRCOMPDATA" == "single-proton" ]; then
			DESTCOMPDATA="${STEAM_COMPAT_DATA_PATH//${STEAM_COMPAT_DATA_PATH##*/}/${PROGNAME,,}\/${STEAM_COMPAT_DATA_PATH##*/}-proton-${DESTPROT}}"
			fixDestCompat
			checkCompatdataSymlink
		elif [ "$REDIRCOMPDATA" == "global-proton" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Using global 'STEAM_COMPAT_DATA_PATH'"
			DESTCOMPDATA="$STLPROTCOMPDATDIR/${CODA}-proton-${DESTPROT}"
			fixDestCompat
			checkCompatdataSymlink
		else
			writelog "INFO" "${FUNCNAME[0]} - Using regular $CODA '$STEAM_COMPAT_DATA_PATH'"
			if [ -L "$STEAM_COMPAT_DATA_PATH" ]; then
				rm "${STEAM_COMPAT_DATA_PATH}/used_by-$AID" 2>/dev/null
				writelog "INFO" "${FUNCNAME[0]} - '$STEAM_COMPAT_DATA_PATH' is a symlink. Removing it, as REDIRCOMPDATA is $REDIRCOMPDATA"
				rm "$STEAM_COMPAT_DATA_PATH"
				mkProjDir "$STEAM_COMPAT_DATA_PATH"
			fi
		fi
	fi
}

function launchIGCS {
	IGCSPROCESS="$(grep "^Process=" "$IGCSINI" | cut -d '=' -f2)"
	writelog "INFO" "${FUNCNAME[0]} - Injecting '$IGCSDLL' into exe '${IGCSPROCESS%.*}' using '$IGCS'"
	writelog "INFO" "${FUNCNAME[0]} - IGCSDST '$IGCSDST'"
	rm "$IGCSINITLOCK" 2>/dev/null
	extProtonRun "R" "$IGCSDST"
}

function injectIGCS {
	writelog "INFO" "${FUNCNAME[0]} - Starting '$IGCS'"
	waitForGamePid
	writelog "INFO" "${FUNCNAME[0]} - Game is running, starting '$IGCS' in '$IGCSWAIT' seconds"
	touch "$IGCSINITLOCK"
	sleep "$IGCSWAIT"
	launchIGCS
}

function postIGCS {
	COUNTER=0

	while [ ! -f "$IGCSINITLOCK" ]; do
		writelog "INFO" "${FUNCNAME[0]} - Waiting for $IGCSINITLOCK to appear"
		if [ -f "$CLOSETMP" ] || [[ "$COUNTER" -ge "$IGCSWAIT" ]]; then
			break
		fi
		COUNTER=$((COUNTER+1))
		sleep 1
	done
	
	writelog "INFO" "${FUNCNAME[0]} - Waited '$COUNTER/$IGCSWAIT' seconds"

	IGCSWAITLEFT=$((IGCSWAIT - COUNTER + 2))
	writelog "INFO" "${FUNCNAME[0]} - Waiting (max $IGCSWAITLEFT more seconds) for $IGCS to initialize"
	COUNTER=0
	
	while [ -f "$IGCSINITLOCK" ]; do
		if [ -f "$CLOSETMP" ] || [[ "$COUNTER" -ge "$IGCSWAITLEFT" ]]; then
			break
		fi
		COUNTER=$((COUNTER+1))
		sleep 1
	done

	COUNTER=0
	if [ -f "$IGCSINITLOCK" ]; then
		writelog "SKIP" "${FUNCNAME[0]} - Lock file $IGCSINITLOCK still exists - giving up"
	else
		COUNTER=0
		WAITWIN=3
		writelog "INFO" "${FUNCNAME[0]} - $IGCS just started, now waiting a bit for its window"

		IGCSWIN="$("$XDO" search --name "$IGCS")"
		# use if $IGCS alone also matches games window:
		# IGCSWIN="$("$XDO" search --name "$SA.*.$IGCS")" # =+ steamapps
		while ! [ "$IGCSWIN" -eq "$IGCSWIN" ] 2>/dev/null; do
			if [[ "$COUNTER" -ge "$WAITWIN" ]]; then
				break
			fi
			COUNTER=$((COUNTER+1))
			sleep 1
		done

		writelog "INFO" "${FUNCNAME[0]} - Closing '$IGCS' window '$IGCSWIN'"
		"$XDO" windowactivate --sync "$IGCSWIN"	key "KP_Enter"

		writelog "INFO" "${FUNCNAME[0]} - And minimize false-positive UUU warn window"
		IGCSPROCESS="$(grep "^Process=" "$IGCSINI" | cut -d '=' -f2)"
		"$XDO" windowminimize "$("$XDO" search --name "${IGCSPROCESS%.*}")"

		if [ -f "$GWXTEMP" ]; then
			WIFO="$(cat "$GWXTEMP")"
			writelog "INFO" "${FUNCNAME[0]} - Setting focus on window '$WIFO'"
			"$XDO" windowactivate "$WIFO"
		else
			writelog "INFO" "${FUNCNAME[0]} - No '$GWXTEMP' found"
		fi
	fi
}
	
function selectIGCSdll {
	if [ -d "$EFD" ]; then
		fixShowGnAid
		export CURWIKI="$PPW/$IGCS"
		TITLE="${PROGNAME}-Select-IGCS-dll"
		pollWinRes "$TITLE"
		setShowPic
		
		PICKIGCSDLL="$("$YAD" --f1-action="$F1ACTION" --image "$SHOWPIC" --image-on-top --window-icon="$STLICON" --form --center --on-top "$WINDECO" \
		--separator="" --title="$TITLE" \
		--text="$(spanFont "$SGNAID - $GUI_SELECTIGCSDLL" "H")" \
		--field=" ":LBL " " \
		--field="$GUI_SELECTDLL":FL "${EFD}" --file-filter="$GUI_DLLFILES (*.dll)| *.dll" "$GEOM")"
		if [ -f "$PICKIGCSDLL" ]; then
			IGCSDLL="${PICKIGCSDLL##*/}"
			if [ ! -f "$EFD/$IGCSDLL" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Copying selected dll '$PICKIGCSDLL' to '$EFD'"
				cp "$PICKIGCSDLL" "$EFD"
			fi
			IGCSINI="$EFD/${IGCS}.ini"
			writelog "INFO" "${FUNCNAME[0]} - Inserting '$IGCSDLL' into '$IGCSINI'"
			sed "/^Dll=/d" -i "$IGCSINI"
			echo "Dll=$IGCSDLL" >> "$IGCSINI"
		else
			writelog "SKIP" "${FUNCNAME[0]} - No dll selected - skipping"
		fi
	fi
}

function createUUUPatchCommand {
	echo "$XDO windowactivate \"GAMEWINXID\" && sleep 1 && $XDO key \"grave\" && $XDO type \"exec $UUUPATCH\" && $XDO key \"KP_Enter\"" > "$UUUPATCHCOMMAND"
	chmod +x "$UUUPATCHCOMMAND"
}

function getGameWXID {
	if [ -n "$VRPGWINXIS" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Using found variable VRPGWINXIS '$VRPGWINXIS' as GAMEWINXID"
		GAMEWINXID="$VRPGWINXIS"
	fi

	if [ -n "$GAMEWINXID" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Already have the windowid '$GAMEWINXID'"
	else
		GAMEWINPID="$(getGameWindowPID)"
		writelog "INFO" "${FUNCNAME[0]} - Determining GAMEWINXID via GAMEWINPID '$GAMEWINPID'"
		GAMEWINXID="$(getGameWinXIDFromPid "$GAMEWINPID")"
 	fi

	if [ -n "$GAMEWINXID" ]; then
		export VRPGWINXIS="$GAMEWINXID"
	fi
}

function injectUUUPatch {
	if [ "$(find "$EFD" -name "$UUUPATCH" | wc -l)" -ge 1 ]; then
		writelog "INFO" "${FUNCNAME[0]} - starting UUU patch command auto executing '$UUUPATCH'"
		waitForGamePid
		getGameWXID

		if [ -n "$GAMEWINXID" ]; then
			echo "$GAMEWINXID" > "$GWXTEMP"
			
			sed "s:GAMEWINXID:$GAMEWINXID:g" -i "$UUUPATCHCOMMAND"
			writelog "INFO" "${FUNCNAME[0]} - starting patch command auto executing '$UUUPATCH'"
			
			if [ "$UUUPATCHWAIT" -ge 1 ]; then
				writelog "INFO" "${FUNCNAME[0]} - Game is running, starting UUU patch command '$UUUPATCHCOMMAND' in '$UUUPATCHWAIT' seconds"
				if [ ! -f "$TRAYCUSC" ] || grep -q "$UUUPATCH" "$TRAYCUSC"; then
					cp "$UUUPATCHCOMMAND" "$TRAYCUSC"
				fi
				sleep "$UUUPATCHWAIT"
				"$UUUPATCHCOMMAND"
			else
				writelog "INFO" "${FUNCNAME[0]} - UUUPATCHWAIT is '$UUUPATCHWAIT', so placing the UUU patch command behind the TrayIcon command '$TRAY_LCS' for manual execution"
				cp "$UUUPATCHCOMMAND" "$TRAYCUSC"
			fi
		else
			writelog "SKIP" "${FUNCNAME[0]} - game window id could not be found - can't start the UUU patch command"
		fi
	else
		writelog "SKIP" "${FUNCNAME[0]} - UE4 console script '$UUUPATCH' not found in game directory '$EFD'"
	fi
}

function checkUUUPatchLaunch {
	if [ "$UUUSEPATCH" -eq 1 ] || [ "$UUUSEVR" -eq 1 ]; then
		createUUUPatchCommand	
		injectUUUPatch &
	fi
}

function prepareUEVRpatch {
	if [ "$UUUSEVR" -eq 1 ]; then
		UUUPATCHFILE="$1"

		if [ ! -f "$UUUPATCHFILE" ]; then
			if [ -f "$GLOBALMISCDIR/${UUUPATCH}-${AID}" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Copying game specific '$GLOBALMISCDIR/${UUUPATCH}-${AID}' to '$UUUPATCHFILE'"
				cp "$GLOBALMISCDIR/$UUUPATCH-${AID}" "$UUUPATCHFILE"
			elif [ -f "$GLOBALMISCDIR/${UUUPATCH}" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Copying generic '$GLOBALMISCDIR/${UUUPATCH}' to '$UUUPATCHFILE'"
				cp "$GLOBALMISCDIR/$UUUPATCH" "$UUUPATCHFILE"
			else
				writelog "WARN" "${FUNCNAME[0]} - No source '$UUUPATCH' file found in '$GLOBALMISCDIR'"
			fi
		else
			writelog "INFO" "${FUNCNAME[0]} - '$UUUPATCHFILE' already available"
		fi
	fi	
}

function checkIGCSInjector {

	if [ "$UUUSEPATCH" -eq 1 ] || [ "$UUUSEVR" -eq 1 ]; then
		writelog "INFO" "${FUNCNAME[0]} - Enabling '$UUU' with '$IGCS' as UUU patch mode is enabled"
		UUUSEIGCS=1
	fi

	if [ "$UUUSEIGCS" -eq 1 ]; then
		writelog "INFO" "${FUNCNAME[0]} - Using '$UUU' with '$IGCS' is enabled"
		USEIGCS=1
	fi
	
	if [ "$USEIGCS" -eq 1 ]; then
		IGCSEXE="${IGCS}.exe"
		IGCSDST="$EFD/$IGCSEXE"
		if [ ! -f "$IGCSDST" ]; then
			writelog "INFO" "${FUNCNAME[0]} - '$IGCSDST' not found"
			IGCSDL="$STLDLDIR/igcs/"
			IGCSSRC="$IGCSDL/$IGCSEXE"
			mkProjDir "$IGCSDL"

			if [ ! -f "$IGCSSRC" ]; then
				IGCSDST="$IGCSDL/${IGCSZIP##*/}"
				if [ ! -f "$IGCSDST" ]; then
					 "$IGCSZIP" "$IGCSDST" "X" "'$IGCSDST' not found - downloading automatically from '$IGCSZIP'"
				fi
				"$UNZIP" "$IGCSDST" -d "$IGCSDL"
			fi
			
			if [ -f "$IGCSSRC" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Copying '$IGCSSRC' to '$IGCSDST'"
				cp "$IGCSSRC" "$IGCSDST"
			fi
		else
			writelog "INFO" "${FUNCNAME[0]} - '$IGCSDST' found"
		fi
		
		if [ -f "$IGCSDST" ]; then
			IGCSINI="$EFD/${IGCS}.ini"
			WSE="$(find "$EFD" -name "*-Win64-Shipping.exe" | head -n1)"

			if [ -n "$WSE" ]; then
				prepareUEVRpatch "${WSE%/*}/../$UUUPATCH"
			fi
			
			if [ ! -f "$IGCSINI" ]; then
				writelog "INFO" "${FUNCNAME[0]} - '$IGCSINI' not found - creating it"
				echo "[InjectionData]" > "$IGCSINI"
				echo "Process=$GAMEEXE" >> "$IGCSINI"
				if [ "$UUUSEIGCS" -eq 1 ]; then
					writelog "INFO" "${FUNCNAME[0]} - WSE is '$WSE'"
					
					if [ -n "$WSE" ]; then
						echo "Process=${WSE##*/}" >> "$IGCSINI"
					else
						echo "Process=$GAMEEXE" >> "$IGCSINI"
					fi
					writelog "INFO" "${FUNCNAME[0]} - Using '${UUU}.dll' as dll in '$IGCSINI'"
					echo "Dll=${UUU}.dll" >> "$IGCSINI"
				else
					echo "Process=$GAMEEXE" >> "$IGCSINI"
				fi
			fi
			
			IGCSDLL="$(grep "^Dll=" "$IGCSINI" | cut -d '=' -f2)"
			if [ "$UUUSEIGCS" -eq 1 ]; then
				if [ "$IGCSDLL" != "${UUU}.dll" ]; then
					writelog "INFO" "${FUNCNAME[0]} - Updating dll in '$IGCSINI' to '${UUU}.dll' because 'UUUSEIGCS' is enabled"
					sed "/^Dll=/d" -i "$IGCSINI"
					echo "Dll=${UUU}.dll" >> "$IGCSINI"
				fi
			fi

			IGCSDLL="$(grep "^Dll=" "$IGCSINI" | cut -d '=' -f2)"
			if [ ! -f "$EFD/$IGCSDLL" ]; then
				if [ "$UUUSEIGCS" -eq 1 ]; then
					UUUDL="$STLDLDIR/uuu"
					UUUSRC="$UUUDL/$IGCSDLL"
					mkProjDir "$UUUDL"	
					writelog "INFO" "${FUNCNAME[0]} - 'UUUSEIGCS' is enabled, but '$EFD/$IGCSDLL' is not available - checking if '$UUUSRC' is available"
					if [ ! -f "$UUUSRC" ]; then
						writelog "WARN" "${FUNCNAME[0]} -'$UUUSRC' was not found - opening Info requester, because it needs to be downloaded manually from '$UUUURL' and extracted to '$UUUDL'"
						export CURWIKI="$PPW/$UUU"
						TITLE="${PROGNAME}-$UUU-Info"
						pollWinRes "$TITLE"
						setShowPic
						XDGO="xdg-open"

						"$YAD" --f1-action="$F1ACTION" --image "$SHOWPIC" --image-on-top --window-icon="$STLICON" --form --center --on-top "$WINDECO" \
						--title="$TITLE" --text="$(spanFont "$(strFix "$GUI_UUUINFO1" "$UUU")" "H")" \
						--field="Url: :RW" "$UUUURL" \
						--field="$GUI_UUUINFO2:LBL" " " \
						--field="$UUUDL":FBTN "$XDGO $UUUDL" "$GEOM"
					fi
					
					if [ -f "$UUUSRC" ]; then
						writelog "INFO" "${FUNCNAME[0]} - Copying '$UUUSRC' to '$EFD'"
						cp "$UUUSRC" "$EFD"
					else
						writelog "SKIP" "${FUNCNAME[0]} -'$UUUSRC' could not be found - skipping"
					fi
				else
					writelog "INFO" "${FUNCNAME[0]} - No valid dll found in '$IGCSINI' - Choose one"
					selectIGCSdll
				fi
			fi

			IGCSDLL="$(grep "^Dll=" "$IGCSINI" | cut -d '=' -f2)"
			if [ -f "$EFD/$IGCSDLL" ]; then
				injectIGCS &
				postIGCS &
			else
				writelog "SKIP" "${FUNCNAME[0]} - Still no valid dll found in '$IGCSINI' - giving up"
			fi
		else
			writelog "SKIP" "${FUNCNAME[0]} - '$IGCSDST' not found and could not be created - skipping '$IGCS'"
		fi
	fi
}

function injectCustomProg {
	writelog "INFO" "${FUNCNAME[0]} - 'Injecting' custom command - i.e. starting delayed"
	waitForGamePid
	writelog "INFO" "${FUNCNAME[0]} - Game is running, starting custom command in '$INJECTWAIT' seconds"
	sleep "$INJECTWAIT"
	launchCustomProg
}

function checkCustomLaunch {
	if [ "$ONLYWICO" -eq 1 ]; then
		# only start $WICO 
		writelog "INFO" "${FUNCNAME[0]} - 'ONLYWICO' is enabled - starting only $WICO"
		launchCustomProg "ONLYWICO"
	else
		# start a custom program:
		if [ -n "$USECUSTOMCMD" ] ; then
			if [ "$USECUSTOMCMD" -eq 1 ] ; then
				writelog "INFO" "${FUNCNAME[0]} - USECUSTOMCMD is set to '$USECUSTOMCMD' - trying to start custom program '$CUSTOMCMD'"
			
				if [ "$INJECT_CUSTOMCMD" -eq 1 ]; then
					injectCustomProg &
				else
					# fork in background and continue
					if [ "$ONLY_CUSTOMCMD" -eq 1 ]; then
						SECONDS=0
					fi

					if [ "$FORK_CUSTOMCMD" -eq 1 ]; then
						writelog "INFO" "${FUNCNAME[0]} - FORK_CUSTOMCMD is set to 1 - forking the custom program in background and continue"
						launchCustomProg
					# or wait
					else
						writelog "INFO" "${FUNCNAME[0]} - FORK_CUSTOMCMD is set to 0 - starting the custom program regularly"
						launchCustomProg
					fi

					if [ "$ONLY_CUSTOMCMD" -eq 1 ]; then
						writelog "INFO" "${FUNCNAME[0]} - ONLY_CUSTOMCMD is set to 1 means only custom program '$CUSTOMCMD' is supposed to start - exiting here"
						duration=$SECONDS
						logPlayTime "$duration"
						writelog "INFO" "${FUNCNAME[0]} - ## CUSTOMCMD STOPPED after '$duration' seconds playtime"
						closeSTL " ######### STOP EARLY $PROGNAME $PROGVERS #########"
						exit
					fi
				fi
			else
				if [ -n "$CUSTOMCMD" ] && [[ ! "$CUSTOMCMD" =~ ${DUMMYBIN}$ ]]; then
					writelog "SKIP" "${FUNCNAME[0]} - USECUSTOMCMD is '$USECUSTOMCMD' therefore skipping the custom program '$CUSTOMCMD'"
				fi
			fi
		fi
	fi
}

function setFWSArch {
	if [ -z "$FWSARCH" ]; then
		FWSARCH="64"
		if [ -n "$GP" ] && [ -f "$GP" ]; then
			if [ "$(getArch "$GP")" == "32" ]; then
				FWSARCH="32"
			fi
		fi
	fi
}

function dlFWS {
	setFWSArch
	mkProjDir "$FWSDLDIR/$FWSARCH"
	DSTFILE="${FWS,,}_x64.zip"

	if [ "$FWSARCH" == "32" ]; then
		DSTFILE="${DSTFILE//_x64}"
		SPAT="86"
	else
		SPAT="64"
	fi
	DLCHK="md5sum"

	INCHK="$("$WGET" -q "${FWSURL%%/fws*}" -O - 2> >(grep -v "SSL_INIT") | grep -A1 "x${SPAT} ZIP Package" | grep MD5 | grep -oP '> \K[^<]+')"
	DLDST="$FWSDLDIR/$FWSARCH/$DSTFILE"
	
	if [ ! -f "$DLDST" ]; then
		notiShow "$(strFix "$NOTY_DLCUSTOMPROTON" "$DSTFILE")"
		dlCheck "$FWSURL/$DSTFILE" "$DLDST" "$DLCHK" "Downloading '$DSTFILE'" "$INCHK"
	fi

	FWSEXE="$FWSDLDIR/$FWSARCH/${FWS}.exe"
	if [ ! -f "$FWSEXE" ]; then
		if [ -f "$DLDST" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Extracting $DSTFILE in '$FWSDLDIR/$FWSARCH'"
			"$UNZIP" -q "$DLDST" -d "$FWSDLDIR/$FWSARCH"
		else
			writelog "SKIP" "${FUNCNAME[0]} - Downloading '$FWS' failed! Disabling '$FWS'"
			USEFWS=0
		fi
	fi

	if [ ! -f "$FWSEXE" ]; then
		writelog "SKIP" "${FUNCNAME[0]} - Extracting '$FWS' failed! Disabling '$FWS'"
		USEFWS=0
	fi
}

function checkFWS {
	if [ "$USEFWS" -eq 1 ]; then
		dlFWS
		if [ "$USEFWS" -eq 1 ]; then
			writelog "INFO" "${FUNCNAME[0]} - 'USEFWS' is enabled - starting '$FWS' exe '$FWSEXE'"
			setFWSArch
			IPAK="vcrun2010-x64"
			if [ "$FWSARCH" == "32" ]; then
				IPAK="${IPAK//x64/x86}"
			fi
			writelog "INFO" "${FUNCNAME[0]} - Installing '$IPAK' into '$GPFX' using '$RUNWINE'"
			installSteWoShPak "$IPAK" "$GPFX" "$RUNWINE"
			writelog "INFO" "${FUNCNAME[0]} - Starting '$FWSEXE' forked into the background"
			restoreOrgVars
			(sleep 2; "$RUNPROTON" run "$FWSEXE") &
			emptyVars "O" "X"
		fi
	fi
}

function togWindows {
	function windowminimize {
		rm "$STLMINWIN" 2>/dev/null
		while read -r WN; do
			WINNAME="${WN##*[[:blank:]]}"
			if "$XPROP" -id "$WINNAME" | grep "_NET_WM_ACTION_MINIMIZE" -q ; then
				if "$XPROP" -id "$WINNAME" | grep "_NET_WM_STATE_HIDDEN" -q ; then
					writelog "SKIP" "${FUNCNAME[1]} ${FUNCNAME[0]} - Skipping minimized '$WINNAME'"
				else
					writelog "INFO" "${FUNCNAME[1]} ${FUNCNAME[0]} - Minimizing '$WINNAME'"
					echo "$WINNAME" >> "$STLMINWIN"
					"$XDO" "${FUNCNAME[0]}" "$WINNAME"
				fi
			fi
		done <<< "$("$XPROP" -root | grep "_NET_CLIENT_LIST(WINDOW)" | cut -d '#' -f2 | tr ',' '\n')"
	}

	function windowraise {
		if [ ! -f "$STLMINWIN" ]; then
			writelog "SKIP" "${FUNCNAME[0]} - Skipping, because no minimized window file STLMINWIN found"
		else
			while read -r WN; do
				WINNAME="${WN##*[[:blank:]]}"
				writelog "INFO" "${FUNCNAME[0]} - Raising '$WINNAME'"
				"$XDO" "${FUNCNAME[0]}" "$WINNAME"
				COUNTER=0
				MAXTRY=3
				while grep -q "_NET_WM_STATE_HIDDEN" -q <<< "$("$XPROP" -id "$WINNAME")"; do
					if [[ "$COUNTER" -ge "$MAXTRY" ]]; then
						echo "$WINNAME" >> "${STLMINWIN}_lazy"
						break
					else
						writelog "INFO" "${FUNCNAME[0]} - '$WINNAME' minimized after $COUNTER tries - raising again"
						"$XDO" "${FUNCNAME[0]}" "$WINNAME"
						COUNTER=$((COUNTER+1))
					fi
				done

			done < "$STLMINWIN"

			if [ -f "${STLMINWIN}_lazy" ]; then
				while read -r WN; do
					WINNAME="${WN##*[[:blank:]]}"
					writelog "INFO" "${FUNCNAME[0]} - Raising lazy '$WINNAME'"
					"$XDO" "${FUNCNAME[0]}" "$WINNAME"
				done < "${STLMINWIN}_lazy"
			fi

			rm "$STLMINWIN" "${STLMINWIN}_lazy" 2>/dev/null
		fi
	}

	if [ "$TOGGLEWINDOWS" -eq 1 ]; then
		writelog "INFO" "${FUNCNAME[0]} - Setting windows to $1"
		"$1"
	fi
}

function installWinetricksPaks {
	WTPAKS="$1"
	WTWINE="$2"
	WTRUN="$3"

	WTSHMLOG="$STLSHM/WINETRICKS.log"
	
	if [ "$WTRUN" == "wineVortexRun" ]; then
		WTPFX="$VORTEXPFX"
	else
		WTPFX="$GPFX"
	fi

	if [ "$USEWINE" -eq 1 ]; then
		 WTPFX="$GWFX"
	fi

	if [ -n "$WTPAKS" ] && [ "$WTPAKS" != "$NON" ] && [ "$WTPAKS" != "0" ]; then
		chooseWinetricks
		mapfile -d " " -t -O "${#INSTPAKS[@]}" INSTPAKS < <(printf '%s' "$WTPAKS")

		WTLOG="$WTPFX/winetricks.log"

		if [ ! -f "$WTLOG" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Installing '$WTPAKS' silently with $WINETRICKS"
			notiShow "$(strFix "$NOTY_WTINST" "$WTPAKS" "$("$WINETRICKS" -V | cut -d ' ' -f1)" "$("$WTWINE" --version)")"
			restoreOrgVars
			if [ -n "$4" ] && [ "$4" == "F" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Using 'force' mode as argument '$4' was given"
				"$WTRUN" "$WINETRICKS" --force --unattended "${INSTPAKS[@]}" >> "$WTSHMLOG" 2>/dev/null
			else
				"$WTRUN" "$WINETRICKS" --unattended "${INSTPAKS[@]}" >> "$WTSHMLOG" 2>/dev/null
			fi
			notiShow "$NOTY_WTFIN"
			emptyVars "O" "X"
			writelog "INFO" "${FUNCNAME[0]} - '$WINETRICKS' Installation of '$WTPAKS' exited"
		fi

		if [ -f "$WTLOG" ]; then
			rmDupLines "$WTLOG"
			if [ ! -f "${WTLOG//.log/.checked}" ]; then
				mapfile -t -O "${#NOTINSTALLED[@]}" NOTINSTALLED <<< "$(comm -23 <(echo "${INSTPAKS[*]}" | tr ' ' '\n' | sort) <(sort < "$WTLOG"))"
				if [ -n "${NOTINSTALLED[0]}" ]; then
					writelog "INFO" "${FUNCNAME[0]} - Trying to installing following new or previously missed packages now: '${NOTINSTALLED[*]}'"
					notiShow "$(strFix "$NOTY_WTINST" "${NOTINSTALLED[*]}" "$("$WINETRICKS" -V | cut -d ' ' -f1)" "$("$WTWINE" --version)")"
					"$WTRUN" "$WINETRICKS" --force --unattended "${NOTINSTALLED[@]}" >> "$WTSHMLOG" 2>/dev/null
					notiShow "$NOTY_WTFIN"
				else
					writelog "INFO" "${FUNCNAME[0]} - All packages of '$WTPAKS' are already installed - nothing to do"
					touch "${WTLOG//.log/.checked}"
				fi
				unset NOTINSTALLED
			else
				writelog "INFO" "${FUNCNAME[0]} - Found ${WTLOG//.log/.checked} - Nothing to do"
			fi
		fi
		unset INSTPAKS
	fi
}

# start winetricks before game launch:
function checkWinetricksLaunch {
	# gui:
	if [ -n "$RUN_WINETRICKS" ]; then
		if [ "$RUN_WINETRICKS" -eq 1 ]; then
			writelog "INFO" "${FUNCNAME[0]} - Launching '$WINETRICKS' before game start"
			extWine64Run "$WINETRICKS" --gui  >> "$STLSHM/WINETRICKS_GUI.log" 2>/dev/null
		fi
	fi
	# silent:
	installWinetricksPaks "$WINETRICKSPAKS" "$RUNWINE" "extWine64Run"
}

function chooseWinetricks {
	if [ -z "$WINETRICKS" ]; then
		if [ "$DLWINETRICKS" -eq 1 ]; then

			WTDLLAST="${WTDLDIR}.txt"
			MAXAGE=1440

			if [ ! -f "$DLWT" ] || [ ! -f "$WTDLLAST" ] || test "$(find "$WTDLLAST" -mmin +"$MAXAGE")"; then
				gitUpdate "$WTDLDIR" "$WINETRICKSURL"
				echo "$(date) - ${FUNCNAME[0]}" > "$WTDLLAST"
			fi

			if [ -f "$DLWT" ]; then
				WINETRICKS="$DLWT"
				writelog "INFO" "${FUNCNAME[0]} - Using '$DLWT' with version '$($DLWT -V | cut -d ' ' -f1)'"
			else
				writelog "SKIP" "${FUNCNAME[0]} - DLWINETRICKS is set to '$DLWINETRICKS', but '$DLWT' was not found!"
			fi
		else
			if [ -x "$(command -v "$SYSWINETRICKS")" ]; then
				WINETRICKS="$SYSWINETRICKS"
				writelog "INFO" "${FUNCNAME[0]} - Using systemwide winetricks with version '$($SYSWINETRICKS -V | cut -d ' ' -f1)'"
			fi	
		fi
	fi
}

function SetWineDebugChannels {
	if [ -n "$1" ]; then
		AID="$1"
		setAIDCfgs
	fi
	loadCfg "$STLGAMECFG"
	fixShowGnAid
	export CURWIKI="$PPW/Wine-Debug"
	TITLE="${PROGNAME}-${FUNCNAME[0]}"
	pollWinRes "$TITLE"
	setShowPic	

	WDCTXT="winedebugchannels.txt"
	WDC="$GLOBALMISCDIR/$WDCTXT"

	WDCSEL="$(
	while read -r wtch; do
		if grep -q "\-${wtch}" <<< "$STLWINEDEBUG"; then
			echo TRUE
		else
			echo FALSE
		fi
		if grep -q "+${wtch}" <<< "$STLWINEDEBUG"; then
			echo TRUE
		else
			echo FALSE
		fi
		echo "$wtch"
	done < "$WDC" | \
	"$YAD" --f1-action="$F1ACTION" --image "$SHOWPIC" --image-on-top --window-icon="$STLICON" --center "$WINDECO" --list --checklist --column="$GUI_MINUS":CHK --column="$GUI_PLUS":CHK --column="$GUI_WDCH" --separator=";" --print-all \
	--text="$(spanFont "$(strFix "$GUI_WDCDIALOG" "$SGNAID")" "H")" --title="$TITLE" --button="$BUT_CAN:0" --button="$BUT_SELECT:2" "$GEOM")"
	case $? in
		0)	{
				writelog "INFO" "${FUNCNAME[0]} - Selected '$BUT_CAN' - Cancelling selection"
			}
		;;
		2)	{
				writelog "INFO" "${FUNCNAME[0]} - Selected '$BUT_SELECT' - Saving Debug Options"

				if [ -z "$WDCSEL" ]; then
					writelog "INFO" "${FUNCNAME[0]} - Nothing selected"
				else
					unset STLWINEDEBUG
					while read -r chanline;do
						chan="$(cut -d ';' -f3 <<< "$chanline")"
						if grep -q "TRUE;FALSE" <<< "$chanline"; then
							STLWINEDEBUG="${STLWINEDEBUG},-${chan}"
						elif grep -q "FALSE;TRUE" <<< "$chanline"; then
							STLWINEDEBUG="${STLWINEDEBUG},+${chan}"
						elif grep -q "TRUE;TRUE" <<< "$chanline"; then
							STLWINEDEBUG="${STLWINEDEBUG},-${chan}"
						fi
					done <<< "$WDCSEL"
					touch "$FUPDATE"
					writelog "INFO" "${FUNCNAME[0]} - Saving following Wine Debug options: '$STLWINEDEBUG'"
					updateConfigEntry "STLWINEDEBUG" "${STLWINEDEBUG#,*}" "$STLGAMECFG"
				fi
			}
		;;
	esac
}

function WinetricksPick {
	WTPREF="$1"

	unset CURWTPAKS OTHERPAKS PAKSEL

	if [ "$WINETRICKSPAKS" == "$NON" ]; then
		declare -a CURWTPAKS
	else
		mapfile -d " " -t -O "${#CURWTPAKS[@]}" CURWTPAKS <<< "$(printf '%s\n' "$WINETRICKSPAKS" | sed '/^[[:space:]]*$/d')"
	fi

	while read -r line; do
		mapfile -d " " -t -O "${#PAKSEL[@]}" PAKSEL <<< "${line%% *}"
	done <<< "$(winetricks "$WTPREF" list)"

	while read -r curpak; do
	if [[ ! "${PAKSEL[*]}" =~ $curpak ]]; then
		mapfile -d " " -t -O "${#OTHERPAKS[@]}" OTHERPAKS <<< "${curpak%% *}"
	fi
	done <<< "$(printf "%s\n" "${CURWTPAKS[@]}")"

	fixShowGnAid
	export CURWIKI="$PPW/Winetricks"
	TITLE="${PROGNAME}-WinetricksPackageSelection-$WTPREF"
	pollWinRes "$TITLE"

	setShowPic
	# TODO? some yad/gtk warnings in WTPREF=apps DESCR:
	WTPICKS="$(
	while read -r packline; do
		PACKNAME="${packline%% *}"

		if [[ "${CURWTPAKS[*]}" =~ $PACKNAME ]]; then
			echo TRUE
		else
			echo FALSE
		fi

		echo "$PACKNAME"

		DESCRRAW="${packline#* }"
		DESCR1="${DESCRRAW//$(grep -oP '\(\K[^\)]+' <<< "$DESCRRAW")}";
		DESCR2="${DESCR1//\!}"
		DESCR="${DESCR2//&/&amp}"
		echo "${DESCR#"${DESCR%%[![:space:]]*}"}"
	done <<< "$("$WINETRICKS" "$WTPREF" list)"	 | \
	"$YAD" --f1-action="$F1ACTION" --image "$SHOWPIC" --image-on-top --window-icon="$STLICON" --center "$WINDECO" --list --checklist --column="$GUI_ADD" --column="$GUI_WTPACK" --column="$GUI_WTDESC" --separator="" --print-column="2" \
	--text="$(spanFont "$(strFix "$GUI_WTPACKDIALOG" "$SGNAID")" "H")" --title="$TITLE" --button="$BUT_CAN:0" --button="$BUT_SELECT:2" "$GEOM")"
	case $? in
		0)	{
				writelog "INFO" "${FUNCNAME[0]} - Selected '$BUT_CAN' - Cancelling selection"
			}
		;;
		2)	{
				writelog "INFO" "${FUNCNAME[0]} - Selected '$BUT_SELECT' - Saving Selection"

				if [ -z "$WTPICKS" ]; then
					writelog "INFO" "${FUNCNAME[0]} - Nothing selected"
					WTPICKS=""
				fi
				
				unset WINETRICKSPAKS
				while read -r line; do
					WINETRICKSPAKS="$WINETRICKSPAKS $line"
				done <<< "$WTPICKS"

				while read -r line; do
					WINETRICKSPAKS="$WINETRICKSPAKS $line"
				done <<< "${OTHERPAKS[*]}"

				if [ -z "$WINETRICKSPAKS" ] || [ "$WINETRICKSPAKS" == "  " ]; then
					WINETRICKSPAKS="$NON"
				fi

				WINETRICKSPAKS1="${WINETRICKSPAKS#*[[:blank:]]}"
				WINETRICKSPAKS="${WINETRICKSPAKS1%*[[:blank:]]}"
				touch "$FUPDATE"
				updateConfigEntry "WINETRICKSPAKS" "$WINETRICKSPAKS" "$STLGAMECFG"
			}
		;;
	esac					
	if [ -n "$2" ]; then
		"$2" "$AID" "${FUNCNAME[0]}"
	fi
}

function cleanDropDown {
	CURSEL="$1"
	OPTIONS="$2"
	
	FILTOPTS="${OPTIONS//\!$CURSEL\!/\!}"
	FILTOPTS="!${FILTOPTS//$CURSEL\!/\!}"
	FILTOPTS="${FILTOPTS//\!\!/\!}"
	echo "$CURSEL$FILTOPTS"
}

function chooseWinetricksPrefix {
	if [ -n "$1" ]; then
		AID="$1"
		setAIDCfgs
	fi

	if [ ! -f "$STLGAMECFG" ]; then
		writelog "ERROR" "${FUNCNAME[0]} - Game config '$STLGAMECFG' not found - exiting"
	else
		chooseWinetricks
		loadCfg "$STLGAMECFG"
		ORGWINETRICKSPAKS="$WINETRICKSPAKS"
		
		writelog "INFO" "${FUNCNAME[0]} - Opening dialog to choose a winetricks prefix"
		export CURWIKI="$PPW/Winetricks"
		TITLE="${PROGNAME}-${FUNCNAME[0]}"
		pollWinRes "$TITLE"
		setShowPic

		WTLOG="$GPFX/winetricks.log"

		function WTPAKINSTLIST {
			while read -r line; do
				if [ -f "$WTLOG" ] && grep -q "^$line$" "$WTLOG"; then
					echo "$line $GUI_WTAI"
				else
					echo "$line"
				fi
			done <<< "$(tr ' ' '\n' <<< "$WINETRICKSPAKS")"
		}

		createProtonList X
		if [ -z "$WTPROTON" ]; then
			WTPROTON="$USEPROTON"
		fi

		WTCATPFX="$("$YAD" --f1-action="$F1ACTION" --image "$SHOWPIC" --image-on-top --window-icon="$STLICON" --form --center --on-top $WINDECO \
		--title="$TITLE" --separator=";" \
		--text="$(spanFont "$GUI_CHOOSEWTCATPFX" "H")" \
		--field=" ":LBL " " \
		--field="$GUI_WTCATPFX!$GUI_CHOOSEWTCATPFX":CB "dlls!apps!dlls!fonts" \
		--field="$GUI_WTPROTON!$(strFix "$DESC_WTPROTON" "$BUT_INSTALL")":CB "$(cleanDropDown "${WTPROTON//\"}" "$PROTYADLIST")" \
		--field="$GUI_WTPROTONSAVE!$(strFix "$DESC_WTPROTONSAVE" "$BUT_INSTALL")":CHK "FALSE" \
		--field=" ":LBL " " \
		--field="$(spanFont "$GUI_CURSELWTPACKS" "H")":LBL " " \
		--field="$(WTPAKINSTLIST)":LBL " " \
		--button="$BUT_SELECT:2" --button="$BUT_DONE:4" --button="$BUT_INSTALL:6" "$GEOM"
		)"
		case $? in
			2)	{
					WTPREF="$(cut -d ';' -f2 <<< "$WTCATPFX")" # WEAK - will be broken when adding fields
					writelog "INFO" "${FUNCNAME[0]} - Selected '$BUT_SELECT' - Opening '$WTPREF' list"
					WinetricksPick "$WTPREF" "${FUNCNAME[0]}"
				}
			;;
			4)	{
					writelog "INFO" "${FUNCNAME[0]} - Selected '$BUT_DONE'"
					if [ "$ORGWINETRICKSPAKS" != "$WINETRICKSPAKS" ]; then
						rm "${WTLOG//.log/.checked}" 2>/dev/null
						writelog "INFO" "${FUNCNAME[0]} - Changed will be installed before next game start"
					else
						writelog "INFO" "${FUNCNAME[0]} - Package list hasn't changed"
					fi
				}
			;;
			6)	{
					WTPROTON="$(cut -d ';' -f3 <<< "$WTCATPFX")"
					writelog "INFO" "${FUNCNAME[0]} - Selected '$BUT_INSTALL' - Installing '$WINETRICKSPAKS' using '$WTPROTON'"
					RUNWTPROTON="$(getProtPathFromCSV "$WTPROTON")"

					if [ ! -f "$RUNWTPROTON" ]; then
						RUNWTPROTON="$(fixProtonVersionMismatch "WTPROTON" "$STLGAMECFG" X)"
					fi

					if [ -f "$(dirname "$RUNWTPROTON")/$DBW" ]; then
						RUNWTWINE="$(dirname "$RUNWTPROTON")/$DBW"
					elif [ -f "$(dirname "$RUNWTPROTON")/$FBW" ]; then
						RUNWTWINE="$(dirname "$RUNWTPROTON")/$FBW"
					fi

					WTPROTONSAVE="$(cut -d ';' -f4 <<< "$WTCATPFX")"
					if [ "$WTPROTONSAVE" == "TRUE" ];then
						writelog "INFO" "${FUNCNAME[0]} - Saving Winetricks Proton WTPROTON '$WTPROTON' into '$STLGAMECFG'"
						touch "$FUPDATE"
						updateConfigEntry "WTPROTON" "$WTPROTON" "$STLGAMECFG"
					fi

					if [ -f "$RUNWTWINE" ]; then
						rm "${WTLOG//.log/.checked}" 2>/dev/null
						installWinetricksPaks "$WINETRICKSPAKS" "$RUNWTWINE" "extWine64Run"
					else
						writelog "ERROR" "${FUNCNAME[0]} - Could not find wine binary for current proton '$WTPROTON'"
					fi
				}
			;;
		esac
	fi
}

# start $WINECFG before game launch:
function checkWineCfgLaunch {
	if [ -n "$RUN_WINECFG" ]; then
		if [ "$RUN_WINECFG" -eq 1 ]; then
			writelog "INFO" "${FUNCNAME[0]} - Starting '$WINECFG' before game start:"
			if [ "$USEWINE" -eq 0 ]; then
				extWine64Run "$WINECFG"
			else
				extWine64Run "$RUNWINECFG"
			fi
		fi
	fi
}

function regEdit {
	REGEDIT="regedit"
	if [ -z "$1" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Starting $REGEDIT without arguments"
		extWine64Run "$RUNWINE" "$REGEDIT"
	else
		writelog "INFO" "${FUNCNAME[0]} - Starting $REGEDIT with argument $1"
		if [ "$USEWINE" -eq 0 ]; then
			extWine64Run "$RUNWINE" "$REGEDIT" "$1"
		else
			extWine64Run "$RUNWINE" "$RUNREGEDIT" "$1"
		fi
		writelog "INFO" "${FUNCNAME[0]} - Applied '$1' using '$REGEDIT' - Setting REGEDIT to 0 now in '$STLGAMECFG'"
		updateConfigEntry "REGEDIT" "0" "$STLGAMECFG"
	fi
}

function customRegs {
	TEMPREG="$GPFX/VirtualDesktop.reg"

	if [ "$VIRTUALDESKTOP" -eq 1 ]; then
		SETVD=1
		if [ -z "$VDRES" ] || [ "$VDRES" == "$NON" ]; then
			VDRES="$(getScreenRes r)"
		fi
				
		if [ -f "$TEMPREG" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Looks like virtual desktop was already applied before"
			if grep -q "$VDRES" "$TEMPREG"; then
				writelog "SKIP" "${FUNCNAME[0]} - The configured resolution in '$TEMPREG' did not change - nothing to do"
				SETVD=0
			else
				writelog "INFO" "${FUNCNAME[0]} - The configured resolution in '$TEMPREG' changed - updating to '$VDRES'"
			fi
		fi

		if [ "$SETVD" -eq 1 ]; then
			if touch "$TEMPREG"; then
				writelog "INFO" "${FUNCNAME[0]} - VIRTUALDESKTOP is set to 1 - enabling virtual desktop"
				{
				echo "Windows Registry Editor Version 5.00"
				echo "[HKEY_CURRENT_USER\Software\Wine\Explorer]"
				echo "\"Desktop\"=\"Default\""
				echo "[HKEY_CURRENT_USER\Software\Wine\Explorer\Desktops]"
				echo "\"Default\"=\"$VDRES\""
				} >> "$TEMPREG"
				if [ -f "$TEMPREG" ]; then
					regEdit "$TEMPREG"
				else
					writelog "SKIP" "${FUNCNAME[0]} - '$TEMPREG' should be here, but it isn't!"
				fi
			else
				writelog "SKIP" "${FUNCNAME[0]} - Could not create '$TEMPREG' - skipping!"
			fi
		fi
	elif [ "$VIRTUALDESKTOP" -eq 0 ]; then
		if [ -f "$TEMPREG" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Virtual desktop is disabled, but was enabled before - removing the registry value"
			sed "s:\[:\[-:g" -i "$TEMPREG"
			regEdit "$TEMPREG"
			rm "$TEMPREG"
		fi		
	fi

	if [ "$REGEDIT" -eq 1 ]; then
		mkProjDir "$STLREGDIR"
		if [ -f "$STLREGDIR/$AID.reg" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Applying registry file '$STLREGDIR/$AID.reg'"
			regEdit "$STLREGDIR/$AID.reg"
		else
			writelog "INFO" "${FUNCNAME[0]} - No game specific regfile found. Opening the regedit editor"
			regEdit
		fi
	fi
}

function useNyrna {
	if [ -n "$RUN_NYRNA" ]; then
		if [ "$RUN_NYRNA" -eq 1 ]; then
			if "$PGREP" -f "$NYRNA" >/dev/null; then
				writelog "SKIP" "${FUNCNAME[0]} - '$NYRNA' already running - skipping"
				RUN_NYRNA=0
			else
			writelog "INFO" "${FUNCNAME[0]} - Starting '$NYRNA'"
			"$NYRNA" &
			fi
		fi
	fi
}

function useReplay {
	if [ -n "$RUN_REPLAY" ]; then
		if [ "$RUN_REPLAY" -eq 1 ]; then
			if "$PGREP" -f "$REPLAY" >/dev/null; then
				writelog "SKIP" "${FUNCNAME[0]} - '$REPLAY' already running - skipping"
				RUN_REPLAY=0
			else
			writelog "INFO" "${FUNCNAME[0]} - Starting '$REPLAY'"
			"$REPLAY" &
			fi
		fi
	fi
}

# gameconqueror
function runGamCon {
	writelog "INFO" "${FUNCNAME[0]} - Starting '$GAMCON' process"

	if [ -n "$GAMCONWAITEXE" ] && [[ ! "$GAMCONWAITEXE" =~ ${DUMMYBIN}$ ]]; then
		if [ -f "$GAMCONWAITEXE" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Waiting for alternative '$GAMCONWAITEXE' process"
			while [ -z "$("$PIDOF" "$GAMCONWAITEXE" | cut -d ' ' -f1)" ]; do 
				writelog "WAIT" "${FUNCNAME[0]} - Waiting for '$GAMCONWAITEXE' PID"
				sleep 1
			done
			GCGPID="$("$PIDOF" "$GAMCONWAITEXE" | cut -d ' ' -f1)"
		else
			writelog "SKIP" "${FUNCNAME[0]} - Alternative '$GAMCONWAITEXE' defined but file doesn't exist - continuing with regular game exe"
			waitForGamePid
			GCGPID="$(GAMEPID)"
		fi
	else
		waitForGamePid
		GCGPID="$(GAMEPID)"
	fi
	
	writelog "INFO" "${FUNCNAME[0]} - Game process found at '$GCGPID'"
	writelog "INFO" "${FUNCNAME[0]} - Starting '$GAMCON $GCGPID'"
	"$GAMCON" "$GCGPID"
}

# start gameconqueror
function checkGamConLaunch {
	if [ "$RUN_GAMCON" -eq 1 ]; then
		# start the whole GamCon start/wait/stop/process
		writelog "INFO" "${FUNCNAME[0]} - Starting '$GAMCON' process for '$AID'"
		if [ "$RUN_GAMCON" -eq 1 ]; then
			runGamCon &
		else
			writelog "SKIP" "${FUNCNAME[0]} - ERROR - RUN_GAMCON is '$RUN_GAMCON' which is invalid - setting to 0"
			RUN_GAMCON=0
		fi
	fi
}

# CheatEngine

function downloadCheatEngine {
	# yes I know 7.3 is released - proper PR accepted, I won't spend more time on CE generally
	CHEATENGINEURLEVAL="$CHEATENGINEURL/download/$CHEATENGINEVERSION/$CESET"
	if [ "$CHEATENGINEVERSION" == "7.2" ]; then
		writelog "WARN" "${FUNCNAME[0]} - Cheat Engine upstream removed version 7.2 - defaulting to wayback machine archive"
		CHEATENGINEURLEVAL="$CEWAYBACKURL/$CHEATENGINEURLEVAL"
	fi
	CESET="$1"
	writelog "INFO" "${FUNCNAME[0]} - Downloading '$CESET' into '$CEDLDIR'"
	notiShow "$(strFix "$NOTY_DLCE" "$CESET")" "S"
	dlCheck "$CHEATENGINEURLEVAL" "$CEDLDIR/$CESET" "X" "Downloading '$CESET'"
	notiShow "$GUI_DONE" "S"
}

function installCheatEngine {
	CESET="${CE// /}${CHEATENGINEVERSION//./}.exe"
	STARTCE=1

	if [ ! -f "$CEDLDIR/$CESET" ]; then
		writelog "INFO" "${FUNCNAME[0]} - '$CE' Installer '$CEDLDIR/$CESET' does not exist - trying to download"
		downloadCheatEngine "$CESET"
	fi

	if [ -f "$CEDLDIR/$CESET" ]; then
		CURMD5="$(md5sum "$CEDLDIR/$CESET")"
		if [ "${CURMD5%% *}" == "$CHEATENGINEMD5SUM" ]; then
			writelog "INFO" "${FUNCNAME[0]} - md5sum of installed '$CEDLDIR/$CESET' is correct: '${CURMD5%% *}'"
		else
			writelog "WARN" "${FUNCNAME[0]} - md5sum of installed '$CEDLDIR/$CESET' is wrong: '${CURMD5%% *}' - trying download again!"
			rm "$CEDLDIR/$CESET"
			downloadCheatEngine "$CESET"
			CURMD5="$(md5sum "$CEDLDIR/$CESET")"
			if [ "${CURMD5%% *}" == "$CHEATENGINEMD5SUM" ]; then
				writelog "INFO" "${FUNCNAME[0]} - New Download was successful - continuing"
			else
				writelog "SKIP" "${FUNCNAME[0]} - New Download failed - skipping CheatEngine"
				notiShow "$(strFix "$NOTY_CHEATENGINEMD5SUM" "${CURMD5%% *}" "$CHEATENGINEMD5SUM")"
				STARTCE=0
			fi
		fi
	fi

	if [ -f "$CEDLDIR/$CESET" ] && [ "$STARTCE" -eq 1 ]; then
			CEDIR="$STLCEDIR/${CE} $CHEATENGINEVERSION"
			CEEXE="$CEDIR/${CE}.exe"
		if [ "$HAVEINNO" -eq 1 ]; then
			"$INNOEXTRACT" -m -s -d "$STLCEDIR" "$CEDLDIR/$CESET"
			if [ -d "$STLCEDIR/app" ]; then
				mv "$STLCEDIR/app" "$CEDIR"
				writelog "INFO" "${FUNCNAME[0]} - Installed '$CE' into '$CEDIR' using '$INNOEXTRACT'"
			else
				writelog "WARN" "${FUNCNAME[0]} - Extraction of '$CEDLDIR/$CESET' into '$CEDIR' using $INNOEXTRACT failed or the output directory is called differently"
			fi
		elif [ -f "$RUNWINE" ]; then
			CEPFX="$STLCEDIR/wineprefix"
			mkProjDir "$CEPFX"
			CEINSTDIR="$CEPFX/$DRC/Program Files/${CE} $CHEATENGINEVERSION"
			writelog "INFO" "${FUNCNAME[0]} - Installing '$CEDLDIR/$CESET' into '$CEPFX' using '$RUNWINE'"
			notiShow "$(strFix "$NOTY_INSTCE" "$CESET")" "S"
			WINE="$RUNWINE" WINEARCH=win64 WINEDEBUG="$STLWINEDEBUG" WINEPREFIX="$CEPFX" "$RUNWINE" "$CEDLDIR/$CESET" "/VERYSILENT"
			notiShow "$GUI_DONE" "S"
			if [ -d "$CEINSTDIR" ]; then
				mv "$CEINSTDIR" "$CEDIR"
				rm -rf "$CEPFX"
				writelog "INFO" "${FUNCNAME[0]} - Installed '$CE' into '$CEDIR'"
			else
				writelog "WARN" "${FUNCNAME[0]} - Extraction of '$CEDLDIR/$CESET' into '$CEDIR' using '$RUNWINE' failed"
			fi
		else
			writelog "SKIP" "${FUNCNAME[0]} - Neither '$INNOEXTRACT' nor '$RUNWINE' could be found - can't install '$CESET' - skipping"
		fi
	else
		writelog "SKIP" "${FUNCNAME[0]} - Downloading '$CEDLDIR/$CESET' failed - can't install - skipping"	
	fi
}

function killPrefixOnGameExit {
	waitForGamePid
	GPID="$(GAMEPID)"
	if [ -n "$GPID" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Game pid '$GPID' found"
	fi
	writelog "INFO" "${FUNCNAME[0]} - Waiting for '$GPID' closing to kill Proton"
		
	tail --pid="$GPID" -f /dev/null
	writelog "INFO" "${FUNCNAME[0]} - Game process '$GPID' finished - Force closing Proton"
	if [ "$USEWINE" -eq 0 ]; then
		WINEPREFIX="$GPFX" "$RUNWINESERVER" -k
	else
		WINEPREFIX="$GWFX" "$RUNWINESERVER" -k
	fi

	touch "$CLOSETMP"
}

function StateSteamWebHelper {
	if [ "$TOGSTEAMWEBHELPER" -eq 1 ]; then
		SWH="steamwebhelper"

		if [ "$1" == "pause" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Stopping all '$SWH' processes"
			SIGVAL="-SIGSTOP"
		elif [ "$1" == "cont" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Continuing all '$SWH' processes"
			SIGVAL="-SIGCONT"
		else
			writelog "INFO" "${FUNCNAME[0]} - No argument - Toggling '$SWH' processes"
			TESTPID="$("$PGREP" "$SWH" | grep -v "$("$PGREP" "${SWH}\.")" | head -n1)"
			SWHSTATE="$(ps -q "$TESTPID" -o state --no-headers)"
			SIGVAL="-SIGSTOP"
			if [ "$SWHSTATE" = "T" ] ; then
				SIGVAL="-SIGCONT"
			fi
		fi

		while read -r swhpid; do
			if [ -n "$swhpid" ] && [ "$swhpid" -eq "$swhpid" ]; then
				kill "$SIGVAL" "$swhpid"
			fi
		done <<< "$("$PGREP" "$SWH" | grep -v "$("$PGREP" "${SWH}\.")")"
	fi
}

# start CheatEngine
function checkCheatEngineLaunch {
	if [ "$RUN_CHEATENGINE" -eq 1 ] && [ "$ISGAME" -eq 2 ] && [ "$USEWINE" -eq 0 ]; then
		# start the whole GamCon start/wait/stop/process
		writelog "INFO" "${FUNCNAME[0]} - Starting '$CE' process for '$AID'"
		if [ "$RUN_CHEATENGINE" -eq 1 ]; then
			CEDIR="$STLCEDIR/${CE} $CHEATENGINEVERSION"
			CEEXE="$CEDIR/${CE}.exe"
			
			if [ ! -f "$CEEXE" ]; then
				writelog "INFO" "${FUNCNAME[0]} - File '$CEEXE' does not exit - starting installer"
				StatusWindow "$GUI_RUN_CHEATENGINE" "installCheatEngine" "InstallCheatEngineStatus"
			fi

			if [ ! -f "$CEEXE" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Installing failed - can't start '$CE' - skipping"
			else
				if [ "$USEGAMEMODERUN" -eq 1 ]; then
					writelog "WARN" "${FUNCNAME[0]} - Disabling '$GMR' for '$CE', because function 'GAMEPID' doesn't find the game pid with it in the current state"
					USEGAMEMODERUN=0
				fi
			
				writelog "INFO" "${FUNCNAME[0]} - Starting '$CEEXE' in the backgound"
				extProtonRun "F" "$CEEXE" "$CUSTOMCMD_ARGS"
				killPrefixOnGameExit &
			fi
		else
			writelog "SKIP" "${FUNCNAME[0]} - ERROR - RUN_CHEATENGINE is '$RUN_CHEATENGINE' which is invalid - setting to 0"
			RUN_CHEATENGINE=0
		fi
	fi
}

function checkSteamAppIDFile {
	if [ -d "$EFD" ] && [ "$STLPLAY" -eq 0 ]; then
		GSAIT="$EFD/$SAIT"
		CSAIT="$EFD/check-$SAIT"

		if [ ! -f "$CSAIT" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Creating new control file '$CSAIT'"
			if [ ! -f "$GSAIT" ]; then
				echo "OWNSAIT=\"0\"" > "$CSAIT"
			else
				echo "OWNSAIT=\"1\"" > "$CSAIT"
			fi
		fi

		if [ "$STEAMAPPIDFILE" -eq 1 ]; then	
			if [ ! -f "$GSAIT" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Creating '$GSAIT' because STEAMAPPIDFILE is enabled"
				echo "$AID" > "$GSAIT"
			else
				writelog "INFO" "${FUNCNAME[0]} - STEAMAPPIDFILE is enabled and '$GSAIT' already exists - nothing to do"
			fi
		else
			if [ ! -f "$GSAIT" ]; then
				writelog "INFO" "${FUNCNAME[0]} - STEAMAPPIDFILE is disabled and there's no '$GSAIT' - nothing to do"
			else
				if [ ! -f "$CSAIT" ]; then
					writelog "INFO" "${FUNCNAME[0]} - Removing '$GSAIT' because STEAMAPPIDFILE is disabled"
					rm "$GSAIT" 2>/dev/null	
				else
					loadCfg "$CSAIT" X
					if [ "$OWNSAIT" -eq 1 ]; then
						writelog "INFO" "${FUNCNAME[0]} - OWNSAIT is '$OWNSAIT', means the game ships an own '$SAIT'. Leaving untouched and enabling STEAMAPPIDFILE"
						updateConfigEntry "STEAMAPPIDFILE" "1" "$STLGAMECFG"
						STEAMAPPIDFILE=1				
					else
						writelog "INFO" "${FUNCNAME[0]} - Removing '$GSAIT' because the game doesn't own it and STEAMAPPIDFILE is disabled"
						rm "$GSAIT" 2>/dev/null	
					fi
				fi
			fi
		fi
	fi
}

function checkPulse {
	if [ "$CHANGE_PULSE_LATENCY" -eq 1 ]; then
		writelog "INFO" "${FUNCNAME[0]} - Setting PULSE_LATENCY_MSEC to '$STL_PULSE_LATENCY_MSEC'"
		export PULSE_LATENCY_MSEC="$STL_PULSE_LATENCY_MSEC"
	fi
}

function getProtWinePath {
	CHECKWINED="${1%/*}/$DBW"
	CHECKWINEF="${1%/*}/$FBW"
	if [ -f "$CHECKWINED" ]; then
		echo "$CHECKWINED"
	elif [ -f "$CHECKWINEF" ]; then
		echo "$CHECKWINEF"
	fi
}

function listSteWoShPaks {
	STSHT1="${STEWOS,,}"
	STSHTXT="${STSHT1//\ /-}.txt"
	STESHALIST="$GLOBALMISCDIR/$STSHTXT"
	cut -d ';' -f1 "$STESHALIST"
}

function getGameDirFromAM {
	APPMAFE="$1"
	GIRAW="$(grep "\"installdir\"" "$APPMAFE" | awk -F '"installdir"' '{print $NF}')"
	GINS="$(awk '{$1=$1};1' <<< "${GIRAW//\"/}")"
	OUTGD="${APPMAFE%/*}/common/$GINS"
	if [ -d "$OUTGD" ]; then
		echo "$OUTGD"
	fi
}

function getGameDirFromAID {
	APPMAFE="$(listAppManifests | grep -m1 "appmanifest_${1}.acf")"
	getGameDirFromAM "$APPMAFE"
}

function runExe {
	IFILE="$1"
	AIDORPFX="$2"
	INSTWINE="$3"
	INSTARGS="$4"
	
	mapfile -d " " -t -O "${#INSTARGSARR[@]}" INSTARGSARR < <(printf '%s' "${INSTARGS//\"}")

	if [ "$AIDORPFX" -eq "$AIDORPFX" ] 2>/dev/null; then
		writelog "INFO" "${FUNCNAME[0]} - '$AIDORPFX' seems to be a SteamAppId - determining its pfx" E
		setGPfxFromAppMa "$AIDORPFX"
		if [ -n "$GPFX" ]; then
			IPFX="$GPFX"
			IAID="$AIDORPFX"
		fi
	else
		IPFX="$AIDORPFX"
		IAID="$(grep -oP "$CODA/\K[^/pfx]+" <<< "$IPFX")"
	fi
	
	if [ "$INSTWINE" != "$NON" ]; then
		IWINE="$INSTWINE"
	else
		if [ "$IAID" -eq "$IAID" ] 2>/dev/null; then
			IAIDCFG="$STLGAMEDIRID/$IAID.conf"
			if [ -f "$IAIDCFG" ]; then
				IUSEPROT="$(grep "^USEPROTON=" "$IAIDCFG" | cut -d '=' -f2)"
				writelog "INFO" "${FUNCNAME[0]} - Searching for wine for '$IUSEPROT' defined in $IAIDCFG"
				IRUNPROT="$(getProtPathFromCSV "${IUSEPROT//\"}")"
				if [ -f "$IRUNPROT" ]; then
					IWINE="$(getProtWinePath "$IRUNPROT")"
					writelog "INFO" "${FUNCNAME[0]} - Using '$IWINE' for installing '$1'"
				else
					writelog "SKIP" "${FUNCNAME[0]} - Could not find path for proton '${IUSEPROT//\"}' in '$IAIDCFG'"
				fi
			fi
		fi
		
		if [ ! -f "$IAIDCFG" ] || [ ! -f "$IWINE" ]; then
			writelog "INFO" "${FUNCNAME[0]} - No wine binary found - falling back to wine from FIRSTUSEPROTON '$FIRSTUSEPROTON'"
			IRUNPROT="$(getProtPathFromCSV "$FIRSTUSEPROTON")"
			if [ -f "$IRUNPROT" ]; then
				IWINE="$(getProtWinePath "$IRUNPROT")"
				writelog "INFO" "${FUNCNAME[0]} - Using '$IWINE' for installing '$IFILE'"
			else
				writelog "SKIP" "${FUNCNAME[0]} - Could not find path for proton '$FIRSTUSEPROTON' in '$IAIDCFG'"
			fi
		fi
	fi
	
	if [ -n "$IPFX" ] && [ -f "$IWINE" ] && [ -f "$IFILE" ]; then
		cd "${IFILE%/*}" >/dev/null || return
		if [ -n "$USEMSI" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Installing package via command 'WINEPREFIX=$IPFX $IWINE msiexec /i $IFILE ${INSTARGS//\"/}'"
			WINEDEBUG="-all" WINEPREFIX="$IPFX" "$IWINE" msiexec /i "$IFILE" "${INSTARGSARR[@]}" >"$STLSHM/${FUNCNAME[0]}_${IFILE##*/}.log" 2>"$STLSHM/${FUNCNAME[0]}_${IFILE##*/}.log"
		else
			if [[ "$1" =~ "dotnet" ]]; then
				MOGUID="$(WINEPREFIX="$IPFX" "$IWINE" uninstaller --list | grep "Wine Mono Windows Support" | cut -d '|' -f1)"
				if [ -n "$MOGUID" ]; then
					writelog "INFO" "${FUNCNAME[0]} - Uninstalling Mono before installing '${IFILE##*/}'"
					WINEPREFIX="$IPFX" "$IWINE" uninstaller --remove "$MOGUID" >"$STLSHM/${FUNCNAME[0]}_mono-uninst.log" 2>"$STLSHM/${FUNCNAME[0]}_mono-uninst.log"
				fi
			fi
			WINEDEBUG="-all" WINEPREFIX="$IPFX" "$IWINE" "$IFILE" "${INSTARGSARR[@]}" >"$STLSHM/${FUNCNAME[0]}_${IFILE##*/}.log" 2>"$STLSHM/${FUNCNAME[0]}_${IFILE##*/}.log"
		fi
		cd - >/dev/null || return
	else
		writelog "SKIP" "${FUNCNAME[0]} - At least one component of the package installation is missing, check above logs"
	fi
}

function installSteWoShPak {
	AIDORPFX="$2"
	if [ -n "$3" ]; then
		INSTWINE="$3"
	else
		INSTWINE="$NON"
	fi

	STSHT1="${STEWOS,,}"
	STSHTXT="${STSHT1//\ /-}.txt"
	STESHALIST="$GLOBALMISCDIR/$STSHTXT"

	CORED="$STEAM_COMPAT_CLIENT_INSTALL_PATH/$SAC/$STEWOS/_CommonRedist/"

	if grep -q "^\"$1\";" "$STESHALIST"; then
		RELPATH="$(grep "^\"$1\";" "$STESHALIST" | cut -d ';' -f2)"
		INSTARGS="$(grep "^\"$1\";" "$STESHALIST" | cut -d ';' -f3)"
		USEMSI="$(grep "^\"$1\";" "$STESHALIST" | cut -d ';' -f4)"
		IFILE="$CORED/${RELPATH//\"/}"
		notiShow "$(strFix "$NOTY_INSTSTART" "$1")"
		writelog "INFO" "${FUNCNAME[0]} - 'runExe \"$IFILE\" \"$AIDORPFX\" \"$INSTWINE\" \"$INSTARGS\"'"
		runExe "$IFILE" "$AIDORPFX" "$INSTWINE" "$INSTARGS"
		notiShow "$(strFix "$NOTY_INSTSTOP" "$1")"
	else
		writelog "SKIP" "${FUNCNAME[0]} - Could not find '$1' in '$STESHALIST' - doesn't seem to be a valid '$STEWOS' name"
	fi
}

# generic Mod functions (Vortex + MO2):

function prepModGameSym {
	DSTL="$1"
	gdir="$2"
	if [ -n "$2" ]; then
		if [ ! -L "$DSTL" ] || [ "$(readlink "$DSTL")" != "$gdir" ]; then
			if [ -L "$DSTL" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Removing symlink '$DSTL' pointing to '$(readlink "$DSTL")'"
				rm "$DSTL" 2>/dev/null
			fi
			if [ -d "$DSTL" ]; then
				writelog "SKIP" "${FUNCNAME[0]} - Not creating symlink from '$gdir' to '$DSTL', because '$DSTL' is a real directory"
			else
				writelog "INFO" "${FUNCNAME[0]} - Creating symlink from '$gdir' to '$DSTL'"
				ln -s "$gdir" "$DSTL"
			fi
		fi
	fi
}

function setModGameReg {
	DSTPFX="$1" 
	MODWINE="$2"
	if [ -f "$MODGREG" ]; then
		WINEPREFIX="$DSTPFX" "$MODWINE" regedit "$MODGREG" 2>/dev/null
		WINEPREFIX="$DSTPFX" "${MODWINE}64" regedit "$MODGREG" 2>/dev/null
		rm "$MODGREG" 2>/dev/null
	fi	
}

function setModGameSyms {
	SYMODE="$1" # MODE - either 'li' or 'set'
	SRCPFX="$2" # Game prefix
	MODGNA="$3" # Game name
	MODGID="$4" # Game Steam ID
	DSTPFX="$5" # Mod manager prefix
	CHKAPMA="$6" # Game app-manifest (.acf)

	if [ ! -d "$SRCPFX" ]; then
		writelog "SKIP" "${FUNCNAME[0]} - '$SRCPFX' missing - looks like the game was removed or never started yet"
	else
		if [ "$SYMODE" == "li" ]; then
			echo "$MODGID;$MODGNA;$SRCPFX;"
		else
			mkProjDir "$DSTPFX/$DRCU/$STUS/$DOCS/$MYGAMES"
			mkProjDir "$DSTPFX/$DRCU/$STUS/$ADLO/cache"
			
			MODLOOT="$DSTPFX/$DRCU/$STUS/$ADLO/LOOT"
			if [ -L "$MODLOOT" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Removing symlink '$MODLOOT' for creating a real directory instead - is it worth/useful to migrate the content to '$MODLOOT'?"
			fi
			mkProjDir "$MODLOOT"

			writelog "INFO" "${FUNCNAME[0]} - Found game '$MODGNA ($MODGID)' with pfx '$SRCPFX'"
			# maybe merge redundant code later:
			
			if [ -d "$SRCPFX/$DRCU/$STUS/$DOCS/$MYGAMES" ]; then
				while read -r gdir; do
					DSTL="$DSTPFX/$DRCU/$STUS/$DOCS/$MYGAMES/${gdir##*/}"
					prepModGameSym "$DSTL" "$gdir"
				done <<< "$(find -L "$SRCPFX/$DRCU/$STUS/$DOCS/$MYGAMES" -mindepth 1 -maxdepth 1 '(' -type d -o -type l -xtype d ')')"
			fi

			if [ -d "$SRCPFX/$DRCU/$STUS/$DOCS" ]; then
				while read -r gdir; do
					if [ "${gdir##*/}" == "$MYGAMES" ]; then
						while read -r gsdir; do
							DSTL="$DSTPFX/$DRCU/$STUS/$DOCS/$MYGAMES/${gsdir##*/}"
							prepModGameSym "$DSTL" "$gsdir"
						done <<< "$(find -L "$SRCPFX/$DRCU/$STUS/$DOCS/$MYGAMES" -mindepth 1 -maxdepth 1 '(' -type d -o -type l -xtype d ')')"
					elif [ "${gdir##*/}" == "$EAGA" ]; then
						mkProjDir "$DSTPFX/$DRCU/$STUS/$DOCS/$EAGA"
						while read -r geadir; do
							DSTL="$DSTPFX/$DRCU/$STUS/$DOCS/$EAGA/${geadir##*/}"
							prepModGameSym "$DSTL" "$geadir"
						done <<< "$(find -L "$SRCPFX/$DRCU/$STUS/$DOCS/$EAGA" -mindepth 1 -maxdepth 1 '(' -type d -o -type l -xtype d ')')"
					elif [ "${gdir##*/}" == "$LAGA" ]; then
						mkProjDir "$DSTPFX/$DRCU/$STUS/$DOCS/$LAGA"
						while read -r gladir; do
							DSTL="$DSTPFX/$DRCU/$STUS/$DOCS/$LAGA/${gladir##*/}"
							prepModGameSym "$DSTL" "$gladir"
						done <<< "$(find -L "$SRCPFX/$DRCU/$STUS/$DOCS/$LAGA" -mindepth 1 -maxdepth 1 '(' -type d -o -type l -xtype d ')')"
					elif [ "${gdir##*/}" == "$BIOW" ]; then
						mkProjDir "$DSTPFX/$DRCU/$STUS/$DOCS/$BIOW"
						while read -r gbiodir; do
							DSTL="$DSTPFX/$DRCU/$STUS/$DOCS/$BIOW/${gbiodir##*/}"
							prepModGameSym "$DSTL" "$gbiodir"
						done <<< "$(find -L "$SRCPFX/$DRCU/$STUS/$DOCS/$BIOW" -mindepth 1 -maxdepth 1 '(' -type d -o -type l -xtype d ')')"
					else
						DSTL="$DSTPFX/$DRCU/$STUS/$DOCS/${gdir##*/}"
						prepModGameSym "$DSTL" "$gdir"
					fi
				done <<< "$(find -L "$SRCPFX/$DRCU/$STUS/$DOCS" -mindepth 1 -maxdepth 1 -not -empty '(' -type d -o -type l -xtype d ')')"
			fi

			if [ -d "$SRCPFX/$DRCU/$STUS/$MYDOCS" ] && [ ! -L "$SRCPFX/$DRCU/$STUS/$MYDOCS" ]; then
				while read -r gdir; do
					if [ "${gdir##*/}" == "$MYGAMES" ]; then
						while read -r gsdir; do
							DSTL="$DSTPFX/$DRCU/$STUS/$DOCS/$MYGAMES/${gsdir##*/}"
							prepModGameSym "$DSTL" "$gsdir"
						done <<< "$(find -L "$SRCPFX/$DRCU/$STUS/$MYDOCS/$MYGAMES" -mindepth 1 -maxdepth 1 '(' -type d -o -type l -xtype d ')')"
					elif [ "${gdir##*/}" == "$EAGA" ]; then
						mkProjDir "$DSTPFX/$DRCU/$STUS/$DOCS/$EAGA"
						while read -r geadir; do
							DSTL="$DSTPFX/$DRCU/$STUS/$DOCS/$EAGA/${geadir##*/}"
							prepModGameSym "$DSTL" "$geadir"
						done <<< "$(find -L "$SRCPFX/$DRCU/$STUS/$MYDOCS/$EAGA" -mindepth 1 -maxdepth 1 '(' -type d -o -type l -xtype d ')')"
					elif [ "${gdir##*/}" == "$LAGA" ]; then
						mkProjDir "$DSTPFX/$DRCU/$STUS/$DOCS/$LAGA"
						while read -r gladir; do
							DSTL="$DSTPFX/$DRCU/$STUS/$DOCS/$LAGA/${gladir##*/}"
							prepModGameSym "$DSTL" "$gladir"
						done <<< "$(find -L "$SRCPFX/$DRCU/$STUS/$MYDOCS/$LAGA" -mindepth 1 -maxdepth 1 '(' -type d -o -type l -xtype d ')')"
					elif [ "${gdir##*/}" == "$BIOW" ]; then
						mkProjDir "$DSTPFX/$DRCU/$STUS/$DOCS/$BIOW"
						while read -r gbiodir; do
							DSTL="$DSTPFX/$DRCU/$STUS/$DOCS/$BIOW/${gbiodir##*/}"
							prepModGameSym "$DSTL" "$gbiodir"
						done <<< "$(find -L "$SRCPFX/$DRCU/$STUS/$DOCS/$BIOW" -mindepth 1 -maxdepth 1 '(' -type d -o -type l -xtype d ')')"
					else
						DSTL="$DSTPFX/$DRCU/$STUS/$DOCS/${gdir##*/}"
						prepModGameSym "$DSTL" "$gdir"
					fi
				done <<< "$(find -L "$SRCPFX/$DRCU/$STUS/$MYDOCS" -mindepth 1 -maxdepth 1 -not -empty '(' -type d -o -type l -xtype d ')')"
			fi

			if [ -d "$SRCPFX/$DRCU/$STUS/$APDA" ]; then
				while read -r gdir; do
					if [ "${gdir##*/}" != "Microsoft" ] ; then
						DSTL="$DSTPFX/$DRCU/$STUS/$ADRO/${gdir##*/}"
						prepModGameSym "$DSTL" "$gdir"
					fi
				done <<< "$(find -L "$SRCPFX/$DRCU/$STUS/$APDA" -mindepth 1 -maxdepth 1 -not -empty '(' -type d -o -type l -xtype d ')')"
			fi

			if [ -d "$SRCPFX/$DRCU/$STUS/$ADLO" ]; then
				while read -r gdir; do
					if [ "${gdir##*/}" != "openvr" ] && [ "${gdir##*/}" != "Microsoft" ] && [ "${gdir##*/}" != "cache" ] ; then
						if [ "${gdir##*/}" == "$MO" ] && [ ! -L "$gdir" ]; then
							writelog "WARN" "${FUNCNAME[0]} - Renaming old real directory '$gdir' to '${gdir}_OLD', to make place for a symlink into '$DSTPFX'"
							mv "$gdir" "${gdir}_OLD"
						else
							DSTL="$DSTPFX/$DRCU/$STUS/$ADLO/${gdir##*/}"
							prepModGameSym "$DSTL" "$gdir"
						fi
					fi
				done <<< "$(find -L "$SRCPFX/$DRCU/$STUS/$ADLO" -mindepth 1 -maxdepth 1 -not -empty '(' -type d -o -type l -xtype d ')')"
			fi

			if [ -d "$SRCPFX/$DRCU/$STUS/$ADLOLO" ]; then
				while read -r gdir; do
					if [ "${gdir##*/}" != "openvr" ] && [ "${gdir##*/}" != "Microsoft" ] ; then
						if [ "${gdir##*/}" == "$MO" ] && [ ! -L "$gdir" ]; then
							writelog "WARN" "${FUNCNAME[0]} - Renaming old real directory '$gdir' to '${gdir}_OLD', to make place for a symlink into '$DSTPFX'"
							mv "$gdir" "${gdir}_OLD"
						else
							DSTL="$DSTPFX/$DRCU/$STUS/$ADLOLO/${gdir##*/}"
							prepModGameSym "$DSTL" "$gdir"
						fi
					fi
				done <<< "$(find -L "$SRCPFX/$DRCU/$STUS/$ADLOLO" -mindepth 1 -maxdepth 1 -not -empty '(' -type d -o -type l -xtype d ')')"
			fi
						
			if [ -d "$SRCPFX/$DRCU/$STUS/$ADLO/LOOT" ]; then
				while read -r gdir; do
					DSTL="$MODLOOT/${gdir##*/}"
					prepModGameSym "$DSTL" "$gdir"
				done <<< "$(find -L "$SRCPFX/$DRCU/$STUS/$ADLO/LOOT" -mindepth 1 -maxdepth 1 -not -empty '(' -type d -o -type l -xtype d ')')"
			fi
			
			if [ -d "$SRCPFX/$DRCU/$STUS/$LSAD" ]; then
				while read -r gdir; do
					if [ "${gdir##*/}" != "openvr" ] && [ "${gdir##*/}" != "Microsoft" ] ; then
						DSTL="$DSTPFX/$DRCU/$STUS/$ADLO/${gdir##*/}"
						prepModGameSym "$DSTL" "$gdir"
					fi
				done <<< "$(find -L "$SRCPFX/$DRCU/$STUS/$LSAD" -mindepth 1 -maxdepth 1 -not -empty '(' -type d -o -type l -xtype d ')')"
			fi

			if [ -d "$SRCPFX/$DRCU/$STUS/$SAGE/$CDPR" ]; then
				mkProjDir "$DSTPFX/$DRCU/$STUS/$SAGE/$CDPR"
				while read -r gdir; do
						DSTL="$DSTPFX/$DRCU/$STUS/$SAGE/$CDPR/${gdir##*/}"
						prepModGameSym "$DSTL" "$gdir"
				done <<< "$(find -L "$SRCPFX/$DRCU/$STUS/$SAGE/$CDPR" -mindepth 1 -maxdepth 1 -not -empty '(' -type d -o -type l -xtype d ')')"
			fi

			MSREG="$SRCPFX/$SREG"
			if [ -f "$MSREG" ]; then
				if grep -qi "^\"installed path\"=" "$MSREG"; then
					MODGREG="$STLSHM/modgames.reg"
					if [ ! -f "$MODGREG" ]; then
						echo "Windows Registry Editor Version 5.00" > "$MODGREG"
					fi
					MEFD="$(getGameDirFromAM "$CHKAPMA")"
					if [ -d "$MEFD" ]; then
						writelog "INFO" "${FUNCNAME[0]} - Game Dir is '$MEFD' - adding the windows variant into the registry, because it is required for this game"
						grep -i -B2 "^\"installed path\"=" "$MSREG" | grep -v "^#\|LastKey\|CurrentVersion\|^--" | head -n1 | sed "s:^\[Software:\[HKEY_LOCAL_MACHINE\\\Software:" | sed "s:\\\\Wow6432Node::" >> "$MODGREG"
						# the path could be grepped as well, but at least two games had the Steamworks Shared path in the reg value instead here
						echo "\"installed path\"=\"Z:${MEFD//\//\\\\}\\\\\"" >> "$MODGREG"
					else
						writelog "SKIP" "${FUNCNAME[0]} - Game Dir '$MEFD' not found"
					fi
				fi
			else
				writelog "SKIP" "${FUNCNAME[0]} - '$MSREG' not found"
			fi
		fi
	fi
}

function listWinSteamLibraries {
	COUNTER=1
	SL1="${SROOT%*/}"
	echo "\"$COUNTER\" \"Z:${SL1//\//\\\\}\""

	unset SLARR
	mapfile -t -O "${#SLARR[@]}" SLARR <<< "$SL1"

	while read -r line; do
		COUNTER=$((COUNTER+1))
		W1="${line//\"}"
		mapfile -t -O "${#SLARR[@]}" SLARR <<< "$W1"
		W2="${W1//\//\\\\}"
		echo "\"$COUNTER\" \"Z:$W2\""
	done <<< "$(grep "\"path\"" "$LFVDF" | awk '{print $2}')"
}

function installDotNet {
	INSTPFX="$1"
	INSTWINE="$2"
	if [ -n "$3" ]; then
		DNVER="$3"
	else
		DNVER="48"
	fi
	chooseWinetricks
	ILOG="$STLSHM/installDotNet.log"
	rm "$ILOG" 2>/dev/null
	writelog "INFO" "${FUNCNAME[0]} - Starting $DOTN$DNVER install - check $ILOG"
	WINEDEBUG="-all" WINEPREFIX="$INSTPFX" WINE="$INSTWINE" "$WINETRICKS" --unattended "$DOTN$DNVER" >> "$ILOG"
	writelog "INFO" "${FUNCNAME[0]} - Stopped $DOTN$DNVER install - check $ILOG"
}

#### VORTEX START: ####

function addVortexStage {
	if [ ! -f "$VORTEXSTAGELIST" ]; then 
		{
		echo "# List of directories, which ${VTX^} uses as 'Stage directories'"
		echo "# (see Wiki for a comprehensive description)"
		} > "$VORTEXSTAGELIST"
	fi

	if [ -z "$1" ]; then
		export CURWIKI="$PPW/${VTX^}"
		TITLE="${PROGNAME}-AddVortexStage"
		pollWinRes "$TITLE"

		NEWVS="$("$YAD" --f1-action="$F1ACTION" --window-icon="$STLICON" --form --center --on-top "$WINDECO" \
		--file --directory \
		--title="$TITLE" \
		--text="$(spanFont "$GUI_SELECTVORTEXDIR" "H")" "$GEOM")"
	else
		if [ -d "$1" ]; then
			NEWVS="$1"
		elif [ -d "$(dirname "$1")" ]; then
			if mkProjDir "$1"; then
				NEWVS="$1"
			else
				writelog "SKIP" "${FUNCNAME[0]} - Skipping invalid argument '$1'"
			fi
		fi
	fi
	
	if [ -n "$NEWVS" ]; then
		echo "$NEWVS" >> "$VORTEXSTAGELIST"
		rmDupLines "$VORTEXSTAGELIST"
	fi
}

function wineVortexRun {
	sleep 1 # required!
	LC_ALL="C" PATH="$STLPATH" LD_LIBRARY_PATH="" LD_PRELOAD="" WINE="$VORTEXWINE" WINEARCH="win64" WINEDEBUG="-all" WINEPREFIX="$VORTEXPFX" "$@" > "$VWRUN" 2>/dev/null
}

function cleanVortex {
	MSCOR="mscorsvw.exe"
	if "$PGREP" "$MSCOR" >/dev/null; then
		writelog "INFO" "${FUNCNAME[0]} - Killing leftovers of $MSCOR"
		"$PKILL" -9 "$MSCOR"
	fi
}

function setVortexDLMime {
	writelog "INFO" "${FUNCNAME[0]} - INFO: Linking Nexus Mods downloads to ${VTX^}"

	VD="$VTX-${PROGNAME,,}-dl.desktop"
	FVD="$HOME/.local/share/applications/$VD"
	
	if [ ! -f "$FVD" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Creating new desktop file $FVD"
		{
		echo "[Desktop Entry]"
		echo "Type=Application"
		echo "Categories=Game;"
		echo "Name=${VTX^} ($PROGNAME - ${PROGNAME,,})"
		echo "MimeType=x-scheme-handler/nxm;x-scheme-handler/nxm-protocol"
		echo "Terminal=false"
		echo "X-KeepTerminal=false"
		echo "Path=$(dirname "$VORTEXEXE")"
		echo "Exec=$(realpath "$0") $VTX u %u"
		echo "NoDisplay=true"
		} >> "$FVD"
		
		MO2D="$MO-${PROGNAME,,}-dl.desktop"
		FMO2D="$HOME/.local/share/applications/$MO2D"
		if [ -f "$FMO2D" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Renaming desktopfile ${FMO2D} to ${FMO2D}-off, because '$VD' was created"
			mv "$FMO2D" "${FMO2D}-off"
		fi
	else
		if grep -q "$VORTEXPFX" "$FVD"; then
			writelog "INFO" "${FUNCNAME[0]} - Desktopfile $FVD seems to be up2date"
			return
		else
			writelog "INFO" "${FUNCNAME[0]} - Renaming desktopfile $FVD and creating a new one for ${PROGNAME,,}"
			mv "$FVD" "$FVD-old"
			setVortexDLMime
		fi	
	fi

	# setting mime types for nxm
	XDGMIME="xdg-mime"

	if [ -x "$(command -v "$XDGMIME" 2>/dev/null)" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Setting download defaults for nexusmod protocol via $XDGMIME pointing at $VD"
		"$XDGMIME" default "$VD" x-scheme-handler/nxm
		"$XDGMIME" default "$VD" x-scheme-handler/nxm-protocol
	else
		writelog "SKIP" "${FUNCNAME[0]} - $XDGMIME not found - couldn't set download defaults for nexusmod protocol - skipping"
	fi
}

function getLatestVortVer {
	VSET="$VTX-setup"
	writelog "INFO" "${FUNCNAME[0]} - Search for latest ${VTX^} stable Release"
	VORTEXSETUP="$("$WGET" -q "${VORTEXRELURL}/latest" -O - 2> >(grep -v "SSL_INIT") | grep -m1 "$VSET" | grep -oE "${VSET}[^\"]+")"
	writelog "INFO" "${FUNCNAME[0]} - Found '$VORTEXSETUP'"
	echo "VORTEXSETUP=$VORTEXSETUP" > "$VTST"
}

function dlLatestVortex {
	getLatestVortVer

	if [ -n "$VORTEXSETUP" ]; then
		export VSPATH="$VORTEXDLDIR/$VORTEXSETUP"

		# download:
		if [ ! -d "$VORTEXDLDIR" ]; then
			mkProjDir "$VORTEXDLDIR"
		fi

		if [ ! -f "$VSPATH" ]; then
			VVRAW="$(grep -oP "${VSET}-\K[^X]+" <<< "$VORTEXSETUP")"
			VORTEXVERSION="${VVRAW%.exe}"
			
			DLURL="$VORTEXRELURL/download/v$VORTEXVERSION/$VORTEXSETUP"
			# no idea how the sha512 is formatted in the yaml, so simply checking the size
			DLCHK="stat"
			INCHK="$("$WGET" -q "${DLURL//$VORTEXSETUP/latest.yml}" -O - 2> >(grep -v "SSL_INIT") | grep "size:" | gawk -F': ' '{print $2}')"

			writelog "INFO" "${FUNCNAME[0]} - Downloading $VORTEXSETUP to $VORTEXDLDIR from '$DLURL'"
			if [ -n "$1" ]; then
				notiShow "$(strFix "$NOTY_DLCUSTOMPROTON" "$VORTEXSETUP")" "S"
				dlCheck "$DLURL" "$VSPATH" "$DLCHK" "Downloading '$VORTEXSETUP'" "$INCHK"
				notiShow "$(strFix "$NOTY_DLCUSTOMPROTON2" "$VORTEXSETUP")" "S"
			else
				notiShow "$(strFix "$NOTY_DLCUSTOMPROTON" "$VORTEXSETUP")"
				dlCheck "$DLURL" "$VSPATH" "$DLCHK" "Downloading '$VORTEXSETUP'" "$INCHK"
				notiShow "$(strFix "$NOTY_DLCUSTOMPROTON2" "$VORTEXSETUP")"
			fi
		fi	
	else
		writelog "SKIP" "${FUNCNAME[0]} - No VORTEXSETUP defined - nothing to download - skipping"
	fi
}

function getVortexStage {
	if [ -z "$VORTEXSTAGING" ]; then
		WANTSTAGE="$1"
		mkProjDir "$WANTSTAGE"
		if [ -d "$WANTSTAGE" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Created dir '$WANTSTAGE' $PARTLOG"
			VORTEXSTAGING="$WANTSTAGE"
		fi
	fi 	
}

function getInstalledGamesWithVortexSupport {
	getVortexSupported
	if [ "$(listInstalledGameIDs | wc -l)" -eq 0 ]; then
		writelog "SKIP" "${FUNCNAME[0]} - No installed games found!"
	else
		mapfile -t -O "${#INSTGAMES[@]}" INSTGAMES <<< "$(listInstalledGameIDs)"
		mapfile -t -O "${#INSTVGAMES[@]}" INSTVGAMES <<< "$(comm -12 <(printf "%s\n" "${VOSTIDS[@]}" | sort -u) <(printf "%s\n" "${INSTGAMES[@]}" | sort -u))"
		if [ -n "$1" ]; then
			printf "%s\n" "${INSTVGAMES[@]}"
		fi
	fi
}

function dlVortexSupportedList {
	VORTEXGAMES="$GLOBALMISCDIR/$VOGAT"
	VORTSUPURL="https://www.nexusmods.com/about/vortex/"
	VORTHTMLLIST="$STLSHM/${VOGAT//txt/html}"
	VORTTMPLIST="$STLSHM/${VOGAT//.txt/-temp.txt}"

	if [ ! -f "$VORTHTMLLIST" ]; then
		dlCheck "$VORTSUPURL" "$VORTHTMLLIST" "X" "Downloading list of ${VTX^} supported games"
	fi
	
	awk '/supported-games/,/Vortex FAQ/' "$VORTHTMLLIST" | grep -oP "(?<=<li><a href=).*" | grep -v "Nexus Mods" | sed "s:^\"/:\":; s:\">:\";\":; s:</a></li>:\":" | sort -o "$VORTTMPLIST"
	grep -wF -f "$VORTTMPLIST" "$VORTEXGAMES" > "${VORTTMPLIST//-temp/-temp2}"
	{
		cat "${VORTTMPLIST//-temp/-temp2}"
		comm -23 "$VORTEXGAMES" "${VORTTMPLIST//-temp/-temp2}"
	} | sort
	rm "${VORTTMPLIST//-temp/-temp2}" "$VORTTMPLIST" 2>/dev/null
}

function getGameSteamCategories {
	SCGAME="$1"

	if [ -z "$SUSDA" ] || [ -z "$STUIDPATH" ]; then
		setSteamPaths
	fi
	if [ -d "$SUSDA" ]; then
		SC="$STUIDPATH/$SRSCV"

		if [ ! -f "$SC" ]; then
			writelog "SKIP" "${FUNCNAME[0]} - File '${SC##*/}' not found in steam userid dir - skipping"
		else
			writelog "INFO" "${FUNCNAME[0]} - File '${SC##*/}' found in steam userid dir - searching categories for game '$SCGAME'"

			while read -r SCAT; do
				mapfile -t -O "${#GSCATS[@]}" GSCATS <<< "$SCAT"
			done <<< "$(sed -n "/\"$SCGAME\"/,/}/p;" "$SC" | sed -n "/\"tags\"/,/}/p" | sed -n "/{/,/}/p" | grep -v '{\|}' | awk '{print $2}' | sed "s:\"::g")"
			if [ -n "$2" ]; then
				OUT1="$(printf "%s," "${GSCATS[@]}")"
				printf "%s\n" "${OUT1%*,}"
			fi
		fi
	else
		writelog "SKIP" "${FUNCNAME[0]} - '$SUSDA' not found - this should not happen! - skipping"
	fi
}

function VortexGamesDialog {
	writelog "INFO" "${FUNCNAME[0]} - Opening ${VTX^} Dialog for en/disabling ${VTX^} for installed games"
	setVortexVars
	getInstalledGamesWithVortexSupport
	export CURWIKI="$PPW/${VTX^}"
	TITLE="${PROGNAME}-${VTX^} Toggle"
	pollWinRes "$TITLE"

	setShowPic
	VGNLIST="$STLSHM/VGNLIST.txt"
	VGNSCLIST="$STLSHM/VGNSCLIST.txt"

	VINGAMES="$(while read -r f; do
		loadCfg "$GEMETA/$f.conf" X
		if [ "$GAMENAME" != "$NON" ]; then
			GNAM="$GAMENAME"
			echo "$f;$GAMENAME" >> "$VGNLIST"
		else
			GNAM="$NON"
		fi

		if [ ! -f "$STLGAMEDIRID/${f}.conf" ]; then
			writelog "SKIP" "${FUNCNAME[0]} - Game config '$STLGAMEDIRID/${f}.conf' not found, so creating a minimal one from '$STLDEFGAMECFG'"
			grep -v "config Version" "$STLDEFGAMECFG" >> "$STLGAMEDIRID/${f}.conf"
		fi

		if grep -q "Vortex" <<< "$(getGameSteamCategories "$f" "X")"; then
			echo TRUE
			echo "$f"
			echo "$GNAM"
			echo "$GUI_Y"
			echo "$f" >> "$VGNSCLIST"
		else
			if grep -q "^USEVORTEX=\"0\"" "$STLGAMEDIRID/${f}.conf" || ! grep -q "^USEVORTEX=" "$STLGAMEDIRID/${f}.conf"; then
				echo FALSE
				echo "$f"
				echo "$GNAM"
				echo "$GUI_N"
			else
				echo TRUE
				echo "$f"
				echo "$GNAM"
				echo "$GUI_N"
			fi
		fi
	done <<< "$(printf "%s\n" "${INSTVGAMES[@]}")" | \
	"$YAD" --f1-action="$F1ACTION" --image "$SHOWPIC" --image-on-top --window-icon="$STLICON" --center "$WINDECO" --list --checklist --column="Use Vortex" --column="Game ID" --column="Game Title" --column "Vortex Steam Category" --separator=";" --print-column="2" \
	--text="$(spanFont "$GUI_VINFO" "H")\n<span font=\"italic\">($GUI_VINFO1)</span>" --title="$TITLE" "$GEOM")"
	case $? in
		0)
			while read -r checkvgame; do
				VGNAM="$(grep "^$checkvgame" "$VGNLIST" | awk -F ';' '{print $2}')"
				GVCFG="$STLGAMEDIRID/${checkvgame}.conf"

				if ! grep -q "$checkvgame" <<< "${VINGAMES[@]}"; then
					writelog "INFO" "${FUNCNAME[0]} - Disabling ${VTX^} for '$VGNAM' in '$GVCFG', if not already disabled"
					touch "$FUPDATE"
					updateConfigEntry "USEVORTEX" "0" "$GVCFG"
					if grep -q "$checkvgame" "$VGNSCLIST" 2>/dev/null; then
						writelog "WARN" "${FUNCNAME[0]} - To really disable ${VTX^} for '$VGNAM', the game needs to be removed from the ${VTX^} Steam Category manually"
					fi
				else
					writelog "INFO" "${FUNCNAME[0]} - Enabling ${VTX^} for '$VGNAM' if not already enabled"
					touch "$FUPDATE"
					updateConfigEntry "USEVORTEX" "1" "$GVCFG"
				fi
			
			done <<< "$(printf "%s\n" "${INSTVGAMES[@]//\"/}")"			
			
		;;
		1) writelog "INFO" "${FUNCNAME[0]} - Selected CANCEL"
		;;
	esac

	rm "$VGNLIST" "$VGNSCLIST" 2>/dev/null
}

function VortexSymDialog {
	setVortexVars
	VPDRC="$VORTEXPFX/$DRC"
	if [ -d "$VPDRC" ]; then
		export CURWIKI="$PPW/${VTX^}"	
		TITLE="${PROGNAME}-${VTX^} Symlinks"
		pollWinRes "$TITLE"

		setShowPic

		cd "$VPDRC" >/dev/null || return
		find . -type l -printf '%p\n%l\n' | "$YAD" --f1-action="$F1ACTION" --image "$SHOWPIC" --image-on-top --window-icon="$STLICON" --center "$WINDECO" --list --column="Symlink in '${VPDRC}/'" --column="Points to Game WinePrefix" --print-column="3" \
		--text="$(spanFont "$GUI_VOSY" "H")\n" --title="$TITLE" "$GEOM"
		cd - >/dev/null || return
	else
		writelog "SKIP" "${FUNCNAME[0]} - Directory '$VPDRC' not found "
	fi
}

function getVortexSupported {
	function gVSIDs {
		SDIR="$1"
		if [ -d "$SDIR" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Searching for SteamIDs in '$SDIR'"
			mapfile -t -O "${#VOSTIDS[@]}" VOSTIDS <<< "$(grep -iR "STEAM_ID =\|steamAppId:" "$SDIR" | grep -v "module.exports" | grep -oP "'\K[^']+" | grep "[0-9]" | sort -u)"
		fi
	}

	setVortexVars
	VGPDIR="$VORTEXINSTDIR/$RABP"
	VUPDIR="$VORTEXPFX/$DRCU/$STUS/$APDA/Vortex/plugins"

	gVSIDs "$VGPDIR"
	gVSIDs "$VUPDIR"
	
	if [ -n "$1" ]; then
		printf "%s\n" "${VOSTIDS[@]}" | sort -n
	fi
}

function checkVortexRegs {
	function addReg {
		MODGREG="$STLSHM/modgames.reg"
		if [ ! -f "$MODGREG" ]; then
			echo "Windows Registry Editor Version 5.00" > "$MODGREG"
		fi
		{
			echo "[$1]"
			echo "\"$2\"=\"$3\""
		} >> "${MODGREG}"
	}

	if grep -q "Wow6432Node" <<< "$1"; then
		REGKEY="$1"
		REG32KEY="${REGKEY//\\Wow6432Node\\/}"
	elif grep -q "WOW6432Node" <<< "$1"; then
		REGKEY="${1//WOW6432Node/Wow6432Node}"
		REG32KEY="${REGKEY//\\Wow6432Node\\/}"
	else
		REG32KEY="$1"
		REGKEY="${REG32KEY//Software\\\\/Software\\\\Wow6432Node\\\\}"
	fi
	PATHKEY="$2"
	INSTP="$3"

	writelog "INFO" "${FUNCNAME[0]} - Checking RegKey '$REGKEY' and updating RegKey '$REG32KEY' in registry for game '$NEXUSGAMEID' now"

	# check if registry path exists:
	if wineVortexRun "$VORTEXWINE" reg QUERY "$REGKEY" >/dev/null ; then
		writelog "INFO" "${FUNCNAME[0]} - Registry path $REGKEY already set"
		# value of the currently set registry path:
		REGPATH="$(wineVortexRun "$VORTEXWINE" reg QUERY "$REGKEY" | grep -i "$PATHKEY" | awk -F 'REG_SZ' '{print $NF}' | awk '{$1=$1};1' | tr -d "\n\r")"

		if [ "$REGPATH" == "${INSTP//\\\\/\\}" ]; then
			writelog "INFO" "${FUNCNAME[0]} - The registry entry '$REGPATH' for '$PATHKEY' is identical to the gamepath '${INSTP//\\\\/\\}'"
		else
			if [ -n "$REGPATH" ]; then
				writelog "WARN" "${FUNCNAME[0]} - The registry entry '$REGPATH' for '$PATHKEY' is not equal to gamepath '${INSTP//\\\\/\\}' - resetting registry to '${INSTP//\\\\/\\}'"
			else
				writelog "WARN" "${FUNCNAME[0]} - The registry entry for '$PATHKEY' is empty - resetting registry to '${INSTP//\\\\/\\}'"
			fi
			wineVortexRun "$VORTEXWINE" reg DELETE "$REGKEY" /f >/dev/null
		fi						
	else
		writelog "NEW" "${FUNCNAME[0]} - Registry path '$REGKEY' does not exist - creating '$PATHKEY' entry for '$INSTP'"
	fi
	if [ -n "$INSTP" ]; then
		addReg "$REG32KEY" "$PATHKEY" "$INSTP"
	else
		writelog "SKIP" "${FUNCNAME[0]} - INSTP is empty - REG32KEY is '$REG32KEY' and PATHKEY is '$PATHKEY'"
	fi
}

function setVortSet {
	echo "${VTX^}.exe --set $1" >> "$VORTSETCMD"
}

function runVortex {
	cd "$VORTEXINSTDIR" >/dev/null || return
	wineVortexRun "$VORTEXWINE" "${VTX^}.exe" "$@"
	cd - >/dev/null || return
}

function runVortSetCmd {
	if [ -f "$VORTSETCMD" ]; then
		rmDupLines "$VORTSETCMD"
		cd "$VORTEXINSTDIR" >/dev/null || return
		wineVortexRun "$VORTEXWINE" "$VORTSETCMD"
		cd - >/dev/null || return
	fi
}

function setVortexDLPath {
	# configure Vortex Download Dir:
	if [ ! -d "$VORTEXDOWNLOADPATH" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Creating ${VTX^} Download Dir '$VORTEXDOWNLOADPATH'"
		mkProjDir "$VORTEXDOWNLOADPATH"
	fi

	VDPF="$VORTEXDOWNLOADPATH/__vortex_downloads_folder"
	if [ ! -f "$VDPF" ]; then
		echo "{\"instance\":\"empty\"}" > "$VDPF"
	fi

	VORTEXDOWNLOADWINPATH="Z:${VORTEXDOWNLOADPATH//\//\\\\}"
	writelog "INFO" "${FUNCNAME[0]} - Setting ${VTX^} Download WinDir '$VORTEXDOWNLOADWINPATH' in ${VTX^}"
	echo "@echo off" > "$VORTSETCMD"
	setVortSet "settings.downloads.path=true"
	setVortSet "settings.downloads.path=\\\"$VORTEXDOWNLOADWINPATH\\\""
}

function setGameVortexStaging {
	VGAMEDIR="$1"

	if [ ! -d  "$VGAMEDIR" ]; then
		writelog "ERROR" "${FUNCNAME[0]} - argument 1 '$1' is no valid directory - can't continue"
	else
		writelog "INFO" "${FUNCNAME[0]} - Looking for the mount point of the partition where the game dir '$VGAMEDIR' is"
		# find matching Staging Directory:
		GAMEMP="$(df -P "$VGAMEDIR" | awk 'END{print $NF}')"
		writelog "INFO" "${FUNCNAME[0]} - Mount point of partition where the game is installed: '$GAMEMP'"
		unset CONFSTAGE VORTEXSTAGING

		if [ -f "$VORTEXSTAGELIST" ]; then
			CONFSTAGE="$(grep "${GAMEMP}/" "$VORTEXSTAGELIST")"
		fi

		if [ -n "$CONFSTAGE" ]; then
			if [ -d "$CONFSTAGE" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Configured VORTEXSTAGING dir found: '$CONFSTAGE'"
				VORTEXSTAGING="$CONFSTAGE"
			else
				writelog "ERROR" "${FUNCNAME[0]} - Configured entry '$CONFSTAGE' found in '$VORTEXSTAGELIST', but this isn't a useable directory"
			fi
		fi

		if [ -z "$VORTEXSTAGING" ]; then
			if [ "$DISABLE_AUTOSTAGES" -eq 1 ]; then
				writelog "SKIP" "${FUNCNAME[0]} - VORTEXSTAGING is empty and autostages was disabled by the user - skipping vortex"
				USEVORTEX="0"
			else
				PARTLOG=" - using that as VORTEXSTAGING dir for all games on partition' $GAMEMP'"
				HOMEMP="$(df -P "${STLVORTEXDIR%/*}" | awk 'END{print $NF}')"
				writelog "INFO" "${FUNCNAME[0]} - HOMEMP is $HOMEMP and GAMEMP is $GAMEMP"

				# don't pollute base steam installation with a ~/.steam/steam/Vortex dir, so default to $STLVORTEXDIR/stageing
				if [ "$GAMEMP" == "$HOMEMP" ]; then	
					getVortexStage "$STLVORTEXDIR/staging"
				fi

				# try in base directory of the partition:
				getVortexStage "$GAMEMP/${VTX^}"

				# then try in the current SteamLibrary dir besides steamapps, as it should be writeable by the user and is unused from steam(?):
				getVortexStage "$(awk -F 'steamapps' '{print $1}' <<< "$VGAMEDIR")${VTX^}"

				# updating Vortex config with the new found VORTEXSTAGING dir:
				touch "$VORTEXSTAGELIST"
				if [ -n "$VORTEXSTAGING" ]; then
					if ! grep -q "$VORTEXSTAGING" < "$VORTEXSTAGELIST"; then
						writelog "INFO" "${FUNCNAME[0]} - Adding '$VORTEXSTAGING' to the ${VTX^} Stage List '$VORTEXSTAGELIST'"
						addVortexStage "$VORTEXSTAGING"
					fi
				fi
			fi
		fi

		if [ -z "$VORTEXSTAGING" ]; then
			writelog "SKIP" "${FUNCNAME[0]} - No useable staging directory autodetected - giving up"
			USEVORTEX="0"
		fi

		if [ -n "$VORTEXSTAGING" ]; then
			writelog "INFO" "${FUNCNAME[0]} - VORTEXSTAGING set to '$VORTEXSTAGING' - configuring '$NEXUSGAMEID' Staging folder installPath"
			VGSGM="$VORTEXSTAGING/$NEXUSGAMEID/mods"

			writelog "INFO" "${FUNCNAME[0]} - Creating ${VTX^} Staging folder '$VGSGM'"
			mkProjDir "$VGSGM"

			VGSGMSF="$VGSGM/__vortex_staging_folder"
			if [ ! -f "$VGSGMSF" ]; then
				echo "{\"instance\":\"empty\",\"game\":\"NEXUSGAMEID\"}" > "$VGSGMSF"
			fi

			GAMESTAGINGWINFOLDER="Z:${VGSGM//\//\\\\}"
			GAMESTAGINGWINFOLDER="${GAMESTAGINGWINFOLDER//$NEXUSGAMEID/\{GAME\}}"
			writelog "INFO" "${FUNCNAME[0]} - Setting Staging folder '$GAMESTAGINGWINFOLDER' in Vortex"

			setVortSet "settings.mods.installPath.$NEXUSGAMEID=true"
			setVortSet "settings.mods.installPath.$NEXUSGAMEID=\\\"$GAMESTAGINGWINFOLDER\\\""
			setVortSet "settings.mods.activator.$NEXUSGAMEID=\\\"hardlink_activator\\\""
		fi
	fi
}

function setupGameVortex {
	VZGAMEDIR="$1"
	VORTGETSET="$STLSHM/vortgetset.txt"

	if [ ! -f "$VORTGETSET" ]; then 
		WINEDEBUG="-all" WINEPREFIX="$VORTEXPFX" "$VORTEXWINE" "$VORTEXEXE" "--get" "settings" > "$VORTGETSET" 2>/dev/null
	fi

	if [ -f "$VORTGETSET" ] && grep -q "$NEXUSGAMEID=\"hardlink_activator\"" "$VORTGETSET"; then
		writelog "SKIP" "${FUNCNAME[0]} - '$NEXUSGAMEID' is already added to Vortex"
	else
		if [ -n "$VZGAMEDIR" ]; then
#		setVortSet "settings.gameMode.discovered.$NEXUSGAMEID.hidden=false"
#		setVortSet "settings.gameMode.discovered.$NEXUSGAMEID.path=true"
#		setVortSet "settings.gameMode.discovered.$NEXUSGAMEID.path=\\\"$VZGAMEDIR\\\""
#		setVortSet "settings.gameMode.discovered.$NEXUSGAMEID.pathSetManually=true"
		setVortSet "settings.mods.activator.$NEXUSGAMEID=true"
		setVortSet "settings.mods.activator.$NEXUSGAMEID=\\\"hardlink_activator\\\""
		fi
	fi
}

function setInstPathReg {
	NEXUSGAMEFILE="$VORTEXINSTDIR/$RABP/game-$NEXUSGAMEID/index.js"

	if [ ! -f "$NEXUSGAMEFILE" ]; then
		writelog "WARN" "${FUNCNAME[0]} - Could not find '$NEXUSGAMEFILE' - maybe ${VTX} uses a different name for the game than '$NEXUSGAMEID'?"
	else
		writelog "INFO" "${FUNCNAME[0]} - Found '$NEXUSGAMEFILE' - looking for usable data"

		# search registry install path in NEXUSGAMEFILE
		if grep -E 'instPath.*winapi.RegGetValue' "$NEXUSGAMEFILE" -A1 | grep "HKEY_LOCAL_MACHINE" -q ; then
			writelog "INFO" "${FUNCNAME[0]} - Found some instPath registry value in '$NEXUSGAMEFILE' - trying to extract it"
			REGKEY=""
			PATHKEY=""
			RAWREG="$(grep -E 'instPath.*winapi.RegGetValue' "$NEXUSGAMEFILE" -A3 | tr -d "\n\r" | awk -F 'RegGetValue' '{print $2}' | cut -d';' -f1 | tr -s " " | sed "s:^(::g" | sed "s:)$::g" | sed 's/, /,/g' | awk '{$1=$1;print}')"

			if [ -n "$RAWREG" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Analyzing found registry snippet $RAWREG"

				if grep -q "HKEY" <<< "$RAWREG"; then
					writelog "INFO" "${FUNCNAME[0]} - Found a HKEY entry: $RAWREG - working on it"
					SNIP="','S" # :)
					REGWIP1="${RAWREG//HINE$SNIP/HINE\\S}"
					REGWIP="${REGWIP1//T_USER','S/T_USER\\\\S}"
					
					writelog "INFO" "${FUNCNAME[0]} - REGWIP is $REGWIP"

					REGWIPKEY="$(awk -F ',' '{print $1}' <<< "$REGWIP" | sed "s:'::g")"
					PATHKEY="$(awk -F ',' '{print $2}' <<< "$REGWIP" | sed "s:'::g")"

					if grep -q -i "WOW6432Node" <<< "$REGWIPKEY"; then
						writelog "INFO" "${FUNCNAME[0]} - Squeezing in a 'WOW6432Node' into the '$REGWIPKEY' string"
						REGKEY="${REGWIPKEY/[Ss][Oo][Ff][Tt][Ww][Aa][Rr][Ee]/Software\\\\\\WOW6432Node}"
					else
						REGKEY="$REGWIPKEY"
					fi

					writelog "INFO" "${FUNCNAME[0]} - Final REGKEY is '$REGKEY'"
				else
					if grep -q "hive" <<< "$RAWREG"; then
						writelog "INFO" "${FUNCNAME[0]} - Found a hive, key, name placeholder - required?"
					else
						writelog "SKIP" "${FUNCNAME[0]} - No valid registry found in cut entry '$RAWREG' - skipping"
					fi
				fi
			else
				writelog "SKIP" "${FUNCNAME[0]} - Haven't found any useable registry entries in '$NEXUSGAMEFILE' - skipping registry insert"
			fi

			# insert registry key when found:
			if [ -n "$REGKEY" ] && [ -n "$PATHKEY" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Inserting registry key '$REGKEY' '$PATHKEY' 'Z:${VGAMEDIR//\//\\\\}'"
				checkVortexRegs "$REGKEY" "$PATHKEY" "Z:${VGAMEDIR//\//\\\\}"
			else
				writelog "SKIP" "${FUNCNAME[0]} - REGKEY '$REGKEY' or PATHKEY '$PATHKEY' is empty - skipping registry insert"
			fi
		fi
	fi
}

function prepareVortexGame {
	VAID="$1"
	if grep -q "\"$VAID\"" "$SEENVORTEXGAMES" 2>/dev/null; then
		NEXUSGAMEID="$(grep "\"$VAID\"" "$VORTEXGAMES" | cut -d ';' -f1)"
		writelog "INFO" "${FUNCNAME[0]} - '$NEXUSGAMEID ($VAID)' is already setup for '${VTX^}' - remove from '$SEENVORTEXGAMES' for retry"
	else
		if grep -q "\"$VAID\"" "$VORTEXGAMES"; then
			if [ -z "$NEXUSGAMEID" ]; then
				NEXUSGAMEID="$(grep "\"$VAID\"" "$VORTEXGAMES" | cut -d ';' -f1)"
				NEXUSGAMEID="${NEXUSGAMEID//\"}"
				updateConfigEntry "NEXUSGAMEID" "$NEXUSGAMEID" "$STLGAMECFG"
				updateConfigEntry "NEXUSGAMEID" "$NEXUSGAMEID" "$GEMETA/$AID.conf"
			fi

			VGNAME="$(grep "\"$VAID\"" "$VORTEXGAMES" | cut -d ';' -f2)"
			VGNAME="${VGNAME//\"}"
			writelog "INFO" "${FUNCNAME[0]} - $(strFix "$NOTY_PREPVTX" "$VGNAME" "$VAID" "$NEXUSGAMEID")"
			notiShow "$(strFix "$NOTY_PREPVTX" "$VGNAME" "$VAID" "$NEXUSGAMEID")" "S" 
			# prepare symlinks in VORTEXPFX
			VAPPMAFE="$(listAppManifests | grep -m1 "${VAID}.acf")"
			VGPFX="$(setGPfxFromAppMa "$VAID" "$VAPPMAFE")"

			GPFXSTUS="$VGPFX/$DRCU/$STUS"
			if [ -d "$GPFXSTUS" ]; then
				setModGameSyms "set" "$VGPFX" "$VGNAME" "$VAID" "$VORTEXPFX" "$VAPPMAFE"
				VGAMEDIR="$(getGameDirFromAID "$VAID")"
				writelog "INFO" "${FUNCNAME[0]} - Game dir for '$VAID' found is: '$VGAMEDIR')"
				setInstPathReg
				checkVortexRegs "HKEY_LOCAL_MACHINE\\Software\\\Wow6432Node\\\Valve\\\Steam\\\Apps\\$VAID" "Installed Path" "Z:${VGAMEDIR//\//\\\\}"
				setModGameReg "$VORTEXPFX" "$VORTEXWINE"
			fi

			grep "\"$VAID\"" "$VORTEXGAMES" >> "$SEENVORTEXGAMES"
			rmDupLines "$SEENVORTEXGAMES"
			if [ ! -d  "$VGAMEDIR" ]; then
				writelog "ERROR" "${FUNCNAME[0]} - variable VGAMEDIR '$VGAMEDIR' is no valid directory - can't continue"
			elif [ -z  "$VGAMEDIR" ]; then
				writelog "ERROR" "${FUNCNAME[0]} - variable VGAMEDIR does not exist - can't continue"
			else
				setGameVortexStaging "$VGAMEDIR"
			fi

			if [ -z "$2" ]; then
				writelog "INFO" "${FUNCNAME[0]} - $(strFix "$NOTY_APPLVTX" "$NEXUSGAMEID" "$VORTSETCMD")"
				notiShow "$(strFix "$NOTY_APPLVTX" "$NEXUSGAMEID" "$VORTSETCMD")" "S" 
				runVortSetCmd
				writelog "INFO" "${FUNCNAME[0]} - Symlinks, registry entries and $VTX settings for '$NEXUSGAMEID' should be ready at this point for ${VTX^}"
			fi
		else
			writelog "SKIP" "${FUNCNAME[0]} - Skip game '$VAID' is not supported by ${VTX^} or the ID is not listed in '$VORTEXGAMES'" "E"
		fi
	fi
}

function prepareAllInstalledVortexGames {
	writelog "INFO" "${FUNCNAME[0]} - Preparing all installed games supported by ${VTX^}" "E"
	setVortexVars
	while read -r line ;do
		unset NEXUSGAMEID
		prepareVortexGame "$line" "X"
	done <<< "$(getInstalledGamesWithVortexSupport X)"
	writelog "INFO" "${FUNCNAME[0]} - Applying ${VTX^} settings for all games via autogenerated cmd '$VORTSETCMD'" "E"
	runVortSetCmd
	writelog "INFO" "${FUNCNAME[0]} - Symlinks, registry entries and $VTX settings for all found supported games should be ready at this point for ${VTX^}" "E"
}

function setVortexConfigVdf {
	mkdir -p "$VORTEXPFX/$DRC/$PFX86S/config"
	mkdir -p "$VORTEXPFX/$DRC/$PFX86S/$SAC"
	VTXSTCFG="$VORTEXPFX/$DRC/$PFX86S/$COCOV"
	writelog "INFO" "${FUNCNAME[0]} - Updating '$COCOV' in the ${VTX^} pfx, to make newly games available when auto-detectable"
	cp "$CFGVDF" "$VTXSTCFG"
	while read -r line; do
		BIF="$(awk '{print $2}' <<< "$line")"
		BIF="${BIF//\"}"
		sed "s:$BIF:Z\:$BIF:" -i "$VTXSTCFG"
	done <<< "$(grep "BaseInstallFolder" "$VTXSTCFG")"
}

function resetVortexSettings {
	setVortexVars
	runVortex "--get" "settings"
	grep -v "^info\: Epic" "$VWRUN" > "$STLSHM/vortsetbefore.txt"
	rm "$VWRUN" 2>/dev/null
	setVortexDLPath
	setVortexConfigVdf
	rm "$SEENVORTEXGAMES" 2>/dev/null
	prepareAllInstalledVortexGames
	runVortex "--get" "settings"
	grep -v "^info\: Epic" "$VWRUN" > "$STLSHM/vortsetafter.txt"
	
	writelog "INFO" "${FUNCNAME[0]} - Diff between ${VTX^} settings before and after reset:" "E"
	diff -u "$STLSHM/vortsetbefore.txt" "$STLSHM/vortsetafter.txt"
}

function startVortex {
	setVortexVars
	askVortex "$1"
	if [ "$USEVORTEX" -eq 1 ]; then
		if [ ! -f "$VORTEXEXE" ]; then
			writelog "WARN" "${FUNCNAME[0]} - VORTEXEXE '$VORTEXEXE' does not exist - installing now"
			StatusWindow "$(strFix "$NOTY_DLCUSTOMPROTON" "${VTX^}")" "dlLatestVortex S" "DownloadVortexStatus"
			StatusWindow "$(strFix "$NOTY_INSTSTART" "${VTX^}")" "installVortex" "InstallVortexStatus"
		fi

		if [ "$RUN_VORTEX_WINETRICKS" -eq 1 ]; then
			writelog "INFO" "${FUNCNAME[0]} - Starting $WINETRICKS before Vortex"
			chooseWinetricks
			WINE="$VORTEXWINE" WINEDEBUG="-all" WINEPREFIX="$VORTEXPFX" "$WINETRICKS"
		fi

		if [ "$RUN_VORTEX_WINECFG" -eq 1 ]; then
			writelog "INFO" "${FUNCNAME[0]} - Starting $WINECFG before Vortex"
			WINE="$VORTEXWINE" WINEDEBUG="-all" WINEPREFIX="$VORTEXPFX" "$WINECFG"
		fi

		if [ -f "$VORTEXEXE" ]; then
			setVortexDLMime
			setVortexDLPath
			setVortexConfigVdf

			if [ -n "$2" ] && [ "$2" -eq "$2" ] 2>/dev/null; then
				StatusWindow "${VTX^}" "prepareVortexGame $2" "PrepareVortexGameStatus"
			elif [ -n "$AID" ] && [ "$AID" != "$PLACEHOLDERAID" ]; then
				StatusWindow "${VTX^}" "prepareVortexGame $AID" "PrepareVortexGameStatus"
			fi

			if [ -n "$NEXUSGAMEID" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Starting ${VTX^} now with command 'runVortex \"--game\" \"$NEXUSGAMEID\"' in WINEPREFIX '$VORTEXPFX'"
				runVortex "--game" "$NEXUSGAMEID"
			else
				if [ "$2" == "url" ]; then
					if [ -z "$3" ]; then
						writelog "INFO" "${FUNCNAME[0]} - need arg3"
						howto
					else
						writelog "INFO" "${FUNCNAME[0]} - Starting ${VTX^} now with command 'runVortex \"-d\" \"$3\""
						runVortex "-d" "$3"
					fi
				elif [ "$2" == "getset" ]; then
					writelog "INFO" "${FUNCNAME[0]} - Showing ${VTX^} settings as requested"
					runVortex "--get" "settings"
					grep -v "^info\: Epic" "$VWRUN"
					rm "$VWRUN" 2>/dev/null
				else
					StatusWindow "${VTX^}" "prepareAllInstalledVortexGames" "PrepareVortexGameStatus"
					writelog "INFO" "${FUNCNAME[0]} - Starting ${VTX^} without options" "E"
					runVortex
				fi
			fi

			cleanVortex
			writelog "INFO" "${FUNCNAME[0]} - ${VTX^} exited - starting game now"
		else
			writelog "ERROR" "${FUNCNAME[0]} - VORTEXEXE '$VORTEXEXE' not found! - exit"
			exit
		fi
	fi
}

function setVortexSELaunch {
	if [ "$1" == "$AID" ] && [ -d "$EFD" ]; then
		SEEXE="$EFD/$2"
		if [ ! -f "$SEEXE" ]; then
			writelog "SKIP" "${FUNCNAME[0]} - Special exe '$2' for '$SGNAID' not found in gamedir '$EFD' - starting normal exe"
		else
			writelog "INFO" "${FUNCNAME[0]} - Found special exe '$2' for '$SGNAID' in gamedir '$EFD'"
			export CURWIKI="$PPW/Vortex"
			TITLE="ScriptExtenderRequester"
			pollWinRes "$TITLE"

			"$YAD" --f1-action="$F1ACTION" --window-icon="$STLICON" --center "$WINDECO" \
			--title="$TITLE" \
			--text="$GUI_SEBINFOUND '$EFD/$2'" \
			--button="${GE^^}":0 \
			--button="$BUT_SAVERUN ${GE^^}":1 \
			--button="$BUT_SAVERUN ${2^^}":2 \
			"$GEOM"
			
			case $? in
				0)  {
					writelog "INFO" "${FUNCNAME[0]} - Starting with the regular Game Exe '$GE'"
					USECUSTOMCMD="0"
					}
				;;
				1) 	{
					writelog "INFO" "${FUNCNAME[0]} - Starting with the regular Game Exe '$GE' and don't ask again"
					USECUSTOMCMD="0"
					updateConfigEntry "SELAUNCH" "0" "$STLGAMECFG"
					}
				;;
				2)  {
					writelog "INFO" "${FUNCNAME[0]} - Starting with the Script Extender Exe '$2' and saving as default"
					writelog "INFO" "${FUNCNAME[0]} - Configuring default start of special exe '$2' by enabling SELAUNCH in '$STLGAMECFG'"
					updateConfigEntry "CUSTOMCMD" "$SEEXE" "$STLGAMECFG"
					updateConfigEntry "USECUSTOMCMD" "1" "$STLGAMECFG"
					updateConfigEntry "ONLY_CUSTOMCMD" "1" "$STLGAMECFG"
					updateConfigEntry "SELAUNCH" "0" "$STLGAMECFG"
					CUSTOMCMD="$SEEXE"
					USECUSTOMCMD="1"
					ONLY_CUSTOMCMD=1
					writelog "INFO" "${FUNCNAME[0]} - Starting $SEEXE instead of the game exe directly after this ${VTX^} instance"
					}
				;;
			esac
		fi
	fi
}

function checkVortexSELaunch {
	# (mostly for Vortex)
	# if $1 is 1 check if a preconfigured exe instead of the game is defined/found - f.e. script extender for skyrim, fallout etc
	# if $1 is 2 it is assumed the check already happended before'

	if [ -z "$1" ]; then
		writelog "INFO" "${FUNCNAME[0]} - using fix '2' as SECHECK"
		SECHECK="2"
	else
		writelog "INFO" "${FUNCNAME[0]} - using argument 1 '$1' as SECHECK"
		SECHECK="$1"
	fi

	if [ "$SECHECK" -eq 0 ]; then
		writelog "INFO" "${FUNCNAME[0]} - SELAUNCH set to '$SECHECK' - skipping any SE checks and directly starting what is configured in '$STLGAMECFG'"
	else	
		if [ "$SECHECK" -eq 2 ] && [ -n "$SELAUNCH" ] && [ "$SELAUNCH" -eq 1 ]; then
			writelog "SKIP" "${FUNCNAME[0]} - Skipping option $SECHECK because SELAUNCH is already enabled"
		else
			setVortexSELaunch "377160" "f4se_loader.exe" "$SECHECK" # Fallout4
			setVortexSELaunch "611660" "f4sevr_loader.exe" "$SECHECK"	# Fallout4 VR
			setVortexSELaunch "611670" "sksevr_loader.exe" "$SECHECK" # Skyrim VR
			setVortexSELaunch "489830" "skse64_loader.exe" "$SECHECK" # Skyrim Special Edition
			setVortexSELaunch "72850" "skse_loader.exe" "$SECHECK"	# Skyrim
			setVortexSELaunch "933480" "skse_loader.exe" "$SECHECK"	# Enderal
			setVortexSELaunch "22300" "fose_loader.exe" "$SECHECK"	# Fallout 3
			setVortexSELaunch "22370" "fose_loader.exe" "$SECHECK"	# Fallout 3 GOTY
			setVortexSELaunch "22380" "nvse_loader.exe" "$SECHECK"	# Fallout New Vegas 
			setVortexSELaunch "22330" "obse_loader.exe" "$SECHECK"	# Oblivion
		fi
	fi
}

function getInstVtxVers {
	grep -ahm1 "\"version\": " "${VORTEXINSTDIR}/${VTXRAA}" | cut -d ':' -f2 | cut -d '"' -f2 # fragile
}

function VortexOptions {
	export CURWIKI="$PPW/Vortex"
	TITLE="${PROGNAME}-${FUNCNAME[0]}"
	pollWinRes "$TITLE" 4
	setShowPic

	VTXHEAD="${VTX^} Options"

	if [ -n "${VORTEXCOMPDATA}" ]; then
		TT_CODA="${VTX^} $CODA: $VORTEXCOMPDATA"
	fi

	if [ -f "${VORTEXSTAGELIST}" ]; then
		TT_STAGES="$(cat "${VORTEXSTAGELIST}")"
	fi

	if [ -f "${VORTEXINSTDIR}/${VTXRAA}" ]; then
		TT_CODA="$(printf '%s\n%s\n' "${TT_CODA}" "Version installed: $(getInstVtxVers)")"
	fi
	mkProjDir "$VORTEXDLDIR"
	VTXDLV="$(find "${VORTEXDLDIR}" -name "${VTX}-setup*" | sort -V | tail -n1 | awk -F'${VTX}-setup' '{print $NF}')"
	if [ -n "$VTXDLV" ]; then
		VSD1="${VTXDLV//${VORTEXDLDIR}\/${VTX}-setup-}"
		VSD="${VSD1//.exe}"
		TT_DL="Newest setup downloaded: ${VSD}"
	fi

	getLatestVortVer
	if [ -n "$VORTEXSETUP" ]; then
		VSO1="${VORTEXSETUP//${VTX}-setup-}"
		VSO="${VSO1//.exe}"
		TT_DL="$(printf '%s\n%s\n' "$TT_DL" "Newest setup online: ${VSO}")"
	fi
	
	"$YAD" --f1-action="$F1ACTION" --image "$SHOWPIC" --image-on-top --center --window-icon="$STLICON" --form --center "$WINDECO" --title="$TITLE" \
	--text="$VTXHEAD" --columns="$COLCOUNT" --f1-action="$F1ACTIONCG" --separator="" \
	--field="$FBUT_GUISET_VTXINST!$TT_CODA":FBTN "$PROGCMD $VTX install gui" \
	--field="$FBUT_GUISET_VTXSTART":FBTN "$PROGCMD $VTX start" \
	--field="$FBUT_GUISET_VTXSTAGE!$TT_STAGES":FBTN "$PROGCMD $VTX stage" \
	--field="$FBUT_GUISET_VTXGAMES":FBTN "$PROGCMD $VTX games" \
	--field="$FBUT_GUISET_VTXSYMS":FBTN "$PROGCMD $VTX symlinks" \
	--field="$FBUT_GUISET_VTXDL!$TT_DL":FBTN "$PROGCMD $VTX download" \
	--button="$BUT_DONE:0" "$GEOM"

	writelog "INFO" "${FUNCNAME[0]} - Selected '$BUT_DONE' - Closing Menu"
}

function setDotNetWine {
	USEDNPROTONVAR="$1"
	USEDNPROTON="${!1}"
#	DNPROTONVAR="$2"
	DNPROTON="${!2}"
	DNWINEVAR="$3"
	INUVP="$USEDNPROTON"

	if [ -z "$USEDNPROTON" ] || [ "$USEDNPROTON" == "$NON" ]; then
		writelog "INFO" "${FUNCNAME[0]} - '$USEDNPROTONVAR' not configured - using default '$DEFDOTNETPROTON'" "E"
		USEDNPROTON="$DEFDOTNETPROTON"
	fi
	
	if [ -z "$DNPROTON" ] || [ ! -f "$DNPROTON" ]; then
		if [ -z "${ProtonCSV[0]}" ]; then
			getAvailableProtonVersions "up" X
		fi
		DNPROTON="$(getProtPathFromCSV "$USEDNPROTON")"
		if [ ! -f "$DNPROTON" ]; then
			DNPROTON="$(fixProtonVersionMismatch "$USEDNPROTONVAR" "$STLDEFGLOBALCFG" X)"
		fi

		if [ ! -f "$DNPROTON" ]; then
			createDLProtList
			DLURL="$(printf "%s\n" "${ProtonDLList[@]}" | grep -m1 "$USEDNPROTON")"
			if [ -n "$DLURL" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Downloading: '$DLURL'" "E"
				StatusWindow "$GUI_DLCUSTPROT" "dlCustomProton ${DLURL//|/\"}" "DownloadCustomProtonStatus"
				DNPROTON="$(getProtPathFromCSV "$USEDNPROTON")"
			else
				writelog "SKIP" "${FUNCNAME[0]} - No download URL found for requested '$USEDNPROTON' - skipping" "E"
			fi
		fi
	fi

	if [ -n "$DNPROTON" ] && [ -f "$DNPROTON" ]; then
		export "$2"="$DNPROTON"
		CHECKDNWINED="$(dirname "$DNPROTON")/$DBW"
		CHECKDNWINEF="$(dirname "$DNPROTON")/$FBW"
		if [ -f "$CHECKDNWINED" ]; then
			FWINEVAR="$CHECKDNWINED"
		elif [ -f "$CHECKDNWINEF" ]; then
			FWINEVAR="$CHECKDNWINEF"
		else
			writelog "ERROR" "${FUNCNAME[0]} - $DNWINEVAR was not found - can't continue"
		fi
		
		if [ -f "$FWINEVAR" ]; then
			export "$DNWINEVAR"="$FWINEVAR"
		fi
		
		if [ "$INUVP" != "$USEDNPROTON" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Updating 'USEDNPROTON' in '${STLDEFGLOBALCFG##*/}' to '$USEDNPROTON'" "E"
			touch "$FUPDATE"
			updateConfigEntry "$USEDNPROTONVAR" "$USEDNPROTON" "$STLDEFGLOBALCFG"
		fi
	else
		writelog "ERROR" "${FUNCNAME[0]} - DNPROTON was not found - can't continue" "E"
	fi
}

function setVortexVars {
	VORTEXPFX="${VORTEXCOMPDATA//\"/}/pfx"
	if [ -z "$VORTEXEXE" ]; then
		VORTEXINSTDIR="$VORTEXPFX/$BTVP"
		VORTEXEXE="$VORTEXINSTDIR/${VTX^}.exe"
	fi

	VORTEXGAMES="$GLOBALMISCDIR/$VOGAT"
	if [ -z "$VORTEXWINE" ] || [ ! -f "$VORTEXWINE" ]; then
		setDotNetWine "USEVORTEXPROTON" "VORTEXPROTON" "VORTEXWINE"
	fi
}

function installVortex {
	if [ -z "$VORTEXSETUP" ]; then
		if [ -f "$VTST" ]; then 
			source "$VTST"
		fi
	fi

	if [ -z "$VSPATH" ]; then
		VSPATH="$VORTEXDLDIR/$VORTEXSETUP"
	fi

	if [ -f "$VSPATH" ]; then
		setVortexVars
		if [ -f "$VORTEXEXE" ]; then
			writelog "SKIP" "${FUNCNAME[0]} - '$VORTEXEXE' does already exists - nothing to install - skipping" "E"
		else
			if [ ! -f "$VORTEXPROTON" ]; then
				writelog "SKIP" "${FUNCNAME[0]} - VORTEXPROTON '$VORTEXPROTON' not found - can't continue" "E"
			else
				writelog "INFO" "${FUNCNAME[0]} - Using '$VORTEXPROTON' for installation" "E"
				STEAM_COMPAT_CLIENT_INSTALL_PATH="$SROOT" STEAM_COMPAT_DATA_PATH="$VORTEXCOMPDATA" "$VORTEXPROTON" "run"
				writelog "INFO" "${FUNCNAME[0]} - STEAM_COMPAT_CLIENT_INSTALL_PATH=\"$SROOT\" STEAM_COMPAT_DATA_PATH=\"$VORTEXCOMPDATA\" \"$VORTEXPROTON\" \"run\""
#				WINEDEBUG="-all" WINEPREFIX="$VORTEXPFX" "$VORTEXWINE" wineboot -i 2>/dev/null
				sleep 3
				notiShow "$(strFix "$NOTY_INSTSTART" "${DOTN^}")" "S"
				installDotNet "$VORTEXPFX" "$VORTEXWINE" "48"
				notiShow "$GUI_DONE" "S"
				sleep 3
				writelog "INFO" "${FUNCNAME[0]} - Installing '$VSPATH' into '$VORTEXPFX'" E
				notiShow "$(strFix "$NOTY_INSTSTART" "${VSPATH##*/}")" "S"
				WINEDEBUG="-all" WINEPREFIX="$VORTEXPFX" "$VORTEXWINE" "$VSPATH" "/S"
				notiShow "$(strFix "$NOTY_INSTSTOP" "${VSPATH##*/}")" "S"
				writelog "INFO" "${FUNCNAME[0]} - Base ${VTX^} installation finished" E
				setVortexDLMime
				notiShow "$GUI_DONE" "S"
			fi
		fi
	else
		writelog "SKIP" "${FUNCNAME[0]} - '$VSPATH' not found - nothing to install - skipping"
	fi
}

function installVortexGui {
	export CURWIKI="$PPW/Vortex"
	TITLE="${PROGNAME}-${FUNCNAME[0]}"
	pollWinRes "$TITLE"
	setShowPic

	createProtonList X

	if [ -f "${VORTEXINSTDIR}/${VTXRAA}" ]; then
		GUI_VTXINST="$(printf '%s\n%s\n' "${GUI_VTXINST}" "Version installed: $(getInstVtxVers)")"
	fi
	mkProjDir "$VORTEXDLDIR"
	VTXDLV="$(find "${VORTEXDLDIR}" -name "${VTX}-setup*" | sort -V | tail -n1 | awk -F'${VTX}-setup' '{print $NF}')"
	if [ -n "$VTXDLV" ]; then
		VSD1="${VTXDLV//${VORTEXDLDIR}\/${VTX}-setup-}"
		VSD="${VSD1//.exe}"
		GUI_VTXINST="$(printf '%s\n%s\n' "${GUI_VTXINST}" "Newest setup downloaded: ${VSD}")"
	fi

	getLatestVortVer
	if [ -n "$VORTEXSETUP" ]; then
		VSO1="${VORTEXSETUP//${VTX}-setup-}"
		VSO="${VSO1//.exe}"
		GUI_VTXINST="$(printf '%s\n%s\n' "${GUI_VTXINST}" "Newest setup online: ${VSO}")"
	fi
	
	VTXINSTARGS="$("$YAD" --f1-action="$F1ACTION" --image "$SHOWPIC" --image-on-top --window-icon="$STLICON" --form --center --on-top $WINDECO \
		--title="$TITLE" --separator="|" \
		--text="$(spanFont "$GUI_VTXINST" "H")" \
		--field="$GUI_USEVORTEXPROTON!$DESC_USEVORTEXPROTON ('USEVORTEXPROTON')":CB "$(cleanDropDown "$USEVORTEXPROTON" "$PROTYADLIST")" \
		--button="$BUT_CAN:0" --button="$BUT_INSTALL:2" "$GEOM"
		)"
		case $? in
			0)	{
					writelog "INFO" "${FUNCNAME[0]} - Selected '$BUT_CAN' - Exiting"
				}
			;;
			2)	{
					mapfile -d "|" -t -O "${#VTARR[@]}" VTARR < <(printf '%s' "$VTXINSTARGS")
					USEVORTEXPROTON="${VTARR[0]}"
					StatusWindow "$(strFix "$NOTY_DLCUSTOMPROTON" "${VTX^}")" "dlLatestVortex S" "DownloadVortexStatus"
					StatusWindow "$(strFix "$NOTY_INSTSTART" "${VTX^}")" "installVortex" "InstallVortexStatus"
				}
			;;	
		esac
}

function askVortex {
	if [ "$USEVORTEX" -eq "1" ] && [ "$1" == "ask" ]; then
		if [ "$WAITVORTEX" -gt 0 ]; then
			writelog "INFO" "${FUNCNAME[0]} - Opening ${VTX^} Requester with timeout '$WAITVORTEX'"
			fixShowGnAid
			export CURWIKI="$PPW/Vortex"
			TITLE="${PROGNAME}-OpenVortex"
			pollWinRes "$TITLE"

			setShowPic

			"$YAD" --f1-action="$F1ACTION" --image "$SHOWPIC" --image-on-top --window-icon="$STLICON" --form --center --on-top "$WINDECO" \
			--title="$TITLE" \
			--text="$(spanFont "$SGNAID - $GUI_ASKVORTEX" "H")" \
			--button="$BUT_VORTEX":0 \
			--button="$BUT_CAN":4 \
			--timeout="$WAITVORTEX" \
			--timeout-indicator=top \
			"$GEOM"

			case $? in
				0)  {
						writelog "INFO" "${FUNCNAME[0]} - Selected to Start ${VTX^}, so not disabling it"
					}
				;;
				4)  {
						writelog "INFO" "${FUNCNAME[0]} - Selected CANCEL - Not starting ${VTX^}"
						USEVORTEX="0"
					}
				;;
				70) {
						writelog "INFO" "${FUNCNAME[0]} - TIMEOUT - Not starting ${VTX^}"
						USEVORTEX="0"
					}
				;;
			esac
		else
			writelog "INFO" "${FUNCNAME[0]} - ${VTX^} Requester was skipped because WAITVORTEX is '$WAITVORTEX'"
		fi
	fi
}

#### VORTEX STOP ####

#### MO2 MOD ORGANIZER START: ####

function getLatestMO2Ver {
	MO2SET="Mod.Organizer"

	writelog "INFO" "${FUNCNAME[0]} - Search for latest '$MO2SET' Release"
	MO2SETUP="$("$WGET" -q "${MO2DLURL}" -O - 2> >(grep -v "SSL_INIT") | grep "exe" | grep -m1 "$MO2SET" | grep -oE "${MO2SET}[^\"]+")"
}

function dlLatestMO2 {
	getLatestMO2Ver

	if [ -n "$MO2SETUP" ]; then
		mkProjDir "$MO2DLDIR"
		MO2SPATH="$MO2DLDIR/$MO2SETUP"
		if [ ! -f "$MO2SPATH" ]; then
			MO2VRAW="$(grep -oP "${MO2SET}-\K[^X]+" <<< "$MO2SETUP")"
			MO2VERSION="${MO2VRAW%.exe}"
			DLURL="$MO2DLURL/download/v$MO2VERSION/$MO2SETUP"
			writelog "INFO" "${FUNCNAME[0]} - Downloading $MO2SETUP to $MO2DLDIR from '$DLURL'"
			
			if [ -n "$1" ]; then
				notiShow "$(strFix "$NOTY_DLCUSTOMPROTON" "$MO2SETUP")" "S"
				dlCheck "$DLURL" "$MO2SPATH" "X" "Downloading '$MO2SETUP'"
				notiShow "$(strFix "$NOTY_DLCUSTOMPROTON2" "$MO2SETUP")" "S"
			else
				notiShow "$(strFix "$NOTY_DLCUSTOMPROTON" "$MO2SETUP")"
				dlCheck "$DLURL" "$MO2SPATH" "X" "Downloading '$MO2SETUP'"
				notiShow "$(strFix "$NOTY_DLCUSTOMPROTON2" "$MO2SETUP")"	
			fi
			if [ -f "$MO2SPATH" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Download succeeded - continuing installation"
			else
				writelog "ERROR" "${FUNCNAME[0]} - Download failed!"
			fi
		fi	
	else
		writelog "SKIP" "${FUNCNAME[0]} - No MO2SETUP defined - nothing to download - skipping"
	fi
}

function setMO2Vars {
	MO2PFX="${MO2COMPDATA//\"/}/pfx"
	if [ -z "$MO2EXE" ]; then
		MO2EXE="$MO2PFX/$MOERPATH"
		NXMG="nxmhandler"
		NMXHLOG="$MO2PFX/$DRCU/$STUS/$ADLO/$MO/${NXMG}.log"
	fi
	MO2GAMES="$GLOBALMISCDIR/mo2games.txt"
	if [ -z "$MO2WINE" ] || [ ! -f "$MO2WINE" ]; then
		setDotNetWine "USEMO2PROTON" "MO2RUNPROT" "MO2WINE"
	fi
}

function installMO2 {
	dlLatestMO2 "S"
	if [ -f "$MO2SPATH" ]; then
		setMO2Vars
		if [ -f "$MO2EXE" ]; then
			writelog "SKIP" "${FUNCNAME[0]} - '$MO2EXE' does already exists - nothing to install - skipping"
		else
			if [ -f "$MO2RUNPROT" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Using '$MO2RUNPROT' for installation" "E"
				STEAM_COMPAT_CLIENT_INSTALL_PATH="$SROOT" STEAM_COMPAT_DATA_PATH="$MO2COMPDATA" "$MO2RUNPROT" "run" 2> "$STLSHM/installMO2_protonrun.log"
				writelog "INFO" "${FUNCNAME[0]} - STEAM_COMPAT_CLIENT_INSTALL_PATH=\"$SROOT\" STEAM_COMPAT_DATA_PATH=\"$MO2COMPDATA\" \"$MO2RUNPROT\" \"run\""
#			WINEDEBUG="-all" WINEPREFIX="$MO2PFX" "$MO2WINE" wineboot -i 2>/dev/null
				sleep 3
				notiShow "$(strFix "$NOTY_INSTSTART" "${DOTN^}")" "S"
				installDotNet "$MO2PFX" "$MO2WINE" "48"
				notiShow "$GUI_DONE" "S"
				sleep 3
				writelog "INFO" "${FUNCNAME[0]} - Installing '$MO2SPATH' into '$MO2PFX'"
				notiShow "$(strFix "$NOTY_INSTSTART" "${MO2SPATH##*/}")"
				WINEDEBUG="-all" WINEPREFIX="$MO2PFX" "$MO2WINE" "$MO2SPATH" "/VERYSILENT"
				notiShow "$(strFix "$NOTY_INSTSTOP" "${MO2SPATH##*/}")" "S"
				writelog "INFO" "${FUNCNAME[0]} - Base ${MO} installation finished"
				notiShow "$GUI_DONE" "S"
			else
				writelog "SKIP" "${FUNCNAME[0]} - MO2RUNPROT '$MO2RUNPROT' not found, can't continue with $MO installion"
			fi
		fi
	else
		writelog "SKIP" "${FUNCNAME[0]} - '$MO2SETUP' not found - nothing to install - skipping"
	fi
}

function checkInstalledMO2Games {
	if [ -n "$1" ]; then
		SYMODE="$1"
	else
		SYMODE="set"
	fi

	while read -r line; do
		MGID="$(cut -d ';' -f2 <<< "$line")"
		MGID="${MGID//\"}"

		while read -r sl; do
			CHKAPMA="$sl/$SA/appmanifest_${MGID}.acf"
			if [ -f "$CHKAPMA" ]; then
				MGNA1="$(cut -d ';' -f1 <<< "$line")"
				MGNA="${MGNA1//\"}"
				MGPFX="$(dirname "$CHKAPMA")/$CODA/${MGID}/pfx"
				setModGameSyms "$SYMODE" "$MGPFX" "$MGNA" "$MGID" "$MO2PFX" "$CHKAPMA"
			fi
		done <<< "$(printf "%s\n" "${SLARR[@]}")"
	done < "$MO2GAMES"
	setModGameReg "$MO2PFX" "$MO2WINE"
}

function prepAllMO2Games {
	MO2STDIR="$MO2PFX/$DRC/$PFX86S"
	MO2SADIR="$MO2STDIR/$SA"
	mkProjDir "$MO2SADIR"
	
	rm "$MO2SADIR/$LIFOVDF" 2>/dev/null
	{
		echo "\"LibraryFolders\""
		echo "{"
		listWinSteamLibraries
		echo "}"
	} >> "$MO2SADIR/$LIFOVDF"

	checkInstalledMO2Games "$1"
}

function listMO2Games {
	echo "Games supported by $MO:"
	echo "---------------------------------"
	cat "$GLOBALMISCDIR/mo2games.txt"
}

function manageMO2GInstance {
	setMO2Vars
	if [ ! -f "$MO2EXE" ]; then
		StatusWindow "$(strFix "$NOTY_INSTSTART" "$MO")" "installMO2" "InstallMO2Status"
	fi
	
	if [ -z "$1" ]; then
		writelog "SKIP" "${FUNCNAME[0]} - argument 1 '$1' is invalid"
	else
		if grep -q "$1" "$MO2GAMES"; then
			MO2AID="$1"
			MO2GA1="$(grep -m1 "\"$MO2AID\"" "$MO2GAMES" | cut -d ';' -f1)"
			MO2GAM="${MO2GA1//\"}"

			MO2GAMIN1="$(grep -m1 "\"$MO2AID\"" "$MO2GAMES" | cut -d ';' -f3)"
			MO2GAMINI="${MO2GAMIN1//\"}"
			
			if [ -n "$MO2GAM" ]; then
				MOIN="$MO2PFX/$DRCU/$STUS/$ADLO/$MO/$MO2GAM"
				MODPRDE="$MOIN/profiles/Default"
				MODLIST="$MODPRDE/modlist.txt"
				MOININI="$MOIN/${MO}.ini"
				MOINEW=0
				if [ ! -f "$MOININI" ]; then
					MO2GADI="$(getGameDirFromAID "$MO2AID")"
					
					if [ -d "$MO2GADI" ]; then
						MO2GAZDI="Z:${MO2GADI//\//\\\\}"
						mkProjDir "$MOIN"
						touch "$MOININI"
						{
						echo "[General]"
						echo "gameName=$MO2GAMINI"
						echo "selected_profile=@ByteArray(Default)"
						echo "gamePath=@ByteArray($MO2GAZDI)"
						} >> "$MOININI"
						MOINEW=1
					else
						writelog "SKIP" "${FUNCNAME[0]} - '$MO2AID' is a supported Id, but the game installation could not be found"
					fi
				fi
				if [ -d "$MOIN" ]; then
					if [ -n "$2" ]; then
						writelog "INFO" "${FUNCNAME[0]} - Using $MO instance '$MO2GAM'"
						MO2INST="$MO2GAM"
					else
						if [ "$MOINEW" -eq 1 ]; then
							writelog "INFO" "${FUNCNAME[0]} - Created initial $MO instance '$MO2GAM'"
						else
							writelog "SKIP" "${FUNCNAME[0]} - $MO instance '$MO2GAM' already exists"
						fi
					fi
				fi
			else
				writelog "INFO" "${FUNCNAME[0]} - Could not find game name for '$MO2AID' - starting regularly with default instance"
			fi
		else
			STAMO2=0
			writelog "SKIP" "${FUNCNAME[0]} - '$MO2AID' is no supported $MO game"
			listMO2Games
		fi
	fi	
}

function createAllMO2Instances {
	setMO2Vars
	while read -r line; do
		manageMO2GInstance "$line"
	done <<< "$(prepAllMO2Games "li" | cut -d ';' -f1)"
}

function prepareMO2 {
	setMO2Vars
	STAMO2=1
	if [ -n "$1" ] && [ "$1" != "$NON" ]; then
		if [ "$1" -eq "$1" ] 2>/dev/null; then
			manageMO2GInstance "$1" "X"
			if [ "$2" == "disabled" ]; then
				STAMO2=0
			fi
		else
			if grep -q "^\"$1\"" "$MO2GAMES"; then
				writelog "INFO" "${FUNCNAME[0]} - Using $MO instance '$1'"
				MO2INST="$1"
			fi
		fi
	else
		if [ ! -f "$MO2EXE" ]; then
			StatusWindow "$(strFix "$NOTY_INSTSTART" "$MO")" "installMO2" "InstallMO2Status"
		fi

		writelog "INFO" "${FUNCNAME[0]} - Updating/creating $MO instances"
		createAllMO2Instances
		STAMO2=1
	fi

	if [ "$STAMO2" -eq 1 ] && [ "$2" != "disabled" ]; then
		if [ ! -f "$MO2EXE" ]; then
			StatusWindow "$(strFix "$NOTY_INSTSTART" "$MO")" "installMO2" "InstallMO2Status"
		fi

		prepAllMO2Games "set"

		if [ -f "$MO2EXE" ]; then
			if [ -z "$MO2INST" ]; then
				if [ -f "$NMXHLOG" ]; then
					writelog "INFO" "${FUNCNAME[0]} - No $MO instance provided - searching last one found in '$NMXHLOG'"
					RINST1="$(tac "$NMXHLOG" | grep -m1 \"reg\")"
					RINST2="${RINST1##*\"reg\" }"
					RINST="$(cut -d '"' -f2 <<< "$RINST2")"
					if [ -n "$RINST" ]; then
						MO2INST1="$(grep -m1 "\"$RINST\"" "$MO2GAMES" | cut -d ';' -f1)"
						MO2INST="${MO2INST1//\"}"
						writelog "INFO" "${FUNCNAME[0]} - Found '$RINST' as last used game in '$NMXHLOG', so using instance '$MO2INST'"
						MO2AID="$(grep -m1 "\"$RINST\"" "$MO2GAMES" | cut -d ';' -f2)"
						manageMO2GInstance "${MO2AID//\"}" "X"
						if [ -z "$EFD" ]; then
							if [ -z "$APPMAFE" ]; then
								APPMAFE="$(listAppManifests | grep -m1 "${MO2AID//\"}.acf")"
							fi
							EFD="$(getGameDirFromAM "$APPMAFE")"
						fi
					fi
				else
					writelog "INFO" "${FUNCNAME[0]} - No log '$NMXHLOG' found, so the last used instance can't be determined - using last supported instance installed instead"
					LAINST="$(checkInstalledMO2Games "li" | tail -n1)"
					MO2INST="$(cut -d ';' -f2 <<< "$LAINST")"
					MO2AID="$(cut -d ';' -f1 <<< "$LAINST")"
				fi
			fi

			if [ -n "$MO2INST" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Using $MO instance '$MO2INST'"
			else
				writelog "INFO" "${FUNCNAME[0]} - No $MO instance provided"
			fi

			setMO2DLMime
		fi
	fi
}

function startMO2 {
	prepareMO2 "$NON" "gui"
	if [ -d "${MO2EXE%/*}" ] ; then
		writelog "INFO" "${FUNCNAME[0]} - Starting '$MO2EXE' in standalone mode with command:" E
		cd "${MO2EXE%/*}" >/dev/null || return
			if [ -n "$MO2INST" ]; then
				writelog "INFO" "${FUNCNAME[0]} - WINEDEBUG=\"-all\" WINEPREFIX=\"$MO2PFX\" \"$MO2WINE\" \"$MO2EXE\" -i \"$MO2INST\"" E
				WINEDEBUG="-all" WINEPREFIX="$MO2PFX" "$MO2WINE" "$MO2EXE" -i "$MO2INST" >"$STLSHM/${FUNCNAME[0]}_${IFILE##*/}.log" 2>"$STLSHM/${FUNCNAME[0]}_${IFILE##*/}.log"
			else
				writelog "INFO" "${FUNCNAME[0]} - WINEDEBUG=\"-all\" WINEPREFIX=\"$MO2PFX\" \"$MO2WINE\" \"$MO2EXE\"" E
				WINEDEBUG="-all" WINEPREFIX="$MO2PFX" "$MO2WINE" "$MO2EXE" >"$STLSHM/${FUNCNAME[0]}_${IFILE##*/}.log" 2>"$STLSHM/${FUNCNAME[0]}_${IFILE##*/}.log"
			fi
		cd - >/dev/null || return
	else
		writelog "SKIP" "${FUNCNAME[0]} - Could not find '$MO2EXE' - can't start $MO - this should not happen" E
	fi
}

function dlMod2nexurl {
	setMO2Vars
	# improvable - feel free to open a PR
	MONGUR1="${1//nxm:\/\/}"
	MONGURL="${MONGUR1%%/*}"
	MODLER="$STLSHM/dlNexMod-$MONGURL"

	if [ -f "$MODLER" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Download Url '$1' for game '$MONGURL' using currently running MO session via '$MODLER'"
		"$MODLER" "$1" >"$MODLER.log" 2>"$MODLER.log"
	else
		setSteamPath "SROOT"
		MONINST="$(grep -i "\"$MONGURL\"" "$MO2GAMES" | head -n1 | cut -d ';' -f1)"
		MOIN="$MO2PFX/$DRCU/$STUS/$ADLO/$MO/${MONINST//\"}"
		MOININI="$MOIN/${MO}.ini"

		if [ -f "$MOININI" ]; then
			cd "${MO2EXE%/*}" >/dev/null || return
				writelog "INFO" "${FUNCNAME[0]} - Download Url '$1' for game '$MONGURL'" "E"
				writelog "INFO" "${FUNCNAME[0]} - STEAM_COMPAT_CLIENT_INSTALL_PATH=\"$SROOT\" STEAM_COMPAT_DATA_PATH=\"$MO2COMPDATA\" \"$MO2RUNPROT\" \"run\" \"${MO}.exe\" \"\$1\""
				STEAM_COMPAT_CLIENT_INSTALL_PATH="$SROOT" STEAM_COMPAT_DATA_PATH="$MO2COMPDATA" "$MO2RUNPROT" "run" "${MO}.exe" "$1"
			cd - >/dev/null || return
		else
			writelog "SKIP" "${FUNCNAME[0]} - Download Url is for game '$MONGURL', which does not have an instance in '$MO2PFX/$DRCU/$STUS/$ADLO/$MO'"
		fi
	fi
}

function setMO2DLMime {
	setMO2Vars

	MO2D="$MO-${PROGNAME,,}-dl.desktop"
	FMO2D="$HOME/.local/share/applications/$MO2D"
	
	if [ ! -f "$FMO2D" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Creating new desktop file $MO2D"
		{
		echo "[Desktop Entry]"
		echo "Type=Application"
		echo "Categories=Game;"
		echo "Name=$MO ($PROGNAME - ${PROGNAME,,})"
		echo "MimeType=x-scheme-handler/nxm;x-scheme-handler/nxm-protocol"
		echo "Terminal=false"
		echo "X-KeepTerminal=false"
		echo "Path=$(dirname "$MO2EXE")"
		echo "Exec=$(realpath "$0") mo2 u %u"
		echo "NoDisplay=true"
		} >> "$FMO2D"
		
		VD="$VTX-${PROGNAME,,}-dl.desktop"
		FVD="$HOME/.local/share/applications/$VD"
		if [ -f "$FVD" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Renaming desktopfile ${FVD} to ${FVD}-off, because '$MO2D' was created"
			mv "$FVD" "$FVD-off"
		fi
	else
		if grep -q "$MO2PFX" "$FMO2D"; then
			writelog "INFO" "${FUNCNAME[0]} - Desktopfile '$FMO2D' looks to be up2date"
			return
		else
			writelog "INFO" "${FUNCNAME[0]} - Renaming desktopfile '$FMO2D' and creating a new one for ${PROGNAME,,}"
			mv "$FMO2D" "$FMO2D-old"
			setMO2DLMime
		fi	
	fi

	# setting mime types for nxm
	XDGMIME="xdg-mime"

	if [ -x "$(command -v "$XDGMIME" 2>/dev/null)" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Setting download defaults for nexusmod protocol via $XDGMIME pointing at $MO2D"
		"$XDGMIME" default "$MO2D" x-scheme-handler/nxm
		"$XDGMIME" default "$MO2D" x-scheme-handler/nxm-protocol
	else
		writelog "SKIP" "${FUNCNAME[0]} - $XDGMIME not found - couldn't set download defaults for nexusmod protocol - skipping"
	fi
}

function checkMO2 {
	if [ "$MO2MODE" != "disabled" ]; then
		writelog "INFO" "${FUNCNAME[0]} - MO2MODE is '$MO2MODE' - starting MO2"

		if [ "$WAITMO2" -gt 0 ]; then
			writelog "INFO" "${FUNCNAME[0]} - Opening $MO Requester with timeout '$WAITMO2'"
			fixShowGnAid
			export CURWIKI="$PPW/Mod-Organizer-2"
			TITLE="${PROGNAME}-Open-Mod-Organizer2"
			pollWinRes "$TITLE"

			setShowPic
#			--button="$BUT_MO2_SIL":4 
			"$YAD" --f1-action="$F1ACTION" --image "$SHOWPIC" --image-on-top --window-icon="$STLICON" --form --center --on-top "$WINDECO" \
			--title="$TITLE" \
			--text="$(spanFont "$SGNAID - $GUI_ASKMO2" "H")" \
			--button="$BUT_MO2_GUI":0 \
			--button="$BUT_MO2_SKIP":6 \
			--timeout="$WAITMO2" \
			--timeout-indicator=top \
			"$GEOM"

			case $? in
				0)  {
						writelog "INFO" "${FUNCNAME[0]} - Selected to start $MO with gui"
						MO2MODE="gui"
					}
				;;
				4)  {
						writelog "INFO" "${FUNCNAME[0]} - Selected to start $MO with mods silently"
						MO2MODE="silent"
					}
				;;
				6)  {
						writelog "INFO" "${FUNCNAME[0]} - Selected CANCEL - Not starting $MO at all"
						MO2MODE="disabled"
					}
				;;
				70) {
						writelog "INFO" "${FUNCNAME[0]} - TIMEOUT - Starting $MO2 gui" # with mods silently"
						MO2MODE="gui"
					}
				;;
			esac
		else
			writelog "INFO" "${FUNCNAME[0]} - $MO Requester was skipped because WAITMO2 is '$WAITMO2' - not changing MO2MODE '$MO2MODE'"
		fi
		prepareMO2 "$AID" "$MO2MODE"
		if [ "$MO2MODE" != "disabled" ] && [ "$USECUSTOMCMD" -eq 1 ]; then
			writelog "INFO" "${FUNCNAME[0]} - Disabling custom command, because $MO2 is enabled"
			USECUSTOMCMD=0
		fi
	fi
}

#### MO2 MOD ORGANIZER STOP ####

# dprs:
function dlLatestDprs {
	writelog "INFO" "${FUNCNAME[0]} - Search for latest $DPRS version online"
	LATDPRS="$("$WGET" -q "${DPRSRELURL}/latest" -O - 2> >(grep -v "SSL_INIT") | grep -m1 "${DPRS}-v*.*.exe" | grep -oE "${DPRS}-v[^\"]+")"

	if [ -n "$LATDPRS" ]; then
		DSPATH="$DPRSDLDIR/$LATDPRS"

		if [ ! -f "$DSPATH" ]; then
			DPRSVR1="${LATDPRS//$DPRS-}"
			DPRSVRS="${DPRSVR1//.exe}"
		
			DLURL="$DPRSRELURL/download/$DPRSVRS/$LATDPRS"
			writelog "INFO" "${FUNCNAME[0]} - Downloading $LATDPRS to $VORTEXDLDIR from '$DLURL'"
			notiShow "$(strFix "$NOTY_DLCUSTOMPROTON" "$LATDPRS")"
			dlCheck "$DLURL" "$DSPATH" "X" "Downloading '$LATDPRS'"
			notiShow "$(strFix "$NOTY_DLCUSTOMPROTON2" "$LATDPRS")"
		else
			writelog "SKIP" "${FUNCNAME[0]} - Already have the latest version in '$DSPATH'"
		fi	
	else
		writelog "SKIP" "${FUNCNAME[0]} - No valid '$DPRS' version found ('$LATDPRS') - nothing to download - skipping"
	fi
}

function dlLatestDepsProg {
	writelog "INFO" "${FUNCNAME[0]} - Search for latest $DEPS version online"
	DEPS64ZIP="${DEPS}_x64_Release.zip"
	DEPS32ZIP="${DEPS64ZIP//64/86}"

	LATDEPSR1="$("$WGET" -q "${DEPURL}/latest" -O - 2> >(grep -v "SSL_INIT") | grep -m1 "$DEPS64ZIP")"
	LATDEPSR2="${LATDEPSR1%/*}"
	LATDEPSV="${LATDEPSR2##*/}"

	if [ -n "$LATDEPSV" ]; then
		DLDIR="$DEPSDLDIR/$LATDEPSV"

		if [ -s "$DEPSLATDIR" ] && [ "$(readlink -f "$DEPSLATDIR")" == "$(readlink -f "$DLDIR")" ]; then
			writelog "SKIP" "${FUNCNAME[0]} - Symlink '$DEPSLATDIR' already points to latest version '$DLDIR'" E
		else
			mkProjDir "$DLDIR/64"
			mkProjDir "$DLDIR/32"
			DEPS64ZPATH="$DLDIR/$DEPS64ZIP"
			DEPS32ZPATH="$DLDIR/$DEPS32ZIP"

			if [ ! -f "$DEPS64ZPATH" ]; then	
				DLURL="$DEPURL/download/$LATDEPSV/$DEPS64ZIP"
				writelog "INFO" "${FUNCNAME[0]} - Downloading $DEPS64ZIP to '$DLDIR' from '$DLURL'"
				notiShow "$(strFix "$NOTY_DLCUSTOMPROTON" "$DEPS64ZIP")" "S"
				dlCheck "$DLURL" "$DEPS64ZPATH" "X" "Downloading '$DEPS64ZIP'"
				notiShow "$(strFix "$NOTY_DLCUSTOMPROTON2" "$DEPS64ZIP")" "S"
			else
				writelog "SKIP" "${FUNCNAME[0]} - Already have '$DEPS64ZIP' in '$DLDIR'"
			fi
			
			if [ ! -f "$DEPS32ZPATH" ]; then	
				DLURL="$DEPURL/download/$LATDEPSV/$DEPS32ZIP"
				writelog "INFO" "${FUNCNAME[0]} - Downloading $DEPS32ZIP to '$DLDIR' from '$DLURL'"
				notiShow "$(strFix "$NOTY_DLCUSTOMPROTON" "$DEPS64ZIP")" "S"
				dlCheck "$DLURL" "$DEPS32ZPATH" "X" "Downloading '$DEPS32ZIP'"
				notiShow "$(strFix "$NOTY_DLCUSTOMPROTON2" "$DEPS64ZIP")" "S"
			else
				writelog "SKIP" "${FUNCNAME[0]} - Already have '$DEPS32ZIP' in '$DLDIR'"
			fi

			rm "$DEPSLATDIR" 2>/dev/null
			writelog "INFO" "${FUNCNAME[0]} - 'ln -s \"$DLDIR\" \"$DEPSLATDIR\"'" E
			ln -s "$DLDIR" "$DEPSLATDIR"
			
			if [ ! -f "$DEPSL64" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Extracting $DEPS64ZIP to '$DLDIR/64'"
				"$UNZIP" -q "$DEPS64ZPATH" -d "$DLDIR/64"
				notiShow "$GUI_DONE" "S"
			fi

			if [ ! -f "$DEPSL32" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Extracting $DEPS32ZIP to '$DLDIR/32'"
				"$UNZIP" -q "$DEPS32ZPATH" -d "$DLDIR/32"
				notiShow "$GUI_DONE" "S"
			fi 		
		fi
	else
		writelog "SKIP" "${FUNCNAME[0]} - No valid '$DEPS' version found ('$LATDPRS') - nothing to download - skipping"
	fi
}

function checkDepsLaunch {
	if [ "$RUN_DEPS" -eq 1 ] && [ "$ISGAME" -eq 2 ] && [ "$USEWINE" -eq 0 ]; then

		if [ "$DEPSAUTOUP" -eq 1 ] || [ ! -f "$DEPSL64" ]; then
			StatusWindow "$(strFix "$NOTY_DLCUSTOMPROTON" "$DEPS")" "dlLatestDepsProg" "DownloadDepsStatus"
		fi

		writelog "INFO" "${FUNCNAME[0]} - Starting '$DEPS' for '$GE ($AID)'"

		if [ "$(getArch "$GP")" == "32" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Using '$DEPSL32' as '$GE' is 32bit" 
			DEPSEXE="$DEPSL32"
		elif [ "$(getArch "$GP")" == "64" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Using '$DEPSL64' as '$GE' is 64bit" 
			DEPSEXE="$DEPSL64"
		else
			writelog "INFO" "${FUNCNAME[0]} - Could not get architecture of '$GP' - using '$DEPSL64'" 
			DEPSEXE="$DEPSL64"	
		fi
		
		if [ ! -f "$DEPSEXE" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Installing failed - can't start '$DEPSEXE' - skipping"
			RUN_DEPS=0
		else
#			installWinetricksPaks "vcrun2019" "$RUNWINE" "extWine64Run" # looks like this is not needed - can't see any difference
			WGP="$(extWine64Run "$RUNWINE" winepath -w "$GP")"
			writelog "INFO" "${FUNCNAME[0]} - Starting '$DEPSEXE' using extWine64Run for the game '$WGP'"
			extWine64Run "$RUNWINE" "$DEPSEXE" "$WGP"
		fi
	fi
}

function startDepressurizer {
	if [ ! -d "$DPRSCOMPDATA" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Creating '$DPRS' $CODA and installing deps"
		mkProjDir "$DPRSCOMPDATA"
		reCreateCompatdata "ccd" "$DPRS" "s"
	fi

	mkProjDir "$DPRSDLDIR"
	if [ "$DPRSPAUTOUP" -eq 1 ]; then
		dlLatestDprs
	fi
	
	DPRSEXE="$(find "${DPRSDLDIR}" -name "${DPRS}-v*.exe" | sort -V | tail -n1)"
	
	if [ ! -f "$DPRSEXE" ] || { [ "$(getArch "$DPRSEXE")" -ne "32" ] && [ "$(getArch "$DPRSEXE")" -ne "64" ];}; then
		dlLatestDprs
		DPRSEXE="$(find "${DPRSDLDIR}" -name "${DPRS}-v*.exe" | sort -V | tail -n1)"
	fi

	if [ ! -f "$DPRSEXE" ]; then
		writelog "ERROR" "${FUNCNAME[0]} - Could not find or download a '$DPRS' exe"
	else

	# copy or symlink required vdf files from steam to the DPRSCOMPDATA

	DPRSPFX="${DPRSCOMPDATA//\"/}/pfx"
	VDFDSTDIR="$DPRSPFX/$DRC/$PFX86S"

	if [ -z "$SUSDA" ] || [ -z "$STUIDPATH" ]; then
		setSteamPaths
	fi
	SC="$STUIDPATH/$SRSCV"
	FSCV="$STUIDPATH/config/$SCVDF"

	AIDST="$VDFDSTDIR/$AAVDF"
	PIDST="$VDFDSTDIR/$APVDF"
	SRSDST="$VDFDSTDIR/$USDA/$STEAMUSERID/$SRSCV"
	SRLDST="$VDFDSTDIR/$USDA/${FLCV//$SUSDA\/}"
	SCDST="$VDFDSTDIR/$USDA/${FLCV//$SUSDA\/}"
	SCSHDST="$VDFDSTDIR/$USDA/$STEAMUSERID/$SCRSH"
	
	AISRC="$FAIVDF"
	PISRC="$PIVDF"
	SRSSRC="$STUIDPATH/$SRSCV"
	SRLSRC="$FLCV"
	SCSRC="$STUIDPATH/config/$SCVDF"
	SCSHSRC="$STUIDPATH/$SCRSH"

	{
		echo "SC $SC"
		echo "FLCV $FLCV"
		echo "FSCV $FSCV"
		echo "AIDST $AIDST"
		echo "PIDST $PIDST"
		echo "SRSDST $SRSDST"
		echo "SRLDST $SRLDST"
		echo "SCDST $SCDST"
		echo "SCSHDST $SCSHDST"
		echo "AISRC $AISRC"
		echo "PISRC $PISRC"
		echo "SRSSRC $SRSSRC"
		echo "SRLSRC $SRLSRC"
		echo "SCSRC $SCSRC"
		echo "SCSHSRC $SCSHSRC"
	} > "$STLSHM/${DPRS}-paths.txt"

	function cleanCpSrcTo {
		if [ -f "$1" ]; then
			mkProjDir "${2%/*}"
			if ! cmp -s "$1" "$2" || [ -L "$2" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Copying '$1' to '$2'"
				rm "$2" 2>/dev/null
				cp "$1" "$2"
			else
				writelog "SKIP" "${FUNCNAME[0]} - '$2' is identical to '$1'"
			fi
		else
			writelog "SKIP" "${FUNCNAME[0]} - Source file '$1' not found"
		fi
	}

	function cleanLnSrcTo {
		if [ -f "$1" ]; then
			mkProjDir "${2%/*}"
			if [ "$(readlink -f "$2")" == "$(readlink -f "$1")" ]; then
				writelog "SKIP" "${FUNCNAME[0]} - '$2' is already pointing to '$1'"
			else
				writelog "INFO" "${FUNCNAME[0]} - Symlinking '$1' to '$2'"
				rm "$2" 2>/dev/null
				ln -s "$1" "$2"
			fi
		else
			writelog "SKIP" "${FUNCNAME[0]} - Source file '$1' not found"
		fi	
	}
	
	if [ "$DPRSUSEVDFSYMLINKS" -eq 1 ]; then
		writelog "INFO" "${FUNCNAME[0]} - Symlinking required vdf files from the linux steam install into '$DPRSCOMPDATA'"
		cleanLnSrcTo "$AISRC" "$AIDST"
		cleanLnSrcTo "$PISRC" "$PIDST"
		cleanLnSrcTo "$SRSSRC" "$SRSDST"
		cleanLnSrcTo "$SRLSRC" "$SRLDST"
		cleanLnSrcTo "$SCSRC" "$SCDST"
		cleanLnSrcTo "$SCSHSRC" "$SCSHDST"
	elif [ "$DPRSUSEVDFSYMLINKS" -eq 0 ]; then
		writelog "INFO" "${FUNCNAME[0]} - Copying required vdf files from the linux steam install to '$DPRSCOMPDATA'"
		cleanCpSrcTo "$AISRC" "$AIDST"
		cleanCpSrcTo "$PISRC" "$PIDST"
		cleanCpSrcTo "$SRSSRC" "$SRSDST"
		cleanCpSrcTo "$SRLSRC" "$SRLDST"
		cleanCpSrcTo "$SCSRC" "$SCDST"
		cleanCpSrcTo "$SCSHSRC" "$SCSHDST"
	else
		writelog "WARN" "${FUNCNAME[0]} - DPRSUSEVDFSYMLINKS is neither '1' nor '0' - this shouldn't happen!"
	fi

	# start $DPRS via proton starting here

		writelog "INFO" "${FUNCNAME[0]} - Using Proton Version '$USEDPRSPROTON'"
			
		if test -z "$DPRSPROTON" || [ ! -f "$DPRSPROTON" ]; then
			if [ -z "${ProtonCSV[0]}" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Don't have the Array of available Proton versions yet - creating"
				getAvailableProtonVersions "up" X
			fi
			DPRSPROTON="$(getProtPathFromCSV "$USEDPRSPROTON")"
		fi

		if [ ! -f "$DPRSPROTON" ]; then
			DPRSPROTON="$(fixProtonVersionMismatch "USEDPRSPROTON" "$STLGAMECFG" X)"
		fi

		if [ ! -f "$DPRSPROTON" ]; then
			writelog "WARN" "${FUNCNAME[0]} - proton file '$DPRSPROTON' for proton version '$USEDPRSPROTON' not found - trying 'USEPROTON' instead"
			DPRSPROTON="$(getProtPathFromCSV "$USEPROTON")"
		fi

		CHECKWINED="$(dirname "$DPRSPROTON")/$DBW"
		CHECKWINEF="$(dirname "$DPRSPROTON")/$FBW"
		if [ -f "$CHECKWINED" ]; then
			DPRSWINE="$CHECKWINED"
		elif [ -f "$CHECKWINEF" ]; then
			DPRSWINE="$CHECKWINEF"
		fi

		if [ -f "$DPRSWINE" ];then
			writelog "INFO" "${FUNCNAME[0]} - Starting '$DPRSEXE' using '$DPRSWINE'"
			DPRSWINEDEBUG="-all"
			DPRSSUDIR="$DPRSPFX/$DRCU/$STUS/$APDA/$DPRS"
			mkProjDir "$DPRSSUDIR"
			cd "$DPRSSUDIR" >/dev/null || return
			sleep 1
			LC_ALL="C" PATH="$STLPATH" LD_LIBRARY_PATH="" LD_PRELOAD="" WINE="$DPRSWINE" WINEARCH="win64" WINEDEBUG="$DPRSWINEDEBUG" WINEPREFIX="$DPRSPFX" "$DPRSWINE" "$DPRSEXE" >/dev/null 2>/dev/null
			cd - >/dev/null || return
		else
			writelog "ERROR" "${FUNCNAME[0]} - Proton Wine for not found - can't start '$DPRSEXE'"
		fi
	fi
}

function checkDep {
	CATNAM="$1"
	CHECKPROG="$2"

	if [ -n "${!CATNAM##*[!0-9]*}" ]; then
		if [ "${!CATNAM}" -eq 1 ]; then
			if [ ! -x "$(command -v "$CHECKPROG")" ]; then
				writelog "WARN" "${FUNCNAME[0]} - Disabling '$CATNAM' because '$CHECKPROG' is missing"
				notiShow "$(strFix "$NOTY_PROGRAMMISSING" "$CATNAM" "$CHECKPROG")"
				unset "$CATNAM"
			fi
		fi
	fi
}

function checkExtDeps {
	if [ -z "$NOTY" ]; then
		NOTY="notify-send"
	fi

	checkDep "USEGAMEMODERUN" "$GAMEMODERUN"
	checkDep "USEGAMESCOPE" "$GAMESCOPE"
	checkDep "RUN_NYRNA" "$NYRNA"
	checkDep "STRACERUN" "$STRACE"
	checkDep "RUN_WINETRICKS" "$WINETRICKS"
	checkDep "WINETRICKSPAKS" "$WINETRICKS"
	checkDep "RUN_REPLAY" "$REPLAY"
	checkDep "USELUXTORPEDA" "$LUXTORPEDACMD"
	checkDep "USEROBERTA" "$ROBERTACMD"
	checkDep "USEBOXTRON" "$BOXTRONCMD"
	checkDep "RUNSBSVR" "$VRVIDEOPLAYER"
	checkDep "RUN_GAMCON" "$GAMCON"
	checkDep "USENETMON" "$NETMON"
	checkDep "USENOTIFIER" "$NOTY"
	checkDep "RUN_WINECFG" "$WINECFG"
	checkDep "CHECKHMD" "$LSUSB"
	checkDep "HAVEINNO" "$INNOEXTRACT"
	checkDep "BACKUPSTEAMUSER" "$RSYNC"
	checkDep "USESPECIALK" "$SEVZA"
}

function setYadBin {
	if [ -f "$1" ]; then
		YADFILE="$1"
	elif [ "$1" == "conty" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Using conty as yad binary"
		if [ ! -f "$CONTYDLDIR/$CONTY" ]; then
			StatusWindow "$(strFix "$NOTY_DLCUSTOMPROTON" "${CONTY%%.*}")" "dlConty" "DownloadContyStatus"
		else
			writelog "INFO" "${FUNCNAME[0]} - Found Conty binary in '$CONTYDLDIR/$CONTY'"
		fi

		if [ -f "$CONTYDLDIR/$CONTY" ]; then
			if [ "$(readlink "$CONTYDLDIR/$YAD")" == "$CONTYDLDIR/$CONTY" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Symlink '$CONTYDLDIR/$YAD' already points to '$CONTYDLDIR/$CONTY'"
			else
				writelog "INFO" "${FUNCNAME[0]} - Creating symlink '$CONTYDLDIR/${YAD##*/}' pointing to '$CONTYDLDIR/$CONTY'"
				ln -s "$CONTYDLDIR/$CONTY" "$CONTYDLDIR/${YAD##*/}"
			fi

			if [ "$(readlink "$CONTYDLDIR/${YAD##*/}")" == "$CONTYDLDIR/$CONTY" ]; then
				YADFILE="$CONTYDLDIR//${YAD##*/}"
			fi
		fi

	elif [ "$1" == "ai" ] || [ "$1" == "appimage" ]; then
		YADSTLIMAGE="Yad-8418e37-x86_64.AppImage"
		YAIDL="$YAIURL/$YADSTLIMAGE/$YADSTLIMAGE"
		YADAPPIMAGE="$YADSTLIMAGE"
		DLCHK="sha512sum"
		mkProjDir "$YADAIDLDIR"

		if [ -n "$2" ] && grep -q "^http" <<< "$2"; then
			YAIDL="$2"
			DLCHK="X"
			if grep -q "AppImage$" <<< "$YAIDL"; then
				YADAPPIMAGE="${YAIDL##*/}"
			else
				YADAPPIMAGE="Yad-$(date +%Y%m%d)-x86_64.AppImage"
			fi

			writelog "INFO" "${FUNCNAME[0]} - Trying to download $YAD from provided url '$YAIDL'"
		elif [ -n "$2" ] && [ -f "$2" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Trying to use provided file '$2' for yad"
			YAIDST="$2"
			DLCHK="X"
		elif [ -n "$2" ] && [ ! -f "$2" ]; then
			writelog "WARN" "${FUNCNAME[0]} - Provided string '$2' is neither a http download url nor a valid absolute path to a file - downloading and using the default instead"
		fi

		if [ -f "$YAIDST" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Using Yad AppImage under '$YAIDST'"
		else
			YAIDST="$YADAIDLDIR/$YADAPPIMAGE"
			if [ "$DLCHK" == "sha512sum" ]; then
				INCHK="$("$WGET" -q "${YAIDL}.${DLCHK}" -O - 2> >(grep -v "SSL_INIT") | cut -d ' ' -f1)"
			else
				INCHK="$NON"
			fi

			dlCheck "$YAIDL" "$YAIDST" "$DLCHK" "Downloading '$YAIDL' to '$YAIDST'" "$INCHK"
		fi
		if [ -f "$YAIDST" ]; then
			YADFILE="$YAIDST"
		fi
	else
		writelog "ERROR" "${FUNCNAME[0]} - '$1' is no valid option"
	fi
	
	if [ -n "$YADFILE" ]; then
		MINYAD="7.2"
		chmod +x "$YADFILE" 2>/dev/null
		YADVER="$("$YADFILE" --version | tail -n1 | cut -d ' ' -f1)"
		if [ "$(printf '%s\n' "$MINYAD" "$YADVER" | sort -V | head -n1)" != "$MINYAD" ] || grep -qi "[A-Z]" <<< "$YADVER" ; then
			writelog "ERROR" "${FUNCNAME[0]} - Version for '$YADFILE' is invalid. You need to at least version '$MINYAD'"
		else
			writelog "INFO" "${FUNCNAME[0]} - configuring yad binary to '$YADFILE'"
			updateConfigEntry "YAD" "$YADFILE" "$STLDEFGLOBALCFG"
		fi
	fi
}

function checkIntDeps {

	if [ "$SKIPINTDEPCHECK" -eq 1 ] || [ "$1" == "yad" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Skipping dependency check for internally used programs"
	else
		DEPSMISSING=0

		while read -r INTDEP; do
			if [ ! -x "$(command -v "${!INTDEP}")" ]; then
				writelog "ERROR" "${FUNCNAME[0]} - ${!INTDEP} not found!" "E"
				notiShow "$(strFix "$NOTY_NOTFOUND" "${!INTDEP}")"
				DEPSMISSING=1
			fi
		done <<< "$(sed -n "/^#STARTINTDEPS/,/^#ENDINTDEPS/p;/^#ENDINTDEPS/q" "$0" | grep -v "^#" | cut -d '=' -f1)"

		if [ -z "$YAD" ]; then
			YAD="$(command -v "yad")"
		fi

		if [ -n "$YAD" ] && [ ! -f "$YAD" ]; then
			OYAD="$YAD"
			writelog "WARN" "${FUNCNAME[0]} - Configured YAD '$YAD' was not found!  Trying to find in in a new location" "E"
			NYAD="$(command -v "yad")"
			if [ -n "$NYAD" ] && [ "$NYAD" != "$OYAD" ];then
				writelog "INFO" "${FUNCNAME[0]} - Updating YAD from '$OYAD' to '$NYAD'" "E"
				YAD="$NYAD"
				touch "$FUPDATE"
				updateConfigEntry "YAD" "$NYAD" "$STLDEFGLOBALCFG"
			else
				writelog "WARN" "${FUNCNAME[0]} - Could not find a new $YAD version" "E"
			fi
		fi

		if [ ! -x "$(command -v "$YAD")" ]; then
			DEPSMISSING=1
			writelog "ERROR" "${FUNCNAME[0]} - '$YAD' was not found! Check '${PROGCMD} --help' for alternatives and/or read '$PROJECTPAGE/wiki/Yad'" "E"
			notiShow "$(strFix "$NOTY_NOTFOUND" "$YAD")"
		fi

		setAwkBin
		
		MINYAD="7.2"
		YADVER="0"

		if [ -f "$YAD" ]; then
			YADVER="$("$YAD" --version | tail -n1 | cut -d ' ' -f1)"
			writelog "INFO" "${FUNCNAME[0]} - Result of version check for yad binary '$YAD' is '$YADVER'"
		fi

		if [ "$(printf '%s\n' "$MINYAD" "$YADVER" | sort -V | head -n1)" != "$MINYAD" ]; then 
			writelog "ERROR" "${FUNCNAME[0]} - Yad version '$YADVER' is too old. You need to update to at least '$MINYAD'" "E"
			notiShow "$(strFix "$NOTY_NOTFOUND2" "$YADVER" "$MINYAD")"
			if [ "$1" != "--help" ] && [ "$1" != "-h" ]; then
				exit
			fi
		fi

		if [ "$DEPSMISSING" -eq 1 ]; then
			writelog "ERROR" "${FUNCNAME[0]} - Above programs need to be installed to use '${PROGNAME,,}'" "E"
			writelog "ERROR" "${FUNCNAME[0]} The dependency check can be disabled by enabling 'SKIPINTDEPCHECK' - exiting now" "E"
			if [ "$1" != "--help" ] && [ "$1" != "-h" ]; then
				exit
			fi
		fi
	fi
}

#####################################################
### CORE LAUNCH START ###

function setLinGameVals {
	if [ "$ISGAME" -eq 3 ]; then
		writelog "INFO" "${FUNCNAME[0]} - Looks like this is a native linux game - disabling some values which are only useful for win games"
		USEVORTEX="0"
		WINETRICKSPAKS="$NON"
		RUN_WINETRICKS="0"
		RUN_WINECFG="0"
		REGEDIT="0"
		VIRTUALDESKTOP="0"
		USERESHADE="0"
		INSTALL_RESHADE="0"
		UUUSEIGCS="0"
		IGCSDST="0"
		USESPECIALK="0"
		USEFWS="0"
	fi
}

function prepareProton {
	if [ "$ISGAME" -eq 2 ]; then
		if [ "$USEWINE" -eq 0 ]; then
			if [ "$EARLYUSEWINE" -eq 1 ]; then
				writelog "INFO" "${FUNCNAME[0]} - Wine has just been disabled, so preparing Proton now"
				getAvailableProtonVersions "up"
				checkStartMode
			fi

			if [ "$HAVEINPROTON" -eq 0 ]; then
				if [ -n "$USEPROTON" ] && [ ! -f "$(getProtPathFromCSV "$USEPROTON")" ]; then
					fixProtonVersionMismatch "USEPROTON" "$STLGAMECFG"
				fi
			
				# (re)initialize Proton dependant variables, when USEPROTON changed in a menu above
				if [ -n "$USEPROTON" ] && [ "$USEPROTON" != "$FIRSTGAMEUSEPROTON" ] && [ "$ISGAME" -eq 2 ]; then
					writelog "INFO" "${FUNCNAME[0]} - setNewProtVars, because '$USEPROTON' != '$FIRSTGAMEUSEPROTON'"
					setNewProtVars "$(getProtPathFromCSV "$USEPROTON")"
				fi
			else
				USEPROTON="$INPROTV"
				setNewProtVars "$(getProtPathFromCSV "$USEPROTON")"
				writelog "INFO" "${FUNCNAME[0]} - Checking the Proton version is not required, because $SLO is used. Proton version set in Steam is '$USEPROTON'"
			fi
			
			if [ "$USEWINEDEBUGPROTON" -eq 1 ]; then
				writelog "INFO" "${FUNCNAME[0]} - Using '$STLWINEDEBUG' as Proton 'WINEDEBUG' parameters, because 'USEWINEDEBUGPROTON' is enabled"
				export WINEDEBUG="$STLWINEDEBUG"
			fi

			if [ -n "$STLWINEDLLOVERRIDES" ] && [ "$STLWINEDLLOVERRIDES" != "$NON" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Using '$STLWINEDLLOVERRIDES' as 'WINEDLLOVERRIDES' parameter"
				export WINEDLLOVERRIDES="$WINEDLLOVERRIDES;$STLWINEDLLOVERRIDES"
			fi
		fi
		
		# export DXVK_CONFIG_FILE if STLDXVKCFG was found or if USEDLSS is enabled:
		DXDLSSCFG="$GLOBALMISCDIR/dxvk-no-nvapiHack.conf"

		if [ -f "$STLDXVKCFG" ]; then
			export DXVK_CONFIG_FILE="$STLDXVKCFG"
		elif [ "$USEDLSS" -eq 1 ] && [ -f "$DXDLSSCFG" ]; then
			writelog "INFO" "${FUNCNAME[0]} - DLSS is enabled and '$DXDLSSCFG' was found - enabling all options required for DLSS"
			export DXVK_CONFIG_FILE="$DXDLSSCFG"
			export PROTON_ENABLE_NVAPI=1
			export PROTON_HIDE_NVIDIA_GPU=0
		fi

		# set VKD3D variables, if it's STL_ variant is != "$NON"

		if [ "$STL_VKD3D_CONFIG" != "$NON" ]; then
			export VKD3D_CONFIG="$STL_VKD3D_CONFIG"
		fi

		if [ "$STL_VKD3D_DEBUG" != "$NON" ]; then
			export VKD3D_DEBUG="$STL_VKD3D_DEBUG"
		fi

		if [ "$STL_VKD3D_SHADER_DEBUG" != "$NON" ]; then
			export VKD3D_SHADER_DEBUG="$STL_VKD3D_SHADER_DEBUG"	
		fi

		if [ "$STL_VKD3D_LOG_FILE" != "$NON" ]; then
			export VKD3D_LOG_FILE="$STL_VKD3D_LOG_FILE"
		fi

		if [ "$STL_VKD3D_VULKAN_DEVICE" != "$NON" ]; then
			export VKD3D_VULKAN_DEVICE="$STL_VKD3D_VULKAN_DEVICE"
		fi

		if [ "$STL_VKD3D_FILTER_DEVICE_NAME" != "$NON" ]; then
			export VKD3D_FILTER_DEVICE_NAME="$STL_VKD3D_FILTER_DEVICE_NAME"
		fi

		if [ "$STL_VKD3D_DISABLE_EXTENSIONS" != "$NON" ]; then
			export VKD3D_DISABLE_EXTENSIONS="$STL_VKD3D_DISABLE_EXTENSIONS"
		fi

		if [ "$STL_VKD3D_TEST_DEBUG" != "$NON" ]; then
			export VKD3D_TEST_DEBUG="$STL_VKD3D_TEST_DEBUG"
		fi

		if [ "$STL_VKD3D_TEST_FILTER" != "$NON" ]; then
			export VKD3D_TEST_FILTER="$STL_VKD3D_TEST_FILTER"
		fi

		if [ "$STL_VKD3D_TEST_EXCLUDE" != "$NON" ]; then
			export VKD3D_TEST_EXCLUDE="$STL_VKD3D_TEST_EXCLUDE"
		fi

		if [ "$STL_VKD3D_TEST_PLATFORM" != "$NON" ]; then
			export VKD3D_TEST_PLATFORM="$STL_VKD3D_TEST_PLATFORM"
		fi

		if [ "$STL_VKD3D_TEST_BUG" != "$NON" ]; then
			export VKD3D_TEST_BUG="$STL_VKD3D_TEST_BUG"
		fi

		if [ "$STL_VKD3D_PROFILE_PATH" != "$NON" ]; then
			export VKD3D_PROFILE_PATH="$STL_VKD3D_PROFILE_PATH"
		fi	

		# shortcut to enable all required flags for SBSVR with ${RESH}
		if [ -n "$SBSVRRS" ]; then
			if [ "$SBSVRRS" -eq 1 ]; then
				writelog "INFO" "${FUNCNAME[0]} - $PROGNAME - SBSVRRS enabled - starting game in SBS-VR using ${RESH}"
				export RUNSBSVR=1
				export INSTALL_RESHADE=1
				export RESHADE_DEPTH3D=1
				export USERESHADE=1
				export ENABLE_VKBASALT=0
			fi
		fi
	else
		writelog "SKIP" "${FUNCNAME[0]} - No Proton game"
	fi	
}

function sortGameArgs {
	if [ -z "$SLOARGS" ] || [ "$SLOARGS" == "$NON" ]; then
		SLOARGS="$NON"

		if [ "$SORTGARGS" -eq 1 ]; then
			if [ "${#ORGCMDARGS[@]}" -ge 1 ]; then
				CFSTG="coming from Steam/the game"
				if [ -n "$ARGUMENTS" ]; then
					writelog "INFO" "${FUNCNAME[0]} - Game arguments '$ARGUMENTS' $CFSTG directly"
					writelog "INFO" "${FUNCNAME[0]} - Separating them from the found arguments '${ORGCMDARGS[*]}'"
					
					while read -r arg; do
						if [ -n "$arg" ] && [ "$arg" != "" ] && grep -q -- "$arg" <<< "$ARGUMENTS" ; then
							writelog "INFO" "${FUNCNAME[0]} - '$arg' is an argument $CFSTG, because it is within ARGUMENTS: '$ARGUMENTS'"
							mapfile -d " " -t -O "${#HARGSARR[@]}" HARGSARR <<< "$arg"
						elif [[ ! "${HARGSARR[*]}" =~ $arg ]] && [ -n "$arg" ] && [ "$arg" != "" ]; then
							writelog "INFO" "${FUNCNAME[0]} - '$arg' is probably an argument coming from $SLO"
							mapfile -d " " -t -O "${#SLOARRGS[@]}" SLOARRGS <<< "$arg"
						else
							writelog "SKIP" "${FUNCNAME[0]} - skipping '$arg'"
						fi
					done <<< "$(printf "%s\n" "${ORGCMDARGS[@]}")"

					if [ "${#HARGSARR[@]}" -ge 1 ] && [ "$HARDARGS" == "$NOPE" ]; then
						writelog "INFO" "${FUNCNAME[0]} - Filling empty game config variable 'HARDARGS' with arguments $CFSTG"
						HARDARGSR="$(printf "%s" "${HARGSARR[@]}" | tr '\n' ' ')"
						HARDARGS="${HARDARGSR%*[[:blank:]]}"
						touch "$FUPDATE"
						updateConfigEntry "HARDARGS" "$HARDARGS" "$STLGAMECFG"
					fi

				else
					writelog "INFO" "${FUNCNAME[0]} - No game arguments $CFSTG found"
					writelog "INFO" "${FUNCNAME[0]} - So assuming '${ORGCMDARGS[*]}' comes completely from $SLO."
					while read -r arg; do
						mapfile -d " " -t -O "${#SLOARRGS[@]}" SLOARRGS <<< "$arg"
					done <<< "$(printf "%s\n" "${ORGCMDARGS[@]}")"
				fi

				if [ "${#SLOARRGS[@]}" -ge 1 ]; then
					SLOARGSR="$(printf "%s" "${SLOARRGS[@]}" | tr '\n' ' ')"
					SLOARGS="${SLOARGSR%*[[:blank:]]}"
					writelog "INFO" "${FUNCNAME[0]} - Set SLOARGS to '$SLOARGS'"
				fi
			else
				writelog "SKIP" "${FUNCNAME[0]} - No game arguments $CFSTG or via $SLO"
			fi
		else
			writelog "SKIP" "${FUNCNAME[0]} - Sorting the game arguments is disabled"
		fi
	else
		writelog "SKIP" "${FUNCNAME[0]} - Nothing to do on the 2nd run"
	fi
}

function initOldProtonArr {
	delEmptyFile "$PROTONCSV"
	if [ -f "$PROTONCSV" ]; then
		unset ProtonCSV
		writelog "INFO" "${FUNCNAME[0]} - Creating an initial array with available Proton versions using the file '$PROTONCSV' which was created during a previous run"
		mapfile -t -O "${#ProtonCSV[@]}" ProtonCSV < "$PROTONCSV"
	fi
}

function initFirstProton {
	initOldProtonArr
	if [ "$HAVEINPROTON" -eq 1 ]; then
		writelog "INFO" "${FUNCNAME[0]} - skipping function, because Proton version is provided by commandline ($PROGCMD used via '$SLO')"
	else
		writelog "INFO" "${FUNCNAME[0]} - Initializing Proton"

		FUP1="$(grep "^USEPROTON=" "$STLDEFGAMECFG" | cut -d '=' -f2)"
		FIRSTUSEPROTON="${FUP1//\"}"

		if [ -z "$FIRSTUSEPROTON" ]; then
			writelog "INFO" "${FUNCNAME[0]} - No Proton version available in template yet - searching for one"
			FIRSTUSEPROTON="$(getDefaultProton)"
			touch "$FUPDATE"
			updateConfigEntry "USEPROTON" "$USEPROTON" "$STLDEFGAMECFG"
			writelog "INFO" "${FUNCNAME[0]} - Updated 'USEPROTON' in '$STLDEFGAMECFG' to '$USEPROTON'"
		fi
		if [ ! -f "$(getProtPathFromCSV "$FIRSTUSEPROTON")" ]; then
			USEPROTON="$FIRSTUSEPROTON"
			fixProtonVersionMismatch "USEPROTON" "$STLDEFGAMECFG"
			FUP1="$(grep "^USEPROTON=" "$STLDEFGAMECFG" | cut -d '=' -f2)"
			FIRSTUSEPROTON="${FUP1//\"}"
		fi

		writelog "INFO" "${FUNCNAME[0]} - Initial Proton version 'FIRSTUSEPROTON' from '$STLDEFGAMECFG' is '$FIRSTUSEPROTON'"
	fi
}

function setMangoHudCfg {
	if [ "$USEMANGOHUDSTLCFG" -eq 1 ]; then
		mkProjDir "$MAHUCID"
		mkProjDir "$MAHUCTI"
		MHIC="$MAHUCID/${AID}.conf"
		writelog "INFO" "${FUNCNAME[0]} - Using internal $MAHU config '$MHIC' as requested"
		getGameName "$AID"
		MHTC="$MAHUCTI/${GAMENAME}.conf"
		
		if [ ! -f "$MHIC" ]; then
			writelog "WARN" "${FUNCNAME[0]} - '$MHIC' does not exist (yet) - trying to create it from the template '$MAHUTMPL'"
			if [ ! -f "$MAHUTMPL" ]; then
				writelog "WARN" "${FUNCNAME[0]} - The template '$MAHUTMPL' does not exist (yet) - trying to get the upstream example config"
				MAHUEX="/usr/share/doc/mangohud/MangoHud.conf.example"
				if [ -f "$MAHUEX" ]; then
					writelog "INFO" "${FUNCNAME[0]} - Copying '$MAHUEX' to '$MAHUTMPL'"
					cp "$MAHUEX" "$MAHUTMPL"
				else
					writelog "SKIP" "${FUNCNAME[0]} - Could not find '$MAHUEX'"
				fi
			fi
			
			if ! grep -q "$MAHULID/XXX" "$MAHUTMPL" && ! grep -q "^output_folder" "$MAHUTMPL" ; then
				writelog "INFO" "${FUNCNAME[0]} - Appending default $MAHU output_folder to '$MAHUTMPL', because none is configured"
				echo "output_folder = $MAHULID/XXX" >> "$MAHUTMPL"
			fi
			
			if [ -f "$MAHUTMPL" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Copying '$MAHUTMPL' to '$MHIC'"
				cp "$MAHUTMPL" "$MHIC"
				if grep -q "$MAHULID/XXX" "$MHIC"; then
					writelog "INFO" "${FUNCNAME[0]} - Setting $MAHU output_folder to '$MAHULID/$AID' in $MHIC"
					sed "s:$MAHULID/XXX:$MAHULID/$AID:" -i "$MHIC"
				fi
			else
				writelog "SKIP" "${FUNCNAME[0]} - Could not find or create '$MAHUTMPL'"
			fi
		fi
		
		if [ -f "$MHIC" ]; then
			if grep -q "$MAHULID/$AID" "$MHIC"; then
				mkProjDir "$MAHULID/$AID"
				mkProjDir "$MAHULTI"
				createSymLink "${FUNCNAME[0]}" "$MAHULID/$AID" "$MAHULTI/${GAMENAME}"
			fi

			writelog "INFO" "${FUNCNAME[0]} - Pointing variable MANGOHUD_CONFIGFILE to '$MHIC'"
			export MANGOHUD_CONFIGFILE="$MHIC"
			createSymLink "${FUNCNAME[0]}" "$MHIC" "$MHTC"
		else
			writelog "SKIP" "${FUNCNAME[0]} - Could not find or create '$MHIC'"
		fi
	fi
}

function autoBumpGE {
	if [ "$AUTOBUMPGE" -eq 1 ] && grep -q "\-GE" <<< "$USEPROTON" && [ "$ISGAME" -eq 2 ]; then
		writelog "INFO" "${FUNCNAME[0]} - Current Proton version is $USEPROTON"
		dlLatestGE "lge" "X"
		getAvailableProtonVersions "up"
		NEWESTGE="$(grep "\-GE" "$PROTONCSV" | sort -n | tail -n1)"
		NEWESTGE="${NEWESTGE%%;*}"
		if [ "$NEWESTGE" == "$USEPROTON" ]; then
			writelog "SKIP" "${FUNCNAME[0]} - $USEPROTON is already the newest Proton-GE version"
		else
			writelog "INFO" "${FUNCNAME[0]} - $(strFix "$NOTY_BUMP" "$USEPROTON" "$USEPROTON" "$NEWESTGE")"
			notiShow "$(strFix "$NOTY_BUMP" "$USEPROTON" "$USEPROTON" "$NEWESTGE")"
			USEPROTON="$NEWESTGE"
			touch "$FUPDATE"
			updateConfigEntry "USEPROTON" "$USEPROTON" "$STLGAMECFG"
		fi
	fi
}

function checkPev {
	if [ "$ISGAME" -eq 2 ] && [ -f "$GP" ]; then
		unset USEPEVA
		mapfile -d " " -t -O "${#USEPEVA[@]}" USEPEVA < <(printf '%s' "USEPEV_PELDD USEPEV_PEPACK USEPEV_PERES USEPEV_PESCAN USEPEV_PESEC USEPEV_PESTR USEPEV_READPE")

		if [ -n "$USEALLPEV" ] && [ "$USEALLPEV" -eq 1 ]; then
			while read -r SUSEPEV; do
				if [ -n "$SUSEPEV" ]; then
					export "$SUSEPEV=1"
				fi
			done <<< "$(printf "%s\n" "${USEPEVA[@]}")"
		fi

		while read -r USEPEV; do
			if [ "${!USEPEV}" -eq 1 ]; then
				PEVCMD="${USEPEV##*_}"
				PEVCMD="${PEVCMD,,}"
				if [ -x "$(command -v "$PEVCMD")" ]; then
					PEVDSTI="$STLGPEVKD/$PEVCMD/id/$AID"
					PEVDSTT="$STLGPEVKD/$PEVCMD/title/$GN"
					
					if [ "$PEVCMD" == "$PERES" ]; then
						if [ ! -d "$PEVDSTI" ] || [ "$(find "$PEVDSTI" -type f | wc -l)" -eq 0 ]; then
							mkProjDir "$PEVDSTI"
							writelog "INFO" "${FUNCNAME[0]} - $USEPEV is enabled, extracting data from '$GP' using '$PEVCMD' to '$PEVDSTI'"
							cd "$PEVDSTI" >/dev/null || return
							notiShow "$(strFix "$NOTY_ANALYZE" "$GE" "$PEVCMD")"
							"$PEVCMD" -x "$GP" &
							cd - >/dev/null || return
						else
							writelog "SKIP" "${FUNCNAME[0]} - $USEPEV is enabled, but already have files in '$PEVDSTI'"
						fi
					else
						PEVDSTF="$PEVDSTI/$PEVCMD-$AID.txt"
						if [ ! -f "$PEVDSTF" ]; then
							mkProjDir "$PEVDSTI"
							writelog "INFO" "${FUNCNAME[0]} - $USEPEV is enabled, using command '$PEVCMD' to write data from '$GP' into '$PEVDSTF'"
							notiShow "$(strFix "$NOTY_ANALYZE" "$GE" "$PEVCMD")"
							"$PEVCMD" "$GP" > "$PEVDSTF" &
						else
							writelog "SKIP" "${FUNCNAME[0]} - $USEPEV is enabled, but already have the datafile '$PEVDSTF'"
						fi
					fi
					mkProjDir "${PEVDSTT%/*}"
					if [ ! -L "$PEVDSTT" ]; then
						ln -rs "$PEVDSTI" "$PEVDSTT"	
					fi
				else
					writelog "SKIP" "${FUNCNAME[0]} - $USEPEV is enabled, but command '$PEVCMD' could not be found"
				fi
			fi
		done <<< "$(printf "%s\n" "${USEPEVA[@]}")"
	fi
}

function checkAllPev {
	if  [ -n "$USEALLPEV" ] && [ "$USEALLPEV" -eq 1 ]; then
		writelog "INFO" "${FUNCNAME[0]} - 'USEALLPEV' is enabled, extracting data from '$GP' with all supported pev tools"
		checkPev
	fi
}

function prepareLaunch {
	rm "$CLOSETMP" 2>/dev/null
	rm "$KILLSWITCH" 2>/dev/null

	linkLog

	createProjectDirs
	fixShowGnAid
	saveCfg "$STLDEFGLOBALCFG" X
	loadCfg "$STLDEFGLOBALCFG" X
	writelog "START" "######### Game Launch: $SGNAID #########"

	getGameData "$AID"

	writelog "INFO" "${FUNCNAME[0]} - Game launch args '${ORGGCMD[*]}'"
	writelog "INFO" "${FUNCNAME[0]} - Gamedir '$GFD'"
	if [ -n "$GPFX" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Proton wineprefix '$GPFX'"
	fi
	writelog "INFO" "${FUNCNAME[0]} -------------------"
	writelog "INFO" "${FUNCNAME[0]} - CreateGameCfg:"
	createGameCfg

	writelog "INFO" "${FUNCNAME[0]} - First LoadCfg: $STLGAMECFG"
	loadCfg "$STLGAMECFG"
	
	checkPev
	
	autoBumpGE
	
	if [ "$ISGAME" -eq 2 ] && [ "$HAVEINPROTON" -eq 0 ]; then
		FIRSTGAMEUSEPROTON="$USEPROTON"
		writelog "INFO" "${FUNCNAME[0]} - Initial Proton version from the game config: '$FIRSTGAMEUSEPROTON'"
		if [ -n "$USEPROTON" ] && [ ! -f "$(getProtPathFromCSV "$USEPROTON")" ]; then
			fixProtonVersionMismatch "USEPROTON" "$STLGAMECFG"
		fi

		writelog "INFO" "${FUNCNAME[0]} - Initializing internal Proton Vars for '$FIRSTGAMEUSEPROTON' using setNewProtVars"
		setNewProtVars "$(getProtPathFromCSV "$USEPROTON")"
	fi
	
	writelog "INFO" "${FUNCNAME[0]} - OpenTrayIcon:"
	openTrayIcon X

	fixCustomMeta "$CUMETA/$AID.conf" # will be removed again later
	loadCfg "$CUMETA/$AID.conf" X
	loadCfg "$GEMETA/$AID.conf" X
	
	writelog "INFO" "${FUNCNAME[0]} - sortGameArgs:"
	sortGameArgs

	if [ -z "$1" ]; then
		writelog "INFO" "${FUNCNAME[0]} - AskSettings:"
		askSettings
	else
		MainMenu "$AID"
	fi

	writelog "INFO" "${FUNCNAME[0]} - Second LoadCfg after menus: $STLGAMECFG"
	loadCfg "$STLGAMECFG"

	if [ -n "$DXVK_SCALE" ] && [ "$DXVK_HUD" != "0" ]; then
		writelog "INFO" "${FUNCNAME[0]} - appending 'scale=$DXVK_SCALE' to the DXVK_HUD variable '$DXVK_HUD'"
		DXVK_HUD="${DXVK_HUD},scale=$DXVK_SCALE"
	fi
		
	# in case a path changed in between, call createProjectDirs again:
	createProjectDirs

	

	# autoapply configuration settings based on the steam categories the game is in:
	autoCategorySettings

	checkAllPev

	writelog "INFO" "${FUNCNAME[0]} - sortGameArgs again, in case something changed above:"
	sortGameArgs

	if [ "$ISGAME" -eq 2 ]; then
		writelog "INFO" "${FUNCNAME[0]} - symlinkSteamUser:"
		symlinkSteamUser "$USESUSYM"

		writelog "INFO" "${FUNCNAME[0]} - restoreSteamUser:"
		restoreSteamUser

		writelog "INFO" "${FUNCNAME[0]} - prepareProton:"
		prepareProton
	fi
####

	writelog "INFO" "${FUNCNAME[0]} -setLinGameVals :"
	setLinGameVals

#################

	# override tweak settings
	writelog "INFO" "${FUNCNAME[0]} - CheckTweakLaunch:"
	checkTweakLaunch

	if [ "$ISGAME" -eq 2 ]; then
		writelog "INFO" "${FUNCNAME[0]} - checkXliveless:"
		checkXliveless

		# choose either system winetricks or downloaded one
		writelog "INFO" "${FUNCNAME[0]} - chooseWinetricks:"
		chooseWinetricks
	fi

	# check dependencies - disable functions if dependency programs are missing and/or warn
	writelog "INFO" "${FUNCNAME[0]} - checkExtDeps:"
	checkExtDeps

	if [ "$ISGAME" -eq 2 ]; then
		writelog "INFO" "${FUNCNAME[0]} - setWineVars:"
		setWineVars

		# start winetricks gui if RUN_WINETRICKS is 1 or silently if WINETRICKSPAKS is not empty
		writelog "INFO" "${FUNCNAME[0]} - CheckWinetricksLaunch:"
		checkWinetricksLaunch

		# start $WINECFG if RUN_WINECFG is 1
		writelog "INFO" "${FUNCNAME[0]} - CheckWineCfgLaunch:"
		checkWineCfgLaunch

		# apply some regs if requested
		writelog "INFO" "${FUNCNAME[0]} - CustomRegs:"
		customRegs
	fi

	# minimize all open windows if TOGGLEWINDOWS is 1
	writelog "INFO" "${FUNCNAME[0]} - TogWindows:"
	togWindows windowminimize

	# Pause steamwebhelper if requested
	writelog "INFO" "${FUNCNAME[0]} - StateSteamWebHelper:"
	StateSteamWebHelper pause

	if [ "$ISGAME" -eq 2 ]; then
		# install ${RESH} if INSTALL_RESHADE is 1
		writelog "INFO" "${FUNCNAME[0]} - InstallReshade:"
		installReshade

		# install Depth3D Shader if RESHADE_DEPTH3D is 1
		writelog "INFO" "${FUNCNAME[0]} - installDepth3DReshade:"
		installDepth3DReshade

		# start game with ${RESH} if USERESHADE is 1
		writelog "INFO" "${FUNCNAME[0]} - checkReshade:"
		checkReshade

		# start game with ${RESH} if USERESHADE is 1
		writelog "INFO" "${FUNCNAME[0]} - useSpecialK:"
		useSpecialK
		
		# open Shader Menu if CHOOSESHADERS is 1
		writelog "INFO" "${FUNCNAME[0]} - ChooseShaders:"
		chooseShaders
	fi

	# use internal $MAHU config if enabled
	if [ "$MANGOHUD" -eq 1 ]; then
		writelog "INFO" "${FUNCNAME[0]} - setMangoHudCfg:"
		setMangoHudCfg
	fi

	# start $NYRNA if RUN_NYRNA is 1
	writelog "INFO" "${FUNCNAME[0]} - UseNyrnaz:"
	useNyrna

	# start $REPLAY if RUN_REPLAY is 1
	writelog "INFO" "${FUNCNAME[0]} - UseReplay:"
	useReplay

	# start game with side-by-side VR if RUNSBSVR is not 0 
	writelog "INFO" "${FUNCNAME[0]} - CheckSBSVRLaunch:"
	checkSBSVRLaunch "$NON"

	# start Vortex if USEVORTEX is 1
	if [ "$USEVORTEX" -eq 1 ]; then
		writelog "INFO" "${FUNCNAME[0]} - ${VTX^} is enabled - startVortex:"
		startVortex "ask" "$AID"
		# (for Vortex) if SELAUNCH is 0 start a preconfigured exe directly
		writelog "INFO" "${FUNCNAME[0]} - CheckVortexSELaunch with argument '$SELAUNCH':"
		checkVortexSELaunch "$SELAUNCH"
	fi

	writelog "INFO" "${FUNCNAME[0]} - checkMO2:"
	checkMO2
	
	# set other screen resolution
	writelog "INFO" "${FUNCNAME[0]} - setNewRes:"
	setNewRes
	
	# start custom user script
	writelog "INFO" "${FUNCNAME[0]} - customUserScriptStart:"
	customUserScriptStart
	
	# redirect STEAM_COMPAT_DATA_PATH on request
	writelog "INFO" "${FUNCNAME[0]} - redirectSCDP:"
	redirectSCDP

	if [ "$ISGAME" -eq 2 ]; then
		# start igcsinjector if USEIGCS is enabled
		writelog "INFO" "${FUNCNAME[0]} - checkIGCSInjector:"
		checkIGCSInjector

		# check if openvr-fsr is enabled
		writelog "INFO" "${FUNCNAME[0]} - checkOpenVRFSR:"
		checkOpenVRFSR
	fi

	# start '$FWS' if USEFWS is enabled
	writelog "INFO" "${FUNCNAME[0]} - CheckFWS:"
	checkFWS

	# start a custom program if USECUSTOMCMD is enabled
	writelog "INFO" "${FUNCNAME[0]} - CheckCustomLaunch:"
	checkCustomLaunch

	if [ "$ISGAME" -eq 2 ]; then
		# start a custom program if UUUSEPATCH or UUUSEVR is enabled
		writelog "INFO" "${FUNCNAME[0]} - checkUUUPatchLaunch:"
		checkUUUPatchLaunch
	fi

	# start strace process in the background if STRACERUN is 1
	writelog "INFO" "${FUNCNAME[0]} - CheckStraceLaunch:"
	checkStraceLaunch

	# start network monitor process in the background if USENETMON is enabled and NETMON found
	writelog "INFO" "${FUNCNAME[0]} - CheckNetMonLaunch:"
	checkNetMonLaunch

	# start gameconqueror when game starts if RUN_GAMCON is -ge 1
	writelog "INFO" "${FUNCNAME[0]} - checkGamConLaunch:"
	checkGamConLaunch

	if [ "$ISGAME" -eq 2 ]; then
		# start CheatEngine when game starts if RUN_CHEATENGINE is -ge 1
		writelog "INFO" "${FUNCNAME[0]} - checkCheatEngineLaunch:"
		checkCheatEngineLaunch
	fi

	# set pulse latency if CHANGE_PULSE_LATENCY is 1
	writelog "INFO" "${FUNCNAME[0]} - checkPulse:"
	checkPulse

	# create/remove steam_appid.txt
	writelog "INFO" "${FUNCNAME[0]} - checkSteamAppIDFile:"
	checkSteamAppIDFile

	# Automatic Grid Update Check before_game
	if [ "$SGDBAUTODL" == "before_game" ] && [ "$STLPLAY" -eq 0 ]; then
		writelog "INFO" "${FUNCNAME[0]} - Automatic Grid Update Check '$SGDBAUTODL'"
		getGrids "$AID" &
	fi

	if [ "$ISGAME" -eq 2 ]; then
		# Create GameTitle Symlink in STLCOMPDAT if enabled
		writelog "INFO" "${FUNCNAME[0]} - setCompatDataTitle:"
		setCompatDataTitle
	fi

	# GAME START
	writelog "INFO" "${FUNCNAME[0]} -launchSteamGame:"
	launchSteamGame

	# GAME ENDED - Closing:
	writelog "STOP" "######### CLEANUP #########"
	closeSTL "######### DONE - $PROGNAME $PROGVERS #########"
}

function switchProton {
	writelog "INFO" "${FUNCNAME[0]} - Switching used Proton and its Variables to version '$1'"

	if [ ! -f "$(getProtPathFromCSV "$1")" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Tried to switch to Proton '$1', but it is not available"
		if [ "$AUTOPULLPROTON" -eq 1 ]; then
			writelog "INFO" "${FUNCNAME[0]} - AUTOPULLPROTON is enabled, so trying to download and enable '$1'"
			createDLProtList
			DLURL="$(printf "%s\n" "${ProtonDLList[@]}" | grep -m1 "$1")"
			if [ -n "$DLURL" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Download for requested '$1' found: '$DLURL'"
				StatusWindow "$GUI_DLCUSTPROT" "dlCustomProton ${DLURL//|/\"}" "DownloadCustomProtonStatus"
			else
				writelog "SKIP" "${FUNCNAME[0]} - No download URL found for requested '$1' - skipping"
			fi
		else
			writelog "SKIP" "${FUNCNAME[0]} - AUTOPULLPROTON is disabled, so giving up switching to proton version '$1'"
		fi
	else
		writelog "INFO" "${FUNCNAME[0]} - Requested Proton version '$1' found under '$(getProtPathFromCSV "$1")'"
	fi

	if [ -f "$(getProtPathFromCSV "$1")" ]; then
		USEPROTON="$1"
		setNewProtVars "$(getProtPathFromCSV "$USEPROTON")"
	fi
}

function prepareProtonDBRating {
	if [ "$USEPDBRATING" ] && [ "$STLPLAY" -eq 0 ]; then
		PDBRAINFO="$STLSHM/PTB-${AID}.txt"
		PDBRASINF="${PDBRAINFO//-/short-}"

		if [ ! -f "$PDBRAINFO" ];then
			mapfile -d ";" -t -O "${#PDBARR[@]}" PDBARR <<< "$(getProtonDBRating "$AID")"
			PDBCONFI="${PDBARR[0]}"
			PDBSCORE="${PDBARR[1]}"
			PDBTOTAL="${PDBARR[2]}"
			PDBTREND="${PDBARR[3]}"
			PDBBESTT="${PDBARR[4]}"
			printf 'ProtonDB Rating Trend: %s' "${PDBTREND}" > "$PDBRASINF"
			printf '%s\nConfidence: %s\nScore: %s\nTotal Votes: %s\nRating Trend: %s\nBest Rating: %s\n' "$GUI_USEPDBRATING" "${PDBCONFI}" "${PDBSCORE}" "${PDBTOTAL}" "${PDBTREND}" "${PDBBESTT}" > "$PDBRAINFO"
		fi
	fi
}

function getProtonDBRating {
	if [ -n "$1" ]; then
		AID="$1"
	fi

	PDBAPI="https://www.protondb.com/api/v1/reports/summaries/XXX.json"

	if [ ! -x "$(command -v "$JQ")" ]; then
		writelog "WARN" "${FUNCNAME[0]} - Can't get data from '${PDBAPI//XXX/$AID}' because '$JQ' is not installed"
	else
		DMIN=1440

		if [ -n "$PDBRATINGCACHE" ] && [ "$PDBRATINGCACHE" -ge 1 ]; then
			PDBDLDIR="$STLDLDIR/proton/rating"
			mkProjDir "$PDBDLDIR"
			PDBAJ="$PDBDLDIR/${AID}.json"
			if [ ! -f "$PDBAJ" ] || test "$(find "$PDBAJ" -mmin +"$(( DMIN * PDBRATINGCACHE ))")"; then
				rm "$PDBAJ" 2>/dev/null
				dlCheck "${PDBAPI//XXX/$AID}" "$PDBAJ" "X" "$NON"
			fi

			if [ -f "$PDBAJ" ]; then
				"$JQ" -r '. | "\(.confidence);\(.score);\(.total);\(.trendingTier);\(.bestReportedTier)"' "$PDBAJ"
			fi
		else
			"$WGET" -q "${PDBAPI//XXX/$AID}" -O - 2> >(grep -v "SSL_INIT") | "$JQ" -r '. | "\(.confidence);\(.score);\(.total);\(.trendingTier);\(.bestReportedTier)"'
		fi
	fi
}

function fixProtonVersionMismatch {
	if [ "$ISGAME" -eq 2 ]; then

		# WIP (incomplete; FIXRUN is never created currently) idea for fixing a possible but rare loop, but no logs in #406 # TODO maybe remove later	#XXXXXXXXXXXXXXXXXXX
		
		FIXRUN="$STLSHM/${FUNCNAME[0]}-${AID}.txt"
		
		if [ -f "$FIXRUN" ]; then
			writelog "INFO" "${FUNCNAME[0]} - A search for a minor version bump was already running previously - recreating list of available Proton versions to restart from scratch"
			rm "$FIXRUN"
			rm "$PROTONCSV"
			createProtonList X
		fi

		ORGPROTCAT="$1"
		MIMAPROT="${!1}"

		if [[ "$MIMAPROT" =~ "experimental" ]]; then
			writelog "INFO" "${FUNCNAME[0]} - Skipping function for 'experimental' Proton version"
		elif [[ "$MIMAPROT" =~ "proton-unknown" ]]; then
			writelog "INFO" "${FUNCNAME[0]} - Skipping function for 'proton-unknown' Proton version"
		else
			writelog "INFO" "${FUNCNAME[0]} - Incoming category is '$ORGPROTCAT' with value '$MIMAPROT'"
			writelog "INFO" "${FUNCNAME[0]} - Looking for an alternative similar version for '$MIMAPROT'"

			notiShow "$(strFix "$NOTY_WANTPROTON3" "$MIMAPROT")"

			if [ ! -f "$PROTONCSV" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Looking for available Proton versions"
				getAvailableProtonVersions "up"
			fi

			MIMAPROTSHORT="^${MIMAPROT%-*}"
			NEWMINORPROT="$(grep "$MIMAPROTSHORT" "$PROTONCSV" | cut -d ';' -f1 | sort -nr | head -n1)"

			if [ -f "$(getProtPathFromCSV "${NEWMINORPROT//\"/}")" ] && [ -n "${NEWMINORPROT//\"/}" ]; then
				NEWMINORRUN="$(getProtPathFromCSV "${NEWMINORPROT//\"/}")"
				writelog "INFO" "${FUNCNAME[0]} - Found Proton '$NEWMINORPROT' in path '$NEWMINORRUN' as an alternative for the requested '$MIMAPROT'"
			elif grep -q "GE" <<< "$MIMAPROT"; then
				writelog "INFO" "${FUNCNAME[0]} - No alternative for '$MIMAPROT' found directly"
				NEWMINORPROT="$(grep "GE" "$PROTONCSV" | cut -d ';' -f1 | sort -nr | head -n1)"
				if [ -f "$(getProtPathFromCSV "${NEWMINORPROT//\"/}")" ]; then
					NEWMINORRUN="$(getProtPathFromCSV "${NEWMINORPROT//\"/}")"
					writelog "INFO" "${FUNCNAME[0]} - Using found '$NEWMINORPROT' instead, as it is at least also a GE Proton like the requested '$MIMAPROT'"
				fi
			fi

			if [ -n "$3" ]; then
				if [ -f "$NEWMINORRUN" ]; then
					writelog "INFO" "${FUNCNAME[0]} - found '$NEWMINORRUN'"
					echo "$NEWMINORRUN"
				fi
			else
				if [ -f "$NEWMINORRUN" ]; then
					switchProton "$NEWMINORPROT"
					notiShow "$(strFix "$NOTY_WANTPROTON2" "$NEWMINORPROT" "$MIMAPROT")"
				elif [ "$AUTOLASTPROTON" -eq 1 ]; then
					writelog "INFO" "${FUNCNAME[0]} - Automatically selecting newest official one"
					setNOP
				else
					writelog "INFO" "${FUNCNAME[0]} - Asking for one"
					needNewProton
				fi
			fi

			if [ ! -f "$(getProtPathFromCSV "$MIMAPROT")" ] && [ "$ORGPROTCAT" == "USEPROTON" ] && [ "$MIMAPROT" != "$NEWMINORPROT" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Automatically updating USEPROTON to '$USEPROTON' in '$2'"
				touch "$FUPDATE"
				updateConfigEntry "USEPROTON" "$USEPROTON" "$2"
				setInternalProtonVars
			fi
		fi
	fi
}

function dlConty {
	function upChkConty {
		DLCHK="sha256sum"

		notiShow "$(strFix "$NOTY_DLCONTY" "$CONTYRELURL/$CONTYDLVERS")" "S"
		dlCheck "$CONTYRELURL/$CONTYDLVERS" "$CONTYDLDIR/$CONTY" "$DLCHK" "Downloading '$CONTYRELURL/$CONTYDLVERS' to '$CONTYDLDIR'" "$INCHK"
		notiShow "$GUI_DONE" "S"		
	}

	mkProjDir "$CONTYDLDIR"
	CONTYDLVERS="$("$WGET" -q "$CONTYRELURL" -O - 2> >(grep -v "SSL_INIT") | grep -m1 "download.*.$CONTY" | grep -oP 'releases\K[^"]+')"
	CONTYVERS="${CONTYDLVERS%/*}"
	CONTYVERS="${CONTYVERS##*/}"
	
	INCHK="$("$WGET" -q "${CONTYRELURL}/tag/${CONTYVERS}" -O - 2> >(grep -v "SSL_INIT")| grep "SHA256" -A10 | grep -m1 "${CONTY}" | cut -d ' ' -f1)"
		
	if [ -f "$CONTYDLDIR/$CONTY" ]; then
		if [ "$UPDATECONTY" -eq 1 ]; then
			if [ -f "$CONTYDLDIR/version.txt" ]; then
				DLVERS="$(cat "$CONTYDLDIR/version.txt")"
			else
				DLVERS="0.0"
			fi

			if [ "$DLVERS" == "$CONTYVERS" ]; then
				writelog "SKIP" "${FUNCNAME[0]} - Skipping downloading Conty - existing version is identical to the latest upstream version '$CONTYVERS'"
			else
				writelog "INFO" "${FUNCNAME[0]} - Updating the available Conty version '$DLVERS' with the newer version '$CONTYVERS'"
				upChkConty
			fi
		else
			writelog "SKIP" "${FUNCNAME[0]} - Skipping downloading Conty - already have one, and update is disabled"
		fi
	else
		upChkConty
	fi

	if [ -f "$CONTYDLDIR/$CONTY" ]; then
		DLSHA="$(sha256sum "$CONTYDLDIR/$CONTY" | cut -d ' ' -f1)"
		writelog "INFO" "${FUNCNAME[0]} - : Downloaded $CONTY has sha256sum '$DLSHA' and should have '$INCHK'"

		if [ "$INCHK" == "$DLSHA" ]; then
			writelog "INFO" "${FUNCNAME[0]} - : $(strFix "$NOTY_CHECKSUM_OK" "$DLSHA")"
			notiShow "$(strFix "$NOTY_CHECKSUM_OK" "$DLSHA")" "S"
			chmod +x "$CONTYDLDIR/$CONTY"
			export RUNCONTY="$CONTYDLDIR/$CONTY"
			if grep -q "[0-9]" <<< "$CONTYVERS"; then
				writelog "INFO" "${FUNCNAME[0]} - Updating Conty version to '$CONTYVERS' in '$CONTYDLDIR/version.txt'"
				echo "$CONTYVERS" > "$CONTYDLDIR/version.txt"
			else
				writelog "SKIP" "${FUNCNAME[0]} - No version found in Url - not writing '$CONTYDLDIR/version.txt'"
			fi
		else
			writelog "ERROR" "${FUNCNAME[0]} - $(strFix "$NOTY_CHECKSUM_NOK" "$DLSHA") - removing the download"
			notiShow "$(strFix "$NOTY_CHECKSUM_NOK" "$DLSHA")" "S"
			rm "$CONTYDLDIR/$CONTY"
		fi
	fi
}

function updateConty {
	if [ "$UPDATECONTY" -eq 1 ]; then
		if [ ! -f "$CONTYDLDIR/version.txt" ]; then
			writelog "INFO" "${FUNCNAME[0]} - No Conty version file found in - so simply downloading latest release"
			StatusWindow "$(strFix "$NOTY_DLCUSTOMPROTON" "${CONTY%%.*}")" "dlConty" "DownloadContyStatus"
		else
			CONTYDLVERS="$("$WGET" -q "$CONTYRELURL" -O - 2> >(grep -v "SSL_INIT") | grep -m1 "download.*.$CONTY" | grep -oP 'releases\K[^"]+')"
			CONTYVERS="${CONTYDLVERS%/*}"
			CONTYVERS="${CONTYVERS##*/}"
			if [ -f "$CONTYDLDIR/version.txt" ]; then
				DLVERS="$(cat "$CONTYDLDIR/version.txt")"
			else
				DLVERS="0.0"
			fi
			writelog "INFO" "${FUNCNAME[0]} - $(strFix "$NOTY_UPDATECONTY" "$CONTYVERS" "$DLVERS")"
			notiShow "$(strFix "$NOTY_UPDATECONTY" "$CONTYVERS" "$DLVERS")"
			StatusWindow "$(strFix "$NOTY_DLCUSTOMPROTON" "${CONTY%%.*}")" "dlConty" "DownloadContyStatus"
		fi
	fi
}

function askConty {
		writelog "INFO" "${FUNCNAME[0]} - Opening Ask Conty Requester"
		fixShowGnAid
		export CURWIKI="$PPW/Conty"
		TITLE="${PROGNAME}-SelectConty"
		pollWinRes "$TITLE"

		setShowPic

		"$YAD" --f1-action="$F1ACTION" --image "$SHOWPIC" --image-on-top --window-icon="$STLICON" --form --center --on-top "$WINDECO" \
		--title="$TITLE" \
		--text="$(spanFont "$SGNAID - $GUI_ASKCONTY" "H")" \
		--button="$BUT_DLCONTY":0 \
		--button="$BUT_SELCONTY":2 \
		--button="$SKIPCONTY":4 \
		"$GEOM"

		case $? in
			0)  {
					writelog "INFO" "${FUNCNAME[0]} - Selected to download Conty"
					StatusWindow "$(strFix "$NOTY_DLCUSTOMPROTON" "${CONTY%%.*}")" "dlConty" "DownloadContyStatus"
				}
			;;
			2)  {
					writelog "INFO" "${FUNCNAME[0]} - Selected to pick local Conty executable"
					PICKCONT="$("$YAD" --file)"

					if [ -f "$PICKCONT" ]; then
						writelog "INFO" "${FUNCNAME[0]} - Picked '$PICKCONT' as Conty executable"
						export RUNCONTY="$PICKCONT"
						touch "$FUPDATE"
						updateConfigEntry "CUSTCONTY" "$PICKCONT" "$STLDEFGLOBALCFG"
						CUSTCONTY="$PICKCONT"
					else
						writelog "SKIP" "${FUNCNAME[0]} - No Conty executable selected - skipping"
						export RUNCONTY="$NON"
					fi
				}
			;;
			4)  {
					writelog "SKIP" "${FUNCNAME[0]} - Selected CANCEL - Not using Conty"
					export RUNCONTY="$NON"
				}
			;;
		esac
}

function findConty {
	if [ -n "$CUSTCONTY" ] && [ "$CUSTCONTY" != "$NON" ] && [ -x "$CUSTCONTY" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Using custom Conty '$CUSTCONTY'"
		export RUNCONTY="$CUSTCONTY"
	elif [ -x "$CONTYDLDIR/$CONTY" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Using downloaded Conty '$CONTYDLDIR/$CONTY'"
		updateConty
		export RUNCONTY="$CONTYDLDIR/$CONTY"
	elif [ -x "$(command -v "$CONTY")" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Using Conty in 'PATH' '$("$WHICH" "$CONTY")'"
		RUNCONTY="$(command -v "$CONTY")"
		export RUNCONTY
	else
		writelog "INFO" "${FUNCNAME[0]} - No Conty found - Opening requester"
		askConty
		if [ "$RUNCONTY" != "$NON" ]; then
			"${FUNCNAME[0]}"
		fi
	fi
}

function checkConty {
	if [ "$AUTOCONTY" -eq 1 ]; then
		if [ "$(getArch "$GP")" == "32" ]; then
			CONTYMODE=1
		else
			CONTYMODE=0
		fi
	elif [ "$USECONTY" -eq 1 ]; then
		CONTYMODE=2
	else
		CONTYMODE=0
	fi
	
	if [ "$CONTYMODE" -ge 1 ]; then
		findConty
			
		if [ -x "$RUNCONTY" ] && [ "$RUNCONTY" != "$NON" ]; then
			if [ "$CONTYMODE" -eq 1 ]; then
				writelog "INFO" "${FUNCNAME[0]} - '$GP' is 32bit - Starting it using Conty executable '$RUNCONTY'"
			else
				writelog "INFO" "${FUNCNAME[0]} - Starting '$GP' using Conty executable '$RUNCONTY', because 'USECONTY' is enabled"
			fi
		else
			writelog "SKIP" "${FUNCNAME[0]} - No Conty executable found 'RUNCONTY' is '$RUNCONTY' - continuing regularly"
			CONTYMODE=0
		fi
	fi
}

function logPlayTime {
	if [ "$LOGPLAYTIME" -eq 1 ] && [ -n "$GN" ] ; then
		mkProjDir "$PLAYTIMELOGDIR"
		# different date formats?
		echo "$(date +%d.%m.%Y): $1 sec" >> "$PLAYTIMELOGDIR/${GN}.log"
	fi
}

function setHuyList {
	HUTXT="helpurls.txt"

	HELPURLLIST="$GLOBALMISCDIR/$HUTXT"
	
	if [ -f "$STLCFGDIR/$HUTXT" ]; then
		HELPURLLIST="$STLCFGDIR/$HUTXT"
	fi

	DHU="defhelpurl"
	
	if [ -z "$HELPURL" ] || [ "$HELPURL" == "$NON" ]; then 
		HELPURL="$(grep "$DHU" "$HELPURLLIST" | cut -d ';' -f2)"
	fi
	HUYLIST="$(while read -r line; do cut -d ';' -f1 <<<"$line"; done <<< "$(grep -v "$DHU" "$HELPURLLIST")" | tr '\n' '!')"
	
	loadCfg "$GEMETA/$AID.conf" X
	 
	if [ -n "$METACRITIC_FULLURL" ]; then
		HUYLIST="${HUYLIST}metacritic!"
	fi 

	if [ -n "$GAMEMANUALURL" ]; then
		HUYLIST="${HUYLIST}gamemanual!"
	fi 
	
	export HUYLIST
}

function checkHelpUrl {
	WANTHELPURL="$1"
	if [ -n "$WANTHELPURL" ] && [ "$WANTHELPURL" != "$NON" ] && [ ! -f "$STLSHM/KillBrowser-$AID.txt" ]; then

		if [ "$WANTHELPURL" == "metacritic" ]; then
			HELPURL="$METACRITIC_FULLURL"
		elif [ "$WANTHELPURL" == "gamemanual" ]; then
			HELPURL="$GAMEMANUALURL"
		else
			HELPURL="$(grep "$WANTHELPURL" "$HELPURLLIST" | grep -v "$DHU" | cut -d ';' -f2)"
			writelog "INFO" "${FUNCNAME[0]} - Searching Help Url for '$WANTHELPURL' with command: 'grep \"$WANTHELPURL\" \"$HELPURLLIST\" | grep -v \"$DHU\" | cut -d ';' -f2'"
		fi

		if [ -n "$HELPURL" ]; then
			HELPURLNQ="${HELPURL//\"}"
			writelog "INFO" "${FUNCNAME[0]} - Selected to open '${HELPURLNQ//AID/$AID}' with '$BROWSER'"
			if ! "$PGREP" -f "$BROWSER" >/dev/null; then
				touch "$STLSHM/KillBrowser-$AID.txt"
			fi
		
			"$BROWSER" "${HELPURLNQ//AID/$AID}" 2>/dev/null & 
		fi
	fi
}

function HelpUrlMenu {
	if [ -n "$1" ]; then
		AID="$1"
		setAIDCfgs
	fi
	fixShowGnAid
	export CURWIKI="$PPW/Help-Url"
	TITLE="${PROGNAME}-${FUNCNAME[0]}"
	pollWinRes "$TITLE"
	setShowPic
	setHuyList

	WANTHELPURL="$("$YAD" --f1-action="$F1ACTION" --image "$SHOWPIC" --image-on-top --window-icon="$STLICON" --form --center --on-top "$WINDECO" \
	--title="$TITLE" --separator="\n" \
	--text="$(spanFont "$SGNAID $(strFix "$GUI_ASKOPURL" "$1")" "H")" \
	--field="$GUI_HELPURL!$DESC_HELPURL ":CB "$(cleanDropDown "${HELPURL}" "${HUYLIST}${NON}")" \
	--button="$BUT_CAN":0 \
	--button="$BUT_OPURL":2 \
	"$GEOM"	)"

	case $? in
		0)  {
				checkHelpUrl "$WANTHELPURL"
				writelog "INFO" "${FUNCNAME[0]} - Selected '$BUT_CAN' - Leaving"
			}
		;;
		2)  {
				writelog "INFO" "${FUNCNAME[0]} - Selected '$BUT_OPURL' - Opening '$WANTHELPURL' in browser"
				checkHelpUrl "$WANTHELPURL"
			}
		;;
	esac
}

function checkPlayTime {
	WASSTESTA="$STLSHM/SteamStart_${AID}.txt"
	if [ ! -f "$WASSTESTA" ]; then
		writelog "INFO" "${FUNCNAME[0]} - The game was not started via '$PROGCMD' but directly from Steam - skipping Crash Requester"
	elif [ -z "$1" ]; then
		writelog "INFO" "${FUNCNAME[0]} - The game was not even started"
	else
		if [ -n "$CRASHGUESS" ] && [ "$1" -lt "$CRASHGUESS" ]; then
			writelog "INFO" "${FUNCNAME[0]} - The game stopped after '$1' seconds - opening CrashGuess Requester"
			fixShowGnAid
			export CURWIKI="$PPW/Crash-Guess"
			TITLE="${PROGNAME}-CrashGuess"
			pollWinRes "$TITLE"

			setShowPic

			setHuyList

			WANTHELPURL="$("$YAD" --f1-action="$F1ACTION" --image "$SHOWPIC" --image-on-top --window-icon="$STLICON" --form --center --on-top "$WINDECO" \
			--title="$TITLE" --separator="\n" \
			--text="$(spanFont "$SGNAID $(strFix "$GUI_ASKCRASHGUESS" "$1")" "H")" \
			--field="$GUI_HELPURL!$DESC_HELPURL ":CB "$(cleanDropDown "${HELPURL}" "${HUYLIST}${NON}")" \
			--button="$BUT_RETRYCG":0 \
			--button="$BUT_SKIPCG":2 \
			--button="$BUT_NO":4 \
			"$GEOM"	)"

			case $? in
				0)  {
						checkHelpUrl "$WANTHELPURL"
						writelog "INFO" "${FUNCNAME[0]} - Selected '$BUT_RETRYCG' so opening settings"
						duration=0
						SECONDS=0
						prepareLaunch X
					}
				;;
				2)  {
						writelog "INFO" "${FUNCNAME[0]} - Selected '$BUT_SKIPCG' - Setting CRASHGUESS to 0 for $SGNAID"
						updateConfigEntry "CRASHGUESS" "0" "$STLGAMECFG"
					}
				;;
				4)  {
						writelog "SKIP" "${FUNCNAME[0]} - Selected '$BUT_NO' - Exiting regularly"
					}
				;;
			esac
		else
			writelog "INFO" "${FUNCNAME[0]} - Playtime '$1' was longer than CRASHGUESS '$CRASHGUESS', not opening the requester"
		fi
	fi
	rm "$WASSTESTA" 2>/dev/null
}

function fixSymlinks {
	if [ "$FIXSYMLINKS" -eq 1 ]; then
		if [ ! -f "$RUNPROTON" ]; then
			writelog "SKIP" "${FUNCNAME[0]} - Fixing Symlinks is enabled, but RUNPROTON '$RUNPROTON' does not exist"
		else
			LRUNPROTDIR="${RUNPROTON%/*}"
			ORUNPROTDIR="$(readlink -f "$LRUNPROTDIR")"
			writelog "INFO" "${FUNCNAME[0]} - Starting Symlink Fix as requested"

			# the loop needs >1 second even without updating any symlinks and might need much longer with many syminks to be recreated
			# maybe worth to create a parsable checkfile to skip it on the next run?
			while read -r fixme; do
				SYML="$(awk -F ';' '{print $1}' <<< "$fixme")"
				OFIL="$(awk -F ';' '{print $2}' <<< "$fixme")"

				# make sure the found result is correct
				if [ "$(readlink -f "${SYML//\"}")" == "$(readlink -f "${OFIL//\"}")" ]; then
					OFIA="${OFIL//\"}"
					OFIB="${OFIA##*/files/}"
					OFIC="${OFIB//\/x86_64-windows}"
					OFID="${OFIC//\/i386-windows}"
					OOUT="${OFID##*/dist/}"
					
					if [ -n "$OOUT" ] && [ "$OOUT" != "" ]; then
						if [ -d "$LRUNPROTDIR/files" ]; then
							NFIL="$LRUNPROTDIR/files/$OOUT"
						elif [ -d "$LRUNPROTDIR/dist" ]; then
							NFIL="$LRUNPROTDIR/dist/$OOUT"
						else
							writelog "SKIP" "${FUNCNAME[0]} - No 'files' or 'dist' dir found in '$LRUNPROTDIR'"
						fi

						unset NEWFILE
						if [ -f "$NFIL" ]; then
							NEWFILE="$NFIL"
						elif [ -f "${NFIL//lib64\/wine/lib64\/wine\/x86_64-windows}" ]; then
							NEWFILE="${NFIL//lib64\/wine/lib64\/wine\/x86_64-windows}"
						elif [ -f "${NFIL//lib\/wine/lib\/wine\/i386-windows}" ]; then
							NEWFILE="${NFIL//lib\/wine/lib\/wine\/i386-windows}"
						else
							writelog "SKIP" "${FUNCNAME[0]} - No equivalent file found for '$OOUT' in '$LRUNPROTDIR'" # collect in generic nofile/${PROTONVERSION}.txt file to skip early?
						fi

						if [ -f "$NEWFILE" ]; then
							writelog "INFO" "${FUNCNAME[0]} - Symlink '${SYML//\"}' points to '${OFIL//\"}', but '$NEWFILE' would be correct - fixing:"
							rm "${SYML//\"}"
							writelog "INFO" "${FUNCNAME[0]} - 'ln -s \"$NEWFILE\" \"${SYML//\"}\"'"
							ln -s "$NEWFILE" "${SYML//\"}"
						fi
					fi
				else
					writelog "SKIP" "${FUNCNAME[0]} - '${SYML//\"}' does not point to '${OFIL//\"}' but to '$(readlink -f "${SYML//\"}")' - Skipping"
				fi
			done <<< "$(find "${GPFX}/${DRC}" -type l -exec echo \"{}\" \; -exec readlink -v {} \; | grep -v "$LRUNPROTDIR\|$ORUNPROTDIR\|$STUS" | grep -iB1 "Proton" | grep -v "^\-\-" | sed 'N;s/\n/;\"/' | sed 's/$/\"/')"
			writelog "INFO" "${FUNCNAME[0]} - Stop Symlink Fix"
		fi
	else
		writelog "SKIP" "${FUNCNAME[0]} - Fixing Symlinks is not enabled"
	fi
}

function unSymlink {
	if [ "$UNSYMLINK" -eq 1 ]; then
			LRUNPROTDIR="${RUNPROTON%/*}"
			ORUNPROTDIR="$(readlink -f "$LRUNPROTDIR")"
			writelog "INFO" "${FUNCNAME[0]} - Starting unsymlinking as requested - might needs some time, depending on the symlink count"

			while read -r unsym; do
				SYML="$(awk -F ';' '{print $1}' <<< "$unsym")"
				OFIL="$(awk -F ';' '{print $2}' <<< "$unsym")"
				mv "${SYML//\"}" "${SYML//\"}_OLD"
				cp "${OFIL//\"}" "${SYML//\"}"
				if [ -f "${SYML//\"}" ]; then
					rm "${SYML//\"}_OLD"
				else
					writelog "SKIP" "${FUNCNAME[0]} - Copying to '${SYML//\"}' failed - reverting symlink"
					mv "${SYML//\"}_OLD" "${SYML//\"}"
				fi
			done <<< "$(find "${GPFX}/${DRC}" -type l -exec echo \"{}\" \; -exec readlink -v {} \; | grep -iB1 "Proton" | grep -v "^\-\-" | sed 'N;s/\n/;\"/' | sed 's/$/\"/')"
			writelog "INFO" "${FUNCNAME[0]} - Stop Unsymlinking"
	else
		writelog "SKIP" "${FUNCNAME[0]} - Unsymlinking is not enabled"
	fi
}

function delPrefix {
	if [ "$DELPFX" -eq 1 ]; then
		if [ -d "$STEAM_COMPAT_DATA_PATH" ] ; then
			writelog "INFO" "${FUNCNAME[0]} - Removing the prefix was enabled - Creating a backup of steamuser before"
			BACKUPSTEAMUSER=1
			backupSteamUser "$AID"

			writelog "INFO" "${FUNCNAME[0]} - Removing the prefix '$GPFX' as requested"
			notiShow "$(strFix "$NOTY_DELPFX" "$GPFX")"
			rm -rf "$STEAM_COMPAT_DATA_PATH" 2>/dev/null
			mkProjDir "$STEAM_COMPAT_DATA_PATH"
		fi
	fi
}

function createOrUpdateSymDir {
	SYML="$1"
	ODIR="$2"
	if [ -d "$SYML" ] && [ ! -L "$SYML" ] ; then
		writelog "WARN" "${FUNCNAME[0]} - Renaming existing '$SYML' to '${SYML}_old'"
		mv "$SYML" "${SYML}_old"
	fi
	
	if [ -L "$SYML" ] && [ "$(readlink "$SYML")" != "$ODIR" ]; then
		writelog "WARN" "${FUNCNAME[0]} - Renaming existing symlink '$SYML' to '${SYML}_old'"
		writelog "WARN" "${FUNCNAME[0]} - because it points to '$(readlink "$SYML")'"
		mv "$SYML" "${SYML}_old"
	fi

	if [ ! -L "$SYML" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Created symlink from '$ODIR' to '$SYML'"
		ln -s "$ODIR" "$SYML"
	fi
}

function gameFix {
	if [ "$AID" -eq 223220 ] || [ "$AID" -eq 246960 ]; then
		writelog "WARN" "${FUNCNAME[0]} - got '$AID' as STEAM_COMPAT_APP_ID - need to change pwd from '$PWD' to '$STEAM_COMPAT_INSTALL_PATH'"
		cd "${STEAM_COMPAT_INSTALL_PATH}/launcher" || return
	fi
}

function startGame {
	
	function setBaseMO2RunCmd {
		unset RUNCMD
		while read -r arg; do
			mapfile -t -O "${#RUNCMD[@]}" RUNCMD <<< "$arg"
			if [ "$arg" == "$WFEAR" ]; then
				break
			fi
		done <<< "$(printf "%s\n" "$@")"
		# done <<< "$(printf "%s\n" "${#RUNCMD[@]}")"
	}
	
	#kind of works, but should be optimized:
#	emptyVars "S" # unset some internal variables before the game starts

	loadCfg "$GEMETA/$AID.conf"

	if [ "$STLPLAY" -eq 0 ]; then
		writelog "INFO" "${FUNCNAME[0]} - Getting the Game Window name:"
		getGameWindowName &
	fi
	touch "$PIDLOCK"
	startSBSVR &

	gameFix

	checkConty

	if [ "$BLOCKINTERNET" -eq 1 ]; then
		writelog "INFO" "${FUNCNAME[0]} - Starting game with blocked internet access"
		BLOCKCMD="unshare"
		BLOCKARGS="-n -r"
		unset BLOCKARGSARR
		mapfile -d " " -t -O "${#BLOCKARGSARR[@]}" BLOCKARGSARR < <(printf '%s' "$BLOCKARGS")
		RUNCMD=("$BLOCKCMD" "${BLOCKARGSARR[@]}" "${@}")
	else
		RUNCMD=("${@}")
	fi

	if [ "$ISGAME" -eq 2 ] && [ "$USEWINE" -ne 1 ]; then
		if [ "$MO2MODE" != "disabled" ]; then
			writelog "INFO" "${FUNCNAME[0]} - MO2MODE is '$MO2MODE' - preparing MO2 symlinks in '$GPFX'"

			GAMMO2DAT="$GPFX/$DRCU/$STUS/$ADLO/$MO"
			ORGMO2DAT="$MO2PFX/$DRCU/$STUS/$ADLO/$MO"
			createOrUpdateSymDir "$GAMMO2DAT" "$ORGMO2DAT"

			OMODDIR="$MO2PFX/$MORDIR"
			GMODDIR="$GPFX/$MORDIR"
			createOrUpdateSymDir "$GMODDIR" "$OMODDIR"
			setBaseMO2RunCmd "$@"
			GMO2EXE="$GPFX/$MOERPATH"
		fi

# silent mode doesn't work, feel free to create a PR
		if [ "$MO2MODE" == "silent" ]; then
MO2MODE="gui"
function disabledWIPSilentMode {
			if [ -n "$MO2GAM" ] && [ -f "$MO2EXE" ]; then
				if [ "$(grep -c "^+" "$MODLIST")" -eq 0 ]; then
					writelog "SKIP" "${FUNCNAME[0]} - Not starting $MO silent as requested, because no mod is enabled in '$MODLIST'"
					notiShow "$(strFix "$NOTY_NOMO" "$GN" "$AID")"
					MO2MODE="gui"
				else
					# both seem to work:
#					ZEXE="Z:${3//\//\\\\}"
#					ZEXE="$(grep "^1\\\binary" "$MOININI" | tr -d "\015" | cut -d '=' -f2)"
#					sed "/^MainWindow_modList_state/d" -i "$MOININI"
#					sed "/^MainWindow_downloadView_state/d" -i "$MOININI"
#					sed "/^MainWindow_geometry/d" -i "$MOININI"

					RUNCMD=("${RUNCMD[@]}" "$GMO2EXE" "moshortcut://$MO2GAM:$MO2GAMINI" "-p" "Default")
#					RUNCMD=("$1" "$2" "$GMO2EXE" "$ZEXE" "-i" "$MO2GAM")
#					RUNCMD=("$1" "$2" "$GMO2EXE" "-i" "$MO2GAM")

					writelog "INFO" "${FUNCNAME[0]} - Starting '$SGNAID' with $MO enabled mods with command '${RUNCMD[*]}'"
					notiShow "$(strFix "$NOTY_STARTSIMO" "$GN" "$AID")"
				fi
			else
				writelog "SKIP" "${FUNCNAME[0]} - Not starting $MO silent as requested, because MO2GAM ('$MO2GAM') or MO2EXE ('$MO2EXE') is empty"
				MO2MODE="gui"
			fi
}
		fi
		if [ "$MO2MODE" == "gui" ]; then
			if [ -n "$MO2GAM" ]; then
				RUNCMD=("${RUNCMD[@]}" "$MO2EXE" "-i" "$MO2GAM")
				writelog "INFO" "${FUNCNAME[0]} - Starting '$SGNAID' with $MO gui via '${RUNCMD[*]}'"
				notiShow "$(strFix "$NOTY_STARTVEMO" "$GN" "$AID")"
			else
				RUNCMD=("${RUNCMD[@]}" "$MO2EXE")
				writelog "INFO" "${FUNCNAME[0]} - Starting '$SGNAID' with $MO gui via '${RUNCMD[*]}'"
				notiShow "$(strFix "$NOTY_STARTVEMO" "$GN" "$AID")"
			fi
		
			MONGURL="$(grep -i "\"$MO2GAM\"" "$MO2GAMES" | head -n1 | cut -d ';' -f4)"
			MONGURL="${MONGURL//\"}"
			MODLER="$STLSHM/dlNexMod-$MONGURL"
			head -n1 "$0" > "$MODLER"
			{
			echo "cd \"${GMO2EXE%/*}\" >/dev/null || return"
			echo "STEAM_COMPAT_CLIENT_INSTALL_PATH=\"$STEAM_COMPAT_CLIENT_INSTALL_PATH\" STEAM_COMPAT_DATA_PATH=\"$STEAM_COMPAT_DATA_PATH\" \"$RUNPROTON\" \"run\" \"${MO}.exe\" -i \"${MO2GAM//\"}\" \"\$1\""
			echo "cd - >/dev/null || return"
			} >> "$MODLER"
			chmod +x "$MODLER"
		fi
	fi

	if [ "$HAVESLRCT" -eq 1 ] && [ "$USESLR" -eq 1 ]; then
		writelog "INFO" "${FUNCNAME[0]} - ## SLR is enabled via USESLR=$USESLR - prepending SLR from Compatibility Tool to the current launch command"
		RUNCMD=("${RUNSLRCT[@]}" "${RUNCMD[@]}")
	fi
	
	if [ "$HAVESLR" -eq 1 ] && [ "$USESLR" -eq 1 ]; then
		writelog "INFO" "${FUNCNAME[0]} - ## SLR is enabled via USESLR=$USESLR - prepending SLR from command line to the current launch command"
		RUNCMD=("${RUNSLR[@]}" "${RUNCMD[@]}")
	fi

	if [ "$HAVESLR" -eq 1 ] && [ "$USESLR" -eq 0 ] ; then
		writelog "SKIP" "${FUNCNAME[0]} - USESLR is disabled, so skipping '$SLR' found in the commandline: '${RUNSLR[*]}'"
	fi

	RUNFORCESLR=0
	if [ "$HAVESLR" -eq 0 ] && [ "$USESLR" -eq 1 ] ; then
		if [ -n "$LASTSLR" ] && [ -f "${LASTSLR% --verb*}" ] && [ "$FORCESLR" -eq 1 ]; then
			writelog "INFO" "${FUNCNAME[0]} - ## No SLR provided from command line, but FORCESLR is $FORCESLR, so prepending LASTSLR '$LASTSLR' to the current launch command"
			mapfile -d " " -t -O "${#LASTSLRARR[@]}" LASTSLRARR < <(printf '%s' "$LASTSLR")
			RUNCMD=("${LASTSLRARR[@]}" "${RUNCMD[@]}")
			RUNFORCESLR=1
		else
			writelog "SKIP" "${FUNCNAME[0]} - No SLR was provided via command line, so configuration USESLR '$USESLR' is ignored '${LASTSLR% --verb*}' $FORCESLR"
		fi
	fi

	if [ "$HAVEREAP" -eq 1 ] && [ "$USEREAP" -eq 1 ]; then
		writelog "INFO" "${FUNCNAME[0]} - ## reaper command is enabled via USEREAP=$USEREAP - prepending to the current launch command"
		RUNCMD=("${REAPCMD[@]}" "${RUNCMD[@]}")
	elif [ "$HAVEREAP" -eq 0 ] && [ "$USEREAP" -eq 1 ] && [ -n "$LASTREAP" ] && [ -f "$LASTREAP" ] && [ "$FORCEREAP" -eq 1 ]; then
		writelog "INFO" "${FUNCNAME[0]} - ## No reaper command provided from command line, but FORCEREAP is $FORCEREAP, so prepending LASTREAP '$LASTREAP' to the current launch command"
		RUNCMD=("$LASTREAP" "SteamLaunch" "AppId=$AID" "--" "${RUNCMD[@]}")
	fi

	if [ "$STARTDEBUG" -eq 1 ]; then
		{
			echo "$(date) - $GN ($AID) - ======================"

			if [ "$HAVESCTP" -eq 0 ] && [ "$HAVEREAP" -eq 0 ]; then
				echo "$(date) - $GN ($AID) - HAVESCTP='$HAVESCTP', and HAVEREAP='$HAVEREAP' - assuming ${PROGNAME,,} is used as compat tool - using regular base game command to continue"
			elif [ "$HAVESCTP" -eq 0 ] && [ "$HAVEREAP" -eq 1 ]; then
				echo "$(date) - $GN ($AID) - HAVESCTP='$HAVESCTP', but also HAVEREAP='$HAVEREAP' - assuming ${PROGNAME,,} is set to both command and compat tool (or compat tool is empty) - steam doesn't provide STEAM_COMPAT_TOOL_PATHS, so have to cut out the reaper line to continue; HAVESLR='$HAVESLR'"
			elif [ "$HAVESCTP" -eq 1 ] && [ "$HAVEREAP" -eq 1 ]; then
				echo "$(date) - $GN ($AID) - HAVESCTP='$HAVESCTP', and HAVEREAP='$HAVEREAP' - assuming $PROGCMD is used as command line tool - switching proton version is disabled"
			elif [ "$HAVESCTP" -eq 1 ] && [ "$HAVEREAP" -eq 0 ]; then
				echo "$(date) - $GN ($AID) - HAVESCTP='$HAVESCTP', but also HAVEREAP='$HAVEREAP' - something went wrong - never seen this in the wild"
			fi

			echo "$(date) - $GN ($AID) - INITIAL LAUNCH COMAND '${INGCMD[*]}'"
			echo "$(date) - $GN ($AID) - HAVESCTP='$HAVESCTP';HAVEREAP='$HAVEREAP';HAVESLR='$HAVESLR';HAVESLRCT='$HAVESLRCT';HAVEINPROTON='$HAVEINPROTON'"
			echo "$(date) - $GN ($AID) - REAPCMD '${REAPCMD[*]}'"
			echo "$(date) - $GN ($AID) - RUNSLR '${RUNSLR[*]}'"
			echo "$(date) - $GN ($AID) - RUNSLRCT '${RUNSLRCT[*]}'"
			echo "$(date) - $GN ($AID) - ISGAME '$ISGAME'"
			echo "$(date) - $GN ($AID) - INPROTCMD '${INPROTCMD[*]}'"
			echo "$(date) - $GN ($AID) - INSTLCMD '${INSTLCMD[*]}'"
			echo "$(date) - $GN ($AID) - ORGGCMD '${ORGGCMD[*]}'"
			echo "$(date) - $GN ($AID) - ORG_STEAM_COMPAT_TOOL_PATHS '${ORG_STEAM_COMPAT_TOOL_PATHS[*]}'"
			echo "$(date) - $GN ($AID) - USEREAP='$USEREAP'; USESLR=$USESLR'"
			echo "$(date) - $GN ($AID) - FINAL LAUNCH RUNCMD '${RUNCMD[*]}'"
			echo "$(date) - $GN ($AID) - ======================"
		} >> "$STLSHM/${PROGNAME,,}-startmode-STARTDEBUG.txt"
	fi

	if [ "$HAVESCTP" -eq 1 ] && [ "$ISGAME" -eq 2 ]; then
		writelog "INFO" "${FUNCNAME[0]} - Rebuilding STEAM_COMPAT_TOOL_PATHS variable:"
		writelog "INFO" "${FUNCNAME[0]} - Adding RUNPROTON '${RUNPROTON%/*}'"
		STEAM_COMPAT_TOOL_PATHS="${RUNPROTON%/*}"
		if [ "$HAVESCTP" -eq 1 ] && [ "$USESLR" -eq 1 ]; then
			RUNSLA="${RUNSLR[0]}"
			writelog "INFO" "${FUNCNAME[0]} - Adding '${RUNSLA%/*}' because USESLR is enabled"
			STEAM_COMPAT_TOOL_PATHS="$STEAM_COMPAT_TOOL_PATHS:${RUNSLA%/*}"
		fi
		writelog "INFO" "${FUNCNAME[0]} - Result: Set STEAM_COMPAT_TOOL_PATHS from '$ORG_STEAM_COMPAT_TOOL_PATHS' to '$STEAM_COMPAT_TOOL_PATHS'"
	elif [ "$RUNFORCESLR" -eq 1 ]; then
		writelog "INFO" "${FUNCNAME[0]} - Rebuilding STEAM_COMPAT_TOOL_PATHS variable, because SLR was forced"
		writelog "INFO" "${FUNCNAME[0]} - Adding RUNPROTON '${RUNPROTON%/*}'"
		STEAM_COMPAT_TOOL_PATHS="${RUNPROTON%/*}"
		LASTSLRPATH="${LASTSLR% --verb*}"
		STEAM_COMPAT_TOOL_PATHS="$STEAM_COMPAT_TOOL_PATHS:${LASTSLRPATH%/*}"
		writelog "INFO" "${FUNCNAME[0]} - Result: Updated STEAM_COMPAT_TOOL_PATHS to '$STEAM_COMPAT_TOOL_PATHS'"
	fi

	SECONDS=0

	if [ "$MO2MODE" != "disabled" ] && [ -n "$GMO2EXE" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Changing pwd to '${GMO2EXE%/*}' for $MO launch"
		cd "${GMO2EXE%/*}" >/dev/null || return
	fi

	if [ -x "$RUNCONTY" ] && [ "$RUNCONTY" != "$NON" ]; then
		writelog "INFO" "${FUNCNAME[0]} - ## Starting game using Conty executable '$RUNCONTY'"
		"$RUNCONTY" "${RUNCMD[@]}"
	else
		writelog "INFO" "${FUNCNAME[0]} - ## ORIGINAL INCOMING LAUNCH COMMAND: '${INGCMD[*]}'"
		writelog "INFO" "${FUNCNAME[0]} - ## STL LAUNCH COMMAND: '${RUNCMD[*]}'"
		writelog "INFO" "${FUNCNAME[0]} - ## GAMESTART HERE ###"

		restoreOrgVars # restore original LC_ and friends for the game
		
		if [ "$HAVESLR" -eq 1 ] && [ "$USESLR" -eq 1 ]; then
			if [ "$STL_PV_VERBOSE" -eq 1 ]; then
				# logged gamestart
				PRESSURE_VESSEL_VERBOSE="$STL_PV_VERBOSE" "${RUNCMD[@]}" 2>&1 | tee "$STLPVLOGDIR/pressure-vessel-${AID}.log"
				# start PV shell "instead"
			elif [ "$STL_PV_SHELL" != "$NON" ]; then
				PRESSURE_VESSEL_SHELL="$STL_PV_SHELL" "${RUNCMD[@]}"
			elif [ "$STL_PV_TERMINAL" != "$NON" ]; then
				PRESSURE_VESSEL_TERMINAL="$STL_PV_TERMINAL" "${RUNCMD[@]}"
			else
				"${RUNCMD[@]}"
			fi
		else # regular gamestart - COMMENTDEBUG:
			"${RUNCMD[@]}"
		fi
	fi

	if [ "$MO2MODE" != "disabled" ]; then
		cd - >/dev/null || return
	fi

	emptyVars "O" "X" # clear original variables again (mostly for a continous log (date))

	if [ "$ISGAME" -eq 2 ] && [ "$USEWINE" -eq 0 ] && { grep -qi "\-GE\-" <<< "$USEPROTON" || grep -qi "\-TKG" <<< "$USEPROTON";}; then
#	if [ "$ISGAME" -eq 2 ] && [ "$USEWINE" -eq 0 ]; then
		RLRUNWINESERVER="$(readlink -f "$RUNWINESERVER")"
		WSPID="$("$PGREP" -a "" | grep "$RLRUNWINESERVER" | grep -v grep | cut -d ' ' -f1 | tail -n1)"
		if [ -n "$WSPID" ] && [ "$WSPID" -eq "$WSPID" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Proton '$USEPROTON' forks its command into background, so waited for the wineserver RUNWINESERVER '$RLRUNWINESERVER' with pid '$WSPID' to finish instead"
			tail --pid="$WSPID" -f /dev/null
			writelog "INFO" "${FUNCNAME[0]} - wineserver process '$WSPID' finished - closing"
		else
			writelog "ERROR" "${FUNCNAME[0]} - Could not determine pid of '$RLRUNWINESERVER'"
		fi
	fi

	duration=$SECONDS
	logPlayTime "$duration"
	writelog "INFO" "${FUNCNAME[0]} - ## GAMESTOP after '$duration' seconds playtime"

	# Continue steamwebhelper if requested
	StateSteamWebHelper cont
}

function gameArgs {
	ARGSTRING="$1"
	unset GAMEARGSARR

	if [ "$1" == "$GAMEARGS" ]; then
		if [ "$SORTGARGS" -eq 1 ]; then
			# add (originally "hardcoded", but now possibly modified) command line arguments coming directly from Steam/the game
			if [ "$HARDARGS" != "$NOPE" ] && [ "$HARDARGS" != "$NON" ]; then
				mapfile -d " " -t -O "${#GAMEARGSARR[@]}" GAMEARGSARR < <(printf '%s' "$HARDARGS")
			fi

			# now append those command line arguments coming from $SLO
			if [ "$SLOARGS" != "$NON" ]; then
				mapfile -d " " -t -O "${#GAMEARGSARR[@]}" GAMEARGSARR < <(printf '%s' "$SLOARGS")
			fi
		else
			if [ "${#ORGCMDARGS[@]}" -ge 1 ]; then
				GAMEARGSARR=("${ORGCMDARGS[@]}")
			fi
		fi
	fi 
	
	# finally add the own custom command line arguments
	if [ "$1" != "$NON" ]; then
		mapfile -d " " -t -O "${#GAMEARGSARR[@]}" GAMEARGSARR < <(printf '%s' "$ARGSTRING")
	fi

	if [ "${#GAMEARGSARR[@]}" -ge 1 ]; then
		writelog "INFO" "${FUNCNAME[0]} - Combined final game command line arguments: '${GAMEARGSARR[*]}'"
	else
		writelog "INFO" "${FUNCNAME[0]} - Game doesn't use any command line arguments"
	fi
}

function fixCustomMeta {
	if [ -f "$1" ] && grep -q "^GAMEDIR=" "$1"; then
		writelog "INFO" "${FUNCNAME[0]} - Renaming variable 'GAMEDIR' to 'MEGAMEDIR' in '$1', because 'GAMEDIR' also exists in the generic metadata, coming from steam" "E"
		sed "s:^GAMEDIR=:MEGAMEDIR=:" -i "$1"
	fi	
}

function initPlay {
	HAVESLR=0
	HAVESLRCT=0
	HAVEREAP=0
	HAVESCTP=0
	INCOPATH=0
	STLPLAY=1

	function setHaveConfs {
		if [ -n "$HAVID" ]; then
			if [ -z "$HAVCUME" ]; then
				HAVCUME="$CUMETA/$HAVID.conf"
			fi

			if [ -z "$HAVGEME" ]; then
				HAVGEME="$GEMETA/$HAVID.conf"
			fi
			
			if [ -z "$HAVGACO" ]; then
				HAVGACO="$STLGAMEDIRID/$HAVID.conf"
			fi
		fi	
	}

	function loadHaveConfs {
		if [ -f "$HAVGEME" ] && [ -z "$LOADEDHAVGEME" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Loading generic metadata found under '$HAVGEME'" "E"
			loadCfg "$HAVGEME"
			LOADEDHAVGEME=1
		fi

		if [ -f "$HAVCUME" ] && [ -z "$LOADEDHAVCUME" ]; then
			fixCustomMeta "$HAVCUME"
			writelog "INFO" "${FUNCNAME[0]} - Loading custom metadata found under '$HAVCUME'" "E"
			loadCfg "$HAVCUME"
			LOADEDHAVCUME=1
		fi

		if [ -f "$HAVGACO" ] && [ -z "$LOADEDHAVGACO" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Loading game config '$HAVGACO'" "E"
			loadCfg "$HAVGACO"
			LOADEDHAVGACO=1
		fi
	}

	function saveHaveCuMe {
		if [ -n "$HAVCUME" ] && [ ! -f "$HAVCUME" ]; then
			touch "$HAVCUME"
		fi
		
		if [ -n "$MEGAMEDIR" ]; then 
			touch "$FUPDATE"
			updateConfigEntry "MEGAMEDIR" "$MEGAMEDIR" "$HAVCUME"
		fi
	}

	function saveHaveGeMe {
		if [ -n "$HAVGEME" ] && [ ! -f "$HAVGEME" ]; then
			touch "$HAVGEME"
		fi

		if [ -n "$HAVID" ]; then
			touch "$FUPDATE"
			updateConfigEntry "GAMEID" "$HAVID" "$HAVGEME"
		elif [ -n "$AID" ] && [ "$AID" != "$PLACEHOLDERAID" ]; then
			touch "$FUPDATE"
			updateConfigEntry "GAMEID" "$AID" "$HAVGEME"
		fi
		
		if [ -n "$EXECUTABLE" ]; then 
			touch "$FUPDATE"
			updateConfigEntry "EXECUTABLE" "$EXECUTABLE" "$HAVGEME"	
			if [ -z "$GAMEEXE" ]; then
				GAMEEXE="${EXECUTABLE//.exe}"
			fi
		fi

		if [ -n "$GE" ] && [ -z "$GAMEEXE" ]; then
			GAMEEXE="$GE"
		fi

		if [ -n "$GAMEEXE" ]; then
			touch "$FUPDATE"
			updateConfigEntry "GAMEEXE" "$GAMEEXE" "$HAVGEME"
		fi

		if [ -z "$GAMENAME" ]; then
			GAMENAME="${EXECUTABLE//.exe}"
		fi
			
		if [ -n "$GAMENAME" ]; then
			touch "$FUPDATE"
			updateConfigEntry "GAMENAME" "$GAMENAME" "$HAVGEME"
		fi

		if [ -z "$KEEPGAMENAME" ]; then
			KEEPGAMENAME=1
			touch "$FUPDATE"
			updateConfigEntry "KEEPGAMENAME" "$KEEPGAMENAME" "$HAVGEME"
		fi	
	}

	if [ "$1" -eq "$1" ] 2>/dev/null; then
		writelog "INFO" "${FUNCNAME[0]} - Assuming incoming argument '$1' is a SteamAppId" "E"
		HAVID="$1"
	elif [ -f "$1" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Assuming incoming argument '$1' is an absolute path to a game exe" "E"
		HAVPA="$1"
		INCOPATH=1
	else
		writelog "INFO" "${FUNCNAME[0]} - Assuming incoming argument '$1' is a game title" "E"
		HAVTI="$1"
	fi
	
	if [ -n "$HAVTI" ] || [ -n "$HAVID" ] && { [ -n "$2" ] && [ -f "$2" ];}; then
		HAVPA="$2"
	fi
	
	if [ -n "$HAVTI" ]; then
		CKHAVGEME="$(find "$TIGEMETA" -iname "$HAVTI.conf")"
		if [ -f "$CKHAVGEME" ]; then
			HAVGEME="$CKHAVGEME"
		fi

		CKHAVCUME="$(find "$TICUMETA" -iname "$HAVTI.conf")"
		if [ -f "$CKHAVCUME" ]; then
			HAVCUME="$CKHAVCUME"
		fi
		
		if [ -z "$HAVGEME" ]; then
			HAVGEMECFG="$(grep -Ri "NAME=\"$HAVTI" "$GEMETA/" | head -n1 | cut -d ':' -f1)"
			CKHAVGEME="$GEMETA/$HAVGEMECFG"
			if [ -f "$CKHAVGEME" ]; then
				HAVGEME="$CKHAVGEME"
			fi

			CKHAVCUME="$(find "$CUMETA" -iname "$HAVGEMECFG")"
			if [ -f "$CKHAVCUME" ]; then
				HAVCUME="$CKHAVCUME"
			fi
		fi
	fi
	
	setHaveConfs
	loadHaveConfs

	if [ -n "$GAMEID" ] && [ -z "$HAVID" ]; then
		HAVID="$GAMEID"
		writelog "INFO" "${FUNCNAME[0]} - Found SteamAppId '$HAVID'" "E"
	fi

	setHaveConfs
	loadHaveConfs

	if [ -z "$EXECUTABLE" ] && [ -f "$HAVPA" ]; then
		EXECUTABLE="${HAVPA##*/}"
	fi

	if [ -z "$EXECUTABLE" ] && [ -n "$GAMENAME" ]; then
		EXECUTABLE="$GAMENAME"
	fi

	if [ -z "$HAVPA" ] && [ -n "$MEGAMEDIR" ] && [ -n "$EXECUTABLE" ]; then
		CHKHAVPA="$MEGAMEDIR/$EXECUTABLE"
		if [ -f "$CHKHAVPA" ]; then
			HAVPA="$CHKHAVPA"
		fi
	fi
	
	if [ -n "$EXECUTABLE" ] && [ -n "$HAVPA" ] && [ "$EXECUTABLE" != "${HAVPA##*/}" ]; then
		EXECUTABLE="${HAVPA##*/}"
	fi

	if [ -n "$MEGAMEDIR" ]; then
		GFD="$MEGAMEDIR"
	fi

	if [ -z "$HAVID" ] &&  [ -z "$GAMEID" ] && [ -n "$HAVPA" ]; then
		HAVID="$(setGNID "${HAVPA##*/}")"
		if [ -z "$GFD" ]; then
			GFD="${HAVPA%/*}"
		fi
		if [ -z "$EFD" ]; then
			EFD="${HAVPA%/*}"
		fi
	fi

	if [ -n "$MEGAMEDIR" ] && [ -n "$HAVPA" ] && [ "$MEGAMEDIR" != "${HAVPA%/*}" ]; then
		MEGAMEDIR="${HAVPA%/*}"
	fi

	if [ -n "${HAVPA%/*}" ] && [ -z "$EFD" ]; then EFD="${HAVPA%/*}"; fi
	if [ -n "${HAVPA%/*}" ] && [ -z "$GFD" ]; then GFD="${HAVPA%/*}"; fi

	setHaveConfs
	loadHaveConfs

	if [ -n "$HAVID" ] &&  [ -z "$GAMEID" ] && { [ -z "$AID" ] || [ "$AID" == "$PLACEHOLDERAID" ];}; then
		writelog "INFO" "${FUNCNAME[0]} - Setting AID to '$HAVID'" "E"
		export AID="$HAVID"
	fi

	if [ -n "$GAMEID" ] && { [ -z "$AID" ] || [ "$AID" == "$PLACEHOLDERAID" ];}; then
		writelog "INFO" "${FUNCNAME[0]} - Setting AID to '$GAMEID'" "E"
		export AID="$GAMEID"
	fi

	saveHaveCuMe
	saveHaveGeMe
    # from here all required vars should be ready to launch

	if [ -n "$AID" ] && [ "$AID" != "$PLACEHOLDERAID" ]; then
		if [ -z "$HAVGACO" ]; then
			HAVGACO="$STLGAMEDIRID/$AID.conf"
		fi

		loadHaveConfs

		if [ -n "$GAMENAME" ] && [ "$GAMENAME" != "$NON" ]; then
			ICGN="$GAMENAME"
		elif [ -n "$GAMEEXE" ] && [ "$GAMEEXE" != "$NON" ]; then
			ICGN="$GAMEEXE"
		elif [ -n "$EXECUTABLE" ] && [ "$EXECUTABLE" != "$NON" ]; then
			ICGN="$GAMEEXE"
		else
			ICGN="$NON"
		fi

		createDesktopIconFile "$AID" "0" "$ICGN" "$HAVPA"

		if [ -f "$HAVPA" ]; then
			if [ -z "$GP" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Set 'GP' to '$HAVPA'" "E"
				GP="$HAVPA"
			else
				writelog "INFO" "${FUNCNAME[0]} - Already have 'GP' '$GP'" "E"
			fi

			if [ "$INCOPATH" -eq 1 ]; then
				while read -r INGARG; do
					mapfile -t -O "${#INGCMD[@]}" INGCMD <<< "$INGARG"
				done <<< "$(printf "%s\n" "$@")"

				FOUNDORGGCMD=0
				while read -r ORGARG; do
					if [ "$FOUNDORGGCMD" -eq 0 ]; then
						mapfile -t -O "${#ORGGCMD[@]}" ORGGCMD <<< "$ORGARG"
						if [[ "$ORGARG" =~ $GP ]]; then
							FOUNDORGGCMD=1
						fi
					else
						mapfile -t -O "${#ORGCMDARGS[@]}" ORGCMDARGS <<< "$ORGARG"
					fi
				done <<< "$(printf "%s\n" "${INGCMD[@]}")"
			else
				ORGGCMD=( "$HAVPA" )
			fi

			if [ -z "$GE" ] && [ -n "$HAVPA" ]; then
				GE="${HAVPA##*/}" 
			fi

			if [ -z "$GP" ] && [ -n "$HAVPA" ]; then
				GP="$HAVPA"
			fi

			if [ -z "$GN" ] && [ -n "$HAVPA" ]; then
				GN="${HAVPA##*/}" 
			fi

			writelog "INFO" "${FUNCNAME[0]} - Game executable used is '$HAVPA'" "E"

			if grep -q "shell script" <<< "$(file "$(realpath "$HAVPA")")" || grep -q "ELF.*.LSB" <<< "$(file "$(realpath "$HAVPA")")" ; then
				writelog "INFO" "${FUNCNAME[0]} - Assuming this is a linux binary" "E"
				ISGAME=3
				GPFX="$NON"
				cd "$MEGAMEDIR" || return
				prepareLaunch
				cd - || return
			else
				writelog "INFO" "${FUNCNAME[0]} - Assuming this is a windows binary" "E"

				if [ -z "$STEAM_COMPAT_INSTALL_PATH" ]; then
					if [ -n "$MEGAMEDIR" ]; then
						export STEAM_COMPAT_INSTALL_PATH="$MEGAMEDIR"
					elif [ -n "$EFD" ]; then
						export STEAM_COMPAT_INSTALL_PATH="$EFD"
					else
						writelog "INFO" "${FUNCNAME[0]} - STEAM_COMPAT_INSTALL_PATH (game dir) is unknown - setting it at least to '${STLDLDIR}'"
						export STEAM_COMPAT_INSTALL_PATH="$STLDLDIR"
					fi
				fi

				if [ -z "$STL_COMPAT_DATA_PATH" ]; then
					STL_COMPAT_DATA_PATH="$STLCOMPDAT/$AID"
				fi

				if [ -n "$STL_COMPAT_DATA_PATH" ]; then
					mkProjDir "$STL_COMPAT_DATA_PATH"
					writelog "INFO" "${FUNCNAME[0]} - Using '$STL_COMPAT_DATA_PATH' as STEAM_COMPAT_DATA_PATH" "E"
					export STEAM_COMPAT_DATA_PATH="$STL_COMPAT_DATA_PATH"
					export GPFX="${STL_COMPAT_DATA_PATH}/pfx"
					ISGAME=2
					cd "$STEAM_COMPAT_INSTALL_PATH" || return
					prepareLaunch
					cd - || return
				else
					writelog "ERROR" "${FUNCNAME[0]} - STEAM_COMPAT_DATA_PATH was not defined"
				fi
			fi
		fi
	else
		writelog "ERROR" "${FUNCNAME[0]} - Could not determine an AppID - can't continue" "E"
	fi
}

function standaloneGames {
	if [ -d "$GEMETA" ]; then
		while read -r line; do
			if [ -n "$1" ] && [ "$1" == "l" ]; then
				SAG="$(grep "^GAMENAME=" "$line" | cut -d '=' -f2)"
				if [ -n "$SAG" ]; then
					echo "${SAG//\"/}"
				fi
			elif [ -n "$1" ] && [ "$1" == "g" ]; then
				unset GAMENAME EXECUTABLE GAMEID
				loadCfg "$line"
				if [ -n "$GAMEID" ] && [ -n "$EXECUTABLE" ]; then
					echo "FALSE"

					if [ -n "$GAMENAME" ]; then
						echo "$GAMENAME"
					else
						echo "$EXECUTABLE"
					fi
					
					echo "$EXECUTABLE"
					echo "$GAMEID"
				else
					writelog "SKIP" "${FUNCNAME[0]} - Skipping config '$line', because at least one of GAMEID:'$GAMEID' EXECUTABLE:'$EXECUTABLE', GAMENAME:'$GAMENAME' is empty"
				fi
			else
				echo "$line"
			fi
		done <<< "$(find "$GEMETA" -name "${GETSTAID}.conf")"
	else
		writelog "ERROR" "${FUNCNAME[0]} - Directory GEMETA '$GEMETA' could not be found" "E"
 	fi
}

function standaloneDefGameIcon {
	if [ -x "$(command -v "$CONVERT" 2>/dev/null)" ]; then
		"$CONVERT" "$STLICON" -resize "128x128!" "$WANTGPNG"
	else
		cp "$STLICON" "$WANTGPNG"
	fi
}

function standaloneGameIcon {
	WANTGPNG="$1"
	AID="$2"
	GAMENAME="$3"
	HAVEPA="$4"
	if [ -f "$WANTGPNG" ]; then
		writelog "SKIP" "${FUNCNAME[0]} - Already have an icon: '$WANTGPNG'"
	else
		writelog "SKIP" "${FUNCNAME[0]} - Trying to find an icon for '$GAMENAME'"
		if grep -q "shell script" <<< "$(file "$(realpath "$HAVPA")")" || grep -q "ELF.*.LSB" <<< "$(file "$(realpath "$HAVPA")")" ; then
			# yes, quick&dirty!
			SYSICN="$(cut -d '=' -f2 <<< "$(grep "^Icon=" "$(find "/usr/share/applications/" -name "${HAVPA##*/}*.desktop" | head -n1)")")"
			if [ -n "$SYSICN" ]; then
				SYSICF="$(find "/usr/share/icons/" -name "${SYSICN}.png" | sort -nr | head -n1)"
				if [ -f "$SYSICF" ]; then
					if [ -x "$(command -v "$CONVERT" 2>/dev/null)" ]; then
						writelog "INFO" "${FUNCNAME[0]} - Creating a '$SYSICF' copy with fix size 128x128 at '$WANTGPNG'"
						"$CONVERT" "$SYSICF" -resize "128x128!" "$WANTGPNG"
					else
						writelog "INFO" "${FUNCNAME[0]} - Copying '$SYSICF' to '$WANTGPNG'"
						cp "$SYSICF" "$WANTGPNG"
					fi
				else
					writelog "INFO" "${FUNCNAME[0]} - Did not find a default icon for '$GAMENAME' using '$STLICON' as default for '$WANTGPNG'"
					standaloneDefGameIcon
				fi
			fi
		else
			PEVDSTI="$STLGPEVKD/$PERES/id/$AID"
			
			if [ -x "$(command -v "$PERES")" ] && { [ ! -d "$PEVDSTI" ] || [ "$(find "$PEVDSTI" -type f | wc -l)" -eq 0 ];}; then
				mkProjDir "$PEVDSTI"
				writelog "INFO" "${FUNCNAME[0]} - extracting data from '${HAVEPA##*/}' using '$PERES' to '$PEVDSTI'"
				cd "$PEVDSTI" >/dev/null || return
				notiShow "$(strFix "$NOTY_ANALYZE" "$HAVEPA" "$PERES")"
				"$PERES" -x "$HAVEPA" &
				cd - >/dev/null || return
			fi
			
			PRI="$PEVDSTI/resources/icons"
			if [ ! -d "$PRI" ]; then
				writelog "INFO" "${FUNCNAME[0]} - directory for alternative icon location not found - using '$STLICON' as default for '$WANTGPNG'"
				standaloneDefGameIcon
			else
				FIRSTICO="$(find "$PRI" -type f -name "*.ico" -printf "%s %p\n" | sort -nr | head -n1 | cut -d ' ' -f2)"
				if [ -f "$FIRSTICO" ]; then
					if [ -x "$(command -v "$CONVERT" 2>/dev/null)" ]; then
						writelog "INFO" "${FUNCNAME[0]} - Converting '$FIRSTICO', extracted from '${HAVEPA##*/}' to '$WANTGPNG'"
						"$CONVERT" "$FIRSTICO" -resize "128x128!" "$WANTGPNG"
					else
						writelog "INFO" "${FUNCNAME[0]} - Could not convert '$FIRSTICO', because '$CONVERT' was not found - using '$STLICON' as default for '$WANTGPNG'"
						cp "$STLICON" "$WANTGPNG"
					fi
				else
					writelog "INFO" "${FUNCNAME[0]} - Could not extract icon from '${HAVEPA##*/}' - using '$STLICON' as default for '$WANTGPNG'"
					standaloneDefGameIcon
				fi
			fi
		fi	
	fi
}

function standaloneDesktopFile {
	INTDTFILE="$1"
	WANTGPNG="$2"
	AID="$3"
	GAMENAME="$4"

	if [ -f "$INTDTFILE" ]; then
		writelog "SKIP" "${FUNCNAME[0]} - $INTDTFILE already exists"
	else
		if [ -n "$GAMENAME" ] && [ "$GAMENAME" != "$NON" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Creating '$INTDTFILE' for '$GAMENAME'"
			{
				echo "[Desktop Entry]"
				echo "Name=${GAMENAME//\"/}"
				echo "Comment=$(strFix "$DF_SLCOMMENT" "${GAMENAME//\"/}" "$PROGNAME")"
				echo "Exec=$(realpath "$0") play $AID"
				echo "Icon=$WANTGPNG"
				echo "Terminal=false"
				echo "Type=Application"
				echo "Categories=Game;"
			} >> "$INTDTFILE"
		fi
	fi
}

function standaloneLaunch {
	setShowPic
	STLA="Standalone-Launcher"
	export CURWIKI="$PPW/$STLA"
	TITLE="${PROGNAME}-$STLA"
	pollWinRes "$TITLE"
	echo "STLISLDFD $STLISLDFD"
	if [ -d "$STLISLDFD" ] && [ "$(find "$STLISLDFD" -name "*.desktop" | wc -l)" -ge 1 ]; then
		"$YAD" --f1-action="$F1ACTION" --icons --window-icon="$STLICON" --read-dir="$STLISLDFD" "$WINDECO" --title="$TITLE" --single-click --keep-icon-size --center --compact --sort-by-name "$GEOM"
	else
		writelog "SKIP" "${FUNCNAME[0]} - No games found in '$STLISLDFD' or directory itself not found"
	fi
}

function standaloneEd {
	if [ -z "$1" ]; then
		writelog "ERROR" "${FUNCNAME[0]} - Need a valid AppID or title for an installed standalone program" "E"
	else
		if [ "$1" -eq "$1" ] 2>/dev/null; then
			AID="$1"
			HAVID="$AID"
		else
			if [ -d "$STLISLDFD" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Looking for AppID for title '$1'" "E"
				TSTAID="$(grep "^Name=$1$" -h -A5 -R "$STLISLDFD" | grep -m1 "Exec=" | grep -o "$GETSTAID")"
				if [ -n "$TSTAID" ] && [ "$TSTAID" -eq "$TSTAID" ] 2>/dev/null; then
					AID="$TSTAID"
					HAVID="$AID"
				fi
			else
				writelog "ERROR" "${FUNCNAME[0]} - directory '$STLISLDFD' missing - can't search for '$1'" "E"
			fi
		fi
		
		if [ -n "$AID" ] && [ "$AID" != "$PLACEHOLDERAID" ]; then
			
			unset MEGAMEDIR GAMENAME KEEPGAMENAME STL_COMPAT_DATA_PATH 
			writelog "INFO" "${FUNCNAME[0]} - Looking for configs for AppID '$AID'" "E"
			HAVGEME="$GEMETA/${AID}.conf"
			if [ -f "$HAVGEME" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Loading found config '$HAVGEME'" "E"
				loadCfg "$HAVGEME"
			fi 

			HAVCUME="$CUMETA/${AID}.conf"
			if [ -f "$HAVCUME" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Loading found config '$HAVCUME'" "E"
				loadCfg "$HAVCUME"
			fi 
			
			WANTGPNG="$STLGPNG/${AID}.png"
			CPICKPROG="$MEGAMEDIR/$EXECUTABLE"

			STED="Standalone-Editor"
			STLA="Standalone-Launcher"
			export CURWIKI="$PPW/$STLA"
			TITLE="${PROGNAME}-$STED"
			pollWinRes "$TITLE"
			
			NEWSTDAT="$("$YAD" --f1-action="$F1ACTION" --image "$WANTGPNG" --window-icon="$STLICON" --form --center --on-top "$WINDECO" \
			--title="$TITLE" --separator="|" \
			--text="$STED" \
			--field=" ":LBL " " \
			--field="     $GUI_PICKPROG!$DESC_PICKPROG":FL "$CPICKPROG" \
			--field="     $GUI_GAMENAME!$DESC_GAMENAME" "${GAMENAME/#-/ -}" \
			--field="     $GUI_KEEPGAMENAME!$DESC_KEEPGAMENAME":CHK "${KEEPGAMENAME/#-/ -}" \
			--field="     $GUI_STL_COMPAT_DATA_PATH!$DESC_STL_COMPAT_DATA_PATH":DIR "${STL_COMPAT_DATA_PATH/#-/ -}" \
			--field="     $GUI_PICKICON!$DESC_PICKICON":FL "${WANTGPNG/#-/ -}" \
			--button="$BUT_DONE":0 --button="$BUT_CAN":2  "$GEOM")"
			case $? in
			0)  {
					writelog "INFO" "${FUNCNAME[0]} - Selected $BUT_DONE"
					unset NSTARR
					mapfile -d "|" -t -O "${#NSTARR[@]}" NSTARR < <(printf '%s' "$NEWSTDAT")
					NPICKPROG="${NSTARR[1]}"
					NGAMENAME="${NSTARR[2]}"
					NKEEPGAMENAME="${NSTARR[3]}"
					NSTL_COMPAT_DATA_PATH="${NSTARR[4]}"
					NPICKICON="${NSTARR[5]}"
					
					NEWIC=0
					
					if [ "$NPICKPROG" != "$CPICKPROG" ]; then
						NMEGAMEDIR="${NPICKPROG%/*}"
						NEXECUTABLE="${NPICKPROG##*/}"

						if [ "$NMEGAMEDIR" != "$MEGAMEDIR" ]; then
							touch "$FUPDATE"
							updateConfigEntry "MEGAMEDIR" "$NMEGAMEDIR" "$HAVCUME"
							NEWIC=1
						fi
						if [ "$NEXECUTABLE" != "$EXECUTABLE" ]; then
							touch "$FUPDATE"
							updateConfigEntry "EXECUTABLE" "$NEXECUTABLE" "$HAVGEME"
							NEWIC=1
						fi
					fi

					if [ "$NGAMENAME" != "$GAMENAME" ]; then
						touch "$FUPDATE"
						updateConfigEntry "GAMENAME" "$NGAMENAME" "$HAVGEME"
						NEWIC=1
					fi

					updateConfigEntry "KEEPGAMENAME" "$NKEEPGAMENAME" "$HAVGEME"	

					if [ "$NSTL_COMPAT_DATA_PATH" != "$STL_COMPAT_DATA_PATH" ]; then
						touch "$FUPDATE"
						updateConfigEntry "STL_COMPAT_DATA_PATH" "$NSTL_COMPAT_DATA_PATH" "$HAVGEME"
						NEWIC=1
					fi

					if [ "$NPICKICON" != "$WANTGPNG" ]; then
						if [ -x "$(command -v "$CONVERT" 2>/dev/null)" ]; then
							"$CONVERT" "$NPICKICON" -resize "128x128!" "$WANTGPNG"
						else
							cp "$NPICKICON" "$WANTGPNG"
						fi
						NEWIC=1
					fi

					if [ "$NEWIC" -eq 1 ]; then
						loadCfg "$HAVGEME"
						loadCfg "$HAVCUME"
						WANTGPNG="$STLGPNG/${AID}.png"
						HAVEPA="$MEGAMEDIR/$EXECUTABLE"
						INTDTFILE="$STLISLDFD/$AID.desktop"
						rm "$INTDTFILE"
						standaloneDesktopFile "$INTDTFILE" "$WANTGPNG" "$AID" "$GAMENAME" "$HAVEPA"
					fi
				}
			;;
			2) 	{
					writelog "INFO" "${FUNCNAME[0]} - Selected $BUT_CAN"

				}
			;;
			esac 
		else
			writelog "ERROR" "${FUNCNAME[0]} - No data found for '$1'" "E"
		fi
	fi
}

function createDLWineList {
	writelog "INFO" "${FUNCNAME[0]} - Generating list of online available Wine archives"
	WINEDLLIST="$STLSHM/WineDL.txt"
	MAXAGE=360

	if [ ! -f "$WINEDLLIST" ] || test "$(find "$WINEDLLIST" -mmin +"$MAXAGE")"; then
		rm "$WINEDLLIST" 2>/dev/null
		while read -r CWURL; do
		if grep -q "$GHURL" <<< "${!CWURL}"; then
			"$WGET" -q "${!CWURL}" -O - 2> >(grep -v "SSL_INIT") | grep "tar.gz\|zip\|tar.xz" | grep "releases" | grep -oE '\"/[^\\"]+' | sed "s|^\"|$GHURL|g" >> "$WINEDLLIST"
		fi
		done <<< "$(grep "^CW_" "$STLURLCFG" | cut -d '=' -f1)"
	fi

	unset WineDLList
	unset WineDLDispList
	while read -r CWVERS; do
		mapfile -t -O "${#WineDLList[@]}" WineDLList <<< "$CWVERS"
		mapfile -t -O "${#WineDLDispList[@]}" WineDLDispList <<< "${CWVERS##*/}"
	done < "$WINEDLLIST"
}

function dlWineGUI {
	createDLWineList

	writelog "INFO" "${FUNCNAME[0]} - Opening dialog to choose a download"

	DLWINELIST="$(printf "!%s\n" "${WineDLDispList[@]//\"/}" | tr -d '\n' | sed "s:^!::" | sed "s:!$::")"
	export CURWIKI="$PPW/Download-Custom-Wine"
	TITLE="${PROGNAME}-DownloadWine"
	pollWinRes "$TITLE"

	if [ -z "$DLWINE" ]; then
		DLWINE="${WineDLDispList[0]}"
	fi

	DLDISPWINE="$("$YAD" --f1-action="$F1ACTION" --window-icon="$STLICON" --form --center --on-top $WINDECO \
	--title="$TITLE" \
	--text="$(spanFont "$GUI_DLWINETEXT" "H")" \
	--field=" ":LBL " " \
	--field="$GUI_DLWINETEXT2!$GUI_DLWINETEXT":CBE "$(cleanDropDown "${DLWINE/#-/ -}" "$DLWINELIST")" \
	"$GEOM")"

	if [ -n "${DLDISPWINE//|/\"}" ]; then
		if grep -q "^http" <<< "${DLDISPWINE//|/\"}"; then
			DLURL="${DLDISPWINE//|/\"}"
			writelog "INFO" "${FUNCNAME[0]} - The URL '$DLURL' was entered manually - downloading directly"
		else
			DLWINEVERSION="${DLDISPWINE//|/}"
			DLURL="$(printf "%s\n" "${WineDLList[@]}" | grep -m1 "${DLDISPWINE//|}")"
			writelog "INFO" "${FUNCNAME[0]} - '${DLDISPWINE//|}' was selected - downloading '$DLURL'"
		fi
		StatusWindow "$(strFix "$NOTY_DLCUSTOMPROTON" "Wine")" "dlWine ${DLURL//|/\"}" "DownloadWineStatus"
	fi
}

# currently unused:
function PickSpecificWine {
	export CURWIKI="$PPW/Download-Custom-Wine"
	TITLE="${PROGNAME}-${FUNCNAME[0]}"
	pollWinRes "$TITLE"

	SPECWINE="$("$YAD" --f1-action="$F1ACTION" --window-icon="$STLICON" --form --center --on-top $WINDECO \
	--title="$TITLE" --separator="|" \
	--text="$(spanFont "GUI_DLSPECWINE" "H")" \
	--field=" ":LBL " " \
	--field="Vanilla":CHK "TRUE" \
	--field="Staging":CHK "TRUE" \
	--field="Proton":CHK "TRUE" \
	--field="TkG":CHK "TRUE" \
	--field=" ":LBL " " \
	--field="x86":CHK "TRUE" \
	--field="amd64":CHK "TRUE" \
	"$GEOM")"

	unset SWINSEL
	mapfile -d "|" -t -O "${#SWINSEL[@]}" SWINSEL < <(printf '%s' "$SPECWINE")
	WANTVAN="${SWINSEL[1]}"
	WANTSTA="${SWINSEL[2]}"
	WANTPRO="${SWINSEL[3]}"
	WANTTKG="${SWINSEL[4]}"
	WANTX86="${SWINSEL[6]}"
	WANTA64="${SWINSEL[7]}"

	if [ "$WANTVAN" == "TRUE" ]; then
		GWI="[0-9]-[x,a]"
		GWO="$NON"
	else
		GWO="[0-9]-[x,a]"
		GWI="releases"
	fi

	if [ "$WANTSTA" == "TRUE" ]; then
		GWI="${GWI}\|staging"
	else
		GWO="${GWO}\|staging"
	fi

	if [ "$WANTPRO" == "TRUE" ]; then
		GWI="${GWI}\|proton"
	else
		GWO="${GWO}\|proton"
	fi

	if [ "$WANTTKG" == "TRUE" ]; then
		GWI="${GWI}\|tkg"
	else
		GWO="${GWO}\|tkg"
	fi

	if [ "$WANTX86" == "TRUE" ]; then
		GWI="${GWI}\|x86"
	else
		GWO="${GWO}\|x86"
	fi

	if [ "$WANTA64" == "TRUE" ]; then
		GWI="${GWI}\|amd64"
	else
		GWO="${GWO}\|amd64"
	fi
}

function dlWine {
	WURL="${1//\"/}"
	WURLFILE="${WURL##*/}"
	DSTDL="$WINEDLDIR/$WURLFILE"
	if [ ! -f "$DSTDL" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Downloading '$WURL' to '$WINEDLDIR'"
		notiShow "$(strFix "$NOTY_DLCUSTOMPROTON" "$WURL")" "S"
		dlCheck "$WURL" "$DSTDL" "X" "Downloading '$WURLFILE'"
		notiShow "$(strFix "$NOTY_DLCUSTOMPROTON2" "$WURL")" "S"
	else
		writelog "INFO" "${FUNCNAME[0]} - File '$DSTDL' already exists - nothing to download"
		notiShow "$(strFix "$NOTY_DLCUSTOMPROTON4" "${WURL##*/}")" "S"
	fi
	extractWine "$DSTDL"
}

function dlWineGate {
	if [ -z "$1" ]; then
		dlWineGUI
	else
		if grep -q "^http" <<< "$1"; then
			writelog "INFO" "${FUNCNAME[0]} - '$1' is an URL - sending directly to dlWine"
			StatusWindow "$(strFix "$NOTY_DLCUSTOMPROTON" "Wine")" "dlWine $*" "DownloadWineStatus"
		elif [ "$1" == "latest" ] || [ "$1" == "l" ]; then
			createDLWineList
			writelog "INFO" "${FUNCNAME[0]} - Downloading latest custom Wine ${WineDLList[0]//\"/}" "E"
			StatusWindow "$(strFix "$NOTY_DLCUSTOMPROTON" "Wine")" "dlWine ${WineDLList[0]//\"/}" "DownloadWineStatus"
		else
			writelog "SKIP" "${FUNCNAME[0]} - Don't know what to do with argument '$1'"
		fi
	fi
}

function extractWine {
	if [ -f "$1" ]; then
		WURLFILE="${1##*/}"
		WDIRRAW="${WURLFILE//wine-/}"
		WDIR="${WDIRRAW//.tar.xz}"
		
		if [ -d "$WINEEXTDIR/$WDIR" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Directory '$WINEEXTDIR/$WDIR' already exists - nothing to extract"
		else
			writelog "INFO" "${FUNCNAME[0]} - Extracting archive '$WURLFILE' to '$WINEEXTDIR'"
			notiShow "$(strFix "$NOTY_DLCUSTOMPROTON3" "$1")" "S"
			"$TAR" xf "$1" -C "$WINEEXTDIR" 2>/dev/null
			notiShow "$GUI_DONE" "S"
		fi
	fi
}

function WineSelection {
	setShowPic
	export CURWIKI="$PPW/Wine-Support"
	TITLE="${PROGNAME}-ChooseWine"
	pollWinRes "$TITLE"

	writelog "INFO" "${FUNCNAME[0]} - Opening Wine Selection"

	 "$YAD" --f1-action="$F1ACTION" --image "$SHOWPIC" --image-on-top --center --window-icon="$STLICON" --form --center "$WINDECO" \
	--title="$TITLE" \
	--text="$(spanFont "$GUI_SELWINE" "H")" \
	--button="$BUT_DLDWINE":0 \
	--button="$BUT_SELWINE":2 \
	"$GEOM"
	
	case $? in
	0)  {
			writelog "INFO" "${FUNCNAME[0]} - Selected Wine Download"
			dlWineGUI
			if [ "$DLWINEVERSION" != "$NON" ]; then
				WINEVERSION="${DLWINEVERSION//|/}"
				writelog "INFO" "${FUNCNAME[0]} - Chose downloaded '$WINEVERSION'"
			fi
		}
	;;
	2) 	{
			writelog "INFO" "${FUNCNAME[0]} - Selected Ready Wine"
			createWineList
			export CURWIKI="$PPW/Wine-Support"
			TITLE="${PROGNAME}-SelectedWine"
			pollWinRes "$TITLE"
			WINSEL="$("$YAD" --f1-action="$F1ACTION" --window-icon="$STLICON" --form --center --on-top $WINDECO \
			--title="$TITLE" \
			--text="$(spanFont "$GUI_SELIWINE" "H")" \
			--field=" ":LBL " " \
			--field="     $GUI_WINEVERSION!$DESC_WINEVERSION ('WINEVERSION')":CBE "$(cleanDropDown "${WINEVERSION/#-/ -}" "$WINEYADLIST")" \
			"$GEOM")"
			WINEVERSION="${WINSEL//|/}"
			writelog "INFO" "${FUNCNAME[0]} - Chose available '$WINEVERSION'"
		}
	;;
	esac 

	writelog "INFO" "${FUNCNAME[0]} - Saving selected wine version '$WINEVERSION' into $STLGAMECFG"
	touch "$FUPDATE"
	updateConfigEntry "WINEVERSION" "$WINEVERSION" "$STLGAMECFG"

	if [ -n "$2" ]; then
		setWineVersion "$AID" "${FUNCNAME[0]}"
	fi
}

function setWineVersion {
	if [ "$USEWINE" -eq 1 ] && [ "$ISGAME" -eq 2 ]; then
		if [[ "$WINEVERSION" =~ ${DUMMYBIN}$ ]] || [ "$WINEVERSION" == "$NON" ]; then
			writelog "INFO" "${FUNCNAME[0]} - No current wine version configured yet"
			if [[ ! "$WINEDEFAULT" =~ ${DUMMYBIN}$ ]] && [ "$WINEDEFAULT" != "$NON" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Default wine version set to '$WINEDEFAULT' - using that as current wine"
				WINEVERSION="$WINEDEFAULT"
			else
				writelog "INFO" "${FUNCNAME[0]} - No current wine version configured and no default one set, so opening a requester"
				WineSelection "$AID" "${FUNCNAME[0]}"
				writelog "INFO" "${FUNCNAME[0]} - Chose '$WINEVERSION' via requester"
			fi
		else
			writelog "INFO" "${FUNCNAME[0]} - Using current wine version '$WINEVERSION'"
		fi

		if [ ! -d "$WINEEXTDIR/${WINEVERSION}" ]; then
		
			if ! grep -q "$WINEVERSION" "$WINEDLLIST"; then
				writelog "ERROR" "${FUNCNAME[0]} - Failed to set wineversion to something usable: '$WINEVERSION' - giving up"
				closeSTL " ######### STOP EARLY '$PROGNAME $PROGVERS' #########"
				exit
			else
				writelog "INFO" "${FUNCNAME[0]} - Configured wine version '$WINEVERSION' is not installed yet, but was found detected as downloadable - trying to install it automatically"
				DLURL="$(grep "$WINEVERSION" "$WINEDLLIST" | head -n1)"
				writelog "INFO" "${FUNCNAME[0]} - Downloading '$WINEVERSION' from '$DLURL'"
				StatusWindow "$(strFix "$NOTY_DLCUSTOMPROTON" "Wine")" "dlWine ${DLURL//|/\"}" "DownloadWineStatus"
				if [ -d "$WINEEXTDIR/${WINEVERSION}" ]; then
					writelog "INFO" "${FUNCNAME[0]} - Downloading and extracting '$WINEVERSION' was successful"
				else
					writelog "ERROR" "${FUNCNAME[0]} - Downloading and extracting '$WINEVERSION' failed - giving up"
					closeSTL " ######### STOP EARLY '$PROGNAME $PROGVERS' #########"
					exit
				fi
			fi
		fi
	fi
	RUNWINEVERSION="$WINEVERSION"
	writelog "INFO" "${FUNCNAME[0]} - Selected wine version is '$RUNWINEVERSION'"
}

function createWineList {
	writelog "INFO" "${FUNCNAME[0]} - Updating the Wine Dropdown List"
	WINEYADLIST="$(printf "!%s\n" "$(find "$WINEEXTDIR" -mindepth 1 -maxdepth 1 -type d -printf '%P!')" | tr -d '\n' | sed "s:^!::" | sed "s:!$::")"
}

function setWineVars {
	if [ "$USEWINE" -eq 1 ] && [ "$ISGAME" -eq 2 ] && { [ -z "$RUNWINEVERSION" ] || [ "$RUNWINEVERSION" != "$WINEVERSION" ];}; then
		writelog "INFO" "${FUNCNAME[0]} - USEWINE is enabled. Creating some wine related variables"

		if [ -n "$RUNWINEVERSION" ] && [[ "$WINEVERSION" =~ ${DUMMYBIN}$ ]]; then
			WINEVERSION="$RUNWINEVERSION"
		else
			createDLWineList
		fi

		setWineVersion
		
		USEWINEBIN="$WINEEXTDIR/${WINEVERSION}/bin"
		writelog "INFO" "${FUNCNAME[0]} - Setting wine bin dir to '$USEWINEBIN'"

		RUNWINE="$USEWINEBIN/wine"
		writelog "INFO" "${FUNCNAME[0]} - Setting wine binary to '$RUNWINE'"

		RUNWINECFG="$USEWINEBIN/$WINECFG"
		writelog "INFO" "${FUNCNAME[0]} - Setting $WINECFG binary to '$RUNWINECFG'"

		RUNREGEDIT="$USEWINEBIN/regedit"
		writelog "INFO" "${FUNCNAME[0]} - Setting regedit binary to '$RUNREGEDIT'"

		RUNWICO="$USEWINEBIN/$WICO"
		writelog "INFO" "${FUNCNAME[0]} - Setting $WICO binary to '$RUNWICO'"

		if [ -n "$ARCHALTEXE" ] && [[ ! "$ARCHALTEXE" =~ ${DUMMYBIN}$ ]]; then
			CHARCH="$ARCHALTEXE"
		else
			CHARCH="$GP"
		fi

		if [ "$(getArch "$CHARCH")" == "32" ]; then
			RUNWINEARCH=win32
		else
			RUNWINEARCH=win64
		fi

		writelog "INFO" "${FUNCNAME[0]} - Game binary '${CHARCH##*/}' is $(getArch "$CHARCH")-bit so creating '$RUNWINEARCH' WINEPREFIX"
		GWFX="${GPFX//pfx/wfx}"
		writelog "INFO" "${FUNCNAME[0]} - Using WINEPREFIX '$GWFX'"
	fi
}

function launchSteamGame {
########################
	if [ "$USEGAMEMODERUN" -eq 1 ]; then
		GMR="$(command -v "$GAMEMODERUN")"
	fi

	if [ "$USEGAMESCOPE" -eq 1 ]; then
		GSC="$(command -v "$GAMESCOPE")"
	fi
	
	if [ "$USEBOXTRON" -eq 1 ] || [ "$USEROBERTA" -eq 1 ] || [ "$USELUXTORPEDA" -eq 1 ]; then
		ISGAME=3
	fi

	# game start command for both proton and linux native games:
	if [ "$USEBOXTRON" -eq 0 ] && [ "$USEROBERTA" -eq 0 ] && [ "$USELUXTORPEDA" -eq 0 ]; then
		# the actual game launch:

		gameArgs "$GAMEARGS"

		GAMESTARTCMD=("${ORGGCMD[@]}" "${GAMEARGSARR[@]}")
		unset GAMEARGSARR
		writelog "INFO" "${FUNCNAME[0]} - GAMESTARTCMD is '${GAMESTARTCMD[*]}'"
	fi

	if [ "$HAVESLR" -eq 1 ] && [ "$USESLR" -eq 1 ]; then
		if [ "$USEBOXTRON" -eq 1 ] || [ "$USELUXTORPEDA" -eq 1 ] || [ "$USEROBERTA" -eq 1 ]; then
			writelog "INFO" "${FUNCNAME[0]} - disabling USESLR is enabled as a conflicting tool is used"
			USESLR=0
		fi
	fi

	# first start with non-proton games here:
	if [ "$ISGAME" -eq 3 ]; then
		# start with boxtron:
		if [ "$USEBOXTRON" -eq 1 ]; then
			DOSEXE="$GP"
			if [ -x "$(command -v "$BOXTRONCMD" 2>/dev/null)" ]; then
				notiShow "$(strFix "$NOTY_BOXTRON" "$GN" "$AID")"
				# disable CHANGE_PULSE_LATENCY else audio gets stuck
				CHANGE_PULSE_LATENCY="0"

				writelog "INFO" "${FUNCNAME[0]} - Starting game '$SGNAID' with boxtron. Full start command is: '$BOXTRONCMD $BOXTRONARGS $DOSEXE'"
				startGame "$BOXTRONCMD" "$BOXTRONARGS" "$DOSEXE"
			else
				writelog "ERROR" "${FUNCNAME[0]} - boxtron command '$BOXTRONCMD' not found - exit"
				exit
			fi

		# start with roberta:
		elif [ "$USEROBERTA" -eq 1 ]; then
			VMEXE="$GP"
			if [ -x "$(command -v "$ROBERTACMD" 2>/dev/null)" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Starting game '$AID' with roberta: '$ROBERTACMD $ROBERTAARGS $VMEXE'"
				notiShow "$(strFix "$NOTY_ROBERTA" "$GN" "$AID")"
				RUNROBERTACMD=("$ROBERTACMD" "$ROBERTAARGS" "$VMEXE")
				startGame "${RUNROBERTACMD[@]}"
			else
				writelog "ERROR" "${FUNCNAME[0]} - roberta command '$ROBERTACMD' not found - exit"
				exit
			fi

		# start with luxtorpeda:
		elif [ "$USELUXTORPEDA" -eq 1 ]; then
			LUXEXE="$GP"
			if [ -x "$(command -v "$LUXTORPEDACMD" 2>/dev/null)" ]; then
				if [ "$USESLR" -eq 1 ]; then
					writelog "INFO" "${FUNCNAME[0]} - Using ${LUXTORPEDACMD^} (Runtime)"
					LUMADO="manual-download"
					LUXTORPEDAARGS="runtime_$LUXTORPEDAARGS"
				else
					LUMADO="manual-download"
				fi
				# skip download if engine_choice.txt exists already:
				if [ ! -f "$HOME"/.config/luxtorpeda/"$AID"/engine_choice.txt ]; then
					writelog "INFO" "${FUNCNAME[0]} - Downloading native game data for '$AID' with luxtorpeda: '$LUXTORPEDACMD' '$LUMADO' $AID"
					notiShow "$(strFix "$NOTY_LUXTORPEDA1" "$GN" "$AID")"
					"$LUXTORPEDACMD" "$LUMADO" "$AID"
				fi
				notiShow "$(strFix "$NOTY_LUXTORPEDA2" "$GN" "$AID")"
				writelog "INFO" "${FUNCNAME[0]} - Starting game '$AID' with luxtorpeda: '$LUXTORPEDACMD $LUXTORPEDAARGS $LUXEXE'"
				RUNLUXTORPEDACMD=("$LUXTORPEDACMD" "$LUXTORPEDAARGS" "$LUXEXE")
				startGame "${RUNLUXTORPEDACMD[@]}"
			else
				writelog "ERROR" "${FUNCNAME[0]} - luxtorpeda command '$LUXTORPEDACMD' not found - exit"
				exit
			fi
		# start a linux native game here:
		else

			# maybe limit this to custom linux commands
			if [ "${GAMESTARTCMD[0]}" == "$WFEAR" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Removing '$WFEAR' from '${GAMESTARTCMD[*]}'"
				GAMESTARTCMD=( "${GAMESTARTCMD[@]:1}" )
				writelog "INFO" "${FUNCNAME[0]} - Result is '${GAMESTARTCMD[*]}'"
			fi

			# start with gamemoderun:
			if [ "$USEGAMEMODERUN" -eq 1 ]; then
				if [ "$USEGAMESCOPE" -eq 1 ]; then
					writelog "INFO" "${FUNCNAME[0]} - Starting native game '$SGNAID' with '$GAMEMODERUN' and '$GAMESCOPE'"
					notiShow "$(strFix "$NOTY_STARTNATGAMOSC" "$GN" "$AID")"
					gameArgs "$GAMESCOPE_ARGS"
					writelog "INFO" "${FUNCNAME[0]} - Full start command is '$GAMEMODERUN $GAMESCOPE ${GAMEARGSARR[*]} ${GAMESTARTCMD[*]}'"
					startGame "$GMR" "$GSC" "${GAMEARGSARR[@]}" "${GAMESTARTCMD[@]}"
				else
					writelog "INFO" "${FUNCNAME[0]} - Starting native game '$SGNAID' with '$GAMEMODERUN' - ${GAMESTARTCMD[*]}"
					notiShow "$(strFix "$NOTY_STARTNATGAMO" "$GN" "$AID")"
					writelog "INFO" "${FUNCNAME[0]} - Full start command is '$GAMEMODERUN ${GAMESTARTCMD[*]}'"
					startGame "$GMR" "${GAMESTARTCMD[@]}"	
				fi
			# start with gamescope:
			elif [ "$USEGAMESCOPE" -eq 1 ]; then
				writelog "INFO" "${FUNCNAME[0]} - Starting native game '$SGNAID' with $GAMESCOPE arguments '$GAMESCOPE_ARGS'"
				notiShow "$(strFix "$NOTY_STARTNATGAMSCO" "$GN" "$AID")"
				gameArgs "$GAMESCOPE_ARGS"
				writelog "INFO" "${FUNCNAME[0]} - Full start command is '$GAMESCOPE ${GAMEARGSARR[*]} ${GAMESTARTCMD[*]}'"
				startGame "$GSC" "${GAMEARGSARR[@]}" "${GAMESTARTCMD[@]}"

			# regular start:
			else
				writelog "INFO" "${FUNCNAME[0]} - Starting native game '$SGNAID'"
				notiShow "$(strFix "$NOTY_STARTNAT" "$GN" "$AID")"
				writelog "INFO" "${FUNCNAME[0]} - Full start command is '${GAMESTARTCMD[*]}'"
				startGame "${GAMESTARTCMD[@]}"
			fi
		fi

	# now games using proton or wine:
	elif [ "$ISGAME" -eq 2 ]; then
		# Wine:
		if [ "$USEWINE" -eq 1 ]; then
			writelog "INFO" "${FUNCNAME[0]} - Using Wine instead of Proton"
			setWineVars

			RUNGAMECMD="${GAMESTARTCMD[*]}"
			RAWGAMECMD="${RUNGAMECMD#*waitforexitandrun }"
			mapfile -d " " -t -O "${#FINGAMECMD[@]}" FINGAMECMD < <(printf '%s' "$RAWGAMECMD")

			# start with gamemoderun:
			if [ "$USEGAMEMODERUN" -eq 1 ]; then
				if [ "$USEGAMESCOPE" -eq 1 ]; then
					gameArgs "$GAMESCOPE_ARGS"
					notiShow "$(strFix "$NOTY_STARTPROTGAMOSC" "$RUNWINEVERSION" "$GN" "$AID")"
					startWineGame "$GMR" "$GSC" "${GAMEARGSARR[@]}"
					writelog "INFO" "${FUNCNAME[0]} - Started game $GN with '$("$RUNWINE" --version)' using '$GAMEMODERUN' and '$GAMESCOPE' with PID '$WINEPID'"
				else
					notiShow "$(strFix "$NOTY_STARTPROTGAMO" "$RUNWINEVERSION" "$GN" "$AID")"
					startWineGame "$GMR"
					writelog "INFO" "${FUNCNAME[0]} - Started game $GN with '$("$RUNWINE" --version)' using '$GAMEMODERUN' with PID '$WINEPID'"
				fi
			# start with gamescope:
			elif [ "$USEGAMESCOPE" -eq 1 ]; then
				gameArgs "$GAMESCOPE_ARGS"
				notiShow "$(strFix "$NOTY_STARTPROTGAMSCO" "$RUNWINEVERSION" "$GN" "$AID")"
				startWineGame "$GSC" "${GAMEARGSARR[@]}"
				writelog "INFO" "${FUNCNAME[0]} - Started game $GN with '$("$RUNWINE" --version)' using '$GAMESCOPE' with PID '$WINEPID'"
			# regular start:
			else
				notiShow "$(strFix "$NOTY_STARTPROT" "$RUNWINEVERSION" "$GN" "$AID")"
				startWineGame
				writelog "INFO" "${FUNCNAME[0]} - Started game $GN with '$("$RUNWINE" --version)' with PID '$WINEPID'"
			fi

			writelog "INFO" "${FUNCNAME[0]} - Waiting for game PID '$WINEPID' to exit..."
			wait "$WINEPID"

		# Proton:
		else
			# proton variants start here:
		
			if [ "$RUN_GDB" -eq 1 ]; then
				GDBGAMESTARTCMD=("${ORGGCMD[@]}" "${GAMEARGSARR[@]}")
			elif [ "$HAVEINPROTON" -eq 1 ]; then
				writelog "INFO" "${FUNCNAME[0]} - Not overriding Proton and using Proton provided by steam commandline '${INPROTCMD[*]}'"
				GAMESTARTCMD=("${INPROTCMD[@]}" "$WFEAR" "${GAMESTARTCMD[@]}")
			else
				writelog "INFO" "${FUNCNAME[0]} - Proton override enabled, so checking if it needs updated"

				if [ -z "$USEPROTON" ]; then
					writelog "INFO" "${FUNCNAME[0]} - No current Proton found"
					if [ "$AUTOLASTPROTON" -eq 1 ]; then
						writelog "INFO" "${FUNCNAME[0]} - Automatically selecting newest official one"
						setNOP
					fi
				fi

				# the last chance to set the Proton version before starting the game,
				setRunProtonFromUseProton

				# remove prefix if requested 
				delPrefix
				
				# so fixing outdated symlinks if requested
				fixSymlinks
				# and/or unsymlink any proton symlink found
				unSymlink

				if [ "$HAVEINPROTON" -eq 1 ] && [ "${INPROTCMD[*]}" == "$RUNPROTON" ]; then
					writelog "INFO" "${FUNCNAME[0]} - Command line proton '${INPROTCMD[*]}' is identical to RUNPROTON '$RUNPROTON' - nothing to change"
					GAMESTARTCMD=("${INPROTCMD[@]}" "$WFEAR" "${GAMESTARTCMD[@]}")
				else
					if [ ! -f "${RUNPROTON//\"/}" ]; then
						writelog "WARN" "${FUNCNAME[0]} - '$USEPROTON' seems outdated as the executable ${RUNPROTON//\"/} wasn't found"
						fixProtonVersionMismatch "USEPROTON" "$STLGAMECFG"
					fi

					if [ "${GAMESTARTCMD[0]}" == "$WFEAR" ]; then
						# removing first ORGGCMD element as it is '$WFEAR'
						unset "GAMESTARTCMD[0]"
					fi
					
					if [ -f "${RUNPROTON//\"/}" ]; then
						writelog "INFO" "${FUNCNAME[0]} - Prepending Proton '$USEPROTON' (='${RUNPROTON//\"/}') to the command line '${GAMESTARTCMD[*]}'"
						GAMESTARTCMD=("${RUNPROTON//\"/}" "$WFEAR" "${GAMESTARTCMD[@]}")
					else
						writelog "INFO" "${FUNCNAME[0]} - Still don't have a usable proton executable in RUNPROTON '{RUNPROTON//\"/}')"
						if [ "$HAVEINPROTON" -eq 1 ]; then
							writelog "INFO" "${FUNCNAME[0]} - Overriding Proton provided by steam commandline '${INPROTCMD[*]}' from command line with '$USEPROTON' (='${RUNPROTON//\"/}')"
							GAMESTARTCMD=("${INPROTCMD[@]}" "$WFEAR" "${GAMESTARTCMD[@]}")
						else
							writelog "ERROR" "${FUNCNAME[0]} - Could not find any usable proton version - this will likely crash - please open an issue on '$PROJECTPAGE' with this log"
						fi
					fi
				
					writelog "INFO" "${FUNCNAME[0]} - UPDATED game start command is: ${GAMESTARTCMD[*]}"
				fi

				if [ "$USERAYTRACING" -eq 1 ]; then
					writelog "INFO" "${FUNCNAME[0]} - Raytracing is enabled with the variable 'USERAYTRACING' - exporting 'VKD3D_CONFIG=dxr11' and appending '-dx12' to the game command line parameters"
					export VKD3D_CONFIG=dxr11
					GAMESTARTCMD=("${GAMESTARTCMD[@]}" "-dx12")
				fi
			fi
		
############
			# set the definitive used versions, which are also stored into writeLastRun
			PROTONVERSION="$(setProtonPathVersion "$RUNPROTON")"

			# start with x64dbg:
			if [ "$RUN_X64DBG" -eq 1 ]; then
				checkX64dbgLaunch "${GAMESTARTCMD[@]}"
			elif [ "$RUN_GDB" -eq 1 ]; then
				if [ -f "$(command -v "$USETERM")" ]; then
					prepareGdb
					injectGdb &
					writelog "INFO" "${FUNCNAME[0]} - Starting '$SGNAID' using '$GDBGAMERUN' and attaching gdb to the running process"
					writelog "WARN" "${FUNCNAME[0]} - This function might not always work as expected - not sure yet if it is worth to maintain"
					notiShow "$(strFix "$NOTY_STARTPROTGDB" "$PROTONVERSION" "$GN" "$AID")"
					"$GDBGAMERUN"
				else
					writelog "ERROR" "${FUNCNAME[0]} - '$GDB' was enabled, but configured terminal '$USETERM' was not found"
				fi
			elif [ "$RUN_DEPS" -eq 1 ]; then
				checkDepsLaunch "${GAMESTARTCMD[@]}"
			# start with gamemoderun:
			elif [ "$USEGAMEMODERUN" -eq 1 ]; then
				if [ "$USEGAMESCOPE" -eq 1 ]; then
					writelog "INFO" "${FUNCNAME[0]} - Starting '$SGNAID' with Proton: '$PROTONVERSION' with '$GAMEMODERUN' and '$GAMESCOPE'"
					gameArgs "$GAMESCOPE_ARGS"
					notiShow "$(strFix "$NOTY_STARTPROTGAMOSC" "$PROTONVERSION" "$GN" "$AID")"
					writelog "INFO" "${FUNCNAME[0]} - Full start command is '$GAMEMODERUN $GAMESCOPE ${GAMEARGSARR[*]} ${GAMESTARTCMD[*]}'"
					startGame "$GMR" "$GSC" "${GAMEARGSARR[@]}" "${GAMESTARTCMD[@]}"		
				else
					writelog "INFO" "${FUNCNAME[0]} - Starting '$SGNAID' with Proton: '$PROTONVERSION' with '$GAMEMODERUN'"
					notiShow "$(strFix "$NOTY_STARTPROTGAMO" "$PROTONVERSION" "$GN" "$AID")"
					writelog "INFO" "${FUNCNAME[0]} - Full start command is '$GAMEMODERUN ${GAMESTARTCMD[*]}'"
					startGame "$GMR" "${GAMESTARTCMD[@]}"
				fi
			# start with gamescope:
			elif [ "$USEGAMESCOPE" -eq 1 ]; then
				writelog "INFO" "${FUNCNAME[0]} - Starting '$SGNAID' with Proton: '$PROTONVERSION' with $GAMESCOPE arguments '$GAMESCOPE_ARGS'"
				notiShow "$(strFix "$NOTY_STARTPROTGAMSCO" "$PROTONVERSION" "$GN" "$AID")"
				gameArgs "$GAMESCOPE_ARGS"
				writelog "INFO" "${FUNCNAME[0]} - Full start command is '$GAMESCOPE ${GAMEARGSARR[*]} ${GAMESTARTCMD[*]}'"
				startGame "$GSC" "${GAMEARGSARR[@]}" "${GAMESTARTCMD[@]}"		
			# regular start:
			else
				writelog "INFO" "${FUNCNAME[0]} - Starting '$SGNAID' with Proton: '$PROTONVERSION'"
				notiShow "$(strFix "$NOTY_STARTPROT" "$PROTONVERSION" "$GN" "$AID")"
				writelog "INFO" "${FUNCNAME[0]} - Full start command is '${GAMESTARTCMD[*]}'"
				startGame "${GAMESTARTCMD[@]}"
			fi
		fi
	else
		writelog "SKIP" "${FUNCNAME[0]} - With ISGAME '$ISGAME' the game failed to start"
	fi

	writelog "STOP" "######### $PROGNAME $PROGVERS #########"
}

### CORE LAUNCH END ###

### COMMAND LINE START ###

function CompatTool {
	
	SCTS="$STEAMCOMPATOOLS/$PROGNAME"

	if [ "$1" == "add" ] ; then
		if [ -d "$SROOT" ]; then
			if [ ! -d "$STEAMCOMPATOOLS" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Initially creating dir '$STEAMCOMPATOOLS'"
				mkProjDir "$STEAMCOMPATOOLS"
			fi

			if [ ! -d "$SCTS" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Creating dir '$SCTS'"
				mkProjDir "$SCTS"

				CVDF="$SCTS/$CTVDF"
				writelog "INFO" "${FUNCNAME[0]} - Creating file '$CVDF'"
				{
				echo "\"compatibilitytools\""
				echo "{"
				echo "  \"compat_tools\""
				echo "  {"
				echo "	\"Proton-${SHOSTL}\" // Internal name of this tool"
				echo "	{"
				echo "	  \"install_path\" \".\""
				echo "	  \"display_name\" \"$NICEPROGNAME\""
				echo ""
				echo "	  \"from_oslist\"  \"windows\""
				echo "	  \"to_oslist\"    \"linux\""
				echo "	}"
				echo "  }"
				echo "}"
				} >> "$CVDF"

				TVDF="$SCTS/toolmanifest.vdf"
				writelog "INFO" "${FUNCNAME[0]} - Creating file '$TVDF'"
				{
				echo "\"manifest\""
				echo "{"
				echo "  \"commandline\" \"/$PROGCMD run\""
				echo "  \"commandline_$WFEAR\" \"/$PROGCMD $WFEAR\""
				echo "}"
				} >> "$TVDF"

				writelog "INFO" "${FUNCNAME[0]} - Creating symlink '$SCTS/$PROGCMD' pointing to '$0'" "E"
				ln -s "$(realpath "$0")" "$SCTS/$PROGCMD"
			else
				writelog "INFO" "${FUNCNAME[0]} - '$SCTS' already exists - checking if '$PROGCMD' symlink needs to be updated"
				if [ "$(readlink "$SCTS/$PROGCMD")" == "$(realpath "$0")" ]; then
					writelog "SKIP" "${FUNCNAME[0]} - Nothing to do the '$SCTS/$PROGCMD' symlink still points to '$0'" "E"
				else
					rm "$SCTS/$PROGCMD"
					ln -s "$(realpath "$0")" "$SCTS/$PROGCMD"
					writelog "SKIP" "${FUNCNAME[0]} - Updated the '$SCTS/$PROGCMD' symlink to '$0'" "E"
				fi
			fi
		else
			writelog "SKIP" "${FUNCNAME[0]} - Steam Home Dir '$SROOT' not found!"
		fi
	elif [ "$1" == "del" ]; then
		if [ ! -d "$SCTS" ]; then
			writelog "SKIP" "${FUNCNAME[0]} - Selected '$1' but '$SCTS' doesn't exist"
		else
			rm "$SCTS/$PROGCMD" 2>/dev/null
			find "$SCTS" -maxdepth 1 -type f -name "*.vdf" -exec rm {} \;
			rmdir "$SCTS"
			if [ ! -d "$SCTS" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Removed '$SCTS' successfully" "E"
			else
				writelog "SKIP" "${FUNCNAME[0]} - Tried to carefully remove '$SCTS', but it still exists - any files inside '$SCTS'?" "E"
			fi
		fi
	else
		if [ ! -d "$SCTS" ]; then
			writelog "INFO" "${FUNCNAME[0]} - '$PROGNAME' is not installed as Steam Compatibility Tool in '$STEAMCOMPATOOLS'" "E"
		else
			writelog "INFO" "${FUNCNAME[0]} - '$PROGNAME' is installed as Steam Compatibility Tool in '$STEAMCOMPATOOLS' and points to '$(readlink "$SCTS/$PROGCMD")'" "E"
		fi
	fi
}

function setRunProtonFromUseProton {
	if [ -n "$USEPROTON" ]; then
		NRUNPROTON="$(getProtPathFromCSV "$USEPROTON")"

		if [ -n "$RUNPROTON" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Setting ORUNPROTON to '$RUNPROTON'"
			ORUNPROTON="$RUNPROTON"
		fi

		if [ -n "$ORUNPROTON" ] && [ "$ORUNPROTON" == "$NRUNPROTON" ]; then
			writelog "SKIP" "${FUNCNAME[0]} - RUNPROTON '$RUNPROTON' hasn't changed"
		elif [ -n "$NRUNPROTON" ]; then
			if [ -z "$ORUNPROTON" ] || [ "$ORUNPROTON" == "" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Initially setting RUNPROTON for USEPROTON '$USEPROTON' to '$NRUNPROTON'"
			else
				writelog "INFO" "${FUNCNAME[0]} - Updating RUNPROTON for USEPROTON '$USEPROTON' from '$ORUNPROTON' to '$NRUNPROTON'"
			fi
			RUNPROTON="$NRUNPROTON"
			writelog "INFO" "${FUNCNAME[0]} - Set RUNPROTON to '$RUNPROTON'"
		fi
	else
		writelog "SKIP" "${FUNCNAME[0]} - USEPROTON is empty"
	fi
}

function checkStartMode {
	if [ -n "${ORGGCMD[0]}" ]; then

		writelog "INFO" "${FUNCNAME[0]} - LoadCfg: $STLGAMECFG"
		loadCfg "$STLGAMECFG"

		if [ "$ISGAME" -eq 2 ]; then
			if [ -n "$USEWINE" ] && [ "$USEWINE" -eq 1 ]; then
				writelog "SKIP" "${FUNCNAME[0]} - USEWINE is enabled - skipping this function"
			elif grep -q "USEWINE=\"1\"" "$STLGAMECFG" ; then
				writelog "SKIP" "${FUNCNAME[0]} - USEWINE is enabled in the to-be-loaded gameconfig '$STLGAMECFG' - skipping this function"
				EARLYUSEWINE=1
				# could still be enabled via steamcategory, but this would be an overkill here, as ${FUNCNAME[0]} is non-fatal
			else
				if [ "$HAVEINPROTON" -eq 1 ]; then
					writelog "INFO" "${FUNCNAME[0]} - Game was started via '$SLO' ('$PROGCMD %command%'),"
					writelog "INFO" "${FUNCNAME[0]} - because a Proton path was found in the command line provided by steam"
					writelog "INFO" "${FUNCNAME[0]} - Override Proton is disabled, when using $PROGCMD as '$SLO', so using it as-is: '${INPROTCMD[*]}'"
					writelog "INFO" "${FUNCNAME[0]} - (ignoring USEPROTON '$USEPROTON' from game config)"
					RUNPROTON="${INPROTCMD[*]}"
					writelog "INFO" "${FUNCNAME[0]} - Set RUNPROTON to '$RUNPROTON'"

					USEPROTON="$INPROTV"
					writelog "INFO" "${FUNCNAME[0]} - Set USEPROTON to '$USEPROTON'"
				else
					writelog "INFO" "${FUNCNAME[0]} - Game was started as Steam Compatibility Tool - automatically enabling override Proton,"
					writelog "INFO" "${FUNCNAME[0]} - as proton doesn't appear in the command line here"
					setRunProtonFromUseProton
				fi

				writelog "INFO" "${FUNCNAME[0]} - Continuing with RUNPROTON='$RUNPROTON'"

				if [ -n "$RUNPROTON" ]; then
					CHECKWINE="$(dirname "$RUNPROTON")/$DBW"

					if [ -f "$CHECKWINE" ]; then
						RUNWINE="$CHECKWINE"
						writelog "INFO" "${FUNCNAME[0]} - Set the wine binary for proton in path '$RUNPROTON' to '$RUNWINE'"
					else
						writelog "WARN" "${FUNCNAME[0]} - Couldn't find the wine binary for the proton in path '$RUNPROTON'"
					fi

					PROTONVERSION="$(setProtonPathVersion "$RUNPROTON")"
				fi
			fi
		fi
	fi
}

function getDefaultProton {
	if [ -n "$INPROTV" ]; then
		echo "$INPROTV"
	else
		getNOP "v"
	fi
}

function FUSEID {
	if [ -n "$1" ]; then
		USEID="$1"
	else
		USEID="$AID"
	fi

	if [ "$USEID" == "$PLACEHOLDERAID" ]; then
		if [ -f "$LASTRUN" ]; then
			PREVAID="$(grep "^PREVAID" "$LASTRUN" | cut -d '=' -f2)"
			if [ -n "$PREVAID" ]; then
				USEID="${PREVAID//\"}"
				PREVGAME="$(grep "^PREVGAME" "$LASTRUN" | cut -d '=' -f2)"
				if [ -n "$PREVGAME" ]; then
					GN="${PREVGAME//\"}"
				fi
			fi
		fi
	fi

	if [ -f "$LOGDIR/$USEID.log" ]; then
		rm "$LOGDIR/$USEID.log"
	fi
	resetAID "$USEID"
	setGN "$USEID"
}

function howto {
	echo "========================="
	echo "$PROGNAME $PROGVERS"
	echo "========================="
	echo "Usage: $PROGCMD [options]..."
	echo ""
	echo "where options include:"
	echo "    addcustomproton|acp <path>       Adds local custom Proton to"
	echo "                                       the internal list from dialog"
	echo "                                       or directly from <path>"
	echo "    addnonsteamgame|ansg <args>      Add a $NSGA to Steam"
	echo "                                       opens gui without args"
	echo "      <args>:                          for cli min arg is'-ep'"
	echo "      -an=|--appname=	                 App Name - optional"
	echo "      -ep=|--exepath=                  Full gamepath required"
	echo "      -sd=|--startdir=                 Start Dir - optional"
	echo "      -ip=|--iconpath=                 Icon Path - optional"
	echo "      -lo=|--launchoptions             Game Launch Options - optional"
	echo "      -hd=|--hide=                     Hide Game - optional*"
	echo "      -adc=|--allowdesktopconf=        Allow Desktop Conf - optional"
	echo "      -ao=|--allowoverlay=             Allow Overlay - optional"
	echo "      -vr=|--openvr=                   OpenVR - optional*"
	echo "      -t=|--tags=                      Tags - quoted, comma-separated"
	echo "      -stllo|--stllaunchoption         Use '${PROGCMD} %command%' as Launch Option"
	echo "    backup <value>                   Backup found '$STUS' files"
	echo "                                       (for 'SteamAppID' or 'all')"
	echo "    block                            Opens the category Block selection menu"
	echo "    compat <cmd>                     Will (add|del|get) ${PROGNAME,,} as" 
	echo "                                       Steam compatibility tool"
	echo "                                       under 'STEAMCOMPATOOLS'"
	echo "    createcompatdata|ccd <gameid><gui> (Re-)create compatdata for <gameid>"
	echo "                                       open <gui> to configure custom programs"
	echo "    createdesktopicon|cdi <game><id> Create desktop icon for <game>"
	echo "                                       <game> is the gameid or"
	echo "                                       with available meta game title"
	echo "                                       0=only internally"
	echo "                                       1=on the desktop"
	echo "                                       2=for the application menu"
	echo "                                       3=for desktop and application menu"
	echo "    createappinfo|cai <id|i|o>       Create raw appinfo for <id>"
	echo "                                      or for 'installed|i' or 'owned|o' games"
	echo "                                      Append any arg to update the raw file"
	echo "                                      (takes a long time for many games!)"
	echo "    createappinfometa|caim <id|i|o>  Read data from raw appinfo for <id>"
	echo "                                      or for 'installed|i' or 'owned|o' games"
	echo "                                      and write to game metadata."
	echo "                                      Append any arg to update the metadata"
	echo "                                      (takes a long time for many games!)"
	echo "    createfirstinstall|cfi <gameid>  Open gui to create a Steam First Time Setup" 
	echo "    <a|c|r|file> (see wiki)            file for game <gameid>"
	echo "    ${DPRS,}|dprs                    Prepare/launch ${DPRS}"
	echo "    dlcustomproton|dcp <url|l>       Download/install custom Proton"
	echo "                                       - from filerequester"
	echo "                                       - directly from <url>"
	echo "                                       - the 'latest|l' GE version"
	echo "                                       - 'latestge|lge' for Proton-GE"
	echo "                                       - 'latesttkg|ltkg' for Proton-TKG"
	echo "    dlwine|dw <url or latest|l>      Download/install Wine archive"
	echo "                                       from filerequester or"
	echo "                                       automatically the latest|l version or"
	echo "                                       directly from <url>"
	echo "    editor <value>                   Opens the editor menu"
	echo "                                       (for 'SteamAppID' or 'last')"
	echo "    fav <value>                      Opens the favorite menu"
	echo "                                       (for 'SteamAppID' or 'last')"
	echo "    gamefiles|gf <gameid>            Opens menu for opening <gameid> files"
	echo "    gamescope|gs <gameid>            Gamescope config-menu for <gameid>"
	echo "    (get commands only for games known by ${PROGNAME,,}:)"
	echo "    getexe|ge <gameid>               Print the Game Exe for <gameid>"
	echo "    getid|gi <gametitle>             Print the SteamAppId for <gametitle>"
	echo "    gettitle|gt <gameid>             Print the Game Title for <gameid>"
	echo "    getcompatdata|gc <gameid/title>  Print the Game compatdata path"
	echo "    getgamedir|gg <gameid/title>     Print the Game dir"
	echo " "
	echo "    lang=<option>                    Mostly to get translated configs"
	echo "                                       on inital setup. <option> can be"
	echo "                                       a language file name without suffix"
	echo "                                       or an path to a valid language file"
 	echo "    launcher <args>                  Start the Game Launcher"
	echo "             CATEGORY                  Show only installed games"
	echo "                                       from Steam Category CATEGORY"
	echo "             menu                      Open Steam Category Menu"
	echo "             last                      Open last Game as 'Menu'"
	echo "             auto                      Create/Download data for all"
	echo "                                       installed games first"
	echo "             update                    ReCreate all Category Menus"
	echo "                                       Can be combined with auto"
	echo "    list <owned|installed>           List ids of <owned|o,installed|i> games"
	echo "    meta                             Generates/Updates metadata"
	echo "                                       for all installed games"
	echo "    mo2                              Mod Organizer 2"
	echo "         install|i                   install MO2 (includes download)"
	echo "         download|d                  download latest MO2 release"
	echo "         start|s                     start MO2 (includes download+install)"
	echo "         list-supported|ls           list games supported by MO2"
	echo "         list-installed|li           list installed games supported by MO2"
	echo "         create-instance|ci <id>     create MO2 instance for <id>"
	echo "         url|u <url>                 open nxm url with MO2"
 	echo "    proton|p <title> <X>             Start and/or create <title> with proton"
	echo "                                       without using steam."
	echo "                                       Optional <X> opens gui"
	echo "    set <var> <for> <value>          Change configuration settings"
	echo "                                       Example:"
	echo "    set RUN_REPLAY all 1               Set RUN_REPLAY for all games to 1"
	echo "    settings <value>                 Opens the $SETMENU"
	echo "                                       (for 'SteamAppID' or 'last')"
	echo "    src                              Shortcut '$STERECO'"
	echo "    steamworksshared|sws <opts>      Steamworks Shared:"
	echo "      <opts>:                          Options:"
	echo "      <l>                              List packages - or"
	echo "      <i>                              Install package with options:"
	echo "      <packagename>                    - packagename"
	echo "      <SteamAppID or pfx>              - SteamAppID or pfx path"
	echo "      <wine binary>                    - Optional wine binary path"
	echo "    update <value>                   Updates <value>:"
	echo "           gamedata <SteamAppID>       Updates missing desktopfiles"
	echo "                                       and pictures of installed games"
	echo "                                       or only from <SteamAppID>"
	echo "           grid <SteamAppID>         Update Steam Grid for installed game(s)"
	echo "                                       optional argument either a SteamAppID,"
	echo "                                       'owned' or 'installed'"
	echo "                                       (default is 'installed')"
	echo "           allgamedata                 The same as above for"
	echo "                                       all games in $SCV"
	echo "           shaders <shadername>        all enabled shaders or <shadername>"
	echo "                                       'list' to list shaders"
	echo "                                       'repos' to update used shader repos"
	echo "           gameshaders <opt1> <opt2|3> open shader selection for dir <opt1>,"
	echo "                                       for last gamedir when <opt1> is empty"
	echo "                                       enable repo <opt1> for dir <opt2>"
	echo "                                        with empty <opt3> or <opt3>=enable"
	echo "                                       disable repo <opt1> for dir <opt2>"
	echo "                                        with  <opt3>=disable"
	echo "                                       block repo <opt1> with <opt2>=block"
	echo "                                       unblock repo <opt1> with <opt2>=unblock"
	echo "           reshade <version>           (re)-download ReShade (version)"
	echo "    version                          Output the program version"
	echo "    ${VTX} <value>                   ${VTX^} commandline options"
	echo "           install                     Installs ${VTX^}"
	echo "           list-supported|ls           List all ${VTX^}-supported Steam Game IDs"
	echo "                                       (offline - ${VTX^} needs to be installed)"
	echo "           list-online|lo              List ${VTX^}-supported games found online"
	echo "           list-owned|low              List owned games with ${VTX^} support"
	echo "           list-installed|li           List installed Games with ${VTX^} support"
	echo "           games                       Gui to en/disable ${VTX^} for supported game"
	echo "           symlinks                    Gui showing ${VTX^} symlinks"
	echo "           start                       Starts ${VTX^}"
	echo "           url|u <url>                 Open nxm url with ${VTX^}"
	echo "           getset                      Show config of installed ${VTX^}"
	echo "           reset                       Reset all autodetected settings in ${VTX^}"
	echo "           stage <path>                Add ${VTX^} stage via dialog"
    echo "                                       or directly the one given in <path>"
	echo "    vr <windowname> <SteamAppID> <s> Start SBS-VR mode for <windowname>"
	echo "                                       and game <SteamAppID>"
	echo "                                       's'ave windowname for the game"
	echo "    wiki <page>                      Opens the wiki <page> in yad"
	echo "    yad <yad binary> <opt>           Configure the used Yad binary"
	echo "                                       <yad binary> can be either"
	echo "                                       <absolute/path>"
	echo "                                       <conty>"
	echo "                                       <ai> or <appimage> plus optional <opt>:"
	echo "                                       <opt> can be either"
	echo "                                         <absolute/path/to/a/yad/appimage>"
	echo "                                         <http/s/yad/appimage/download/url>"
	echo "                                       (see Wiki for details)"
}

#STARTCMDLINE
function commandline {
	if [ "$1" == "addcustomproton" ] || [ "$1" == "acp" ]; then
		addCustomProton "$2" "$3"
	elif [ "$1" == "addnonsteamgame" ] || [ "$1" == "ansg" ] ; then
		if [ -z "$2" ]; then
			addNonSteamGameGui "$NON"
		else
			if grep -q "ep=\|--exepath=" <<< "$*"; then
				if grep -q "gui" <<< "$*"; then
					addNonSteamGameGui "$@"
				else
					addNonSteamGame "$@"
				fi
			else
				writelog "INFO" "${FUNCNAME[0]} - Command line parameters insufficent - starting the Gui"
				addNonSteamGameGui "$NON"
			fi
		fi
	elif [ "$1" == "backup" ]; then
		if [ "$2" == "all" ]; then
			backupSteamUserGate "$2"
		else
			FUSEID "$2"
			backupSteamUserGate "$USEID"
		fi
	elif [ "$1" == "block" ]; then
		FUSEID "$2"
		setGuiBlockSelection "$USEID"
	elif [ "$1" == "sort" ]; then
		setGuiSortOrder
	elif [ "$1" == "compat" ]; then
		if [ -n "$2" ]; then
			if [ "$2" == "add" ] || [ "$2" == "del" ] || [ "$2" == "get" ]; then
				CompatTool "$2"
			else
				howto
			fi
		else
			CompatTool "get"
		fi
	elif [ "$1" == "conty" ]; then
		if [ -n "$2" ]; then
			if [ "$2" == "up" ] || [ "$2" == "update" ]; then
				updateConty
			fi
		fi
	elif [ "$1" == "createcompatdata" ] || [ "$1" == "ccd" ]; then
		FUSEID "$2"
		writelog "INFO" "${FUNCNAME[0]} - Starting Install via command: reCreateCompatdata \"$1\" \"$USEID\" \"$3\""
		reCreateCompatdata "$1" "$USEID" "$3"
	elif [ "$1" == "createdesktopicon" ] || [ "$1" == "cdi" ]; then
		if [ "$2" == "all" ]; then
			if [ "$(listInstalledGameIDs | wc -l)" -eq 0 ]; then
				writelog "SKIP" "${FUNCNAME[0]} - No installed games found!" "E"
			else
				while read -r CATAID; do
					createDesktopIconFile "$CATAID" "$3"
				done <<< "$(listInstalledGameIDs)"
			fi
		else
			FUSEID "$2"
			createDesktopIconFile "$USEID" "$3"
		fi
	elif [ "$1" == "createappinfo" ] || [ "$1" == "cai" ]; then
		if [ "$2" == "installed" ] || [ "$2" == "i" ]; then
			if [ "$(listInstalledGameIDs | wc -l)" -eq 0 ]; then
				writelog "SKIP" "${FUNCNAME[0]} - No installed games found!" "E"
			else
				while read -r CATAID; do
					getRawAppIDInfo "$CATAID" "$3"
				done <<< "$(listInstalledGameIDs)"
			fi
		elif [ "$2" == "owned" ] || [ "$2" == "o" ]; then
			while read -r CATAID; do
				getRawAppIDInfo "$CATAID" "$3"
			done <<< "$(getOwnedAids)"
		else
			FUSEID "$2"
			getRawAppIDInfo "$USEID" "$3"
		fi
	elif [ "$1" == "createappinfometa" ] || [ "$1" == "caim" ]; then
		if [ -n "$2" ]; then
			if [ "$2" == "installed" ] || [ "$2" == "i" ]; then
				if [ "$(listInstalledGameIDs | wc -l)" -eq 0 ]; then
					writelog "SKIP" "${FUNCNAME[0]} - No installed games found!" "E"
				else
					while read -r CATAID; do
						writeAllAIMeta "$CATAID" "$3"
					done <<< "$(listInstalledGameIDs)"
				fi
			elif [ "$2" == "owned" ] || [ "$2" == "o" ]; then
				while read -r CATAID; do
					writeAllAIMeta "$CATAID" "$3"
				done <<< "$(getOwnedAids)"
			else
				if [ "$2" -eq "$2" ]; then
					FUSEID "$2"
					writeAllAIMeta "$USEID" "$3"
				fi
			fi
		else
			writelog "INFO" "${FUNCNAME[0]} - need at least 'installed|i' or 'owned|o' or a SteamAppId as arg2" "E"
		fi
	elif [ "$1" == "createfirstinstall" ] || [ "$1" == "cfi" ]; then
		FUSEID "$2"
		CreateCustomEvaluatorScript "$USEID"
	elif [ "$1" == "${DPRS,}" ] || [ "$1" == "dprs" ]; then
		startDepressurizer
	elif [ "$1" == "dlcustomproton" ] || [ "$1" == "dcp" ]; then
		dlCustomProtonGate "$2"
	elif [ "$1" == "dlwine" ] || [ "$1" == "dw" ]; then
		dlWineGate "$2"
	elif [ "$1" == "dxvkhud" ] || [ "$1" == "dxh" ]; then
		FUSEID "$2"
		DxvkHudPick "$USEID"
	elif [ "$1" == "dotnet" ]; then
		if [ -n "$3" ]; then
			installDotNet "$2" "$3" "$4"
		else
			writelog "INFO" "${FUNCNAME[0]} - need at least a winepfx as arg2 '$2' and a wine binary as arg3" "E"
			#howto
		fi
	elif [ "$1" == "editor" ]; then
		FUSEID "$2"
		EditorDialog "$USEID"		
	elif [ "$1" == "fav" ]; then
		FUSEID "$2"
		if [ -n "$3" ] && [ "$3" == "set" ]; then
			setGuiFavoritesSelection "$USEID"
		else
			openTrayIcon
			favoritesMenu "$USEID"
			cleanYadLeftOvers
		fi
	elif [ "$1" == "gamefiles" ] || [ "$1" == "gf" ]; then
		FUSEID "$2"
		GameFilesMenu "$USEID"	
	elif [ "$1" == "gamescope" ] || [ "$1" == "gs" ]; then
		FUSEID "$2"
		GameScopeGui "$USEID" "$3"
	elif [ "$1" == "getexe" ] || [ "$1" == "ge" ]; then
		getExeFromID "$2"
	elif [ "$1" == "getid" ] || [ "$1" == "gi" ]; then
		getIDFromTitle "$2"
	elif [ "$1" == "gettitle" ] || [ "$1" == "gt" ]; then
		getTitleFromID "$2"
	elif [ "$1" == "getcompatdata" ] || [ "$1" == "gc" ]; then
		getCompatData "$2"
	elif [ "$1" == "getgamedir" ] || [ "$1" == "gg" ]; then
		getGameDir "$2"
	elif [ "$1" == "help" ] || [ "$1" == "--help" ]; then
		howto
	elif [ "$1" == "helpurl" ] || [ "$1" == "hu" ]; then
		FUSEID "$2"
		HelpUrlMenu "$USEID"
		if [ -z "$3" ]; then
			rm "$STLSHM/KillBrowser-$AID.txt" 2>/dev/null
		fi
	elif [ "$1" == "launcher" ]; then
		openGameLauncher "$2" "$3"
	elif [ "$1" == "list" ]; then
		if [ "$2" == "owned" ] || [ "$2" == "o" ]; then
			getOwnedAids
		elif [ "$2" == "installed" ] || [ "$2" == "i" ]; then
			if [ "$(listInstalledGameIDs | wc -l)" -eq 0 ]; then
				writelog "SKIP" "${FUNCNAME[0]} - No installed games found!" "E"
			else
				listInstalledGameIDs
			fi
		elif [ "$2" == "appmanifests" ] || [ "$2" == "am" ]; then
			listAppManifests
		fi
	elif [ "$1" == "meta" ]; then
		createMetaData "yes"
	elif [ "$1" == "mo2" ]; then
		if [ -n "$2" ]; then
			if [ "$2" == "download" ] || [ "$2" == "d" ]; then
				dlLatestMO2
			elif [ "$2" == "install" ] || [ "$2" == "i" ]; then
				StatusWindow "$(strFix "$NOTY_INSTSTART" "$MO")" "installMO2" "InstallMO2Status"
			elif [ "$2" == "start" ] || [ "$2" == "s" ]; then
				startMO2
			elif [ "$2" == "list-supported" ] || [ "$2" == "ls" ]; then
				listMO2Games
			elif [ "$2" == "list-installed" ] || [ "$2" == "li" ]; then
				setMO2Vars
				prepAllMO2Games "li"
			elif [ "$2" == "create-instance" ] || [ "$2" == "ci" ]; then
				if [ -z "$3" ] || [ "$3" == "all" ]; then
					createAllMO2Instances
				else
					manageMO2GInstance "$3"
				fi
			elif [ "$2" == "url" ] || [ "$2" == "u" ]; then
				dlMod2nexurl "$3"
			else
				writelog "INFO" "${FUNCNAME[0]} - arg2 '$2' is no valid command"
				howto
			fi
		else
			echo "need arg2"
			howto
		fi
	elif [ "$1" == "noty" ]; then
		if [ -n "$2" ]; then
			NTEXT="$2"
		else
			NTEXT="notifier test"
		fi
		notiShow "$NTEXT"
	elif [ "$1" == "onetimerun" ] || [ "$1" == "otr" ]; then
		FUSEID "$2"
		OneTimeRunGui "$USEID"
	elif [ "$1" == "pdb" ]; then
		getProtonDBRating "$2"
	elif [ "$1" == "pickwin" ] || [ "$1" == "pw" ]; then
		pickGameWindowNameMeta "$2" "$3"
	elif [ "$1" == "play" ]; then
		if [ -z "$2" ]; then
			writelog "INFO" "${FUNCNAME[0]} - need at a valid game name or SteamAppId of an installed game or an absolute path to a game exe as arg2 '$2' or 'gui' for a menu" "E"
		else
			if [ "$2" == "gui" ]; then
				standaloneLaunch
			elif [ "$2" == "ed" ]; then
				standaloneEd "${@:3}"
			elif [ "$2" == "list" ]; then
				standaloneGames l
			else
				initPlay "${@:2}"
			fi
		fi
	elif [ "$1" == "proton" ] || [ "$1" == "p" ]; then
		StandaloneProtonGame "$2" "$3"
	elif [ "$1" == "set" ]; then
		if [ -n "$2" ]; then
				ENTLIST="$(sed -n "/#STARTsaveCfgdefault_template/,/#ENDsaveCfgdefault_template/p;/#ENDsaveCfgdefault_template/q" "$0" | grep "echo" | grep "=" | cut -d '"' -f2 | cut -d '=' -f1 | sed 's/^#//')"
				if ! grep "$2" <<< "$ENTLIST" >/dev/null; then
					writelog "INFO" "${FUNCNAME[0]} - '$2' is no valid entry - valid are:" "E"
					writelog "INFO" "${FUNCNAME[0]} ------------------------" "E"
					writelog "INFO" "${FUNCNAME[0]} - $ENTLIST" "E"
					writelog "INFO" "${FUNCNAME[0]} ------------------------" "E"
					exit
				fi
			if [ -n "$3" ]; then
				if [ -z "$4" ]; then
					writelog "INFO" "${FUNCNAME[0]} - argument 4 is missing - exit" "E"
					exit
				else
					if [ "$3" == "all" ]; then
						writelog "INFO" "${FUNCNAME[0]} - arg3 is all - updating all config files in '$STLGAMEDIRID':" "E"
						while read -r file; do
							writelog "INFO" "${FUNCNAME[0]} - updating entry '$2' to value '$4' in config $file" "E"
							touch "$FUPDATE"
							updateConfigEntry "$2" "$4" "$file"
						done <<< "$(find "$STLGAMEDIRID" -name "*.conf")"
					else
						if [ -f "$STLGAMEDIRID/$3.conf" ]; then
							writelog "INFO" "${FUNCNAME[0]} - updating entry '$2' to value '$4' in config '$STLGAMEDIRID/$3.conf'" "E"
							touch "$FUPDATE"
							updateConfigEntry "$2" "$4" "$STLGAMEDIRID/$3.conf"
						else
							writelog "INFO" "${FUNCNAME[0]} - config file '$STLGAMEDIRID/$3.conf' does not exist - nothing to do - exit" "E"
							exit
						fi
					fi
				fi
			else
				writelog "INFO" "${FUNCNAME[0]} - arg3 is missing, you need to provide either the SteamAppId of the game or 'all' to batch update all game configs with the chosen entry!" "E"
				exit
			fi
		else
			writelog "INFO" "${FUNCNAME[0]} - arg2 is missing, you need to provide a valid config entry which should be updated!" "E"
			exit
		fi
	elif [ "$1" == "settings" ]; then
		startSettings "$2"
	elif [ "$1" == "src" ]; then
			"$STEAM" "${STEAM}://${RECO}"
	elif [ "$1" == "steamworksshared" ] || [ "$1" == "sws" ]; then
		if [ -n "$2" ]; then
			if [ "$2" == "install" ] || [ "$2" == "i" ]; then
				if [ -n "$4" ]; then
				installSteWoShPak "$3" "$4" "$5"
				else
					writelog "INFO" "${FUNCNAME[0]} - Need at least package name as arg 3 and a wineprefix OR a SteamAppID as arg 4" E
					writelog "INFO" "${FUNCNAME[0]} - and optionally an absolute path to to a wine binary as arg 5" E
				fi
			elif [ "$2" == "list" ] || [ "$2" == "l" ]; then
				listSteWoShPaks
			else	
				writelog "INFO" "${FUNCNAME[0]} - arg2 '$2' is no valid command"
				howto
			fi
		else
			echo "need arg2"
			howto
		fi
	elif [ "$1" == "${SPEK,,}" ]; then
		if [ -n "$2" ]; then
			if [ "$2" == "download" ] || [ "$2" == "dl" ]; then
				dlSpecialK "$3"
			else
				howto
			fi
		else
			howto
		fi
	elif [ "$1" == "update" ]; then
		if [ -n "$2" ]; then
			if [ "$2" == "gamedata" ]; then
				if [ -z "$3" ]; then
					getGameDataForInstalledGames
				else
					echo getGameData "$3"
					getGameData "$3"
				fi
			elif [ "$2" == "grid" ]; then
				if [ -z "$3" ]; then
					getGridsForOwnedGames
				elif [ "$3" == "owned" ]; then
					getGridsForOwnedGames
				elif [ "$3" == "installed" ]; then
					getGridsForInstalledGames				
				else
					getGrids "$3"
				fi
			elif [ "$2" == "allgamedata" ]; then
				getDataForAllGamesinSharedConfig
			elif [ "$2" == "shader" ] || [ "$2" == "shaders" ]; then
				StatusWindow "$GUI_DLSHADER" "dlShaders $3"  "DownloadShadersStatus"
			elif [ "$2" == "gameshader" ] || [ "$2" == "gameshaders" ]; then
				if [ -z "$3" ]; then
					writelog "INFO" "${FUNCNAME[0]} - No game directory in argument 3 provided - using last game!"
					GameShaderDialog
				else
					if [ -d "$3" ]; then
						writelog "INFO" "${FUNCNAME[0]} - command line: GameShaderDialog \"$3\""
						GameShaderDialog "$3"
					else
						if [ -n "$4" ]; then
							if [ -d "$4" ]; then
								if [ -n "$5" ] && [ "$5" == "disable" ]; then
									disableThisGameShaderRepo "$3" "$4"
								else
									enableThisGameShaderRepo "$3" "$4"
								fi
							elif [ "$4" == "block" ]; then
								echo "$3" >> "$SHADERREPOBLOCKLIST"
								sort -u "$SHADERREPOBLOCKLIST" -o "$SHADERREPOBLOCKLIST"
							elif [ "$4" == "unblock" ]; then
								grep -v "^${3}$" "$SHADERREPOBLOCKLIST" > "$STLSHM/SHADERREPOBLOCKLIST_tmp.txt"
								mv "$STLSHM/SHADERREPOBLOCKLIST_tmp.txt" "$SHADERREPOBLOCKLIST"
							else
								writelog "SKIP" "${FUNCNAME[0]} - Invalid argument '$4' - exit"
							fi
						else
							writelog "SKIP" "${FUNCNAME[0]} - Game directory '$3' does not exist - exit"
						fi
					fi
				fi
			elif [ "$2" == "reshade" ]; then
				dlReShade "$3"
			else
				howto
			fi
		else
			howto
		fi
	elif [ "$1" == "version" ]; then
		echo "${PROGNAME,,}-${PROGVERS}"
	elif [ "$1" == "$VTX" ]; then
		USEVORTEX=1
		if [ -n "$2" ]; then
			if [ "$2" == "install" ] || [ "$2" == "i" ]; then
				if [ -n "$3" ] && [ "$3" == "gui" ]; then
					installVortexGui
				else
					StatusWindow "$(strFix "$NOTY_DLCUSTOMPROTON" "${VTX^}")" "dlLatestVortex S" "DownloadVortexStatus"
					StatusWindow "$(strFix "$NOTY_INSTSTART" "${VTX^}")" "installVortex" "InstallVortexStatus"
				fi
			elif [ "$2" == "start" ]; then
				startVortex "noask" "$3"
			elif [ "$2" == "url" ] || [ "$2" == "u" ]; then
				startVortex "noask" "url" "$3"
			elif [ "$2" == "getset" ]; then
				startVortex "noask" "$2"
			elif [ "$2" == "gui" ]; then
				VortexOptions
			elif [ "$2" == "reset" ]; then
				resetVortexSettings
			elif [ "$2" == "stage" ]; then
				addVortexStage "$3"
			elif [ "$2" == "list-supported" ] || [ "$2" == "ls" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Games With ${VTX^} Support found in the ${VTX^} installation:" "E"
				getVortexSupported X
			elif [ "$2" == "list-online" ] || [ "$2" == "lo" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Games With ${VTX^} Support listed online:" "E"
				dlVortexSupportedList
			elif [ "$2" == "list-owned" ] || [ "$2" == "low" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Games owned with ${VTX^} Support:" "E"
				VORTEXGAMES="$GLOBALMISCDIR/$VOGAT"
				while read -r line; do
					grep "\"$line\"" "$VORTEXGAMES"
				done <<< "$(getOwnedAids)"
			elif [ "$2" == "list-installed" ] || [ "$2" == "li" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Installed Games With ${VTX^} Support"
				setVortexVars
				while read -r line ;do echo -ne "$line;"; getTitleFromID "$line"; done <<< "$(getInstalledGamesWithVortexSupport X)"
			elif [ "$2" == "games" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Opening Gui for en/disabling ${VTX^} for installed and supported games"
				VortexGamesDialog
			elif [ "$2" == "symlinks" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Opening Gui showing Symlinks in the ${VTX^} WINEPREFIX"
				VortexSymDialog
			elif [ "$2" == "download" ] || [ "$2" == "d" ]; then
				StatusWindow "$(strFix "$NOTY_DLCUSTOMPROTON" "${VTX^}")" "dlLatestVortex S" "DownloadVortexStatus"
			else	
				writelog "INFO" "${FUNCNAME[0]} - arg2 '$2' is no valid command"
				howto
			fi
		else
			echo "need arg2"
			howto
		fi
	elif [ "$1" == "vr" ]; then
		if [ -n "$3" ]; then
			GAMEWINDOW="$2"
			AID="$3"
			setAIDCfgs
			if [ -n "$4" ] && [ "$4" == "s" ]; then
				storeGameWindowNameMeta "$(getGameWinNameFromXid "$2")"
			fi
			checkSBSVRLaunch "$2" 
		else
			howto
		fi
	elif [ "$1" == "wiki" ]; then
		OpenWikiPage "$2"
	elif [ "$1" == "winetricks" ] || [ "$1" == "wt" ]; then
		FUSEID "$2"
		chooseWinetricksPrefix "$USEID"
	elif [ "$1" == "winedebugchannel" ] || [ "$1" == "wdc" ]; then
		FUSEID "$2"
		SetWineDebugChannels "$USEID"
	elif [ "$1" == "yad" ]; then
		if [ -n "$2" ]; then
			setYadBin "$2" "$3"
		else
			writelog "INFO" "${FUNCNAME[0]} ------------------------"
			writelog "INFO" "${FUNCNAME[0]} - arg2 '$2' needs to be a valid yad parameter"
			howto
		fi
	else
		if ! grep -q "lang=\|run" <<< "$@" ; then
			writelog "INFO" "${FUNCNAME[0]} ------------------------"
			writelog "INFO" "${FUNCNAME[0]} - arg1 '$1' is no valid command"
			howto
		fi
	fi
}
#ENDCMDLINE


### COMMAND LINE END ###

function writeLastRun {
	writelog "INFO" "${FUNCNAME[0]} - Recreating $LASTRUN"
	{
	echo "RUNPROTON=\"$RUNPROTON\""
	echo "RUNWINE=\"$RUNWINE\""
	echo "PROTONVERSION=\"$PROTONVERSION\""
	echo "PREVAID=\"$AID\""
	echo "PREVGAME=\"$GN\""
	echo "PREVEFD=\"$EFD\""
	} >	"$LASTRUN"
}

function storeMetaData {
	MAID="$1"
	MGNA1="${2//\//_}"
	MGNA="${MGNA1//\"/}"
	MPFX="$3"
	GDIR="$4"

	writelog "INFO" "${FUNCNAME[0]} - Saving metadata for game '$MGNA ($MAID)'"

	if [ ! -f "$GEMETA/$MAID.conf" ]; then
		if [ "$SGDBAUTODL" == "no_meta" ] ; then
			writelog "INFO" "${FUNCNAME[0]} - Automatic Grid Update Check '$SGDBAUTODL'"
			getGrids "$MAID"
		fi
		touch "$GEMETA/$MAID.conf"
	fi
	
	loadCfg "$GEMETA/$MAID.conf" X
	updateConfigEntry "GAMEID" "$MAID" "$GEMETA/$MAID.conf"

	if [ -z "$KEEPGAMENAME" ] || [ "$KEEPGAMENAME" -eq 0 ] || [ "$GAMENAME" == "$NON" ]; then
		updateConfigEntry "GAMENAME" "$MGNA" "$GEMETA/$MAID.conf"
	fi

	if [ -n "$GE" ] && [ -z "$GAMEEXE" ]; then
		GAMEEXE="$GE"
	fi

	if [ -n "$GAMEEXE" ]; then
		updateConfigEntry "GAMEEXE" "$GAMEEXE" "$GEMETA/$MAID.conf"
	fi

	if [ -n "$GP" ]; then
		updateConfigEntry "GAMEARCH" "$(getArch "$GP")" "$GEMETA/$MAID.conf"
	fi
	
	if [ ! -f "$CUMETA/$MAID.conf" ]; then
		touch "$CUMETA/$MAID.conf"
	fi
	loadCfg "$CUMETA/$MAID.conf" X

	if [ "$MPFX" != "$NON" ]; then
		updateConfigEntry "WINEPREFIX" "$MPFX" "$CUMETA/$MAID.conf"
	fi

	updateConfigEntry "MEGAMEDIR" "$GDIR" "$CUMETA/$MAID.conf"

	if [ "$STLPLAY" -eq 1 ]; then
		touch "$FUPDATE"
		updateConfigEntry "STL_COMPAT_DATA_PATH" "$STEAM_COMPAT_DATA_PATH" "$CUMETA/$MAID.conf"
	fi
	createSymLink "${FUNCNAME[0]}" "$GEMETA/$MAID.conf" "$TIGEMETA/${MGNA}.conf" X
	createSymLink "${FUNCNAME[0]}" "$CUMETA/$MAID.conf" "$TICUMETA/${MGNA}.conf" X

	if [ "$STLPLAY" -eq 0 ]; then
		createSymLink "${FUNCNAME[0]}" "$EVMETAID/${EVALSC}_${MAID}.vdf" "$EVMETATITLE/${EVALSC}_${MGNA}.vdf"
	fi
}

function delMenuTemps {
	find "$STLSHM" -maxdepth 1 -type f -regextype posix-extended -regex '^.*menu.[A-Z,a-z,0-9]{8}' -exec rm {} \;	
}

function delWinetricksTemps {
	# cosmetics - GE leaves empty winetricks directories back, removing them
	find "/tmp" -maxdepth 1 -type d -regextype posix-extended -regex '^.*winetricks.[A-Z,a-z,0-9]{8}' -exec rmdir {} \;	2>/dev/null
}

function cleanSUTemp {
	if [ "$ISGAME" -eq 2 ] && [ "$CLEANPROTONTEMP" -eq 1 ]; then
		PFXSUTEMP="$GPFX/$DRCU/$STUS/Temp"
		if [ -d "$PFXSUTEMP" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Cleaning up Temp directory '$PFXSUTEMP'"
			rm -rf "${PFXSUTEMP:?}" 
		else
			writelog "SKIP" "${FUNCNAME[0]} - Temp directory '$PFXSUTEMP' exists, but is empty"
		fi
	fi
}

function restoreSteamUser {

	function startRestore {
		writelog "INFO" "${FUNCNAME[0]} - Restoring backup from '$BACKUPSRC' to '$SteamUserDir'"
		notiShow "$(strFix "$NOTY_STARTRESTORE" "$BACKUPSRC" "$AID")"
		mkProjDir "$SteamUserDir"
		"$RSYNC" -am "$BACKUPSRC" "$SteamUserDir" 
		notiShow "$(strFix "$NOTY_STOPRESTORE" "$SteamUserDir")"
	}
	
	function startRestoreBecause {
		writelog "INFO" "${FUNCNAME[0]} - Restoring, because '$RSTUS' is set"
		startRestore
	}

	function askRestore {
		writelog "INFO" "${FUNCNAME[0]} - Asking if $STUS data from '$BACKUPSRC' shall be restored to '$SteamUserDir'"

		export CURWIKI="$PPW/Backup Support"
		TITLE="${PROGNAME}-Ask_Restore_SteamUser_data"
		pollWinRes "$TITLE"

		"$YAD" --f1-action="$F1ACTION" --image "$SHOWPIC" --image-on-top --window-icon="$STLICON" --center --on-top "$WINDECO" \
		--title="$TITLE" \
		--text="$(spanFont "$(strFix "$GUI_AR" "$BACKUPSRC" "$SteamUserDir")" "H")\n<span font=\"italic\">$1</span>" $GEOM
		case $? in
			0) 	{
					writelog "INFO" "${FUNCNAME[0]} - Restoring '$SteamUserDir' from '$BACKUPSRC' confirmed"
					startRestore
				}
			;;
			1)	{
					writelog "INFO" "${FUNCNAME[0]} - Selected CANCEL - Not restoring '$BACKUPSRC' to '$SteamUserDir'"
				}
			;;
		esac
	}

	if [ -n "$1" ] && [ "$1" != "$NON" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Using value '$1' from argument for RESTORESTEAMUSER"
		RSTUS="$1"
	else
		writelog "INFO" "${FUNCNAME[0]} - Using configured value '$RESTORESTEAMUSER' for RESTORESTEAMUSER"
		RSTUS="$RESTORESTEAMUSER"
	fi

	SteamUserDir="$GPFX/$DRCU/$STUS"
	BACKUPSRC="$SUBADIRID/$AID/$STUS/"
	
	if [ "$RSTUS" == "$NON" ] ; then
		writelog "INFO" "${FUNCNAME[0]} - Restoration of $STUS data is disabled with RESTORESTEAMUSER being '$RSTUS"
	else
		if [ -n "$AID" ] && [ -d "$BACKUPSRC" ] && [ -d "$GPFX" ]; then
			if [ "$RSTUS" == "ask-always" ] ; then
				askRestore "$GUI_AR_ALWAYSASK"
			elif [ "$RSTUS" == "restore-always" ] ; then
				startRestoreBecause
			elif [ ! -f "$SteamUserDir/$BTS" ] ; then
				if [ "$RSTUS" == "ask-if-dst-has-no-backup-timestamp" ] ; then
					askRestore "$GUI_AR_ASKNODSTTS"
				elif [ "$RSTUS" == "restore-if-dst-has-no-backup-timestamp" ] ; then
					startRestoreBecause
				elif [ "$RSTUS" == "restore-if-dst-is-empty" ]; then
					if [ ! -d "$SteamUserDir" ] || [ "$(find "$SteamUserDir" -type f | wc -l)" -eq 0 ]; then
						startRestoreBecause
					elif [ "$RSTUS" == "ask-if-unsure" ] ; then
						askRestore "$GUI_AR_ALWAYSASK"	
					fi
				elif [ "$RSTUS" == "ask-if-unsure" ] ; then
					askRestore "$GUI_AR_ASKUNSURE"
				fi
			elif [ -f "$BACKUPSRC/$BTS" ] && [ -f "$SteamUserDir/$BTS" ]; then
				if [ "$(cat "$BACKUPSRC/$BTS")" -gt "$(cat "$SteamUserDir/$BTS")" ]; then
					writelog "INFO" "${FUNCNAME[0]} - Data in '$BACKUPSRC' is newer than in '$SteamUserDir'"
					if [ "$RSTUS" == "restore-if-backup-timestamp-is-newer" ] ; then
						startRestoreBecause
					elif [ "$RSTUS" == "ask-if-unsure" ] ; then
						askRestore "$GUI_AR_ALWAYSASK"
					fi
				else
					writelog "INFO" "${FUNCNAME[0]} - Data in '$BACKUPSRC' is older than in '$SteamUserDir'"
					if [ "$RSTUS" == "ask-if-unsure" ]; then
						askRestore "$GUI_AR_ASKUNSURE"
					elif [ "$RSTUS" == "restore-always" ]; then
						startRestoreBecause
					fi
				fi
			elif [ "$RSTUS" == "ask-if-unsure" ] ; then
				askRestore "$GUI_AR_ASKUNSURE"
			else
				writelog "SKIP" "${FUNCNAME[0]} - Have to skip - this should never happen. RESTORESTEAMUSER is '$RSTUS'"
			fi
		else
			writelog "SKIP" "${FUNCNAME[0]} - At least one of AID '$AID', BACKUPSRC '$BACKUPSRC', SteamUserDir '$SteamUserDir' is missing - can't start restoration of $STUS data"
		fi
	fi
}

function backupSteamUser {
	if [ "$BACKUPSTEAMUSER" -eq 1 ]; then
		BAID="$1"

		if [ -n "$GN" ]; then
			BACKTI="$GN"
		else
			getGameName "$BAID"
			if [ -n "$GAMENAME" ] && [ "$GAMENAME" != "$NON" ]; then
				BACKTI="$GAMENAME"
			fi
		fi

		if [ -n "$2" ]; then
			if [ -d "$2" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Using argument 2 '$2' as WINEPREFIX'"
				GPFX="$2"
			else
				writelog "SKIP" "${FUNCNAME[0]} - Directory in argument 2 '$2' does not exist"
				GPFX=""
			fi
		fi

		setGPfxFromAppMa "$BAID"

		if [ -z "$GPFX" ]; then
			if [ -f "$CUMETA/$BAID.conf" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Loading metadata config '$CUMETA/$BAID.conf'"
				loadCfg "$CUMETA/$BAID.conf" X
				if [ -d "$WINEPREFIX" ]; then
					writelog "INFO" "${FUNCNAME[0]} - Searching in stored metadata WINEPREFIX '$WINEPREFIX' for files to backup"
					GPFX="$WINEPREFIX"
				else
					writelog "SKIP" "${FUNCNAME[0]} - Stored metadata WINEPREFIX '$WINEPREFIX' does not exist"
				fi
			else
				writelog "SKIP" "${FUNCNAME[0]} - No metadata config '$CUMETA/$BAID.conf' found to search for the WINEPREFIX"
				GPFX=""
			fi
		fi

		if [ -z "$GPFX" ]; then
			if [ -z "$BACKTI" ]; then
				writelog "SKIP" "${FUNCNAME[0]} - Game pfx unknown for '$BAID'"
			else
				writelog "SKIP" "${FUNCNAME[0]} - Game pfx unknown for '$BACKTI ($BAID)'"
			fi
		else
			if [ -z "$2" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Backup enabled for Game '$BACKTI ($BAID)'"
			fi
			mkProjDir "$SUBADIRID/$BAID"
			mkProjDir "$SUBADIRTI"
			SteamUserDir="$GPFX/$DRCU/$STUS"
			
			if [ -d "$SteamUserDir" ]; then
				writelog "INFO" "${FUNCNAME[0]} - backing up directory '$SteamUserDir' to '$SUBADIRID/$BAID'"
				if [ -z "$2" ]; then
					notiShow "$(strFix "$NOTY_STARTBACKUP" "$BACKTI" "$BAID")"
				fi
				mkProjDir "$BACKEX"
				
				EXID="$BACKEX/exclude-${BAID}.txt"
				touch "$EXGLOB" "$EXID"
				"$RSYNC" -am --exclude-from="$EXGLOB" --exclude-from="$EXID" "$SteamUserDir" "$SUBADIRID/$BAID"
				date +%s > "$SUBADIRID/$BAID/$STUS/$BTS"

				if [ -z "$2" ]; then
					notiShow "$(strFix "$NOTY_STOPBACKUP" "$BACKTI" "$BAID")"
				fi
			else
				writelog "SKIP" "${FUNCNAME[0]} - directory '$SteamUserDir' does not exist - nothing to backup"
			fi

			if [ -z "$BACKTI" ]; then
				if [ -z "$2" ]; then
					writelog "SKIP" "${FUNCNAME[0]} - Skipping symlinking backup - no valid game name found"
				fi
			else
				createSymLink "${FUNCNAME[0]}" "$SUBADIRID/$BAID" "$SUBADIRTI/$BACKTI"
			fi
		fi
	fi
}

function backupSteamUserGate {
	BACKUPSTEAMUSER=1
	if [ "$1" != "all" ]; then
		backupSteamUser "$1"
	else
		LOGFILE="$TEMPLOG"
		writelog "INFO" "${FUNCNAME[0]} - Selected to backup all '$STUS' files from all found pfxes"

		while read -r APPMA; do
			AMF="${APPMA##*/}"
			BAID="$(cut -d'_' -f2 <<< "$AMF" | cut -d'.' -f1)"
			BPFX="$(dirname "$APPMA")/$CODA/$BAID/pfx"
			if [ -d "$BPFX" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Backup all '$STUS' files for pfx '$BPFX'"
				backupSteamUser "$BAID" "$BPFX"
			fi
		done <<< "$(listAppManifests)"
	fi
}

function createMetaData {
	LASTMETAUP="$METADIR/lastmeta.txt"
	MAXMETAAGE=1440
	
	if [ -n "$1" ] && [ "$1" == "yes" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Updating metadata requested via command line"
		rm "$LASTMETAUP"
	fi
	
	if [ ! -f "$LASTMETAUP" ] || test "$(find "$LASTMETAUP" -mmin +"$MAXMETAAGE")"; then
		writelog "INFO" "${FUNCNAME[0]} - Creating/Updating metadata for all installed games found"

		while read -r APPMA; do
			AMF="${APPMA##*/}"
			MAID="$(cut -d'_' -f2 <<< "$AMF" | cut -d'.' -f1)"

			GNRAW="$(grep "\"name\"" "$APPMA" | awk -F '"name"' '{print $NF}')"
			GNAM="$(awk '{$1=$1};1' <<< "$GNRAW")"
			GDIR="$(getGameDirFromAM "$APPMA")"
			MPFX="$(dirname "$APPMA")/$CODA/$MAID/pfx"

			storeMetaData "$MAID" "$GNAM" "$MPFX" "$GDIR"
		done <<< "$(listAppManifests)"
		writelog "INFO" "${FUNCNAME[0]} - Done with Creating/Updating metadata"
		date +%y-%m-%d > "$LASTMETAUP"
	fi
}

function getLatestX64dbgSnap {
	basename "$("$WGET" -q "$X64DBGURL" -O - 2> >(grep -v "SSL_INIT") | grep -E 'releases.*download.*snapshot.*zip' | cut -d '"' -f2 | head -n1)"
}

function dlX64Dbg {
	DLDST="$X64DBGDLDIR"
	DLCH="$DLDST/commithash.txt"
	if [ -f "$DLCH" ]; then
		writelog "SKIP" "${FUNCNAME[0]} - '$X64D' is already ready"
	else	
		mkProjDir "$DLDST"
		X64ZIP="$(getLatestX64dbgSnap)"

		if [ ! -f "$DLDST/$X64ZIP" ]; then
			notiShow "$(strFix "$NOTY_DLCUSTOMPROTON" "$X64ZIP")" "S"
			dlCheck "${X64DBGURL//tag/download}/$X64ZIP" "$DLDST/$X64ZIP" "X" "Downloading '$X64ZIP'"
			notiShow "$(strFix "$NOTY_DLCUSTOMPROTON2" "$X64ZIP")" "S"
		fi
	
		if [ ! -s "$DLDST/$X64ZIP" ]; then
			writelog "SKIP" "${FUNCNAME[0]} - Downloaded file '$DLDST/$X64ZIP' is empty - removing"
			rm "$DLDST/$X64ZIP" 2>/dev/null
		else
			notiShow "$(strFix "$NOTY_DLCUSTOMPROTON3" "$X64ZIP")" "S"
			writelog "INFO" "${FUNCNAME[0]} - Download of '$X64ZIP' to '$DLDST' was successful"
			"$UNZIP" -q "$DLDST/$X64ZIP" -d "$DLDST" 2>/dev/null
			notiShow "$GUI_DONE" "S"
			if [ -f "$DLCH" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Extracted '$X64ZIP' to '$DLDST'"
			else
				writelog "SKIP" "${FUNCNAME[0]} - Extracting of file '$DLDST/$X64ZIP' failed"
			fi
		fi
	fi
}

# start x64dbg
function checkX64dbgLaunch {
	if [ "$RUN_X64DBG" -eq 1 ] && [ "$ISGAME" -eq 2 ] && [ "$USEWINE" -eq 0 ]; then
		writelog "INFO" "${FUNCNAME[0]} - Starting '$X64D' for '$GE ($AID)'"

		if [ "$(getArch "$GP")" == "32" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Using '$X32D' as '$GE' is 32bit" 
			XDBGEXE="$X32D"
		elif [ "$(getArch "$GP")" == "64" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Using '$X64D' as '$GE' is 64bit" 
			XDBGEXE="$X64D"
		else
			writelog "INFO" "${FUNCNAME[0]} - Could not get architecture of '$GP' - using '$X64D'" 
			XDBGEXE="$X64D"	
		fi
		
		XDBFPATH="$X64DBGDLDIR/release/${XDBGEXE//dbg/}/${XDBGEXE}.exe"
		
		if [ ! -f "$XDBFPATH" ]; then
			writelog "INFO" "${FUNCNAME[0]} - File '$X64EXE' does not exit - starting installer"
			StatusWindow "$(strFix "$NOTY_DLCUSTOMPROTON" "$X64D")" "dlX64Dbg" "DownloadX64DbgStatus"
		fi

		if [ ! -f "$XDBFPATH" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Installing failed - can't start '$XDBFPATH' - skipping"
			RUN_X64DBG=0
		else
			writelog "INFO" "${FUNCNAME[0]} - Applying registry '${X64D}.reg'"
			regEdit "$GLOBALMISCDIR/${X64D}.reg"

			WGP="$(extWine64Run "$RUNWINE" winepath -w "$GP")"
			writelog "INFO" "${FUNCNAME[0]} - Starting '$XDBFPATH' using extWine64Run for the game '$WGP'"
			extWine64Run "$RUNWINE" "$XDBFPATH" "$WGP"
		fi
	fi
}

function prepareGdb {
	GDBOPTS="$STLSHM/gdb.conf"
	WIREPY="WineReload.py"
	WINEREL="$STLSHM/$WIREPY"
	WIREURL="$WINERELOADURL/$WIREPY"
	GST10="gstreamer-1.0"

	if [ ! -f "$WINEREL" ]; then
		dlCheck "$WIREURL" "$WINEREL" "X" "Downloading '$DLSRC' to '$DLDST'"
	fi
	
	if [ ! -f "$GDBOPTS" ]; then
		{
		echo "set confirm off"
		echo "set pagination off"
		echo "handle SIGUSR1 noprint nostop"
		echo "handle SIGSYS noprint nostop"
		echo "source $WINEREL"
		} > "$GDBOPTS"
	fi

	if [ -z "$RUNPROTON" ]; then
		setRunProtonFromUseProton
	fi

	PROTONBASEPATH="$(dirname "$RUNPROTON")/files"
	if [ ! -d "$PROTONBASEPATH" ]; then
		PROTONBASEPATH="$(dirname "$RUNPROTON")/dist"
	fi

	setRunWineServer "${FUNCNAME[0]}"

	PBIPA="$PROTONBASEPATH/bin"
	PLIPA="$PROTONBASEPATH/lib"
	PLIPA64="$PROTONBASEPATH/lib64"


	if [ -n "$(GETALTEXEPATH)" ]; then
		WORKDIR="$(GETALTEXEPATH)"
	else
		WORKDIR="$EFD"
	fi

	{
	head -n1 "$0"
	echo "PATH=\"$PATH=:$PBIPA\" WINEDEBUG=\"-all\" WINEDLLPATH=\"${PLIPA64}/wine:${PLIPA}/wine:$WINEDLLPATH\" LD_LIBRARY_PATH=\"$LD_LIBRARY_PATH:${PLIPA64}:${PLIPA}:$WORKDIR\" \
	WINEPREFIX=\"$GPFX\" WINEESYNC=1 WINEFSYNC=1 WINEDLLOVERRIDES=\"$WINEDLLOVERRIDES;steam.exe=b;dotnetfx35.exe=b;dxvk_config=n;d3d11=n;d3d10=n;d3d10core=n;d3d10_1=n;d3d9=n;dxgi=n\" \
	WINE_LARGE_ADDRESS_AWARE=1 GST_PLUGIN_SYSTEM_PATH_1_0=\"${PLIPA64}/${GST10}:${PLIPA}/${GST10}:$GST_PLUGIN_SYSTEM_PATH_1_0\" WINE_GST_REGISTRY_DIR=\"${WINEPREFIX}/${GST10}/\" \
	\"$RUNWINE\" \"steam.exe\" \"${GDBGAMESTARTCMD[*]}\""
	} > "$GDBGAMERUN"	
	chmod +x "$GDBGAMERUN"
}

#start gdb
function injectGdb {
	function setgampi {
		GAMPI="$("$PGREP" -a "" | grep -i "${GP##*/}"  | grep "Z:" | grep -v "$PROGCMD" | cut -d ' ' -f1 | tail -n1)"
	}
	
	MAXWAIT=5
	COUNTER=0
	
	while ! [ "$GAMPI" -eq "$GAMPI" ] 2>/dev/null; do
		writelog "INFO" "${FUNCNAME[0]} - setgampi"
		setgampi
		if [[ "$COUNTER" -ge "$MAXWAIT" ]]; then
			writelog "ERROR" "${FUNCNAME[0]} - Timeout waiting for game pid $GAMPI - Skipping '$GDB'"
			return 
		fi
		COUNTER=$((COUNTER+1))
		sleep 1
	done

	if [ -n "$GAMPI" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Found GamePid '$GAMPI' - Starting '$GDB'"
		{
		head -n1 "$0"
		echo "\"$GDB\" \"-x\" \"$GDBOPTS\" \"-p\" \"$GAMPI\""
		} > "$GDBRUN"
		chmod +x "$GDBRUN"
		"$USETERM" "$TERMARGS" "bash -c \"$GDBRUN\""
	fi
}

function startSettings {
	FUSEID "$1"

	writelog "INFO" "${FUNCNAME[0]} - createProtonList:"
	createProtonList X

	writelog "INFO" "${FUNCNAME[0]} - openTrayIcon:"
	openTrayIcon

	writelog "INFO" "${FUNCNAME[0]} - MainMenu:"
	MainMenu "$USEID"

	writelog "INFO" "${FUNCNAME[0]} - cleanYadLeftOvers:"
	cleanYadLeftOvers	
}

function retBool {
	if [ "$1" == "TRUE" ]; then
		echo "1"
	else
		echo "0"
	fi	
}

function SteamCatSelect {
	writelog "INFO" "${FUNCNAME[0]} - Steam Category Selection"
	export CURWIKI="$PPW/Steam-Categories"
	TITLE="${PROGNAME}-SteamCategorySelection"
	pollWinRes "$TITLE"

	setShowPic
	unset VALTAGS
	mapfile -d "\n" -t -O "${#VALTAGS[@]}" VALTAGS <<< "$(getActiveSteamCategories)"
	SCATSELOUT="$(while read -r f; do if [[ ! "${SCATSEL[*]}" =~ $f ]]; then 	echo FALSE ; echo "$f"; else echo TRUE ; echo "$f" ;fi ; done <<< "$(printf "%s\n" "${VALTAGS[@]}")" | \
	"$YAD" --f1-action="$F1ACTION" --image "$SHOWPIC" --image-on-top --window-icon="$STLICON" --center $WINDECO --list --checklist --column=Choose --column=SteamCategory --separator="\n" --print-column="2" \
	--text="$(spanFont "$GUI_STEAMCATSEL" "H")" --title="$TITLE" --button="$BUT_SEL":0 --button="$BUT_CAN":2 "$GEOM")"

	case $? in
		0)  {
		writelog "INFO" "${FUNCNAME[0]} - Selected Select"
				if [ -n "$SCATSELOUT" ]; then
					writelog "INFO" "${FUNCNAME[0]} - Selected following Categories2: '$(sort -u <<< "$SCATSELOUT" | sed '/^$/d' | tr '\n' ',')'"
					unset SCATSEL
					mapfile -d "\n" -t -O "${#SCATSEL[@]}" SCATSEL <<< "$(sort -u <<< "$SCATSELOUT" | sed '/^$/d')"
				fi
			}
		;;
		2)  writelog "INFO" "${FUNCNAME[0]} - Selected CANCEL"
		;;
	esac

	goBackToPrevFunction "${FUNCNAME[0]}" "$2"
}

function AutoMarkSCat {
	writelog "INFO" "${FUNCNAME[0]} - Auto-marking specific Steam Categories"

	if ! grep -q "$DESC_NOST" <<< "$(printf "%s" "${SCATSEL[@]}" | tr '\n' ',')" && grep -q "$DESC_NOST" <<< "$(getActiveSteamCategories | tr '\n' ',')"; then
		writelog "INFO" "${FUNCNAME[0]} - Marking '$DESC_NOST' as Category"
		mapfile -d "\n" -t -O "${#SCATSEL[@]}" SCATSEL <<< "$DESC_NOST"
	fi
	
	function maybeLater {
		if [ -f "$AUTOADDSCATLIST" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Marking everything found in '$AUTOADDSCATLIST' as Steam Category"
			while read -r line; do
				mapfile -d "\n" -t -O "${#SCATSEL[@]}" SCATSEL <<< "$line"
			done < "$AUTOADDSCATLIST"
		else
			writelog "INFO" "${FUNCNAME[0]} - No file '$AUTOADDSCATLIST' containing Steam Categories found for adding"
		fi
	}
}

function addNonSteamGameGui {
	writelog "INFO" "${FUNCNAME[0]} - Starting the Gui for adding a $NSGA to Steam"

	# defaults
	if [ -n "$1" ]; then
		for i in "$@"
		do
		case $i in
			-ep=*|--exepath=*)
			NOSTGEXEPATH="${i#*=}";
			shift
			;;
		esac
		done

		NOSTGAPPNAME="${NOSTGEXEPATH##*/}"
		NOSTGSTDIR="${NOSTGEXEPATH%/*}"
	fi
	
	if grep -q "^NOSTEAMSTLDEF=\"1\"" "$STLDEFGLOBALCFG"; then
		NOSTGICONPATH="$STLICON"
	else
		NOSTGICONPATH=""
	fi
	NOSTGHIDE=0
	NOSTGADC=1
	NOSTGAO=1
	NOSTGVR=0
	unset VALTAGS
	mapfile -d "\n" -t -O "${#VALTAGS[@]}" VALTAGS <<< "$(getActiveSteamCategories | sed '/^$/d')"
	VALIDTAGS="$(printf "%s" "${VALTAGS[@]}" | tr '\n' ',' | sed 's/,*$//g')"

	AutoMarkSCat

	if [[ -v SCATSEL[@] ]]; then
		NOSTTAGS="$(printf "%s" "${SCATSEL[@]}" | tr '\n' ',' | sed 's/,*$//g')"
	fi 
	export CURWIKI="$PPW/Add-Non-Steam-Game"
	TITLE="${PROGNAME}-$NSGA"
	pollWinRes "$TITLE"

	NSGSET="$("$YAD" --f1-action="$F1ACTION" --window-icon="$STLICON" --form --center --on-top "$WINDECO" \
	--title="$TITLE" --separator="|" \
	--text="$(spanFont "$GUI_ADDNSG" "H")\n<span font=\"italic\">$(strFix "$GUI_WARNNSG1" "$STERECO")\n$(strFix "$GUI_WARNNSG2" "$STERECO"))</span>" \
	--field=" ":LBL " " \
	--field="     $GUI_NOSTGAPPNAME!$DESC_NOSTGAPPNAME ('NOSTGAPPNAME')" "${NOSTGAPPNAME/#-/ -}" \
	--field="     $GUI_NOSTGEXEPATH!$DESC_NOSTGEXEPATH ('NOSTGEXEPATH')":FL "${NOSTGEXEPATH/#-/ -}" \
	--field="     $GUI_NOSTGSTDIR!$DESC_NOSTGSTDIR ('NOSTGSTDIR')":DIR "${NOSTGSTDIR/#-/ -}" \
	--field="     $GUI_NOSTGICONPATH!$DESC_NOSTGICONPATH ('NOSTGICONPATH')":FL "${NOSTGICONPATH/#-/ -}" \
	--field="     $GUI_NOSTGLAOP!$DESC_NOSTGLAOP ('NOSTGLAOP')" "${NOSTGLAOP/#-/ -}" \
	--field="     $GUI_NOSTGHIDE!$DESC_NOSTGHIDE ('NOSTGHIDE')":CHK "${NOSTGHIDE/#-/ -}" \
	--field="     $GUI_NOSTGADC!$DESC_NOSTGADC ('NOSTGADC')":CHK "${NOSTGADC/#-/ -}" \
	--field="     $GUI_NOSTGAO!$DESC_NOSTGAO ('NOSTGAO')":CHK "${NOSTGAO/#-/ -}" \
	--field="     $GUI_NOSTGVR!$DESC_NOSTGVR ('NOSTGVR')":CHK "${NOSTGVR/#-/ -}" \
	--field="     $GUI_NOSTTAGS!$DESC_NOSTTAGS ('NOSTTAGS')":CBE "$(cleanDropDown "${NOSTTAGS/#-/ -}" "$VALIDTAGS")" \
	--button="$BUT_CAN":0 --button="$BUT_TAGS":2 --button="$BUT_CREATE":4 "$GEOM")"

	case $? in
		0)  writelog "INFO" "${FUNCNAME[0]} - Selected '$BUT_CAN'"
		;;
		2)  writelog "INFO" "${FUNCNAME[0]} - Selected '$BUT_TAGS"
			SteamCatSelect "$NON" "${FUNCNAME[0]}"
		;;
		4)  writelog "INFO" "${FUNCNAME[0]} - Selected '$BUT_CREATE'"
			if [ -n "$NSGSET" ]; then
				mapfile -d "|" -t -O "${#NSGSETARR[@]}" NSGSETARR < <(printf '%s' "$NSGSET")
				NOSTGAPPNAME="${NSGSETARR[1]}"
				NOSTGEXEPATH="${NSGSETARR[2]}"
				NOSTGSTDIR="${NSGSETARR[3]}"
				NOSTGICONPATH="${NSGSETARR[4]}"
				NOSTGLAOP="${NSGSETARR[5]}"
				NOSTGHIDE="$(retBool "${NSGSETARR[6]}")"
				NOSTGADC="$(retBool "${NSGSETARR[7]}")"
				NOSTGAO="$(retBool "${NSGSETARR[8]}")"
				NOSTGVR="$(retBool "${NSGSETARR[9]}")"
				NOSTTAGS="${NSGSETARR[10]}"
				writelog "INFO" "${FUNCNAME[0]} - Launching command: addNonSteamGame -an=\"$NOSTGAPPNAME\" -ep=\"$NOSTGEXEPATH\" -sd=\"$NOSTGSTDIR\" -ip=\"$NOSTGICONPATH\" -lo=\"$NOSTGLAOP\" -hd=\"$NOSTGHIDE\" -adc=\"$NOSTGADC\" -ao=\"$NOSTGAO\" -vr=\"$NOSTGVR\" -t=\"$NOSTTAGS\""
				addNonSteamGame	-an="$NOSTGAPPNAME" -ep="$NOSTGEXEPATH" -sd="$NOSTGSTDIR" -ip="$NOSTGICONPATH" -lo="$NOSTGLAOP" -hd="$NOSTGHIDE" -adc="$NOSTGADC" -ao="$NOSTGAO" -vr="$NOSTGVR" -t="$NOSTTAGS"
			fi
		;;
	esac
}

function addNonSteamGame {
	if [ -z "$SUSDA" ] || [ -z "$STUIDPATH" ]; then
		setSteamPaths
	fi
	SCPATH="$STUIDPATH/config/$SCVDF"

	function getCRC {
		echo -n "$1" | gzip -c | tail -c 8 | od -An -N 4 -tx4
	}

	function dec2hex {
		 printf '%x\n' "$1"
	}

	function hex2dec {
		printf "%d\n" "0x${1#0x}"
	}

	function splitTags {
		mapfile -d "," -t -O "${#TAGARR[@]}" TAGARR < <(printf '%s' "$1")
		for i in "${!TAGARR[@]}"; do
			if grep -q "${TAGARR[$i]}" <<< "$(getActiveSteamCategories)"; then
				printf '\x01%s\x00%s\x00' "$i" "${TAGARR[i]}"
			fi
		done
	}

	NOSTHIDE=0
	NOSTADC=1
	NOSTAO=1
	NOSTVR=0
	NOSTSTLLO=0

	for i in "$@"; do
		case $i in
			-an=*|--appname=*)
			NOSTAPPNAME="${i#*=}"
			shift
			;;
			-ep=*|--exepath=*)
			QEP="${i#*=}"; NOSTEXEPATH="\"$QEP\""
			shift
			;;
			-sd=*|--startdir=*)
			QSD="${i#*=}"; NOSTSTDIR="\"$QSD\""
			shift
			;;
			-ip=*|--iconpath=*)
			NOSTICONPATH="${i#*=}"
			shift
			;;
			-lo=*|--launchoptions=*)
			NOSTLAOP="${i#*=}"
			shift
			;;
			-hd=*|--hide=*)
			NOSTHIDE="${i#*=}"
			shift
			;;
			-adc=*|--allowdesktopconf=*)
			NOSTADC="${i#*=}"
			shift
			;;
			-ao=*|--allowoverlay=*)
			NOSTAO="${i#*=}"
			shift
			;;
			-vr=*|--openvr=*)
			NOSTVR="${i#*=}"
			shift
			;;
			-t=*|--tags=*)
			NOSTTAGS="${i#*=}"
			shift
			;;
			-stllo=*|--stllaunchoption=*)
			NOSTSTLLO="${i#*=}"
			shift
			;;
			*)
			;;
		esac
	done

	if [ -n "${NOSTEXEPATH}" ]; then
	
		if [ -z "${NOSTAPPNAME}" ]; then
			NOSTAPPNAME="${QEP##*/}"
		fi

		if [ -z "${NOSTSTDIR}" ]; then
			QSD="$(dirname "$QEP")"; NOSTSTDIR="\"$QSD\""
		fi

		if [ "$NOSTSTLLO" -eq 1 ]; then
			NOSTGICONPATH="$STLICON"
		fi

		# looks like the appid used here is randomly generated or at least not created from CRC
		# (like the shortcutnames found in screenshots.vdf - see commented out lines)
		# NOSTCRC="$(getCRC "${NOSTEXEPATH}${NOSTAPPNAME}")"
		# NOSTSCNHEX="${NOSTCRC}02000000"
		# echo "NOSTSCNHEX = ${NOSTSCNHEX}"

		NOSTAIDRHX="$(printf "%03x%03x%02x\n" $((RANDOM%4096)) $((RANDOM%4096)) $((RANDOM%256)))"
		NOSTAID="$(hex2dec "$NOSTAIDRHX")"
		NOSTAIDHX="\x$(awk '{$1=$1}1' FPAT='.{2}' OFS="\\\x" <<< "$NOSTAIDRHX")"

		writelog "INFO" "${FUNCNAME[0]} - === Adding new $NSGA ==="
		writelog "INFO" "${FUNCNAME[0]} - AppID: '${NOSTAID}'"
		writelog "INFO" "${FUNCNAME[0]} - App Name: '${NOSTAPPNAME}'"
		writelog "INFO" "${FUNCNAME[0]} - Exe Path: '${NOSTEXEPATH}'"
		writelog "INFO" "${FUNCNAME[0]} - Start Dir: '${NOSTSTDIR}'"
		writelog "INFO" "${FUNCNAME[0]} - Icon Path: '${NOSTICONPATH}'"
		writelog "INFO" "${FUNCNAME[0]} - Launch options: '${NOSTLAOP}'"
		writelog "INFO" "${FUNCNAME[0]} - Is Hidden: '${NOSTHIDE}'"
		writelog "INFO" "${FUNCNAME[0]} - Allow Desktop Config: '${NOSTADC}'"
		writelog "INFO" "${FUNCNAME[0]} - Allow Overlay: '${NOSTAO}'"
		writelog "INFO" "${FUNCNAME[0]} - OpenVR: '${NOSTVR}'"
		writelog "INFO" "${FUNCNAME[0]} - Tags: '${NOSTTAGS}'"

		if [ -f "$SCPATH" ]; then
			writelog "INFO" "${FUNCNAME[0]} - The file '$SCPATH' already exists, creating a backup, then removing the 2 closing backslashes at the end"
			cp "$SCPATH" "${SCPATH//.vdf}_${PROGNAME}_backup.vdf" 2>/dev/null
			truncate -s-2 "$SCPATH"
			OLDSET="$(grep -aPo '\x00[0-9]\x00\x02appid' "$SCPATH" | tail -n1 | tr -dc '0-9')"
			NEWSET=$((OLDSET + 1))
			writelog "INFO" "${FUNCNAME[0]} - Last set in file has ID '$OLDSET', so continuing with '$OLDSET'"
		else
			writelog "INFO" "${FUNCNAME[0]} - Creating new $SCPATH"
			printf '\x00%s\x00' "shortcuts" > "$SCPATH"
			NEWSET=0
		fi

		writelog "INFO" "${FUNCNAME[0]} - Adding new set '$NEWSET'"

		{
		printf '\x00%s\x00' "$NEWSET"
		printf '\x02%s\x00%b' "appid" "$NOSTAIDHX"
		printf '\x01%s\x00%s\x00' "appname" "$NOSTAPPNAME"
		printf '\x01%s\x00%s\x00' "Exe" "$NOSTEXEPATH"
		printf '\x01%s\x00%s\x00' "StartDir" "$NOSTSTDIR"

		if [ -n "$NOSTICONPATH" ]; then
			printf '\x01%s\x00%s\x00' "icon" "$NOSTICONPATH"
		else
			printf '\x01%s\x00\x00' "icon"
		fi

		printf '\x01%s\x00\x00' "ShortcutPath"

		if [ -n "$NOSTLAOP" ]; then
			printf '\x01%s\x00%s\x00' "LaunchOptions" "$NOSTLAOP"
		else
			printf '\x01%s\x00\x00' "LaunchOptions"
		fi
		
		if [ "$NOSTHIDE" -eq 1 ]; then
			printf '\x02%s\x00\x01\x00\x00\x00' "IsHidden"
		else
			printf '\x02%s\x00\x00\x00\x00\x00' "IsHidden"
		fi

		if [ "$NOSTADC" -eq 1 ]; then
			printf '\x02%s\x00\x01\x00\x00\x00' "AllowDesktopConfig"
		else
			printf '\x02%s\x00\x00\x00\x00\x00' "AllowDesktopConfig"
		fi

		if [ "$NOSTAO" -eq 1 ]; then
			printf '\x02%s\x00\x01\x00\x00\x00' "AllowOverlay"
		else
			printf '\x02%s\x00\x00\x00\x00\x00' "AllowOverlay"
		fi

		if [ "$NOSTVR" -eq 1 ]; then
			printf '\x02%s\x00\x01\x00\x00\x00' "openvr"
		else
			printf '\x02%s\x00\x00\x00\x00\x00' "openvr"
		fi

		printf '\x02%s\x00\x00\x00\x00\x00' "Devkit"
		printf '\x01%s\x00\x00' "DevkitGameID"

		printf '\x02%s\x00\x00\x00\x00\x00' "LastPlayTime"
		printf '\x00%s\x00' "tags"
		splitTags "$NOSTTAGS"
		printf '\x08'
		printf '\x08'

		#file end:
		printf '\x08'
		printf '\x08'
		} >> "$SCPATH"
		
		writelog "INFO" "${FUNCNAME[0]} - Finished adding new $NSGA"
	fi
}

#STARTCLOSESTL ###
function closeSTL {
	writelog "INFO" "${FUNCNAME[0]} - closing STL"

	updateConfigEntry "CUSTOMCMD" "$DUMMYBIN" "$STLDEFGAMECFG"
	
	# dummy file which could be used to stop possible while loops
	writelog "INFO" "${FUNCNAME[0]} - Creating '$CLOSETMP'"
	touch "$CLOSETMP"

	setPrevRes
	customUserScriptStop	# USERSTOP

	checkPlayTime "$duration"

	if [ -f "$STLSHM/KillBrowser-$AID.txt" ]; then
		writelog "INFO" "${FUNCNAME[0]} - '$BROWSER' instance was created, so closing it now, to exit the game session"
		"$PKILL" -f "$BROWSER"
		rm "$STLSHM/KillBrowser-$AID.txt"
	fi

	if [ "$MO2MODE" != "disabled" ] && [ -n "$MODLER" ] && [ -f "$MODLER" ]; then 
		rm "$MODLER" 2>/dev/null
	fi

	cleanSUTemp
	backupSteamUser "$AID"

	if [ "$SGDBAUTODL" == "after_game" ] ; then
		writelog "INFO" "${FUNCNAME[0]} - Automatic Grid Update Check '$SGDBAUTODL'"
		getGrids "$AID"
	fi

	if [ "$ISGAME" -eq 2 ] && [ "$PROTON_LOG" -eq 1 ]; then
		createSymLink "${FUNCNAME[0]}" "$STLPROTONIDLOGDIR/steam-${AID}.log" "$STLPROTONTILOGDIR//steam-${GN}.log"
	fi

	writelog "INFO" "${FUNCNAME[0]} - Game '$SGNAID' exited - cleaning up custom processes if necessary"

# all variables in closeSTL are blocked from being unset before gamestart - dirty list with variables to keep which are not used here:
#DXVK_HUD DXVK_LOG_LEVEL ENABLE_VKBASALT LOGDIR LOGLEVEL MANGOHUD NETOPTS PROTON_DEBUG_DIR PROTON_DUMP_DEBUG_COMMANDS PROTON_FORCE_LARGE_ADDRESS_AWARE
#PROTON_LOG PROTON_LOG_DIR PROTON_NO_D3D10 PROTON_NO_D3D11 PROTON_NO_ESYNC PROTON_NO_FSYNC PROTON_ENABLE_NVAPI PROTON_HIDE_NVIDIA_GPU PROTON_USE_WINED3D STL_PV_SHELL STL_PV_TERMINAL
#STL_PV_VERBOSE USESLR WINEDLLOVERRIDES WINE_FULLSCREEN_INTEGER_SCALING WINE_FULLSCREEN_FSR WINE_FULLSCREEN_FSR_STRENGTH

	# kill $VRVIDEOPLAYER in case it wasn't closed before
	if [ -n "$RUNSBSVR" ]; then
		if [ "$RUNSBSVR" -eq 1 ]; then
			if "$PGREP" -f "$VRVIDEOPLAYER" >/dev/null; then
				"$PKILL" -f "$VRVIDEOPLAYER"
				writelog "INFO" "${FUNCNAME[0]} - $VRVIDEOPLAYER killed"
			fi
		fi
	fi
	
	# kill $NYRNA if running
	if [ -n "$RUN_NYRNA" ]; then
		if [ "$RUN_NYRNA" -eq 1 ]; then
			if "$PGREP" -f "$NYRNA" >/dev/null; then
				"$PKILL" -f "$NYRNA"
				# also remove systray created in /tmp/ ("systray_" with 6 random chars should be save enough)
				find /tmp -maxdepth 1 -type f -regextype posix-extended -regex '^.*systray_[A-Z,a-z,0-9]{6}' -exec rm {} \;
				writelog "INFO" "${FUNCNAME[0]} - $NYRNA killed"
			fi
		fi
	fi

	# kill $REPLAY if running
	if [ -n "$RUN_REPLAY" ]; then
		if [ "$RUN_REPLAY" -eq 1 ]; then
			if "$PGREP" -f "$REPLAY" >/dev/null; then
				"$PKILL" -f "$REPLAY"
				writelog "INFO" "${FUNCNAME[0]} - $REPLAY killed"
			fi
		fi
	fi

	# kill $GAMCON if running
	if [ "$RUN_GAMCON" -eq 1 ]; then
		writelog "INFO" "${FUNCNAME[0]} - Game process finished - closing '$GAMCON'"
		"$PKILL" -f "$GAMCON"
		writelog "INFO" "${FUNCNAME[0]} - Killed '$GAMCON' script"
	fi

	# kill $CE if running
	if [ "$RUN_CHEATENGINE" -eq 1 ] && [ -n "$CEPID" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Game process finished - closing '$CE' by killing CEPID '$CEPID'"
		kill "$CEPID" 2>/dev/null
	fi
	
	# stop network monitor if running

	if [ "$USENETMON" -eq 1 ]; then
		if "$PGREP" "$NETMON" >/dev/null; then
			"$PKILL" -f "$NETMON"
			writelog "INFO" "${FUNCNAME[0]} - $NETMON killed"
			# remove duplicate lines to make reading easier
			rmDupLines "$NETMONDIR/$AID-$NETMON.log"
		fi
	fi

	togWindows windowraise	# TOGGLEWINDOWS

	getHexAidForAid "$AID" X

	cleanYadLeftOvers

	notiShow "$(strFix "$NOTY_STLSTOP" "$GN" "$AID" "$PROGNAME")"

	sleep 1 # so any while loop still running gets the chance to see it
	writelog "INFO" "${FUNCNAME[0]} - Removing '$CLOSETMP'"
	rm "$CLOSETMP" 2>/dev/null
	writelog "STOP" "######### ${FUNCNAME[0]} $PROGNAME $PROGVERS #########"
	rm "$UPWINTMPL" 2>/dev/null
	rm "$KILLSWITCH" 2>/dev/null
	rm "$GWXTEMP" 2>/dev/null
	rm "$STLSHM/lola-*.txt" 2>/dev/null

	# only useful for win games or games started outside steam:
	if [ "$STLPLAY" -eq 1 ] || { [ "$ISGAME" -eq 2 ] && [ "$USEWINE" -eq 0 ];}; then
		writeLastRun
		storeMetaData "$AID" "$GN" "$GPFX" "$EFD"
	fi

	delMenuTemps
	delWinetricksTemps
	if [ "$AID" != "$PLACEHOLDERAID" ]; then
		echo "log can be found under: '$TEMPLOG' and '$LOGFILE'"
	else
		echo "log can be found under: '$TEMPLOG'"
	fi
#	emptyVars "A" "$1"
}
#ENDCLOSESTL ###

# main:#################

function saveOrgVars {
	writelog "INFO" "${FUNCNAME[0]} - Storing some original variables to restore them later" "P"

	env | grep "=" | sort -o "$VARSIN"

	ORG_LD_PRELOAD="$LD_PRELOAD"
	ORG_LD_LIBRARY_PATH="$LD_LIBRARY_PATH"
	ORG_LC_ALL="$LC_ALL"
	ORG_PATH="$PATH"
}

function emptyVars {
	# clear "original" variables

	if [ "$1" == "O" ] ; then
		LC_ALL="" 
		STLPATH="$(tr ':' '\n' <<< "$PATH" | grep -v "$STERU" | tr '\n' ':')"
		PATH="$STLPATH"
		LD_LIBRARY_PATH=""
		LD_PRELOAD=""
		if [ -z "$2" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Emptied some original variables as they slowdown several system calls when started from steam" "P"
			writelog "INFO" "${FUNCNAME[0]} - Set \$PATH to '$PATH'" "P"
		fi
#	# empty "some" internal variables created by ${PROGNAME,,} (before starting the game)
	elif [ "$1" == "S" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Clearing some '${PROGNAME,,}' internal variables before the game starts"

		TIEXV="$STLSHM/TrayIconVars.txt"
		TIEXF="$STLSHM/TrayIconFuncs.txt"

		if [ ! -f "$TIEXV" ]; then
			sed -n "/^#STARTIEX/,/^#ENDIEX/p;/^#ENDIEX/q" "$0" | grep export | grep -v "export \-f" | cut -d '=' -f1 | awk -F 'export ' '{print $2}' > "$TIEXV"
		fi

		if [ ! -f "$TIEXF" ]; then
			sed -n "/^#STARTIEX/,/^#ENDIEX/p;/^#ENDIEX/q" "$0" | grep "export \-f" | awk -F '-f ' '{print $2}' > "$TIEXF"
		fi

		while read -r intvar; do
			if [ -n "$intvar" ]; then
				if [[ "$intvar" =~ "BASH_FUNC" ]]; then
					BAFU1="${intvar#BASH_FUNC_*}"
					BAFU="${BAFU1%%\%}"
					if grep -q "${BAFU%%\%}" "$STLSHM/TIEXF"; then
						writelog "INFO" "${FUNCNAME[0]} - Skipping TrayIcon function '${BAFU%%\%}'"
					else
						if grep -q "function ${BAFU%%\%}" "$0"; then
							writelog "INFO" "${FUNCNAME[0]} - Clearing function '${BAFU%%\%}'"
							unset -f "${BAFU%%\%}"
						else
							writelog "INFO" "${FUNCNAME[0]} - Skipping unknown function '${BAFU%%\%}'"
						fi
					fi
				else
					if grep -q "$intvar" "$STLSHM/TIEXV"; then
						writelog "INFO" "${FUNCNAME[0]} - Skipping TrayIcon variable '$intvar'"
					else
						if ! grep -q "\$${intvar}" "$0" ; then
							writelog "INFO" "${FUNCNAME[0]} - Skipping unknown variable '$intvar'"
						else
							if grep -q "$intvar" <<< "$(sed -n "/^#STARTCLOSESTL/,/^#ENDCLOSESTL/p;/^#ENDCLOSESTL/q" "$0")"; then
								writelog "INFO" "${FUNCNAME[0]} - Skipping variable in closeSTL '$intvar'"
							else
								writelog "INFO" "${FUNCNAME[0]} - Clearing variable '$intvar'"
								unset "$intvar"
							fi
						fi
					fi
				fi
			fi
		done <<< "$(comm -32 <(cut -d '=' -f1 < "$STLSHM/${FUNCNAME[0]}-in") <(cut -d '=' -f1 < "$VARSIN"))"

# empty "all" internal variables created by ${PROGNAME,,} - the ending logfile is "$2" and is written here
	elif [ "$1" == "A" ]; then
		env | grep "=" | grep -v "^ " | sort -o "$STLSHM/${FUNCNAME[0]}-in"
		writelog "STOP" "$2"
		restoreOrgVars

		while read -r intvar; do
			if [ -n "$intvar" ]; then
				if [[ "$intvar" =~ "BASH_FUNC" ]]; then
					BAFU1="${intvar#BASH_FUNC_*}"
					BAFU="${BAFU1%%\%}"
					unset -f "${BAFU%%\%}"
				else
					unset "$intvar"
				fi
			fi
		done <<< "$(comm -32 <(cut -d '=' -f1 < "$STLSHM/${FUNCNAME[0]}-in") <(cut -d '=' -f1 < "$VARSIN"))"
		env > "$STLSHM/${FUNCNAME[0]}-out"
	fi
}

function restoreOrgVars {
	writelog "INFO" "${FUNCNAME[0]} - Restoring previously cleared Variables"
	LD_PRELOAD="$ORG_LD_PRELOAD"
	LD_LIBRARY_PATH="$ORG_LD_LIBRARY_PATH"
	LC_ALL="$ORG_LC_ALL"
	PATH="$ORG_PATH"
}

function rmOldLog {
	# restart $LOGFILE only if older than 3 minutes # TODO minutes configurable?
	setAIDCfgs
	if [ -f "$LOGFILE" ]; then
		if test "$(find "$LOGFILE" -mmin -3 2>/dev/null)"; then
			rm "$LOGFILE" 2>/dev/null
		fi
	fi
}

function CreateCustomEvaluatorScript {
	# create temporary '$TEVALSC'
	function createTempEvals {

		# first the correct install order:
		OCNT=0

		echo "\"$EVALSC\"" > "$TEVALSC"
		echo "{" >> "$TEVALSC"
		while read -r ordline; do
			if grep -q "$ordline" <<< "$EVALSCFILES"; then
				echo "	\"$OCNT\"" >> "$TEVALSC"
				if [ -f "${GLOBSTLEVPACKS}/$ordline" ]; then
					cat "${GLOBSTLEVPACKS}/$ordline" >> "$TEVALSC"
				else
					cat "${GLOBEVPACKS}/$ordline" >> "$TEVALSC"
				fi				
				OCNT=$((OCNT+1))
			fi
		done < "$GLOBEVPACKORDER"

		# then append those packages which are not in the order list:
		while read -r wantevascs; do
			if ! grep -q "$wantevascs" "$GLOBEVPACKORDER"; then
				echo "	\"$OCNT\"" >> "$TEVALSC"
				if [ -f "${GLOBSTLEVPACKS}/$wantevascs" ]; then
					cat "${GLOBSTLEVPACKS}/$wantevascs" >> "$TEVALSC"
				else
					cat "${GLOBEVPACKS}/$wantevascs" >> "$TEVALSC"
				fi
				OCNT=$((OCNT+1))
			fi
		done <<< "$EVALSCFILES"
		
		while read -r intpak; do
			if [ -n "$intpak" ] ; then
				IPFDIR="$(awk -F'"' '{print $4}' <<< "$intpak")"
				IPDIR="${IPFDIR##*/}"
				INTPAKWA="$STLSHM/intpak"
				# dirty workaround - proper fix?
				echo "tac \"$OEVALSC\" | awk '/$IPDIR/,/appid/' | tac" > "$INTPAKWA"
				chmod +x "$INTPAKWA"
				{
					echo "	\"$OCNT\""
					echo "	{"
					"$INTPAKWA"
					echo "	}" 
				} >> "$TEVALSC"
				OCNT=$((OCNT+1))
				rm "$INTPAKWA" 2>/dev/null
			fi
		done <<< "$(grep "$LIINPA" "$OEVALSC" | grep -v "${STEWOS}\|${STLDLDIR}\|STESHA\|STLDLDIR")"
		
		echo "}" >> "$TEVALSC"
		writelog "INFO" "${FUNCNAME[0]} - Created temporary '$TEVALSC'"
	}

	mkProjDir "$EVMETACUSTOMID"
	mkProjDir "$EVMETAADDONID"
	
	writelog "INFO" "${FUNCNAME[0]} - Starting Gui for Creating a custom '$EVALSC'"
	export CURWIKI="$PPW/Steam-First-Time-Setup"
	TITLE="${PROGNAME}-${FUNCNAME[0]}"
	pollWinRes "$TITLE"
	setShowPic

	EUNID="$1"

	REVALSC="$EVMETAID/${EVALSC}_${EUNID}.vdf"
	CEVALSC="$EVMETACUSTOMID/${EVALSC}_${EUNID}.vdf"
	AEVALSC="$EVMETAADDONID/${EVALSC}_${EUNID}.vdf"
	TEVALSC="${STLSHM}/${EVALSC}_${EUNID}_temp.vdf"

	REVP="packages"
	SEVP="stlpackages"
	GLOBEVPACKS="${GLOBALEVALDIR}/$REVP"
	GLOBSTLEVPACKS="${GLOBALEVALDIR}/$SEVP"

	GLOBEVPACKORDER="${GLOBALEVALDIR}/order.txt"
	TEVALSCSEL="$NON"

	if [ -f "$REVALSC" ]; then
		FOUNDEVALSC="Original"
		OEVALSC="$REVALSC"
		TEVALSCSEL="Original"
	fi
	
	if [ -f "$CEVALSC" ]; then
		if [ -n "$FOUNDEVALSC" ]; then
			FOUNDEVALSC="${FOUNDEVALSC}, Custom"
		else
			FOUNDEVALSC="Custom"
		fi
		OEVALSC="$CEVALSC"
		TEVALSCSEL="Custom"
	fi
	
	if [ -f "$AEVALSC" ]; then
		if [ -n "$FOUNDEVALSC" ]; then
			FOUNDEVALSC="${FOUNDEVALSC}, Addon"
		else
			FOUNDEVALSC="Addon"
		fi
		OEVALSC="$AEVALSC"
		TEVALSCSEL="Addon"
	fi

	if [ -f "$OEVALSC" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Pre-Selection is based on packages enabled in '$OEVALSC'"
	else
		TEVALSCSEL="$NON"
	fi

	GUITEXT1="$(strFix "$GUI_FOUNDEVALSC" "$FOUNDEVALSC")"
	GUITEXT2="$(strFix "$GUI_TEVALSCSEL" "$TEVALSCSEL")"
	GUITEXT3="$(strFix "$GUI_ADDEVALSC" "$SHADDESTDIR")"

	EVALSCFILES="$(
	while read -r EPACK; do
		if [ -f "$OEVALSC" ]; then
			PACKPROC="$(grep "process 1" "$EPACK")"
			if [ -n "$PACKPROC" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Searching in '$PACKPROC' '$OEVALSC'"
				if grep -Fq "$PACKPROC" "$OEVALSC"; then
					echo TRUE ; echo "${EPACK##*/}"
				else
					echo FALSE ; echo "${EPACK##*/}"
				fi
			else
				echo FALSE ; echo "${EPACK##*/}"
			fi
		else
			echo FALSE ; echo "${EPACK##*/}"
		fi
	done <<< "$(find "${GLOBALEVALDIR}" \( -type f -and -path "*/$REVP/*" -or -path "*/$SEVP/*" \))" | \
		"$YAD" --f1-action="$F1ACTION" --image "$SHOWPIC" --image-on-top --window-icon="$STLICON" --center "$WINDECO" \
		--list --checklist --column="$GUI_ADD" --column=Script --separator="" --print-column="2" \
		--text="${GUITEXT1}\n$GUITEXT2\n$GUITEXT3" \
		--title="$TITLE" \
		--button="$BUT_SAEVALSC":2 --button="$BUT_SCEVALSC":4 --button="$BUT_ONLYINSTALL":6 --button="$BUT_CAN":8 \
		"$GEOM"
	)"
	case $? in
		2) 	{
				createTempEvals
				writelog "INFO" "${FUNCNAME[0]} - Selected Saving as Addon '$EVALSC': '$AEVALSC'"
				if [ -f "$AEVALSC" ]; then
					mv "$AEVALSC" "${AEVALSC//.vdf/_back.vdf}"
				fi
				mv "$TEVALSC" "$AEVALSC"
			}
		;;
		4)	{
				createTempEvals
				writelog "INFO" "${FUNCNAME[0]} - Selected Saving as Custom '$EVALSC': '$CEVALSC'"
				if [ -f "$CEVALSC" ]; then
					mv "$CEVALSC" "${CEVALSC//.vdf/_back.vdf}"
				fi
				mv "$TEVALSC" "$CEVALSC"
			}
		;;
		6)	{
				writelog "INFO" "${FUNCNAME[0]} - Selected to only install the packages without saving"
				createTempEvals
				writelog "INFO" "${FUNCNAME[0]} - Starting Install via command: reCreateCompatdata \"$EUNID\" \"${FUNCNAME[0]}\" \"$TEVALSC\""
				reCreateCompatdata "$EUNID" "${FUNCNAME[0]}" "$TEVALSC"
			}
		;;
		8)	{
				writelog "INFO" "${FUNCNAME[0]} - Selected CANCEL"
			}
		;;
	esac
}

function reCreateCompatdata {
	function runEvalsc {
		unset LEV
		mapfile -d " " -t -O "${#LEV[@]}" LEV <<< "run ${ISCEXE} ${LECO}\\${EVALSC}_${1}.vdf"
		rm "$EVALISRUN" 2>/dev/null
		touch "$EVALISRUN"
		checkFirstTimeRun "${LEV[@]}" >/dev/null 2>/dev/null
		rm "$EVALISRUN"	"$FRSTATE" "${FRSTATE}-prev" 2>/dev/null
		doneEvacInstall
	}
	
	function getCurStep {
		unset GCS
		mapfile -d " " -t -O "${#GCS[@]}" GCS <<< "run ${ISCEXE} --${GECUST} ${1}"
		checkFirstTimeRun "${GCS[@]}" >/dev/null 2>/dev/null
		PRFRSTATE="${FRSTATE}-prev"

		if [ -f "$FRSTATE" ]; then
			if ! cmp -s -- "$FRSTATE" "$PRFRSTATE"; then
				cp "$FRSTATE" "$PRFRSTATE"
				notiShow "$(strFix "$NOTY_FRSTATE" "$(cat "$FRSTATE")")" "X"
				writelog "INFO" "${FUNCNAME[0]} - $(strFix "$NOTY_FRSTATE" "$(cat "$FRSTATE")")"
			fi
		fi
	}

	WANTGUI=0
	if [ "$1" == "ccd" ] || [ "$1" == "createcompatdata" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Started from command-line"
		EUNID="$2"
		if [ -n "$3" ]; then
			WANTGUI=1
		fi
	else
		writelog "INFO" "${FUNCNAME[0]} - Started from gui"
		EUNID="$1"
		WANTGUI=1
		BACKFUNC="$2"
	fi

	SCCILECO="$STEAM_COMPAT_CLIENT_INSTALL_PATH/$LECO"
	ISCEXE="$SCCILECO/$ISCRI.exe"
	
	if [ -n "$EUNID" ]; then
		SRCORIGEVSC="$EVMETAID/${EVALSC}_${EUNID}.vdf"
		SRCCUSTEVSC="$EVMETACUSTOMID/${EVALSC}_${EUNID}.vdf"

		if [ "$EUNID" == "$DPRS" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Starting '$DPRS' Installation"
			SRCORIGEVSC="${GLOBALEVALDIR}/sets/${EVALSC}_${DPRS,}.vdf"
			SRCEVSC="$SRCORIGEVSC"
			DESTCODA="$DPRSCOMPDATA"
			EARLYPROT="$DPRSPROTON"
			export STEAM_COMPAT_APP_ID="$DPRS"
			STEAM_COMPAT_INSTALL_PATH="$DPRSCOMPDATA"
		fi	
		
		if [ ! -f "$ISCEXE" ]; then
			writelog "ERROR" "${FUNCNAME[0]} - '$ISCEXE' not found"
		else		
			if [ ! -f "$SRCORIGEVSC" ] && [ ! -f "$SRCCUSTEVSC" ]; then
				if [ "$WANTGUI" -eq 0 ]; then
					writelog "ERROR" "${FUNCNAME[0]} - Neither '$SRCORIGEVSC' nor '$SRCCUSTEVSC' found (see wiki if the reason for not being able to continue is unknown)"
					writelog "ERROR" "${FUNCNAME[0]} - Alternatively start the same command with an additional 'gui' parameter, to create a '$SRCCUSTEVSC' via gui"
					HAVEEVSC=0
				else
					writelog "INFO" "${FUNCNAME[0]} - Requester to create a custom Install file via Gui"
					CreateCustomEvaluatorScript "$EUNID"
					if [ -f "$SRCCUSTEVSC" ]; then
						HAVEEVSC=1
					else
						HAVEEVSC=0
					fi
				fi
			else
				HAVEEVSC=1
			fi
			
			if [ "$HAVEEVSC" -eq 1 ]; then
				if [ -f "$CUMETA/${EUNID}.conf" ]; then
					writelog "INFO" "${FUNCNAME[0]} - Loading Metadata '$CUMETA/${EUNID}.conf'"
					loadCfg "$CUMETA/${EUNID}.conf"
				fi

				if [ -z "$DESTCODA" ]; then
					if [ -n "$WINEPREFIX" ]; then
						DESTCODA="${WINEPREFIX%/*}"
					elif [ -n "$STEAM_COMPAT_DATA_PATH" ]; then
						DESTCODA="$STEAM_COMPAT_DATA_PATH"
					elif [ -n "$GPFX" ]; then
						DESTCODA="${GPFX%/*}"
					else
						getCompatData "${EUNID}" >/dev/null
						DESTCODA="$(cut -d ';' -f2 <<< "$FCOMPDAT")"
					fi
				fi

				if [ -n "$DESTCODA" ]; then
					export STEAM_COMPAT_DATA_PATH="$DESTCODA"
					writelog "INFO" "${FUNCNAME[0]} - Destination $CODA is '$STEAM_COMPAT_DATA_PATH'"

					if [ -z "$STEAM_COMPAT_INSTALL_PATH" ]; then
						if [ -n "$MEGAMEDIR" ]; then
							export STEAM_COMPAT_INSTALL_PATH="$MEGAMEDIR"
						elif [ -n "$EFD" ]; then
							export STEAM_COMPAT_INSTALL_PATH="$EFD"
						else
							writelog "INFO" "${FUNCNAME[0]} - STEAM_COMPAT_INSTALL_PATH (game dir) is unknown - setting it at least to '${STLDLDIR}'"
							export STEAM_COMPAT_INSTALL_PATH="$STLDLDIR"
						fi
					fi

					RECRECODA=1

					find "$DESTCODA" -maxdepth 0 -empty -exec rmdir {} \; 2>/dev/null

					if [ -d "$DESTCODA" ]; then
						if [ "$3" == "s" ]; then
							RCSEL="$(confirmReq "Ask_Recreate_Compatdata" "$(strFix "$GUI_RECRECODA" "$EUNID" "${EUNID}_${PROGNAME,,}")")"
							if [ "$RCSEL" -eq 0 ]; then
							{
								writelog "INFO" "${FUNCNAME[0]} - Confirmed recreating the wineprefix"
								RECRECODA=1
							}
							else
								writelog "INFO" "${FUNCNAME[0]} - Selected CANCEL - Not recreating the wineprefix"
								RECRECODA=0
							fi
						fi

						if [ "$RECRECODA" -eq 1 ]; then
							if [ -d "${DESTCODA}_${PROGNAME,,}" ]; then
								writelog "INFO" "${FUNCNAME[0]} - Removing previous backup $CODA backup '${DESTCODA}_${PROGNAME,,}'"
								rm -rf "${DESTCODA}_${PROGNAME,,}" 2>/dev/null
							fi
							
							find "$DESTCODA" -maxdepth 0 -empty -exec rmdir {} \;

							if [ -d "$DESTCODA" ]; then
								writelog "INFO" "${FUNCNAME[0]} - Moving existing $CODA to '${DESTCODA}_${PROGNAME,,}'"
								mv "$DESTCODA" "${DESTCODA}_${PROGNAME,,}"
							fi
						fi
					fi

					if [ "$RECRECODA" -eq 1 ]; then
						if [ -z "$STEAM_COMPAT_APP_ID" ]; then
							export STEAM_COMPAT_APP_ID="${EUNID}"
						fi

						mkProjDir "$DESTCODA"
						EVALISRUN="$STLSHM/evalisrun.txt"
						
						cd "$STEAM_COMPAT_CLIENT_INSTALL_PATH" >/dev/null || return
						
						writelog "INFO" "${FUNCNAME[0]} - Launching First Run Installer"

						runEvalsc "${EUNID}" &

						while [ ! -f "$EVALISRUN" ];do
							sleep 0.1
						done
						
						while [ -f "$EVALISRUN" ];do
							getCurStep "${EUNID}"
							sleep 1
						done
						
						cd - >/dev/null || return
					fi
				else
					writelog "SKIP" "${FUNCNAME[0]} - No destination $CODA determined"
				fi
			fi

			if [ -n "$BACKFUNC" ]; then
				"$BACKFUNC" "$AID" "${FUNCNAME[0]}"
			fi
		fi
	else
		writelog "SKIP" "${FUNCNAME[0]} - Need SteamAppId as argument"
	fi
}

function createModifiedEvalsc {
	if [ -z "$ISCRILOG" ]; then
		ISCRILOG="$STLSHM/${PROGNAME,,}-${ISCRI}-temp_$RANDOM.log"
	fi 

	STESHA="$STEAM_COMPAT_CLIENT_INSTALL_PATH$SAC/$STEWOS"
	if [ ! -d "$STESHA" ]; then
		writelog "WARN" "${FUNCNAME[0]} - '$STESHA' not found - packages expected there won't be found" "X" "$ISCRILOG"
	fi

	SOURCEEVALSC="$1"
	DSTEVALSC="$2"

	if [ ! -f "$SOURCEEVALSC" ]; then
		writelog "SKIP" "${FUNCNAME[0]} - '$SOURCEEVALSC' does not exists" "X" "$ISCRILOG"
	elif [ ! -f "$DSTEVALSC" ]; then
		SCCILECO="$STEAM_COMPAT_CLIENT_INSTALL_PATH/$LECO"

		# creating a temporary copy of the evaluatorscript in $SCCILECO:
		writelog "INFO" "${FUNCNAME[0]} - Copying '$SOURCEEVALSC' to '$SCCILECO'" "X" "$ISCRILOG"
		cp "$SOURCEEVALSC" "$DSTEVALSC"
		
		# replace placeholders with real paths
		writelog "INFO" "${FUNCNAME[0]} - Replacing placeholders with real paths in '$DSTEVALSC'" "X" "$ISCRILOG"
		sed "s:STESHA:$STESHA:g" -i "$DSTEVALSC"
		sed "s:STLDLDIR:$STLDLDIR:g" -i "$DSTEVALSC"
	else
		writelog "SKIP" "${FUNCNAME[0]} - '$DSTEVALSC' already exists" "X" "$ISCRILOG"
	fi
}

function cleanupOutdatedEvals {
	writelog "INFO" "${FUNCNAME[0]} - Cleaning up outdated files in '$EVMETAID'"

	mkProjDir "$EVMETAOLD"
	while read -r oldfile; do
		if [ -f "$oldfile" ]; then
			mv "$oldfile" "$EVMETAOLD"
		fi
	done <<< "$(grep -Rl "foreign_install_path" "$EVMETAID")"
	
	while read -r oldfile; do
		if [ -f "$oldfile" ]; then
			while read -r lipent; do
				ABSLIINPA="$(cut -d \" -f4 <<< "$lipent")" # too weak?
				if [ ! -d "${ABSLIINPA//\"}" ] && [ "${ABSLIINPA//\"}" != "STLDLDIR" ] && [ "${ABSLIINPA//\"}" != "STESHA" ]; then
					mv "$oldfile" "$EVMETAOLD"
				fi
			done <<< "$(grep "$LIINPA" "$oldfile")"
		fi
	done <<< "$(grep -Rl "$LIINPA" "$EVMETAID")"
	writelog "INFO" "${FUNCNAME[0]} - Finished cleaning up '$EVMETAID'"
}

function doneEvacInstall {
	notiShow "$(strFix "$NOTY_FRDONE" "$EUNID")" "X"
	writelog "INFO" "${FUNCNAME[0]} - $(strFix "$NOTY_FRDONE" "$EUNID")" "E"	
}

function runEvacInstall {
	INSTPROT="$1"
	# call $ISCRI via proton with the modified evaluatorscript as parameter:
	writelog "INFO" "${FUNCNAME[0]} - '$EVALSC' - START - STEAM_COMPAT_DATA_PATH=\"$STEAM_COMPAT_DATA_PATH\" '$INSTPROT run $ISCEXE $EVSC'" "X" "$ISCRILOG"
	STEAM_COMPAT_DATA_PATH="$STEAM_COMPAT_DATA_PATH" "$INSTPROT" run "$ISCEXE" "$EVSC"
	# move the temporary modified evaluatorscript into '$STMSHM'
	mv "$DSTEVSC" "$STLSHM/${DSTEVSC##*/}_$RANDOM"
}

function checkFirstTimeRun {
	ISCRILOG="$STLSHM/${PROGNAME,,}-${ISCRI}-${STEAM_COMPAT_APP_ID}.log"
	GPFX="$STEAM_COMPAT_DATA_PATH/pfx"
	SCCILECO="$STEAM_COMPAT_CLIENT_INSTALL_PATH/$LECO"
	ISCEXE="$SCCILECO/$ISCRI.exe"
	EVALPROTCONF="$STLSHM/evalprot-${STEAM_COMPAT_APP_ID}.conf"
	
	function waitForEvaluatorscript {
		mkProjDir "$EVMETAID"
		mkProjDir "$EVMETATITLE"
		
		ISCRILOG="$2"
		EVALVDF="$SCCILECO/$1"
		writelog "INFO" "${FUNCNAME[0]} - Waiting for '$EVALVDF' to appear" "X" "$ISCRILOG"
		while [ ! -f "$EVALVDF" ]; do 
			sleep 0.1
		done
		cp "$EVALVDF" "$EVMETAID"
		writelog "INFO" "${FUNCNAME[0]} - Copied '$EVALVDF' to '$EVMETAID/$1'" "X" "$ISCRILOG"
	}
	
	function findEarlyProt {
		if [ -n "$2" ]; then
			ISCRILOG="$2"
			writelog "INFO" "${FUNCNAME[0]} - Trying to get a proton version from '$1'" "X" "$ISCRILOG"
			if grep -q "^USEPROTON" "$1"; then
				CONFPROTRAW="$(grep "^USEPROTON" "$1" | cut -d '=' -f2)"
				CONFPROT="${CONFPROTRAW//\"}"

				if [ -z "$SUSDA" ]; then
					setSteamPaths
				fi
				
				createProtonList
				
				if [ -f "$PROTONCSV" ]; then
					writelog "INFO" "${FUNCNAME[0]} - Searching '$CONFPROT' in '$PROTONCSV'" "X" "$ISCRILOG"

					if grep -q "^${CONFPROT}" "$PROTONCSV"; then
						writelog "INFO" "${FUNCNAME[0]} - Found '$CONFPROT' in '$PROTONCSV'" "X" "$ISCRILOG"
						EARLYPROT="$(grep "^${CONFPROT}" "$PROTONCSV" | cut -d ';' -f2)"
						export EARLYPROT
					else
						writelog "INFO" "${FUNCNAME[0]} - '$CONFPROT' not found in '$PROTONCSV'" "X" "$ISCRILOG"
						# if configured USEPROTON proton binary was not found, try to find a minor version bump instead:
						TESTEARLYPROT="$(fixProtonVersionMismatch "CONFPROT" "$STLGAMECFG" "X")"
						if [ -f "$TESTEARLYPROT" ]; then
							writelog "INFO" "${FUNCNAME[0]} - Found a minor version mismatch binary for '$CONFPROT':'$TESTEARLYPROT'" "X" "$ISCRILOG"
							EARLYPROT="$TESTEARLYPROT"
							export EARLYPROT
						else
							writelog "SKIP" "${FUNCNAME[0]} - Found '$TESTEARLYPROT' does not exist" "X" "$ISCRILOG"
						fi
					fi
				else
					writelog "ERROR" "${FUNCNAME[0]} - Could not create '$PROTONCSV'" "X" "$ISCRILOG"
				fi
			else
				writelog "SKIP" "${FUNCNAME[0]} - No USEPROTON entry found in '$1'" "X" "$ISCRILOG"
			fi
		fi	
	}

	rmOldLog

	if [ -n "$STEAM_RUNTIME_LIBRARY_PATH" ]; then
		touch "$STLSHM/SteamStart_${STEAM_COMPAT_APP_ID}.txt"
	fi
	
	if [ -f "$(find "$LOGFILE" -not -newermt '-5 seconds' 2>/dev/null)" ]; then
		if ! grep -q "$ISCRI" <<< "$(tail -n1 "$LOGFILE")"; then
			writelog "START" "######### '$ISCRI' #########" "X" "$ISCRILOG"
		fi
	fi
	# skip $ISCRI completely if a SKIP file exists for $STEAM_COMPAT_APP_ID
	if [ -f "$EVMETASKIPID/${EVALSC}_${STEAM_COMPAT_APP_ID}.vdf" ]; then
		writelog "SKIP" "${FUNCNAME[0]} - Skipping '$ISCRI' line '$*' because '$EVMETASKIPID/${EVALSC}_${STEAM_COMPAT_APP_ID}.vdf' exists" "X" "$ISCRILOG"
	else
		# filter evaluatorscript command
		if grep -q "$EVALSC" <<< "$@"; then
			# shellcheck disable=SC1003
			EVSC="$(awk -F 'legacycompat\\\' '{print $NF}' <<< "$@")"
		fi

		cleanupOutdatedEvals

		# check if evaluatorscript should be started:
		if [ ! -d "$GPFX" ] || [ ! -f "$EVMETAID/$EVSC" ]; then
			# get a proton version for the install process:
			if grep -q "$EVALSC" <<< "$@"; then

				# first check if the game has a game has a ${PROGNAME,,} config and use the corresponding proton version:
				if [ -z "$EARLYPROT" ] && [ ! -f "$EVALPROTCONF" ] && [ -f "$STLGAMEDIRID/$STEAM_COMPAT_APP_ID.conf" ]; then
					findEarlyProt "$STLGAMEDIRID/$STEAM_COMPAT_APP_ID.conf" "$ISCRILOG"
				fi
				# as fallback check if the game template ${PROGNAME,,} config has a usable proton version:
				if [ -z "$EARLYPROT" ] && [ ! -f "$EVALPROTCONF" ] && [ -f "$STLDEFGAMECFG" ]; then
					findEarlyProt "$STLDEFGAMECFG" "$ISCRILOG"
				fi

				# if everything else failed, check for a "static proton version" just for the base install - either from file or from system variable:
				if [ -z "$EARLYPROT" ] && [ ! -f "$EVALPROTCONF" ] && [ -f "$STLEARLYPROTCONF" ]; then
					writelog "INFO" "${FUNCNAME[0]} - Trying to get a proton version from '$STLEARLYPROTCONF'" "X" "$ISCRILOG"
					source "$STLEARLYPROTCONF"
				fi

				# fallback if for whatever reason USEPROTON is empty everywhere - trying to get NOP
				if [ -z "$EARLYPROT" ]; then
					writelog "INFO" "${FUNCNAME[0]} - Last try - trying to get Newest Official Proton" "X" "$ISCRILOG"
					CONFPROT="$(getDefaultProton)"
					createProtonList
					EARLYPROT="$(grep "^${CONFPROT}" "$PROTONCSV" | cut -d ';' -f2)"
				fi
				
				# write found protonversion into temp config, so below GECUST runs can use it as well:
				if [ -n "$EARLYPROT" ]; then
					writelog "INFO" "${FUNCNAME[0]} - Writing 'EARLYPROT=$EARLYPROT' into '$EVALPROTCONF'" "X" "$ISCRILOG"
					echo "EARLYPROT=\"$EARLYPROT\"" > "$EVALPROTCONF"
					echo "TEVSC=\"$EVSC\"" >> "$EVALPROTCONF"
				fi			
			fi

			# reload proton version from above EVALSC run:
			TEVSC="$NON"
			if [ -z "$EARLYPROT" ] && [ -f "$EVALPROTCONF" ]; then
				source "$EVALPROTCONF"
			fi
			# only continue with proton being available:
			if [ -n "$EARLYPROT" ] && [ -f "$EARLYPROT" ]; then
					# filter evaluatorscript command
					if grep -q "$EVALSC" <<< "$@"; then
						mapfile -d " " -t -O "${#RUNISCCMD[@]}" RUNISCCMD < <(printf '%s' "$(awk -F 'run ' '{print $NF}' <<< "$*")")
						# no evaluatorscript for the started game yet in the metadata - so starting the collector:
						
						SRCCUSTEVSC="$EVMETACUSTOMID/$EVSC"
						SRCORIGEVSC="$EVMETAID/$EVSC"
						
						TEVALSC="${STLSHM}/${EVALSC}_${STEAM_COMPAT_APP_ID}_temp.vdf"
						if [ -f "$TEVALSC" ]; then
							SRCEVSC="$TEVALSC"
							writelog "INFO" "${FUNCNAME[0]} - Using '$SRCEVSC' as source" "X" "$ISCRILOG"
						fi
						
						if [ -z "$SRCEVSC" ]; then
							if [ ! -f "$SRCORIGEVSC" ] && [ ! -f "$SRCCUSTEVSC" ]; then
								SRCEVSC="$SRCORIGEVSC"
								writelog "INFO" "${FUNCNAME[0]} - Both the copy '$SRCORIGEVSC' of the original and a custom '$SRCCUSTEVSC' are missing - trying to get the original'" "X" "$ISCRILOG"
							elif [ -f "$SRCORIGEVSC" ] && [ ! -f "$SRCCUSTEVSC" ]; then
								SRCEVSC="$SRCORIGEVSC"
								writelog "INFO" "${FUNCNAME[0]} - Using '$SRCEVSC' as source" "X" "$ISCRILOG"
							elif [ -f "$SRCORIGEVSC" ] && [ -f "$SRCCUSTEVSC" ]; then
								SRCEVSC="$SRCCUSTEVSC"
								writelog "INFO" "${FUNCNAME[0]} - Using custom '$SRCCUSTEVSC' as source, as it overrides the original '$SRCORIGEVSC' which also does exist" "X" "$ISCRILOG"
							elif [ ! -f "$SRCORIGEVSC" ] && [ -f "$SRCCUSTEVSC" ]; then
								SRCEVSC="$SRCCUSTEVSC"
								writelog "INFO" "${FUNCNAME[0]} - Using custom '$SRCCUSTEVSC' as source, and the original '$SRCORIGEVSC' does not exist" "X" "$ISCRILOG"
							fi
						fi
					
						if [ -n "$EVSC" ] && [ ! -f "$SRCEVSC" ] && [ "$SRCEVSC" == "$SRCORIGEVSC" ]; then
							waitForEvaluatorscript "$EVSC" "$ISCRILOG" &
							writelog "INFO" "${FUNCNAME[0]} - '$EVALSC' START - '$EARLYPROT run ${RUNISCCMD[*]}'" "X" "$ISCRILOG"
							"$EARLYPROT" run "${RUNISCCMD[@]}"
							while [ ! -f "$SRCEVSC" ]; do 
								sleep 0.1
							done
						fi

						# have a evaluatorscript to work with:
						if [ -f "$SRCEVSC" ]; then
							DSTEVSC="$STEAM_COMPAT_CLIENT_INSTALL_PATH/$EVSC"
							createModifiedEvalsc "$SRCEVSC" "$DSTEVSC"

							if grep -q "$EVMETACUSTOMID" <<< "$SRCEVSC" ; then
								notiShow "$(strFix "$NOTY_FRSTART" "Custom")" "X"
							elif grep -q "$STLSHM" <<< "$SRCEVSC" ; then
								notiShow "$(strFix "$NOTY_FRSTART" "Live")" "X"			
							else
								notiShow "$(strFix "$NOTY_FRSTART" "Regular")" "X"
							fi

							runEvacInstall "$EARLYPROT"
							SRCADDONEVSC="$EVMETAADDONID/$EVSC"
							if [ -f "$SRCADDONEVSC" ]; then
								writelog "INFO" "${FUNCNAME[0]} - Found additional install script in '$SRCADDONEVSC'" "X" "$ISCRILOG"
								
								DSTEVSC="$STEAM_COMPAT_CLIENT_INSTALL_PATH/$EVSC"
								createModifiedEvalsc "$SRCADDONEVSC" "$DSTEVSC"
								notiShow "$(strFix "$NOTY_FRSTART" "Addon")" "X"
								runEvacInstall "$EARLYPROT"
							fi
				
							if [ "$SRCEVSC" == "$TEVALSC" ]; then
								rm "$TEVALSC" 2>/dev/null
								writelog "INFO" "${FUNCNAME[0]} - Removed temporary '$TEVALSC'" "X" "$ISCRILOG"
							fi

							writelog "INFO" "${FUNCNAME[0]} - '$EVALSC' - STOP - '$EARLYPROT run $ISCEXE $EVSC'" "X" "$ISCRILOG"
						else
							writelog "INFO" "${FUNCNAME[0]} - '$EVALSC' - SKIP - '$SRCEVSC' not found" "X" "$ISCRILOG"
						fi
					# filter get-current-step command - this only updates the steam install gui process.
					elif grep -q "$GECUST" <<< "$@"; then
						"$EARLYPROT" "$@" | tee "$FRSTATE" | tee -a "$ISCRILOG"
						echo "" >> "$ISCRILOG"
						STINFO="$(date +%H:%M:%S) $NICEPROGNAME running"
						if [ -f "$TEVSC" ]; then
							# shellcheck disable=SC1003
							while read -r COMRED; do
								if "$PGREP" -a "" | grep "$STEWOS" | grep -v "runasadmin" | grep "${COMRED//\"}" >/dev/null ; then
										writelog "INFO" "${FUNCNAME[0]} - Installation of '${COMRED//\"}' running" | tee -a "$ISCRILOG"
									STINFO="$(date +%H:%M:%S) $NICEPROGNAME sees ${COMRED//\"}"
									break
								fi
							done <<< "$(grep "process 1" "$TEVSC" | awk -F'\\' '{print $NF}')"
						fi
						printf '\n%s\n' "$STINFO"	# heh, hello Steam Gui
					# should not happen, but better log it anyway just in case:
					else
						writelog "SKIP" "${FUNCNAME[0]} - Skipping '$ISCRI' command '$*' - Exiting" "X" "$ISCRILOG"
					fi
			else
				if ! grep -q "$GECUST" <<< "$@"; then
					writelog "SKIP" "${FUNCNAME[0]} - No usable Proton version found - ignoring '$ISCRI' command '$*' - Exiting" "X" "$ISCRILOG"
				fi
			fi
		else
			writelog "SKIP" "${FUNCNAME[0]} - Skipping '$ISCRI' command '$*' - Exiting" "X" "$ISCRILOG"
		fi
	fi
}

function getCurrentCommandline {
	# filter $ISCRI commands
	if grep -q "$ISCRI" <<< "$@"; then
		writelog "INFO" "${FUNCNAME[0]} - Running checkFirstTimeRun with arguments '${*}'" "P"
		checkFirstTimeRun "$@"
		exit
	else
		echo "$@" > "${STLSHM}/cmdline.txt"
		INPROSTR="proton $WFEAR"
		if grep -q "$INPROSTR" <<< "$@"; then
			HAVEINPROTON=1
			writelog "INFO" "${FUNCNAME[0]} - Found Proton in command line arguments '${*}'" "P"
		else
			HAVEINPROTON=0
			writelog "INFO" "${FUNCNAME[0]} - No Proton in command line arguments '${*}'" "P"
		fi
	fi
}

function initShmStl {
	mkProjDir "$MTEMP"
	SHMVERS="$STLSHM/version"
	
	if [ -f "$SHMVERS" ]; then
		if [ "$PROGVERS" != "$(cat "$SHMVERS")" ]; then
			mv "${STLSHM}" "${STLSHM}-$((100 + RANDOM % 100))"
			mkProjDir "$MTEMP"
			echo "$PROGVERS" > "$SHMVERS"
		fi	
	else
		echo "$PROGVERS" > "$SHMVERS"
	fi
}

##################

function main {

	initShmStl
	rm "$TEMPLOG" "$WINRESLOG" "$PRELOG" "$APPMALOG" "$GGDLOG" 2>/dev/null
	touch "$PRELOG"
	mkProjDir "$LOGDIRID"
	initAID "$@"
	setAIDCfgs
	loadLangFile "$STLDEFLANG"
	getCurrentCommandline "$@"
	saveOrgVars
	emptyVars "O"

	writelog "START" "######### Initializing Game Launch $AID using $PROGNAME $PROGVERS #########" "P"

	if [ -f "$STLDEFGLOBALCFG" ] && grep -q "^RESETLOG=\"1\"" "$STLDEFGLOBALCFG"; then
		if [ -f "$PRELOG" ]; then
			mv "$PRELOG" "$LOGFILE"
		else
			rmOldLog
			rm "$PRELOG" 2>/dev/null
		fi
		# from here the '$LOGFILE' is written directly
		writelog "INFO" "${FUNCNAME[0]} - Starting with a clean log"
	fi

	writelog "INFO" "${FUNCNAME[0]} - Start creating default configs"
	createDefaultCfgs "$@"

	writelog "INFO" "${FUNCNAME[0]} - Checking internal dependencies:"
	checkIntDeps "$@"

	writelog "INFO" "${FUNCNAME[0]} - Initializing first Proton:"
	initFirstProton

	writelog "INFO" "${FUNCNAME[0]} - Initializing default window resolution"
	setInitWinXY

	if [ -z "$1" ]; then
		writelog "INFO" "${FUNCNAME[0]} - No arguments provided. See '$PROGCMD --help' for possible command line parameters" "E"
	else
		writelog "INFO" "${FUNCNAME[0]} - Checking command line: incoming arguments '${*}'"

		if [ -n "$SteamAppId" ] && [ "$SteamAppId" -eq "0" ]; then
			if grep -q "\"$1\"" <<< "$(sed -n "/^#STARTCMDLINE/,/^#ENDCMDLINE/p;/^#ENDCMDLINE/q" "$0" | grep if)"; then
				writelog "INFO" "${FUNCNAME[0]} - Seems like a '$PROGCMD'-internal command was started - checking the command line"
				commandline "$@"
			else
				setCustomGameVars "$@"
				if [ -n "$ISGAME" ]; then
					if [ "$ISGAME" -eq 2 ] || [ "$ISGAME" -eq 3 ]; then
						prepareLaunch
					fi
				else
					writelog "ERROR" "${FUNCNAME[0]} - Unknown command '$*'" "E"
				fi
			fi
		elif grep -q "$SAC" <<< "$@" || grep -q "$L2EA" <<< "$@"; then
			if grep -q "update" <<< "$@" || grep -q "^play" <<< "$@" ; then
				commandline "$@"
			else
				setGameVars "$@"

				if [ "$ISGAME" -eq 2 ] || [ "$ISGAME" -eq 3 ]; then
					prepareLaunch
				else
					writelog "INFO" "${FUNCNAME[0]} - Unknown parameter '${ORGGCMD[*]}'" "E"
				fi
			fi
		else
			commandline "$@"
		fi
	fi
}

if [ "$EUID" = 0 ]; then
	echo "'$PROGCMD' is not meant to be run as root - Exiting"
else
	main "$@"
fi
