From d1ce48eba2a38909f33df965ab672249156dc47d Mon Sep 17 00:00:00 2001 From: xXJSONDeruloXx Date: Fri, 3 Apr 2026 09:43:16 -0400 Subject: =?UTF-8?q?fix:=20migrate=20per-game=20FGType=20=E2=86=92=20FGInpu?= =?UTF-8?q?t/FGOutput=20on=20patch=20and=20launch?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Already-patched games have OptiScaler.ini entries using the old FGType key (e.g. FGType=nukems). The v0.9-final DLL no longer recognises FGType and silently falls back to nofg, breaking frame gen without any error. Add _migrate_optiscaler_ini() in main.py which: - detects FGType= in a per-game INI - if FGInput is absent: replaces the single FGType line with both FGInput= and FGOutput= - if FGInput is already present (INI already migrated): just drops the stale FGType line - is a no-op when FGType is not present (fresh installs, already migrated) Call the migration from _manual_patch_directory_impl immediately before _disable_hq_font_auto so any re-patch via the GUI heals the INI. Mirror the same logic in fgmod.sh so that games using the launch wrapper are migrated automatically on the very next launch, with no manual re-patch required. --- defaults/assets/fgmod.sh | 19 +++++++++++++++++++ main.py | 45 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/defaults/assets/fgmod.sh b/defaults/assets/fgmod.sh index cffce14..efc1d59 100755 --- a/defaults/assets/fgmod.sh +++ b/defaults/assets/fgmod.sh @@ -137,6 +137,25 @@ fi # 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= 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" diff --git a/main.py b/main.py index 3d63849..4092ab0 100644 --- a/main.py +++ b/main.py @@ -128,6 +128,50 @@ class Plugin: decky.logger.error(f"Failed to copy launcher scripts: {e}") return False + def _migrate_optiscaler_ini(self, ini_file): + """Migrate pre-v0.9-final OptiScaler.ini: replace FGType with FGInput + FGOutput. + + v0.9-final split the single FGType key into separate FGInput and FGOutput keys. + Games already patched with an older build will have FGType= in their + per-game INI but no FGInput/FGOutput entries, causing the new DLL to silently + fall back to nofg. This migration runs at patch-time and at every fgmod.sh + launch so users never have to manually touch their INI. + """ + try: + if not ini_file.exists(): + return False + + with open(ini_file, 'r') as f: + content = f.read() + + fg_type_match = re.search(r'^FGType\s*=\s*(\S+)', content, re.MULTILINE) + if not fg_type_match: + return True # Nothing to migrate + + fg_value = fg_type_match.group(1) + + if re.search(r'^FGInput\s*=', content, re.MULTILINE): + # FGInput already present (INI already in v0.9-final format); + # just remove the now-unknown FGType line. + content = re.sub(r'^FGType\s*=\s*\S+\n?', '', content, flags=re.MULTILINE) + decky.logger.info(f"Removed stale FGType from {ini_file} (FGInput already present)") + else: + # Replace the single FGType=X line with FGInput=X then FGOutput=X + content = re.sub( + r'^FGType\s*=\s*\S+', + f'FGInput={fg_value}\nFGOutput={fg_value}', + content, + flags=re.MULTILINE + ) + decky.logger.info(f"Migrated FGType={fg_value} → FGInput={fg_value}, FGOutput={fg_value} in {ini_file}") + + with open(ini_file, 'w') as f: + f.write(content) + return True + except Exception as e: + decky.logger.error(f"Failed to migrate OptiScaler.ini: {e}") + return False + def _disable_hq_font_auto(self, ini_file): """Disable the new HQ font auto mode to avoid missing font assertions on Wine/Proton.""" try: @@ -542,6 +586,7 @@ class Plugin: decky.logger.warning("No OptiScaler.ini found to copy") if target_ini.exists(): + self._migrate_optiscaler_ini(target_ini) self._disable_hq_font_auto(target_ini) plugins_src = fgmod_path / "plugins" -- cgit v1.2.3