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

### project ###

PROGNAME="SteamTinkerLaunch"
NICEPROGNAME="Steam Tinker Launch"
PROGVERS="v6.15"
PROGCMD="${0##*/}"
GHURL="https://github.com"
PROJECTPAGE="$GHURL/frostworx/steamtinkerlaunch"
PPW="$PROJECTPAGE/wiki"
CURWIKI="$PPW"

### internal dependencies ###
#STARTINTDEPS
GIT="git"
PGREP="pgrep"
PIDOF="pidof"
PKILL="pkill"
TAR="tar"
UNZIP="unzip"
WGET="wget"
WHICH="which"
XDO="xdotool"
XPROP="xprop"
XRANDR="xrandr"
XWININFO="xwininfo"
AWK="gawk"
#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"
OSSL="openssl"
CONTY="conty.sh"

STARTDEBUG=0
HAVEOSSL=1
CHECKHMD=1
X32D="x32dbg"
X64D="x64dbg"
FACO="favorites.conf"
MENSO="menusort.conf"
MENUBLOCK="menublock.conf"
DSHM="/dev/shm"
STLSHM="$DSHM/$PROGCMD"
MTEMP="$STLSHM/menutemp"
STLICON="$STLSHM/stl-steam-checked.png"
NOICON="$STLSHM/empty.png"
FAVPIC="$STLSHM/fav.jpg"
DFDIR="$STLSHM/desktopfiles"
CLOSETMP="$STLSHM/${PROGCMD}-closing.tmp"
KILLSWITCH="$STLSHM/KillSwitch"
TEMPLOG="$STLSHM/${PROGCMD}.log"
WINRESLOG="$STLSHM/winres.log"
GWIDFILE="$STLSHM/${PROGCMD}-sbsgwid"
PIDLOCK="$STLSHM/pid.lock"
VRINITLOCK="$STLSHM/vrinit.lock"
IGCSINITLOCK="$STLSHM/igcsinit.lock"
VRINITRESULT="$STLSHM/vrinit.conf"
UUUPATCH="$PROGCMD-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"
NON="none"
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"
LSAD="$LOSE/$APDA"
RUNCONTY="$NON"
WINX="800"
WINY="600"
F1ACTION="bash -c OpenWiki"
F1ACTIONCG="bash -c setColGui"
BTS="backup-timestamp"
### default vars ###

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

SYSTEMSTLCFGDIR="/usr/share/$PROGCMD"														# systemwide config dir
BASELOGDIR="$STLCFGDIR/logs"																# base logfile dir
DEFLOGDIR="$BASELOGDIR/$PROGCMD"															# default stllogfile 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
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"
STLCOMPDAT="$STLCFGDIR/compatdata"
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"
STUS="steamuser"
SUBADIR="$STLBACKDIR/$STUS"
SUBADIRID="$SUBADIR/id"
SUBADIRTI="$SUBADIR/title"
RSP="reshadepresets"
STLRSPRESETDIR="$STLCFGDIR/$RSP"
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"
STLVORTEXDIR="$STLCFGDIR/$VTX"
VORTEXDLDIR="$STLDLDIR/Vortex"
PLACEHOLDERAID="31337"
PLACEHOLDERGN="Placeholder"

SOMEPOPULARWINEPAKS="dotnet4 quartz xact"
SOMEWINEDEBUGOPTIONS="-all,+steam,+vrclient,+vulkan"
SOMEWINEDLLOVERRIDES="dxgi=n,b;d3d9=n,b;d3dcompiler_47=n,b"
SGDBDIMOPTS="460x215,920x430,600x900,342x482,660x930"
SGDBSTYOPTS="alternate,blurred,white_logo,material,no_logo"

STLGAMES="$STLCFGDIR/games"
STLGDESKD="$STLGAMES/desktop"
STLIDFD="$STLGAMES/desktopfiles"
STLAPPINFOIDDIR="$STLGAMES/appinfo"
STLGHEADD="$STLGAMES/header"
STLGSAD="$STLGAMES/standalone"
STLGICONS="$STLGAMES/icons"
STLGICO="$STLGICONS/ico"
STLGZIP="$STLGICONS/zip"
STLGPNG="$STLGICONS/png"
STLGSAPD="$STLGSAD/titles"
STLGSACD="$STLGSAD/compatdata"

#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 initAID {
	if [ -n "$STEAM_COMPAT_APP_ID" ]; then
		AID="$STEAM_COMPAT_APP_ID"
	fi

	if [ -z "$AID" ] || [ "$AID" -eq "0" ]; then
		# shellcheck disable=SC2154		# SteamAppId comes from Steam
		if [ -z "$SteamAppId" ]; then
			AID="$PLACEHOLDERAID"
		else
			if [ "$SteamAppId" -eq "0" ]; then
				AID="${STEAM_COMPAT_DATA_PATH##*/}"
			else
				AID="$SteamAppId"
			fi
		fi
	fi

	if [ -n "$STEAM_COMPAT_DATA_PATH" ]; then
		OSCDP="$STEAM_COMPAT_DATA_PATH"
	fi
}

function setSTLPath {
	STLPATH="$(tr ':' '\n' <<< "$PATH" | grep -v "$STERU" | tr '\n' ':')"
	PATH="$STLPATH"
}

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
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"
CODA="compatdata"
CTD="compatibilitytools.d"
USS="/usr/share/steam"
SYSSTEAMCOMPATOOLS="$USS/$CTD"
SLR="SteamLinuxRuntime"
STERU="steam-runtime"
DBW="dist/bin/wine"
FBW="files/bin/wine"
STLPROTDIR="$STLCFGDIR/proton"
STLPROTCOMPDATDIR="$STLPROTDIR/$CODA"
STLPROTSTUSDIR="$STLPROTDIR/$STUS"
STLEARLYPROTCONF="$STLPROTDIR/earlyproton.conf"
PROCU="proton/custom"
CTVDF="compatibilitytool.vdf"
SCV="sharedconfig.vdf"
SCVDF="shortcuts.vdf"
SRSCV="7/remote/$SCV"
LCV="localconfig.vdf"
LASTRUN="$LOGDIR/lastrun.txt"																# some variables from the last run which might be reused
SAIT="steam_appid.txt"
RS_D3D47_DEST="d3dcompiler_47.dll"
RS_DX_DEST="dxgi.dll"
RS_D9_DEST="d3d9.dll"
RSSU="ReShade_Setup"
RSINI="ReShade.ini"
RSPINI="ReShadePreset.ini"
IGCS="IGCSInjector"
UUU="UniversalUE4Unlocker"
SD3DVR="SuperDepth3D_VR+"
RSENABLED="ReShade-${PROGCMD}-enabled.txt"
RSDISABLED="ReShade-${PROGCMD}-disabled.txt"
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/Vortex"
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
			STPA="${HSR}/${2}"
			export "$1"="$STPA"
			writelog "INFO" "${FUNCNAME[0]} - Set '$1' to '$STPA'"
		elif [ -e "${HSS}/${2}" ]; then
			STPA="${HSS}/${2}"
			export "$1"="$STPA"
			writelog "INFO" "${FUNCNAME[0]} - Set '$1' to '$STPA'"
		else
			writelog "ERROR" "${FUNCNAME[0]} - '$2' not found for variable '$1' in '$HSR' or '$HSS'!" "E"
		fi	
	else
		writelog "SKIP" "${FUNCNAME[0]} - '$1' already defined as '${!1}'"
	fi
}

function setSteamPaths {
	setSteamPath "SROOT"
	setSteamPath "SUSDA" "userdata"
	setSteamPath "DEFSTEAMAPPS" "$SA"
	setSteamPath "DEFSTEAMAPPSCOMMON" "$SAC"
	setSteamPath "CFGVDF" "config/config.vdf"
	setSteamPath "LFVDF" "config/libraryfolders.vdf"

	if [ -z "$STEAM_COMPAT_CLIENT_INSTALL_PATH" ]; then
		export STEAM_COMPAT_CLIENT_INSTALL_PATH="$SROOT"
	fi

	mkdir -p "$SROOT/$CTD" 2>/dev/null
	setSteamPath "STEAMCOMPATOOLS" "$CTD"
	STEAMUSERID="$(find "$SUSDA" -maxdepth 1 -type d -name "[1-9]*")"
	SUIC="$STEAMUSERID/config"
	FLCV="$SUIC/$LCV"
	
	writelog "INFO" "${FUNCNAME[0]} - Found SteamUserId '$STEAMUSERID'"
}

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 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 getGamePic {
	if [ "$DLGAMEDATA" -eq 1 ]; then
		DLPIC="$1"
		if [ ! -f "$DLPIC" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Downloading picture for game '$(basename "${1//.jpg/}")'"
			"$WGET" -q "$2" -O "$DLPIC"
		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" | gawk -F '"name"' '{print $NF}')"
			GNRAW="$(gawk '{$1=$1};1' <<< "$GNRAW1")"
			writelog "INFO" "${FUNCNAME[0]} - Found Game Name '$GNRAW' in '$APPMA'"
		fi
	elif [ -f "$STLAPPINFOIDDIR/${1}.txt" ]; then
		GNRAW="$(grep "^name" -A1 -m1 "$STLAPPINFOIDDIR/${1}.txt" | tail -n1)"
		writelog "INFO" "${FUNCNAME[0]} - Found Game Name '$GNRAW' in '$STLAPPINFOIDDIR/${1}.txt'"
	else
		if [ "$DLGAMEDATA" -eq 1 ]; then
			APIURL="https://api.steampowered.com/ISteamApps/GetAppList/v2"
			APIDL="$STLDLDIR/SteamApps.json"
			MAXAGE=1440
			if [ ! -f "$APIDL" ] || test "$(find "$APIDL" -mmin +"$MAXAGE")"; then
				writelog "INFO" "${FUNCNAME[0]} - Downloading $APIDL"
				"$WGET" -q "$APIURL" -O "$APIDL"
			fi
		fi

		if [ -f "$APIDL" ]; then
			if  [ ! -x "$(command -v "$("$WHICH" "$JQ" 2>/dev/null)" 2>/dev/null)" ]; 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
		fi
	fi
	GAMENAME="${GNRAW//\"/}"
}

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

	if [ -f "$DESTDTF" ]; then
		writelog "SKIP" "${FUNCNAME[0]} - $DESTDTF already exists"
	else
		getGameName "$1"

		if [ -n "$GAMENAME" ] && [ "$GAMENAME" != "$NON" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Creating $DESTDTF" "E"

			{
				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 [ -z "$AID" ] || [ "$AID" == "$PLACEHOLDERAID" ]; then
		if [ "$1" -eq "$1" ] 2>/dev/null; then
			AID="$1"
		else
			AID="$(getIDFromTitle "$1")"
		fi
	fi

	WANTGPNG="$STLGPNG/${AID}.png"
	INTDTFILE="$STLIDFD/$AID.desktop"

	if [ -f "$INTDTFILE" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Already have an internal desktop file - skipping"
	else
		if [ -n "$AID" ] && [ ! -f "$WANTGPNG" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Don't have a desktop icon yet - trying to create it"
			getGameIcon
		fi

		# create desktop file internally for optionally using it on the desktop
		if [ -f "$WANTGPNG" ] && [ ! -f "$INTDTFILE" ]; then
			writeDesktopFile "$AID" "$INTDTFILE" "$WANTGPNG"
		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" "E"
			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" "E"
			cp "$INTDTFILE" "$HOME/.local/share/applications/" 2>/dev/null	
		fi	
	fi
}

function getRawAppIDInfo {
	AIVDF="$HSS/appcache/appinfo.vdf"
	AIIDRAW="$STLAPPINFOIDDIR/${1}.txt"

	if [ -s "$AIIDRAW" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Already have raw appinfo file for '$1' in '$AIIDRAW'"
	else
		if [ ! -s "$AIIDRAW" ]; then
			rm "$AIIDRAW" 2>/dev/null
		fi

		if [ -f "$AIVDF" ]; then
			SEARCHID="$1"
		#		echo "putt 2600"
			HXTST="$(printf '%x\n' "$SEARCHID" | fold -w2 | tail -n1)"
			if [ "${#HXTST}" -eq 1 ]; then
				SHEX1="$(printf '0%x\n' "$SEARCHID" | fold -w2 | tac)";
			else
				SHEX1="$(printf '%x\n' "$SEARCHID" | fold -w2 | tac)";
			fi

			unset SHEXOUT
			while read -r line; do
				SHEXOUT="$SHEXOUT\x${line}"
			done <<< "${SHEX1^^}"
#			echo "SHEXOUT $SHEXOUT"
			sed "s/\x61\x70\x70\x69\x64\x00${SHEXOUT}\x00\x00/APPID$1/g" "$AIVDF" | strings | sed -n "/APPID$1/,/^appid/p" > "$AIIDRAW"
		fi
	fi
}

function getIconData {
	getRawAppIDInfo "$2"
	AIIDRAW="$STLAPPINFOIDDIR/${2}.txt"
	if [ -f "$AIIDRAW" ]; then
		grep -A1 -m1 "^$1" "$AIIDRAW" | tail -n1
	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'" "E"
			IcotoPng
		else
			ICONAME="$(getIconData clienticon "$AID")"
			if [ -n "$ICONAME" ]; then
				ICOPATH="$ICODIR/${ICONAME}.ico"
				if [ -f "$ICOPATH" ]; then
					writelog "INFO" "${FUNCNAME[0]} - Found ico for '$AID' under '$ICOPATH'" "E"
					cp "$ICOPATH" "$WANTGICO"
					IcotoPng
				else
					writelog "SKIP" "${FUNCNAME[0]} - Absolute path for Steam ico '$ICONAME' not valid - skipping" "E"
				fi
			else
				writelog "SKIP" "${FUNCNAME[0]} - Could not find the icon name for '$AID' in appinfo - skipping" "E"
			fi
		fi		
	}
	
	function extractGZip {
		BIGGESTPNG="$("$UNZIP" -l "$WANTGZIP" | grep "\.png" | sort -n | tail -n1 | gawk -F ':[0-9][0-9]   ' '{print $NF}')" # weak gawk might break here(?)
		if [ -n "$BIGGESTPNG" ];then
			writelog "INFO" "${FUNCNAME[0]} - Extracting biggest png file '$BIGGESTPNG' in archive '$WANTGZIP' to '$WANTGPNG'" "E"
			writelog "INFO" "${FUNCNAME[0]} - $UNZIP -dqq ${WANTGPNG//.png} $WANTGZIP $BIGGESTPNG" "E"
			"$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" "E"
		fi
	}

	if [ -z "$AID" ]; then
		writelog "SKIP" "${FUNCNAME[0]} - Don't have a Steam gameid - skipping" "E"
	else
		WANTGPNG="$STLGPNG/${AID}.png"
		if [ -f "$WANTGPNG" ]; then
			writelog "Info" "${FUNCNAME[0]} - Already have game icon png '$WANTGPNG' - nothing to to" "E"
		else
			ICODIR="$HSS/steam/games"
			
			if [ ! -d "$ICODIR" ]; then
				writelog "SKIP" "${FUNCNAME[0]} - Steam ico directory not found - skipping" "E"
			else
				WANTGZIP="$STLGZIP/${AID}.zip"
				if [ -f "$WANTGZIP" ]; then
					writelog "INFO" "${FUNCNAME[0]} - Already have game icon zip '$WANTGZIP' - extracting" "E"
					extractGZip "$WANTGZIP" "$WANTGPNG"
				else
					writelog "INFO" "${FUNCNAME[0]} - Looking for icon hash in appinfo"
					
					LICONZIP="$(getIconData linuxclienticon "$AID")"
					if [ -n "$LICONZIP" ]; then
						LICONPATH="$ICODIR/${LICONZIP}.zip"
						if [ -f "$LICONPATH" ]; then
							writelog "INFO" "${FUNCNAME[0]} - Found icon zip for '$AID' under '$LICONPATH'" "E"
							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" "E"
							getIco
						fi
					else
						writelog "SKIP" "${FUNCNAME[0]} - Could not find the icon zip for '$AID' in appinfo - trying to find ico instead" "E"
						getIco
					fi
				fi
			fi
		fi
	fi
}

function getGameData {
	if  ! grep -q ",${1}," <<< "$NOGAMES" ; then
		getGamePic "$STLGHEADD/$1.jpg" "$STASSURL/$1/header.jpg"
		writeDesktopFile "$1" "$STLGDESKD/$1.desktop" "$STLGHEADD/$1.jpg"
	fi
}

function getParsableGameList {
	if [ -z "$SUSDA" ]; then
		setSteamPaths
	fi
	if [ -d "$SUSDA" ]; then
		STEAMUSERID="$(find "$SUSDA" -maxdepth 1 -type d -name "[1-9]*")"
		SC="$STEAMUSERID/$SRSCV"
		APPI="Apps"
		APPO="StartMenuShortcutCheck"
		LIST="$(gawk "/$APPI/,/$APPO/" "$SC" | grep -v "$APPI\|$APPO" | gawk '{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 {
	while read -r CATAID; do
		if [ -n "$CATAID" ]; then
			getGameData "$CATAID"
		fi
	done <  <(listInstalledGameIDs)
}

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

function getGrid {
	if checkSGDbApi; then

		URLSTR="$("$WGET" --header="Authorization: Bearer $SGDBAPIKEY" -q "${STEAMGRIDDBAPI}/${1}?styles=${SGDBSTYLES}&dimensions=${SGDBDIMS}&types=${SGDBTYPES}&nsfw=${SGDBNSFW}&humor=${SGDBHUMOR}" -O - | "$JQ" -r '.data' | "$JQ" '.[0].url')"

		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

			mkdir -p "$GRIDDLDIR" 2>/dev/null
	
			DLDST="$GRIDDLDIR/${1}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" "E"
					STARTDL=0
				elif [ "$SGDBHASFILE" == "backup" ]; then
					BACKDIR="${GRIDDLDIR}/backup"
					mkdir -p "$BACKDIR" 2>/dev/null
					writelog "INFO" "${FUNCNAME[0]} - Backup existing file into '$BACKDIR', because SGDBHASFILE is set to '$SGDBHASFILE'" "E"
					mv "$DLDST" "$BACKDIR"
				elif [ "$SGDBHASFILE" == "replace" ]; then
					writelog "INFO" "${FUNCNAME[0]} - Replacing existing file '$DLDST', because SGDBHASFILE is set to '$SGDBHASFILE'" "E"
					rm "$DLDST" 2>/dev/null
				fi
			fi
			
			if [ "$STARTDL" -eq 1 ]; then
				writelog "INFO" "${FUNCNAME[0]} - Downloading '$DLSRC' to '$DLDST'" "E"
				"$WGET" -q "$DLSRC" -O "$DLDST"
			fi
		else
			writelog "INFO" "${FUNCNAME[0]} - No grid found to download for '$1' - maybe loosen filters?" "E"
		fi
	fi
}

function getGridsForInstalledGames {
	if checkSGDbApi; then
		while read -r CATAID; do
			getGrid "$CATAID"
		done <  <(listInstalledGameIDs)
	fi
}

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

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\"" | gawk -F '{+' '{print $NF}' | sed 's/\"/'$'\\\n/g' | sort -u | grep -i "^[a-z]"
}

function createCategoryMenus {
	DFIDIR="$DFDIR/installed"
	mkdir -p "$DFIDIR" 2>/dev/null

	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"
			mkdir -p "$DFCDIR" 2>/dev/null
			while read -r CATGAME; do
				if [ -f "$STLGDESKD/$CATGAME.desktop" ]; then
					if [ ! -h "$DFCDIR/$CATGAME.desktop" ]; then
						ln -s "$STLGDESKD/$CATGAME.desktop" "$DFCDIR"
					fi

					if [ ! -h "$DFIDIR/$CATGAME.desktop" ]; then
						ln -s "$STLGDESKD/$CATGAME.desktop" "$DFIDIR"
					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
	}

	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
		while read -r BIF; do
			findAppMa "${BIF//\"/}/$SA"
		done <<< "$(grep "BaseInstallFolder\|\"path\"" "$CFGVDF" "$LFVDF" 2>/dev/null | gawk '{print $3}' | sort -u)"
	else
		writelog "SKIP" "${FUNCNAME[0]} - Neither file CFGVDF '$CFGVDF' nor file LFVDF '$LFVDF' found - this should not happen! - skipping"
	fi
}

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%/*}" 1
	mkProjDir "${TEMPLGUICFG%/*}" 1
	
	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 '$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" "E"
		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'" "E"
		if [ "$1" == "auto" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Found arument 'auto'. Automatically creating/downloading required data for all installed games found" "E"
			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'" "E"
			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 "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'" "E"
						DFCDIR="$DFDIR/last"
						mkdir -p "$DFCDIR" 2>/dev/null
						cp "$STLGDESKD/$AID.desktop" "$DFCDIR"
						GLgui "$1"
					else
						writelog "SKIP" "${FUNCNAME[0]} - '$1' selected, but file '$STLGDESKD/$AID.desktop' not found" "E"
					fi
				fi
			fi
		elif [ -d "$DFDIR/$1" ]; then
			GLgui "$1"
		else
			writelog "SKIP" "${FUNCNAME[0]} - Steam Category '$1' not found in '$DFDIR'" "E"
			writelog "SKIP" "${FUNCNAME[0]} - Only found '$(ls "$DFDIR")'" "E"
		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 still is 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"
	AIDREG="$GLOBALREGDIR/$AID.reg"
}

function setCompatDataTitle {
	if [ "$STORECOMPDATTITLE" -eq 1 ] && [ -n "$OSCDP" ]; then
		mkProjDir "$STLCOMPDAT" 1
		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 {

	if [ -n "$STEAM_COMPAT_DATA_PATH" ]; then
	# win game
		GPFX="$STEAM_COMPAT_DATA_PATH/pfx"														# currently used WINEPREFIX
		GP="$(printf "%s\n" "$@" | grep -v "proton\|$SLR" | grep -m1 "$SAC")"					# the absolute game path of the windows game exe
		GE="$(gawk -F '.exe' '{print $1}' <<< "${GP##*/}")"										# just the windows game exe name
		ISGAME=2																				# with STEAM_COMPAT_DATA_PATH being available it is a windows game
	else
	# linux game
		GPRAW="$(printf "%s\n" "$@" | grep -m1 "$SAC")"											# the absolute game path of the game exe
		if grep -q "/./" <<< "$GPRAW"; then
			GP="${GPRAW//\/.\//\/}"
		else
			GP="$GPRAW"
		fi
		
		GE="${GP##*/}"																			# the game executable
		ISGAME=3																				# no STEAM_COMPAT_DATA_PATH, so it is no windows game
	fi

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

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

	GFD="$(gawk -F 'common' '{print $1}' <<< "$EFD")common/$(gawk -F 'common' '{print $NF}' <<< "$EFD" | cut -d'/' -f2)" # f.e. used for vortex symlinks
	GN="$(grep -oE 'common/[^\/]+' <<< "$EFD" | gawk -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

	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

	# 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

	# 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 "${#ORGGCMD[@]}" ORGGCMD <<< "$ORGARG"
			fi
		done <<< "$(printf "%s\n" "${WIPCGCMD[@]}")"
	else
		while read -r ORGARG; do
			mapfile -t -O "${#ORGGCMD[@]}" ORGGCMD <<< "$ORGARG"
		done <<< "$(printf "%s\n" "${WIPCGCMD[@]}")"	
	fi

	if [ "${ORGGCMD[0]}" == "$WFEAR" ]; then
		# removing first ORGGCMD element as it is '$WFEAR'
		unset "ORGGCMD[0]"
	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)"

	if [ "$(getArch "$GP")" == "32" ] || [ "$(getArch "$GP")" == "64" ]; then
	# win game
		ISGAME=2
		GPFX="$STEAM_COMPAT_DATA_PATH/pfx"
	else
		ISGAME=3
	fi
	
	GE="$(gawk -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
			echo "${RSPF##*/}"
		done <<< "$(find "$STLLANGDIR" -name "*.txt")"

		while read -r RSPF; do
			basename "${RSPF//.txt/}"
		done <<< "$(find "$GLOBALSTLLANGDIR" -name "*.txt")"
	}
	LANGYADLIST="$(listLANG | sort -u | tr '\n' '!' | sed "s:^!::" | sed "s:!$::")"
}

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"
			source "$LANGFILENAME"
			STLLANG="$(cut -d '.' -f1 <<< "${LANGFILENAME##*/}")"
			LAFI="$STLLANGDIR/${STLLANG}.txt"
			if [ ! -f "$LAFI" ]; then
				mkProjDir "$STLLANGDIR" 1
				cp "$LANGFILENAME" "$LAFI"
			fi
		else
			LAFI="$STLLANGDIR/${LANGFILENAME}.txt"

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

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

function loadLanguage {
	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="$(gawk -F 'lang=' '{print $2}' <<< "$@" | cut -d ' ' -f1)"
		if [ -n "$ARGSLANG" ]; then
			STLLANG="$ARGSLANG"
		fi
	fi

	if [ -n "$STLLANG" ]; then 
		writelog "INFO" "${FUNCNAME[0]} - Now load the language file '$STLLANG'"
		loadLangFile "$STLLANG"
	fi
	
	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
}

function OVPROT {
	if [ "$HAVEINPROTON" -eq 1 ]; then
		writelog "INFO" "${FUNCNAME[0]} - proton override is disabled, because Steam Launch option was used"
		echo 0
	else
		writelog "INFO" "${FUNCNAME[0]} - No proton provided by steam command line, so an override is required"
		if [ -n "$OVERRIDEPROTON" ] && [ "$OVERRIDEPROTON" -eq 1 ]; then
			writelog "INFO" "${FUNCNAME[0]} - Proton override is already enabled anyway"
		else
			writelog "INFO" "${FUNCNAME[0]} - Force Enabling proton override"
			OVERRIDEPROTON=1
		fi

		if [ -n "$OVERRIDEPROTON" ] && [ "$OVERRIDEPROTON" -eq 1 ]; then
			writelog "INFO" "${FUNCNAME[0]} - proton override is enabled"
			echo 1
		else
			writelog "INFO" "${FUNCNAME[0]} - proton override is disabled"
			echo 0
		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
			PROTPATH="$1"
			CTVDF="$(dirname "$PROTPATH")/$CTVDF"
			PPV="$(dirname "$PROTPATH")/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="$(gawk '{print $2}' < "$PPV")"
			fi

			if [ -z "$PROTVOUT" ]; then
				# if no useful version was provided - hardcode it here:
				if grep -q "Proton 3.7" <<<"$PROTPATH"; 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//\"/}'"

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

function fillProtonCSV {
	if [ -n "$1" ]; then
		protonfileV="$1"
	else
		protonfileV="$(setProtonPathVersion "$PROTBIN")"
	fi
	if [ -n "$protonfileV" ]; then
		PCSV="\"${protonfileV//\"/}\";\"$PROTBIN\""
		writelog "INFO" "${FUNCNAME[0]} - Adding Proton '${PCSV//\"}'"
		mapfile -t -O "${#ProtonCSV[@]}" ProtonCSV <<< "$PCSV"
	fi
}

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

function delEmptyFile {
	if [ -f "$1" ]; then
		if [ "$(wc -l < "$1")" -eq 0 ]; then
			rm "$1" 2>/dev/null
		fi
	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
			if [ "$HAVEINPROTON" -eq 1 ]; then
				writelog "INFO" "${FUNCNAME[0]} - Skipping check for available Proton versions and directly using the proton version configured from inside Steam"
			else
				PROTONCSV="$STLSHM/ProtonCSV.txt"
				unset ProtonList
				delEmptyFile "$PROTONCSV"
				if [ ! -f "$PROTONCSV" ] || { [ -n "$1" ] &&  [ "$1" = "up" ]; } || [ "$1" == "F" ]; then
					writelog "INFO" "${FUNCNAME[0]} - Initially creating an array with available Proton versions"

					# 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 "$STEAMCOMPATOOLS" -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 "$SYSSTEAMCOMPATOOLS" -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 [ -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 "$DEFSTEAMAPPSCOMMON" -mindepth 1 -maxdepth 1 -type d -name "Proton*")"	
					else
						writelog "SKIP" "${FUNCNAME[0]} - Directory DEFSTEAMAPPSCOMMON '$DEFSTEAMAPPSCOMMON' not found - this should not happen! - skipping"
					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 | gawk '{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'"

						gawk -i inplace '!visited[$0]++' "$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"
				gawk -i inplace '!visited[$0]++' "$PROTONCSV"
			fi
		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 "$DL_D3D47_64" ]						; then	DL_D3D47_64="https://lutris.net/files/tools/dll/d3dcompiler_47.dll"; fi
		if [ -z "$DL_D3D47_32" ]						; then	DL_D3D47_32="$GHURL/frostworx/repo-assets/raw/master/misc/D3DCompiler_47.zip"; fi
		if [ -z "$RESHADEDLURL" ]						; then	RESHADEDLURL="https://reshade.me/downloads"; fi
		if [ -z "$VORTEXRELURL" ]						; then	VORTEXRELURL="$GHURL/Nexus-Mods/Vortex/releases"; fi
		if [ -z "$DXVKURL" ]							; then	DXVKURL="$GHURL/doitsujin/dxvk"; fi
		if [ -z "$XLIVEURL" ]							; then	XLIVEURL="$GHURL/ThirteenAG/Ultimate-ASI-Loader/releases/download/v4.52/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
	}

	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="$("$WHICH" geany 2>/dev/null)"; fi
		if [ -z "$MAXASK" ]								; then	MAXASK="3"; fi
		if [ -z "$BROWSER" ]							; then	BROWSER="$("$WHICH" firefox 2>/dev/null)"; fi
		if [ -z "$NOTY" ]								; then	NOTY="$("$WHICH" notify-send 2>/dev/null)"; fi
		if [ -z "$USENOTIFIER" ]						; then	USENOTIFIER="1"; fi
		if [ -z "$NETMON" ]								; then	NETMON="$("$WHICH" netstat 2>/dev/null)"; fi
		if [ -z "$NETOPTS" ]							; then	NETOPTS="-taucp -W"; fi
		if [ -z "$NETMONDIR" ]							; then	NETMONDIR="$LOGDIR"; fi
		if [ -z "$VRVIDEOPLAYER" ]						; then	VRVIDEOPLAYER="$("$WHICH" vr-video-player 2>/dev/null)"; fi
		if [ -z "$GAMCON" ]								; then	GAMCON="/usr/share/gameconqueror/GameConqueror.py"; fi
		if [ -z "$GLOBALREGDIR" ]						; then	GLOBALREGDIR="$SYSTEMSTLCFGDIR/regs"; 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 "$GLOBALRSPRESETDIR" ]					; then	GLOBALRSPRESETDIR="$SYSTEMSTLCFGDIR/$RSP"; 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="4.9.1"; fi
		if [ -z "$DOWNLOAD_RESHADE" ]					; then	DOWNLOAD_RESHADE="1"; fi
		if [ -z "$RESHADESRCDIR" ]						; then	RESHADESRCDIR="$STLDLDIR/reshade"; fi
		if [ -z "$RS_D3D47_64" ]						; then	RS_D3D47_64="d3dcompiler_47_64.dll"; fi
		if [ -z "$RS_D3D47_32" ]						; then	RS_D3D47_32="d3dcompiler_47_32.dll"; 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 "$WINEDLDIR" ]							; then	WINEDLDIR="$STLDLDIR/wine"; fi
		if [ -z "$WINEEXTDIR" ]							; then	WINEEXTDIR="$STLCFGDIR/wine"; fi
		if [ -z "$USEVORTEXPROTON" ]					; then	USEVORTEXPROTON="$NON"; fi
		if [ -z "$VORTEXCOMPDATA" ]						; then	VORTEXCOMPDATA="$STLVORTEXDIR/compatdata"; fi
		if [ -z "$VORTEXWINEDEBUG" ]					; then	VORTEXWINEDEBUG="-all"; fi
		if [ -z "$VORTEX_DXVK_LOG_LEVEL" ]				; then	VORTEX_DXVK_LOG_LEVEL="$NON"; fi
		if [ -z "$VORTEX_DXVK_LOG_PATH" ]				; then	VORTEX_DXVK_LOG_PATH="$NON"; fi
		if [ -z "$VORTEXDOWNLOADPATH" ]					; then	VORTEXDOWNLOADPATH="$STLVORTEXDIR/downloads"; fi
		if [ -z "$VORTEXINSTALL" ]						; then	VORTEXINSTALL="1"; 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 "$USEWGETGUI" ]							; then	USEWGETGUI="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="$("$WHICH" yad 2>/dev/null)"; fi
	}

	function setDefaultCfgValuesdefault_template {
		if [ -z "$USESLR" ]								; then	USESLR="1"; fi
		if [ -z "$USEREAP" ]							; then	USEREAP="1"; fi
		if [ -z "$USEPROTON" ]							; then	USEPROTON="$(getDefaultProton)"; fi
		if [ -z "$OVERRIDEPROTON" ]						; then	OVERRIDEPROTON="0"; fi
		if [ -z "$REDIRCOMPDATA" ]						; then	REDIRCOMPDATA="disabled"; fi
		if [ -z "$REDIRSTEAMUSER" ]						; then	REDIRSTEAMUSER="disabled"; fi
		if [ -z "$PROTONCHECK" ]						; then	PROTONCHECK="disabled"; fi
		if [ -z "$USECUSTOMCMD" ]						; then	USECUSTOMCMD="0"; fi
		if [ -z "$CUSTOMCMD" ]							; then	CUSTOMCMD="$("$WHICH" echo 2>/dev/null)"; 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 "$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="$("$WHICH" echo 2>/dev/null)"; fi
		if [ -z "$RUN_X64DBG" ]							; then	RUN_X64DBG="0";	fi
		if [ -z "$USEVORTEX" ]							; then	USEVORTEX="0"; fi
		if [ -z "$WAITVORTEX" ]							; then	WAITVORTEX="2"; 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="$("$WHICH" echo 2>/dev/null)"; fi
		if [ -z "$WINEDEFAULT" ]						; then	WINEDEFAULT="$("$WHICH" echo 2>/dev/null)"; fi
		if [ -z "$USEWICO" ]							; then	USEWICO="0"; fi
		if [ -z "$VIRTUALDESKTOP" ]						; then	VIRTUALDESKTOP="0"; 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 "$RESHADEPRESET" ]						; then	RESHADEPRESET="$NON"; fi
		if [ -z "$CHOOSESHADERS" ]						; then	CHOOSESHADERS="0"; fi
		if [ -z "$ALTEXEPATH" ]							; then	ALTEXEPATH="/tmp"; fi
		if [ -z "$ARCHALTEXE" ]							; then	ARCHALTEXE="$("$WHICH" echo 2>/dev/null)"; 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 "$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_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="$("$WHICH" echo 2>/dev/null)"; fi
		if [ -z "$USERSTOP" ]							; then	USERSTOP="$("$WHICH" echo 2>/dev/null)"; 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
	}
	
	"${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 "## 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 "## ReShade DL URL"
			echo "RESHADEDLURL=\"$RESHADEDLURL\""
			echo "## Vortex 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\""
			} >> "$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_WINEDLDIR"
			echo "WINEDLDIR=\"$WINEDLDIR\""
			echo "## $DESC_WINEEXTDIR"
			echo "WINEEXTDIR=\"$WINEEXTDIR\""			
			echo "## $DESC_AUTOPULLPROTON"
			echo "AUTOPULLPROTON=\"$AUTOPULLPROTON\""
			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_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_GLOBALREGDIR"
			echo "GLOBALREGDIR=\"$GLOBALREGDIR\""
			echo "## $DESC_GLOBALSBSTWEAKS"
			echo "GLOBALSBSTWEAKS=\"$GLOBALSBSTWEAKS\""
			echo "## $DESC_GLOBALTWEAKS"
			echo "GLOBALTWEAKS=\"$GLOBALTWEAKS\""
			echo "## $DESC_GLOBALCATEGORYDIR"
			echo "GLOBALCATEGORYDIR=\"$GLOBALCATEGORYDIR\""
			echo "## $DESC_GLOBALRSPRESETDIR"
			echo "GLOBALRSPRESETDIR=\"$GLOBALRSPRESETDIR\""
			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_RS_D3D47_64"
			echo "RS_D3D47_64=\"$RS_D3D47_64\""
			echo "## $DESC_RS_D3D47_32"
			echo "RS_D3D47_32=\"$RS_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_VORTEXWINEDEBUG"
			echo "VORTEXWINEDEBUG=\"$VORTEXWINEDEBUG\""
			echo "## $DESC_VORTEX_DXVK_LOG_LEVEL"
			echo "VORTEX_DXVK_LOG_LEVEL=\"$VORTEX_DXVK_LOG_LEVEL\""
			echo "## $DESC_VORTEX_DXVK_LOG_PATH"
			echo "VORTEX_DXVK_LOG_PATH=\"$VORTEX_DXVK_LOG_PATH\""
			echo "## $DESC_VORTEXDOWNLOADPATH"
			echo "VORTEXDOWNLOADPATH=\"$VORTEXDOWNLOADPATH\""
			echo "## $DESC_VORTEXINSTALL"
			echo "VORTEXINSTALL=\"$VORTEXINSTALL\""
			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_USEWGETGUI"
			echo "USEWGETGUI=\"$USEWGETGUI\""
			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\""
			} >> "$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_SLR"
			echo "USESLR=\"$USESLR\""
			echo "## $DESC_USEREAP"
			echo "USEREAP=\"$USEREAP\""
			echo "## $(strFix "$DESC_OVERRIDEPROTON" "$PROGCMD")"
			echo "OVERRIDEPROTON=\"$OVERRIDEPROTON\""
			echo "## $DESC_USEPROTON"
			echo "USEPROTON=\"$USEPROTON\""
			echo "## $DESC_REDIRCOMPDATA"
			echo "REDIRCOMPDATA=\"$REDIRCOMPDATA\""
			echo "## $DESC_REDIRSTEAMUSER"
			echo "REDIRSTEAMUSER=\"$REDIRSTEAMUSER\""
			echo "## $DESC_PROTONCHECK"
			echo "PROTONCHECK=\"$PROTONCHECK\""
			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_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_USEVORTEX"
			echo "USEVORTEX=\"$USEVORTEX\""
			echo "## $DESC_WAITVORTEX"
			echo "WAITVORTEX=\"$WAITVORTEX\""
			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_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_RESHADEPRESET"
			echo "RESHADEPRESET=\"$RESHADEPRESET\""
			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_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_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\""
			} >> "$1"
			#ENDsaveCfgdefault_template
		fi
	}

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

function notiShow { 
	if [ -n "$2" ]; then
		NOTY="$("$WHICH" notify-send 2>/dev/null)"
	fi
	
	if [ -n "$USENOTIFIER" ] && [ "$USENOTIFIER" -eq 1 ] || [ -n "$2" ]; then
		if  [ ! -x "$(command -v "$("$WHICH" "$NOTY" 2>/dev/null)" 2>/dev/null)" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Warning - '$NOTY' not found - disabling notifier"
			USENOTIFIER=0
		else
			"$NOTY" "$1"
		fi
	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 PROTPATH {
	if [ -z "${ProtonCSV[0]}" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Don't have the Array of available Proton versions yet - creating"
		getAvailableProtonVersions "up" X
	fi
	printProtonArr | grep "^$1" | sort -nr | head -n1 | cut -d ';' -f2
}

function setRunWineServer {
	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' to '$RUNWINE' 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' to '$RUNWINE' 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
}

function setNewProtVars {
	if [ "$ISGAME" -eq 2 ] && [ "$USEWINE" -eq 0 ]; then
		if [ "$HAVEINPROTON" -eq 1 ]; then
			if [ -z "$RUNWINESERVER" ]; then
				setRunWineServer
			fi
		else
			# arg1 is absolute proton path
			if [ "$(OVPROT)" -eq 1 ]; 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"
					mkdir "$(dirname "$RUNPROTON")/dist"
					"$TAR" xf "$(dirname "$RUNPROTON")/$PDTGZ" -C "$(dirname "$RUNPROTON")/dist"
				fi

				setRunWineServer
				
				PROTONVERSION="$(setProtonPathVersion "$RUNPROTON")"
				USEPROTON="$PROTONVERSION"
			else
				writelog "SKIP" "${FUNCNAME[0]} - Using Steam Proton '$FIRSTUSEPROTON' instead of $PROGCMD Proton '$USEPROTON' because OVERRIDEPROTON is disabled"
				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 [ "$(OVPROT)" -eq 1 ] || [ -n "$1" ]; 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 "$1"
		
		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 "${USEPROTON/#-/ -}!$PROTYADLIST" \
		--title="$TITLE" "$GEOM")"



		if [ -n "$PICKPROTON" ]; then
			if [ -n "$1" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Only returning '$PICKPROTON'"
				echo "${PICKPROTON//\'}"
			else
				writelog "INFO" "${FUNCNAME[0]} - Selected Proton Version $PICKPROTON"
				setNewProtVars "$(PROTPATH "$PICKPROTON")"
			fi
		else
			writelog "INFO" "${FUNCNAME[0]} - No Proton Version was selected - try again"
			"${FUNCNAME[0]}"
		fi
	fi
}

function wgetGui {
	SRCURL="$1"
	DESTDIR="$2"
	
	if [ "$USEWGETGUI" -eq 1 ]; then
		writelog "INFO" "${FUNCNAME[0]} - Downloading '$SRCURL' via Gui, as 'USEWGETGUI' is enabled"
		export CURWIKI="$PPW/Downloads"
		TITLE="Download"
		pollWinRes "$TITLE"

		DLFILE="${1##*/}"
		DLTEXT="$(strFix "$GUI_DLTO" "$DLFILE" "${DESTDIR//$DLFILE}")"
		
		writelog "INFO" "${FUNCNAME[0]} - $DLTEXT"

		"$WGET" -q --show-progress "$SRCURL" -O "$DESTDIR" 2>&1 | sed -u -e "s:\.::g;s:%.*$::g;s:.*K::g;s:^[[:space:]]*::g" | \
		"$YAD" --f1-action="$F1ACTION" --window-icon="$STLICON" --center --on-top "$WINDECO" --title="$TITLE" --progress --auto-close --text="$(spanFont "$DLTEXT" "H")" "$GEOM"
		case $? in
			0)  {
					writelog "INFO" "${FUNCNAME[0]} - Clicked Close or Download failed - deleting the unfinished download"
					rm "${DESTDIR//$DLFILE}/$DLFILE" 2>/dev/null
				}
			;;
		esac
	else
		writelog "INFO" "${FUNCNAME[0]} - Downloading '$SRCURL' via command line, as 'USEWGETGUI' is disabled"
		writelog "INFO" "${FUNCNAME[0]} - Download Command is '$WGET -q $SRCURL -O $DESTDIR'"
		"$WGET" -q "$SRCURL" -O "$DESTDIR"
	fi
}

function dlCustomProton {
	CPURL="${1//\"/}"
	PROTV="${2//\"/}"
	CPURLFILE="${CPURL##*/}"
	DSTDL="$CUSTPROTDLDIR/$CPURLFILE"
	if [ ! -f "$DSTDL" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Downloading '$CPURL' to '$CUSTPROTDLDIR'"
		notiShow "$(strFix "$NOTY_DLCUSTOMPROTON" "$CPURL")"
		# "$WGET" "$CPURL" -O "$DSTDL"
		wgetGui "$CPURL" "$DSTDL"
		notiShow "$(strFix "$NOTY_DLCUSTOMPROTON2" "$CPURL")"
	else
		writelog "INFO" "${FUNCNAME[0]} - File '$DSTDL' already exists - nothing to download"
		notiShow "$(strFix "$NOTY_DLCUSTOMPROTON4" "$CPURLFILE")"
	fi
	
	PROTNAMERAW="${CPURLFILE%%.tar*}"
	PROTNAME="${PROTNAMERAW//.zip/}"

	if [ -d "$CUSTPROTEXTDIR/$PROTNAME" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Directory '$CUSTPROTEXTDIR/$PROTNAME' already exists - nothing to extract"
	else
		if grep -q "\.tar\." <<< "$DSTDL"; then
			notiShow "$(strFix "$NOTY_DLCUSTOMPROTON5" "$CPURLFILE")"

			PROTRELPATH="$("$TAR" -tf "$DSTDL" | grep "proton$" 2>/dev/null )"
			if [ -n "$PROTRELPATH" ]; then
				if grep -q "^proton$" <<< "$PROTRELPATH"; then
					EXTDEST="$CUSTPROTEXTDIR/$PROTNAME"
					PROTFULLPATH="$EXTDEST/$PROTRELPATH"
					writelog "INFO" "${FUNCNAME[0]} - Archive is a tarbomb - creating parent directory '$EXTDEST' as extract dest dir"
					mkProjDir "$EXTDEST" 1
				else
					writelog "INFO" "${FUNCNAME[0]} - Archive contains proton in subdirectory '$PROTRELPATH'"
					PROTFULLPATH="$CUSTPROTEXTDIR/$PROTRELPATH"
					EXTDEST="$CUSTPROTEXTDIR"
				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")"
					"$TAR" xf "$DSTDL" -C "$EXTDEST" 2>/dev/null
					getAvailableProtonVersions "up"
				fi
			else
				notiShow "$(strFix "$NOTY_DLCUSTOMPROTON6" "$CPURL")"
				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="$CUSTPROTEXTDIR/$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")"
					"$UNZIP" "$DSTDL" -d "$CUSTPROTEXTDIR/$SUBDIR" 2>/dev/null
					getAvailableProtonVersions "up"
				fi
			else
				notiShow "$(strFix "$NOTY_DLCUSTOMPROTON6" "$CPURL")"
				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
	
	if [ -f "$PROTFULLPATH" ]; then
		if [ -n "$PROTV" ]; then
			addCustomProtonToList "$PROTFULLPATH" "$PROTV"
		else
			addCustomProtonToList "$PROTFULLPATH"
		fi
	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 -  | 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 "${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"
			dlCustomProton "${DLDISPCUSTPROT}"
		else
			DLURL="$(printf "%s\n" "${ProtonDLList[@]}" | grep -m1 "${DLDISPCUSTPROT}")"
			writelog "INFO" "${FUNCNAME[0]} - '${DLDISPCUSTPROT}' was selected - downloading '$DLURL'"
			dlCustomProton "${DLURL}"
		fi

		createProtonList
	fi
}

function dlNewCustomProt {
	NEWESTPROT="$1"
	DLURL="$(grep "$NEWESTPROT" <<< "$(printf "%s\n" "${ProtonDLList[@]}")")"
	dlCustomProton "$DLURL"
}

function dlUpCustomProton {
	NEWESTPROT="$1"
	dlNewCustomProt "$NEWESTPROT"
	NEWMINORPROT="$(printProtonArr | grep "^${NEWESTPROT%-*}" | cut -d ';' -f1 | sort -nr | head -n1)"
	NEWMINORRUN="$(PROTPATH "${NEWMINORPROT//\"/}")"
	if [ -f "$NEWMINORRUN" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Enabling proton override"
		OVERRIDEPROTON=1
		switchProton "$NEWMINORPROT"
		writelog "INFO" "${FUNCNAME[0]} - $(strFix "$NOTY_NEWPROTON2" "$CURPROTON" "$NEWMINORPROT")"
		notiShow "$(strFix "$NOTY_NEWPROTON2" "$CURPROTON" "$NEWMINORPROT")"
		updateConfigEntry "USEPROTON" "$NEWMINORPROT" "$STLGAMECFG"
		loadCfg "$STLGAMECFG"
	else
		writelog "SKIP" "${FUNCNAME[0]} - File '$NEWMINORRUN' couldn't be found - skipping version change"
	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
				writelog "INFO" "${FUNCNAME[0]} - Downloading github avatar for user '$GITHUBUSER' to use as custom fallback picture"
				"$WGET" -q "$GHURL/${GITHUBUSER}.png" -O "$CUSTOMFALLBACKPIC"
			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 [ "$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" ]; then
					setSteamPaths
				fi
				STEAMUSERID="$(find "$SUSDA" -maxdepth 1 -type d -name "[1-9]*")"
				CUSTPIC="$STEAMUSERID/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 dlCustomProtonAsk {
	NEWESTPROT="$1"

	writelog "INFO" "${FUNCNAME[0]} - Asking if proton version '$NEWESTPROT' should be updated"

	setShowPic
	export CURWIKI="$PPW/Download-Custom-Proton"
	TITLE="${PROGNAME}-NewProtonAvailable"
	pollWinRes "$TITLE"
	
	"$YAD" --f1-action="$F1ACTION" --image "$SHOWPIC" --image-on-top --window-icon="$STLICON" --form --scroll --center "$WINDECO" \
    --title="$TITLE" \
	--text="$(spanFont "$(strFix "$NOTY_NEWPROTON" "$NEWESTPROT" "$CURPROTON")\n$(strFix "$GUI_DLCUSTPROTASK" "$NEWESTPROT")" "H")" \
	"$GEOM" \
	--button="$ASKPROTBUTC":0 \
	--button="$ASKPROTBUTD":1 \
	--button="$ASKPROTBUTU":2
	case $? in
		0)  {
				writelog "INFO" "${FUNCNAME[0]} - Selected cancel - doing dothing"
			}
		;;
		1) 	{
				writelog "INFO" "${FUNCNAME[0]} - Selected to only download '$NEWESTPROT'"
				dlNewCustomProt "$NEWESTPROT"
			}
		;;
		2) 	{
				writelog "INFO" "${FUNCNAME[0]} - Selected to download and use '$NEWESTPROT'"
				dlUpCustomProton "$NEWESTPROT"
			}
		;;
	esac
}

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")"
				dlCustomProton "$CPURL"
			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")"
				CPV="$(cut -d ';' -f1 <<< "$CPURLWIP")"
				dlCustomProton "$CPURL" "$CPV"
			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 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"
			dlCustomProton "$@"
		else
			if [ "$1" == "latest" ] || [ "$1" == "l" ]; then
				createDLProtList
				writelog "INFO" "${FUNCNAME[0]} - Downloading latest custom Proton ${ProtonDLDispList[0]//\"/}" E
				dlCustomProton "${ProtonDLList[0]//\"/}"
			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!" "E"
				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'" "E"
			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]} - $PROGCMD 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 | gawk '$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 "$("$WHICH" geany 2>/dev/null)" 2>/dev/null)" ]; then
			FOUNDEDITOR="$("$WHICH" geany 2>/dev/null)"
		elif  [ -x "$(command -v "$("$WHICH" gedit 2>/dev/null)" 2>/dev/null)" ]; then
			FOUNDEDITOR="$("$WHICH" gedit 2>/dev/null)"
		elif  [ -x "$(command -v "$("$WHICH" leafpad 2>/dev/null)" 2>/dev/null)" ]; then
			FOUNDEDITOR="$("$WHICH" leafpad 2>/dev/null)"
		elif  [ -x "$(command -v "$("$WHICH" kwrite 2>/dev/null)" 2>/dev/null)" ]; then
			FOUNDEDITOR="$("$WHICH" kwrite 2>/dev/null)"
		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 [ -z "$GPFX" ]; then
		APPMA="$(listAppManifests | grep "${1}.acf")"
		if [ -n "$APPMA" ]; then
			AMF="${APPMA##*/}"
			GPFX="$(dirname "$APPMA")/$CODA/$1/pfx"
			writelog "INFO" "${FUNCNAME[0]} - Found WINEPREFIX '$GPFX' in '$AMF'"
		fi
	fi
	
	if [ -z "$GPFX" ] && [ -n "$AMF" ]; 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
	
	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 "$GAMEDIR" -name "$UUUPATCH")"
		if	[ -f "$UUUPATCHFILE" ]; then
			CfgFiles+=("$UUUPATCHFILE")
		fi
	fi
	
	if [ "$USEOPENVRFSR" -eq 1 ]; then
		OVRFP="$EFD/${OVFS}-${PROGCMD}-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" "E"
	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
		TSHADDESTDIR="$(GETALTEXEPATH)"
	else
		TSHADDESTDIR="$EFD"
	fi

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

	if [ ! -f "$RUNWINE" ]; then
		setRunWineServer
	fi

	export RUNWINESERVER="${RUNWINE}server"

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

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

function openTrayIcon {
	# loading gameconfig here, as some vars might have to be exported
	writelog "INFO" "${FUNCNAME[0]} - LoadCfg: $STLGAMECFG"
	loadCfg "$STLGAMECFG"

	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
		}

		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"
		}
		
		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" \
		--text="$TRAY_TOOLTIP" >/dev/null 2>/dev/null &
		YADTRAYPID="$!"
	fi
}

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

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

function createDropdownLists {
	createProtonList
	createWineList
	createLanguageList
	createReShadePresetList
}

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 "${STLLANG/#-/ -}!$LANGYADLIST" `#CAT_Gui` `#MENU_GLOBAL` \
--field="     $GUI_STARTMENU!$DESC_STARTMENU ('STARTMENU')":CB "${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 "${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 "${SGDBHASFILE/#-/ -}!skip!backup!replace" `#CAT_SteamGridDB` `#MENU_GLOBAL` \
--field="     $GUI_SGDBAUTODL!$DESC_SGDBAUTODL ('SGDBAUTODL')":CB "${SGDBAUTODL/#-/ -}!$NON!after_game!before_game!no_meta" `#CAT_SteamGridDB` `#MENU_GLOBAL` \
--field="     $GUI_SGDBSTYLES!$DESC_SGDBSTYLES ('SGDBSTYLES')":CBE "${SGDBSTYLES/#-/ -}!${SGDBSTYOPTS//,/\!}" `#CAT_SteamGridDB` `#MENU_GLOBAL` \
--field="     $GUI_SGDBDIMS!$DESC_SGDBDIMS ('SGDBDIMS')":CBE "${SGDBDIMS/#-/ -}!${SGDBDIMOPTS//,/\!}" `#CAT_SteamGridDB` `#MENU_GLOBAL` \
--field="     $GUI_SGDBTYPES!$DESC_SGDBTYPES ('SGDBTYPES')":CBE "${SGDBTYPES/#-/ -}!animated!static!animated,static!static,animated" `#CAT_SteamGridDB` `#MENU_GLOBAL` \
--field="     $GUI_SGDBNSFW!$DESC_SGDBNSFW ('SGDBNSFW')":CBE "${SGDBNSFW/#-/ -}!any!false!true" `#CAT_SteamGridDB` `#MENU_GLOBAL` \
--field="     $GUI_SGDBHUMOR!$DESC_SGDBHUMOR ('SGDBHUMOR')":CBE "${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_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 "${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_USEWGETGUI!$DESC_USEWGETGUI ('USEWGETGUI')":CHK "${USEWGETGUI/#-/ -}" `#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 "${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 "${GAMESCREENRES/#-/ -}!$(printf "%s\n" "$("$XRANDR" --current | grep "[0-9]x" | gawk '{print $1}' | grep "^[0-9]" | 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 "${STL_PV_SHELL/#-/ -}!none!after!fail!instead" `#CAT_Misc` `#MENU_GAME` \
--field="     $GUI_STL_PV_TERMINAL!$DESC_STL_PV_TERMINAL ('STL_PV_TERMINAL')":CB "${STL_PV_TERMINAL/#-/ -}!none!auto!tty!xterm" `#CAT_Misc` `#MENU_GAME` \
--field="$(spanFont "$GUI_OPTSPROTON" "H")":LBL "SKIP" `#CAT_Proton` `#HEAD_Proton` `#MENU_GAME` `#MENU_GLOBAL` \
--field="     $GUI_OVERRIDEPROTON!$(strFix "$DESC_OVERRIDEPROTON" "$PROGCMD") ('OVERRIDEPROTON')":CHK "${OVERRIDEPROTON/#-/ -}" `#CAT_Proton` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_USEPROTON!$DESC_USEPROTON ('USEPROTON')":CB "${USEPROTON/#-/ -}!$PROTYADLIST" `#CAT_Proton` `#MENU_GAME` \
--field="     $GUI_USESLR!$DESC_USESLR ('USESLR')":CHK "${USESLR/#-/ -}" `#CAT_Proton` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_USEREAP!$DESC_USEREAP ('USEREAP')":CHK "${USEREAP/#-/ -}" `#CAT_Proton` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_AUTOLASTPROTON!$DESC_AUTOLASTPROTON ('AUTOLASTPROTON')":CHK "${AUTOLASTPROTON/#-/ -}" `#CAT_Proton` `#SUB_Checkbox` `#MENU_GLOBAL` \
--field="     $GUI_AUTOPULLPROTON!$DESC_AUTOPULLPROTON ('AUTOPULLPROTON')":CHK "${AUTOPULLPROTON/#-/ -}" `#CAT_Proton` `#SUB_Checkbox` `#MENU_GLOBAL` \
--field="     $GUI_REDIRCOMPDATA!$DESC_REDIRCOMPDATA ('REDIRCOMPDATA')":CB "${REDIRCOMPDATA/#-/ -}!disabled!single-proton!global-proton" `#CAT_Proton` `#MENU_GAME` \
--field="     $GUI_REDIRSTEAMUSER!$DESC_REDIRSTEAMUSER ('REDIRSTEAMUSER')":CB "${REDIRSTEAMUSER/#-/ -}!disabled!symlink!restore-backup" `#CAT_Proton` `#MENU_GAME` \
--field="     $GUI_PROTONCHECK!$DESC_PROTONCHECK ('PROTONCHECK')":CB "${PROTONCHECK/#-/ -}!disabled!ask_before_menu!ask_before_game!auto_download!auto_download_and_use!only_notify" `#CAT_Proton` `#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_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 "${DXVK_HUD/#-/ -}!0!1" `#CAT_Proton` `#SUB_Dxvk` `#MENU_GAME` \
--field="     $GUI_DXVK_LOG_LEVEL!$DESC_DXVK_LOG_LEVEL ('DXVK_LOG_LEVEL')":CB "${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_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_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_BACKUPSTEAMUSER!$DESC_BACKUPSTEAMUSER ('BACKUPSTEAMUSER')":CHK "${BACKUPSTEAMUSER/#-/ -}" `#CAT_Proton` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_RESTORESTEAMUSER!$DESC_RESTORESTEAMUSER ('RESTORESTEAMUSER')":CB "${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_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_RS_D3D47_32!$DESC_RS_D3D47_32 ('RS_D3D47_32')" "${RS_D3D47_32/#-/ -}" `#CAT_Shader` `#SUB_ReShade` `#MENU_GLOBAL` \
--field="     $GUI_RS_D3D47_64!$DESC_RS_D3D47_64 ('RS_D3D47_64')" "${RS_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_RESHADEPRESET!$DESC_RESHADEPRESET ('RESHADEPRESET')":CB "${RESHADEPRESET/#-/ -}!$RSPRESETLIST" `#CAT_Shader` `#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_GLOBALREGDIR!$DESC_GLOBALREGDIR ('GLOBALREGDIR')":DIR "${GLOBALREGDIR/#-/ -}" `#CAT_Paths` `#SUB_Directories` `#MENU_GLOBAL` \
--field="     $GUI_GLOBALRSPRESETDIR!$DESC_GLOBALRSPRESETDIR ('GLOBALRSPRESETDIR')":DIR "${GLOBALRSPRESETDIR/#-/ -}" `#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_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_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="$(spanFont "$GUI_OPTSURLS" "H")":LBL "SKIP" `#CAT_Urls` `#HEAD_Urls` `#MENU_URL` \
--field="     $GUI_PROJECTPAGE!$(strFix "$DESC_PROJECTPAGE") ('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_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="$(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_VORTEXINSTALL!$DESC_VORTEXINSTALL ('VORTEXINSTALL')":CHK "${VORTEXINSTALL/#-/ -}" `#CAT_Vortex` `#SUB_Checkbox` `#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_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 "${USEVORTEXPROTON/#-/ -}!$PROTYADLIST" `#CAT_Vortex` `#MENU_GLOBAL` \
--field="     $GUI_VORTEXWINEDEBUG!$DESC_VORTEXWINEDEBUG ('VORTEXWINEDEBUG')":CBE "${VORTEXWINEDEBUG/#-/ -}!$SOMEWINEDEBUGOPTIONS" `#CAT_Vortex` `#MENU_GLOBAL` \
--field="     $GUI_VORTEX_DXVK_LOG_LEVEL!$DESC_VORTEX_DXVK_LOG_LEVEL ('VORTEX_DXVK_LOG_LEVEL')":CB "${VORTEX_DXVK_LOG_LEVEL/#-/ -}!none!error!warn!info!debug" `#CAT_Vortex` `#MENU_GLOBAL`  \
--field="     $GUI_VORTEX_DXVK_LOG_PATH!$DESC_VORTEX_DXVK_LOG_PATH ('VORTEX_DXVK_LOG_PATH')" "${VORTEX_DXVK_LOG_PATH/#-/ -}" `#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 "${WINEVERSION/#-/ -}!$WINEYADLIST" `#CAT_Wine` `#MENU_GAME` \
--field="     $GUI_WINEDEFAULT!$DESC_WINEDEFAULT ('WINEDEFAULT')":CBE "${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 "${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_USEWICO!$DESC_USEWICO ('USEWICO')":CHK "${USEWICO/#-/ -}" `#CAT_Wine` `#SUB_Checkbox` `#MENU_GAME` \
--field="     $GUI_STLWINEDEBUG!$DESC_STLWINEDEBUG ('STLWINEDEBUG')":CBE "${STLWINEDEBUG/#-/ -}!$SOMEWINEDEBUGOPTIONS" `#CAT_Wine` `#MENU_GAME` \
--field="     $GUI_STLWINEDLLOVERRIDES!$DESC_STLWINEDLLOVERRIDES ('STLWINEDLLOVERRIDES')":CBE "${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` \

#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"

	if [ -z "$2" ]; then
		if [ "$PROTONCHECK" == "disabled" ] || [ "$PROTONCHECK" == "ask_before_menu" ] || [ "$PROTONCHECK" == "only_notify" ]; then
			if [ "$ISGAME" -eq 2 ] && [ "$USEWINE" -eq 0 ]; then
				writelog "INFO" "${FUNCNAME[0]} - Entering checkProtonBump"
				checkProtonBump "$USEPROTON"
			fi
		fi
	fi

	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 "$@"

	if [ -z "$2" ]; then
		if [ "$PROTONCHECK" == "disabled" ] || [ "$PROTONCHECK" == "ask_before_menu" ] || [ "$PROTONCHECK" == "only_notify" ]; then
			if [ "$ISGAME" -eq 2 ] && [ "$USEWINE" -eq 0 ]; then
				writelog "INFO" "${FUNCNAME[0]} - Entering checkProtonBump"
				checkProtonBump "$USEPROTON" 
			fi
		fi
	fi

	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"
}

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

	setShowPic
	
	CATDD="${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 {
	SGNAID="$GN ($AID)"
	SGNAID="${SGNAID//&/+}"
}

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

function MainMenu {
	prepareMenu "$@"

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

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

	TT_OPENURL="Help Url Gui"
	prepareProtonDBRating
	if [ -f "$PDBRAINFO" ];then
		SETHEAD="$SETHEAD \n $(cat "$PDBRASINF")"
		TT_OPENURL="$(cat "$PDBRAINFO")"
	fi

	loadCfg "$CUMETA/$AID.conf" X
	loadCfg "$GEMETA/$AID.conf" X

	if [ -L "${GPFX%/*}" ]; then
		SETHEAD="$SETHEAD \n ${GUI_SCD}: '${GPFX%/*}' (symlink)"
	else
		SETHEAD="$SETHEAD \n ${GUI_SCD}: '${GPFX%/*}'"
	fi

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

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

	if [ -n "$GAMEDIR" ]; then
		SETHEAD="$SETHEAD \n ${GUI_SGD}: '$(fixShow "$GAMEDIR")'"
	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
	
	# filter html incompatible chars here
	#SETHEAD="${SETHEAD//&/+}"
	
	createProtonList X
	WANTPROTON="$("$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_OTP":CB "${USEPROTON/#-/ -}!$PROTYADLIST" \
	--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 \"$EFD\"" \
	--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\"" \
	--field="$FBUT_GUISET_GASCO":FBTN "$PROGCMD gs \"$AID\"" \
	--field="$FBUT_GUISET_VORTEX":FBTN "$PROGCMD vortex gui" \
	--field="$FBUT_GUISET_WIKI":FBTN "$PROGCMD wiki" \
	--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"
			setGuiCategoryMenuSel "$AID" "${FUNCNAME[0]}"
		}
	;;
	6) 	{
			clickInfo "${FUNCNAME[0]}" "$?" "$BUT_GM" "$SETMENU" "$GAMMENU"
			openGameMenu "$AID" "${FUNCNAME[0]}"
		}
	;;
	8) 	{
			clickInfo "${FUNCNAME[0]}" "$?" "$BUT_DGM" "$SETMENU" "Game Default Menu"
			openGameDefaultMenu "$AID" "${FUNCNAME[0]}"
		}
	;;
	10) 	{
			clickInfo "${FUNCNAME[0]}" "$?" "$BUT_GLM" "$SETMENU" "Global Menu"
			openGlobalMenu "$AID" "${FUNCNAME[0]}" "1"
		}
	;;
	12) 	{
			clickInfo "${FUNCNAME[0]}" "$?" "$BUT_FAV" "$SETMENU" "Favorites"
			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
		writelog "INFO" "${FUNCNAME[0]} - Found active '$STLMENUSORTCFG' - autoupdating missing Categories"
		while read -r catent; do
			if ! grep -q "^$catent" "$STLMENUSORTCFG"; then
				writelog "INFO" "${FUNCNAME[0]} - Adding missing Category '$catent'"
				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]} - '$*'" "E"
	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"
		gawk -i inplace '!visited[$0]++' "$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}"
	 
	if [ "$ARGPCMD" == "$NON" ]; then
		if [ "$PROTONCHECK" == "disabled" ] || [ "$PROTONCHECK" == "ask_before_menu" ] || [ "$PROTONCHECK" == "only_notify" ]; then
			if [ "$ISGAME" -eq 2 ] && [ "$USEWINE" -eq 0 ]; then
				writelog "INFO" "${FUNCNAME[0]} - Entering checkProtonBump"
				checkProtonBump "$USEPROTON" 
			fi
		fi
	fi

	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 {
	if [ -n "$3" ] && grep -q ".log" <<< "$3"; then
		WRITELOG="$3"
	elif [ "$AID" == "$PLACEHOLDERAID" ] || [ -z "$AID" ]; then
		WRITELOG="$TEMPLOG"
	else
		WRITELOG="$LOGFILE"
	fi

#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 [ -z "$LOGLEVEL" ]; then
		LOGLEVEL=2
	fi
	
	if [ "$LOGLEVEL" -eq 1 ]; then
		if grep -q "$1" <<< "$LOGONE"; then
			echo "$(date) $1 - $2" >> "$WRITELOG"
		fi
	fi

	if [ "$LOGLEVEL" -eq 2 ]; then
		echo "$(date) $1 - $2" >> "$WRITELOG"
	fi

	if [ -n "$3" ]; then
		if [ "$3" == "E" ]; then
			echo "$(date) $1 - $2"
		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
		mkdir "$GITDIR" >/dev/null 2>/dev/null
		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

		while read -r line; do
			if [ -n "$line" ]; then
				export "${line//\"/}"
			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" != "$("$WHICH" echo 2>/dev/null)" ] && [ "$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"
	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 | gawk '$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"
					checkDepth3DUse
				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]} - $PROGCMD 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"
					checkDepth3DUse
				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]} - $PROGCMD 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]} - $PROGCMD 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"
						checkDepth3DUse
						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"
				checkDepth3DUse
			fi
		fi
	fi
}

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

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

	if [ ! -f "$DLDST/$OVRFSRZIP" ]; then
		notiShow "$(strFix "$NOTY_DLCUSTOMPROTON" "$OVRFSRZIP")"
		wgetGui "${OVRFSRURL}/download/$FSRV/$OVRFSRZIP" "$DLDST/$OVRFSRZIP"
		notiShow "$(strFix "$NOTY_DLCUSTOMPROTON2" "$OVRFSRZIP")"
	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")"
		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}-${PROGCMD}-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"
				dlOvrFSR
			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:" | gawk -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:" | gawk -F 'Process id: ' '{print $2}' | cut -d ' ' -f1)"
				writelog "INFO" "${FUNCNAME[0]} - Found gamewindow '$GAMEWINDOW' PID $GAMPI"
			else
				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 [ -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]} - $PROGCMD is just closing - leaving loop"
				WASCLOSED=1
				break
			fi
			TESTPID="$("$XDO" getactivewindow getwindowpid)"
			SYMCWD="$(readlink "/proc/$TESTPID/cwd")"
			SYMEXE="$(readlink "/proc/$TESTPID/exe")"
			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

			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
}

function storeGameWindowNameMeta {
	GAMEWINDOW="$1"
	if [ -n "$GAMEWINDOW" ] && [ "$GAMEWINDOW" != "$NON" ]; 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
	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
			grep "^GAMENAME" "$GEMETA/${1}.conf" | cut -d '=' -f2
		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 compatdata dir found for '$1'"
			fi
		else
			echo "No compatdata 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/}");$GAMEDIR"
					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/}");$GAMEDIR"
					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]} - $PROGCMD 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
					checkDepth3DUse
					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
						checkDepth3DUse
						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" | gawk -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
				checkDepth3DUse
			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]} - $PROGCMD 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]} - $PROGCMD 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" | gawk -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]} - $PROGCMD 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" | gawk -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"
				checkDepth3DUse
			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
				checkDepth3DUse
			fi
		fi
	fi
}

function RSiniToGameDir {
	DESTINIABS="$1"
	DESTINI="${1##*/}"
	GSRSINI="$GLOBALRSPRESETDIR/$RESHADEPRESET/$DESTINI"
	USRSINI="$STLRSPRESETDIR/$RESHADEPRESET/$DESTINI"

	if [ ! -f "$DESTINIABS" ]; then
		if [ -f "$GSRSINI" ] && [ -f "$USRSINI" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Both global and user '$DESTINI' exist for '$RESHADEPRESET'- copying user file into gamedir"
			cp "$USRSINI" "$DESTINIABS"
		elif [ ! -f "$GSRSINI" ] && [ -f "$USRSINI" ]; then
			writelog "INFO" "${FUNCNAME[0]} - User '$DESTINI' exist for '$RESHADEPRESET'- copying into gamedir"
			cp "$USRSINI" "$DESTINIABS"
		elif [ -f "$GSRSINI" ] && [ ! -f "$USRSINI" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Global '$DESTINI' exist for '$RESHADEPRESET'- copying into gamedir"
			cp "$GSRSINI" "$DESTINIABS"
		elif [ ! -f "$GSRSINI" ] && [ ! -f "$USRSINI" ]; then
			writelog "SKIP" "${FUNCNAME[0]} - Neither global nor user '$DESTINI' exist - nothing to copy - skipping"
		fi	
	else
		writelog "SKIP" "${FUNCNAME[0]} - '$DESTINIABS' already exists - nothing to do - skipping"
	fi

}

function presetReShade {

	if [ -n "$RESHADEPRESET" ] && [ "$RESHADEPRESET" != "$NON" ]; then
		writelog "INFO" "${FUNCNAME[0]} - RESHADEPRESET is set to '$RESHADEPRESET'"
		DRSINI="$1/$RSINI"
		DRSPINI="$1/$RSPINI"

		RSiniToGameDir "$DRSINI"
		RSiniToGameDir "$DRSPINI"
	else
		writelog "SKIP" "${FUNCNAME[0]} - No specific ReShade Preset $RESHADEPRESET configured - skipping"
	fi
}

function createReShadePresetList {

	function listRSP {
		while read -r RSPF; do
			echo "${RSPF##*/}"
		done <<< "$(find "$GLOBALRSPRESETDIR" -mindepth 1 -maxdepth 1 -type d)"

		while read -r RSPF; do
			echo "${RSPF##*/}"
		done <<< "$(find "$STLRSPRESETDIR" -mindepth 1 -maxdepth 1 -type d)"
	}
	RSPRESETLIST="$(listRSP | sort -u | tr '\n' '!' | sed "s:^!::" | sed "s:!$::")"
}


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"

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

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

	if [ ! -s "$DLDST" ]; then
		writelog "SKIP" "${FUNCNAME[0]} - Downloaded file '$DLDST' is empty - removing" "E"
		rm "$DLDST" 2>/dev/null
	else
		"$UNZIP" -q "$DLDST" -d "$RESHADESRCDIR" 2>/dev/null
		writelog "INFO" "${FUNCNAME[0]} - Downloaded and extracted ReShade-v${DLVERS} file '$DLDST'" "E"
	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/$RS_D3D47_32" ]; then
				writelog "404" "${FUNCNAME[0]} - '$RESHADESRCDIR/$RS_D3D47_32' missing - downloading"

				if [ ! -d "$RESHADESRCDIR" ]; then
					writelog "404" "${FUNCNAME[0]} - '$RESHADESRCDIR' does not exist - trying to create it" 
					mkdir -p "$RESHADESRCDIR" >/dev/null 2>/dev/null
				fi

				if [ -d "$RESHADESRCDIR" ]; then
					writelog "INFO" "${FUNCNAME[0]} - '$RESHADESRCDIR' exist - installing ReShade in here" 
					DLDST="$RESHADESRCDIR/d3dcompiler_47.zip"
					"$WGET" "$DL_D3D47_32" -O "$DLDST"
					"$UNZIP" "$DLDST" -d "$RESHADESRCDIR"
					mv "$RESHADESRCDIR/d3dcompiler_47.dll" "$RESHADESRCDIR/$RS_D3D47_32"
				fi
			fi

			if [ ! -f "$RESHADESRCDIR/$RS_D3D47_64" ]; then
				writelog "404" "${FUNCNAME[0]} - '$RESHADESRCDIR/$RS_D3D47_64' missing - downloading" 
				"$WGET" "$DL_D3D47_64" -O "$RESHADESRCDIR/$RS_D3D47_64"
			fi

			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 ReShade download log '${RESHADESRCDIR}/${RSSU}.log'"
					if [ "$RSVERS" != "$(cat "${RESHADESRCDIR}/${RSSU}.log")" ]; then
						writelog "INFO" "${FUNCNAME[0]} - Last downloaded is ReShade Version '$(cat "${RESHADESRCDIR}/${RSSU}.log")' is not equal to the latest available ReShade 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"
		dlShaders "depth3d"
	fi	
}

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

function createShaderRepoList {
	SHADREPOURL="https://www.pcgamingwiki.com/wiki/ReShade"
	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 - | sed -n '/Repository</,/table>/p' | grep "^<td>" | gawk '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

	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"  "E"
					notiShow "$(strFix "$NOTY_DLSHADERS" "$SHADNAM")"
					gitUpdate "$(SHADSRC "$SHADNAM")" "${SHADURL//\"/}"
				else
					writelog "SKIP" "${FUNCNAME[0]} - Skipping $SHADNAM" "E"
				fi
			done < "$SHADREPOLIST"
		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" "E"
			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 getAvailableShaders {
	unset ShaderFiles
	while read -r shadfx; do
		ShaderFiles+=("${shadfx//$STLSHADDIR\//}")
	done <<< "$(find "$STLSHADDIR" -name "*.fx" | grep -vFf "$SHADERREPOBLOCKLIST")"

	unset BlockedShaderFiles
	while read -r shadfx; do
		BlockedShaderFiles+=("${shadfx//$STLSHADDIR\//}")
	done <<< "$(find "$STLSHADDIR" -name "*.fx" -o -name "*.png" -o -name "*.fxh" -o -name "*.cfg" | grep -Ff "$SHADERREPOBLOCKLIST")"
}

function GameShaderDialog {
	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
			SHADDESTDIR="$EFD"
			if [ -n "$EFD" ] && [ -d "$EFD" ]; then
				SHADDESTDIR="$EFD"
			else
				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
	fi

	if [ "$SHADDESTDIR" != "$NON" ] && [ ! -d "$SHADDESTDIR" ]; then
		mkdir -p "$SHADDESTDIR" 2>/dev/null
	fi

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

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

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

		getAvailableShaders
		writelog "INFO" "${FUNCNAME[0]} - Found ${#ShaderFiles[@]} available Shader Files from the enabled Shader Repos - opening Selection"
		export CURWIKI="$PPW/Shader-Management"
		TITLE="${PROGNAME}-Shader"
		pollWinRes "$TITLE"

		setShowPic

		SHADFILES="$(while read -r f; do if [ ! -f "$SHADDESTDIR/${f##*/}" ]; then 	echo FALSE ; echo "$f"; else echo TRUE ; echo "$f" ;fi ; done <<< "$(printf "%s\n" "${ShaderFiles[@]}")" | \
		"$YAD" --f1-action="$F1ACTION" --image "$SHOWPIC" --image-on-top --window-icon="$STLICON" --center "$WINDECO" --list --checklist --column="$GUI_ADD" --column=Shader --separator=" " --print-column="2" \
		--text="$(spanFont "$(strFix "$GUI_SHADERDIALOG" "${SHADDESTDIR##*/}")" "H")" --title="$TITLE" "$GEOM")"
		case $? in
			0)  {
					writelog "INFO" "${FUNCNAME[0]} - Updating selected shaders"
	
					while read -r upshad; do
						if [ -f "$SHADDESTDIR/${upshad##*/}" ]; then
							if ! grep -q "$upshad" <<< "$SHADFILES"; then
								writelog "INFO" "${FUNCNAME[0]} - File '$SHADDESTDIR/${upshad##*/}' exists, but is unchecked - removing"
								rm "$SHADDESTDIR/${upshad##*/}"
							fi
						else
							if grep -q "$upshad" <<< "$SHADFILES"; then
								writelog "INFO" "${FUNCNAME[0]} - File '$SHADDESTDIR/${upshad##*/}' does not exist, but is checked - installing"
								cp "$STLSHADDIR/$upshad" "$SHADDESTDIR"

								if grep -q "\.jpg\|\.png" "$STLSHADDIR/$upshad"; then
									while read -r texture; do
										TNAM="${texture##*/}"
										if grep -q "$TNAM" "$STLSHADDIR/$upshad"; then
											writelog "INFO" "${FUNCNAME[0]} - Shader '${upshad##*/}' uses texture '$TNAM'"
											if [ ! -f "$SHADDESTDIR/$TNAM" ]; then
												writelog "INFO" "${FUNCNAME[0]} - Copying texture '$TNAM' into the gamedir"
												cp "$texture" "$SHADDESTDIR"
											else
												writelog "SKIP" "${FUNCNAME[0]} - Texture '$TNAM' already exists in the gamedir"
											fi
										fi
									done <<< "$(while read -r tdir; do find "$tdir" -type f ; done <<< "$(find "$STLSHADDIR" -type d -name "*Textures*")")"	
								fi

								while read -r shadadd; do
									if [ ! -f "$SHADDESTDIR/${shadadd##*/}" ]; then
										SUBDIRPATH="${shadadd//$(dirname "$STLSHADDIR/$upshad")/}"
										writelog "INFO" "${FUNCNAME[0]} - Installing shader helper file '$SUBDIRPATH' into '$SHADDESTDIR'"
										mkdir -p "$SHADDESTDIR/$(dirname "$SUBDIRPATH")" 2>/dev/null
										cp "$shadadd" "$SHADDESTDIR/$(dirname "$SUBDIRPATH")"
									fi
								done <  <(find "$(dirname "$STLSHADDIR/$upshad")" -name "*.fxh" -o -name "*.txt")
							fi
						fi
					
					done <<< "$(printf "%s\n" "${ShaderFiles[@]//\"/}")"

					writelog "INFO" "${FUNCNAME[0]} - Removing shaders from blocked repos if found in '$SHADDESTDIR'"
					
					while read -r blockshad; do
						if [ -f "$SHADDESTDIR/${blockshad##*/}" ]; then
							# chance to have a false positive here is very low, removing anyway only if found one matching file in the repos:
							if [ "$(find "$STLSHADDIR" -name "*.fx" -o -name "*.png" -o -name "*.fxh" -o -name "*.cfg" | grep -c "${blockshad##*/}")" -eq 1 ]; then
								writelog "INFO" "${FUNCNAME[0]} - Shader '$SHADDESTDIR/${blockshad##*/}' from blocked repo found - removing" "E"
								rm "$SHADDESTDIR/${blockshad##*/}"
							fi
						fi
					done <<< "$(printf "%s\n" "${BlockedShaderFiles[@]//\"/}")"
					
					if grep -qi "include*.*Reshade" "${SHADDESTDIR}"/*.fx ; then
						writelog "INFO" "${FUNCNAME[0]} - Installing Reshade helper files"
						RESHASHA="reshade-shaders/Shaders"

						RFXHF="ReShade.fxh"
						if [ ! -f "$SHADDESTDIR/$RFXHF" ]; then
							cp "$STLSHADDIR/$RESHASHA/$RFXHF" "$SHADDESTDIR" 2>/dev/null
						fi
						
						RUFXHF="ReShadeUI.fxh"
						if [ ! -f "$SHADDESTDIR/$RUFXHF" ]; then
							cp "$STLSHADDIR/$RESHASHA/$RUFXHF" "$SHADDESTDIR" 2>/dev/null
						fi
					fi
				}
			;;
			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
		writelog "INFO" "${FUNCNAME[0]} - Opening Shader Menu"
		GameShaderDialog "$EFD"
	fi
}

function installRSdll {
	if [ ! -f "$INSTDESTDIR/$1" ] || [ "$1" == "F" ]; then
		if [ "$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/$RSENABLED"
				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
}

function installRSd3d47dll {
	if [ ! -f "$INSTDESTDIR/$RS_D3D47_DEST" ]; then
		if [ ! -f "$RESHADESRCDIR/$1" ]; then
			writelog "SKIP" "${FUNCNAME[0]} - Sourcefile '$RESHADESRCDIR/$1' missing - skipping this file" 
		else
			cp "$RESHADESRCDIR/$1" "$INSTDESTDIR/$RS_D3D47_DEST" >/dev/null 2>/dev/null
			writelog "INFO" "${FUNCNAME[0]} - Copied '$RESHADESRCDIR/$1' to '$INSTDESTDIR/$RS_D3D47_DEST'" 
		fi
	else
		writelog "SKIP" "${FUNCNAME[0]} - Destfile '$INSTDESTDIR/$RS_D3D47_DEST' already exists - skipping this file" 
	fi
}

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

			prepareReshadeFiles

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

			presetReShade "$INSTDESTDIR"

			# checking for previous dll conficts between $RS_D3D47_DEST and $RS_D9_DEST
			if [ -f "$INSTDESTDIR/${RS_DX_DEST//.dll/.log}" ]; then
				if grep -q "Another ReShade 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" != "$("$WHICH" echo 2>/dev/null)" ]; then
				CHARCH="$ARCHALTEXE"
			else
				CHARCH="$GP"
			fi

			#32bit:
			if [ "$(getArch "$CHARCH")" == "32" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Installing 32bit Reshade as '$CHARCH' is 32bit" 
				#d3d47
				installRSd3d47dll "$RS_D3D47_32"
				#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 Reshade as '$CHARCH' is 64bit" 
				#d3d47
				installRSd3d47dll "$RS_D3D47_64"
				#dxgi:
				installRSdll "$RS_DX_DEST" "0" "$RS_64"
				#d3d9:
				installRSdll "$RS_D9_DEST" "$NOD3D9" "$RS_64"
			else
				writelog "SKIP" "${FUNCNAME[0]} - ERROR in ReShade installation - no file information detected for '$CHARCH' or any 'neighbor file' - setting USERESHADE=0 for this session"
				export USERESHADE=0
			fi
		fi
	fi
}

function installReshadeDepth3D {
	SHADERPOOL="depth3d"
	
	if [ -n "$RESHADE_DEPTH3D" ]; then
		if [ "$RESHADE_DEPTH3D" -eq 1 ]; then
			dlShaders "$SHADERPOOL"

			if [ -n "$(GETALTEXEPATH)" ]; then
				INSTDESTDIR="$(GETALTEXEPATH)"
			else
				INSTDESTDIR="$EFD"
			fi
	
			RESHADEPRESET="$SD3DVR"
			OLDSD3DVR="${SD3DVR//+/}.fx"
			if [ -f "$INSTDESTDIR"/"$OLDSD3DVR" ]; then
				writelog "INFO" "${FUNCNAME[0]} - '$OLDSD3DVR' was renamed to '$SD3DVR' upstream - removing the old file"
				rm "$INSTDESTDIR"/"$OLDSD3DVR" 2>/dev/null
			fi

			presetReShade "$INSTDESTDIR"

			writelog "INFO" "${FUNCNAME[0]} - Copying shaders into gamedir"
			while read -r file; do
				writelog "INFO" "${FUNCNAME[0]} - CHECKING '$INSTDESTDIR/${file##*/}'"

				if [ -f "$INSTDESTDIR"/"${file##*/}" ]; then
					writelog "INFO" "${FUNCNAME[0]} - '$INSTDESTDIR/${file##*/}' already exists - updating"
					cp "$file" "$INSTDESTDIR"
				else
					writelog "INFO" "${FUNCNAME[0]} - Copying new file '$file' to '$EFD'"
					cp "$file" "$INSTDESTDIR"
				fi
			done <<< "$(find "$(SHADSRC "$SHADERPOOL")/Shaders/" -maxdepth 1 -name "*.fx*")"
		fi
	fi
}

function useReshade {
	if [ -n "$USERESHADE" ]; then
		if [ "$USERESHADE" -eq 1 ]; then
			if [ -f "$EFD/$RSDISABLED" ]; then
				writelog "INFO" "${FUNCNAME[0]} - ReShade has been disabled previously using '$PROGCMD' - enabling it now"
				RSDLL="$(cat "$EFD/$RSDISABLED")" 
				mv "$EFD/$RSDLL" "$EFD/${RSDLL//_disabled/}"
				rm "$EFD/$RSDISABLED" 2>/dev/null
				echo "${RSDLL//_disabled/}" > "$EFD/$RSENABLED"
			fi

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

			if [ -f "$EFD/$RSINI" ] && [ ! -f "$EFD/$RSENABLED" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Looks like Reshade was installed previously using '$PROGCMD' without creating '$RSENABLED' - recreating it now"
				INSTALL_RESHADE=1 installReshade F
			fi

			writelog "INFO" "${FUNCNAME[0]} - Setting WINEDLLOVERRIDES for ReShade: dxgi=n,b;d3d9=n,b;d3dcompiler_47=n,b"
			export WINEDLLOVERRIDES="$WINEDLLOVERRIDES;dxgi=n,b;d3d9=n,b;d3dcompiler_47=n,b"
		else
			if [ -f "$EFD/$RSINI" ] && [ ! -f "$EFD/$RSENABLED" ] && [ ! -f "$EFD/$RSDISABLED" ] ; then
				writelog "INFO" "${FUNCNAME[0]} - USERESHADE is '$USERESHADE' - looks like Reshade was installed previously using '$PROGCMD' without creating '$RSENABLED' - recreating it now"
				INSTALL_RESHADE=1 installReshade F
			fi

			if [ -f "$EFD/$RSENABLED" ]; then
				writelog "INFO" "${FUNCNAME[0]} - ReShade has been installed previously with '$PROGCMD' - disabling it now"
				RSDLL="$(cat "$EFD/$RSENABLED")" 
				mv "$EFD/$RSDLL" "$EFD/${RSDLL}_disabled"
				rm "$EFD/$RSENABLED" 2>/dev/null
				echo "${RSDLL}_disabled" > "$EFD/$RSDISABLED"
			fi
		fi
	fi	
}

function checkDepth3DUse {
	SPIDIS="$EFD/${RSPINI}_disabled"
	if [ "$RUNSBSVR" -eq 0 ] && [ -f "$EFD/$RSPINI" ]; then
		if grep -q "Techniques=${SD3DVR//+/}" "$EFD/$RSPINI"; then
			writelog "INFO" "${FUNCNAME[0]} - Deactivating '$SD3DVR' because VR is disabled"
			mv "$EFD/$RSPINI" "$SPIDIS"
		fi
	fi
	if [ "$RUNSBSVR" -eq 1 ] && [ ! -f "$EFD/$RSPINI" ] && [ -f "$SPIDIS" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Reactivating '$SD3DVR' because VR is enabled"
		mv "$SPIDIS" "$EFD/$RSPINI"
	fi
}

function getUsedVars {
	while read -r line; do 
		if  grep -q -v "^#" <<< "$line"; then
			gawk -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 setInitWinXY {

	SCRW="$(getScreenRes w)"
	SCRH="$(getScreenRes h)"
	
	WINX=$(( SCRW * 3 / 4))
	WINY=$(( SCRH * 3 / 4))
	writelog "INFO" "${FUNCNAME[0]} - Using '${WINX}x${WINY}' as default resolution for all windows without a configured resolution"
}

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" != "$("$WHICH" echo 2>/dev/null)" ]; 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" != "$("$WHICH" echo 2>/dev/null)" ]; 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

		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 if $2 is 1 or empty
function mkProjDir {
	if [ -n "$2" ]; then
		if [ "$2" -eq 1 ]; then
			if [ ! -d "$1" ]; then
				mkdir -p "$1" 2>/dev/null >/dev/null
			fi
		fi
	fi
}

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

# 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 -q "config Version: $PROGVERS" "$1"; then
			writelog "SKIP" "${FUNCNAME[0]} - Config file '$CFGFILE' already at version '$PROGVERS'"
		else
			OLDVERS="$(grep "config Version" "$CFGFILE" | gawk -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

			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 grep -q "\\$" <<< "$LVAL"; then

						if grep -q "WINX$\|WINY\|POSX\|POSY$" <<< "$LVAL"; then
							VARNAM=${LVAL//\$/DEF}
						else
							VARNAM=${LVAL//\$/}
						fi
						OUTVAL=${!VARNAM}
					else
						OUTVAL="$LVAL"
					fi

					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" | gawk -F 'echo ' '{print $2}' | grep -v "\"##" | 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
		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?" "E"
		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" | gawk -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 {
	stlicon64="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="

	if [ ! -f "$STLICON" ]; then
		base64 -d <<< "$stlicon64" > "$STLICON"
	fi

	onepix64="R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw=="

	if [ ! -f "$NOICON" ]; then
		base64 -d <<< "$onepix64" > "$NOICON"
	fi
}

function createDefaultCfgs {
	writelog "INFO" "${FUNCNAME[0]} - Preparing some default configs"

	createProjectDirs

	rm "$TEMPLOG" "$WINRESLOG" 2>/dev/null

	loadLanguage "$@"
	setSteamPaths

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

	saveCfg "$STLURLCFG" X
	loadCfg "$STLURLCFG" X

	prepareGUI
	genDefIcon
	createProjectDirs
	getAvailableProtonVersions "up"

	checkStartMode
	saveCfg "$STLDEFGAMECFG" X
	createProjectDirs
	setGlobalAIDCfgs
	listAllSettingsEntries
	checkEntryBlocklist
	updateMenuSortFile
}

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

	CFGCAT="$1"
	CFGVALUE="$2"
	CFGFILE="$3"

	if [ -z "$3" ]; then
		writelog "SKIP" "${FUNCNAME[0]} - Expected 3 arguments - only got $*"
	else
		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" ] || [ -f "$FUPDATE" ]; then
					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"
						if [ "$CFGCAT" == "USEPROTON" ]; then
							writelog "INFO" "${FUNCNAME[0]} - Updating One Time Proton for this launch to the updated USEPROTON value '$CFGVALUE'"
							WANTPROTON="$CFGVALUE"
						fi
					fi
					rm "$FUPDATE" 2>/dev/null
				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 ]; then
		if [ -z "$SUSDA" ]; then
			setSteamPaths
		fi
		if [ -d "$SUSDA" ]; then
			STEAMUSERID="$(find "$SUSDA" -maxdepth 1 -type d -name "[1-9]*")"
			SC="$STEAMUSERID/$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 '$AID'"

				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 '{\|}' | gawk '{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"
#	IFS=" " read -r -a RUNSTRACEOPTS <<< "$STRACEOPTS"
	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"
			mkdir "$NETMONDIR" 2>/dev/null
		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
			#IFS=" " read -r -a RUNNETOPTS <<< "$NETOPTS"
			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/Program Files (x86)/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/"
			mkdir -p "$XLDL" 2>/dev/null

			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 "$XLDL/$XLIVEDLL" ]; then
					writelog "INFO" "${FUNCNAME[0]} - '$XLDL/$XLIVEDLL' not found - downloading automatically from '$XLIVEURL'"
					"$WGET" "$XLIVEURL" -P "$XLDL"
					"$UNZIP" "$XLDL/${DLURL##*/}" -d "$XLDL"
					if [ -f "$XLDL/dinput8.dll" ]; then
						mv "$XLDL/dinput8.dll" "$XLDL/$XLIVEDLL"
					fi
				fi
				if [ -f "$XLDL/$XLIVEDLL" ]; then
					writelog "INFO" "${FUNCNAME[0]} - Found '$XLIVEDLL' in '$XLDL' - copying into gamedir '$EFD'"
					cp "$XLDL/$XLIVEDLL" "$EFD"
				fi
			fi
		fi
	fi
}

function GameScopeGui {
	if [ -n "$1" ]; then
		AID="$1"
		setAIDCfgs
	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 "${GSINTRES//\"}!$(printf "%s\n" "$("$XRANDR" --current | grep "[0-9]x" | gawk '{print $1}' | grep "^[0-9]" | tr '\n' '!')")" \
			--field="$GUI_GSSHWRES!$DESC_GSSHWRES ('GSSHWRES')":CBE "${GSSHWRES//\"}!$(printf "%s\n" "$("$XRANDR" --current | grep "[0-9]x" | gawk '{print $1}' | grep "^[0-9]" | tr '\n' '!')")" \
			--field="$GUI_GSFLR!$DESC_GSFLR ('GSFLR')":CBE "${GSFLR//\"}!30!60!90!120!$UL" \
			--field="$GUI_GSFLU!$DESC_GSFLU ('GSFLU')":CBE "${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="$(PROTPATH "$SAPPROTON")"
			if [ ! -f "$RUNSAPPROTON" ]; then
				RUNSAPPROTON="$(fixProtonVersionMismatch "$SAPPROTON" X)"
			fi

			if [ ! -f "$RUNSAPPROTON" ]; then
				writelog "SKIP" "${FUNCNAME[0]} - No executable for selected Proton '$SAPPROTON' found" E
			elif [ ! -f "$SAPEXE" ]; then
				writelog "SKIP" "${FUNCNAME[0]} - No executable found" E
			elif [ ! -d "$SAP_COMPAT_DATA_PATH" ]; then
				writelog "SKIP" "${FUNCNAME[0]} - No compatdata dir found" E
			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'" E
				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/${PROGCMD}-$((10000 + RANDOM % 10000))"
			mkProjDir "$SAP_COMPAT_DATA_PATH" 1
			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 "${SAPGAME}!$SAPGAMELIST" \
		--field="$GUI_SAPPROTON!$DESC_SAPPROTON":CB "${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]}" "E"
					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'" E
							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'" E
							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" 1
	SAPGUI=1
	SAPRUN="TRUE"

	if [ -n "$1" ] && [ -z "$2" ] && [ -f "${STLGSAPD}/${1}.conf" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Loading '${STLGSAPD}/${1}.conf' silently" "E"
		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" "E"
			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" "E"
		loadCfg "${STLGSAPD}/${1}.conf"
		SAPGUI=1
	elif [ -z "$1" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Only starting plain gui" "E"
	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'"
			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" "E"
	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 "${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="$(PROTPATH "$OTPROTON")"
						if [ ! -f "$RUNOTPROTON" ]; then
							RUNOTPROTON="$(fixProtonVersionMismatch "$OTPROTON" 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" == "$("$WHICH" echo 2>/dev/null)" ]; 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" == "$("$WHICH" echo 2>/dev/null)" ]; 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" 2>/dev/null)" ]; then
		writelog "INFO" "${FUNCNAME[0]} - '$CUSTOMCMD' found"
		LACO="$CUSTOMCMD"
		CUSTCOM="$("$WHICH" "$CUSTOMCMD" 2>/dev/null)"
		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" || 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 - || return
		fi

	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" "E"
	else
		DXVKHUDLIST="0,1,devinfo,fps,frametimes,submissions,drawcalls,pipelines,memory,gpuload,version,api,compiler,samplers,full"

		unset CURDXH

		if [ "$DXVK_HUD" -eq "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"

			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" 1

		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" "E"
		
		if [ ! -d "$SUSYD" ]; then
			writelog "INFO" "${FUNCNAME[0]} - '$SUSYD' does not yet exists" "E"
			if [ -d "$SteamUserDir" ]; then
				mv "$SteamUserDir" "$SUSYD"
			else
				mkProjDir "$SUSYD" 1
			fi
		else
			writelog "INFO" "${FUNCNAME[0]} - '$SUSYD' does already exists" "E"
		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" "E"
			else
				writelog "INFO" "${FUNCNAME[0]} - '$SteamUserDir' is already a symlink pointing to the unexpected directory '$(readlink "$SteamUserDir")' instead of '$SUSYD' - nothing to do" "E"
			fi
		else
			if [ -d "$SteamUserDir" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Syncing files from '$SteamUserDir' to '$SUSYD'" "E"
				"$RSYNC" -amu "$SteamUserDir" "$SUSYD"
				BACKSUD="${SteamUserDir}_${PROGCMD}_$((900 + RANDOM % 100))"
				mv "$SteamUserDir" "$BACKSUD"
				writelog "INFO" "${FUNCNAME[0]} - Backing up '$SteamUserDir' to '$BACKSUD'" "E"
			fi

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

				ln -s "$SUSYD" "$SteamUserDir"
			else
				writelog "SKIP" "${FUNCNAME[0]} - '$SteamUserDir' still exists - can't create a symlink pointing to '$SUSYD'" "E"
			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'" "E"
			restoreSteamUser "restore-if-dst-is-empty"
		fi
	else
		writelog "SKIP" "${FUNCNAME[0]} - Symlinking $STUS is disabled - Checking if a symlink needs to be reverted" "E"
		
		if [ -L "$SteamUserDir" ]; then
			SUSYD="$(readlink "$SteamUserDir")"
			writelog "INFO" "${FUNCNAME[0]} - '$SteamUserDir' points to '$SUSYD'"
			if [ -d "$SUSYD" ]; then
				rm "$SteamUserDir"
				mkProjDir "$SteamUserDir" 1
				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" "E"
					"$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 - " "E"
					writelog "INFO" "${FUNCNAME[0]} - Pulling files from backup if existing instead" "E"
					restoreSteamUser "restore-if-dst-is-empty"	
				fi
			fi
		else
			writelog "SKIP" "${FUNCNAME[0]} - '$SteamUserDir' is no symlink - nothing to do" "E"
		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 compatdata dir and '$SYM' as symlink pointing to it"

		if [ ! -f "${DIR}/version" ]; then
			writelog "INFO" "${FUNCNAME[0]} - New compatdata '$DIR' does not exist yet"
			if [ -d "${STEAM_COMPAT_DATA_PATH}_SAC" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Moving found backed autocloud compatdata '${STEAM_COMPAT_DATA_PATH}_SAC' to '$DIR'"
				mkProjDir "${DIR%/*}" 1
				mv "${STEAM_COMPAT_DATA_PATH}_SAC" "$DIR"
			else
				writelog "INFO" "${FUNCNAME[0]} - Creating new compatdata dir '$DIR'"
				mkProjDir "$DIR" 1	
			fi
		else
			writelog "INFO" "${FUNCNAME[0]} - Using existing compatdata '$DIR'"
			if [ -d "${STEAM_COMPAT_DATA_PATH}_SAC" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Found backed autocloud compatdata '${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/${PROGCMD}-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 compatdata '$REDIRCOMPDATA' mode"

			PVF="$STEAM_COMPAT_DATA_PATH/version"
			SCDPPV="$(cat "$PVF")"
			
			SPVF="$STEAM_COMPAT_DATA_PATH/${PROGCMD}-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 compatdata by creating the steam_autocloud.vdf"
					writelog "INFO" "${FUNCNAME[0]} - Moving the compatdata 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 compatdata '$STEAM_COMPAT_DATA_PATH' matches the expected version '$DESTPROT' (allowing minor version mismatch)"
					CDPVOK=1
				else
					writelog "INFO" "${FUNCNAME[0]} - Proton in compatdata '$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 compatdata 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]} - Compatdata 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]} - Compatdata 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]} - Compatdata 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 compatdata 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		
	}

	if [ -n "$STEAM_COMPAT_DATA_PATH" ]; then # should be enough
		if [ -n "$WANTPROTON" ] && [ "$WANTPROTON" != "$USEPROTON" ]; then
			DESTPROT1="${WANTPROTON//proton-}"
		else
			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
		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##*/}/${PROGCMD}\/${STEAM_COMPAT_DATA_PATH##*/}-proton-${DESTPROT}}"
			checkCompatdataSymlink
		elif [ "$REDIRCOMPDATA" == "global-proton" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Using global 'STEAM_COMPAT_DATA_PATH'"
			DESTCOMPDATA="$STLPROTCOMPDATDIR/${CODA}-proton-${DESTPROT}"
			checkCompatdataSymlink
		else
			writelog "INFO" "${FUNCNAME[0]} - Using regular compatdata '$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" 1	
			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 "$(xdotool 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 {
	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
}

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" 1

			if [ ! -f "$IGCSSRC" ]; then
				if [ ! -f "$IGCSDL/${IGCSZIP##*/}" ]; then
					writelog "INFO" "${FUNCNAME[0]} - '$IGCSDL/${IGCSZIP##*/}' not found - downloading automatically from '$IGCSZIP'"
					"$WGET" "$IGCSZIP" -P "$IGCSDL"
				fi
				"$UNZIP" "$IGCSDL/${IGCSZIP##*/}" -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" 1	
					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" != "$("$WHICH" echo 2>/dev/null)" ]; then
					writelog "SKIP" "${FUNCNAME[0]} - USECUSTOMCMD is '$USECUSTOMCMD' therefore skipping the custom program '$CUSTOMCMD'"
				fi
			fi
		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"

	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[@]}"
			else
				"$WTRUN" "$WINETRICKS" --unattended "${INSTPAKS[@]}"
			fi
			notiShow "$NOTY_WTFIN"
			emptyVars "O" "X"
			writelog "INFO" "${FUNCNAME[0]} - '$WINETRICKS' Installation of '$WTPAKS' exited"
		fi

		if [ -f "$WTLOG" ]; then
			gawk -i inplace '!visited[$0]++' "$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[@]}"
					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
		fi
	fi
	# silent:
	installWinetricksPaks "$WINETRICKSPAKS" "$RUNWINE" "extWine64Run"
}

function chooseWinetricks {
	if [ "$ISGAME" -ne 3 ]; 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 "$("$WHICH" "$SYSWINETRICKS" 2>/dev/null)" 2>/dev/null)" ]; 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 chooseWinetricksPrefix {
	if [ -n "$1" ]; then
		AID="$1"
		setAIDCfgs
	fi

	if [ ! -f "$STLGAMECFG" ]; then
		writelog "ERROR" "${FUNCNAME[0]} - Game config '$STLGAMECFG' not found - exiting" "E"
	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 "${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" E
					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="$(PROTPATH "$WTPROTON")"

					if [ ! -f "$RUNWTPROTON" ]; then
						RUNWTPROTON="$(fixProtonVersionMismatch "$WTPROTON" 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'" E
						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 {
	if [ -n  "$VIRTUALDESKTOP" ]; then
		TEMPREG="$GPFX/VirtualDesktop.reg"

		if [ "$VIRTUALDESKTOP" -eq 1 ]; then
			if [ -f "$TEMPREG" ]; then
				writelog "SKIP" "${FUNCNAME[0]} - Looks like virtual desktop was already applied before"
			else
				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\"=\"$(getScreenRes r)\""
					} >> "$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
	fi

	if [ "$REGEDIT" -eq 1 ]; then
		writelog "INFO" "${FUNCNAME[0]} - REGEDIT set, looking for '$AID' registry files"

		if [ -f "$AIDREG" ]; then
			regEdit "$AIDREG"
		fi
		
		if [ -f "$STLREGDIR/$AID.reg" ]; then
			regEdit "$STLREGDIR/$AID.reg"
		fi
	else
		if [ "$REGEDIT" -ne 0 ]; then
		
			AIDREG="$GLOBALREGDIR/$REGEDIT"

			if [ -f "$AIDREG" ]; then
				regEdit "$AIDREG"
			fi

			if [ -f "$STLREGDIR/$REGEDIT" ]; then
				regEdit "$STLREGDIR/$REGEDIT"		
			fi

			if [ ! -f "$AIDREG" ] && [ ! -f "$STLREGDIR/$REGEDIT" ]; then
				writelog "SKIP" "${FUNCNAME[0]} - '$REGEDIT' neither found global nor local - skipping"
			fi
		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" != "$("$WHICH" echo 2>/dev/null)" ]; 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 {
	if [ "$CHEATENGINEVERSION" == "7.2" ]; then
		writelog "ERROR" "${FUNCNAME[0]} - Cheat Engine upstream removed version 7.2 - check the wiki for details!" "E"
	else
	CESET="$1"
	writelog "INFO" "${FUNCNAME[0]} - Downloading '$CESET' into '$CEDLDIR'"
	notiShow "$(strFix "$NOTY_DLCE" "$CESET")"
#	"$WGET" -q "$CHEATENGINEURL/download/$CHEATENGINEVERSION/$CESET" -O "$CEDLDIR/$CESET"
	wgetGui "$CHEATENGINEURL/download/$CHEATENGINEVERSION/$CESET" "$CEDLDIR/$CESET"
	fi
}

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" 1
			CEINSTDIR="$CEPFX/$DRC/Program Files/${CE} $CHEATENGINEVERSION"
			writelog "INFO" "${FUNCNAME[0]} - Installing '$CEDLDIR/$CESET' into '$CEPFX' using '$RUNWINE'"
			notiShow "$(strFix "$NOTY_INSTCE" "$CESET")"
			WINE="$RUNWINE" WINEARCH=win64 WINEDEBUG="$STLWINEDEBUG" WINEPREFIX="$CEPFX" "$RUNWINE" "$CEDLDIR/$CESET" "/VERYSILENT"
			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"
				installCheatEngine
			fi

			if [ ! -f "$CEEXE" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Installing failed - can't start '$CE' - skipping"
			else
				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 {
	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
}

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
}

# Vortex:
function addVortexStage {
	if [ ! -f "$VORTEXSTAGELIST" ]; then 
		{
		echo "# List of directories, which Vortex uses as 'Stage directories'"
		echo "# (see Wiki for a comprehensive description)"
		} > "$VORTEXSTAGELIST"
	fi

	if [ -z "$1" ]; then
		export CURWIKI="$PPW/Vortex"
		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 mkdir "$1" 2>/dev/null; then
				NEWVS="$1"
			else
				writelog "SKIP" "${FUNCNAME[0]} - Skipping invalid argument '$1'"
			fi
		fi
	fi
	
	if [ -n "$NEWVS" ]; then
		echo "$NEWVS" >> "$VORTEXSTAGELIST"
		gawk -i inplace '!visited[$0]++' "$VORTEXSTAGELIST"
	fi
}

function setVortexProtonWine {
	if [ -n "$VORTEXWINE" ] && [ -f "$VORTEXWINE" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Already have a working VORTEXWINE '$VORTEXWINE'"
	else
		if [ -z "$USEVORTEXPROTON" ] || [ "$USEVORTEXPROTON" == "$NON" ]; then
			writelog "INFO" "${FUNCNAME[0]} - USEVORTEXPROTON not configured opening gui"
			USEVORTEXPROTON="$(needNewProton "X")"
		fi

		if [ -z "$USEVORTEXPROTON" ] || [ "$USEVORTEXPROTON" == "$NON" ]; then
			writelog "ERROR" "${FUNCNAME[0]} - USEVORTEXPROTON still not configured - giving up!"
			USEVORTEX="0"
		else	
			writelog "INFO" "${FUNCNAME[0]} - Using Proton Version '$USEVORTEXPROTON'"
		
			if test -z "$VORTEXPROTON" || [ ! -f "$VORTEXPROTON" ]; 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
				VORTEXPROTON="$(PROTPATH "$USEVORTEXPROTON")"
			fi

			if [ ! -f "$VORTEXPROTON" ]; then
				VORTEXPROTON="$(fixProtonVersionMismatch "$USEVORTEXPROTON" X)"
			fi

			if [ ! -f "$VORTEXPROTON" ]; then
				writelog "WARN" "${FUNCNAME[0]} - proton file '$VORTEXPROTON' for proton version '$VORTEXPROTON' not found - trying 'USEPROTON' instead" "E"
				VORTEXPROTON="$(PROTPATH "$USEPROTON")"
			fi

			if [ -f "$VORTEXPROTON" ]; then
				export VORTEXPROTON
				CHECKVTXWINED="$(dirname "$VORTEXPROTON")/$DBW"
				CHECKVTXWINEF="$(dirname "$VORTEXPROTON")/$FBW"
				if [ -f "$CHECKVTXWINED" ]; then
					VORTEXWINE="$CHECKVTXWINED"
					export VORTEXWINE
				elif [ -f "$CHECKVTXWINEF" ]; then
					VORTEXWINE="$CHECKVTXWINEF"
					export VORTEXWINE	
				else
					writelog "ERROR" "${FUNCNAME[0]} -VORTEXWINE '$VORTEXWINE' was not found - can't continue with using Vortex!" "E"
					USEVORTEX="0"
				fi
			else
				writelog "ERROR" "${FUNCNAME[0]} -VORTEXPROTON '$VORTEXPROTON' was not found - can't continue with using Vortex!" "E"
				USEVORTEX="0"	
			fi
		fi
	fi
}

function wineVortexRun {
	# leave LC_ALL=C else your "My Documents" will not be found!
	VORTEXPFX="${VORTEXCOMPDATA//\"/}/pfx"
	setVortexProtonWine
	sleep 1 # required!

	LC_ALL="C" PATH="$STLPATH" LD_LIBRARY_PATH="" LD_PRELOAD="" DXVK_LOG_PATH="$VORTEX_DXVK_LOG_PATH" DXVK_LOG_LEVEL="$VORTEX_DXVK_LOG_LEVEL" WINE="$VORTEXWINE"  WINEARCH="win64" WINEDEBUG="$VORTEXWINEDEBUG" WINEPREFIX="$VORTEXPFX" "$@"
}

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 Vortex"

	VD="$VTX-$PROGCMD-dl.desktop"
	FVD="$HOME/.local/share/applications/$VD"
	VORTEXPFX="${VORTEXCOMPDATA//\"/}/pfx"
	setVortexProtonWine
	
	if [ ! -f "$FVD" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Creating new desktop file $FVD"
		{
		echo "[Desktop Entry]"
		echo "Type=Application"
		echo "Categories=Game;"
		echo "Name=Vortex ($PROGNAME - $PROGCMD)"
		echo "MimeType=x-scheme-handler/nxm;x-scheme-handler/nxm-protocol"
		echo "Terminal=false"
		echo "X-KeepTerminal=false"
		echo "Path=$(dirname "$VORTEXEXE")"
		echo "Exec=env LC_ALL=C WINEDEBUG=\"-all\" WINEPREFIX=\"$VORTEXPFX\" \"$VORTEXWINE\" Vortex.exe -d %u"
		echo "NoDisplay=true"
		} >> "$FVD"
	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 $PROGCMD"
			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 getLatestMO2Ver {
	MO2SET="Mod.Organizer"

	writelog "INFO" "${FUNCNAME[0]} - Search for latest '$MO2SET' Release"
	MO2SETUP="$("$WGET" -q  "${MO2DLURL}" -O - | grep "exe" | grep -m1 "$MO2SET" | grep -oE "${MO2SET}[^\"]+")"
}

function dlLatestMO2 {
	getLatestMO2Ver

	if [ -n "$MO2SETUP" ]; then
		mkProjDir "$MO2DLDIR" 1
		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'" E
			wgetGui "$DLURL" "$MO2SPATH"

			if [ -f "$MO2SPATH" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Download succeeded - continuing installation" E
			else
				writelog "ERROR" "${FUNCNAME[0]} - Download failed!" E
			fi
		fi	
	else
		writelog "SKIP" "${FUNCNAME[0]} - No MO2SETUP defined - nothing to download - skipping"
	fi
}

function getLatestVortVer {
	VSET="$VTX-setup"

	if [ "$USEVORTEXPRERELEASE" -eq 1 ]; then
		writelog "INFO" "${FUNCNAME[0]} - Search for latest Vortex Pre-Release"
		VORTEXSETUP="$("$WGET" -q  "${VORTEXRELURL}" -O - | grep -m1 "$VSET" | grep -oE "${VSET}[^\"]+")"
	else
		writelog "INFO" "${FUNCNAME[0]} - Search for latest Vortex stable Release"
		VORTEXSETUP="$("$WGET" -q  "${VORTEXRELURL}/latest" -O - | grep -m1 "$VSET" | grep -oE "${VSET}[^\"]+")"
	fi
}

function dlLatestVortex {
	VORTEXPFX="${VORTEXCOMPDATA//\"/}/pfx"
	getLatestVortVer

	if [ -n "$VORTEXSETUP" ]; then
		VSPATH="$VORTEXDLDIR/$VORTEXSETUP"

		# download:
		if [ ! -d "$VORTEXDLDIR" ]; then
			mkdir -p "$VORTEXDLDIR" 2>/dev/null
		fi

		if [ ! -f "$VSPATH" ]; then
			VVRAW="$(grep -oP "${VSET}-\K[^X]+" <<< "$VORTEXSETUP")"
			VORTEXVERSION="${VVRAW%.exe}"
			DLURL="$VORTEXRELURL/download/v$VORTEXVERSION/$VORTEXSETUP"
			writelog "INFO" "${FUNCNAME[0]} - Downloading $VORTEXSETUP to $VORTEXDLDIR from '$DLURL'" E
			notiShow "$(strFix "$NOTY_DLCUSTOMPROTON" "$VORTEXSETUP")"
			wgetGui "$DLURL" "$VSPATH"
			notiShow "$(strFix "$NOTY_DLCUSTOMPROTON2" "$VORTEXSETUP")"
		fi	
	else
		writelog "SKIP" "${FUNCNAME[0]} - No VORTEXSETUP defined - nothing to download - skipping"
	fi
}

function linkVortex {
	LNSRC="$1"
	LNDST="$2"
#	LNDST="${2%/*}"
	writelog "INFO" "${FUNCNAME[0]} - LNSRC='$LNSRC': Should point into Game WINEPREFIX"
	writelog "INFO" "${FUNCNAME[0]} - LNDST='$LNDST': Should point into Vortex WINEPREFIX"

	if grep -q -i "$VTX" <<< "$LNSRC"; then
		writelog "WARN" "${FUNCNAME[0]} - Symlink Source '$LNSRC' seems to be in the Vortex WINEPREFIX which probably is an error!"
	fi

	if ! grep -q -i "$VTX" <<< "$LNDST"; then
		writelog "WARN" "${FUNCNAME[0]} - Symlink Destination '$LNDST' seems not to be in the Vortex WINEPREFIX which probably is an error!"
	fi

	if readlink "$LNDST" >/dev/null ; then
		writelog "INFO" "${FUNCNAME[0]} - Symlink $LNDST already exists"
		if [ "$(readlink "$LNDST")" == "$LNSRC" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Symlink $LNDST already points to the correct directory $LNSRC"
		else
			writelog "INFO" "${FUNCNAME[0]} - Symlink $LNDST points to $(readlink "$LNDST") which is not the correct directory $LNSRC - renewing!"
			rm "$LNDST"
			ln -s "$LNSRC" "$LNDST"
		fi
	else
		if [ -d "$LNDST" ]; then
			if [ "$( find "$LNDST" -type l | wc -l)" -eq 0 ]; then
				writelog "INFO" "${FUNCNAME[0]} - $LNDST is a real directory - renaming it to $LNDST-$(date +%y-%m-%d)"
				mv "$LNDST" "${LNDST}-$(date +%y-%m-%d)"
			else
				writelog "WARN" "${FUNCNAME[0]} - $LNDST is a real directory, but contains symlinks, which is a sign that it is an important Vortex directory"
				writelog "WARN" "${FUNCNAME[0]} - Leaving it untouched, but next Symlink Step might fail"
			fi
		fi
		writelog "INFO" "${FUNCNAME[0]} - Symlink from '$LNSRC' to '$LNDST' does not exist yet - creating it now"
		ln -s "$LNSRC" "$LNDST"
	fi
}

function getVortexStage {
	if [ -z "$VORTEXSTAGING" ]; then
		WANTSTAGE="$1"
		mkdir "$WANTSTAGE" 2>/dev/null
		if [ -d "$WANTSTAGE" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Created dir '$WANTSTAGE' $PARTLOG"
			VORTEXSTAGING="$WANTSTAGE"
		fi
	fi 	
}

function getInstalledGamesWithVortexSupport {
	getVortexSupported
	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
}

function getGameSteamCategories {
	SCGAME="$1"

	if [ -z "$SUSDA" ]; then
		setSteamPaths
	fi
	if [ -d "$SUSDA" ]; then
		STEAMUSERID="$(find "$SUSDA" -maxdepth 1 -type d -name "[1-9]*")"
		SC="$STEAMUSERID/$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 '{\|}' | gawk '{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 Vortex Dialog for en/disabling Vortex for installed games"

	getInstalledGamesWithVortexSupport
	export CURWIKI="$PPW/Vortex"
	TITLE="${PROGNAME}-Vortex 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" | gawk -F ';' '{print $2}')"
				GVCFG="$STLGAMEDIRID/${checkvgame}.conf"

				if ! grep -q "$checkvgame" <<< "${VINGAMES[@]}"; then
					writelog "INFO" "${FUNCNAME[0]} - Disabling Vortex 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 Vortex for '$VGNAM', the game needs to be removed from the Vortex Steam Category manually" E
					fi
				else
					writelog "INFO" "${FUNCNAME[0]} - Enabling Vortex 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" "E"
		;;
	esac

	rm "$VGNLIST" "$VGNSCLIST" 2>/dev/null
}

function VortexSymDialog {
	VORTEXPFX="${VORTEXCOMPDATA//\"/}/pfx"
	VPDRC="$VORTEXPFX/$DRC"
	if [ -d "$VPDRC" ]; then
		export CURWIKI="$PPW/Vortex"	
		TITLE="${PROGNAME}-Vortex Symlinks"
		pollWinRes "$TITLE"

		setShowPic

		cd "$VPDRC" || 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 - || return
	else
		writelog "SKIP" "${FUNCNAME[0]} - Directory '$VPDRC' not found " E
	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
	}

	VORTEXPFX="${VORTEXCOMPDATA//\"/}/pfx"
	VORTEXINSTDIR="$VORTEXPFX/$BTVP"
	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 setupGameVortex {
	VORTEXPFX="${VORTEXCOMPDATA//\"/}/pfx"
	setVortexProtonWine

	if [ -d "$VORTEXINSTDIR" ]; then
		VBP="$VORTEXINSTDIR/$RABP"
		writelog "INFO" "${FUNCNAME[0]} - Trying to find the Nexus GameID for the game '$SGNAID' in Vortex Install dir $VORTEXINSTDIR"

		SEARCH="$AID"
		if [ "$AID" == "22370" ]; then # Fallout 3 German is not detected by vortex
			SEARCH="22300"
		fi

		NEXUSGAMEBETA=0
		NEXUSGAMEFILE="$(grep -r -i "$SEARCH" "$VBP"/game-*/index.js | grep -i "steamAppId\|STEAM_ID\|STEAMAPP_ID\|STEAM_APP_ID" | grep -oE '^[^\:]+' | sort -u | head -n1)"
		if [ -z "$NEXUSGAMEFILE" ]; then
			USVOPLU="$VORTEXPFX/$DRCU/$STUS/$APDA/Vortex/plugins"
			writelog "INFO" "${FUNCNAME[0]} - No NEXUSGAMEFILE found in Vortex install dir - trying to find it in the Vortex user data '$USVOPLU'"
			NEXUSGAMEFILE="$(grep -R -i "$SEARCH" "$USVOPLU"/*/index.js | grep -i "steamAppId\|STEAM_ID\|STEAMAPP_ID\|STEAM_APP_ID" | grep -oE '^[^\:]+' | sort -u | head -n1)"
			if [ -n "$NEXUSGAMEFILE" ]; then
				NEXUSGAMEBETA=1
			fi
		fi
		if [ -n "$NEXUSGAMEFILE" ]; then
			if [ -f "$NEXUSGAMEFILE" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Found NEXUSGAMEFILE $NEXUSGAMEFILE for the game '$SGNAID'"

				if [ -n "$NEXUSGAMEID" ] ; then
					writelog "INFO" "${FUNCNAME[0]} - Found Nexus GameID '$NEXUSGAMEID' for the game '$SGNAID' in game config"
				else
					NEXUSGAMEID="$(gawk -F 'game-' '{print $2}' <<< "$(basename "$(gawk -F '/index.js' '{print $1}' <<< "$NEXUSGAMEFILE")")")"
					if [ -n "$NEXUSGAMEID" ]; then
						writelog "INFO" "${FUNCNAME[0]} - Autodetected Nexus GameID '$NEXUSGAMEID' - adding it to the game config '$STLGAMECFG' and generic Meta Config '$GEMETA/$AID.conf'"
						updateConfigEntry "NEXUSGAMEID" "$NEXUSGAMEID" "$STLGAMECFG"
						updateConfigEntry "NEXUSGAMEID" "$NEXUSGAMEID" "$GEMETA/$AID.conf"
						writelog "INFO" "${FUNCNAME[0]} - Cut the Nexus GameID '$NEXUSGAMEID' for the game '$SGNAID' out of the filename '$NEXUSGAMEFILE'"
					fi
				fi
			else
				writelog "SKIP" "${FUNCNAME[0]} - NEXUSGAMEFILE '$NEXUSGAMEFILE' is not a valid file"
				return
			fi
		else
			writelog "SKIP" "${FUNCNAME[0]} - Looks like the game '$SGNAID' is not supported in Vortex/Nexus, or autodetecting failed"
		fi
	else
		writelog "ERROR" "${FUNCNAME[0]} - Vortex Install dir '$VORTEXINSTDIR' not found - this shouldn't happen"
	fi

	# configure Game Specific Vortex Settings:
	if [ -n "$NEXUSGAMEID" ] || [ "$NEXUSGAMEBETA" -eq 1 ]; then

		# configure Vortex Download Dir:
		if [ -z "$VORTEXDOWNLOADPATH" ]; then
			VORTEXDOWNLOADPATH="$STLDLDIR"
			writelog "INFO" "${FUNCNAME[0]} - VORTEXDOWNLOADPATH was not set - set default to '$VORTEXDOWNLOADPATH'"
		fi

		if [ -n "$VORTEXDOWNLOADPATH" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Configuring $VORTEXDOWNLOADPATH as Vortex Download Path"

			if [ ! -d "$VORTEXDOWNLOADPATH" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Creating Vortex Download Dir '$VORTEXDOWNLOADPATH'"
				mkdir -p "$VORTEXDOWNLOADPATH"
			fi

			VDPF="$VORTEXDOWNLOADPATH/__vortex_downloads_folder"
			if [ ! -f "$VDPF" ]; then
				echo "{\"instance\":\"empty\"}" > "$VDPF"
			fi

			VORTEXDOWNLOADWINPATH="$(wineVortexRun "$VORTEXWINE" winepath -w "$VORTEXDOWNLOADPATH" | sed "s/\\\/\\\\\\\/g")"
			writelog "INFO" "${FUNCNAME[0]} - Setting Vortex Download WinDir '$VORTEXDOWNLOADWINPATH' in Vortex"
			cd "$VORTEXINSTDIR" || return
			wineVortexRun "$VORTEXWINE" "$VORTEXEXE" --set settings.downloads.path=true
			wineVortexRun "$VORTEXWINE" "$VORTEXEXE" --set settings.downloads.path=\""$VORTEXDOWNLOADWINPATH"\"
			cd - || return
		fi

		# Game Settings:

		# autodiscover our "manual added" game
		GDNP="C:\\\Program Files (x86)\\\Steam\\\steamapps\\\common\\\\$GN"
		
		if [ -n "$NEXUSGAMEID" ]; then
			cd "$VORTEXINSTDIR" || return
			wineVortexRun "$VORTEXWINE" "$VORTEXEXE" --set settings.gameMode.discovered."$NEXUSGAMEID".hidden=false
			wineVortexRun "$VORTEXWINE" "$VORTEXEXE" --set settings.gameMode.discovered."$NEXUSGAMEID".path=true
			wineVortexRun "$VORTEXWINE" "$VORTEXEXE" --set settings.gameMode.discovered."$NEXUSGAMEID".path=\""$GDNP"\"
			wineVortexRun "$VORTEXWINE" "$VORTEXEXE" --set settings.mods.activator."$NEXUSGAMEID"=true
			wineVortexRun "$VORTEXWINE" "$VORTEXEXE" --set settings.mods.activator."$NEXUSGAMEID"=\"hardlink_activator\"
			cd - || return
		fi
		
		if [ -f "$NEXUSGAMEFILE" ]; then
			if grep -q -E 'getPath.*documents' "$NEXUSGAMEFILE"; then
				writelog "INFO" "${FUNCNAME[0]} - Found Modpath in $NEXUSGAMEFILE - creating it in 'WINEPREFIX'"
				# LOAD_ORDER_FILENAME exclude for witcher3
				GMODPATH="$(grep -E 'getPath.*documents' "$NEXUSGAMEFILE" | grep -v "LOAD_ORDER_FILENAME\|()" | gawk -F ')\, ' '{print $NF}' | gawk -F ')' '{print $1}' | sed "s:, :\/:g" | sed "s:'::g")"
				if [ -n "$SteamUserMyDocs" ] && [ -n "$GMODPATH" ]; then
					writelog "INFO" "${FUNCNAME[0]} - Creating directory $SteamUserMyDocs/$GMODPATH"
					mkdir -p "$SteamUserMyDocs/$GMODPATH" 2>/dev/null
				fi
			fi

			# find matching Staging Directory:
			GAMEMP="$(df -P "$GP" | gawk 'END{print $NF}')"
			writelog "INFO" "${FUNCNAME[0]} - Mount point of partition where the game is installed: '$GAMEMP'"
			CONFSTAGE=""

			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 you disabled autostages - skipping vortex"
					USEVORTEX="0"
				else
					PARTLOG=" - using that as VORTEXSTAGING dir for all games on partition' $GAMEMP'"
					HOMEMP="$(df -P "$STLVORTEXDIR" | gawk '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/Vortex"

					# then try in the current SteamLibrary dir besides steamapps, as it should be writeable by the user and is unused from steam(?):
					getVortexStage "$(gawk -F 'steamapps' '{print $1}' <<< "$GP")Vortex"

					# updating Vortex config with the new found VORTEXSTAGING dir:
					if [ -n "$VORTEXSTAGING" ]; then
						if ! grep -q "$VORTEXSTAGING" < "$VORTEXSTAGELIST"; then
							writelog "INFO" "${FUNCNAME[0]} - Adding '$VORTEXSTAGING' to the Vortex 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" ] && [ -n "$NEXUSGAMEID" ]; then
				writelog "INFO" "${FUNCNAME[0]} - VORTEXSTAGING set to '$VORTEXSTAGING' - configuring '$NEXUSGAMEID' installPath"
				VGSGM="$VORTEXSTAGING/$NEXUSGAMEID/mods"

				writelog "INFO" "${FUNCNAME[0]} - Creating Vortex Staging folder '$VGSGM'"
				mkdir -p "$VGSGM"

				VGSGMSF="$VGSGM/__vortex_staging_folder"
				if [ ! -f "$VGSGMSF" ]; then
					echo "{\"instance\":\"empty\",\"game\":\"NEXUSGAMEID\"}" > "$VGSGMSF"
				fi

				GAMESTAGINGWINFOLDER="$(wineVortexRun "$VORTEXWINE" winepath -w "$VGSGM" | sed "s/\\\/\\\\\\\/g")"
				writelog "INFO" "${FUNCNAME[0]} - Setting Staging folder '$GAMESTAGINGWINFOLDER' in Vortex"

				cd "$VORTEXINSTDIR" || return
				wineVortexRun "$VORTEXWINE" "$VORTEXEXE" --set settings.mods.installPath."$NEXUSGAMEID"=true
				wineVortexRun "$VORTEXWINE" "$VORTEXEXE" --set settings.mods.installPath."$NEXUSGAMEID"=\""$GAMESTAGINGWINFOLDER"\"
				cd - || return

			fi

			# 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=""

				# would as well work in a loop for all index.js files, but better just take those which are actually need:
				RAWREG="$(grep -E 'instPath.*winapi.RegGetValue' "$NEXUSGAMEFILE" -A3 | tr -d "\n\r" | gawk -F 'RegGetValue' '{print $2}' | cut -d';' -f1  | tr -s " " | sed "s:^(::g" | sed "s:)$::g" | sed  's/, /,/g' | gawk '{$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="$(gawk -F ',' '{print $1}' <<< "$REGWIP" | sed "s:'::g")"
						PATHKEY="$(gawk -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, to make the generic function checkVortexRegs happy"
							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'"
					checkVortexRegs "$REGKEY" "$PATHKEY"
				else
					writelog "SKIP" "${FUNCNAME[0]} - REGKEY '$REGKEY' or PATHKEY '$PATHKEY' is empty - skipping registry insert"
				fi
			fi

			# create custom paths in WINEPREFIX so symlinks can already be created
			customVortexGameSettings
		fi
	else
		writelog "SKIP" "${FUNCNAME[0]} - NEXUSGAMEID is empty and no Beta extension found - skipping automatic adding game '$SGNAID' to Vortex"
	fi
}

function precustomVortexGameDirs {
	
	if [ "$AID" == "$1" ]; then

		CDIR="$SteamUserDir/$MyDocsMyGames/$2"
		if [ ! -d "$CDIR" ]; then
			mkdir -p "$CDIR" 2>/dev/null
			writelog "INFO" "${FUNCNAME[0]} - Created dir '$CDIR'"
		fi

		CADGDIR="$SteamUserDir/$LSAD/$2"
		if [ ! -d "$CADGDIR" ]; then
			mkdir -p "$CADGDIR" 2>/dev/null
			writelog "INFO" "${FUNCNAME[0]} - Created dir '$CADGDIR'"
		fi
	fi
}

function customVortexGameSettings {
	precustomVortexGameDirs "377160" "${GN// /}"		# Fallout4
	precustomVortexGameDirs "611660" "${GN// /}"		# Fallout4 VR
	precustomVortexGameDirs "611670" "${GN//VR/ VR}"	# Skyrim VR
	precustomVortexGameDirs "489830" "$GN"				# Skyrim Special Edition
	precustomVortexGameDirs "72850" "$GN"				# Skyrim
	precustomVortexGameDirs "933480" "$GN"				# Enderal
	precustomVortexGameDirs "22300" "${GN// /}"			# Fallout 3
	precustomVortexGameDirs "22370" "${GN// /}"			# Fallout 3 GOTY
	precustomVortexGameDirs "22380" "FalloutNV"			# Fallout New Vegas 
	precustomVortexGameDirs "22330" "$GN"				# Oblivion

	# Fallout3 symlink:
	if [ "$AID" == "22370" ]; then
		FOGDIR="$SteamUserDir/$LSAD/Fallout3goty"
		if [ ! -d "$FOGDIR" ]; then
			mkdir -p "$FOGDIR" 2>/dev/null
		fi

		if [ -d "$FOGDIR" ]; then
			ln -s "$FOGDIR" "${FOGDIR//goty/}"
			ln -s "$UserLocalSetAppData/Fallout3goty" "$UserLocalSetAppData/Fallout3"
		fi
	fi
}

function startVortex {
	VORTEXPFX="${VORTEXCOMPDATA//\"/}/pfx"
	initVortexStuff

	setVortexProtonWine

	if [ -f "$VORTEXEXE" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Starting Vortex now with command '$VORTEXWINE $VORTEXEXE --game $NEXUSGAMEID' in WINEPREFIX '$VORTEXPFX'"

		setVortexDLMime

		if [ -n "$NEXUSGAMEID" ]; then
			cd "$VORTEXINSTDIR" || return
			wineVortexRun "$VORTEXWINE" "$VORTEXEXE" --game "$NEXUSGAMEID"
			cd - || return
		else
			if [ "$1" == "getset" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Showing settings as requested"
				cd "$VORTEXINSTDIR" || return
				wineVortexRun "$VORTEXWINE" "$VORTEXEXE" --get settings
				cd - || return
			else
				writelog "INFO" "${FUNCNAME[0]} - Starting Vortex without options"
				cd "$VORTEXINSTDIR" || return
				wineVortexRun "$VORTEXWINE" "$VORTEXEXE"
				cd - || return
			fi
		fi

		cleanVortex
		writelog "INFO" "${FUNCNAME[0]} - Vortex exited - starting game now"
	else
		writelog "ERROR" "${FUNCNAME[0]} - VORTEXEXE '$VORTEXEXE' not found! - exit"
		exit
	fi
}

function checkVortexRegs {
	# this is a bit of a mess - not 100% sure if we always should use wine64 for adding non-"Wow6432Node" keys, so querying the Wow6432Node key and adding the non-"Wow6432Node" key
	# in very rare cases the non-"Wow6432Node" key is searched in the registry - f.e. witcher 3, so additionally adding every key using wine64  - probably shouldn't be a problem(?)

	REGKEY="$1"
	REG32KEY="${REGKEY//\\Wow6432Node\\/}"

	setVortexProtonWine

	if [ -n "$2" ]; then
		PATHKEY="$2"
	else
		PATHKEY="Installed Path"
	fi

	if [ -n "$3" ]; then
		INSTP="$3"
	else
		INSTP="C:\\Program Files (x86)\\Steam\\steamapps\\common\\$GN"
	fi

	writelog "INFO" "${FUNCNAME[0]} - Checking RegKey '$REGKEY' and updating RegKey '$REG32KEY' in registry for game '$SGNAID' 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" | gawk -F 'REG_SZ' '{print $NF}' | gawk '{$1=$1};1' | tr -d "\n\r")"
		WSACPATH="$(SteamAppsCommonRelativeW=${SteamAppsCommonRelative//drive_c/C:}; echo "${SteamAppsCommonRelativeW//\//\\}"\\"$GN")"

		if [ "$REGPATH" == "$WSACPATH" ]; then
			writelog "INFO" "${FUNCNAME[0]} - The registry entry '$REGPATH' is identical to the gamepath '$WSACPATH'"
		else
			writelog "WARN" "${FUNCNAME[0]} - The registry entry '$REGPATH' is not equal to gamepath '$WSACPATH' - resetting registry to '$WSACPATH'"
			# remove old outdated registry path:
			wineVortexRun "$VORTEXWINE" reg DELETE "$REGKEY" /f >/dev/null
			# add new registry path:
			writelog "NEW" "${FUNCNAME[0]} - Registry path '$REGKEY' removed - recreating '$PATHKEY' entry for '$INSTP'"
			wineVortexRun "$VORTEXWINE" reg ADD "$REG32KEY" /f /t "REG_SZ" /v "$PATHKEY" /d "$INSTP" /f
		fi						
	else
		writelog "NEW" "${FUNCNAME[0]} - Registry path '$REGKEY' does not exist - creating '$PATHKEY' entry for '$INSTP'"
		# add new registry path:
		wineVortexRun "$VORTEXWINE" reg ADD "$REG32KEY" /f /t "REG_SZ" /v "$PATHKEY" /d "$INSTP"
		VORTEXWINE64="${VORTEXWINE//wine/wine64}"

		if  [ -x "$(command -v "$VORTEXWINE64" 2>/dev/null)" ]; then
			writelog "NEW" "${FUNCNAME[0]} - Adding the same entry using wine64"
			wineVortexRun "$VORTEXWINE64" reg ADD "$REG32KEY" /f /t "REG_SZ" /v "$PATHKEY" /d "$INSTP"
		fi
	fi
}

function setVortexSELaunch {
	if [ "$1" == "$AID" ]; 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 Vortex 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="Vortex Options"

	VORTEXPFX="${VORTEXCOMPDATA//\"/}/pfx"
	VORTEXINSTDIR="$VORTEXPFX/$BTVP"

	if [ -n "${VORTEXCOMPDATA}" ]; then
		TT_CODA="Vortex compatdata: $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

	VTXDLV="$(find "${VORTEXDLDIR}" -name "${VTX}-setup*" | sort -V | tail -n1 | gawk -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 installVortex {
	USEVORTEX="1"
	initVortexStuff

	if [ -f "$VORTEXPROTON" ]; then
		reCreateCompatdata "ccd" "$VTX" "s"

		writelog "INFO" "${FUNCNAME[0]} - Base Vortex installation finished" "E"

		VDN="dotnet48"

		writelog "INFO" "${FUNCNAME[0]} - Trying to install $VDN now, which might fail depending on the used wine/proton version" "E"
		if [ -n "$1" ] && [ "$1" == "X" ]; then
			installWinetricksPaks "$VDN" "$VORTEXWINE" "wineVortexRun"
		elif [ -n "$1" ] && [ "$1" == "F" ]; then
			installWinetricksPaks "$VDN" "$VORTEXWINE" "wineVortexRun" "F"
		fi
		setVortexDLMime
	fi
}

function installVortexGui {
	export CURWIKI="$PPW/Vortex"
	TITLE="${PROGNAME}-${FUNCNAME[0]}"
	pollWinRes "$TITLE"
	setShowPic

	createProtonList X

	VORTEXPFX="${VORTEXCOMPDATA//\"/}/pfx"
	VORTEXINSTDIR="$VORTEXPFX/$BTVP"
	if [ -f "${VORTEXINSTDIR}/${VTXRAA}" ]; then
		GUI_VTXINST="$(printf '%s\n%s\n' "${GUI_VTXINST}" "Version installed: $(getInstVtxVers)")"
	fi

	VTXDLV="$(find "${VORTEXDLDIR}" -name "${VTX}-setup*" | sort -V | tail -n1 | gawk -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 "$USEVORTEXPROTON!$PROTYADLIST" \
     		--field="$GUI_INSTALLDOTNET!$DESC_INSTALLDOTNET":CHK "FALSE" \
     		--field="$GUI_FORCEWT!$DESC_FORCEWT":CHK "FALSE" \
		--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]}"
					INSTALLDOTNET="${VTARR[1]}"
					FORCEWT="${VTARR[2]}"

					if [ "$INSTALLDOTNET" == "TRUE" ] && [ "$FORCEWT" == "FALSE" ]; then
						installVortex X
					elif [ "$INSTALLDOTNET" == "TRUE" ] && [ "$FORCEWT" == "TRUE" ]; then
						installVortex F
					else
						installVortex
					fi
				}
			;;	
		esac
}

function askVortex {
	if [ "$USEVORTEX" == "1" ]; then
		if [ "$WAITVORTEX" -gt 0 ]; then
			writelog "INFO" "${FUNCNAME[0]} - Opening Vortex 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 Vortex, so not disabling it"
					}
				;;
				4)  {
						writelog "INFO" "${FUNCNAME[0]} - Selected CANCEL - Not starting Vortex"
						USEVORTEX="0"
					}
				;;
				70) {
						writelog "INFO" "${FUNCNAME[0]} - TIMEOUT - Not starting Vortex"
						USEVORTEX="0"
					}
				;;
			esac
		else
			writelog "INFO" "${FUNCNAME[0]} - Vortex Requester was skipped because WAITVORTEX is '$WAITVORTEX'"
		fi
	fi
}

function initVortexStuff {
	setVortexProtonWine
	if [ -z "$VORTEXWINE" ] || [ ! -f "$VORTEXWINE" ]; then
		writelog "INFO" "${FUNCNAME[0]} - No wine binary configured in variable VORTEXPROTON or wine in variable '$VORTEXPROTON' not found"
		if [ -n "$RUNWINE" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Using RUNWINE '$RUNWINE' as VORTEXWINE instead"
			VORTEXWINE="${RUNWINE//\"/}"
		else
			writelog "SKIP" "${FUNCNAME[0]} - Can't find a usable wine binary for VORTEXWINE - skipping"
			USEVORTEX="0"
		fi
	fi

	VORTEXPFX="${VORTEXCOMPDATA//\"/}/pfx"
	VORTEXINSTDIR="$VORTEXPFX/$BTVP"
	VORTEXEXE="$VORTEXINSTDIR/Vortex.exe"
}
	
function checkVortex {
	writelog "INFO" "${FUNCNAME[0]} - Vortex is enabled"
	VORTEXPFX="${VORTEXCOMPDATA//\"/}/pfx"
	setVortexProtonWine
	askVortex
	initVortexStuff
	writelog "INFO" "${FUNCNAME[0]} - VORTEXWINE is '$VORTEXWINE'"

	# checking WINEPREFIX for Vortex:
	if [ -n "$VORTEXPFX" ]; then
		mkdir -p "$VORTEXPFX" 2>/dev/null
		if [ -d "$VORTEXPFX" ]; then
			writelog "INFO" "${FUNCNAME[0]} - VORTEXPFX is a 'pfx' subdirectory of '$VORTEXCOMPDATA' and the directory exists"

			# checking for Vortex.exe:
			if [ -f "$VORTEXEXE" ]; then
				writelog "INFO" "${FUNCNAME[0]} - VORTEXEXE '$VORTEXEXE' exists"

				# creating some required directories in VORTEXPFX:
				SteamAppsCommonRelative="$DRC/Program Files (x86)/Steam/$SAC"
				VortexSteamAppsCommon="$VORTEXPFX/$SteamAppsCommonRelative"

				writelog "INFO" "${FUNCNAME[0]} - Creating subdirectories in '$VORTEXPFX' if missing"

				if [ ! -d "$VortexSteamAppsCommon" ]; then
					writelog "INFO" "${FUNCNAME[0]} - Creating directory $VortexSteamAppsCommon"
					mkdir -p "$VortexSteamAppsCommon"
				fi
				MyDocs="My Documents"
				MyDocsMyGames="$MyDocs/My Games"
				LocalSetAppData="$LSAD"
				
				if [ -d "$VORTEXPFX/$DRCU/$STUS" ]; then
					writelog "INFO" "${FUNCNAME[0]} - Vortex is running with Proton wine - configuring for user '$STUS'"
					VUSER="$STUS"
				else
					writelog "INFO" "${FUNCNAME[0]} - Vortex is running with regular wine - configuring for user '$USER'"
					VUSER="$USER"
				fi
				
				UserMyDocs="$VORTEXPFX/$DRCU/$VUSER/$MyDocs"
				UserMyDocsMyGames="$VORTEXPFX/$DRCU/$VUSER/$MyDocsMyGames"
				UserLocalSetAppData="$VORTEXPFX/$DRCU/$VUSER/$LocalSetAppData"
				
				if readlink "$UserMyDocsMyGames" >/dev/null ; then
					writelog "INFO" "${FUNCNAME[0]} - Removing symlink '$UserMyDocsMyGames' pointing to '$(readlink "$UserMyDocsMyGames")'"
					rm "$UserMyDocsMyGames"
				fi

				if readlink "$UserLocalSetAppData" >/dev/null ; then
					writelog "INFO" "${FUNCNAME[0]} - Removing symlink '$UserLocalSetAppData' pointing to '$(readlink "$UserLocalSetAppData")'"
					rm "$UserLocalSetAppData"
				fi
				
				mkdir -p "$UserMyDocsMyGames" 2>/dev/null
				mkdir -p "$UserLocalSetAppData" 2>/dev/null

				# game specific part:
				writelog "INFO" "${FUNCNAME[0]} - Preparing required registry and path settings for '$GFD' and '$SGNAID'"

				if [ "$USEWINE" -eq 0 ]; then
					GVFX="$GPFX"
				else
					GVFX="$GWFX"
				fi

				if [ -d "$GVFX" ] || [ -z "$(ls -A "$GVFX")" ]; then
					writelog "INFO" "${FUNCNAME[0]} - Original game WINEPREFIX $GVFX is not empty, so assuming it is useable"

					# checking symlinks:
					linkVortex "$GFD" "$VortexSteamAppsCommon/$GN"
					SteamUserDir="$GVFX/$DRCU/$STUS"
					
					SteamUserMyDocs="$SteamUserDir/$MyDocs"

					setupGameVortex

					# My Documents:
					while read -r dir; do
						if [ -d "$dir" ]; then
							writelog "INFO" "${FUNCNAME[0]} - Creating symlink from '$dir' to UserMyDocs '$UserMyDocs'"
							linkVortex "$dir" "$UserMyDocs/${dir##*/}"
						fi
					done <<< "$(find "$SteamUserMyDocs" -mindepth 1 -maxdepth 1 -type d | grep -v 'Music$\|Templates$\|Downloads$\|Pictures$\|Games$\|Videos$')"

					# My Games:
					SteamUserMyDocsMyGames="$SteamUserDir/$MyDocsMyGames"
					
					if [ -d  "$SteamUserMyDocsMyGames" ]; then
						while read -r dir; do
							if [ -d "$dir" ]; then
								writelog "INFO" "${FUNCNAME[0]} - Creating symlink 'from' $dir to UserMyDocsMyGames '$UserMyDocsMyGames'"
								linkVortex "$dir" "$UserMyDocsMyGames/${dir##*/}"
							fi
						done <<< "$(find "$SteamUserMyDocsMyGames" -mindepth 1 -maxdepth 1 -type d)"
					fi
					
					# Application Data:
					SteamUserLocalSetAppData="$SteamUserDir/$LocalSetAppData"
					while read -r dir; do
						if [ -d "$dir" ]; then
							writelog "INFO" "${FUNCNAME[0]} - Creating symlink from '$dir' to UserLocalSetAppData '$UserLocalSetAppData'"
							linkVortex "$dir" "$UserLocalSetAppData/${dir##*/}"
						fi
					done <<< "$(find "$SteamUserLocalSetAppData" -mindepth 1 -maxdepth 1 -type d | grep -v 'Microsoft\|openvr')"			

					# registry:
					checkVortexRegs "HKEY_LOCAL_MACHINE\\Software\\\Wow6432Node\\\Valve\\\Steam\\\Apps\\$AID"

					# symlinks and registry entries should be ready at this point for vortex
					writelog "INFO" "${FUNCNAME[0]} - Symlinks and registry entries should be ready at this point for Vortex"

					# start Vortex:
					startVortex
				else
					writelog "SKIP" "${FUNCNAME[0]} -  original game WINEPREFIX '$GVFX' does not exist or is empty - skipping Vortex and starting the game now once to create it!"
				fi

			# Vortex is not installed
			else
				writelog "WARN" "${FUNCNAME[0]} - VORTEXEXE '$VORTEXEXE' does not exist"
				if [ "$VORTEXINSTALL" -eq 1 ]; then
					writelog "INFO" "${FUNCNAME[0]} - VORTEXINSTALL is set to 1 so installing it now"
					installVortex X
					if [ -f "$VORTEXEXE" ]; then
						writelog "INFO" "${FUNCNAME[0]} - Looks like Vortex was installed correctly now - retrying to start it"
						checkVortex
					else
						writelog "ERROR" "${FUNCNAME[0]} - '$VORTEXEXE' still does not exist - please check '$VORTEXINSTDIR' or even the whole '$VORTEXPFX'"
					fi
				else
					writelog "SKIP" "${FUNCNAME[0]} - VORTEXINSTALL is set to 0 - skipping Vortex"
				fi
			fi
		else
			writelog "SKIP" "${FUNCNAME[0]} -  VORTEXPFX  is a 'pfx' subdirectory of '$VORTEXCOMPDATA' but the directory does not exist - skipping"
		fi
	else
		writelog "SKIP" "${FUNCNAME[0]} - But VORTEXPFX is not defined - skipping"
	fi
}

function checkDep {
	CATNAM="$1"
	CHECKPROG="$2"

	if [ -n "${!CATNAM##*[!0-9]*}" ]; then
		if [ "${!CATNAM}" -eq 1 ]; then
			if  [ ! -x "$(command -v "$("$WHICH" "$CHECKPROG" 2>/dev/null)" 2>/dev/null)" ]; then
				writelog "WARN" "${FUNCNAME[0]} - Disabling '$CATNAM' because '$CHECKPROG' is missing"
				notiShow "$(strFix "$NOTY_PROGRAMMISSING" "$CATNAM" "$CHECKPROG")"
				unset "$CATNAM"
			fi
		fi
	fi
}

function checkExtDeps {
	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"
}

function setYadBin {
	if [ -f "$1" ]; then
		YADFILE="$1"
	elif [ "$1" == "conty" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Using conty as yad binary" "E"
		if [ ! -f "$CONTYDLDIR/$CONTY" ]; then
			USEWGETGUI=0 dlConty
		else
			writelog "INFO" "${FUNCNAME[0]} - Found Conty binary in '$CONTYDLDIR/$CONTY'" "E"
		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'" "E"
			else
				writelog "INFO" "${FUNCNAME[0]} - Creating symlink '$CONTYDLDIR/${YAD##*/}' pointing to '$CONTYDLDIR/$CONTY'" "E"
				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
		YAI="$STLDLDIR/Yad-313ada9-x86_64.AppImage"
		if [ -f "$YAI" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Found Yad AppImage under '$YAI'" "E"
		else
			YAZ="yad-appimage.zip"
			YAIURL="$PROJECTPAGE/files/5451226/$YAZ"
			writelog "INFO" "${FUNCNAME[0]} - Downloading AppImage from '$YAIURL'" "E"
			"$WGET" -q "$YAIURL" -O "$STLDLDIR/$YAZ"
			"$UNZIP" -q "$STLDLDIR/$YAZ" -d "$STLDLDIR"
			rm "$STLDLDIR/$YAZ" 2>/dev/null
		fi
		if [ -f "$YAI" ]; then
			YADFILE="$YAI"
		fi
	else
		writelog "ERROR" "${FUNCNAME[0]} - '$1' is no valid option" "E"
	fi
	
	if [ -n "$YADFILE" ]; then
		MINYAD="7.2"
		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'" "E"
		else
			writelog "INFO" "${FUNCNAME[0]} - configuring yad binary to '$YADFILE'" "E"
			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" "E"
	else
		DEPSMISSING=0

		while read -r INTDEP; do

			if  [ ! -x "$(command -v "$("$WHICH" "${!INTDEP}" 2>/dev/null)" 2>/dev/null)" ]; 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  [ ! -x "$(command -v "$("$WHICH" "$YAD" 2>/dev/null)" 2>/dev/null)" ]; then
			DEPSMISSING=1
			writelog "ERROR" "${FUNCNAME[0]} - '$YAD' was not found! Check 'stl --help' for alternatives and/or read '$PROJECTPAGE/wiki/Custom-Yad'" "E"
			notiShow "$(strFix "$NOTY_NOTFOUND" "$YAD")"
		fi


		if  [ -x "$(command -v "$("$WHICH" "awk" 2>/dev/null)" 2>/dev/null)" ] && [ ! -x "$(command -v "$("$WHICH" "$AWK" 2>/dev/null)" 2>/dev/null)" ]; then
			writelog "WARN" "${FUNCNAME[0]} - Binary awk was found, but not '$AWK'. As awk can also be a different binary with different parameters 'gawk' is used for '$AWK'" "E"
		fi	

		MINYAD="7.2"
		YADVER="0"

		if [ -f "$YAD" ]; then
			YADVER="$("$YAD" --version | tail -n1 | cut -d ' ' -f1)"
		fi

		if [ "$1" == "--help" ]|| [ "$1" == "-h" ]; then
			howto
		else
			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")"
				exit
			fi

			if [ "$DEPSMISSING" -eq 1 ]; then
				writelog "ERROR" "${FUNCNAME[0]} - Above programs need to be installed to use '$PROGCMD'" "E"
				writelog "ERROR" "${FUNCNAME[0]} The dependency check can be disabled with enabling 'SKIPINTDEPCHECK' - exiting now" "E"
				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"
	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 #########"

	createDefaultCfgs "${ORGGCMD[@]}"
	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
	
	FIRSTUSEPROTON="$USEPROTON"
	writelog "INFO" "${FUNCNAME[0]} - OpenTrayIcon:"
	openTrayIcon

	if [ -z "$1" ]; then
		writelog "INFO" "${FUNCNAME[0]} - AskSettings:"
		askSettings
	else
		MainMenu "$AID"
	fi
	
	#  in case a path changed in between, call createProjectDirs again:
	writelog "INFO" "${FUNCNAME[0]} - CreateProjectDirs:"
	createProjectDirs

	writelog "INFO" "${FUNCNAME[0]} - LoadCfg: $STLGAMECFG"
	loadCfg "$STLGAMECFG"

	createDesktopIconFile "$AID" "0"

	# autoapply configuration settings based on the steam categories the game is in:
	writelog "INFO" "${FUNCNAME[0]} - AutoCategorySettings:"
	autoCategorySettings

	symlinkSteamUser "$USESUSYM"

	restoreSteamUser

	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 "$(PROTPATH "$USEPROTON")" ]; then
				fixProtonVersionMismatch "$USEPROTON"
			fi
		
			# (re)initialize Proton dependant variables, when USEPROTON changed in a menu above
			if [ -n "$USEPROTON" ] && [ "$USEPROTON" != "$FIRSTUSEPROTON" ] && [ "$ISGAME" -eq 2 ]; then
				setNewProtVars "$(PROTPATH "$USEPROTON")"
			fi
		else
			USEPROTON="$INPROTV"
			setNewProtVars "$(PROTPATH "$USEPROTON")"
			writelog "INFO" "${FUNCNAME[0]} - Checking the Proton version is not required, because Steam Launch option 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
		
		if [ "$HAVEINPROTON" -eq 0 ]; then
			if [ "$PROTONCHECK" == "ask_before_game" ] || [ "$PROTONCHECK" == "auto_download" ] || [ "$PROTONCHECK" == "auto_download_and_use" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Entering checkProtonBump"
				checkProtonBump "$USEPROTON" 
			fi
		fi
	fi
	
	# export DXVK_CONFIG_FILE if STLDXVKCFG was found:
	if [ -f "$STLDXVKCFG" ]; then
		export DXVK_CONFIG_FILE="$STLDXVKCFG"
	fi


	# shortcut to enable all required flags for SBSVR with ReShade
	if [ -n "$SBSVRRS" ]; then
		if [ "$SBSVRRS" -eq 1 ]; then
			writelog "INFO" "${FUNCNAME[0]} - $PROGNAME - SBSVRRS enabled - starting game in SBS-VR using ReShade"
			export RUNSBSVR=1
			export INSTALL_RESHADE=1
			export RESHADE_DEPTH3D=1
			export USERESHADE=1
			export ENABLE_VKBASALT=0
		fi
	fi

####

	setLinGameVals

#################

	# override tweak settings
	writelog "INFO" "${FUNCNAME[0]} - CheckTweakLaunch:"
	checkTweakLaunch

	# remove GFWL if NOGFWL is 1
	writelog "INFO" "${FUNCNAME[0]} - checkXliveless:"
	checkXliveless

	# choose either system winetricks or downloaded one
	writelog "INFO" "${FUNCNAME[0]} - chooseWinetricks:"
	chooseWinetricks

	# check dependencies - disable functions if dependency programs are missing and/or warn
	writelog "INFO" "${FUNCNAME[0]} - checkExtDeps:"
	checkExtDeps

	# set some wine variables if USEWINE is 1
	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

	# 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

	# install ReShade if INSTALL_RESHADE is 1
	writelog "INFO" "${FUNCNAME[0]} - InstallReshade:"
	installReshade

	# install Depth3D Shader if RESHADE_DEPTH3D is 1
	writelog "INFO" "${FUNCNAME[0]} - InstallReshadeDepth3D:"
	installReshadeDepth3D

	# start game wih Reshade if USERESHADE is 1
	writelog "INFO" "${FUNCNAME[0]} - UseReshade:"
	useReshade

	# open Shader Menu if CHOOSESHADERS  is 1
	writelog "INFO" "${FUNCNAME[0]} - ChooseShaders:"
	chooseShaders

	# 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"

	# disable side-by-side Depth3D Shader if RUNSBSVR is 0 
	writelog "INFO" "${FUNCNAME[0]} - CheckDepth3DUse:"
	checkDepth3DUse

	# start Vortex if USEVORTEX is 1
	if [ "$USEVORTEX" -eq 1 ]; then
		writelog "INFO" "${FUNCNAME[0]} - CheckVortex:"
		checkVortex
		# (for Vortex) if SELAUNCH is 0 start a preconfigured exe directly
		writelog "INFO" "${FUNCNAME[0]} - CheckVortexSELaunch with argument '$SELAUNCH':"
		checkVortexSELaunch "$SELAUNCH"
	fi
	
	# set other screen resolution
	setNewRes
	
	# start custom user script
	customUserScriptStart
	
	# redirect STEAM_COMPAT_DATA_PATH on request
	redirectSCDP

	# start igcsinjector if USEIGCS is enabled
	writelog "INFO" "${FUNCNAME[0]} - :"
	checkIGCSInjector

	# check if openvr-fsr is enabled
	checkOpenVRFSR

	# start a custom program if USECUSTOMCMD is enabled
	writelog "INFO" "${FUNCNAME[0]} - CheckCustomLaunch:"
	checkCustomLaunch

	# start a custom program if UUUSEPATCH or UUUSEVR is enabled
	writelog "INFO" "${FUNCNAME[0]} - checkUUUPatchLaunch:"
	checkUUUPatchLaunch
	
	# 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
	checkGamConLaunch

	# start CheatEngine when game starts if RUN_CHEATENGINE is -ge 1
	checkCheatEngineLaunch

	# set pulse latency if CHANGE_PULSE_LATENCY is 1
	checkPulse

	# create/remove steam_appid.txt
	checkSteamAppIDFile

	# Automatic Grid Update Check before_game
	if [ "$SGDBAUTODL" == "before_game" ] ; then
		writelog "INFO" "${FUNCNAME[0]} - Automatic Grid Update Check '$SGDBAUTODL'"
		getGrid "$AID" &
	fi

	# Create GameTitle Symlink in STLCOMPDAT if enabled
	setCompatDataTitle

	# GAME START
	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 "$(PROTPATH "$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'"
				dlCustomProton "${DLURL//|/\"}"
			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 '$(PROTPATH "$1")'"
	fi

	if [ -f "$(PROTPATH "$1")" ]; then
		USEPROTON="$1"
		setNewProtVars "$(PROTPATH "$USEPROTON")"
	fi
}

function prepareProtonDBRating {
	if [ "$USEPDBRATING" ]; then
		PDBRAINFO="$STLSHM/PTB-${AID}.txt"
		PDBRASINF="${PDBRAINFO//-/short-}"

		if [ ! -f "$PDBRAINFO" ];then
			getProtonDBRating
			
			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
	
	if [ ! -x "$(command -v "$("$WHICH" "$JQ" 2>/dev/null)" 2>/dev/null)" ]; then
		writelog "WARN" "${FUNCNAME[0]} - Can't get data from '${PDBAPI//XXX/$AID}' because '$JQ' is not installed" "E"
	else
		PDBAPI="https://www.protondb.com/api/v1/reports/summaries/XXX.json"
		DMIN=1440

		if [ -n "$PDBRATINGCACHE" ] && [ "$PDBRATINGCACHE" -ge 1 ]; then
			PDBDLDIR="$STLDLDIR/proton/rating"
			mkProjDir "$PDBDLDIR" 1
			PDBAJ="$PDBDLDIR/${AID}.json"
			if [ ! -f "$PDBAJ" ] || test "$(find "$PDBAJ" -mmin +"$(( DMIN * PDBRATINGCACHE ))")"; then
				rm "$PDBAJ" 2>/dev/null
				"$WGET" -q "${PDBAPI//XXX/$AID}" -O "$PDBAJ"
			fi

			if [ -f "$PDBAJ" ]; then
				"$JQ" -r '. | "\(.confidence);\(.score);\(.total);\(.trendingTier);\(.bestReportedTier)"' "$PDBAJ"
			fi
		else
			"$WGET" -q "${PDBAPI//XXX/$AID}" -O - | "$JQ" -r '. | "\(.confidence);\(.score);\(.total);\(.trendingTier);\(.bestReportedTier)"'
		fi
	fi
}

function fixProtonVersionMismatch {
	ORGUSEPROTON="$USEPROTON"
	MIMAPROT="$1"
	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 "$(PROTPATH "${NEWMINORPROT//\"/}")" ] && [ -n "${NEWMINORPROT//\"/}" ]; then
		NEWMINORRUN="$(PROTPATH "${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 "$(PROTPATH "${NEWMINORPROT//\"/}")" ]; then
			NEWMINORRUN="$(PROTPATH "${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 "$2" ]; 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
}

function checkProtonBump {

	if [ -z "$1" ]; then
		writelog "SKIP" "${FUNCNAME[0]} - Need Proton version as argument 1" "E"
	else
		CURPROTON="$1"

		if [ "$PROTONCHECK" == "disabled" ]; then
			writelog "INFO" "${FUNCNAME[0]} - PROTONCHECK is '$PROTONCHECK' - nothing to do"
		else
			if [ "$OVERRIDEPROTON" -eq 0 ]; then
				writelog "INFO" "${FUNCNAME[0]} - OVERRIDEPROTON is $OVERRIDEPROTON - so currently set '$USEPROTON' isn't used anyway - nothing to do"
			else		
				if [ -z "${ProtonDLList[0]}" ]; then
					createDLProtList
				fi

				if [ -z "${ProtonDLDispList[0]}" ]; then
					writelog "SKIP" "${FUNCNAME[0]} - ProtonDLList is empty, so createDLProtList failed here!"
				else
					writelog "INFO" "${FUNCNAME[0]} - Searching in created Proton Download List for possible updates"

					if grep -q -Eo '[0-9]$' <<< "$CURPROTON"; then
						NEWESTPROTR1="$(grep "^${CURPROTON%-*}" <<< "$(printf "%s\n" "${ProtonDLDispList[@]//\"/}")" | sort -Vr | head -n1)"
					else
						MINV="$(grep -Eo "[0-9]*" <<< "$CURPROTON" | tail -n1)"
						SEARCHPAT="${CURPROTON//$MINV/[0-9]}"
						NEWESTPROTR1="$(grep "^$SEARCHPAT" <<< "$(printf "%s\n" "${ProtonDLDispList[@]//\"/}")" | sort -Vr | head -n1)"
					fi
				
					NEWESTPROTR2="${NEWESTPROTR1//.tar.gz/}"
					NEWESTPROT="${NEWESTPROTR2//.zip/}"

					if [ "$(printf '%s\n' "$NEWESTPROT" "$CURPROTON" | sort -V | head -n1)" != "$NEWESTPROT" ]; then 
						writelog "INFO" "${FUNCNAME[0]} - Found an update for '$CURPROTON' to version '$NEWESTPROT'"
					
						notiShow "$(strFix "$NOTY_NEWPROTON" "$NEWESTPROT" "$CURPROTON")"
					
						writelog "INFO" "${FUNCNAME[0]} - PROTONCHECK is currently set to '$PROTONCHECK'"
					
						if [ "$PROTONCHECK" == "ask_before_menu" ] || [ "$PROTONCHECK" == "ask_before_game" ]; then
							dlCustomProtonAsk "$NEWESTPROT"
						elif [ "$PROTONCHECK" == "auto_download" ]; then
							dlNewCustomProt "$NEWESTPROT"
						elif [ "$PROTONCHECK" == "auto_download_and_use" ]; then
							dlUpCustomProton "$NEWESTPROT"
						elif [ "$PROTONCHECK" == "only_notify" ]; then
							writelog "INFO" "${FUNCNAME[0]} - Only opening a notifier about the new version"
						fi
					fi
				fi
			fi
		fi
	fi
}

function OneTimeProton {
	if [ -n "$WANTPROTON" ] &&  [ -n "$USEPROTON" ]; then
		if [ "$HAVEINPROTON" -eq 1 ]; then
			writelog "SKIP" "${FUNCNAME[0]} - Skipping OneTimeProton, because Steam Launch Option is used"
		else
			if [ "$WANTPROTON" != "$USEPROTON" ]; then
				if [ -z "$USEPROTON" ]; then
					DISPPROT="$NON"
				else
					DISPPROT="$USEPROTON"
				fi
				writelog "INFO" "${FUNCNAME[0]} - One time Proton version '$WANTPROTON' selected, but '$DISPPROT' is set"
				notiShow "$(strFix "$NOTY_WANTPROTON" "$WANTPROTON" "$DISPPROT")"
				writelog "INFO" "${FUNCNAME[0]} - Enabling proton override"
				OVERRIDEPROTON=1
			
				if [ -f "$(PROTPATH "$WANTPROTON")" ]; then
					writelog "INFO" "${FUNCNAME[0]} -  One time Proton version '$WANTPROTON' does exist - switching"
					switchProton "$WANTPROTON"
				else
					fixProtonVersionMismatch "$WANTPROTON"
				fi
			fi
		fi
	fi
}

function dlConty {
	mkProjDir "$CONTYDLDIR" 1
	CONTYDLVERS="$("$WGET" -q "$CONTYRELURL" -O - | grep -m1 "download.*.$CONTY" | grep -oP 'releases\K[^"]+')"

	if grep -q "$CONTY" <<< "$CONTYDLVERS"; then
		writelog "INFO" "${FUNCNAME[0]} - Downloading '$CONTYRELURL/$CONTYDLVERS' to '$CONTYDLDIR'"
		notiShow "$(strFix "$NOTY_DLCONTY" "$CONTYRELURL/$CONTYDLVERS")"
		wgetGui "$CONTYRELURL/$CONTYDLVERS" "$CONTYDLDIR/$CONTY"
		if [ -f "$CONTYDLDIR/$CONTY" ]; then
			DLSHA="$(sha256sum "$CONTYDLDIR/$CONTY" | cut -d ' ' -f1)"
			if "$WGET" -q "$CONTYRELURL" -O - | grep -q "$DLSHA"; then
				writelog "INFO" "${FUNCNAME[0]} - The sha256 checksum of the downloaded file is correct: '$DLSHA' - continuing"
				chmod +x "$CONTYDLDIR/$CONTY"
				export RUNCONTY="$CONTYDLDIR/$CONTY"
				CONTYVERS="$(cut -d '/' -f3 <<< "$CONTYDLVERS")";
				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]} - The sha256 checksum of the downloaded file is wrong: '$DLSHA' - removing the download"
				rm "$CONTYDLDIR/$CONTY"
			fi
		fi
		writelog "INFO" "${FUNCNAME[0]} - Setting RUNCONTY to '$CONTYDLDIR/$CONTY'"
		export RUNCONTY="$CONTYDLDIR/$CONTY'"
	else
		writelog "SKIP" "${FUNCNAME[0]} - Failed to download Conty - skipping"
		export RUNCONTY="$NON"
	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"
			dlConty
		else
			LATESTCONTY="$("$WGET" -q "$CONTYRELURL" -O - | grep -m1 "download.*.$CONTY" | grep -oP 'releases\K[^"]+' | cut -d '/' -f3)"
			DLVERS="$(cat "$CONTYDLDIR/version.txt")"
			if [ "$(printf '%s\n' "$DLVERS" "$LATESTCONTY" | sort -V | head -n1)" != "$LATESTCONTY" ]; then 
				writelog "INFO" "${FUNCNAME[0]} - $(strFix "$NOTY_UPDATECONTY" "$LATESTCONTY" "$DLVERS")"
				notiShow "$(strFix "$NOTY_UPDATECONTY" "$LATESTCONTY" "$DLVERS")"
				dlConty
			else
				writelog "INFO" "${FUNCNAME[0]} - Conty already at newest version '$DLVERS'"
			fi
		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"
					dlConty
				}
			;;
			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 "$("$WHICH" "$CONTY" 2>/dev/null)" 2>/dev/null)" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Using Conty in 'PATH' '$("$WHICH" "$CONTY")'"
		RUNCONTY="$("$WHICH" "$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" 1
		# 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' '!')"	
	export HUYLIST
}

function checkHelpUrl {
	WANTHELPURL="$1"
	if  [ -n "$WANTHELPURL" ] && [ "$WANTHELPURL" != "$NON" ] && [ ! -f "$STLSHM/KillBrowser-$AID.txt" ]; then
		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'"

		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}" & 
		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 "${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 "${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 #XXXXXXXXX
					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 startGame {
	#kind of works, but should be optimized:
#	emptyVars "S"  # unset some internal variables before the game starts

	loadCfg "$GEMETA/$AID.conf"
	writelog "INFO" "${FUNCNAME[0]} - Getting the Game Window name:"
	getGameWindowName &
	touch "$PIDLOCK"
	startSBSVR &

	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 [ "$HAVESLR" -eq 1 ] && [ "$USESLR" -eq 1 ]; then
		writelog "INFO" "${FUNCNAME[0]} - ## SLR is enabled via USESLR=$USESLR - prepending to the current launch command"
		RUNCMD=("${RUNSLR[@]}" "${RUNCMD[@]}")
	else
		if [ "$HAVESLR" -eq 1 ]; then
			writelog "SKIP" "${FUNCNAME[0]} - USESLR is disabled, so skipping '$SLR' found in the commandline: '${RUNSLR[*]}'"
		else
			writelog "SKIP" "${FUNCNAME[0]} - No SLR was provided via command line, so configuration USESLR '$USESLR' is ignored"
		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[@]}")
	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 $PROGCMD 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 $PROGCMD 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';HAVEINPROTON='$HAVEINPROTON'"
			echo "$(date) - $GN ($AID) - REAPCMD '${REAPCMD[*]}'"
			echo "$(date) - $GN ($AID) - RUNSLR '${RUNSLR[*]}'"
			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';OVERRIDEPROTON='$OVERRIDEPROTON'"
			echo "$(date) - $GN ($AID) - FINAL LAUNCH RUNCMD '${RUNCMD[*]}'"
			echo "$(date) - $GN ($AID) - ======================"
		} >> "/tmp/$PROGCMD-startmode-DEBUG-XXXXXXXXX"
	fi
	
	if [ "$HAVESCTP" -eq 1 ]; 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'"
	fi

	SECONDS=0

	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
	emptyVars "O" "X" # clear original variables again (mostly for a continous log (date))

	if [ "$ISGAME" -eq 2 ] && [ "$USEWINE" -eq 0 ] && { grep -q "\-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)"
		writelog "INFO" "${FUNCNAME[0]} - Proton '$USEPROTON' forks its command into background, so waited for the wineserver RUNWINESERVER '$RLRUNWINESERVER' with pid '$WSPID' to finish instead"
#		writelog "INFO" "${FUNCNAME[0]} - Waited for the wineserver RUNWINESERVER '$RLRUNWINESERVER' with pid '$WSPID' to finish"
		tail --pid="$WSPID" -f /dev/null
		writelog "INFO" "${FUNCNAME[0]} - wineserver process '$WSPID' finished - closing"
	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
	mapfile -d " " -t -O "${#GAMEARGSARR[@]}" GAMEARGSARR < <(printf '%s' "$ARGSTRING")
}

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 -  | 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 "${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"
			dlWine "${DLURL//|/\"}"
		else
			DLWINEVERSION="${DLDISPWINE//|/}"
			DLURL="$(printf "%s\n" "${WineDLList[@]}" | grep -m1 "${DLDISPWINE//|}")"
			writelog "INFO" "${FUNCNAME[0]} - '${DLDISPWINE//|}' was selected - downloading '$DLURL'"
			dlWine "${DLURL//|/\"}"
		fi
	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'" "E"
		notiShow "$(strFix "$NOTY_DLCUSTOMPROTON" "$WURL")"
		wgetGui "$WURL" "$DSTDL"
		notiShow "$(strFix "$NOTY_DLCUSTOMPROTON2" "$WURL")"
	else
		writelog "INFO" "${FUNCNAME[0]} - File '$DSTDL' already exists - nothing to download" "E"
		notiShow "$(strFix "$NOTY_DLCUSTOMPROTON4" "${WURL##*/}")"
	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"
			dlWine "$@"
		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" "E"
		else
			writelog "INFO" "${FUNCNAME[0]} - Extracting archive '$WURLFILE' to '$WINEEXTDIR'"
			notiShow "$(strFix "$NOTY_DLCUSTOMPROTON3" "$1")"
			"$TAR" xf "$1" -C "$WINEEXTDIR" 2>/dev/null
		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 "${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" == "$("$WHICH" echo 2>/dev/null)" ] || [ "$WINEVERSION" == "$NON" ]; then
			writelog "INFO" "${FUNCNAME[0]} - No current wine version configured yet"
			if [ "$WINEDEFAULT" != "$("$WHICH" echo 2>/dev/null)" ] && [ "$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'"
				dlWine "${DLURL//|/\"}"
				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" == "$("$WHICH" echo 2>/dev/null)" ]; 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" != "$("$WHICH" echo 2>/dev/null)" ]; 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="$("$WHICH" "$GAMEMODERUN" 2>/dev/null)"
	fi

	if [ "$USEGAMESCOPE" -eq 1 ]; then
		GSC="$("$WHICH" "$GAMESCOPE" 2>/dev/null)"
	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:
		if [ "$GAMEARGS" != "$NON" ]; then
			gameArgs "$GAMEARGS"
#			mapfile -t -O "${#RUNGAMEARGS[@]}" RUNGAMEARGS <<< "$GAMEARGS"
		fi

		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
				# 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' manual-download $AID"
					notiShow "$(strFix "$NOTY_LUXTORPEDA1" "$GN" "$AID")"
					"$LUXTORPEDACMD" manual-download "$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:
			OneTimeProton
		
			if [ "$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
					else
						writelog "INFO" "${FUNCNAME[0]} - Asking for one"
						needNewProton
					fi
				fi

				# the last chance to set the Proton version before starting the game,
				setRunProtonFromUseProton

				# 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"
					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
			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[@]}"
			# 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'" "E"
				mkdir -p "$STEAMCOMPATOOLS" 2>/dev/null
			fi

			if [ ! -d "$SCTS" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Creating dir '$SCTS'" "E"
				mkdir -p "$SCTS" 2>/dev/null

				CVDF="$SCTS/$CTVDF"
				writelog "INFO" "${FUNCNAME[0]} - Creating file '$CVDF'" "E"
				{
				echo "\"compatibilitytools\""
				echo "{"
				echo "  \"compat_tools\""
				echo "  {"
				echo "	\"Proton-$PROGCMD\" // 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'" "E"
				{
				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" "E"
				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!" "E"
		fi
	elif [ "$1" == "del" ]; then
		if [ ! -d "$SCTS" ]; then
			writelog "SKIP" "${FUNCNAME[0]} - Selected '$1' but '$SCTS' doesn't exist" "E"
		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="$(PROTPATH "$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
	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 Steam Launch Options ('$PROGCMD %command%'),"
					writelog "INFO" "${FUNCNAME[0]} - because a Proton path was found in the command line provided by steam"
#					if [ "$OVERRIDEPROTON" -eq 0 ]; then
						writelog "INFO" "${FUNCNAME[0]} - Override Proton is disabled, when using stl as Steam Launch Option, 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]} - Override it, because override proton is enabled"
#						setRunProtonFromUseProton
#					fi
				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 'stl %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) $PROGCMD 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>           Create raw appinfo for <id> or 'all'"
	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 "    dlcustomproton|dcp <url|l>       Download/install custom Proton"
	echo "                                       - from filerequester"
	echo "                                       - directly from <url>"
	echo "                                       - the 'latest|l' version"
	echo "    dlwine|dw <url>                  Download/install Wine archive"
	echo "                                       from filerequester 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 "    (get commands only for games known by $PROGCMD:)"
	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 "    meta                             Generates/Updates metadata"
	echo "                                       for all installed games"
 	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 "    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 "           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 <gamedir>       open shader selection for <gamedir>"
	echo "                                       or for last gamedir"
	echo "           reshade <version>           (re)-download ReShade (version)"
	echo "    version                          Output the program version"
	echo "    vortex <value>                   Vortex commandline options"
	echo "           install                     Installs vortex"
	echo "           supported <X>                List all Vortex-supported Steam Game IDs"
	echo "                                       (offline - Vortex needs to be installed)"
	echo "                                       Show installed Games with Vortex support"
	echo "                                       with parameter 'X'"
	echo "           games                       Gui to en/disable Vortex for supported game"
	echo "           symlinks                    Gui showing Vortex symlinks"
	echo "           start                       Starts vortex"
	echo "           getset                      Show config of installed vortex"
	echo "           stage <path>                Add vortex 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>                 Configure the used Yad binary"
	echo "                                       <yad binary> can be either"
	echo "                                       <absolute/path>"
	echo "                                       <conty>"
	echo "                                       <ai> or <appimage>"
	echo "                                       (see Wiki for details)"
}

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" E
				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" == "createcompatdata" ] || [ "$1" == "ccd" ]; then
		FUSEID "$2"
		writelog "INFO" "${FUNCNAME[0]} - Starting Install via command: reCreateCompatdata \"$1\" \"$USEID\" \"$3\"" "E"
		reCreateCompatdata "$1" "$USEID" "$3"
	elif  [ "$1" == "createdesktopicon" ] || [ "$1" == "cdi" ]; then
		if [ "$2" == "all" ]; then
			while read -r CATAID; do
				"$0" cdi "$CATAID" "$3"
			done <<< "$(listInstalledGameIDs)"
		else
			FUSEID "$2"
			createDesktopIconFile "$USEID" "$3"
		fi
	elif  [ "$1" == "createappinfo" ] || [ "$1" == "cai" ]; then
		if [ "$2" == "all" ]; then
			while read -r CATAID; do
				"$0" cai "$CATAID"
			done <<< "$(listInstalledGameIDs)"
		else
			FUSEID "$2"
			getRawAppIDInfo "$USEID"
		fi
	elif  [ "$1" == "createfirstinstall" ] || [ "$1" == "cfi" ]; then
		FUSEID "$2"
		CreateCustomEvaluatorScript "$USEID"
	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" == "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" == "gamescope" ] || [ "$1" == "gs" ]; then
		FUSEID "$2"
		GameScopeGui "$USEID"	
	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"
	elif  [ "$1" == "launcher" ]; then
		openGameLauncher "$2" "$3"
	elif  [ "$1" == "list" ]; then
		if [ "$2" == "owned" ]; then
			getAllOwnedGames
		fi
	elif  [ "$1" == "meta" ]; then
		createMetaData "yes"
	elif  [ "$1" == "mo2" ]; then
		if [ -n "$2" ]; then
			#if [ "$2" == "install" ]; then
			#	installMO2Set
			
			if [ "$2" == "download" ]; then
				dlLatestMO2
			else	
				writelog "INFO" "${FUNCNAME[0]} - arg2 '$2' is no valid command" E
				howto
			fi
		else
			echo "need arg2"
			howto
		fi
	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" == "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
							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
							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" == "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
					getGridsForInstalledGames
				else
					getGrid "$3"
				fi
			elif [ "$2" == "allgamedata" ]; then
				getDataForAllGamesinSharedConfig
			elif [ "$2" == "shader" ] || [ "$2" == "shaders" ]; then
				dlShaders "$3"
			elif [ "$2" == "gameshaders" ]; then
				if [ -z "$3" ]; then
					writelog "INFO" "${FUNCNAME[0]} - No game directory in argument 3 provided - using last game!" "E"
					GameShaderDialog
				else
					if [ -d "$3" ]; then
						GameShaderDialog "$3"
					else
						writelog "SKIP" "${FUNCNAME[0]} - Game directory '$3' does not exist - exit" "E"
					fi
				fi
			elif [ "$2" == "reshade" ]; then
				dlReShade "$3"
			else
				howto
			fi
		else
			howto
		fi
	elif  [ "$1" == "version" ]; then
		echo "${PROGCMD}-${PROGVERS}"
	elif  [ "$1" == "$VTX" ]; then
		if [ -n "$2" ]; then
			if [ "$2" == "install" ]; then
				if [ -n "$3" ] && [ "$3" == "gui" ]; then
					installVortexGui
				else
					installVortex X
				fi
			elif [ "$2" == "start" ]; then
				USEVORTEX="1"
				startVortex
			elif [ "$2" == "getset" ]; then
				USEVORTEX="1"
				startVortex "$2"
			elif [ "$2" == "gui" ]; then
				VortexOptions
			elif [ "$2" == "stage" ]; then
				addVortexStage "$3"
			elif [ "$2" == "supported" ]; then
				if [ -n "$3" ]; then
					writelog "INFO" "${FUNCNAME[0]} - Installed Games With Vortex Support" E
					getInstalledGamesWithVortexSupport X
				else
					writelog "INFO" "${FUNCNAME[0]} - Games With Vortex Support" E
					getVortexSupported X
				fi
			elif [ "$2" == "games" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Opening Gui for en/disabling Vortex for installed and supported games" E
				VortexGamesDialog
			elif [ "$2" == "symlinks" ]; then
				writelog "INFO" "${FUNCNAME[0]} - Opening Gui showing Symlinks in the Vortex WINEPREFIX" E
				VortexSymDialog
			elif [ "$2" == "download" ]; then
				dlLatestVortex
			else	
				writelog "INFO" "${FUNCNAME[0]} - arg2 '$2' is no valid command" E
				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"
		else
			writelog "INFO" "${FUNCNAME[0]} ------------------------" E
			writelog "INFO" "${FUNCNAME[0]} - arg2 '$2' needs to be a valid yad parameter" E
			howto
		fi
	else
		if ! grep -q "lang=\|run" <<< "$@" ; then
			writelog "INFO" "${FUNCNAME[0]} ------------------------" E
			writelog "INFO" "${FUNCNAME[0]} - arg1 '$1' is no valid command" E
			howto
		fi
	fi
}

### 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)'"

	mkProjDir "$GEMETA" 1
	mkProjDir "$CUMETA" 1
	mkProjDir "$TIGEMETA" 1
	mkProjDir "$TICUMETA" 1

	if [ ! -f "$GEMETA/$MAID.conf" ]; then
		if [ "$SGDBAUTODL" == "no_meta" ] ; then
			writelog "INFO" "${FUNCNAME[0]} - Automatic Grid Update Check '$SGDBAUTODL'"
			getGrid "$MAID"
		fi
		touch "$GEMETA/$MAID.conf"
	fi
	
	loadCfg "$GEMETA/$MAID.conf" X
	updateConfigEntry "GAMEID" "$MAID" "$GEMETA/$MAID.conf"
	updateConfigEntry "GAMENAME" "$MGNA" "$GEMETA/$MAID.conf"

	if [ -n "$GE" ]; 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
	updateConfigEntry "WINEPREFIX" "$MPFX" "$CUMETA/$MAID.conf"
	updateConfigEntry "GAMEDIR" "$GDIR" "$CUMETA/$MAID.conf"

	createSymLink "${FUNCNAME[0]}" "$GEMETA/$MAID.conf" "$TIGEMETA/${MGNA}.conf" X
	createSymLink "${FUNCNAME[0]}" "$CUMETA/$MAID.conf" "$TICUMETA/${MGNA}.conf" X
	createSymLink "${FUNCNAME[0]}" "$EVMETAID/${EVALSC}_${MAID}.vdf" "$EVMETATITLE/${EVALSC}_${MGNA}.vdf"
}

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'" "E"
		notiShow "$(strFix "$NOTY_STARTRESTORE" "$BACKUPSRC" "$AID")"
		mkProjDir "$SteamUserDir" 1
		"$RSYNC" -am "$BACKUPSRC" "$SteamUserDir" 
		notiShow "$(strFix "$NOTY_STOPRESTORE" "$SteamUserDir")"
	}
	
	function startRestoreBecause {
		writelog "INFO" "${FUNCNAME[0]} - Restoring, because '$RSTUS' is set" "E"
		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" "E"
		RSTUS="$1"
	else
		writelog "INFO" "${FUNCNAME[0]} - Using configured value '$RESTORESTEAMUSER' for RESTORESTEAMUSER" "E"
		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" "E"
	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'" "E"
					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'" "E"
					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'" "E"
			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" "E"
		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" 1
			mkProjDir "$SUBADIRTI" 1
			SteamUserDir="$GPFX/$DRCU/$STUS"
			
			if [ -d "$SteamUserDir" ]; then
				writelog "INFO" "${FUNCNAME[0]} - backing up directory '$SteamUserDir' to '$SUBADIRID/$BAID'" "E"
				if [ -z "$2" ]; then
					notiShow "$(strFix "$NOTY_STARTBACKUP" "$BACKTI" "$BAID")"
				fi
				mkProjDir "$BACKEX" 1
				
				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" "E"

		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'" #"E"
				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" "E"
		rm "$LASTMETAUP"
	fi
	
	if [ ! -f "$LASTMETAUP" ] || test "$(find "$LASTMETAUP" -mmin +"$MAXMETAAGE")"; then
		writelog "INFO" "${FUNCNAME[0]} - Creating/Updating metadata for all installed games found" "E"

		while read -r APPMA; do
			AMF="${APPMA##*/}"
			MAID="$(cut -d'_' -f2 <<< "$AMF" | cut -d'.' -f1)"

			GNRAW="$(grep "\"name\"" "$APPMA" | gawk -F '"name"' '{print $NF}')"
			GNAM="$(gawk '{$1=$1};1' <<< "$GNRAW")"

			GIRAW="$(grep "\"installdir\"" "$APPMA" | gawk -F '"installdir"' '{print $NF}')"
			GINS="$(gawk '{$1=$1};1' <<< "${GIRAW//\"/}")"
			GDIR="$(dirname "$APPMA")/common/$GINS"
			MPFX="$(dirname "$APPMA")/$CODA/$MAID/pfx"

			storeMetaData "$MAID" "$GNAM" "$MPFX" "$GDIR"
		done <  <(listAppManifests)
		writelog "INFO" "${FUNCNAME[0]} - Done with Creating/Updating metadata" "E"
		date +%y-%m-%d > "$LASTMETAUP"
	fi
}


function getLatestX64dbgSnap {
	basename "$("$WGET" -q "$X64DBGURL" -O - |  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" 1
		X64ZIP="$(getLatestX64dbgSnap)"

		if [ ! -f "$DLDST/$X64ZIP" ]; then
			notiShow "$(strFix "$NOTY_DLCUSTOMPROTON" "$X64ZIP")"
			# "$WGET" -q "${X64DBGURL//tag/download}/$X64ZIP" -O "$DLDST/$X64ZIP"
			wgetGui "${X64DBGURL//tag/download}/$X64ZIP" "$DLDST/$X64ZIP"
			notiShow "$(strFix "$NOTY_DLCUSTOMPROTON2" "$X64ZIP")"
		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")"
			writelog "INFO" "${FUNCNAME[0]} - Download of '$X64ZIP' to '$DLDST' was successful"
			"$UNZIP" -q "$DLDST/$X64ZIP" -d "$DLDST" 2>/dev/null
			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"
			dlX64Dbg
		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 "$GLOBALREGDIR/${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 startSettings {
	FUSEID "$1"
	createProtonList X
	openTrayIcon
	MainMenu "$USEID"
	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" E
				if [ -n "$SCATSELOUT" ]; then
					writelog "INFO" "${FUNCNAME[0]} - Selected following Categories2: '$(sort -u <<< "$SCATSELOUT" | sed '/^$/d' | tr '\n' ',')'" E
					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" E

	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" E
		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" E
			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" E
		fi
	}
}

function addNonSteamGameGui {
	checkDep "HAVEOSSL" "$OSSL"

	if [ -z "$HAVEOSSL" ]; then
		writelog "INFO" "${FUNCNAME[0]} - '$OSSL' could not be found, can't generate a random AppID without it" E
	else
		writelog "INFO" "${FUNCNAME[0]} - Starting the Gui for adding a $NSGA to Steam" "E"

		# 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 "${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'" E
			;;
			2)  writelog "INFO" "${FUNCNAME[0]} - Selected '$BUT_TAGS" E
				SteamCatSelect "$NON" "${FUNCNAME[0]}"
			;;
			4)  writelog "INFO" "${FUNCNAME[0]} - Selected '$BUT_CREATE'" E
				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\"" E
					addNonSteamGame	-an="$NOSTGAPPNAME" -ep="$NOSTGEXEPATH" -sd="$NOSTGSTDIR" -ip="$NOSTGICONPATH" -lo="$NOSTGLAOP" -hd="$NOSTGHIDE" -adc="$NOSTGADC" -ao="$NOSTGAO" -vr="$NOSTGVR" -t="$NOSTTAGS"
				fi
			;;
		esac
	fi
}

function addNonSteamGame {
	checkDep "HAVEOSSL" "$OSSL"

	if [ -z "$HAVEOSSL" ]; then
		writelog "INFO" "${FUNCNAME[0]} - '$OSSL' could not be found, can't generate a random AppID without it" E
	else
		if [ -z "$SUSDA" ]; then
			setSteamPaths
		fi
		STEAMUSERID="$(find "$SUSDA" -maxdepth 1 -type d -name "[1-9]*")"
		SCPATH="$STEAMUSERID/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="$("$OSSL" rand -hex 4)"
			NOSTAID="$(hex2dec "$NOSTAIDRHX")"
			NOSTAIDHX="\x$(gawk '{$1=$1}1' FPAT='.{2}' OFS="\\\x" <<< "$NOSTAIDRHX")"

			writelog "INFO" "${FUNCNAME[0]} - === Adding new $NSGA ===" E
			writelog "INFO" "${FUNCNAME[0]} - AppID: '${NOSTAID}'" E
			writelog "INFO" "${FUNCNAME[0]} - App Name: '${NOSTAPPNAME}'" E
			writelog "INFO" "${FUNCNAME[0]} - Exe Path: '${NOSTEXEPATH}'" E
			writelog "INFO" "${FUNCNAME[0]} - Start Dir: '${NOSTSTDIR}'" E
			writelog "INFO" "${FUNCNAME[0]} - Icon Path: '${NOSTICONPATH}'" E
			writelog "INFO" "${FUNCNAME[0]} - Launch options: '${NOSTLAOP}'" E
			writelog "INFO" "${FUNCNAME[0]} - Is Hidden: '${NOSTHIDE}'" E
			writelog "INFO" "${FUNCNAME[0]} - Allow Desktop Config: '${NOSTADC}'" E
			writelog "INFO" "${FUNCNAME[0]} - Allow Overlay: '${NOSTAO}'" E
			writelog "INFO" "${FUNCNAME[0]} - OpenVR: '${NOSTVR}'" E
			writelog "INFO" "${FUNCNAME[0]} - Tags: '${NOSTTAGS}'" E

			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
	fi
}

#STARTCLOSESTL ###
function closeSTL {
	writelog "INFO" "${FUNCNAME[0]} - closing STL"

	# 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

	cleanSUTemp
	backupSteamUser "$AID"

	if [ "$SGDBAUTODL" == "after_game" ] ; then
		writelog "INFO" "${FUNCNAME[0]} - Automatic Grid Update Check '$SGDBAUTODL'"
		getGrid "$AID"
	fi

	if [ "$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_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
			gawk -i inplace '!visited[$0]++' "$NETMONDIR/$AID-$NETMON.log"
		fi
	fi

	togWindows windowraise	# TOGGLEWINDOWS

	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
	
	# only useful for win games:
	if [ "$ISGAME" -eq 2 ] && [ "$USEWINE" -eq 0 ]; then
		writeLastRun
		storeMetaData "$AID" "$GN" "$GPFX" "$EFD"
	fi

	delMenuTemps
	delWinetricksTemps
	
#	emptyVars "A" "$1"
}
#ENDCLOSESTL ###

# main:#################

function saveOrgVars {
	# Storing some original Variables to restore them later

	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="" 
		setSTLPath
		LD_LIBRARY_PATH=""
		LD_PRELOAD=""

#	# empty "some" internal variables created by $PROGCMD (before starting the game)
	elif [ "$1" == "S" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Clearing some '$PROGCMD' 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 | gawk -F 'export ' '{print $2}' > "$TIEXV"
		fi

		if [ ! -f "$TIEXF" ]; then
			sed -n "/^#STARTIEX/,/^#ENDIEX/p;/^#ENDIEX/q" "$0" | grep "export \-f" | gawk -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 $PROGCMD - 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\" | gawk '/$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'" "E"
	}

	mkProjDir "$EVMETACUSTOMID" 1
	mkProjDir "$EVMETAADDONID" 1
	
	writelog "INFO" "${FUNCNAME[0]} - Starting Gui for Creating a custom '$EVALSC'" "E"
	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'" "E"
	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'" "E"
				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'" "E"
				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" "E"
				createTempEvals
				writelog "INFO" "${FUNCNAME[0]} - Starting Install via command: reCreateCompatdata \"$EUNID\" \"${FUNCNAME[0]}\" \"$TEVALSC\"" "E"
				reCreateCompatdata "$EUNID" "${FUNCNAME[0]}" "$TEVALSC"
			}
		;;
		8)	{
				writelog "INFO" "${FUNCNAME[0]} - Selected CANCEL" "E"
			}
		;;
	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 --silent -- "$FRSTATE" "$PRFRSTATE"; then
				cp "$FRSTATE" "$PRFRSTATE"
				notiShow "$(strFix "$NOTY_FRSTATE" "$(cat "$FRSTATE")")" "X"
				writelog "INFO" "${FUNCNAME[0]} - $(strFix "$NOTY_FRSTATE" "$(cat "$FRSTATE")")" "E"
			fi
		fi
	}

	WANTGUI=0
	if [ "$1" == "ccd" ] || [ "$1" == "createcompatdata" ]; then
		writelog "INFO" "${FUNCNAME[0]} - Started from command-line" "E"
		EUNID="$2"
		if [ -n "$3" ]; then
			WANTGUI=1
		fi
	else
		writelog "INFO" "${FUNCNAME[0]} - Started from gui" "E"
		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" == "$VTX" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Starting Vortex Set Installation" "E"
			SRCORIGEVSC="${GLOBALEVALDIR}/sets/${EVALSC}_${VTX}.vdf"
			SRCEVSC="$SRCORIGEVSC"
			DESTCODA="$VORTEXCOMPDATA"
			EARLYPROT="$VORTEXPROTON"
			export STEAM_COMPAT_APP_ID="$VTX"
			STEAM_COMPAT_INSTALL_PATH="$VORTEXCOMPDATA"
		fi
		
		if [ ! -f "$ISCEXE" ]; then
			writelog "ERROR" "${FUNCNAME[0]} - '$ISCEXE' not found" "E"
		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)" "E"
					writelog "ERROR" "${FUNCNAME[0]} - Alternatively start the same command with an additional 'gui' parameter, to create a '$SRCCUSTEVSC' via gui" "E"
					HAVEEVSC=0
				else
					writelog "INFO" "${FUNCNAME[0]} - Requester to create a custom Install file via Gui" "E"
					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'" "E"
					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 compatdata is '$STEAM_COMPAT_DATA_PATH'" "E"

					if [ -z "$STEAM_COMPAT_INSTALL_PATH" ]; then
						if [ -n "$GAMEDIR" ]; then
							export STEAM_COMPAT_INSTALL_PATH="$GAMEDIR"
						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}'" "E"
							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}_${PROGCMD}")")"
							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}_${PROGCMD}" ]; then
								writelog "INFO" "${FUNCNAME[0]} - Removing previous backup compatdata backup '${DESTCODA}_${PROGCMD}'" "E"
								rm -rf "${DESTCODA}_${PROGCMD}" 2>/dev/null
							fi
							
							find "$DESTCODA" -maxdepth 0 -empty -exec rmdir {} \;

							if [ -d "$DESTCODA" ]; then
								writelog "INFO" "${FUNCNAME[0]} - Moving existing compatdata to '${DESTCODA}_${PROGCMD}'" "E"
								mv "$DESTCODA" "${DESTCODA}_${PROGCMD}"
							fi
						fi
					fi

					if [ "$RECRECODA" -eq 1 ]; then
						if [ -z "$STEAM_COMPAT_APP_ID" ]; then
							export STEAM_COMPAT_APP_ID="${EUNID}"
						fi

						mkdir -p "$DESTCODA" 2>/dev/null
						EVALISRUN="$STLSHM/evalisrun.txt"
						
						cd "$STEAM_COMPAT_CLIENT_INSTALL_PATH" >/dev/null || return
						
						writelog "INFO" "${FUNCNAME[0]} - Launching First Run Installer" "E"

						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 compatdata determined" "E"
				fi
			fi

			if [ -n "$BACKFUNC" ]; then
				"$BACKFUNC" "$AID" "${FUNCNAME[0]}"
			fi
		fi
	else
		writelog "SKIP" "${FUNCNAME[0]} - Need SteamAppId as argument" "E"
	fi
}

function autoEvalscPushVersion {
	# Vortex autoupdate
	if grep -q VORTEXVERS "$1"; then
		if [ ! -f "$VORTEXDLDIR/NOUPDATE" ]; then
			dlLatestVortex
		fi

		VORTEXVERS="$NON"

		if [ -n "$VORTEXSETUP" ]; then
			VORTEXSETUPRAW="$VORTEXSETUP"
			writelog "INFO" "${FUNCNAME[0]} - Already have VORTEXSETUP '$VORTEXSETUPRAW'" "E" | tee -a "$ISCRILOG"
		else
			# ip sort found here: https://www.oreilly.com/library/view/bash-cookbook/0596526784/ch08s03.html
			VORTEXSETUPRAW="$(find "$VORTEXDLDIR" | sort -t . -k 1,1n -k 2,2n -k 3,3n -k 4,4n | tail -n1)"
			writelog "INFO" "${FUNCNAME[0]} - Found newest downloaded VORTEXSETUP '$VORTEXSETUPRAW'" "E" | tee -a "$ISCRILOG"
		fi

		VORTEXVERSW1="${VORTEXSETUPRAW##*-}"
		VORTEXVERS="${VORTEXVERSW1//.exe}"
		writelog "INFO" "${FUNCNAME[0]} - Newest VORTEXVERS '$VORTEXVERS'" "E" | tee -a "$ISCRILOG"

		if [ -n "$VORTEXVERS" ] && [ "$VORTEXVERS" != "$NON" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Replacing 'VORTEXVERS' in '$1' with '$VORTEXVERS'" "E" | tee -a "$ISCRILOG"
			sed "s:VORTEXVERS:$VORTEXVERS:g" -i "$1"
		else
			writelog "ERROR" "${FUNCNAME[0]} - No usable VORTEXVERS 'VORTEXVERS' found" "E" | tee -a "$ISCRILOG"
		fi
	fi

	# Mod Organizer 2 autoupdate
	if grep -q MO2VERS "$1"; then
		if [ ! -f "$MO2DLDIR/NOUPDATE" ]; then
			dlLatestMO2
		fi

		MO2VERS="$NON"

		if [ -n "$MO2SETUP" ]; then
			MO2RAW="$MO2SETUP"
			writelog "INFO" "${FUNCNAME[0]} - Already have MO2SETUP '$MO2RAW'" "E" | tee -a "$ISCRILOG"
		else
			# ip sort found here: https://www.oreilly.com/library/view/bash-cookbook/0596526784/ch08s03.html
			MO2RAW="$(find "$MO2DLDIR" | sort -t . -k 1,1n -k 2,2n -k 3,3n -k 4,4n | tail -n1)"
			writelog "INFO" "${FUNCNAME[0]} - Found newest downloaded MO2SETUP '$MO2RAW'" "E" | tee -a "$ISCRILOG"
		fi

		MO2VERSW1="${MO2RAW##*-}"
		MO2VERS="${MO2VERSW1//.exe}"
		writelog "INFO" "${FUNCNAME[0]} - Newest MO2VERS '$MO2VERS'" "E" | tee -a "$ISCRILOG"

		if [ -n "$MO2VERS" ] && [ "$MO2VERS" != "$NON" ]; then
			writelog "INFO" "${FUNCNAME[0]} - Replacing 'MO2VERS' in '$1' with '$MO2VERS'" "E" | tee -a "$ISCRILOG"
			sed "s:MO2VERS:$MO2VERS:g" -i "$1"
		else
			writelog "ERROR" "${FUNCNAME[0]} - No usable MO2VERS 'MO2VERS' found" "E" | tee -a "$ISCRILOG"
		fi
	fi
}

function createModifiedEvalsc {
	if [ -z "$ISCRILOG" ]; then
		ISCRILOG="$STLSHM/${PROGCMD}-${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" "E" | tee -a "$ISCRILOG"
	fi

	SOURCEEVALSC="$1"
	DSTEVALSC="$2"

	if [ ! -f "$SOURCEEVALSC" ]; then
		writelog "SKIP" "${FUNCNAME[0]} - '$SOURCEEVALSC' does not exists" "E" | tee -a "$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'" "E" | tee -a "$ISCRILOG"
		cp "$SOURCEEVALSC" "$DSTEVALSC"
		
		# replace version placeholders automatically:
		autoEvalscPushVersion "$DSTEVALSC"
		
		# replace placeholders with real paths
		writelog "INFO" "${FUNCNAME[0]} - Replacing placeholders with real paths in '$DSTEVALSC'" "E" | tee -a "$ISCRILOG"
		sed "s:STESHA:$STESHA:g" -i "$DSTEVALSC"
		sed "s:STLDLDIR:$STLDLDIR:g" -i "$DSTEVALSC"
	else
		writelog "SKIP" "${FUNCNAME[0]} - '$DSTEVALSC' already exists" "E" | tee -a "$ISCRILOG"
	fi
}

function cleanupOutdatedEvals {
	writelog "INFO" "${FUNCNAME[0]} - Cleaning up outdated files in '$EVMETAID'"

	mkProjDir "$EVMETAOLD" 1
	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'" "E" | tee -a "$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/${PROGCMD}-${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" 1
		mkProjDir "$EVMETATITLE" 1
		
		ISCRILOG="$2"
		EVALVDF="$SCCILECO/$1"
		writelog "INFO" "${FUNCNAME[0]} - Waiting for '$EVALVDF' to appear" "E" | tee -a "$ISCRILOG"
		while [ ! -f "$EVALVDF" ]; do 
			sleep 0.1
		done
		cp "$EVALVDF" "$EVMETAID"
		writelog "INFO" "${FUNCNAME[0]} - Copied '$EVALVDF' to '$EVMETAID/$1'" "E" | tee -a "$ISCRILOG"
	}
	
	function findEarlyProt {
		if [ -n "$2" ]; then
			ISCRILOG="$2"
			writelog "INFO" "${FUNCNAME[0]} - Trying to get a proton version from '$1'" "E" | tee -a "$ISCRILOG"
			if grep -q "^USEPROTON" "$1"; then
				CONFPROTRAW="$(grep "^USEPROTON" "$1" | cut -d '=' -f2)"
				CONFPROT="${CONFPROTRAW//\"}"
				PROTONCSV="$STLSHM/ProtonCSV.txt"
				if [ -z "$SUSDA" ]; then
					setSteamPaths
				fi
				
				createProtonList
				
				if [ -f "$PROTONCSV" ]; then
					writelog "INFO" "${FUNCNAME[0]} - Searching '$CONFPROT' in '$PROTONCSV'" "E" | tee -a "$ISCRILOG"

					if grep -q "^${CONFPROT}" "$PROTONCSV"; then
						writelog "INFO" "${FUNCNAME[0]} - Found '$CONFPROT' in '$PROTONCSV'" "E" | tee -a "$ISCRILOG"
						EARLYPROT="$(grep "^${CONFPROT}" "$PROTONCSV" | cut -d ';' -f2)"
						export EARLYPROT
					else
						writelog "INFO" "${FUNCNAME[0]} - '$CONFPROT' not found in '$PROTONCSV'" "E" | tee -a "$ISCRILOG"
						# if configured USEPROTON proton binary was not found, try to find a minor version bump instead:
						TESTEARLYPROT="$(fixProtonVersionMismatch "$CONFPROT" "X")"
						if [ -f "$TESTEARLYPROT" ]; then
							writelog "INFO" "${FUNCNAME[0]} - Found a minor version mismatch binary for '$CONFPROT':'$TESTEARLYPROT'" "E" | tee -a "$ISCRILOG"
							EARLYPROT="$TESTEARLYPROT"
							export EARLYPROT
						else
							writelog "SKIP" "${FUNCNAME[0]} - Found '$TESTEARLYPROT' does not exist" "E" | tee -a "$ISCRILOG"
						fi
					fi
				else
					writelog "ERROR" "${FUNCNAME[0]} - Could not create '$PROTONCSV'" "E" | tee -a "$ISCRILOG"
				fi
			else
				writelog "SKIP" "${FUNCNAME[0]} - No USEPROTON entry found in '$1'" "E" | tee -a "$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' #########" "E" | tee -a "$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" "E" | tee -a "$ISCRILOG"
	else
		# filter evaluatorscript command
		if grep -q "$EVALSC" <<< "$@"; then
			# shellcheck disable=SC1003
			EVSC="$(gawk -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 stl 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 stl 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'" "E" | tee -a "$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" "E" | tee -a "$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'" "E" | tee -a "$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' "$(gawk -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" "E" | tee -a "$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'" "E" | tee -a "$ISCRILOG"
							elif [ -f "$SRCORIGEVSC" ] && [ ! -f "$SRCCUSTEVSC" ]; then
								SRCEVSC="$SRCORIGEVSC"
								writelog "INFO" "${FUNCNAME[0]} - Using '$SRCEVSC' as source" "E" | tee -a "$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" "E" | tee -a "$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" "E" | tee -a "$ISCRILOG"
							fi
						fi
					
						if [ -n "$EVSC" ] && [ ! -f "$SRCEVSC" ] && [ "$SRCEVSC" == "$SRCORIGEVSC" ]; then
							waitForEvaluatorscript "$EVSC" "$ISCRILOG" &
							writelog "INFO" "${FUNCNAME[0]} - '$EVALSC' START - '$EARLYPROT run ${RUNISCCMD[*]}'" "E" | tee -a "$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'" "E" | tee -a "$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'" "E" | tee -a "$ISCRILOG"
							fi

							writelog "INFO" "${FUNCNAME[0]} - '$EVALSC' - STOP  - '$EARLYPROT run $ISCEXE $EVSC'" "E" | tee -a "$ISCRILOG"
						else
							writelog "INFO" "${FUNCNAME[0]} - '$EVALSC' - SKIP  - '$SRCEVSC' not found" "E" | tee -a "$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" | gawk -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" "E" | tee -a "$ISCRILOG"
					fi
			else
				if ! grep -q "$GECUST" <<< "$@"; then
					writelog "SKIP" "${FUNCNAME[0]} - No usable Proton version found - ignoring '$ISCRI' command '$*' - Exiting" "E" | tee -a "$ISCRILOG"
				fi
			fi
		else
			writelog "SKIP" "${FUNCNAME[0]} - Skipping '$ISCRI' command '$*' - Exiting" "E" | tee -a "$ISCRILOG"
		fi
	fi
}

function getCurrentCommandline {
	# filter $ISCRI commands
	if grep -q "$ISCRI" <<< "$@"; then
		checkFirstTimeRun "$@"
		exit
	else
		echo "$@" > "${STLSHM}/cmdline.txt"
		INPROSTR="proton $WFEAR"
		if grep -q "$INPROSTR" <<< "$@"; then
			HAVEINPROTON=1
		else
			HAVEINPROTON=0
		fi
	fi
}

function initShmStl {
	mkProjDir "$MTEMP" 1
	SHMVERS="$STLSHM/version"

	if [ -f "$SHMVERS" ]; then
		if [ "$PROGVERS" != "$(cat "$SHMVERS")" ]; then
			mv "${STLSHM}" "${STLSHM}-$((100 + RANDOM % 100))"
			mkProjDir "$MTEMP" 1
			echo "$PROGVERS" > "$SHMVERS"
		fi	
	else
		echo "$PROGVERS" > "$SHMVERS"
	fi
}

##################

function main {

	initShmStl
	initAID "$@"
	setAIDCfgs
	loadLangFile "$STLDEFLANG"
	getCurrentCommandline "$@"
	saveOrgVars
	emptyVars "O"

	writelog "START" "######### Initializing Game Launch $AID #########"

	if [ -f "$STLDEFGLOBALCFG" ] && grep -q "^RESETLOG=\"1\"" "$STLDEFGLOBALCFG"; then
		rmOldLog
		writelog "INFO" "Starting with a clean log"
	fi

	writelog "INFO" "emptyVars - Emptied some original Variables as they slowdown several system calls when started from steam"
	createDefaultCfgs "$@"
	checkIntDeps "$@"
	setInitWinXY

	if [ -z "$1" ]; then
		writelog "INFO" "${FUNCNAME[0]} - No arguments provided. See '$PROGCMD --help' for possible command line parameters" "E"
	else
		if [ -n "$SteamAppId" ] && [ "$SteamAppId" -eq "0" ]; then
			setCustomGameVars "$@"
			if [ -n "$ISGAME" ]; then
				if [ "$ISGAME" -eq 2 ] || [ "$ISGAME" -eq 3 ]; then
					prepareLaunch
				fi
			else
				writelog "ERROR" "${FUNCNAME[0]} - Unknown command '$*'" "E"
			fi
		elif grep -q "$SAC" <<< "$@" || grep -q "$L2EA" <<< "$@"; then
			if grep -q "update" <<< "$@"; 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
