summaryrefslogtreecommitdiff
path: root/defaults
diff options
context:
space:
mode:
Diffstat (limited to 'defaults')
-rwxr-xr-xdefaults/assets/fgmod-uninstaller.sh54
-rwxr-xr-xdefaults/assets/fgmod.sh112
-rw-r--r--defaults/assets/update-optiscaler-config.py110
3 files changed, 224 insertions, 52 deletions
diff --git a/defaults/assets/fgmod-uninstaller.sh b/defaults/assets/fgmod-uninstaller.sh
index 38abcf4..5e5143c 100755
--- a/defaults/assets/fgmod-uninstaller.sh
+++ b/defaults/assets/fgmod-uninstaller.sh
@@ -4,13 +4,13 @@ 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" || echo "Zenity failed to display error"
fi
- logger -t fgmod-uninstaller "โŒ ERROR: $1"
+ logger -t fgmod-uninstaller "ERROR: $1"
exit 1
}
@@ -101,66 +101,78 @@ cd "$exe_folder_path" || error_exit "Failed to change directory to $exe_folder_p
# Verify current directory before proceeding
[[ "$(pwd)" != "$exe_folder_path" ]] && error_exit "Unexpected working directory: $(pwd)"
-logger -t fgmod-uninstaller "๐ŸŸข Uninstalling from: $exe_folder_path"
+logger -t fgmod-uninstaller "Uninstalling from: $exe_folder_path"
# === Remove OptiScaler Files ===
-echo "๐Ÿงน Removing 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..."
+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"
# === Remove Supporting Libraries ===
-echo "๐Ÿงน Removing supporting libraries..."
-rm -f "libxess.dll" "libxess_dx11.dll" "libxess_fg.dll" "libxell.dll" "nvngx.dll" "nvngx.ini"
-rm -f "amd_fidelityfx_dx12.dll" "amd_fidelityfx_framegeneration_dx12.dll" "amd_fidelityfx_upscaler_dx12.dll" "amd_fidelityfx_vk.dll"
+echo " Removing supporting libraries..."
+rm -f "nvngx.dll" "nvngx.ini"
+# Only remove files if backups exist (to avoid removing restored originals)
+[[ -f "libxess.dll.b" ]] && rm -f "libxess.dll"
+[[ -f "libxess_dx11.dll.b" ]] && rm -f "libxess_dx11.dll"
+[[ -f "libxess_fg.dll.b" ]] && rm -f "libxess_fg.dll"
+[[ -f "libxell.dll.b" ]] && rm -f "libxell.dll"
+[[ -f "amd_fidelityfx_dx12.dll.b" ]] && rm -f "amd_fidelityfx_dx12.dll"
+[[ -f "amd_fidelityfx_framegeneration_dx12.dll.b" ]] && rm -f "amd_fidelityfx_framegeneration_dx12.dll"
+[[ -f "amd_fidelityfx_upscaler_dx12.dll.b" ]] && rm -f "amd_fidelityfx_upscaler_dx12.dll"
+[[ -f "amd_fidelityfx_vk.dll.b" ]] && rm -f "amd_fidelityfx_vk.dll"
# === Remove FG Mod Files ===
-echo "๐Ÿงน Removing frame generation mod files..."
+echo " Removing frame generation mod files..."
rm -f "dlssg_to_fsr3_amd_is_better.dll" "dlssg_to_fsr3.ini"
# === Remove NVAPI Files (Current and Legacy) ===
-echo "๐Ÿงน Removing NVAPI files..."
-rm -f "fakenvapi.dll" "fakenvapi.ini" # Current v0.9.0-pre4 approach
+echo " Removing NVAPI files..."
+rm -f "fakenvapi.dll" "fakenvapi.ini" # v0.9.0-final
rm -f "nvapi64.dll" "nvapi64.dll.b" # Legacy cleanup for older versions and backups
# === Remove ASI Plugins ===
-echo "๐Ÿงน Removing ASI plugins directory..."
+echo " Removing ASI plugins directory..."
rm -rf "plugins"
+# === Remove D3D12_Optiscaler directory (required by v0.9.0-final) ===
+rm -rf "D3D12_Optiscaler"
+
# === Remove Legacy Files ===
-echo "๐Ÿงน Removing 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..."
+echo " Restoring original DLLs..."
original_dlls=("d3dcompiler_47.dll" "amd_fidelityfx_dx12.dll" "amd_fidelityfx_framegeneration_dx12.dll" "amd_fidelityfx_upscaler_dx12.dll" "amd_fidelityfx_vk.dll" "libxess.dll" "libxess_dx11.dll" "libxess_fg.dll" "libxell.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"
+ echo " Restored original $dll"
+ logger -t fgmod-uninstaller "Restored original $dll"
fi
done
# === Self-remove uninstaller ===
-echo "๐Ÿ—‘๏ธ Removing uninstaller..."
+echo " Removing uninstaller..."
rm -f "fgmod-uninstaller.sh"
-echo "โœ… fgmod removed from this game successfully!"
-logger -t fgmod-uninstaller "โœ… fgmod removed from $exe_folder_path"
+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 >/dev/null 2>&1
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 d48856d..decb981 100755
--- a/defaults/assets/fgmod.sh
+++ b/defaults/assets/fgmod.sh
@@ -4,13 +4,13 @@ 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" || echo "Zenity failed to display error"
fi
- logger -t fgmod "โŒ ERROR: $1"
+ logger -t fgmod "ERROR: $1"
exit 1
}
@@ -68,7 +68,7 @@ for arg in "$@"; do
fi
# Extract executable path from YAML
- exe_path=$(grep -E '^\s*exe:' "$config_file" | sed 's/.*exe:[[:space:]]*//')
+ exe_path=$(grep -E '^\s*exe:' "$config_file" | sed 's/.*exe:[[:space:]]*//' )
if [[ -n "$exe_path" ]]; then
exe_folder_path=$(dirname "$exe_path")
@@ -89,12 +89,12 @@ if [[ -d "$exe_folder_path/Engine" ]]; then
exe_folder_path=$(dirname "$ue_exe")
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!"
+[[ ! -d "$exe_folder_path" ]] && error_exit " Could not resolve game directory!"
+[[ ! -w "$exe_folder_path" ]] && error_exit " No write permission to the game folder!"
-logger -t fgmod "๐ŸŸข Target directory: $exe_folder_path"
-logger -t fgmod "๐Ÿงฉ Using DLL name: $dll_name"
-logger -t fgmod "๐Ÿ“„ Preserve INI: $preserve_ini"
+logger -t fgmod "Target directory: $exe_folder_path"
+logger -t fgmod "Using DLL name: $dll_name"
+logger -t fgmod "Preserve INI: $preserve_ini"
# === Cleanup Old Injectors ===
rm -f "$exe_folder_path"/{dxgi.dll,winmm.dll,nvngx.dll,_nvngx.dll,nvngx-wrapper.dll,dlss-enabler.dll,OptiScaler.dll}
@@ -107,34 +107,71 @@ done
# === Remove nvapi64.dll and its backup (conflicts from previous fakenvapi versions) ===
rm -f "$exe_folder_path/nvapi64.dll" "$exe_folder_path/nvapi64.dll.b"
-echo "๐Ÿงน Cleaned up nvapi64.dll and backup (legacy fakenvapi conflicts)"
+echo " Cleaned up nvapi64.dll and backup (legacy fakenvapi conflicts)"
# === 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"
+ 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"
+ 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
# === 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"
+ 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"
+ 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
+# === OptiScaler env variables Handling ===
+if [[ -f "$fgmod_path/update-optiscaler-config.py" ]]; then
+ python "$fgmod_path/update-optiscaler-config.py" "$exe_folder_path/OptiScaler.ini"
+fi
+
+# OptiScaler 0.9.0-pre11 can assert on Proton when HQ font auto mode tries to load
+# an external TTF that is not present. Only normalize the default auto value.
+sed -i 's/^UseHQFont[[:space:]]*=[[:space:]]*auto$/UseHQFont=false/' "$exe_folder_path/OptiScaler.ini" || true
+
+# === Migrate FGType โ†’ FGInput/FGOutput (pre-v0.9-final INIs) ===
+# v0.9-final split the single FGType key into FGInput + FGOutput. Games that were
+# patched with an older build will have FGType=<value> with no FGInput/FGOutput,
+# causing the new DLL to silently use nofg. Fix that here on every launch.
+_fgtype_ini="$exe_folder_path/OptiScaler.ini"
+if grep -q '^FGType=' "$_fgtype_ini" 2>/dev/null; then
+ _fgtype_val=$(sed -n 's/^FGType=\(.*\)/\1/p' "$_fgtype_ini")
+ echo " Migrating FGType=$_fgtype_val โ†’ FGInput/FGOutput in OptiScaler.ini"
+ logger -t fgmod "Migrating FGType=$_fgtype_val โ†’ FGInput/FGOutput"
+ if grep -q '^FGInput=' "$_fgtype_ini"; then
+ # FGInput already present โ€” INI already in v0.9-final format; just drop FGType
+ sed -i '/^FGType=/d' "$_fgtype_ini" || true
+ else
+ # Replace FGType=X with FGInput=X + FGOutput=X
+ sed -i "s/^FGType=.*$/FGInput=$_fgtype_val\nFGOutput=$_fgtype_val/" "$_fgtype_ini" || true
+ fi
+fi
+unset _fgtype_ini _fgtype_val
+
# === ASI Plugins Directory ===
if [[ -d "$fgmod_path/plugins" ]]; then
- echo "๐Ÿ”Œ Installing ASI plugins directory"
+ echo " Installing ASI plugins directory"
cp -r "$fgmod_path/plugins" "$exe_folder_path/" || true
- logger -t fgmod "๐Ÿ”Œ ASI plugins directory installed to $exe_folder_path"
+ logger -t fgmod "ASI plugins directory installed to $exe_folder_path"
else
- echo "โš ๏ธ No plugins directory found in fgmod"
+ echo " No plugins directory found in fgmod"
+fi
+
+# === D3D12_Optiscaler Directory (required for FSR4/FidelityFX DX12 path) ===
+if [[ -d "$fgmod_path/D3D12_Optiscaler" ]]; then
+ echo " Installing D3D12_Optiscaler directory"
+ cp -r "$fgmod_path/D3D12_Optiscaler" "$exe_folder_path/" || true
+ logger -t fgmod "D3D12_Optiscaler directory installed to $exe_folder_path"
+else
+ echo " No D3D12_Optiscaler directory found in fgmod"
fi
# === Supporting Libraries ===
@@ -150,27 +187,27 @@ cp -f "$fgmod_path/nvngx.dll" "$exe_folder_path/" || true
# === Nukem FG Mod Files (now in fgmod directory) ===
cp -f "$fgmod_path/dlssg_to_fsr3_amd_is_better.dll" "$exe_folder_path/" || true
-# Note: dlssg_to_fsr3.ini is not included in v0.9.0-pre4 archive
+# Note: dlssg_to_fsr3.ini is not included in v0.9.0-final archive
# === FakeNVAPI Files ===
# Remove legacy nvapi64.dll to avoid conflicts
# rm -f "$exe_folder_path/nvapi64.dll"
-# echo "๐Ÿงน Removed legacy nvapi64.dll"
+# echo " Removed legacy nvapi64.dll"
# Copy fakenvapi.dll with original name (v1.3.8.1)
cp -f "$fgmod_path/fakenvapi.dll" "$exe_folder_path/" || true
cp -f "$fgmod_path/fakenvapi.ini" "$exe_folder_path/" || true
-echo "๐Ÿ“ฆ Installed fakenvapi.dll and fakenvapi.ini"
+echo " Installed fakenvapi.dll and fakenvapi.ini"
# === Additional Support Files ===
# cp -f "$fgmod_path/d3dcompiler_47.dll" "$exe_folder_path/" || true
-# Note: d3dcompiler_47.dll is not included in v0.9.0-pre4 archive
+# Note: d3dcompiler_47.dll is not included in v0.9.0-final archive
-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"
+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
@@ -186,8 +223,21 @@ if [[ $# -gt 1 ]]; then
# Execute the original command
export SteamDeck=0
- export WINEDLLOVERRIDES="$WINEDLLOVERRIDES,dxgi=n,b"
- exec "$@"
+ # Build WINEDLLOVERRIDES from the actual proxy DLL name (strip extension to get the stem)
+ if [[ "$dll_name" == *.dll ]]; then
+ _wine_dll="${dll_name%.dll}"
+ export WINEDLLOVERRIDES="$WINEDLLOVERRIDES,${_wine_dll}=n,b"
+ unset _wine_dll
+ fi
+ # .asi files are loaded by an ASI loader โ€” no WINEDLLOVERRIDES entry needed
+
+ # Filter out leading -- separators (from Steam launch options)
+ while [[ $# -gt 0 && "$1" == "--" ]]; do
+ shift
+ done
+
+ exec >/dev/null 2>&1
+ "$@"
else
echo "Done!"
echo "----------------------------------------"
diff --git a/defaults/assets/update-optiscaler-config.py b/defaults/assets/update-optiscaler-config.py
new file mode 100644
index 0000000..f4a65de
--- /dev/null
+++ b/defaults/assets/update-optiscaler-config.py
@@ -0,0 +1,110 @@
+import os
+import sys
+import re
+from configparser import ConfigParser
+
+def update_optiscaler_config(file_path):
+ if not os.path.exists(file_path):
+ print(f"Error: File '{file_path}' not found.")
+ return
+
+ with open(file_path, 'r') as f:
+ lines = f.readlines()
+
+ config = ConfigParser()
+ config.optionxform = str # Preserve case for keys (otherwise PATH could match Path)
+ config.read(file_path)
+
+ # Because we want to support unprefixed env variables, we need to count key occurrences across all sections of the ini file
+ # Keys that appear multiple times should be prefixed like Section_Key by the user for them to be targeted properly
+
+ # Normalize section names: strip - and . so V-Sync becomes VSync
+ # This allows env vars like VSync_Key to match INI section [V-Sync]
+ def normalize_section(section_name):
+ return section_name.replace('-', '').replace('.', '')
+
+ key_occurrences = {}
+ key_to_sections = {}
+ section_normalized_to_actual = {} # Maps normalized section name to actual section name
+
+ for section in config.sections():
+ normalized = normalize_section(section)
+ section_normalized_to_actual[normalized] = section
+
+ for key in config.options(section):
+ key_occurrences[key] = key_occurrences.get(key, 0) + 1
+ if key not in key_to_sections:
+ key_to_sections[key] = []
+ key_to_sections[key].append(section)
+
+ env_updates = []
+
+ # Handle OptiScaler_Section_Key format
+ optiscaler_vars = {k: v for k, v in os.environ.items() if k.startswith("OptiScaler_")}
+ for env_name, env_value in optiscaler_vars.items():
+ parts = env_name.split('_', 2)
+ if len(parts) >= 3:
+ env_updates.append(('optiscaler', parts[1], parts[2], env_value, env_name))
+
+ # Handle Section_Key and Key formats
+ other_vars = {k: v for k, v in os.environ.items() if not k.startswith("OptiScaler_")}
+ for env_name, env_value in other_vars.items():
+ # Try Section_Key format
+ if '_' in env_name:
+ parts = env_name.split('_', 1)
+ section_from_env = parts[0]
+ key = parts[1]
+
+ # Try exact section match first
+ if config.has_section(section_from_env) and config.has_option(section_from_env, key):
+ env_updates.append(('section_key', section_from_env, key, env_value, env_name))
+ continue
+
+ # Try section match with normalized section names
+ if section_from_env in section_normalized_to_actual:
+ actual_section = section_normalized_to_actual[section_from_env]
+ if config.has_option(actual_section, key):
+ env_updates.append(('section_key', actual_section, key, env_value, env_name))
+ continue
+
+ # Try Key format (only if key appears exactly once across all sections)
+ if env_name in key_occurrences and key_occurrences[env_name] == 1:
+ section = key_to_sections[env_name][0]
+ env_updates.append(('key', section, env_name, env_value, env_name))
+
+ print(f"Found {len(env_updates)} updates to apply")
+ for entry in env_updates:
+ print(f"> {entry}")
+
+ for update_type, section_target, key_target, env_value, env_name in env_updates:
+ found_section = False
+
+ # Regex to match [Section] and Key=Value (case-sensitive)
+ section_pattern = re.compile(rf'^\s*\[{re.escape(section_target)}]\s*')
+ key_pattern = re.compile(rf'^(\s*{re.escape(key_target)}\s*)=.*')
+
+ for i, line in enumerate(lines):
+ # Track if we are inside the correct section
+ if section_pattern.match(line):
+ found_section = True
+ continue
+
+ # If we hit a new section before finding the key, the key doesn't exist in the target section
+ if found_section and line.strip().startswith('[') and not section_pattern.match(line):
+ break
+
+ # Replace the value if the key is found within the correct section
+ if found_section and key_pattern.match(line):
+ lines[i] = key_pattern.sub(r'\1=' + env_value, line)
+ print(f"Updated: [{section_target}] {key_target} = {env_value} (from {env_name})")
+ break
+
+ # Write the modified content back
+ with open(file_path, 'w') as f:
+ f.writelines(lines)
+
+if __name__ == "__main__":
+ if len(sys.argv) < 2:
+ print("Usage: python update-optiscaler-config.py <path_to_ini>")
+ else:
+ update_optiscaler_config(sys.argv[1]) \ No newline at end of file