mirror of
https://github.com/izzy2lost/PSX2.git
synced 2026-07-05 15:18:36 -07:00
fix crash on settings change
Now changing settings globally or per game doesn't crash the app. Works on the fly, without crashing.
This commit is contained in:
@@ -15,7 +15,6 @@ import android.net.Uri;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
// Use Material 3 dialog builder for per‑game settings dialog
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import androidx.fragment.app.DialogFragment;
|
||||
|
||||
@@ -200,18 +199,42 @@ public class GameSettingsDialogFragment extends DialogFragment {
|
||||
.setView(view)
|
||||
.setNegativeButton("Cancel", (d, w) -> d.dismiss())
|
||||
.setPositiveButton("Save", (d, w) -> {
|
||||
// Apply blending to runtime as well for immediate effect
|
||||
NativeApp.setBlendingAccuracy(spBlendingAccuracy.getSelectedItemPosition());
|
||||
final int blendLevel = spBlendingAccuracy.getSelectedItemPosition();
|
||||
final int rendererIdx = spRenderer.getSelectedItemPosition();
|
||||
final int resIdx = spResolution.getSelectedItemPosition();
|
||||
final boolean wide = swWidescreenPatches.isChecked();
|
||||
final boolean noInt = swNoInterlacingPatches.isChecked();
|
||||
final boolean enablePatches = swEnablePatchCodes.isChecked();
|
||||
final boolean enableCheats = swEnableCheats.isChecked();
|
||||
|
||||
// Persist per-game INI explicitly (supports Auto as well)
|
||||
writeGameSettingsIni(ctx, gameSerial, gameCrc,
|
||||
spBlendingAccuracy.getSelectedItemPosition(),
|
||||
spRenderer.getSelectedItemPosition(),
|
||||
spResolution.getSelectedItemPosition(),
|
||||
swWidescreenPatches.isChecked(),
|
||||
swNoInterlacingPatches.isChecked(),
|
||||
/*enablePatches*/ swEnablePatchCodes.isChecked(),
|
||||
swEnableCheats.isChecked());
|
||||
blendLevel, rendererIdx, resIdx, wide, noInt,
|
||||
/*enablePatches*/ enablePatches, enableCheats);
|
||||
|
||||
// Live-apply per-game settings in one batch
|
||||
try {
|
||||
int renderer;
|
||||
// rendererIdx: 0=Auto,1=Vulkan,2=OpenGL,3=Software
|
||||
if (rendererIdx == 0) renderer = -1;
|
||||
else if (rendererIdx == 1) renderer = 14;
|
||||
else if (rendererIdx == 2) renderer = 12;
|
||||
else renderer = 13;
|
||||
|
||||
float scale = Math.max(1, Math.min(8, resIdx + 1));
|
||||
NativeApp.applyPerGameSettingsBatch(renderer, scale, blendLevel, wide, noInt, enablePatches, enableCheats);
|
||||
} catch (Throwable t) {
|
||||
android.util.Log.e("GameSettings", "Per-game batch apply failed: " + t.getMessage());
|
||||
}
|
||||
|
||||
// Refresh quick UI (renderer label) to reflect runtime renderer
|
||||
try {
|
||||
android.app.Activity a = getActivity();
|
||||
if (a instanceof MainActivity) {
|
||||
((MainActivity) a).runOnUiThread(() -> ((MainActivity) a).refreshQuickUi());
|
||||
}
|
||||
} catch (Throwable ignored) {}
|
||||
|
||||
d.dismiss();
|
||||
})
|
||||
.setNeutralButton("Reset to Global", (d, w) -> {
|
||||
|
||||
@@ -825,10 +825,24 @@ public class MainActivity extends AppCompatActivity implements GamesCoverDialogF
|
||||
private void updateRendererButtonLabel() {
|
||||
MaterialButton btn_bios = findViewById(R.id.btn_bios);
|
||||
if (btn_bios != null) {
|
||||
btn_bios.setText(rendererShortLabel(getCurrentRendererPref()));
|
||||
int current = getCurrentRendererPref();
|
||||
try {
|
||||
// Prefer runtime renderer from core to reflect per-game overrides
|
||||
int runtime = NativeApp.getCurrentRenderer();
|
||||
// Only accept expected values
|
||||
if (runtime == -1 || runtime == 12 || runtime == 13 || runtime == 14) {
|
||||
current = runtime;
|
||||
}
|
||||
} catch (Throwable ignored) {}
|
||||
btn_bios.setText(rendererShortLabel(current));
|
||||
}
|
||||
}
|
||||
|
||||
// Public minimal UI refresh hook for dialogs
|
||||
public void refreshQuickUi() {
|
||||
updateRendererButtonLabel();
|
||||
}
|
||||
|
||||
private void setRendererAndSave(int renderer) {
|
||||
SharedPreferences prefs = getSharedPreferences("app_prefs", MODE_PRIVATE);
|
||||
prefs.edit().putInt("renderer", renderer).apply();
|
||||
|
||||
@@ -37,7 +37,6 @@ public class NativeApp {
|
||||
|
||||
public static native void initialize(String path, int apiVer);
|
||||
public static native String getGameTitle(String path);
|
||||
// New: Resolve game title from a URI (content:// or file://). Implement in native when available.
|
||||
public static native String getGameTitleFromUri(String gameUri);
|
||||
public static native String getGameSerial();
|
||||
public static native float getFPS();
|
||||
@@ -78,6 +77,29 @@ public class NativeApp {
|
||||
public static native void setShadeBoostContrast(int contrast);
|
||||
public static native void setShadeBoostSaturation(int saturation);
|
||||
|
||||
// Apply multiple settings in one atomic batch (safer live updates)
|
||||
public static native void applyGlobalSettingsBatch(int renderer,
|
||||
float upscaleMultiplier,
|
||||
int aspectRatio,
|
||||
int blendingAccuracy,
|
||||
boolean widescreenPatches,
|
||||
boolean noInterlacingPatches,
|
||||
boolean loadTextures,
|
||||
boolean asyncTextureLoading,
|
||||
boolean hudVisible);
|
||||
|
||||
// Apply per-game settings (subset) in one batch
|
||||
public static native void applyPerGameSettingsBatch(int renderer,
|
||||
float upscaleMultiplier,
|
||||
int blendingAccuracy,
|
||||
boolean widescreenPatches,
|
||||
boolean noInterlacingPatches,
|
||||
boolean enablePatches,
|
||||
boolean enableCheats);
|
||||
|
||||
// Query current runtime renderer from the core (reflects global/per-game)
|
||||
public static native int getCurrentRenderer();
|
||||
|
||||
// Per-game settings
|
||||
public static native void saveGameSettings(String filename, int blendingAccuracy, int renderer,
|
||||
int resolution, boolean widescreenPatches,
|
||||
|
||||
@@ -15,7 +15,6 @@ import android.content.res.ColorStateList;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
// Use MaterialAlertDialogBuilder for Material 3 dialogs.
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import androidx.fragment.app.DialogFragment;
|
||||
import androidx.core.widget.CompoundButtonCompat;
|
||||
@@ -39,8 +38,8 @@ public class SettingsDialogFragment extends DialogFragment {
|
||||
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 widescreenPatches = prefs.getBoolean("widescreen_patches", true);
|
||||
boolean noInterlacingPatches = prefs.getBoolean("no_interlacing_patches", true);
|
||||
boolean loadTextures = prefs.getBoolean("load_textures", false);
|
||||
boolean asyncTextureLoading = prefs.getBoolean("async_texture_loading", true);
|
||||
boolean hudVisible = prefs.getBoolean("hud_visible", false);
|
||||
@@ -184,8 +183,8 @@ public class SettingsDialogFragment extends DialogFragment {
|
||||
int savedRenderer = prefs.getInt("renderer", RENDERER_AUTO);
|
||||
float savedScale = prefs.getFloat("upscale_multiplier", 1.0f);
|
||||
int savedAspectRatio = prefs.getInt("aspect_ratio", 1); // 1 = Auto 4:3/3:2 (recommended)
|
||||
boolean savedWidescreen = prefs.getBoolean("widescreen_patches", false);
|
||||
boolean savedNoInterlacing = prefs.getBoolean("no_interlacing_patches", false);
|
||||
boolean savedWidescreen = prefs.getBoolean("widescreen_patches", true);
|
||||
boolean savedNoInterlacing = prefs.getBoolean("no_interlacing_patches", true);
|
||||
boolean savedLoadTextures = prefs.getBoolean("load_textures", false);
|
||||
boolean savedAsyncTextureLoading = prefs.getBoolean("async_texture_loading", true);
|
||||
boolean savedHud = prefs.getBoolean("hud_visible", false);
|
||||
@@ -217,7 +216,7 @@ public class SettingsDialogFragment extends DialogFragment {
|
||||
|
||||
MaterialAlertDialogBuilder b = new MaterialAlertDialogBuilder(requireContext(),
|
||||
com.google.android.material.R.style.ThemeOverlay_Material3_MaterialAlertDialog);
|
||||
b.setTitle("Graphics Settings")
|
||||
b.setTitle("Global Settings")
|
||||
.setView(view)
|
||||
.setNegativeButton("Cancel", (d, w) -> d.dismiss())
|
||||
.setPositiveButton("Save", (d, w) -> {
|
||||
@@ -236,52 +235,35 @@ public class SettingsDialogFragment extends DialogFragment {
|
||||
boolean asyncTextureLoading = swAsyncTextureLoading.isChecked();
|
||||
boolean hudVisible = (swDevHud != null && swDevHud.isChecked());
|
||||
|
||||
// Debug logging
|
||||
android.util.Log.d("SettingsDialog", "Saving renderer setting: " + renderer +
|
||||
" (-1=Auto, 12=OpenGL, 13=Software, 14=Vulkan)");
|
||||
|
||||
// Save renderer setting first with commit() to ensure immediate write
|
||||
prefs.edit().putInt("renderer", renderer).apply();
|
||||
android.util.Log.d("SettingsDialog", "Renderer setting saved successfully");
|
||||
|
||||
// Small delay to ensure setting is persisted
|
||||
// Persist settings to SharedPreferences
|
||||
int blendingLevel = spBlending.getSelectedItemPosition();
|
||||
prefs.edit()
|
||||
.putInt("renderer", renderer)
|
||||
.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 in one batch to avoid repeated ApplySettings calls
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
} catch (InterruptedException ignored) {}
|
||||
|
||||
// Apply renderer change (might crash, but setting is already saved)
|
||||
try {
|
||||
NativeApp.renderGpu(renderer);
|
||||
android.util.Log.d("SettingsDialog", "Applied renderer change to: " + renderer);
|
||||
} catch (Exception e) {
|
||||
android.util.Log.e("SettingsDialog", "Failed to apply renderer: " + e.getMessage());
|
||||
// If renderer change fails, we'll still have the setting saved
|
||||
// for next app restart
|
||||
NativeApp.applyGlobalSettingsBatch(renderer, scale, aspectRatio, blendingLevel,
|
||||
widescreenPatches, noInterlacingPatches, loadTextures, asyncTextureLoading, hudVisible);
|
||||
} catch (Throwable t) {
|
||||
android.util.Log.e("SettingsDialog", "Batch apply failed: " + t.getMessage());
|
||||
}
|
||||
|
||||
// Persist all other settings
|
||||
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.setBlendingAccuracy(blendingLevel);
|
||||
NativeApp.setWidescreenPatches(widescreenPatches);
|
||||
NativeApp.setNoInterlacingPatches(noInterlacingPatches);
|
||||
NativeApp.setLoadTextures(loadTextures);
|
||||
NativeApp.setAsyncTextureLoading(asyncTextureLoading);
|
||||
NativeApp.setHudVisible(hudVisible);
|
||||
// Refresh quick UI (renderer label) if hosting activity is MainActivity
|
||||
try {
|
||||
android.app.Activity a = getActivity();
|
||||
if (a instanceof MainActivity) {
|
||||
((MainActivity) a).runOnUiThread(() -> ((MainActivity) a).refreshQuickUi());
|
||||
}
|
||||
} catch (Throwable ignored) {}
|
||||
});
|
||||
|
||||
return b.create();
|
||||
|
||||
Reference in New Issue
Block a user