feat: Implement 32:9 aspect ratio

This commit introduces support for a 32:9 aspect ratio throughout Citron.

Key changes include:

-   **Enum Updates**: Added `R32_9` to `Settings::AspectRatio` and `Layout::AspectRatio` enums, ensuring consistent integer mapping for casting between them.
-   **Core Logic**:
    -   Modified `UISettings::CalculateWidth` to correctly compute width for the 32:9 ratio.
    -   Updated `Layout::EmulationAspectRatio` to handle the new `R32_9` case and return the appropriate float value (9.0f / 32.0f).
-   **Android Integration**:
    -   Updated `EmulationFragment.kt` and `EmulationActivity.kt` (for Picture-in-Picture) to recognize and apply the 32:9 aspect ratio (mapping setting value `4` to `Rational(32, 9)`).
-   **UI Configuration**:
    -   Added "Force 32:9" to the aspect ratio selection in the graphics settings UI via `shared_translation.cpp`. This string is translatable.

This enhancement allows users to utilize ultra-widescreen 32:9 displays for a more immersive experience.

Signed-off-by: Zephyron <zephyron@citron-emu.org>
This commit is contained in:
Zephyron
2025-05-18 15:10:47 +10:00
parent 0d46968e6c
commit c5604ced4f
7 changed files with 22 additions and 7 deletions

View File

@@ -1,4 +1,5 @@
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project // SPDX-FileCopyrightText: 2023 yuzu Emulator Project
// SPDX-FileCopyrightText: 2025 citron Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
package org.citron.citron_emu.activities package org.citron.citron_emu.activities
@@ -312,6 +313,7 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
1 -> Rational(4, 3) 1 -> Rational(4, 3)
2 -> Rational(21, 9) 2 -> Rational(21, 9)
3 -> Rational(16, 10) 3 -> Rational(16, 10)
4 -> Rational(32, 9)
else -> null // Best fit else -> null // Best fit
} }
return this.apply { aspectRatio?.let { setAspectRatio(it) } } return this.apply { aspectRatio?.let { setAspectRatio(it) } }

View File

@@ -1,4 +1,5 @@
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project // SPDX-FileCopyrightText: 2023 yuzu Emulator Project
// SPDX-FileCopyrightText: 2025 citron Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
package org.citron.citron_emu.fragments package org.citron.citron_emu.fragments
@@ -577,6 +578,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
1 -> Rational(4, 3) 1 -> Rational(4, 3)
2 -> Rational(21, 9) 2 -> Rational(21, 9)
3 -> Rational(16, 10) 3 -> Rational(16, 10)
4 -> Rational(32, 9)
else -> null // Best fit else -> null // Best fit
} }
when (verticalAlignment) { when (verticalAlignment) {

View File

@@ -1,4 +1,5 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include "citron/configuration/shared_translation.h" #include "citron/configuration/shared_translation.h"
@@ -56,18 +57,18 @@ std::unique_ptr<TranslationMap> InitializeTranslations(QWidget* parent) {
// Core // Core
INSERT( INSERT(
Settings, use_multi_core, tr("Multicore CPU Emulation"), Settings, use_multi_core, tr("Multicore CPU Emulation"),
tr("This option increases CPU emulation thread use from 1 to the Switchs maximum of 4.\n" tr("This option increases CPU emulation thread use from 1 to the Switch's maximum of 4.\n"
"This is mainly a debug option and shouldnt be disabled.")); "This is mainly a debug option and shouldn't be disabled."));
INSERT( INSERT(
Settings, memory_layout_mode, tr("Memory Layout"), Settings, memory_layout_mode, tr("Memory Layout"),
tr("Increases the amount of emulated RAM from the stock 4GB of the retail Switch to the " tr("Increases the amount of emulated RAM from the stock 4GB of the retail Switch to the "
"developer kit's 8/6GB.\nIts doesnt improve stability or performance and is intended " "developer kit's 8/6GB.\nIt's doesn't improve stability or performance and is intended "
"to let big texture mods fit in emulated RAM.\nEnabling it will increase memory " "to let big texture mods fit in emulated RAM.\nEnabling it will increase memory "
"use. It is not recommended to enable unless a specific game with a texture mod needs " "use. It is not recommended to enable unless a specific game with a texture mod needs "
"it.")); "it."));
INSERT(Settings, use_speed_limit, QStringLiteral(), QStringLiteral()); INSERT(Settings, use_speed_limit, QStringLiteral(), QStringLiteral());
INSERT(Settings, speed_limit, tr("Limit Speed Percent"), INSERT(Settings, speed_limit, tr("Limit Speed Percent"),
tr("Controls the game's maximum rendering speed, but its up to each game if it runs " tr("Controls the game's maximum rendering speed, but it's up to each game if it runs "
"faster or not.\n200% for a 30 FPS game is 60 FPS, and for a " "faster or not.\n200% for a 30 FPS game is 60 FPS, and for a "
"60 FPS game it will be 120 FPS.\nDisabling it means unlocking the framerate to the " "60 FPS game it will be 120 FPS.\nDisabling it means unlocking the framerate to the "
"maximum your PC can reach.")); "maximum your PC can reach."));
@@ -125,7 +126,7 @@ std::unique_ptr<TranslationMap> InitializeTranslations(QWidget* parent) {
"Options lower than 1X can cause rendering issues.")); "Options lower than 1X can cause rendering issues."));
INSERT(Settings, scaling_filter, tr("Window Adapting Filter:"), QStringLiteral()); INSERT(Settings, scaling_filter, tr("Window Adapting Filter:"), QStringLiteral());
INSERT(Settings, fsr_sharpening_slider, tr("FSR Sharpness:"), INSERT(Settings, fsr_sharpening_slider, tr("FSR Sharpness:"),
tr("Determines how sharpened the image will look while using FSRs dynamic contrast.")); tr("Determines how sharpened the image will look while using FSR's dynamic contrast."));
INSERT(Settings, anti_aliasing, tr("Anti-Aliasing Method:"), INSERT(Settings, anti_aliasing, tr("Anti-Aliasing Method:"),
tr("The anti-aliasing method to use.\nSMAA offers the best quality.\nFXAA has a " tr("The anti-aliasing method to use.\nSMAA offers the best quality.\nFXAA has a "
"lower performance impact and can produce a better and more stable picture under " "lower performance impact and can produce a better and more stable picture under "
@@ -188,7 +189,7 @@ std::unique_ptr<TranslationMap> InitializeTranslations(QWidget* parent) {
tr("Runs work in the background while waiting for graphics commands to keep the GPU from " tr("Runs work in the background while waiting for graphics commands to keep the GPU from "
"lowering its clock speed.")); "lowering its clock speed."));
INSERT(Settings, max_anisotropy, tr("Anisotropic Filtering:"), INSERT(Settings, max_anisotropy, tr("Anisotropic Filtering:"),
tr("Controls the quality of texture rendering at oblique angles.\nIts a light setting " tr("Controls the quality of texture rendering at oblique angles.\nIt's a light setting "
"and safe to set at 16x on most GPUs.")); "and safe to set at 16x on most GPUs."));
INSERT(Settings, gpu_accuracy, tr("Accuracy Level:"), INSERT(Settings, gpu_accuracy, tr("Accuracy Level:"),
tr("GPU emulation accuracy.\nMost games render fine with Normal, but High is still " tr("GPU emulation accuracy.\nMost games render fine with Normal, but High is still "
@@ -406,6 +407,7 @@ std::unique_ptr<ComboboxTranslationMap> ComboboxEnumeration(QWidget* parent) {
PAIR(AspectRatio, R4_3, tr("Force 4:3")), PAIR(AspectRatio, R4_3, tr("Force 4:3")),
PAIR(AspectRatio, R21_9, tr("Force 21:9")), PAIR(AspectRatio, R21_9, tr("Force 21:9")),
PAIR(AspectRatio, R16_10, tr("Force 16:10")), PAIR(AspectRatio, R16_10, tr("Force 16:10")),
PAIR(AspectRatio, R32_9, tr("Force 32:9")),
PAIR(AspectRatio, Stretch, tr("Stretch to Window")), PAIR(AspectRatio, Stretch, tr("Stretch to Window")),
}}); }});
translations->insert({Settings::EnumMetadata<Settings::AnisotropyMode>::Index(), translations->insert({Settings::EnumMetadata<Settings::AnisotropyMode>::Index(),

View File

@@ -1,4 +1,5 @@
// SPDX-FileCopyrightText: 2016 Citra Emulator Project // SPDX-FileCopyrightText: 2016 Citra Emulator Project
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include <QSettings> #include <QSettings>
@@ -47,6 +48,8 @@ u32 CalculateWidth(u32 height, Settings::AspectRatio ratio) {
return height * 21 / 9; return height * 21 / 9;
case Settings::AspectRatio::R16_10: case Settings::AspectRatio::R16_10:
return height * 16 / 10; return height * 16 / 10;
case Settings::AspectRatio::R32_9:
return height * 32 / 9;
case Settings::AspectRatio::R16_9: case Settings::AspectRatio::R16_9:
case Settings::AspectRatio::Stretch: case Settings::AspectRatio::Stretch:
// TODO: Move this function wherever appropriate to implement Stretched aspect // TODO: Move this function wherever appropriate to implement Stretched aspect

View File

@@ -1,4 +1,5 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#pragma once #pragma once
@@ -149,7 +150,7 @@ ENUM(ScalingFilter, NearestNeighbor, Bilinear, Bicubic, Gaussian, ScaleForce, Fs
ENUM(AntiAliasing, None, Fxaa, Smaa, MaxEnum); ENUM(AntiAliasing, None, Fxaa, Smaa, MaxEnum);
ENUM(AspectRatio, R16_9, R4_3, R21_9, R16_10, Stretch); ENUM(AspectRatio, R16_9, R4_3, R21_9, R16_10, R32_9, Stretch);
ENUM(ConsoleMode, Handheld, Docked); ENUM(ConsoleMode, Handheld, Docked);

View File

@@ -1,4 +1,5 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include <cmath> #include <cmath>
@@ -70,6 +71,8 @@ float EmulationAspectRatio(AspectRatio aspect, float window_aspect_ratio) {
return 9.0f / 21.0f; return 9.0f / 21.0f;
case AspectRatio::R16_10: case AspectRatio::R16_10:
return 10.0f / 16.0f; return 10.0f / 16.0f;
case AspectRatio::R32_9:
return 9.0f / 32.0f;
case AspectRatio::StretchToWindow: case AspectRatio::StretchToWindow:
return window_aspect_ratio; return window_aspect_ratio;
default: default:

View File

@@ -1,4 +1,5 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#pragma once #pragma once
@@ -28,6 +29,7 @@ enum class AspectRatio {
R4_3, R4_3,
R21_9, R21_9,
R16_10, R16_10,
R32_9,
StretchToWindow, StretchToWindow,
}; };