1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
|
import os
import subprocess
import json
from decky_plugin import PluginBase
class Plugin(PluginBase):
async def get_installed_games(self) -> str:
library_file = "/home/deck/.steam/steam/steamapps/libraryfolders.vdf"
libraries = []
# Parse libraryfolders.vdf
if os.path.exists(library_file):
with open(library_file, "r") as f:
lines = f.readlines()
for line in lines:
if '"path"' in line:
path = line.split('"')[3]
libraries.append(os.path.join(path, "steamapps"))
# Fetch installed games from libraries
games = []
for library in libraries:
if os.path.exists(library):
manifest_files = [f for f in os.listdir(library) if f.startswith("appmanifest_")]
for manifest in manifest_files:
with open(os.path.join(library, manifest), "r") as f:
lines = f.readlines()
appid = ""
name = ""
for line in lines:
if '"appid"' in line:
appid = line.split('"')[3]
elif '"name"' in line:
name = line.split('"')[3]
if appid and name:
games.append({"appid": appid, "name": name})
# Return games as JSON string for compatibility with TSX
return json.dumps(games)
@callable
async def run_install_fgmod(self) -> dict:
script = """
#!/usr/bin/env bash
set -euo pipefail # Exit on error, undefined variable, or pipe failure
trap 'echo "An error occurred. Exiting."' ERR
# Define paths
assets_path="$HOME/homebrew/plugins/Decky-Framegen/assets"
mod_path="$assets_path"
nvidiaver=555.52.04
enablerver=3.02.000.0
fakenvapiver=v1.2.0
# Ensure the assets directory exists
if [[ ! -d "$assets_path" ]]; then
echo "Error: Assets directory does not exist at $assets_path!"
exit 1
fi
# Clear existing mod files
echo "Preparing mod directory..."
rm -rf "$mod_path"/*
mkdir -p "$mod_path"
# Copy fgmod scripts from assets
echo "Copying fgmod scripts..."
cp "$assets_path/fgmod.sh" "$mod_path/fgmod" || { echo "Error: fgmod.sh not found in assets!"; exit 1; }
cp "$assets_path/fgmod-uninstaller.sh" "$mod_path/fgmod-uninstaller.sh" || { echo "Error: fgmod-uninstaller.sh not found in assets!"; exit 1; }
# Navigate to mod_path
cd "$mod_path"
# Download required files
echo "Downloading required files..."
curl -OLf "https://github.com/artur-graniszewski/DLSS-Enabler/releases/download/$enablerver/dlss-enabler-setup-$enablerver.exe"
curl -OLf "https://download.nvidia.com/XFree86/Linux-x86_64/$nvidiaver/NVIDIA-Linux-x86_64-$nvidiaver.run"
curl -OLf "https://raw.githubusercontent.com/mozilla/fxc2/master/dll/d3dcompiler_47.dll"
curl -OLf "https://github.com/FakeMichau/innoextract/releases/download/6.3.0/innoextract"
curl -OLf "https://github.com/FakeMichau/fakenvapi/releases/download/$fakenvapiver/fakenvapi.7z"
# Validate downloads
echo "Validating downloaded files..."
required_files=(
"dlss-enabler-setup-$enablerver.exe"
"NVIDIA-Linux-x86_64-$nvidiaver.run"
"d3dcompiler_47.dll"
"innoextract"
"fakenvapi.7z"
)
for file in "${required_files[@]}"; do
if [[ ! -f $file ]]; then
echo "Error: Missing required file: $file"
exit 1
fi
done
# Extract and prepare files
echo "Extracting and preparing files..."
chmod +x NVIDIA-Linux-x86_64-$nvidiaver.run innoextract
./NVIDIA-Linux-x86_64-$nvidiaver.run -x
./innoextract dlss-enabler-setup-$enablerver.exe
mv app/* . || true
rm -r app || true
if command -v 7z &>/dev/null; then
7z -y x fakenvapi.7z
fi
cp -f NVIDIA-Linux-x86_64-$nvidiaver/nvngx.dll _nvngx.dll
cp -f NVIDIA-Linux-x86_64-$nvidiaver/LICENSE "licenses/LICENSE (NVIDIA driver)"
chmod +r _nvngx.dll
# Cleanup unnecessary files
echo "Cleaning up temporary files..."
rm -rf innoextract NVIDIA-Linux-x86_64-$nvidiaver dlss-enabler-setup-$enablerver.exe \
NVIDIA-Linux-x86_64-$nvidiaver.run fakenvapi.7z
# Update script paths
sed -i "s|mod_path=\"/usr/share/fgmod\"|mod_path=\"$mod_path\"|g" "$mod_path/fgmod" "$mod_path/fgmod-uninstaller.sh"
chmod +x "$mod_path/fgmod" "$mod_path/fgmod-uninstaller.sh"
# Handle Flatpak Steam
if flatpak list | grep -q "com.valvesoftware.Steam"; then
echo "Flatpak version of Steam detected. Granting access to $mod_path."
flatpak override --user --filesystem="$mod_path" com.valvesoftware.Steam
echo "Please restart Steam for changes to take effect."
fi
echo "All done!"
echo "For Steam, add this to the launch options: \"$mod_path/fgmod\" %COMMAND%"
echo "For Heroic, add this as a new wrapper: \"$mod_path/fgmod\""
"""
try:
process = subprocess.run(script, shell=True, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
return {"status": "success", "output": process.stdout}
except subprocess.CalledProcessError as e:
return {"status": "error", "message": e.stderr}
async def _main(self):
decky.logger.info("Plugin loaded.")
async def _unload(self):
decky.logger.info("Plugin unloaded.")
|