From c68fa374863f96b45dd9f571ebbaed12c4b43bac Mon Sep 17 00:00:00 2001 From: izzy2lost Date: Fri, 22 Aug 2025 15:03:51 -0400 Subject: [PATCH] fix changing renderers --- app/src/main/cpp/native-lib.cpp | 11 +- app/src/main/cpp/pcsx2/GS/GS.cpp | 13 +- .../psx2/GameSettingsDialogFragment.java | 129 +++++++++++++++--- .../psx2/SettingsDialogFragment.java | 49 ++++--- app/src/main/res/layout/dialog_settings.xml | 16 +++ app/src/main/res/values/arrays.xml | 1 - 6 files changed, 181 insertions(+), 38 deletions(-) diff --git a/app/src/main/cpp/native-lib.cpp b/app/src/main/cpp/native-lib.cpp index 53926dc..708ac32 100644 --- a/app/src/main/cpp/native-lib.cpp +++ b/app/src/main/cpp/native-lib.cpp @@ -121,6 +121,8 @@ static void ApplyPerGameSettingsForPath(const std::string& game_path) s_settings_interface.SetBoolValue("EmuCore", "EnableCheats", bval); } +// (renderGpu JNI defined later; keep only one definition) + extern "C" JNIEXPORT void JNICALL Java_com_izzy2lost_psx2_NativeApp_setHudVisible(JNIEnv* env, jclass clazz, jboolean p_visible) @@ -722,10 +724,15 @@ extern "C" JNIEXPORT void JNICALL Java_com_izzy2lost_psx2_NativeApp_renderGpu(JNIEnv *env, jclass clazz, jint p_value) { + // Accept 12(OpenGL), 13(Software), 14(Vulkan) + if (p_value != 12 && p_value != 13 && p_value != 14) + return; + + // Persist to base settings and apply immediately if possible + s_settings_interface.SetIntValue("EmuCore/GS", "Renderer", (int)p_value); EmuConfig.GS.Renderer = static_cast(p_value); - if(MTGS::IsOpen()) { + if (MTGS::IsOpen()) MTGS::ApplySettings(); - } } extern "C" diff --git a/app/src/main/cpp/pcsx2/GS/GS.cpp b/app/src/main/cpp/pcsx2/GS/GS.cpp index 7d7e40c..9f3ced4 100644 --- a/app/src/main/cpp/pcsx2/GS/GS.cpp +++ b/app/src/main/cpp/pcsx2/GS/GS.cpp @@ -342,8 +342,19 @@ bool GSopen(const Pcsx2Config::GSOptions& config, GSRendererType renderer, u8* b { GSConfig = config; + // If the selected renderer is Auto (often from a per-game settings layer), + // prefer the base/global renderer when it is explicitly set, otherwise + // fall back to the hardware/platform preferred renderer. if (renderer == GSRendererType::Auto) - renderer = GSUtil::GetPreferredRenderer(); + { + const int base_renderer_val = Host::GetBaseIntSettingValue("EmuCore/GS", "Renderer", + static_cast(GSRendererType::Auto)); + const GSRendererType base_renderer = static_cast(base_renderer_val); + if (base_renderer != GSRendererType::Auto) + renderer = base_renderer; + else + renderer = GSUtil::GetPreferredRenderer(); + } bool res = OpenGSDevice(renderer, true, false, vsync_mode, allow_present_throttle); if (res) diff --git a/app/src/main/java/com/izzy2lost/psx2/GameSettingsDialogFragment.java b/app/src/main/java/com/izzy2lost/psx2/GameSettingsDialogFragment.java index e8e93e7..c11e0f3 100644 --- a/app/src/main/java/com/izzy2lost/psx2/GameSettingsDialogFragment.java +++ b/app/src/main/java/com/izzy2lost/psx2/GameSettingsDialogFragment.java @@ -69,7 +69,7 @@ public class GameSettingsDialogFragment extends DialogFragment { blendingAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spBlendingAccuracy.setAdapter(blendingAdapter); - // Renderer Spinner + // Renderer Spinner (no Auto; entries: Vulkan, OpenGL, Software) Spinner spRenderer = view.findViewById(R.id.sp_renderer); ArrayAdapter rendererAdapter = ArrayAdapter.createFromResource(ctx, R.array.renderer_entries, android.R.layout.simple_spinner_item); @@ -89,7 +89,7 @@ public class GameSettingsDialogFragment extends DialogFragment { Switch swEnablePatchCodes = view.findViewById(R.id.sw_enable_patch_codes); Switch swEnableCheats = view.findViewById(R.id.sw_enable_cheats); - // Load existing per-game settings from INI and prefill widgets + // Load existing per-game settings from INI and prefill widgets; if missing, use global try { String serial = gameSerial; if (serial == null || serial.isEmpty()) { @@ -99,18 +99,30 @@ public class GameSettingsDialogFragment extends DialogFragment { // Build INI path String dataRoot = getContext().getExternalFilesDir(null).getAbsolutePath(); java.io.File ini = new java.io.File(new java.io.File(dataRoot, "gamesettings"), serial + ".ini"); + boolean appliedRenderer = false; + boolean appliedBlend = false; if (ini.exists()) { - String content = new String(java.nio.file.Files.readAllBytes(ini.toPath())); + String content = ""; + try { + java.io.FileInputStream fis = new java.io.FileInputStream(ini); + java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream(); + byte[] buf = new byte[4096]; + int n; + while ((n = fis.read(buf)) != -1) baos.write(buf, 0, n); + fis.close(); + content = baos.toString("UTF-8"); + } catch (Exception ignored) {} // Very light parsing java.util.regex.Matcher m; m = java.util.regex.Pattern.compile("(?m)^Renderer=\\s*(.+)$").matcher(content); if (m.find()) { String rv = m.group(1).trim(); - int idx = 0; - if ("Vulkan".equalsIgnoreCase(rv)) idx = 1; - else if ("OpenGL".equalsIgnoreCase(rv)) idx = 2; - else if ("Software".equalsIgnoreCase(rv)) idx = 3; + int idx = 0; // 0=Vulkan,1=OpenGL,2=Software + if ("Vulkan".equalsIgnoreCase(rv) || "14".equals(rv)) idx = 0; + else if ("OpenGL".equalsIgnoreCase(rv) || "12".equals(rv)) idx = 1; + else if ("Software".equalsIgnoreCase(rv) || "13".equals(rv)) idx = 2; spRenderer.setSelection(idx); + appliedRenderer = true; } m = java.util.regex.Pattern.compile("(?m)^upscale_multiplier=\\s*([0-9]+(?:\\.[0-9]+)?)$").matcher(content); if (m.find()) { @@ -132,6 +144,7 @@ public class GameSettingsDialogFragment extends DialogFragment { else if ("Maximum".equalsIgnoreCase(bv)) idx = 5; } spBlendingAccuracy.setSelection(idx); + appliedBlend = true; } m = java.util.regex.Pattern.compile("(?m)^EnableWideScreenPatches=\\s*(true|false)$").matcher(content); if (m.find()) swWidescreenPatches.setChecked(Boolean.parseBoolean(m.group(1))); @@ -142,11 +155,29 @@ public class GameSettingsDialogFragment extends DialogFragment { m = java.util.regex.Pattern.compile("(?m)^EnablePatches=\\s*(true|false)$").matcher(content); if (m.find()) swEnablePatchCodes.setChecked(Boolean.parseBoolean(m.group(1))); } + + // If no per-game renderer specified, mirror the global renderer choice + if (!appliedRenderer) { + android.content.SharedPreferences prefs = ctx.getSharedPreferences("app_prefs", Context.MODE_PRIVATE); + int globalRenderer = prefs.getInt("renderer", 14); // default Vulkan + int idx = (globalRenderer == 14) ? 0 : (globalRenderer == 12 ? 1 : 2); + spRenderer.setSelection(idx); + } + // If no per-game blending specified, mirror the global blending + if (!appliedBlend) { + android.content.SharedPreferences prefs = ctx.getSharedPreferences("app_prefs", Context.MODE_PRIVATE); + int globalBlend = prefs.getInt("blending_accuracy", 1); + spBlendingAccuracy.setSelection(Math.max(0, Math.min(5, globalBlend))); + } } } catch (Throwable ignored) { // Fallback to defaults if loading fails spBlendingAccuracy.setSelection(1); - spRenderer.setSelection(0); + // Mirror global default when error + android.content.SharedPreferences prefs = ctx.getSharedPreferences("app_prefs", Context.MODE_PRIVATE); + int globalRenderer = prefs.getInt("renderer", 14); + int idx = (globalRenderer == 14) ? 0 : (globalRenderer == 12 ? 1 : 2); + spRenderer.setSelection(idx); spResolution.setSelection(0); } @@ -158,19 +189,20 @@ public class GameSettingsDialogFragment extends DialogFragment { // Apply blending to runtime as well for immediate effect NativeApp.setBlendingAccuracy(spBlendingAccuracy.getSelectedItemPosition()); - saveGameSettings(gameSerial, gameCrc, - spBlendingAccuracy.getSelectedItemPosition(), - spRenderer.getSelectedItemPosition(), - spResolution.getSelectedItemPosition(), - swWidescreenPatches.isChecked(), - swNoInterlacingPatches.isChecked(), - /*enablePatches*/ swEnablePatchCodes.isChecked(), - swEnableCheats.isChecked()); + // Persist per-game INI explicitly to mirror global defaults and avoid Auto + writeGameSettingsIni(ctx, gameSerial, gameCrc, + spBlendingAccuracy.getSelectedItemPosition(), + spRenderer.getSelectedItemPosition(), + spResolution.getSelectedItemPosition(), + swWidescreenPatches.isChecked(), + swNoInterlacingPatches.isChecked(), + /*enablePatches*/ swEnablePatchCodes.isChecked(), + swEnableCheats.isChecked()); d.dismiss(); }) .setNeutralButton("Reset to Global", (d, w) -> { - // TODO: Delete game-specific settings file - deleteGameSettings(gameSerial, gameCrc); + // Delete game-specific settings file so globals apply + deleteGameSettingsIni(ctx, gameSerial, gameCrc); d.dismiss(); }); @@ -256,4 +288,65 @@ public class GameSettingsDialogFragment extends DialogFragment { NativeApp.deleteGameSettings(filename); } + + private static String pickSettingsFileName(String gameSerial, String gameCrc) { + if (gameSerial != null && !gameSerial.isEmpty()) return gameSerial + ".ini"; + if (gameCrc != null && !gameCrc.isEmpty()) return gameCrc + ".ini"; + return null; + } + + private static void writeGameSettingsIni(Context ctx, + String gameSerial, + String gameCrc, + int blendingAccuracyIdx, + int rendererIdx, + int resolutionIdx, + boolean widescreenPatches, + boolean noInterlacingPatches, + boolean enablePatches, + boolean enableCheats) { + try { + String fileName = pickSettingsFileName(gameSerial, gameCrc); + if (fileName == null) return; + java.io.File baseDir = new java.io.File(ctx.getExternalFilesDir(null), "gamesettings"); + if (!baseDir.exists()) baseDir.mkdirs(); + java.io.File ini = new java.io.File(baseDir, fileName); + + // Map indices + String rendererName = (rendererIdx == 0) ? "Vulkan" : (rendererIdx == 1 ? "OpenGL" : "Software"); + float upscale = Math.max(1, Math.min(8, resolutionIdx + 1)); + int abl = Math.max(0, Math.min(5, blendingAccuracyIdx)); + + StringBuilder sb = new StringBuilder(); + sb.append("[EmuCore/GS]\n"); + sb.append("Renderer=").append(rendererName).append('\n'); + sb.append("upscale_multiplier=").append((int) upscale).append('\n'); + sb.append("accurate_blending_unit=").append(abl).append('\n'); + sb.append('\n'); + sb.append("[EmuCore]\n"); + sb.append("EnableWideScreenPatches=").append(widescreenPatches).append('\n'); + sb.append("EnableNoInterlacingPatches=").append(noInterlacingPatches).append('\n'); + sb.append("EnablePatches=").append(enablePatches).append('\n'); + sb.append("EnableCheats=").append(enableCheats).append('\n'); + + try { + java.io.FileOutputStream fos = new java.io.FileOutputStream(ini, false); + byte[] data = sb.toString().getBytes("UTF-8"); + fos.write(data); + fos.flush(); + fos.close(); + } catch (Exception ignored) {} + } catch (Throwable ignored) { + } + } + + private static void deleteGameSettingsIni(Context ctx, String gameSerial, String gameCrc) { + try { + String fileName = pickSettingsFileName(gameSerial, gameCrc); + if (fileName == null) return; + java.io.File ini = new java.io.File(new java.io.File(ctx.getExternalFilesDir(null), "gamesettings"), fileName); + if (ini.exists()) ini.delete(); + } catch (Throwable ignored) { + } + } } diff --git a/app/src/main/java/com/izzy2lost/psx2/SettingsDialogFragment.java b/app/src/main/java/com/izzy2lost/psx2/SettingsDialogFragment.java index 8828572..71ef25d 100644 --- a/app/src/main/java/com/izzy2lost/psx2/SettingsDialogFragment.java +++ b/app/src/main/java/com/izzy2lost/psx2/SettingsDialogFragment.java @@ -35,6 +35,7 @@ public class SettingsDialogFragment extends DialogFragment { int renderer = prefs.getInt("renderer", RENDERER_VULKAN); float scale = prefs.getFloat("upscale_multiplier", 1.0f); int aspectRatio = prefs.getInt("aspect_ratio", 1); + int blendingAccuracy = prefs.getInt("blending_accuracy", 1); // 0..5 boolean widescreenPatches = prefs.getBoolean("widescreen_patches", false); boolean noInterlacingPatches = prefs.getBoolean("no_interlacing_patches", false); boolean loadTextures = prefs.getBoolean("load_textures", false); @@ -50,6 +51,7 @@ public class SettingsDialogFragment extends DialogFragment { android.util.Log.d("SettingsDialog", "Applied renderer: " + renderer); NativeApp.renderUpscalemultiplier(scale); NativeApp.setAspectRatio(aspectRatio); + NativeApp.setBlendingAccuracy(blendingAccuracy); NativeApp.setWidescreenPatches(widescreenPatches); NativeApp.setNoInterlacingPatches(noInterlacingPatches); NativeApp.setLoadTextures(loadTextures); @@ -74,6 +76,7 @@ public class SettingsDialogFragment extends DialogFragment { RadioButton rbVk = view.findViewById(R.id.rb_renderer_vk); RadioButton rbSw = view.findViewById(R.id.rb_renderer_sw); Spinner spScale = view.findViewById(R.id.sp_scale); + Spinner spBlending = view.findViewById(R.id.sp_blending_accuracy); Spinner spAspectRatio = view.findViewById(R.id.sp_aspect_ratio); Switch swWidescreen = view.findViewById(R.id.sw_widescreen); Switch swNoInterlacing = view.findViewById(R.id.sw_no_interlacing); @@ -180,6 +183,12 @@ public class SettingsDialogFragment extends DialogFragment { scaleAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spScale.setAdapter(scaleAdapter); + // Populate blending accuracy spinner (0..5) + ArrayAdapter blendAdapter = ArrayAdapter.createFromResource(ctx, + R.array.blending_accuracy_entries, android.R.layout.simple_spinner_item); + blendAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + spBlending.setAdapter(blendAdapter); + // Populate aspect ratio spinner ArrayAdapter aspectAdapter = ArrayAdapter.createFromResource(ctx, R.array.aspect_ratio_entries, android.R.layout.simple_spinner_item); @@ -195,6 +204,7 @@ public class SettingsDialogFragment extends DialogFragment { boolean savedLoadTextures = prefs.getBoolean("load_textures", false); boolean savedAsyncTextureLoading = prefs.getBoolean("async_texture_loading", true); boolean savedHud = prefs.getBoolean("hud_visible", false); + int savedBlending = prefs.getInt("blending_accuracy", 1); if (savedRenderer == RENDERER_VULKAN) rbVk.setChecked(true); else if (savedRenderer == RENDERER_SOFTWARE) rbSw.setChecked(true); @@ -204,6 +214,9 @@ public class SettingsDialogFragment extends DialogFragment { if (scaleIndex < 0 || scaleIndex >= scaleAdapter.getCount()) scaleIndex = 0; spScale.setSelection(scaleIndex); + if (savedBlending < 0 || savedBlending >= blendAdapter.getCount()) savedBlending = 1; + spBlending.setSelection(savedBlending); + if (savedAspectRatio >= 0 && savedAspectRatio < aspectAdapter.getCount()) { spAspectRatio.setSelection(savedAspectRatio); } else { @@ -258,24 +271,28 @@ public class SettingsDialogFragment extends DialogFragment { } // Persist all other settings - prefs.edit() - .putFloat("upscale_multiplier", scale) - .putInt("aspect_ratio", aspectRatio) - .putBoolean("widescreen_patches", widescreenPatches) - .putBoolean("no_interlacing_patches", noInterlacingPatches) - .putBoolean("load_textures", loadTextures) - .putBoolean("async_texture_loading", asyncTextureLoading) - .putBoolean("hud_visible", hudVisible) - .apply(); + int blendingLevel = spBlending.getSelectedItemPosition(); + + prefs.edit() + .putFloat("upscale_multiplier", scale) + .putInt("aspect_ratio", aspectRatio) + .putInt("blending_accuracy", blendingLevel) + .putBoolean("widescreen_patches", widescreenPatches) + .putBoolean("no_interlacing_patches", noInterlacingPatches) + .putBoolean("load_textures", loadTextures) + .putBoolean("async_texture_loading", asyncTextureLoading) + .putBoolean("hud_visible", hudVisible) + .apply(); // Apply other settings - NativeApp.renderUpscalemultiplier(scale); - NativeApp.setAspectRatio(aspectRatio); - NativeApp.setWidescreenPatches(widescreenPatches); - NativeApp.setNoInterlacingPatches(noInterlacingPatches); - NativeApp.setLoadTextures(loadTextures); - NativeApp.setAsyncTextureLoading(asyncTextureLoading); - NativeApp.setHudVisible(hudVisible); + NativeApp.renderUpscalemultiplier(scale); + NativeApp.setAspectRatio(aspectRatio); + NativeApp.setBlendingAccuracy(blendingLevel); + NativeApp.setWidescreenPatches(widescreenPatches); + NativeApp.setNoInterlacingPatches(noInterlacingPatches); + NativeApp.setLoadTextures(loadTextures); + NativeApp.setAsyncTextureLoading(asyncTextureLoading); + NativeApp.setHudVisible(hudVisible); }); return b.create(); diff --git a/app/src/main/res/layout/dialog_settings.xml b/app/src/main/res/layout/dialog_settings.xml index f988ab5..93a2d16 100644 --- a/app/src/main/res/layout/dialog_settings.xml +++ b/app/src/main/res/layout/dialog_settings.xml @@ -77,6 +77,22 @@ android:layout_marginStart="16dp"/> + + + + + + diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index 35db0ec..4556559 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -29,7 +29,6 @@ - Auto (Recommended) Hardware (Vulkan) Hardware (OpenGL) Software (Slow, accurate)