From b0864223f00a53ba9018d3992a75092b6b2828d8 Mon Sep 17 00:00:00 2001
From: Alex Smith <alex.smith2844@gmail.com>
Date: Tue, 31 Dec 2024 17:27:12 +0500
Subject: [PATCH 1/5] removeNonSteamGame

---
 data_from_portwine/scripts/add_in_steam.sh | 63 +++++++++++++++++-----
 1 file changed, 49 insertions(+), 14 deletions(-)

diff --git a/data_from_portwine/scripts/add_in_steam.sh b/data_from_portwine/scripts/add_in_steam.sh
index 717da97a..69f2a166 100755
--- a/data_from_portwine/scripts/add_in_steam.sh
+++ b/data_from_portwine/scripts/add_in_steam.sh
@@ -48,12 +48,14 @@ generateShortcutGridAppId() {
 ### END MAGIC APPID FUNCTIONS
 
 getSteamShortcutsVdfFileHex() {
-	STCFGPATH="$(getUserPath)"
-	if [[ -n "${STCFGPATH}" ]]; then
+	if [[ -z "${STCFGPATH}" ]]; then
+		STCFGPATH="$(getUserPath)"
+	fi
+	if [[ -n "${STCFGPATH}" ]] && [[ -z "${SCPATH}" ]]; then
 		SCPATH="${STCFGPATH}/shortcuts.vdf"
-		if [[ -f "${SCPATH}" ]]; then
-			LC_ALL=C perl -0777 -ne 'print unpack("H*", $_)' "${SCPATH}"
-		fi
+	fi
+	if [[ -n "${SCPATH}" ]] && [[ -f "${SCPATH}" ]]; then
+		LC_ALL=C perl -0777 -ne 'print unpack("H*", $_)' "${SCPATH}"
 	fi
 }
 
@@ -301,21 +303,54 @@ addGrids() {
 	fi
 }
 
-addNonSteamGame() {
-	NOSTAPPNAME="${name_desktop}"
-	NOSTSHPATH="${STEAM_SCRIPTS}/${name_desktop}.sh"
-	NOSTEXEPATH="\"${NOSTSHPATH}\""
-	NOSTICONPATH="${PORT_WINE_PATH}/data/img/${name_desktop_png}.png"
-	if [[ -z "${NOSTSTDIR}" ]]; then
-		NOSTSTDIR="\"${STEAM_SCRIPTS}\""
+removeNonSteamGame() {
+	if [[ -z "${STCFGPATH}" ]]; then
+		STCFGPATH="$(getUserPath)"
 	fi
-	STCFGPATH="$(getUserPath)"
-	if [[ -n "${STCFGPATH}" ]]; then
+	if [[ -n "${STCFGPATH}" ]] && [[ -z "${SCPATH}" ]]; then
+		SCPATH="${STCFGPATH}/shortcuts.vdf"
+	fi
+	if [[ -n "${SCPATH}" ]] && [[ -f "${SCPATH}" ]]; then
+		cp "${SCPATH}" "${SCPATH//.vdf}_${PROGNAME}_backup.vdf" 2>/dev/null
+	fi
+	[[ -n "${1:-}" ]] && appid="$1"
+	if [[ -n "${appid}" ]]; then
+		NOSTAIDVDFHEX=$(bigToLittleEndian $(printf '%08x' "${appid}"))
+		LC_ALL=C perl -pe '
+			$hex = pack("H*", shift);
+			$pos = index($_, $hex);
+			if ($pos != -1) {
+				$start_pos = rindex($_, "\x00", $pos - 1);
+				$end_pos = index($_, "ppid", $pos);
+				$end_pos = index($_, "\x08\x08", $pos) if $end_pos == -1;
+				if ($start_pos != -1 && $end_pos != -1) {
+					$end_pos += 4;
+					$_ = substr($_, 0, $start_pos) . substr($_, $end_pos);
+				}
+			}
+		' "${SCPATH}" "${NOSTAIDVDFHEX}" > "${SCPATH}~"
+		mv "${SCPATH}~" "${SCPATH}"
+		rm -f "${STCFGPATH}/grid/${appid}.jpg" "${STCFGPATH}/grid/${appid}p.jpg" "${STCFGPATH}/grid/${appid}_hero.jpg" "${STCFGPATH}/grid/${appid}_logo.png"
+	fi
+}
+
+addNonSteamGame() {
+	if [[ -z "${STCFGPATH}" ]]; then
+		STCFGPATH="$(getUserPath)"
+	fi
+	if [[ -n "${STCFGPATH}" ]] && [[ -z "${SCPATH}" ]]; then
 		SCPATH="${STCFGPATH}/shortcuts.vdf"
 	fi
 	if [[ -n "${SCPATH}" ]]; then
+		NOSTAPPNAME="${name_desktop}"
+		NOSTSHPATH="${STEAM_SCRIPTS}/${name_desktop}.sh"
 		NOSTAIDGRID=$(getAppId "${NOSTSHPATH}")
 		if [[ -z "${NOSTAIDGRID}" ]]; then
+			NOSTEXEPATH="\"${NOSTSHPATH}\""
+			if [[ -z "${NOSTSTDIR}" ]]; then
+				NOSTSTDIR="\"${STEAM_SCRIPTS}\""
+			fi
+			NOSTICONPATH="${PORT_WINE_PATH}/data/img/${name_desktop_png}.png"
 			NOSTAIDVDF="$(generateShortcutVDFAppId "${NOSTAPPNAME}${NOSTEXEPATH}")"  # signed integer AppID, stored in the VDF as hexidecimal - ex: -598031679
 			NOSTAIDVDFHEX="$(generateShortcutVDFHexAppId "$NOSTAIDVDF")"  # 4byte little-endian hexidecimal of above 32bit signed integer, which we write out to the binary VDF - ex: c1c25adc
 			NOSTAIDVDFHEXFMT="\x$(awk '{$1=$1}1' FPAT='.{2}' OFS="\\\x" <<< "$NOSTAIDVDFHEX")"  # binary-formatted string hex of the above which we actually write out - ex: \xc1\xc2\x5a\xdc

From f5dd208f2ad7af167d135fb8de6418024034564a Mon Sep 17 00:00:00 2001
From: Alex Smith <alex.smith2844@gmail.com>
Date: Tue, 31 Dec 2024 19:53:44 +0500
Subject: [PATCH 2/5] getUserId getUserIds getUserPath

---
 data_from_portwine/scripts/add_in_steam.sh | 57 ++++++++++++++++------
 1 file changed, 41 insertions(+), 16 deletions(-)

diff --git a/data_from_portwine/scripts/add_in_steam.sh b/data_from_portwine/scripts/add_in_steam.sh
index 69f2a166..35425235 100755
--- a/data_from_portwine/scripts/add_in_steam.sh
+++ b/data_from_portwine/scripts/add_in_steam.sh
@@ -41,7 +41,8 @@ generateShortcutVDFHexAppId() {
 }
 
 # Takes an signed 32bit integer and converts it to an unsigned 32bit integer
-generateShortcutGridAppId() {
+extractSteamId32() {
+# 	STUID32=$((STUID64 - 76561197960265728))
 	echo $(($1 & 0xFFFFFFFF))
 }
 ## ----------
@@ -134,29 +135,55 @@ getSteamGridDBId() {
 	fi
 }
 
-getUserPath() {
+getUserIds() {
+	SLUF="${HOME}/.local/share/Steam/config/loginusers.vdf"
+	if [[ -f "${SLUF}" ]]; then
+		STUIDS=()
+		while read -r line; do
+			if [[ "${line}" =~ ^[[:space:]]*\"([0-9]+)\"$ ]]; then
+				STUID=$(extractSteamId32 "${BASH_REMATCH[1]}")
+				STUIDS+=("${STUID}")
+			fi
+		done < "${SLUF}"
+		if [[ ${#STUIDS[@]} -gt 0 ]]; then
+			echo "${STUIDS[@]}"
+		fi
+	fi
+}
+
+getUserId() {
 	SLUF="${HOME}/.local/share/Steam/config/loginusers.vdf"
 	if [[ -f "${SLUF}" ]]; then
 		SLUFUB=false
-		STUID64=""
+		STUID=""
 		while read -r line; do
 			if [[ "${line}" =~ ^[[:space:]]*\"([0-9]+)\"$ ]]; then
 				STUIDCUR="${BASH_REMATCH[1]}"
 				SLUFUB=true
 			elif [[ "${line}" == *'"MostRecent"'*'"1"' && ${SLUFUB} = true ]]; then
-				STUID64="${STUIDCUR}"
+				STUID=$(extractSteamId32 "${STUIDCUR}")
 				break
 			elif [[ "${line}" == "}" ]]; then
 				SLUFUB=false
 			fi
 		done < "${SLUF}"
-		if [ -n "${STUID64}" ]; then
-			STUID32=$((STUID64 - 76561197960265728))
-			STUIDPATH="${HOME}/.local/share/Steam/userdata/${STUID32}"
-			if [[ -d "${STUIDPATH}" ]]; then
-				if [[ -f "${STUIDPATH}/config/shortcuts.vdf" ]]; then
-					echo "${STUIDPATH}/config"
-				fi
+	fi
+	if [ -n "${STUID}" ]; then
+		echo "${STUID}"
+	fi
+}
+
+getUserPath() {
+	if [[ -n "${1:-}" ]]; then
+		STUID="$1"
+	else
+		STUID="$(getUserId)"
+	fi
+	if [ -n "${STUID}" ]; then
+		STUIDPATH="${HOME}/.local/share/Steam/userdata/${STUID}"
+		if [[ -d "${STUIDPATH}" ]]; then
+			if [[ -f "${STUIDPATH}/config/shortcuts.vdf" ]]; then
+				echo "${STUIDPATH}/config"
 			fi
 		fi
 	fi
@@ -304,17 +331,15 @@ addGrids() {
 }
 
 removeNonSteamGame() {
+	[[ -n "${1:-}" ]] && appid="$1"
 	if [[ -z "${STCFGPATH}" ]]; then
 		STCFGPATH="$(getUserPath)"
 	fi
 	if [[ -n "${STCFGPATH}" ]] && [[ -z "${SCPATH}" ]]; then
 		SCPATH="${STCFGPATH}/shortcuts.vdf"
 	fi
-	if [[ -n "${SCPATH}" ]] && [[ -f "${SCPATH}" ]]; then
+	if [[ -n "${appid}" ]] && [[ -n "${SCPATH}" ]] && [[ -f "${SCPATH}" ]]; then
 		cp "${SCPATH}" "${SCPATH//.vdf}_${PROGNAME}_backup.vdf" 2>/dev/null
-	fi
-	[[ -n "${1:-}" ]] && appid="$1"
-	if [[ -n "${appid}" ]]; then
 		NOSTAIDVDFHEX=$(bigToLittleEndian $(printf '%08x' "${appid}"))
 		LC_ALL=C perl -pe '
 			$hex = pack("H*", shift);
@@ -354,7 +379,7 @@ addNonSteamGame() {
 			NOSTAIDVDF="$(generateShortcutVDFAppId "${NOSTAPPNAME}${NOSTEXEPATH}")"  # signed integer AppID, stored in the VDF as hexidecimal - ex: -598031679
 			NOSTAIDVDFHEX="$(generateShortcutVDFHexAppId "$NOSTAIDVDF")"  # 4byte little-endian hexidecimal of above 32bit signed integer, which we write out to the binary VDF - ex: c1c25adc
 			NOSTAIDVDFHEXFMT="\x$(awk '{$1=$1}1' FPAT='.{2}' OFS="\\\x" <<< "$NOSTAIDVDFHEX")"  # binary-formatted string hex of the above which we actually write out - ex: \xc1\xc2\x5a\xdc
-			NOSTAIDGRID="$(generateShortcutGridAppId "$NOSTAIDVDF")"  # unsigned 32bit ingeger version of "$NOSTAIDVDF", which is used as the AppID for Steam artwork ("grids"), as well as for our shortcuts
+			NOSTAIDGRID="$(extractSteamId32 "$NOSTAIDVDF")"  # unsigned 32bit ingeger version of "$NOSTAIDVDF", which is used as the AppID for Steam artwork ("grids"), as well as for our shortcuts
 
 			create_new_dir "${STEAM_SCRIPTS}"
 			echo "#!/usr/bin/env bash" > "${NOSTSHPATH}"

From df86ec04167087270c5dde32e72f9c4254fb4f26 Mon Sep 17 00:00:00 2001
From: Alex Smith <alex.smith2844@gmail.com>
Date: Tue, 31 Dec 2024 20:55:49 +0500
Subject: [PATCH 3/5] getAppExe

---
 data_from_portwine/scripts/add_in_steam.sh | 35 +++++++++++++++++-----
 1 file changed, 27 insertions(+), 8 deletions(-)

diff --git a/data_from_portwine/scripts/add_in_steam.sh b/data_from_portwine/scripts/add_in_steam.sh
index 35425235..8c77b2cb 100755
--- a/data_from_portwine/scripts/add_in_steam.sh
+++ b/data_from_portwine/scripts/add_in_steam.sh
@@ -74,10 +74,14 @@ getSteamShortcutEntryHex() {
 	printf "%s" "${SHORTCUTSVDFINPUTHEX}" | grep -oP "${SHORTCUTSVDFMATCHPATTERN}\K.*?(?=${SHORTCUTVDFENDPAT})"
 }
 
+getAppExe() {
+	[[ -n "$1" ]] && listNonSteamGames | jq -r --arg id "$1" 'map(select(.id == $id)) | first(.[].exe)'
+}
+
 getAppTarget() {
-	exe=$(listNonSteamGames | jq -r --arg id "$1" 'map(select(.id == $id)) | first(.[].exe)')
+	exe=$(getAppExe "$1")
 	if [[ -n "${exe}" ]]; then
-		if [[ "${exe}" =~ .sh$ ]] ; then
+		if [[ "${exe}" =~ .sh$ ]]; then
 			parseSteamTargetExe "${exe}"
 		else
 			echo "${exe}";
@@ -90,7 +94,7 @@ getSteamGameId() {
 }
 
 getAppId() {
-	listNonSteamGames | jq -r --arg exe "$1" 'map(select(.exe == $exe)) | first(.[]?.id)'
+	[[ -n "$1" ]] && listNonSteamGames | jq -r --arg exe "$1" 'map(select(.exe == $exe)) | first(.[]?.id)'
 }
 
 getSteamId() {
@@ -141,8 +145,7 @@ getUserIds() {
 		STUIDS=()
 		while read -r line; do
 			if [[ "${line}" =~ ^[[:space:]]*\"([0-9]+)\"$ ]]; then
-				STUID=$(extractSteamId32 "${BASH_REMATCH[1]}")
-				STUIDS+=("${STUID}")
+				STUIDS+=("$(extractSteamId32 "${BASH_REMATCH[1]}")")
 			fi
 		done < "${SLUF}"
 		if [[ ${#STUIDS[@]} -gt 0 ]]; then
@@ -332,13 +335,14 @@ addGrids() {
 
 removeNonSteamGame() {
 	[[ -n "${1:-}" ]] && appid="$1"
-	if [[ -z "${STCFGPATH}" ]]; then
-		STCFGPATH="$(getUserPath)"
-	fi
+	[[ -n "${2:-}" ]] && NOSTSHPATH="$2"
+	[[ -z "${STUID}" ]] && STUID=$(getUserId)
+	[[ -z "${STCFGPATH}" ]] && STCFGPATH="$(getUserPath ${STUID})"
 	if [[ -n "${STCFGPATH}" ]] && [[ -z "${SCPATH}" ]]; then
 		SCPATH="${STCFGPATH}/shortcuts.vdf"
 	fi
 	if [[ -n "${appid}" ]] && [[ -n "${SCPATH}" ]] && [[ -f "${SCPATH}" ]]; then
+		[[ -z "${NOSTSHPATH}" ]] && NOSTSHPATH=$(getAppExe ${appid})
 		cp "${SCPATH}" "${SCPATH//.vdf}_${PROGNAME}_backup.vdf" 2>/dev/null
 		NOSTAIDVDFHEX=$(bigToLittleEndian $(printf '%08x' "${appid}"))
 		LC_ALL=C perl -pe '
@@ -357,6 +361,21 @@ removeNonSteamGame() {
 		mv "${SCPATH}~" "${SCPATH}"
 		rm -f "${STCFGPATH}/grid/${appid}.jpg" "${STCFGPATH}/grid/${appid}p.jpg" "${STCFGPATH}/grid/${appid}_hero.jpg" "${STCFGPATH}/grid/${appid}_logo.png"
 	fi
+	if [[ -n "${STUID}" ]] && [[ -n "${NOSTSHPATH}" ]] && [[ -f "${NOSTSHPATH}" ]]; then
+		isInstallGame=false
+		for STUIDCUR in $(getUserIds); do
+			[[ "${STUIDCUR}" == "${STUID}" ]] && continue
+			STCFGPATH="$(getUserPath ${STUIDCUR})"
+			SCPATH="${STCFGPATH}/shortcuts.vdf"
+			if [[ -n "$(getAppId "${NOSTSHPATH}")" ]]; then
+				isInstallGame=true
+				break
+			fi
+		done
+		if [[ ${isInstallGame} == false ]]; then
+			rm "${NOSTSHPATH}"
+		fi
+	fi
 }
 
 addNonSteamGame() {

From 23be9fc637107b406c67cb1f33da98d84db84247 Mon Sep 17 00:00:00 2001
From: Alex Smith <alex.smith2844@gmail.com>
Date: Thu, 2 Jan 2025 03:09:24 +0500
Subject: [PATCH 4/5] addEntry

---
 data_from_portwine/scripts/add_in_steam.sh | 203 ++++++++++++---------
 1 file changed, 116 insertions(+), 87 deletions(-)

diff --git a/data_from_portwine/scripts/add_in_steam.sh b/data_from_portwine/scripts/add_in_steam.sh
index 8c77b2cb..54ae69b1 100755
--- a/data_from_portwine/scripts/add_in_steam.sh
+++ b/data_from_portwine/scripts/add_in_steam.sh
@@ -210,19 +210,22 @@ listInstalledSteamGames() {
 }
 
 listNonSteamGames() {
-	getSteamShortcutHex | while read -r SCVDFE; do
-		jq -n \
-			--arg id "$(parseSteamShortcutEntryAppID "${SCVDFE}")" \
-			--arg name "$(parseSteamShortcutEntryAppName "${SCVDFE}")" \
-			--arg exe "$(parseSteamShortcutEntryExe "${SCVDFE}")" \
-			'{id: $id, name: $name, exe: $exe}'
-	done | jq -s '.'
+    getSteamShortcutHex | while read -r SCVDFE; do
+        jq -n \
+            --arg id "$(parseSteamShortcutEntryAppID "${SCVDFE}")" \
+            --arg name "$(parseSteamShortcutEntryAppName "${SCVDFE}")" \
+            --arg exe "$(parseSteamShortcutEntryExe "${SCVDFE}")" \
+            --arg dir "$(parseSteamShortcutEntryStartDir "${SCVDFE}")" \
+            --arg icon "$(parseSteamShortcutEntryIcon "${SCVDFE}")" \
+            --arg args "$(parseSteamShortcutEntryLaunchOptions "${SCVDFE}")" \
+            '{id: $id, name: $name, exe: $exe, dir: $dir, icon: $icon, args: $args}'
+    done | jq -s '.'
 }
 
 listSteamGames() {
 	(
 	 	jq -r 'map({AppId: .id, SteamAppId: .id, SteamGameId: .id, Name: .name}) | .[] | tostring' <<< "$(listInstalledSteamGames)"
-		jq -r '.[] | tostring' <<< "$(listNonSteamGames)" | while read game; do
+		jq -r '.[] | tostring' <<< "$(listNonSteamGames)" | while read -r game; do
 			id=$(jq -r '.id' <<< "${game}")
 			name=$(jq -r '.name' <<< "${game}")
 			jq -r \
@@ -240,19 +243,22 @@ convertSteamShortcutAppID() {
 }
 
 convertSteamShortcutHex() {
-	# printf "%s" "$1" | xxd -r -p | tr -d '\0'
 	LC_ALL=C perl -le 'print pack "H*", $ARGV[0]' "$1" | tr -d '\0'
 }
 
+convertStringToSteamShortcutHex() {
+	LC_ALL=C perl -e 'print unpack "H*", "$ARGV[0]" . "\x00"' "$(echo "$1" | tr -cd '[:alpha:]')"
+}
+
 parseSteamShortcutEntryHex() {
 	SHORTCUTSVDFINPUTHEX="$1"  # The hex block representing the shortcut
 	SHORTCUTSVDFMATCHPATTERN="$2"  # The pattern to match against in the block
 	convertSteamShortcutHex "$(getSteamShortcutEntryHex "${SHORTCUTSVDFINPUTHEX}" "${SHORTCUTSVDFMATCHPATTERN}")"
 }
 
-parseSteamShortcutEntryExe() {
-	SHORTCUTVDFEXEHEXPAT="000145786500"  # 'Exe' ('exe' is 6578650a if we ever need it)
-	parseSteamShortcutEntryHex "$1" "${SHORTCUTVDFEXEHEXPAT}" | tr -d '"'
+parseSteamShortcutEntryAppID() {
+	SHORTCUTVDFAPPIDHEXPAT="617070696400"  # 'appid'
+	convertSteamShortcutAppID "$(printf "%s" "$1" | grep -oP "${SHORTCUTVDFAPPIDHEXPAT}\K.{8}")"
 }
 
 parseSteamShortcutEntryAppName() {
@@ -260,9 +266,24 @@ parseSteamShortcutEntryAppName() {
 	parseSteamShortcutEntryHex "$1" "${SHORTCUTVDFNAMEHEXPAT}"
 }
 
-parseSteamShortcutEntryAppID() {
-	SHORTCUTVDFAPPIDHEXPAT="617070696400"  # 'appid'
-	convertSteamShortcutAppID "$(printf "%s" "$1" | grep -oP "${SHORTCUTVDFAPPIDHEXPAT}\K.{8}")"
+parseSteamShortcutEntryExe() {
+	SHORTCUTVDFEXEHEXPAT="000145786500"  # 'Exe' ('exe' is 6578650a if we ever need it)
+	parseSteamShortcutEntryHex "$1" "${SHORTCUTVDFEXEHEXPAT}" | tr -d '"'
+}
+
+parseSteamShortcutEntryStartDir() {
+	SHORTCUTVDFSTARTDIRHEXPAT="0001537461727444697200"
+	parseSteamShortcutEntryHex "$1" "${SHORTCUTVDFSTARTDIRHEXPAT}" | tr -d '"'
+}
+
+parseSteamShortcutEntryIcon() {
+	SHORTCUTVDFICONHEXPAT="000169636f6e00"
+	parseSteamShortcutEntryHex "$1" "${SHORTCUTVDFICONHEXPAT}"
+}
+
+parseSteamShortcutEntryLaunchOptions() {
+	SHORTCUTVDFARGHEXPAT="00014c61756e63684f7074696f6e7300" # echo "0001$(convertStringToSteamShortcutHex "LaunchOptions")"
+	parseSteamShortcutEntryHex "$1" "${SHORTCUTVDFARGHEXPAT}" | tr '\002' '\n' | head -n 1 | tr -d '\000'
 }
 
 parseSteamTargetExe() {
@@ -333,47 +354,90 @@ addGrids() {
 	fi
 }
 
+addEntry() {
+	if [[ -n "${SCPATH}" ]]; then
+		if [[ -f "${SCPATH}" ]] ; then
+			truncate -s-2 "${SCPATH}"
+			OLDSET="$(grep -aPo '\x00[0-9]\x00\x02appid' "${SCPATH}" | tail -n1 | tr -dc '0-9')"
+			NEWSET=$((OLDSET + 1))
+		else
+			printf '\x00%s\x00' "shortcuts" > "${SCPATH}"
+			NEWSET=0
+		fi
+		NOSTAIDVDFHEXFMT="\x$(awk '{$1=$1}1' FPAT='.{2}' OFS="\\\x" <<< "$NOSTAIDVDFHEX")"  # binary-formatted string hex of the above which we actually write out - ex: \xc1\xc2\x5a\xdc
+
+		{
+			printf '\x00%s\x00' "${NEWSET}"
+			printf '\x02%s\x00%b' "appid" "${NOSTAIDVDFHEXFMT}"
+			printf '\x01%s\x00%s\x00' "AppName" "${NOSTAPPNAME}"
+			printf '\x01%s\x00%s\x00' "Exe" "\"${NOSTEXEPATH}\""
+			printf '\x01%s\x00%s\x00' "StartDir" "\"${NOSTSTDIR}\""
+			printf '\x01%s\x00%s\x00' "icon" "${NOSTICONPATH}"
+			printf '\x01%s\x00%s\x00' "ShortcutPath" ""
+			printf '\x01%s\x00%s\x00' "LaunchOptions" "${NOSTARGS:-}"
+
+			printf '\x02%s\x00%b\x00\x00\x00' "IsHidden" "\x00"
+			printf '\x02%s\x00%b\x00\x00\x00' "AllowDesktopConfig" "\x00"
+
+			# These values are now stored in localconfig.vdf under the "Apps" section,
+			# under a block using the Non-Steam Game Signed 32bit AppID. (i.e., -223056321)
+			# This is handled by `updateLocalConfigAppsValue` below
+			#
+			# Unsure if required, but still write these to the shortcuts.vdf file for consistency
+			printf '\x02%s\x00%b\x00\x00\x00' "AllowOverlay" "\x00"
+			printf '\x02%s\x00%b\x00\x00\x00' "OpenVR" "\x00"
+
+			printf '\x02%s\x00\x00\x00\x00\x00' "Devkit"
+			printf '\x01%s\x00\x00' "DevkitGameID"
+			printf '\x02%s\x00\x00\x00\x00\x00' "DevkitOverrideAppID"
+			printf '\x02%s\x00\x00\x00\x00\x00' "LastPlayTime"
+			printf '\x01%s\x00\x00' "FlatpakAppID"
+			printf '\x00%s\x00' "tags"
+			printf '\x08\x08\x08\x08'
+		} >> "${SCPATH}"
+	fi
+}
+
 removeNonSteamGame() {
-	[[ -n "${1:-}" ]] && appid="$1"
-	[[ -n "${2:-}" ]] && NOSTSHPATH="$2"
+	[[ -n "$1" ]] && appid="$1"
 	[[ -z "${STUID}" ]] && STUID=$(getUserId)
 	[[ -z "${STCFGPATH}" ]] && STCFGPATH="$(getUserPath ${STUID})"
 	if [[ -n "${STCFGPATH}" ]] && [[ -z "${SCPATH}" ]]; then
 		SCPATH="${STCFGPATH}/shortcuts.vdf"
 	fi
-	if [[ -n "${appid}" ]] && [[ -n "${SCPATH}" ]] && [[ -f "${SCPATH}" ]]; then
-		[[ -z "${NOSTSHPATH}" ]] && NOSTSHPATH=$(getAppExe ${appid})
-		cp "${SCPATH}" "${SCPATH//.vdf}_${PROGNAME}_backup.vdf" 2>/dev/null
-		NOSTAIDVDFHEX=$(bigToLittleEndian $(printf '%08x' "${appid}"))
-		LC_ALL=C perl -pe '
-			$hex = pack("H*", shift);
-			$pos = index($_, $hex);
-			if ($pos != -1) {
-				$start_pos = rindex($_, "\x00", $pos - 1);
-				$end_pos = index($_, "ppid", $pos);
-				$end_pos = index($_, "\x08\x08", $pos) if $end_pos == -1;
-				if ($start_pos != -1 && $end_pos != -1) {
-					$end_pos += 4;
-					$_ = substr($_, 0, $start_pos) . substr($_, $end_pos);
-				}
-			}
-		' "${SCPATH}" "${NOSTAIDVDFHEX}" > "${SCPATH}~"
-		mv "${SCPATH}~" "${SCPATH}"
-		rm -f "${STCFGPATH}/grid/${appid}.jpg" "${STCFGPATH}/grid/${appid}p.jpg" "${STCFGPATH}/grid/${appid}_hero.jpg" "${STCFGPATH}/grid/${appid}_logo.png"
-	fi
-	if [[ -n "${STUID}" ]] && [[ -n "${NOSTSHPATH}" ]] && [[ -f "${NOSTSHPATH}" ]]; then
-		isInstallGame=false
-		for STUIDCUR in $(getUserIds); do
-			[[ "${STUIDCUR}" == "${STUID}" ]] && continue
-			STCFGPATH="$(getUserPath ${STUIDCUR})"
-			SCPATH="${STCFGPATH}/shortcuts.vdf"
-			if [[ -n "$(getAppId "${NOSTSHPATH}")" ]]; then
-				isInstallGame=true
-				break
+	if [[ -n "${appid}" ]]; then
+		games=$(listNonSteamGames)
+		NOSTSHPATH=$(jq -r --arg id "${appid}" 'map(select(.id == $id)) | first(.[].exe)' <<< "${games}")
+		if [[ -n "${NOSTSHPATH}" ]]; then
+			mv "${SCPATH}" "${SCPATH//.vdf}_${PROGNAME}_backup.vdf" 2>/dev/null
+			jq --arg id "${appid}" 'map(select(.id != $id))' <<< "${games}" | jq -c '.[]' | while read -r game; do
+				NOSTAIDGRID=$(jq -r '.id' <<< "${game}")
+				NOSTAPPNAME=$(jq -r '.name' <<< "${game}")
+				NOSTEXEPATH=$(jq -r '.exe' <<< "${game}")
+				NOSTSTDIR=$(jq -r '.dir' <<< "${game}")
+				NOSTICONPATH=$(jq -r '.icon' <<< "${game}")
+				NOSTARGS=$(jq -r '.args' <<< "${game}")
+				NOSTAIDVDFHEX=$(bigToLittleEndian $(printf '%08x' "${NOSTAIDGRID}"))
+				addEntry
+			done
+			rm -f "${STCFGPATH}/grid/${appid}.jpg" "${STCFGPATH}/grid/${appid}p.jpg" "${STCFGPATH}/grid/${appid}_hero.jpg" "${STCFGPATH}/grid/${appid}_logo.png"
+			if [[ -f "${NOSTSHPATH}" ]]; then
+				isInstallGame=false
+				for STUIDCUR in $(getUserIds); do
+					[[ "${STUIDCUR}" == "${STUID}" ]] && continue
+					STCFGPATH="$(getUserPath ${STUIDCUR})"
+					SCPATH="${STCFGPATH}/shortcuts.vdf"
+					if [[ -n "$(getAppId "${NOSTSHPATH}")" ]]; then
+						isInstallGame=true
+						break
+					fi
+				done
+				unset STCFGPATH SCPATH
+				if [[ ${isInstallGame} == false ]]; then
+					rm "${NOSTSHPATH}"
+				fi
 			fi
-		done
-		if [[ ${isInstallGame} == false ]]; then
-			rm "${NOSTSHPATH}"
+			restartSteam
 		fi
 	fi
 }
@@ -390,14 +454,13 @@ addNonSteamGame() {
 		NOSTSHPATH="${STEAM_SCRIPTS}/${name_desktop}.sh"
 		NOSTAIDGRID=$(getAppId "${NOSTSHPATH}")
 		if [[ -z "${NOSTAIDGRID}" ]]; then
-			NOSTEXEPATH="\"${NOSTSHPATH}\""
+			NOSTEXEPATH="${NOSTSHPATH}"
 			if [[ -z "${NOSTSTDIR}" ]]; then
-				NOSTSTDIR="\"${STEAM_SCRIPTS}\""
+				NOSTSTDIR="${STEAM_SCRIPTS}"
 			fi
 			NOSTICONPATH="${PORT_WINE_PATH}/data/img/${name_desktop_png}.png"
 			NOSTAIDVDF="$(generateShortcutVDFAppId "${NOSTAPPNAME}${NOSTEXEPATH}")"  # signed integer AppID, stored in the VDF as hexidecimal - ex: -598031679
 			NOSTAIDVDFHEX="$(generateShortcutVDFHexAppId "$NOSTAIDVDF")"  # 4byte little-endian hexidecimal of above 32bit signed integer, which we write out to the binary VDF - ex: c1c25adc
-			NOSTAIDVDFHEXFMT="\x$(awk '{$1=$1}1' FPAT='.{2}' OFS="\\\x" <<< "$NOSTAIDVDFHEX")"  # binary-formatted string hex of the above which we actually write out - ex: \xc1\xc2\x5a\xdc
 			NOSTAIDGRID="$(extractSteamId32 "$NOSTAIDVDF")"  # unsigned 32bit ingeger version of "$NOSTAIDVDF", which is used as the AppID for Steam artwork ("grids"), as well as for our shortcuts
 
 			create_new_dir "${STEAM_SCRIPTS}"
@@ -413,43 +476,9 @@ addNonSteamGame() {
 
 			if [[ -f "${SCPATH}" ]] ; then
 				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))
-			else
-				printf '\x00%s\x00' "shortcuts" > "${SCPATH}"
-				NEWSET=0
 			fi
 
-			{
-				printf '\x00%s\x00' "${NEWSET}"
-				printf '\x02%s\x00%b' "appid" "${NOSTAIDVDFHEXFMT}"
-				printf '\x01%s\x00%s\x00' "AppName" "${NOSTAPPNAME}"
-				printf '\x01%s\x00%s\x00' "Exe" "${NOSTEXEPATH}"
-				printf '\x01%s\x00%s\x00' "StartDir" "${NOSTSTDIR}"
-				printf '\x01%s\x00%s\x00' "icon" "${NOSTICONPATH}"
-				printf '\x01%s\x00%s\x00' "ShortcutPath" ""
-				printf '\x01%s\x00%s\x00' "LaunchOptions" ""
-
-				printf '\x02%s\x00%b\x00\x00\x00' "IsHidden" "\x00"
-				printf '\x02%s\x00%b\x00\x00\x00' "AllowDesktopConfig" "\x00"
-
-				# These values are now stored in localconfig.vdf under the "Apps" section,
-				# under a block using the Non-Steam Game Signed 32bit AppID. (i.e., -223056321)
-				# This is handled by `updateLocalConfigAppsValue` below
-				#
-				# Unsure if required, but still write these to the shortcuts.vdf file for consistency
-				printf '\x02%s\x00%b\x00\x00\x00' "AllowOverlay" "\x00"
-				printf '\x02%s\x00%b\x00\x00\x00' "OpenVR" "\x00"
-
-				printf '\x02%s\x00\x00\x00\x00\x00' "Devkit"
-				printf '\x01%s\x00\x00' "DevkitGameID"
-				printf '\x02%s\x00\x00\x00\x00\x00' "DevkitOverrideAppID"
-				printf '\x02%s\x00\x00\x00\x00\x00' "LastPlayTime"
-				printf '\x01%s\x00\x00' "FlatpakAppID"
-				printf '\x00%s\x00' "tags"
-				printf '\x08\x08\x08\x08'
-			} >> "${SCPATH}"
+			addEntry
 
 			# TODO: замень использование steamgriddb на steam так как сайт steamgriddb у многих без VPN не работает
 			# а пока просто блочим использование

From 59d3ee4f4ec609067dd1b1b101d875ad79777238 Mon Sep 17 00:00:00 2001
From: Alex Smith <alex.smith2844@gmail.com>
Date: Tue, 7 Jan 2025 17:59:14 +0500
Subject: [PATCH 5/5] portwine_delete_shortcut

---
 data_from_portwine/scripts/add_in_steam.sh  |  5 +-
 data_from_portwine/scripts/functions_helper | 56 ++++++++++++++-------
 2 files changed, 42 insertions(+), 19 deletions(-)

diff --git a/data_from_portwine/scripts/add_in_steam.sh b/data_from_portwine/scripts/add_in_steam.sh
index 54ae69b1..de27bb9b 100755
--- a/data_from_portwine/scripts/add_in_steam.sh
+++ b/data_from_portwine/scripts/add_in_steam.sh
@@ -400,6 +400,7 @@ addEntry() {
 
 removeNonSteamGame() {
 	[[ -n "$1" ]] && appid="$1"
+	[[ -n "$2" ]] && NOSTSHPATH="$2"
 	[[ -z "${STUID}" ]] && STUID=$(getUserId)
 	[[ -z "${STCFGPATH}" ]] && STCFGPATH="$(getUserPath ${STUID})"
 	if [[ -n "${STCFGPATH}" ]] && [[ -z "${SCPATH}" ]]; then
@@ -407,7 +408,7 @@ removeNonSteamGame() {
 	fi
 	if [[ -n "${appid}" ]]; then
 		games=$(listNonSteamGames)
-		NOSTSHPATH=$(jq -r --arg id "${appid}" 'map(select(.id == $id)) | first(.[].exe)' <<< "${games}")
+		[[ -z "${NOSTSHPATH}" ]] && NOSTSHPATH=$(jq -r --arg id "${appid}" 'map(select(.id == $id)) | first(.[].exe)' <<< "${games}")
 		if [[ -n "${NOSTSHPATH}" ]]; then
 			mv "${SCPATH}" "${SCPATH//.vdf}_${PROGNAME}_backup.vdf" 2>/dev/null
 			jq --arg id "${appid}" 'map(select(.id != $id))' <<< "${games}" | jq -c '.[]' | while read -r game; do
@@ -450,8 +451,8 @@ addNonSteamGame() {
 		SCPATH="${STCFGPATH}/shortcuts.vdf"
 	fi
 	if [[ -n "${SCPATH}" ]]; then
+		[[ -z "${NOSTSHPATH}" ]] && NOSTSHPATH="${STEAM_SCRIPTS}/${name_desktop}.sh"
 		NOSTAPPNAME="${name_desktop}"
-		NOSTSHPATH="${STEAM_SCRIPTS}/${name_desktop}.sh"
 		NOSTAIDGRID=$(getAppId "${NOSTSHPATH}")
 		if [[ -z "${NOSTAIDGRID}" ]]; then
 			NOSTEXEPATH="${NOSTSHPATH}"
diff --git a/data_from_portwine/scripts/functions_helper b/data_from_portwine/scripts/functions_helper
index f7d31fcd..3eb57ea9 100755
--- a/data_from_portwine/scripts/functions_helper
+++ b/data_from_portwine/scripts/functions_helper
@@ -6308,7 +6308,18 @@ portwine_change_shortcut () {
     then PW_SHORTCUT_DESKTOP="TRUE"
     else PW_SHORTCUT_DESKTOP="FALSE"
     fi
-    PW_SHORTCUT_STEAM="FALSE"
+    if [[ -n $PW_DELETE_STEAM ]]; then
+        source "${PORT_SCRIPTS_PATH}/add_in_steam.sh"
+        NOSTSHPATH="${PW_DELETE_SHORTCUT_STEAM[0]//#@_@#/ }"
+        NOSTAIDGRID=$(getAppId "${NOSTSHPATH}")
+        if [[ -n "${NOSTSHPATH}" ]] && [[ -n "${NOSTAIDGRID}" ]]; then
+            PW_SHORTCUT_STEAM="TRUE"
+        else
+            PW_SHORTCUT_STEAM="FALSE"
+        fi
+    else
+        PW_SHORTCUT_STEAM="FALSE"
+    fi
 
     unset name_desktop
     create_name_desktop
@@ -6334,6 +6345,7 @@ portwine_change_shortcut () {
     PORTWINE_CHANGE_SHORTCUT=1
     if [[ $PW_YAD_OUT == 1 ]] ; then
         [[ "$PW_GUI_START" == "NOTEBOOK" ]] && unset PW_YAD_FORM_TAB
+        PW_SHORTCUT_STEAM="FALSE"
         portwine_delete_shortcut
         restart_pp
     fi
@@ -6341,24 +6353,29 @@ portwine_change_shortcut () {
 }
 
 portwine_search_shortcut () {
-    unset PW_DELETE_SHORTCUT_MENU PW_DELETE_SHORTCUT_DESKTOP
-    PW_DELETE_MENU="$(grep -il "${portwine_exe}" "${HOME}/.local/share/applications"/*.desktop 2>/dev/null)"
-    read -r -d '' -a PW_DELETE_SHORTCUT_MENU <<< "${PW_DELETE_SHORTCUT_MENU[*]} ${PW_DELETE_MENU// /#@_@#}"
+    unset PW_DELETE_SHORTCUT_MENU PW_DELETE_SHORTCUT_STEAM PW_DELETE_SHORTCUT_DESKTOP
+    if [[ -n "${portwine_exe}" ]]; then
+        PW_DELETE_MENU="$(grep -il "${portwine_exe}" "${HOME}/.local/share/applications"/*.desktop 2>/dev/null)"
+        read -r -d '' -a PW_DELETE_SHORTCUT_MENU <<< "${PW_DELETE_SHORTCUT_MENU[*]} ${PW_DELETE_MENU// /#@_@#}"
 
-    PW_DELETE_PP="$(grep -il "${portwine_exe}" "${PORT_WINE_PATH}"/*.desktop 2>/dev/null)"
-    read -r -d '' -a PW_DELETE_SHORTCUT_MENU <<< "${PW_DELETE_SHORTCUT_MENU[*]} ${PW_DELETE_PP// /#@_@#}"
+        PW_DELETE_PP="$(grep -il "${portwine_exe}" "${PORT_WINE_PATH}"/*.desktop 2>/dev/null)"
+        read -r -d '' -a PW_DELETE_SHORTCUT_MENU <<< "${PW_DELETE_SHORTCUT_MENU[*]} ${PW_DELETE_PP// /#@_@#}"
 
-    if [[ -d "${HOME}/Desktop" ]] ; then
-        PW_DELETE_DESKTOP="$(grep -il "${portwine_exe}" "${HOME}/Desktop"/*.desktop 2>/dev/null)"
-        read -r -d '' -a PW_DELETE_SHORTCUT_DESKTOP <<< "${PW_DELETE_SHORTCUT_DESKTOP[*]} ${PW_DELETE_DESKTOP// /#@_@#}"
-    fi
-    if [[ -d "${HOME}/Рабочий стол" ]] ; then
-        PW_DELETE_DESKTOP="$(grep -il "${portwine_exe}" "${HOME}/Рабочий стол"/*.desktop 2>/dev/null)"
-        read -r -d '' -a PW_DELETE_SHORTCUT_DESKTOP <<< "${PW_DELETE_SHORTCUT_DESKTOP[*]} ${PW_DELETE_DESKTOP// /#@_@#}"
-    fi
-    if [[ $(xdg-user-dir DESKTOP) ]] ; then
-        PW_DELETE_DESKTOP="$(grep -il "${portwine_exe}" "$(xdg-user-dir DESKTOP)"/*.desktop 2>/dev/null)"
-        read -r -d '' -a PW_DELETE_SHORTCUT_DESKTOP <<< "${PW_DELETE_SHORTCUT_DESKTOP[*]} ${PW_DELETE_DESKTOP// /#@_@#}"
+        PW_DELETE_STEAM="$(grep -il "${portwine_exe}" "${STEAM_SCRIPTS}"/*.sh 2>/dev/null)"
+        read -r -d '' -a PW_DELETE_SHORTCUT_STEAM <<< "${PW_DELETE_SHORTCUT_STEAM[*]} ${PW_DELETE_STEAM// /#@_@#}"
+
+        if [[ -d "${HOME}/Desktop" ]] ; then
+            PW_DELETE_DESKTOP="$(grep -il "${portwine_exe}" "${HOME}/Desktop"/*.desktop 2>/dev/null)"
+            read -r -d '' -a PW_DELETE_SHORTCUT_DESKTOP <<< "${PW_DELETE_SHORTCUT_DESKTOP[*]} ${PW_DELETE_DESKTOP// /#@_@#}"
+        fi
+        if [[ -d "${HOME}/Рабочий стол" ]] ; then
+            PW_DELETE_DESKTOP="$(grep -il "${portwine_exe}" "${HOME}/Рабочий стол"/*.desktop 2>/dev/null)"
+            read -r -d '' -a PW_DELETE_SHORTCUT_DESKTOP <<< "${PW_DELETE_SHORTCUT_DESKTOP[*]} ${PW_DELETE_DESKTOP// /#@_@#}"
+        fi
+        if [[ $(xdg-user-dir DESKTOP) ]] ; then
+            PW_DELETE_DESKTOP="$(grep -il "${portwine_exe}" "$(xdg-user-dir DESKTOP)"/*.desktop 2>/dev/null)"
+            read -r -d '' -a PW_DELETE_SHORTCUT_DESKTOP <<< "${PW_DELETE_SHORTCUT_DESKTOP[*]} ${PW_DELETE_DESKTOP// /#@_@#}"
+        fi
     fi
 }
 
@@ -6371,6 +6388,11 @@ portwine_delete_shortcut () {
     for delete_shortcut in "${PW_DELETE_SHORTCUT_MENU[@]}" "${PW_DELETE_SHORTCUT_DESKTOP[@]}" ; do
         rm -f "${delete_shortcut//#@_@#/ }"
     done
+
+    if [[ "${PW_SHORTCUT_STEAM}" == "FALSE" ]] && [[ -n "${NOSTSHPATH}" ]] && [[ -n "${NOSTAIDGRID}" ]]; then
+        source "${PORT_SCRIPTS_PATH}/add_in_steam.sh"
+        removeNonSteamGame "${NOSTAIDGRID}" "${NOSTSHPATH}"
+    fi
 }
 
 portwine_missing_shortcut () {