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..105f49ab8 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 @@ -1,4 +1,4 @@ -// Copyright 2023 Citra Emulator Project +// Copyright Citra Emulator Project / Azahar Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. @@ -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 06b8167ab..ef62087e1 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 @@ -45,7 +45,8 @@ enum class BooleanSetting( USE_FRAME_LIMIT("use_frame_limit", Settings.SECTION_RENDERER, true), DEBUG_RENDERER("renderer_debug", Settings.SECTION_DEBUG, false), DISABLE_RIGHT_EYE_RENDER("disable_right_eye_render", Settings.SECTION_RENDERER, false), - USE_ARTIC_BASE_CONTROLLER("use_artic_base_controller", Settings.SECTION_CONTROLS, false); + USE_ARTIC_BASE_CONTROLLER("use_artic_base_controller", Settings.SECTION_CONTROLS, false), + UPRIGHT_SCREEN("upright_screen", 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 428a2d226..fc0b40d67 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 @@ -1072,6 +1072,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 7aeecf453..e1f653a09 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 @@ -306,6 +306,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 08e492a7b..9df017a6f 100644 --- a/src/android/app/src/main/jni/config.cpp +++ b/src/android/app/src/main/jni/config.cpp @@ -202,6 +202,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 @@ + + Height Cycle Layouts Swap Screens + Rotate Screen Upright Reset Overlay Show Controller Overlay Close Game diff --git a/src/core/frontend/emu_window.cpp b/src/core/frontend/emu_window.cpp index 85abe0959..70658cf29 100644 --- a/src/core/frontend/emu_window.cpp +++ b/src/core/frontend/emu_window.cpp @@ -215,7 +215,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( @@ -223,7 +224,8 @@ void EmuWindow::UpdateCurrentFramebufferLayout(u32 width, u32 height, bool is_po break; case Settings::PortraitLayoutOption::PortraitOriginal: layout = Layout::PortraitOriginalLayout(width, height, - Settings::values.swap_screen.GetValue()); + Settings::values.swap_screen.GetValue(), + Settings::values.upright_screen.GetValue()); break; } } else { diff --git a/src/core/frontend/framebuffer_layout.cpp b/src/core/frontend/framebuffer_layout.cpp index 4a1cbf3e5..0e930900a 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); @@ -51,11 +51,11 @@ FramebufferLayout PortraitTopFullFrameLayout(u32 width, u32 height, bool swapped return res; } -FramebufferLayout PortraitOriginalLayout(u32 width, u32 height, bool swapped) { +FramebufferLayout PortraitOriginalLayout(u32 width, u32 height, bool swapped, bool upright) { ASSERT(width > 0); ASSERT(height > 0); const float scale_factor = 1; - 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); @@ -408,7 +408,8 @@ FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale, bool is_secondar res_scale) + gap; // clang-format on return PortraitTopFullFrameLayout(width, height, - Settings::values.swap_screen.GetValue()); + Settings::values.swap_screen.GetValue(), + Settings::values.upright_screen.GetValue()); case Settings::PortraitLayoutOption::PortraitOriginal: width = Core::kScreenTopWidth * res_scale; height = (Core::kScreenTopHeight + Core::kScreenBottomHeight) * res_scale; diff --git a/src/core/frontend/framebuffer_layout.h b/src/core/frontend/framebuffer_layout.h index 8c315f515..6e4dc45a8 100644 --- a/src/core/frontend/framebuffer_layout.h +++ b/src/core/frontend/framebuffer_layout.h @@ -71,7 +71,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 the mobile Original layout @@ -81,7 +82,8 @@ FramebufferLayout PortraitTopFullFrameLayout(u32 width, u32 height, bool is_swap * @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 PortraitOriginalLayout(u32 width, u32 height, bool is_swapped); +FramebufferLayout PortraitOriginalLayout(u32 width, u32 height, bool is_swapped, + bool upright = false); /** * Factory method for constructing a FramebufferLayout with only the top or bottom screen