diff options
| author | Kurt Himebauch <136133082+xXJSONDeruloXx@users.noreply.github.com> | 2025-07-17 00:28:42 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-07-17 00:28:42 -0400 |
| commit | 74ac6e7b7a18c2ae969b08242a5919f903d294e2 (patch) | |
| tree | e6d48b345c4933ea21a83ef6e2dc315ba9a990f3 | |
| parent | e905b94fe5b40b438f2ce63caad90760fea7fc9a (diff) | |
| download | Decky-Framegen-74ac6e7b7a18c2ae969b08242a5919f903d294e2.tar.gz Decky-Framegen-74ac6e7b7a18c2ae969b08242a5919f903d294e2.zip | |
v0.10.0 initial implementation of proper optiscaler nightly statically linked (#113)
* initial implementation of proper optiscaler nightly statically linked
* default ini to nukems on mod dir install
* description tweaks
| -rwxr-xr-x | defaults/assets/fgmod-uninstaller.sh | 95 | ||||
| -rwxr-xr-x | defaults/assets/fgmod.sh | 130 | ||||
| -rwxr-xr-x | defaults/assets/prepare.sh | 47 | ||||
| -rw-r--r-- | justfile | 11 | ||||
| -rw-r--r-- | main.py | 269 | ||||
| -rw-r--r-- | package.json | 108 | ||||
| -rw-r--r-- | plugin.json | 2 | ||||
| -rwxr-xr-x | src/index.tsx | 12 |
8 files changed, 359 insertions, 315 deletions
diff --git a/defaults/assets/fgmod-uninstaller.sh b/defaults/assets/fgmod-uninstaller.sh index dd5f198..93f279f 100755 --- a/defaults/assets/fgmod-uninstaller.sh +++ b/defaults/assets/fgmod-uninstaller.sh @@ -1,15 +1,16 @@ #!/usr/bin/env bash -set -x # Enable debugging -exec > >(tee -i /tmp/prepare.log) 2>&1 # Log output and errors +set -x +exec > >(tee -i /tmp/fgmod-uninstaller.log) 2>&1 error_exit() { - echo "$1" + echo "โ $1" if [[ -n $STEAM_ZENITY ]]; then $STEAM_ZENITY --error --text "$1" else - zenity --error --text "$1" + zenity --error --text "$1" || echo "Zenity failed to display error" fi + logger -t fgmod-uninstaller "โ ERROR: $1" exit 1 } @@ -18,10 +19,8 @@ if [ "$#" -lt 1 ]; then exit 1 fi -game_path="" -mod_path="/usr/share/fgmod" - -# Locate the game folder based on the first argument +# === Resolve Game Path === +exe_folder_path="" if [[ "$1" == *.exe ]]; then exe_folder_path=$(dirname "$1") else @@ -44,9 +43,7 @@ else fi # Fallback to STEAM_COMPAT_INSTALL_PATH when no path was found -if [[ ! -d $exe_folder_path ]] && [[ -n ${STEAM_COMPAT_INSTALL_PATH} ]]; then - exe_folder_path=${STEAM_COMPAT_INSTALL_PATH} -fi +[[ -z "$exe_folder_path" && -n "$STEAM_COMPAT_INSTALL_PATH" ]] && exe_folder_path="$STEAM_COMPAT_INSTALL_PATH" # Check for Unreal Engine game paths if [[ -d "$exe_folder_path/Engine" ]]; then @@ -55,51 +52,65 @@ if [[ -d "$exe_folder_path/Engine" ]]; then fi # Verify the game folder exists -if [[ ! -d $exe_folder_path ]]; then - error_exit "Unable to locate the game folder. Ensure the game is installed and the path is correct." -fi +[[ ! -d "$exe_folder_path" ]] && error_exit "Unable to locate the game folder: $exe_folder_path" # Avoid operating on the uninstaller's own directory script_dir=$(dirname "$(realpath "$0")") -if [[ "$(realpath "$exe_folder_path")" == "$script_dir" ]]; then - error_exit "The target directory matches the script's directory. Aborting to prevent accidental deletion." -fi +[[ "$(realpath "$exe_folder_path")" == "$script_dir" ]] && error_exit "The target directory matches the script's directory. Aborting to prevent accidental deletion." # Change to the game directory cd "$exe_folder_path" || error_exit "Failed to change directory to $exe_folder_path" # Verify current directory before proceeding -if [[ "$(pwd)" != "$exe_folder_path" ]]; then - error_exit "Unexpected working directory: $(pwd)" -fi - -# Log the resolved exe_folder_path for debugging -echo "Resolved exe_folder_path: $exe_folder_path" >> /tmp/fgmod-uninstaller.log - -# Perform uninstallation -rm -f "dlss-enabler.dll" "dxgi.dll" "nvngx-wrapper.dll" "_nvngx.dll" -rm -f "dlssg_to_fsr3_amd_is_better.dll" "dlssg_to_fsr3_amd_is_better-3.0.dll" -rm -f "dlss-enabler-upscaler.dll" "nvngx.ini" -rm -f "d3dcompiler_47.dll" "amd_fidelityfx_dx12.dll" "amd_fidelityfx_vk.dll" -rm -f "nvapi64.dll" "fakenvapi.ini" "OptiScaler.log" -rm -f "dlss-enabler.log" "dlssg_to_fsr3.log" "fakenvapi.log" - -# Restore original DLLs if they exist -mv -f "libxess.dll.b" "libxess.dll" 2>/dev/null # keeping this for legacy patched games to successfully revert changes with newer builds of plugin -mv -f "d3dcompiler_47.dll.b" "d3dcompiler_47.dll" 2>/dev/null -mv -f "amd_fidelityfx_dx12.dll.b" "amd_fidelityfx_dx12.dll" 2>/dev/null -mv -f "amd_fidelityfx_vk.dll.b" "amd_fidelityfx_vk.dll" 2>/dev/null +[[ "$(pwd)" != "$exe_folder_path" ]] && error_exit "Unexpected working directory: $(pwd)" + +logger -t fgmod-uninstaller "๐ข Uninstalling from: $exe_folder_path" + +# === Remove OptiScaler Files === +echo "๐งน Removing OptiScaler files..." +rm -f "OptiScaler.dll" "dxgi.dll" "winmm.dll" "dbghelp.dll" "version.dll" "wininet.dll" "winhttp.dll" "OptiScaler.asi" +rm -f "OptiScaler.ini" "OptiScaler.log" + +# === Remove Nukem FG Mod Files === +echo "๐งน Removing Nukem FG Mod files..." +rm -f "dlssg_to_fsr3_amd_is_better.dll" "dlssg_to_fsr3.ini" "dlssg_to_fsr3.log" +rm -f "nvapi64.dll" "fakenvapi.ini" "fakenvapi.log" +rm -f "amdxcffx64.dll" + +# === Remove Supporting Libraries === +echo "๐งน Removing supporting libraries..." +rm -f "libxess.dll" "nvngx.dll" "nvngx.ini" + +# === Remove Legacy Files === +echo "๐งน Removing legacy files..." +rm -f "dlss-enabler.dll" "dlss-enabler-upscaler.dll" "dlss-enabler.log" +rm -f "nvngx-wrapper.dll" "_nvngx.dll" +rm -f "dlssg_to_fsr3_amd_is_better-3.0.dll" + +# === Restore Original DLLs === +echo "๐ Restoring original DLLs..." +original_dlls=("d3dcompiler_47.dll" "amd_fidelityfx_dx12.dll" "amd_fidelityfx_vk.dll" "nvapi64.dll" "amdxcffx64.dll" "libxess.dll") +for dll in "${original_dlls[@]}"; do + if [[ -f "${dll}.b" ]]; then + mv "${dll}.b" "$dll" + echo "โ
Restored original $dll" + logger -t fgmod-uninstaller "โ
Restored original $dll" + fi +done -# Self-remove uninstaller (now optional for safety) -echo "Uninstaller self-removal skipped for safety. Remove manually if needed." +# === Self-remove uninstaller === +echo "๐๏ธ Removing uninstaller..." +rm -f "fgmod-uninstaller.sh" -echo "fgmod removed from this game." +echo "โ
fgmod removed from this game successfully!" +logger -t fgmod-uninstaller "โ
fgmod removed from $exe_folder_path" +# === Execute original command if provided === if [[ $# -gt 1 ]]; then - echo "Launching the game..." + echo "๐ Launching the game..." export SteamDeck=0 export WINEDLLOVERRIDES="${WINEDLLOVERRIDES},dxgi=n,b" exec "$@" else - echo "Uninstallation complete. No game specified to run." + echo "โ
Uninstallation complete. No game specified to run." fi
\ No newline at end of file diff --git a/defaults/assets/fgmod.sh b/defaults/assets/fgmod.sh index 026d546..134ded0 100755 --- a/defaults/assets/fgmod.sh +++ b/defaults/assets/fgmod.sh @@ -1,42 +1,41 @@ #!/usr/bin/env bash -set -x # Enable debugging -exec > >(tee -i /tmp/prepare.log) 2>&1 # Log output and errors +set -x +exec > >(tee -i /tmp/fgmod-install.log) 2>&1 error_exit() { - echo "$1" + echo "โ $1" if [[ -n $STEAM_ZENITY ]]; then $STEAM_ZENITY --error --text "$1" else - zenity --error --text "$1" + zenity --error --text "$1" || echo "Zenity failed to display error" fi + logger -t fgmod "โ ERROR: $1" exit 1 } -mod_path="/usr/share/fgmod" +# === CONFIG === +fgmod_path="$HOME/fgmod" +dll_name="${DLL:-dxgi.dll}" +preserve_ini="${PRESERVE_INI:-true}" -if [ "$#" -lt 1 ]; then - echo "Usage: $0 program [program_arguments...]" - exit 1 +# === Resolve Game Path === +if [[ "$#" -lt 1 ]]; then + error_exit "Usage: $0 program [program_arguments...]" fi -# One arg means the command is ran standalone +exe_folder_path="" if [[ $# -eq 1 ]]; then - if [[ "$1" == *.exe ]]; then - exe_folder_path=$(dirname "$1") - else - exe_folder_path=$1 - fi + [[ "$1" == *.exe ]] && exe_folder_path=$(dirname "$1") || exe_folder_path="$1" else for arg in "$@"; do if [[ "$arg" == *.exe ]]; then - # Special cases, only FG-supported games [[ "$arg" == *"Cyberpunk 2077"* ]] && arg=${arg//REDprelauncher.exe/bin/x64/Cyberpunk2077.exe} [[ "$arg" == *"Witcher 3"* ]] && arg=${arg//REDprelauncher.exe/bin/x64_dx12/witcher3.exe} [[ "$arg" == *"HITMAN 3"* ]] && arg=${arg//Launcher.exe/Retail/HITMAN3.exe} [[ "$arg" == *"HITMAN World of Assassination"* ]] && arg=${arg//Launcher.exe/Retail/HITMAN3.exe} - [[ "$arg" == *"SYNCED"* ]] && arg=${arg//Launcher\/sop_launcher.exe/SYNCED.exe} # UE with a launcher - [[ "$arg" == *"2KLauncher"* ]] && arg=${arg//2KLauncher\/LauncherPatcher.exe/DoesntMatter.exe} # 2K launcher games + [[ "$arg" == *"SYNCED"* ]] && arg=${arg//Launcher\/sop_launcher.exe/SYNCED.exe} + [[ "$arg" == *"2KLauncher"* ]] && arg=${arg//2KLauncher\/LauncherPatcher.exe/DoesntMatter.exe} [[ "$arg" == *"Warhammer 40,000 DARKTIDE"* ]] && arg=${arg//launcher\/Launcher.exe/binaries/Darktide.exe} [[ "$arg" == *"Warhammer Vermintide 2"* ]] && arg=${arg//launcher\/Launcher.exe/binaries_dx12/vermintide2_dx12.exe} [[ "$arg" == *"Satisfactory"* ]] && arg=${arg//FactoryGameSteam.exe/Engine/Binaries/Win64/FactoryGameSteam-Win64-Shipping.exe} @@ -46,65 +45,70 @@ else done fi -# Fallback to STEAM_COMPAT_INSTALL_PATH when no path was found -if [[ ! -d $exe_folder_path ]] && [[ -n ${STEAM_COMPAT_INSTALL_PATH} ]]; then - echo "Trying the path from STEAM_COMPAT_INSTALL_PATH" - exe_folder_path=${STEAM_COMPAT_INSTALL_PATH} -fi +[[ -z "$exe_folder_path" && -n "$STEAM_COMPAT_INSTALL_PATH" ]] && exe_folder_path="$STEAM_COMPAT_INSTALL_PATH" -# Check for UE games if [[ -d "$exe_folder_path/Engine" ]]; then - ue_exe_path=$(find "$exe_folder_path" -maxdepth 4 -mindepth 4 -path "*Binaries/Win64/*.exe" -not -path "*/Engine/*" | head -1) - exe_folder_path=$(dirname "$ue_exe_path") + ue_exe=$(find "$exe_folder_path" -maxdepth 4 -mindepth 4 -path "*Binaries/Win64/*.exe" -not -path "*/Engine/*" | head -1) + exe_folder_path=$(dirname "$ue_exe") fi -if [[ -d $exe_folder_path ]]; then - if [[ ! -w $exe_folder_path ]]; then - error_exit "No write permission to the game folder!" - fi +[[ ! -d "$exe_folder_path" ]] && error_exit "โ Could not resolve game directory!" +[[ ! -w "$exe_folder_path" ]] && error_exit "๐ No write permission to the game folder!" - original_dlls=("d3dcompiler_47.dll" "amd_fidelityfx_dx12.dll" "amd_fidelityfx_vk.dll") +logger -t fgmod "๐ข Target directory: $exe_folder_path" +logger -t fgmod "๐งฉ Using DLL name: $dll_name" +logger -t fgmod "๐ Preserve INI: $preserve_ini" - # Assume that the mod is not installed when dlss-enabler.dll is not present - if [[ ! -f "$exe_folder_path/dlss-enabler.dll" ]]; then - [[ -f "$exe_folder_path/dxgi.dll" ]] && error_exit 'dxgi.dll is already present in the game folder!\nThis script uses dxgi.dll to load required files.\nRemove the mod using dxgi.dll or install DLSS Enabler manually.' - for dll in "${original_dlls[@]}"; do - if [[ ! -f "$exe_folder_path/${dll}.b" ]]; then - mv -f "$exe_folder_path/$dll" "$exe_folder_path/${dll}.b" 2>/dev/null - fi - done - fi +# === Cleanup Old Injectors === +rm -f "$exe_folder_path"/{dxgi.dll,winmm.dll,nvngx.dll,_nvngx.dll,nvngx-wrapper.dll,dlss-enabler.dll,OptiScaler.dll} - cp -f "$mod_path/fgmod-uninstaller.sh" "$exe_folder_path" || - error_exit "Couldn't copy the uninstaller!" +# === Optional: Backup Original DLLs === +original_dlls=("d3dcompiler_47.dll" "amd_fidelityfx_dx12.dll" "amd_fidelityfx_vk.dll" "nvapi64.dll" "amdxcffx64.dll") +for dll in "${original_dlls[@]}"; do + [[ -f "$exe_folder_path/$dll" && ! -f "$exe_folder_path/$dll.b" ]] && mv -f "$exe_folder_path/$dll" "$exe_folder_path/$dll.b" +done - cp -f "$mod_path/dlss-enabler.dll" "$exe_folder_path" && - cp -f "$mod_path/dxgi.dll" "$exe_folder_path" && - cp -f "$mod_path/nvngx-wrapper.dll" "$exe_folder_path" || - error_exit "Couldn't copy DLSS Enabler files!" +# === Core Install === +if [[ -f "$fgmod_path/renames/$dll_name" ]]; then + echo "โ
Using pre-renamed $dll_name" + cp "$fgmod_path/renames/$dll_name" "$exe_folder_path/$dll_name" || error_exit "โ Failed to copy $dll_name" +else + echo "โ ๏ธ Pre-renamed $dll_name not found, falling back to OptiScaler.dll" + cp "$fgmod_path/OptiScaler.dll" "$exe_folder_path/$dll_name" || error_exit "โ Failed to copy OptiScaler.dll as $dll_name" +fi - # File is not preset on Nvidia installs so will fail on some setups on purpose - cp -f "$mod_path/nvapi64.dll" "$exe_folder_path" 2>/dev/null +# === OptiScaler.ini Handling === +if [[ "$preserve_ini" == "true" && -f "$exe_folder_path/OptiScaler.ini" ]]; then + echo "๐ Preserving existing OptiScaler.ini (user settings retained)" + logger -t fgmod "๐ Existing OptiScaler.ini preserved in $exe_folder_path" +else + echo "๐ Installing OptiScaler.ini from plugin defaults" + cp "$fgmod_path/OptiScaler.ini" "$exe_folder_path/OptiScaler.ini" || error_exit "โ Failed to copy OptiScaler.ini" + logger -t fgmod "๐ OptiScaler.ini installed to $exe_folder_path" +fi - cp -f "$mod_path/_nvngx.dll" "$exe_folder_path" || - error_exit "Couldn't copy _nvngx.dll!" +# === Supporting Libraries === +cp -f "$fgmod_path/libxess.dll" "$exe_folder_path/" || true +cp -f "$fgmod_path/amd_fidelityfx_dx12.dll" "$exe_folder_path/" || true +cp -f "$fgmod_path/amd_fidelityfx_vk.dll" "$exe_folder_path/" || true +cp -f "$fgmod_path/nvngx.dll" "$exe_folder_path/" || true - cp -f "$mod_path/dlssg_to_fsr3_amd_is_better.dll" "$exe_folder_path" && - cp -f "$mod_path/dlssg_to_fsr3_amd_is_better-3.0.dll" "$exe_folder_path" || - error_exit "Couldn't copy dlssg-to-fsr3!" +# === Nukem FG Mod Files (now in fgmod directory) === +cp -f "$fgmod_path/dlssg_to_fsr3_amd_is_better.dll" "$exe_folder_path/" || true +cp -f "$fgmod_path/dlssg_to_fsr3.ini" "$exe_folder_path/" || true +cp -f "$fgmod_path/nvapi64.dll" "$exe_folder_path/" || true +cp -f "$fgmod_path/fakenvapi.ini" "$exe_folder_path/" || true +cp -f "$fgmod_path/amdxcffx64.dll" "$exe_folder_path/" || true - cp -f "$mod_path/dlss-enabler-upscaler.dll" "$exe_folder_path" && - cp -f "$mod_path/amd_fidelityfx_dx12.dll" "$exe_folder_path" && - cp -f "$mod_path/amd_fidelityfx_vk.dll" "$exe_folder_path" && - cp -f "$mod_path/d3dcompiler_47.dll" "$exe_folder_path" || - error_exit "Couldn't copy Optiscaler files!" +# === Additional Support Files === +cp -f "$fgmod_path/d3dcompiler_47.dll" "$exe_folder_path/" || true - cp -n "$mod_path/nvngx.ini" "$exe_folder_path" - cp -n "$mod_path/fakenvapi.ini" "$exe_folder_path" -else - error_exit "Path doesn't exist!" -fi +echo "โ
Installation completed successfully!" +echo "๐ For Steam, add this to the launch options: \"$fgmod_path/fgmod\" %COMMAND%" +echo "๐ For Heroic, add this as a new wrapper: \"$fgmod_path/fgmod\"" +logger -t fgmod "๐ข Installation completed successfully for $exe_folder_path" +# === Execute original command === if [[ $# -gt 1 ]]; then # Log to both file and system journal logger -t fgmod "==================" @@ -119,7 +123,7 @@ if [[ $# -gt 1 ]]; then # Execute the original command export SteamDeck=0 export WINEDLLOVERRIDES="$WINEDLLOVERRIDES,dxgi=n,b" - "$@" + exec "$@" else echo "Done!" echo "----------------------------------------" diff --git a/defaults/assets/prepare.sh b/defaults/assets/prepare.sh deleted file mode 100755 index 65f92e1..0000000 --- a/defaults/assets/prepare.sh +++ /dev/null @@ -1,47 +0,0 @@ -#!/usr/bin/env bash - -set -x # Enable debugging -exec > >(tee -i /tmp/prepare.log) 2>&1 # Log output and errors - -mod_path="$HOME/fgmod" -bin_path="$(dirname "$(realpath "$0")")/../bin" -assets_path="$(dirname "$(realpath "$0")")" - -standalone=1 - -if [[ -d "$mod_path" ]] && [[ ! $mod_path == . ]]; then - rm -r "$mod_path" -fi - -mkdir -p "$mod_path" -cd "$mod_path" || exit 1 - -# Copy all files from bin directory into the current directory -cp "$bin_path"/* . - -# # Unzip assets.zip so that all files are in the modpath root, then remove the zip file -# unzip -j -o assets.zip && rm assets.zip - -# Copy fgmod.sh and fgmod-uninstaller.sh from defaults/assets -# cp "$assets_path/fgmod.sh" "$mod_path/fgmod" || exit 1 -# cp "$assets_path/fgmod-uninstaller.sh" "$mod_path" || exit 1 - -# Update paths in scripts -sed -i 's|mod_path="/usr/share/fgmod"|mod_path="'"$mod_path"'"|g' fgmod -chmod +x fgmod - -sed -i 's|mod_path="/usr/share/fgmod"|mod_path="'"$mod_path"'"|g' fgmod-uninstaller.sh -chmod +x fgmod-uninstaller.sh - -echo "" - -# Flatpak compatibility -if flatpak list | grep "com.valvesoftware.Steam" 1>/dev/null; then - echo "Flatpak version of Steam detected, adding access to fgmod's folder" - echo "Please restart Steam!" - flatpak override --user --filesystem="$mod_path" com.valvesoftware.Steam -fi - -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\"" -echo "All done!"
\ No newline at end of file diff --git a/justfile b/justfile new file mode 100644 index 0000000..07aa118 --- /dev/null +++ b/justfile @@ -0,0 +1,11 @@ +default: + echo "Available recipes: build, test, clean" + +build: + rm -rf node_modules && .vscode/build.sh + +test: + scp "/Users/kurt/Developer/FG-plugins/Decky-Framegen/out/Decky-Framegen.zip" deck@192.168.0.6:~/Desktop + +clean: + rm -rf node_modules dist
\ No newline at end of file @@ -2,6 +2,8 @@ import decky # Old-style Decky import import os import subprocess import json +import shutil +import re from pathlib import Path class Plugin: @@ -11,84 +13,240 @@ class Plugin: async def _unload(self): decky.logger.info("Framegen plugin unloaded.") - async def run_uninstall_fgmod(self) -> dict: + async def extract_static_optiscaler(self) -> dict: + """Extract OptiScaler from the plugin's bin directory.""" try: - result = subprocess.run( - ["/bin/bash", Path(decky.DECKY_PLUGIN_DIR) / "assets" / "fgmod-remover.sh"], + # Set up paths + bin_path = Path(decky.DECKY_PLUGIN_DIR) / "bin" + extract_path = Path(decky.HOME) / "fgmod" + + # Find the OptiScaler archive in the bin directory + optiscaler_archive = None + for file in bin_path.glob("*.7z"): + if "OptiScaler" in file.name: + optiscaler_archive = file + break + + if not optiscaler_archive: + return {"status": "error", "message": "OptiScaler archive not found in plugin bin directory"} + + # Clean up existing directory + if extract_path.exists(): + shutil.rmtree(extract_path) + + extract_path.mkdir(exist_ok=True) + + decky.logger.info(f"Extracting {optiscaler_archive.name} to {extract_path}") + + # Extract the 7z file + extract_cmd = [ + "7z", + "x", + "-y", + "-o" + str(extract_path), + str(optiscaler_archive) + ] + + extract_result = subprocess.run( + extract_cmd, capture_output=True, text=True, - check=True + check=False ) - return {"status": "success", "output": result.stdout} - except subprocess.CalledProcessError as e: - decky.logger.error(e.output) - return {"status": "error", "message": str(e), "output": e.output} - - async def run_install_fgmod(self) -> dict: - try: - assets_dir = Path(decky.DECKY_PLUGIN_DIR) / "assets" - prepare_script = assets_dir / "prepare.sh" - - if not prepare_script.exists(): - decky.logger.error(f"prepare.sh not found: {prepare_script}") + + if extract_result.returncode != 0: + decky.logger.error(f"Extraction failed: {extract_result.stderr}") return { "status": "error", - "message": f"prepare.sh not found in plugin assets." + "message": f"Failed to extract OptiScaler archive: {extract_result.stderr}" } + + # Create renamed copies of OptiScaler.dll + try: + renames_dir = extract_path / "renames" + renames_dir.mkdir(exist_ok=True) + + source_file = extract_path / "OptiScaler.dll" + + rename_files = [ + "dxgi.dll", + "winmm.dll", + "dbghelp.dll", + "version.dll", + "wininet.dll", + "winhttp.dll", + "OptiScaler.asi" + ] + + if source_file.exists(): + for rename_file in rename_files: + dest_file = renames_dir / rename_file + shutil.copy2(source_file, dest_file) + decky.logger.info(f"Created renamed copy: {dest_file}") + else: + decky.logger.error(f"Source file {source_file} does not exist") + + except Exception as e: + decky.logger.error(f"Failed to create renamed copies: {e}") + + # Copy launcher scripts from assets + try: + assets_dir = Path(decky.DECKY_PLUGIN_DIR) / "assets" + + # Copy fgmod script + fgmod_script_src = assets_dir / "fgmod.sh" + fgmod_script_dest = extract_path / "fgmod" + if fgmod_script_src.exists(): + shutil.copy2(fgmod_script_src, fgmod_script_dest) + fgmod_script_dest.chmod(0o755) + decky.logger.info(f"Copied fgmod script to {fgmod_script_dest}") + + # Copy uninstaller script + uninstaller_src = assets_dir / "fgmod-uninstaller.sh" + uninstaller_dest = extract_path / "fgmod-uninstaller.sh" + if uninstaller_src.exists(): + shutil.copy2(uninstaller_src, uninstaller_dest) + uninstaller_dest.chmod(0o755) + decky.logger.info(f"Copied uninstaller script to {uninstaller_dest}") + + except Exception as e: + decky.logger.error(f"Failed to copy launcher scripts: {e}") + + # Extract version from filename + version_match = optiscaler_archive.name.replace('.7z', '') + if '_v' in version_match: + version = 'v' + version_match.split('_v')[1] + else: + version = version_match + + # Create version file + version_file = extract_path / "version.txt" + try: + with open(version_file, 'w') as f: + f.write(version) + decky.logger.info(f"Created version file: {version}") + except Exception as e: + decky.logger.error(f"Failed to create version file: {e}") + + # Modify OptiScaler.ini to set FGType=nukems + try: + ini_file = extract_path / "OptiScaler.ini" + if ini_file.exists(): + with open(ini_file, 'r') as f: + content = f.read() + + # Replace FGType=auto with FGType=nukems + updated_content = re.sub(r'FGType\s*=\s*auto', 'FGType=nukems', content) + + with open(ini_file, 'w') as f: + f.write(updated_content) + + decky.logger.info("Modified OptiScaler.ini to set FGType=nukems") + else: + decky.logger.warning(f"OptiScaler.ini not found at {ini_file}") + except Exception as e: + decky.logger.error(f"Failed to modify OptiScaler.ini: {e}") + + return { + "status": "success", + "message": f"Successfully extracted OptiScaler {version} to ~/fgmod", + "version": version + } + + except Exception as e: + decky.logger.error(f"Extract failed: {str(e)}") + return {"status": "error", "message": f"Extract failed: {str(e)}"} - # Ensure prepare.sh has execution permissions - prepare_script.chmod(0o755) - - # Run prepare.sh directly from the plugin's assets folder - process = subprocess.run( - ["/bin/bash", str(prepare_script)], - cwd=str(assets_dir), # Run in assets directory to use correct paths - capture_output=True, - text=True, - timeout=300 - ) - - decky.logger.info(f"Script output:\n{process.stdout}") - decky.logger.error(f"Script errors:\n{process.stderr}") + async def run_uninstall_fgmod(self) -> dict: + try: + # Remove fgmod directory + fgmod_path = Path(decky.HOME) / "fgmod" + + if fgmod_path.exists(): + shutil.rmtree(fgmod_path) + decky.logger.info(f"Removed directory: {fgmod_path}") + return { + "status": "success", + "output": "Successfully removed fgmod directory" + } + else: + return { + "status": "success", + "output": "No fgmod directory found to remove" + } + + except Exception as e: + decky.logger.error(f"Uninstall error: {str(e)}") + return { + "status": "error", + "message": f"Uninstall failed: {str(e)}", + "output": str(e) + } - if "All done!" not in process.stdout: - decky.logger.error("Installation did not complete successfully") + async def run_install_fgmod(self) -> dict: + try: + decky.logger.info("Starting OptiScaler installation from static bundle") + + # Extract the static OptiScaler bundle + extract_result = await self.extract_static_optiscaler() + + if extract_result["status"] != "success": return { "status": "error", - "message": process.stdout + process.stderr + "message": f"OptiScaler extraction failed: {extract_result.get('message', 'Unknown error')}" } - + + # Handle Flatpak compatibility + try: + fgmod_path = Path(decky.HOME) / "fgmod" + + # Check if Flatpak Steam is installed + flatpak_check = subprocess.run( + ["flatpak", "list"], + capture_output=True, + text=True, + check=False + ) + + if flatpak_check.returncode == 0 and "com.valvesoftware.Steam" in flatpak_check.stdout: + decky.logger.info("Flatpak Steam detected, adding filesystem access") + + subprocess.run([ + "flatpak", "override", "--user", + f"--filesystem={fgmod_path}", + "com.valvesoftware.Steam" + ], check=False) + + decky.logger.info("Added Flatpak filesystem access") + + except Exception as e: + decky.logger.warning(f"Flatpak setup had issues (this is OK): {e}") + return { "status": "success", - "output": "You can now replace DLSS with FSR Frame Gen!" + "output": "Successfully installed OptiScaler with all necessary components! You can now replace DLSS with FSR Frame Gen!" } - except subprocess.TimeoutExpired: - decky.logger.error("Installation script timed out") - return { - "status": "error", - "message": "Installation timed out" - } - except subprocess.CalledProcessError as e: - decky.logger.error(f"Script error: {e.stderr}") - return { - "status": "error", - "message": e.stderr - } except Exception as e: - decky.logger.error(f"Unexpected error: {str(e)}") + decky.logger.error(f"Unexpected error during installation: {str(e)}") return { "status": "error", - "message": str(e) + "message": f"Installation failed: {str(e)}" } async def check_fgmod_path(self) -> dict: path = Path(decky.HOME) / "fgmod" required_files = [ - "amd_fidelityfx_dx12.dll", "amd_fidelityfx_vk.dll", "d3dcompiler_47.dll", "DisableNvidiaSignatureChecks.reg", - "dlss-enabler.dll", "dlss-enabler-upscaler.dll", "dlssg_to_fsr3_amd_is_better-3.0.dll", "dlssg_to_fsr3_amd_is_better.dll", - "dlssg_to_fsr3.ini", "dxgi.dll", "dxvk.conf", "fakenvapi.ini", "fgmod", "fgmod-uninstaller.sh", - "libxess.dll", "nvapi64.dll", "nvngx.ini", "nvngx-wrapper.dll", "_nvngx.dll", "RestoreNvidiaSignatureChecks.reg" + "OptiScaler.dll", + "dlssg_to_fsr3_amd_is_better.dll", + "fakenvapi.ini", + "nvapi64.dll", + "amdxcffx64.dll", + "amd_fidelityfx_dx12.dll", + "amd_fidelityfx_vk.dll", + "libxess.dll", + "fgmod", + "fgmod-uninstaller.sh" ] if path.exists(): @@ -103,6 +261,7 @@ class Plugin: try: steam_root = Path(decky.HOME) / ".steam" / "steam" library_file = Path(steam_root) / "steamapps" / "libraryfolders.vdf" + if not library_file.exists(): return {"status": "error", "message": "libraryfolders.vdf not found"} @@ -121,7 +280,7 @@ class Plugin: continue for appmanifest in steamapps_path.glob("appmanifest_*.acf"): - game_info = {"appid": None, "name": None} + game_info = {"appid": "", "name": ""} try: with open(appmanifest, "r", encoding="utf-8") as file: diff --git a/package.json b/package.json index 1d9c1d9..6d7f0d2 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "decky-framegen", - "version": "0.9.1", - "description": "plugin to swap DLSS with FSR, to enable upscaling and framegen in games without built in FSR.", + "version": "0.10.0", + "description": "plugin to install OptiScaler bleeding-edge and enable upscaling and framegen in a large variety of games.", "type": "module", "scripts": { "build": "rollup -c", @@ -49,108 +49,14 @@ ] } }, - "remote_binary_bundling" : false, + "remote_binary_bundling" : true, "remote_binary": [ { - "name": "DisableNvidiaSignatureChecks.reg", - "url": "https://github.com/xXJSONDeruloXx/Decky-Framegen/releases/download/binaries-DLSS-Enabler-3.02-Stable/DisableNvidiaSignatureChecks.reg", - "sha256hash": "0db810f38303fc82b6fbd0cebd7f073bf0271d3bc5f065b7584598c4eda670f7" - }, - { - "name": "RestoreNvidiaSignatureChecks.reg", - "url": "https://github.com/xXJSONDeruloXx/Decky-Framegen/releases/download/binaries-DLSS-Enabler-3.02-Stable/RestoreNvidiaSignatureChecks.reg", - "sha256hash": "c096400b3106fcab37ac98fd33f8c7483af0f85b118d16133ee268aa122ddc68" - }, - { - "name": "_nvngx.dll", - "url": "https://github.com/xXJSONDeruloXx/Decky-Framegen/releases/download/binaries-DLSS-Enabler-3.02-Stable/_nvngx.dll", - "sha256hash": "52a68acc4e477eeff598b5ca01f26215dc5aa487c8f150b02c27ad099c11de0b" - }, - { - "name": "amd_fidelityfx_dx12.dll", - "url": "https://github.com/xXJSONDeruloXx/Decky-Framegen/releases/download/binaries-DLSS-Enabler-3.02-Stable/amd_fidelityfx_dx12.dll", - "sha256hash": "77809405a0ff464b63654f1264f0ec0fcf8f243dac7c15b5f5c032615520d143" - }, - { - "name": "amd_fidelityfx_vk.dll", - "url": "https://github.com/xXJSONDeruloXx/Decky-Framegen/releases/download/binaries-DLSS-Enabler-3.02-Stable/amd_fidelityfx_vk.dll", - "sha256hash": "29d6c8c5088f6442f915d4b895dfffe09a2b5f0f1d36ab46b59d6b08c8a37b05" - }, - { - "name": "d3dcompiler_47.dll", - "url": "https://github.com/xXJSONDeruloXx/Decky-Framegen/releases/download/binaries-DLSS-Enabler-3.02-Stable/d3dcompiler_47.dll", - "sha256hash": "4432bbd1a390874f3f0a503d45cc48d346abc3a8c0213c289f4b615bf0ee84f3" - }, - { - "name": "dlss-enabler-upscaler.dll", - "url": "https://github.com/xXJSONDeruloXx/Decky-Framegen/releases/download/binaries-DLSS-Enabler-3.02-Stable/dlss-enabler-upscaler.dll", - "sha256hash": "9449350177f64b9be5a97440417b4c8c4b5c648a4ab41b057cad17134fe4b401" - }, - { - "name": "dlss-enabler.dll", - "url": "https://github.com/xXJSONDeruloXx/Decky-Framegen/releases/download/binaries-DLSS-Enabler-3.02-Stable/dlss-enabler.dll", - "sha256hash": "00a880facebf5380cd9630f259fc28dd5e6f17875cdced958a2c3e38bed51b4e" - }, - { - "name": "dlssg_to_fsr3.ini", - "url": "https://github.com/xXJSONDeruloXx/Decky-Framegen/releases/download/binaries-DLSS-Enabler-3.02-Stable/dlssg_to_fsr3.ini", - "sha256hash": "30bd3c459e4db2159db0fd5f22d42a049153bab86ece7fad2febef145181ecbf" - }, - { - "name": "dlssg_to_fsr3_amd_is_better-3.0.dll", - "url": "https://github.com/xXJSONDeruloXx/Decky-Framegen/releases/download/binaries-DLSS-Enabler-3.02-Stable/dlssg_to_fsr3_amd_is_better-3.0.dll", - "sha256hash": "ce794bd6489068bd316e38aceb6db323766a2172ecada0e868913526c8c06ab0" - }, - { - "name": "dlssg_to_fsr3_amd_is_better.dll", - "url": "https://github.com/xXJSONDeruloXx/Decky-Framegen/releases/download/binaries-DLSS-Enabler-3.02-Stable/dlssg_to_fsr3_amd_is_better.dll", - "sha256hash": "bc0255ca9de9fe760fec38d91a6793b4ceb45684385a5085306edb8e74ae174d" - }, - { - "name": "dxgi.dll", - "url": "https://github.com/xXJSONDeruloXx/Decky-Framegen/releases/download/binaries-DLSS-Enabler-3.02-Stable/dxgi.dll", - "sha256hash": "9ae73670c5dbb80f40d98176cb4426992f0cb0b9d0143b1d8083838d03b7d6fc" - }, - { - "name": "dxvk.conf", - "url": "https://github.com/xXJSONDeruloXx/Decky-Framegen/releases/download/binaries-DLSS-Enabler-3.02-Stable/dxvk.conf", - "sha256hash": "fb4b28b38fa5d36e95f76498416f7875815e94d2914878b70599cd6d87a98e12" - }, - { - "name": "fakenvapi.ini", - "url": "https://github.com/xXJSONDeruloXx/Decky-Framegen/releases/download/binaries-DLSS-Enabler-3.02-Stable/fakenvapi.ini", - "sha256hash": "672d65665cddb21a10b525daa987179871ddf97f328861a3e4b6a76671457e28" - }, - { - "name": "fgmod", - "url": "https://github.com/xXJSONDeruloXx/Decky-Framegen/releases/download/binaries-DLSS-Enabler-3.02-Stable/fgmod", - "sha256hash": "70bcf240e160cf5f75f861e40032cbc788889fd81bf3ca836466b8be1e561d58" - }, - { - "name": "libxess.dll", - "url": "https://github.com/xXJSONDeruloXx/Decky-Framegen/releases/download/binaries-DLSS-Enabler-3.02-Stable/libxess.dll", - "sha256hash": "703ab8debc05ae209f6e4622cc06edf9f95a241f7ce68ee75c8955564d36ad70" - }, - { - "name": "nvapi64.dll", - "url": "https://github.com/xXJSONDeruloXx/Decky-Framegen/releases/download/binaries-DLSS-Enabler-3.02-Stable/nvapi64.dll", - "sha256hash": "8c9d602442d291a6c51db7cdd9f79a0617de5742af42a56fcb918e4f9ca3ba52" - }, - { - "name": "nvngx-wrapper.dll", - "url": "https://github.com/xXJSONDeruloXx/Decky-Framegen/releases/download/binaries-DLSS-Enabler-3.02-Stable/nvngx-wrapper.dll", - "sha256hash": "6bb7f36f7dc3fffd588f2c6d2341c13f2a690ade0a7ef6c74ccdb2387cd5952e" - }, - { - "name": "nvngx.ini", - "url": "https://github.com/xXJSONDeruloXx/Decky-Framegen/releases/download/binaries-DLSS-Enabler-3.02-Stable/nvngx.ini", - "sha256hash": "3e083428c87054235aedb61cb4cc5afa1716a540146b978ddcd3ce2d590292a8" - }, - { - "name": "fgmod-uninstaller.sh", - "url": "https://github.com/xXJSONDeruloXx/Decky-Framegen/releases/download/binaries-DLSS-Enabler-3.02-Stable/fgmod-uninstaller.sh", - "sha256hash": "6a61ee21f587ad1976522a36adfa610140f2b486fbc812ca334b55ce50fcd395" + "sha256hash": "e902c99be8a2501fac8ba636f79ed681964367a104e7e2e441d4bf4f894b2879", + "name": "BUNDLED_OptiScaler_v0.7.7-pre12_20250702.7z", + "url": "https://github.com/xXJSONDeruloXx/OptiScaler-Bleeding-Edge/releases/download/OptiScaler_v0.7.7-pre12_20250702_unsigned_dll-20250704-021155/BUNDLED_OptiScaler_v0.7.7-pre12_20250702.7z", + "size": 60721676 } ] } diff --git a/plugin.json b/plugin.json index 426f835..125d5ad 100644 --- a/plugin.json +++ b/plugin.json @@ -5,7 +5,7 @@ "api_version": 1, "publish": { "tags": ["DLSS", "Framegen","upscaling","FSR"], - "description": "Allows using FSR for upscaling and frame generation in games with DLSS support. Uses DLSS Enabler and Optiscaler.", + "description": "Allows using FSR for upscaling and frame generation in games with DLSS support. Uses the latest OptiScaler bleeding-edge build with static linking.", "image": "https://raw.githubusercontent.com/xXJSONDeruloXx/Decky-Framegen/main/assets/decky_framegen.jpeg" } } diff --git a/src/index.tsx b/src/index.tsx index eeb95ea..64dabdb 100755 --- a/src/index.tsx +++ b/src/index.tsx @@ -111,21 +111,21 @@ function FGModInstallerSection() { {pathExists !== null ? ( <PanelSectionRow> <div style={{ color: pathExists ? "green" : "red" }}> - {pathExists ? "Mod Is Installed" : "Mod Not Installed"} + {pathExists ? "OptiScaler Mod Is Installed" : "OptiScaler Mod Not Installed"} </div> </PanelSectionRow> ) : null} {pathExists === false ? ( <PanelSectionRow> <ButtonItem layout="below" onClick={handleInstallClick} disabled={installing}> - {installing ? "Installing..." : "Install FG Mod"} + {installing ? "Installing..." : "Install OptiScaler FG Mod"} </ButtonItem> </PanelSectionRow> ) : null} {pathExists === true ? ( <PanelSectionRow> <ButtonItem layout="below" onClick={handleUninstallClick} disabled={uninstalling}> - {uninstalling ? "Uninstalling..." : "Uninstall FG Mod"} + {uninstalling ? "Uninstalling..." : "Uninstall OptiScaler FG Mod"} </ButtonItem> </PanelSectionRow> ) : null} @@ -171,7 +171,7 @@ function FGModInstallerSection() { ) : null} <PanelSectionRow> <div> - Install the mod above, then select and patch a game below to enable DLSS in the game's menu. + Install the OptiScaler-based mod above, then select and patch a game below to enable DLSS replacement with FSR Frame Generation. Map a button to "insert" key to bring up the OptiScaler menu in-game. </div> </PanelSectionRow> </PanelSection> @@ -222,7 +222,7 @@ function InstalledGamesSection() { onOK={async () => { try { await SteamClient.Apps.SetAppLaunchOptions(selectedGame.appid, '~/fgmod/fgmod %COMMAND%'); - setResult(`Launch options set for ${selectedGame.name}. You can now select DLSS in the game's menu.`); + setResult(`Launch options set for ${selectedGame.name}. You can now select DLSS in the game's menu, and access OptiScaler with Insert key.`); } catch (error) { logError('handlePatchClick: ' + String(error)); setResult(error instanceof Error ? `Error setting launch options: ${error.message}` : 'Error setting launch options'); @@ -237,7 +237,7 @@ function InstalledGamesSection() { try { await SteamClient.Apps.SetAppLaunchOptions(selectedGame.appid, '~/fgmod/fgmod-uninstaller.sh %COMMAND%'); - setResult(`DLSS mods will uninstall on next launch of ${selectedGame.name}.`); + setResult(`OptiScaler will uninstall on next launch of ${selectedGame.name}.`); } catch (error) { logError('handleUnpatchClick: ' + String(error)); setResult(error instanceof Error ? `Error clearing launch options: ${error.message}` : 'Error clearing launch options'); |
