diff --git a/src/android/app/src/main/java/org/citra/citra_emu/display/ScreenAdjustmentUtil.kt b/src/android/app/src/main/java/org/citra/citra_emu/display/ScreenAdjustmentUtil.kt index c80e79ec6..52dc6b97d 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/display/ScreenAdjustmentUtil.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/display/ScreenAdjustmentUtil.kt @@ -68,4 +68,13 @@ class ScreenAdjustmentUtil( settings.saveSetting(IntSetting.ORIENTATION_OPTION, SettingsFile.FILE_NAME_CONFIG) activity.requestedOrientation = orientationOption } + + fun toggleScreenUpright() { + val uprightBoolean = BooleanSetting.UPRIGHT_SCREEN.boolean + BooleanSetting.UPRIGHT_SCREEN.boolean = !uprightBoolean + settings.saveSetting(BooleanSetting.UPRIGHT_SCREEN, SettingsFile.FILE_NAME_CONFIG) + NativeLibrary.reloadSettings() + NativeLibrary.updateFramebuffer(NativeLibrary.isPortraitMode) + + } } diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/BooleanSetting.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/BooleanSetting.kt index 4e5481d7c..54129a32f 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/BooleanSetting.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/BooleanSetting.kt @@ -15,6 +15,7 @@ enum class BooleanSetting( ALLOW_PLUGIN_LOADER("allow_plugin_loader", Settings.SECTION_SYSTEM, true), SWAP_SCREEN("swap_screen", Settings.SECTION_LAYOUT, false), INSTANT_DEBUG_LOG("instant_debug_log", Settings.SECTION_DEBUG, false), + UPRIGHT_SCREEN("upright_screen", Settings.SECTION_LAYOUT, false), CUSTOM_LAYOUT("custom_layout",Settings.SECTION_LAYOUT,false); override var boolean: Boolean = defaultValue diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.kt index 31401567f..b2a1eb2ee 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.kt @@ -951,6 +951,15 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) IntSetting.SCREEN_LAYOUT.defaultValue ) ) + add( + SwitchSetting( + BooleanSetting.UPRIGHT_SCREEN, + R.string.emulation_rotate_upright, + 0, + BooleanSetting.UPRIGHT_SCREEN.key, + BooleanSetting.UPRIGHT_SCREEN.defaultValue + ) + ) add( SingleChoiceSetting( IntSetting.PORTRAIT_SCREEN_LAYOUT, diff --git a/src/android/app/src/main/java/org/citra/citra_emu/fragments/EmulationFragment.kt b/src/android/app/src/main/java/org/citra/citra_emu/fragments/EmulationFragment.kt index e91876584..5b529e83c 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/fragments/EmulationFragment.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/fragments/EmulationFragment.kt @@ -287,6 +287,11 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram true } + R.id.menu_rotate_upright -> { + screenAdjustmentUtil.toggleScreenUpright() + true + } + R.id.menu_lock_drawer -> { when (EmulationMenuSettings.drawerLockMode) { DrawerLayout.LOCK_MODE_UNLOCKED -> { diff --git a/src/android/app/src/main/jni/config.cpp b/src/android/app/src/main/jni/config.cpp index 19e422324..37ebe6418 100644 --- a/src/android/app/src/main/jni/config.cpp +++ b/src/android/app/src/main/jni/config.cpp @@ -199,6 +199,7 @@ void Config::ReadValues() { ReadSetting("Layout", Settings::values.cardboard_screen_size); ReadSetting("Layout", Settings::values.cardboard_x_shift); ReadSetting("Layout", Settings::values.cardboard_y_shift); + ReadSetting("Layout", Settings::values.upright_screen); Settings::values.portrait_layout_option = static_cast(sdl2_config->GetInteger( diff --git a/src/android/app/src/main/res/drawable/ic_rotate_up_right.xml b/src/android/app/src/main/res/drawable/ic_rotate_up_right.xml new file mode 100644 index 000000000..aeff0d109 --- /dev/null +++ b/src/android/app/src/main/res/drawable/ic_rotate_up_right.xml @@ -0,0 +1,15 @@ + + + + + + + \ No newline at end of file diff --git a/src/android/app/src/main/res/menu/menu_in_game.xml b/src/android/app/src/main/res/menu/menu_in_game.xml index d42d59264..950ab6fc8 100644 --- a/src/android/app/src/main/res/menu/menu_in_game.xml +++ b/src/android/app/src/main/res/menu/menu_in_game.xml @@ -35,9 +35,13 @@ + + START HOME Swap Screens + Rotate Screen Upright X Y L diff --git a/src/core/frontend/emu_window.cpp b/src/core/frontend/emu_window.cpp index 6c2811cf0..aefb5184a 100644 --- a/src/core/frontend/emu_window.cpp +++ b/src/core/frontend/emu_window.cpp @@ -201,7 +201,8 @@ void EmuWindow::UpdateCurrentFramebufferLayout(u32 width, u32 height, bool is_po switch (portrait_layout_option) { case Settings::PortraitLayoutOption::PortraitTopFullWidth: layout = Layout::PortraitTopFullFrameLayout(width, height, - Settings::values.swap_screen.GetValue()); + Settings::values.swap_screen.GetValue(), + Settings::values.upright_screen.GetValue()); break; case Settings::PortraitLayoutOption::PortraitCustomLayout: layout = Layout::CustomFrameLayout( diff --git a/src/core/frontend/framebuffer_layout.cpp b/src/core/frontend/framebuffer_layout.cpp index 7cf52a29c..0f386781f 100644 --- a/src/core/frontend/framebuffer_layout.cpp +++ b/src/core/frontend/framebuffer_layout.cpp @@ -39,11 +39,11 @@ FramebufferLayout DefaultFrameLayout(u32 width, u32 height, bool swapped, bool u Settings::SmallScreenPosition::BelowLarge); } -FramebufferLayout PortraitTopFullFrameLayout(u32 width, u32 height, bool swapped) { +FramebufferLayout PortraitTopFullFrameLayout(u32 width, u32 height, bool swapped, bool upright) { ASSERT(width > 0); ASSERT(height > 0); const float scale_factor = swapped ? 1.25f : 0.8f; - FramebufferLayout res = LargeFrameLayout(width, height, swapped, false, scale_factor, + FramebufferLayout res = LargeFrameLayout(width, height, swapped, upright, scale_factor, Settings::SmallScreenPosition::BelowLarge); const int shiftY = -(int)(swapped ? res.bottom_screen.top : res.top_screen.top); res.top_screen = res.top_screen.TranslateY(shiftY); @@ -365,7 +365,8 @@ FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale, bool is_secondar width = Core::kScreenTopWidth * res_scale; height = (Core::kScreenTopHeight + Core::kScreenBottomHeight) * res_scale; return PortraitTopFullFrameLayout(width, height, - Settings::values.swap_screen.GetValue()); + Settings::values.swap_screen.GetValue(), + Settings::values.upright_screen.GetValue()); } } else { auto layout_option = Settings::values.layout_option.GetValue(); diff --git a/src/core/frontend/framebuffer_layout.h b/src/core/frontend/framebuffer_layout.h index adcf26630..554f81d45 100644 --- a/src/core/frontend/framebuffer_layout.h +++ b/src/core/frontend/framebuffer_layout.h @@ -69,7 +69,8 @@ FramebufferLayout DefaultFrameLayout(u32 width, u32 height, bool is_swapped, boo * @param is_swapped if true, the bottom screen will be displayed above the top screen * @return Newly created FramebufferLayout object with mobile portrait screen regions initialized */ -FramebufferLayout PortraitTopFullFrameLayout(u32 width, u32 height, bool is_swapped); +FramebufferLayout PortraitTopFullFrameLayout(u32 width, u32 height, bool is_swapped, + bool upright = false); /** * Factory method for constructing a FramebufferLayout with only the top or bottom screen