fix changing renderers

This commit is contained in:
izzy2lost
2025-08-22 15:03:51 -04:00
parent ec7ac6cb7e
commit c68fa37486
6 changed files with 181 additions and 38 deletions
+9 -2
View File
@@ -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<GSRendererType>(p_value);
if(MTGS::IsOpen()) {
if (MTGS::IsOpen())
MTGS::ApplySettings();
}
}
extern "C"
+12 -1
View File
@@ -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<int>(GSRendererType::Auto));
const GSRendererType base_renderer = static_cast<GSRendererType>(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)
@@ -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<CharSequence> 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) {
}
}
}
@@ -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<CharSequence> 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<CharSequence> 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();
@@ -77,6 +77,22 @@
android:layout_marginStart="16dp"/>
</RadioGroup>
<View
android:layout_width="match_parent"
android:layout_height="12dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Blending Accuracy"
android:textStyle="bold"
android:paddingBottom="8dp"/>
<Spinner
android:id="@+id/sp_blending_accuracy"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<View
android:layout_width="match_parent"
android:layout_height="12dp"/>
-1
View File
@@ -29,7 +29,6 @@
</string-array>
<string-array name="renderer_entries">
<item>Auto (Recommended)</item>
<item>Hardware (Vulkan)</item>
<item>Hardware (OpenGL)</item>
<item>Software (Slow, accurate)</item>