diff --git a/src/android/app/src/main/java/org/citra/citra_emu/display/ScreenLayout.kt b/src/android/app/src/main/java/org/citra/citra_emu/display/ScreenLayout.kt index 2ec4716b7..60f9e5dcd 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/display/ScreenLayout.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/display/ScreenLayout.kt @@ -41,7 +41,8 @@ enum class SmallScreenPosition(val int: Int) { enum class PortraitScreenLayout(val int: Int) { // These must match what is defined in src/common/settings.h TOP_FULL_WIDTH(0), - CUSTOM_PORTRAIT_LAYOUT(1); + CUSTOM_PORTRAIT_LAYOUT(1), + ORIGINAL(2); companion object { fun from(int: Int): PortraitScreenLayout { 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..765fcd5ec 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 @@ -886,10 +886,10 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram val layoutOptionMenuItem = when (IntSetting.PORTRAIT_SCREEN_LAYOUT.int) { PortraitScreenLayout.TOP_FULL_WIDTH.int -> R.id.menu_portrait_layout_top_full - PortraitScreenLayout.CUSTOM_PORTRAIT_LAYOUT.int -> R.id.menu_portrait_layout_custom - + PortraitScreenLayout.ORIGINAL.int -> + R.id.menu_portrait_layout_original else -> R.id.menu_portrait_layout_top_full @@ -914,6 +914,11 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram true } + R.id.menu_portrait_layout_original -> { + screenAdjustmentUtil.changePortraitOrientation(PortraitScreenLayout.ORIGINAL.int) + true + } + else -> true } } diff --git a/src/android/app/src/main/res/menu/menu_portrait_screen_layout.xml b/src/android/app/src/main/res/menu/menu_portrait_screen_layout.xml index afa9f27e0..4b8e4b7cd 100644 --- a/src/android/app/src/main/res/menu/menu_portrait_screen_layout.xml +++ b/src/android/app/src/main/res/menu/menu_portrait_screen_layout.xml @@ -11,6 +11,10 @@ android:id="@+id/menu_portrait_layout_custom" android:title="@string/emulation_screen_layout_custom" /> + + diff --git a/src/android/app/src/main/res/values/arrays.xml b/src/android/app/src/main/res/values/arrays.xml index 4159d9e4e..c50001792 100644 --- a/src/android/app/src/main/res/values/arrays.xml +++ b/src/android/app/src/main/res/values/arrays.xml @@ -32,11 +32,13 @@ @string/emulation_portrait_layout_top_full @string/emulation_screen_layout_custom + @string/emulation_screen_layout_original 0 1 + 2 diff --git a/src/common/settings.h b/src/common/settings.h index e484c1cd2..f96c0383e 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -51,6 +51,7 @@ enum class PortraitLayoutOption : u32 { // formerly mobile portrait PortraitTopFullWidth, PortraitCustomLayout, + PortraitOriginal }; /** Defines where the small screen will appear relative to the large screen diff --git a/src/core/frontend/emu_window.cpp b/src/core/frontend/emu_window.cpp index 6c2811cf0..963ac0ca9 100644 --- a/src/core/frontend/emu_window.cpp +++ b/src/core/frontend/emu_window.cpp @@ -207,6 +207,9 @@ void EmuWindow::UpdateCurrentFramebufferLayout(u32 width, u32 height, bool is_po layout = Layout::CustomFrameLayout( width, height, Settings::values.swap_screen.GetValue(), is_portrait_mode); break; + case Settings::PortraitLayoutOption::PortraitOriginal: + layout = Layout::PortraitOriginalLayout(width, height, Settings::values.swap_screen.GetValue()); + break; } } else { switch (layout_option) { diff --git a/src/core/frontend/framebuffer_layout.cpp b/src/core/frontend/framebuffer_layout.cpp index 7cf52a29c..0729cae34 100644 --- a/src/core/frontend/framebuffer_layout.cpp +++ b/src/core/frontend/framebuffer_layout.cpp @@ -51,6 +51,19 @@ FramebufferLayout PortraitTopFullFrameLayout(u32 width, u32 height, bool swapped return res; } +FramebufferLayout PortraitOriginalLayout(u32 width, u32 height, bool swapped) { + ASSERT(width > 0); + ASSERT(height > 0); + const float scale_factor = 1; + FramebufferLayout res = LargeFrameLayout(width, height, swapped, false, 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); + res.bottom_screen = res.bottom_screen.TranslateY(shiftY); + return res; + +} + FramebufferLayout SingleFrameLayout(u32 width, u32 height, bool swapped, bool upright) { ASSERT(width > 0); ASSERT(height > 0); @@ -346,7 +359,7 @@ FramebufferLayout CustomFrameLayout(u32 width, u32 height, bool is_swapped, bool FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale, bool is_secondary, bool is_portrait) { - int width, height; + u32 width, height; if (is_portrait) { auto layout_option = Settings::values.portrait_layout_option.GetValue(); switch (layout_option) { @@ -363,9 +376,13 @@ FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale, bool is_secondar Settings::values.swap_screen.GetValue(), is_portrait); case Settings::PortraitLayoutOption::PortraitTopFullWidth: width = Core::kScreenTopWidth * res_scale; - height = (Core::kScreenTopHeight + Core::kScreenBottomHeight) * res_scale; + height = static_cast(Core::kScreenTopHeight + Core::kScreenBottomHeight * 1.25) * res_scale; return PortraitTopFullFrameLayout(width, height, Settings::values.swap_screen.GetValue()); + case Settings::PortraitLayoutOption::PortraitOriginal: + width = Core::kScreenTopWidth * res_scale; + height = (Core::kScreenTopHeight + Core::kScreenBottomHeight) * res_scale; + return PortraitOriginalLayout(width, height, Settings::values.swap_screen.GetValue()); } } else { auto layout_option = Settings::values.layout_option.GetValue(); @@ -479,6 +496,7 @@ FramebufferLayout GetCardboardSettings(const FramebufferLayout& layout) { if (is_portrait) { switch (Settings::values.portrait_layout_option.GetValue()) { case Settings::PortraitLayoutOption::PortraitTopFullWidth: + case Settings::PortraitLayoutOption::PortraitOriginal: cardboard_screen_width = top_screen_width; cardboard_screen_height = top_screen_height + bottom_screen_height; bottom_screen_left += (top_screen_width - bottom_screen_width) / 2; diff --git a/src/core/frontend/framebuffer_layout.h b/src/core/frontend/framebuffer_layout.h index adcf26630..60bc2f437 100644 --- a/src/core/frontend/framebuffer_layout.h +++ b/src/core/frontend/framebuffer_layout.h @@ -62,8 +62,8 @@ FramebufferLayout reverseLayout(FramebufferLayout layout); FramebufferLayout DefaultFrameLayout(u32 width, u32 height, bool is_swapped, bool upright); /** - * Factory method for constructing the mobile Full Width Top layout - * Two screens at top, full width, no gap between them + * Factory method for constructing the mobile Full Width (Default) layout + * Two screens at top, full width (so different heights) * @param width Window framebuffer width in pixels * @param height Window framebuffer height in pixels * @param is_swapped if true, the bottom screen will be displayed above the top screen @@ -71,6 +71,16 @@ FramebufferLayout DefaultFrameLayout(u32 width, u32 height, bool is_swapped, boo */ FramebufferLayout PortraitTopFullFrameLayout(u32 width, u32 height, bool is_swapped); +/** + * Factory method for constructing the mobile Original layout + * Two screens at top, equal heights + * @param width Window framebuffer width in pixels + * @param height Window framebuffer height in pixels + * @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); + /** * Factory method for constructing a FramebufferLayout with only the top or bottom screen * @param width Window framebuffer width in pixels