From 69a937c997bbaf0cc4732936e400f0698ca843f8 Mon Sep 17 00:00:00 2001 From: izzy2lost Date: Sun, 7 Dec 2025 12:01:57 -0500 Subject: [PATCH] added landscape & portrait toggle - fixed audio bug causing crashes --- app/src/main/cpp/pcsx2/Host/AudioStream.cpp | 6 + app/src/main/cpp/pcsx2/SPU2/spu2.cpp | 3 +- .../psx2/GamesCoverDialogFragment.java | 151 +++++++++++------- .../java/com/izzy2lost/psx2/MainActivity.java | 81 +++++++++- .../res/layout/drawer_header_settings.xml | 56 ++++++- 5 files changed, 236 insertions(+), 61 deletions(-) diff --git a/app/src/main/cpp/pcsx2/Host/AudioStream.cpp b/app/src/main/cpp/pcsx2/Host/AudioStream.cpp index ab13a15..0a140c6 100644 --- a/app/src/main/cpp/pcsx2/Host/AudioStream.cpp +++ b/app/src/main/cpp/pcsx2/Host/AudioStream.cpp @@ -370,6 +370,9 @@ void AudioStream::StereoSampleReaderImpl(SampleType* dest, const SampleType* src void AudioStream::InternalWriteFrames(const SampleType* data, u32 num_frames) { + if (!m_buffer || m_buffer_size == 0) + return; + const u32 free = m_buffer_size - GetBufferedFramesRelaxed(); if (free <= num_frames) { @@ -635,6 +638,9 @@ void AudioStream::EndWrite(u32 num_frames) void AudioStream::WriteChunk(const SampleType* chunk) { + if (!m_buffer || m_buffer_size == 0) + return; + if (!IsExpansionEnabled() && !IsStretchEnabled()) { InternalWriteFrames(chunk, CHUNK_SIZE); diff --git a/app/src/main/cpp/pcsx2/SPU2/spu2.cpp b/app/src/main/cpp/pcsx2/SPU2/spu2.cpp index 84b793a..8d4c388 100644 --- a/app/src/main/cpp/pcsx2/SPU2/spu2.cpp +++ b/app/src/main/cpp/pcsx2/SPU2/spu2.cpp @@ -444,7 +444,8 @@ __forceinline void spu2Output(StereoOut32 out) { s_current_chunk_pos = 0; - s_output_stream->WriteChunk(s_current_chunk.data()); + if (s_output_stream) + s_output_stream->WriteChunk(s_current_chunk.data()); if (SPU2::IsAudioCaptureActive()) [[unlikely]] GSCapture::DeliverAudioPacket(s_current_chunk.data()); diff --git a/app/src/main/java/com/izzy2lost/psx2/GamesCoverDialogFragment.java b/app/src/main/java/com/izzy2lost/psx2/GamesCoverDialogFragment.java index b910013..c09e5af 100644 --- a/app/src/main/java/com/izzy2lost/psx2/GamesCoverDialogFragment.java +++ b/app/src/main/java/com/izzy2lost/psx2/GamesCoverDialogFragment.java @@ -634,10 +634,34 @@ public class GamesCoverDialogFragment extends DialogFragment { } catch (Throwable ignored) {} } - private void setupDialogDrawerSettings(View header) { + private void setupDialogDrawerSettings(View header) { if (header == null) return; android.content.SharedPreferences prefs = requireContext().getSharedPreferences("app_prefs", Context.MODE_PRIVATE); + MaterialButtonToggleGroup tgOrientation = header.findViewById(R.id.drawer_tg_orientation); + View tbOrientAuto = header.findViewById(R.id.drawer_tb_orientation_auto); + View tbOrientLand = header.findViewById(R.id.drawer_tb_orientation_landscape); + View tbOrientPort = header.findViewById(R.id.drawer_tb_orientation_portrait); + if (tgOrientation != null && tbOrientAuto != null && tbOrientLand != null && tbOrientPort != null) { + int savedOrientation = prefs.getInt("orientation_lock", MainActivity.ORIENTATION_AUTO); + int checkId = savedOrientation == MainActivity.ORIENTATION_LANDSCAPE ? tbOrientLand.getId() + : (savedOrientation == MainActivity.ORIENTATION_PORTRAIT ? tbOrientPort.getId() : tbOrientAuto.getId()); + tgOrientation.check(checkId); + tgOrientation.addOnButtonCheckedListener((group, checkedId, isChecked) -> { + if (!isChecked) return; + int mode = MainActivity.ORIENTATION_AUTO; + if (checkedId == tbOrientLand.getId()) mode = MainActivity.ORIENTATION_LANDSCAPE; + else if (checkedId == tbOrientPort.getId()) mode = MainActivity.ORIENTATION_PORTRAIT; + try { + if (getActivity() instanceof MainActivity) { + ((MainActivity) getActivity()).setOrientationPreference(mode); + } else { + prefs.edit().putInt("orientation_lock", mode).apply(); + } + } catch (Throwable ignored) {} + }); + } + // Aspect Ratio spinner android.widget.Spinner spAspect = header.findViewById(R.id.drawer_sp_aspect_ratio); if (spAspect != null) { @@ -1245,66 +1269,81 @@ public class GamesCoverDialogFragment extends DialogFragment { try { View root = getView(); if (root == null) return; - + com.google.android.material.navigation.NavigationView nav = root.findViewById(R.id.dialog_nav_view); - if (nav != null && nav.getHeaderCount() > 0) { - View header = nav.getHeaderView(0); - if (header != null) { - android.content.SharedPreferences prefs = requireContext().getSharedPreferences("app_prefs", Context.MODE_PRIVATE); - - // Refresh spinner values to reflect current settings - android.widget.Spinner spAspect = header.findViewById(R.id.drawer_sp_aspect_ratio); - if (spAspect != null && spAspect.getAdapter() != null) { - int savedAspect = prefs.getInt("aspect_ratio", 1); - android.widget.ArrayAdapter aspectAdapter = (android.widget.ArrayAdapter) spAspect.getAdapter(); - if (savedAspect >= 0 && savedAspect < aspectAdapter.getCount()) { - spAspect.setSelection(savedAspect); - } - } + if (nav == null || nav.getHeaderCount() == 0) return; - android.widget.Spinner spScale = header.findViewById(R.id.drawer_sp_scale); - if (spScale != null && spScale.getAdapter() != null) { - float savedScale = prefs.getFloat("upscale_multiplier", 1.0f); - android.widget.ArrayAdapter scaleAdapter = (android.widget.ArrayAdapter) spScale.getAdapter(); - int scaleIndex = Math.max(0, Math.min(scaleAdapter.getCount() - 1, Math.round(savedScale) - 1)); - spScale.setSelection(scaleIndex); - } + View header = nav.getHeaderView(0); + if (header == null) return; - android.widget.Spinner spBlending = header.findViewById(R.id.drawer_sp_blending_accuracy); - if (spBlending != null && spBlending.getAdapter() != null) { - int savedBlend = prefs.getInt("blending_accuracy", 1); - android.widget.ArrayAdapter blendAdapter = (android.widget.ArrayAdapter) spBlending.getAdapter(); - if (savedBlend >= 0 && savedBlend < blendAdapter.getCount()) { - spBlending.setSelection(savedBlend); - } - } - - // Refresh switch states - com.google.android.material.materialswitch.MaterialSwitch swWide = header.findViewById(R.id.drawer_sw_widescreen); - if (swWide != null) { - swWide.setChecked(prefs.getBoolean("widescreen_patches", true)); - } + android.content.SharedPreferences prefs = requireContext().getSharedPreferences("app_prefs", Context.MODE_PRIVATE); - com.google.android.material.materialswitch.MaterialSwitch swNoInt = header.findViewById(R.id.drawer_sw_no_interlacing); - if (swNoInt != null) { - swNoInt.setChecked(prefs.getBoolean("no_interlacing_patches", true)); - } - - com.google.android.material.materialswitch.MaterialSwitch swLoadTex = header.findViewById(R.id.drawer_sw_load_textures); - if (swLoadTex != null) { - swLoadTex.setChecked(prefs.getBoolean("load_textures", false)); - } - - com.google.android.material.materialswitch.MaterialSwitch swAsyncTex = header.findViewById(R.id.drawer_sw_async_textures); - if (swAsyncTex != null) { - swAsyncTex.setChecked(prefs.getBoolean("async_texture_loading", true)); - } - - com.google.android.material.materialswitch.MaterialSwitch swPrecache = header.findViewById(R.id.drawer_sw_precache_textures); - if (swPrecache != null) { - swPrecache.setChecked(prefs.getBoolean("precache_textures", false)); - } + try { + MaterialButtonToggleGroup tgOrientation = header.findViewById(R.id.drawer_tg_orientation); + View tbOrientAuto = header.findViewById(R.id.drawer_tb_orientation_auto); + View tbOrientLand = header.findViewById(R.id.drawer_tb_orientation_landscape); + View tbOrientPort = header.findViewById(R.id.drawer_tb_orientation_portrait); + if (tgOrientation != null && tbOrientAuto != null && tbOrientLand != null && tbOrientPort != null) { + int savedOrientation = prefs.getInt("orientation_lock", MainActivity.ORIENTATION_AUTO); + int checkId = savedOrientation == MainActivity.ORIENTATION_LANDSCAPE ? tbOrientLand.getId() + : (savedOrientation == MainActivity.ORIENTATION_PORTRAIT ? tbOrientPort.getId() : tbOrientAuto.getId()); + tgOrientation.check(checkId); } + } catch (Exception e) { + android.util.Log.e("GamesCoverDialog", "Error refreshing orientation toggle: " + e.getMessage()); + } + + // Refresh spinner values to reflect current settings + android.widget.Spinner spAspect = header.findViewById(R.id.drawer_sp_aspect_ratio); + if (spAspect != null && spAspect.getAdapter() != null) { + int savedAspect = prefs.getInt("aspect_ratio", 1); + android.widget.ArrayAdapter aspectAdapter = (android.widget.ArrayAdapter) spAspect.getAdapter(); + if (savedAspect >= 0 && savedAspect < aspectAdapter.getCount()) { + spAspect.setSelection(savedAspect); + } + } + + android.widget.Spinner spScale = header.findViewById(R.id.drawer_sp_scale); + if (spScale != null && spScale.getAdapter() != null) { + float savedScale = prefs.getFloat("upscale_multiplier", 1.0f); + android.widget.ArrayAdapter scaleAdapter = (android.widget.ArrayAdapter) spScale.getAdapter(); + int scaleIndex = Math.max(0, Math.min(scaleAdapter.getCount() - 1, Math.round(savedScale) - 1)); + spScale.setSelection(scaleIndex); + } + + android.widget.Spinner spBlending = header.findViewById(R.id.drawer_sp_blending_accuracy); + if (spBlending != null && spBlending.getAdapter() != null) { + int savedBlend = prefs.getInt("blending_accuracy", 1); + android.widget.ArrayAdapter blendAdapter = (android.widget.ArrayAdapter) spBlending.getAdapter(); + if (savedBlend >= 0 && savedBlend < blendAdapter.getCount()) { + spBlending.setSelection(savedBlend); + } + } + + // Refresh switch states + com.google.android.material.materialswitch.MaterialSwitch swWide = header.findViewById(R.id.drawer_sw_widescreen); + if (swWide != null) { + swWide.setChecked(prefs.getBoolean("widescreen_patches", true)); + } + + com.google.android.material.materialswitch.MaterialSwitch swNoInt = header.findViewById(R.id.drawer_sw_no_interlacing); + if (swNoInt != null) { + swNoInt.setChecked(prefs.getBoolean("no_interlacing_patches", true)); + } + + com.google.android.material.materialswitch.MaterialSwitch swLoadTex = header.findViewById(R.id.drawer_sw_load_textures); + if (swLoadTex != null) { + swLoadTex.setChecked(prefs.getBoolean("load_textures", false)); + } + + com.google.android.material.materialswitch.MaterialSwitch swAsyncTex = header.findViewById(R.id.drawer_sw_async_textures); + if (swAsyncTex != null) { + swAsyncTex.setChecked(prefs.getBoolean("async_texture_loading", true)); + } + + com.google.android.material.materialswitch.MaterialSwitch swPrecache = header.findViewById(R.id.drawer_sw_precache_textures); + if (swPrecache != null) { + swPrecache.setChecked(prefs.getBoolean("precache_textures", false)); } } catch (Throwable ignored) {} } diff --git a/app/src/main/java/com/izzy2lost/psx2/MainActivity.java b/app/src/main/java/com/izzy2lost/psx2/MainActivity.java index 6b121b8..3be73c7 100644 --- a/app/src/main/java/com/izzy2lost/psx2/MainActivity.java +++ b/app/src/main/java/com/izzy2lost/psx2/MainActivity.java @@ -38,6 +38,7 @@ import android.app.RemoteAction; import android.graphics.drawable.Icon; import android.app.PendingIntent; import android.content.pm.PackageManager; +import android.content.pm.ActivityInfo; import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.contract.ActivityResultContracts; @@ -55,7 +56,6 @@ import androidx.core.view.WindowInsetsCompat; import androidx.core.graphics.Insets; import com.google.android.material.button.MaterialButton; - import java.io.File; import java.io.FileOutputStream; import java.io.IOException; @@ -70,6 +70,10 @@ import java.util.List; import java.util.Locale; public class MainActivity extends AppCompatActivity implements GamesCoverDialogFragment.OnGameSelectedListener, ControllerInputHandler.ControllerInputListener { + public static final int ORIENTATION_AUTO = 0; + public static final int ORIENTATION_LANDSCAPE = 1; + public static final int ORIENTATION_PORTRAIT = 2; + private String m_szGamefile = ""; private HIDDeviceManager mHIDDeviceManager; @@ -1942,11 +1946,67 @@ public class MainActivity extends AppCompatActivity implements GamesCoverDialogF } } + private int normalizeOrientationPref(int value) { + if (value == ORIENTATION_LANDSCAPE || value == ORIENTATION_PORTRAIT) return value; + return ORIENTATION_AUTO; + } + + public void setOrientationPreference(int mode) { + int normalized = normalizeOrientationPref(mode); + try { + SharedPreferences prefs = getSharedPreferences("app_prefs", MODE_PRIVATE); + prefs.edit().putInt("orientation_lock", normalized).apply(); + } catch (Throwable ignored) {} + applyOrientationPreference(normalized); + } + + public void applyOrientationPreference() { + int mode = ORIENTATION_AUTO; + try { + SharedPreferences prefs = getSharedPreferences("app_prefs", MODE_PRIVATE); + mode = normalizeOrientationPref(prefs.getInt("orientation_lock", ORIENTATION_AUTO)); + } catch (Throwable ignored) {} + applyOrientationPreference(mode); + } + + private void applyOrientationPreference(int mode) { + int requested = ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR; + if (mode == ORIENTATION_LANDSCAPE) { + requested = ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE; + } else if (mode == ORIENTATION_PORTRAIT) { + requested = ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT; + } + + try { + setRequestedOrientation(requested); + } catch (Throwable e) { + android.util.Log.e("MainActivity", "Failed to apply orientation preference: " + e.getMessage()); + } + } + private void setupDrawerSettings(View header) { if (header == null) return; SharedPreferences prefs = getSharedPreferences("app_prefs", MODE_PRIVATE); + MaterialButtonToggleGroup tgOrientation = header.findViewById(R.id.drawer_tg_orientation); + View tbOrientAuto = header.findViewById(R.id.drawer_tb_orientation_auto); + View tbOrientLand = header.findViewById(R.id.drawer_tb_orientation_landscape); + View tbOrientPort = header.findViewById(R.id.drawer_tb_orientation_portrait); + if (tgOrientation != null && tbOrientAuto != null && tbOrientLand != null && tbOrientPort != null) { + int savedOrientation = normalizeOrientationPref(prefs.getInt("orientation_lock", ORIENTATION_AUTO)); + int checkId = savedOrientation == ORIENTATION_LANDSCAPE ? tbOrientLand.getId() + : (savedOrientation == ORIENTATION_PORTRAIT ? tbOrientPort.getId() : tbOrientAuto.getId()); + tgOrientation.check(checkId); + tgOrientation.addOnButtonCheckedListener((group, checkedId, isChecked) -> { + if (!isChecked) return; + int mode = ORIENTATION_AUTO; + if (checkedId == tbOrientLand.getId()) mode = ORIENTATION_LANDSCAPE; + else if (checkedId == tbOrientPort.getId()) mode = ORIENTATION_PORTRAIT; + setOrientationPreference(mode); + }); + } + // Aspect Ratio spinner - setup like QuickActions Spinner spAspect = header.findViewById(R.id.drawer_sp_aspect_ratio); if (spAspect != null) { @@ -2118,7 +2178,22 @@ public class MainActivity extends AppCompatActivity implements GamesCoverDialogF android.util.Log.e("MainActivity", "SharedPreferences is null during refreshDrawerSettings"); return; } - + + try { + MaterialButtonToggleGroup tgOrientation = header.findViewById(R.id.drawer_tg_orientation); + View tbOrientAuto = header.findViewById(R.id.drawer_tb_orientation_auto); + View tbOrientLand = header.findViewById(R.id.drawer_tb_orientation_landscape); + View tbOrientPort = header.findViewById(R.id.drawer_tb_orientation_portrait); + if (tgOrientation != null && tbOrientAuto != null && tbOrientLand != null && tbOrientPort != null) { + int savedOrientation = normalizeOrientationPref(prefs.getInt("orientation_lock", ORIENTATION_AUTO)); + int checkId = savedOrientation == ORIENTATION_LANDSCAPE ? tbOrientLand.getId() + : (savedOrientation == ORIENTATION_PORTRAIT ? tbOrientPort.getId() : tbOrientAuto.getId()); + tgOrientation.check(checkId); + } + } catch (Exception e) { + android.util.Log.e("MainActivity", "Error refreshing orientation toggle: " + e.getMessage()); + } + // Refresh spinner values to reflect current settings try { Spinner spAspect = header.findViewById(R.id.drawer_sp_aspect_ratio); @@ -2249,6 +2324,8 @@ public class MainActivity extends AppCompatActivity implements GamesCoverDialogF // Apply renderer setting int renderer = prefs.getInt("renderer", -1); NativeApp.renderGpu(renderer); + + applyOrientationPreference(); } catch (Throwable ignored) {} } diff --git a/app/src/main/res/layout/drawer_header_settings.xml b/app/src/main/res/layout/drawer_header_settings.xml index adccd4e..3007d5f 100644 --- a/app/src/main/res/layout/drawer_header_settings.xml +++ b/app/src/main/res/layout/drawer_header_settings.xml @@ -104,14 +104,66 @@ android:textColor="@color/brand_primary" android:checkable="true" /> + + + + + + + + + + + +