From 13634f1db89833f8c3ca77cfc0730290e3603064 Mon Sep 17 00:00:00 2001 From: izzy2lost Date: Sat, 28 Feb 2026 05:58:45 -0500 Subject: [PATCH] added aspect ratio options --- android/app/src/main/cpp/xemu_android.cpp | 5 +++ .../com/izzy2lost/x1box/SettingsActivity.kt | 14 ++++++ .../src/main/res/layout/activity_settings.xml | 43 +++++++++++++++++++ android/app/src/main/res/values/strings.xml | 5 +++ ui/xemu.c | 21 ++++++++- 5 files changed, 87 insertions(+), 1 deletion(-) diff --git a/android/app/src/main/cpp/xemu_android.cpp b/android/app/src/main/cpp/xemu_android.cpp index f9a11bd6d1..9329049ee1 100644 --- a/android/app/src/main/cpp/xemu_android.cpp +++ b/android/app/src/main/cpp/xemu_android.cpp @@ -693,6 +693,8 @@ static bool WriteConfigToml(const std::string& config_path, return true; } +extern "C" void xemu_android_set_display_mode_setting(int mode); + static SetupFiles SyncSetupFiles() { SetupFiles out{}; JNIEnv* env = GetEnv(); @@ -800,6 +802,9 @@ static SetupFiles SyncSetupFiles() { } out.audio_driver = GetPrefString(env, activity, "setting_audio_driver"); + int displayMode = GetPrefInt(env, activity, "setting_display_mode", 0); + xemu_android_set_display_mode_setting(displayMode); + out.config_path = base + "/xemu.toml"; WriteConfigToml(out.config_path, out.mcpx, out.flash, out.hdd, out.dvd, out.eeprom, emuSettings); LogInfoFmt("SyncSetupFiles: config %s", out.config_path.c_str()); diff --git a/android/app/src/main/java/com/izzy2lost/x1box/SettingsActivity.kt b/android/app/src/main/java/com/izzy2lost/x1box/SettingsActivity.kt index d22fc3fa64..21364664a4 100644 --- a/android/app/src/main/java/com/izzy2lost/x1box/SettingsActivity.kt +++ b/android/app/src/main/java/com/izzy2lost/x1box/SettingsActivity.kt @@ -20,6 +20,7 @@ class SettingsActivity : AppCompatActivity() { val btn1x = findViewById(R.id.btn_scale_1x) val btn2x = findViewById(R.id.btn_scale_2x) val btn3x = findViewById(R.id.btn_scale_3x) + val toggleDisplayMode = findViewById(R.id.toggle_display_mode) val toggleThread = findViewById(R.id.toggle_tcg_thread) val btnMulti = findViewById(R.id.btn_thread_multi) val btnSingle = findViewById(R.id.btn_thread_single) @@ -38,6 +39,13 @@ class SettingsActivity : AppCompatActivity() { else -> toggleScale.check(R.id.btn_scale_1x) } + val displayMode = prefs.getInt("setting_display_mode", 0) + when (displayMode) { + 1 -> toggleDisplayMode.check(R.id.btn_display_4_3) + 2 -> toggleDisplayMode.check(R.id.btn_display_16_9) + else -> toggleDisplayMode.check(R.id.btn_display_stretch) + } + val tcgThread = prefs.getString("setting_tcg_thread", "multi") ?: "multi" if (tcgThread == "single") { toggleThread.check(R.id.btn_thread_single) @@ -58,6 +66,11 @@ class SettingsActivity : AppCompatActivity() { } btnSave.setOnClickListener { + val selectedDisplayMode = when (toggleDisplayMode.checkedButtonId) { + R.id.btn_display_4_3 -> 1 + R.id.btn_display_16_9 -> 2 + else -> 0 + } val selectedScale = when (toggleScale.checkedButtonId) { R.id.btn_scale_2x -> 2 R.id.btn_scale_3x -> 3 @@ -74,6 +87,7 @@ class SettingsActivity : AppCompatActivity() { } prefs.edit() + .putInt("setting_display_mode", selectedDisplayMode) .putInt("setting_surface_scale", selectedScale) .putString("setting_tcg_thread", selectedThread) .putBoolean("setting_use_dsp", switchDsp.isChecked) diff --git a/android/app/src/main/res/layout/activity_settings.xml b/android/app/src/main/res/layout/activity_settings.xml index e40afbfd49..3828ad5797 100644 --- a/android/app/src/main/res/layout/activity_settings.xml +++ b/android/app/src/main/res/layout/activity_settings.xml @@ -97,6 +97,49 @@ + + + + + + + + + + + + Save Display + Aspect Ratio + Stretch + 4:3 + 16:9 + Internal Resolution Scale 1x (Native 480p) 2x (960p) diff --git a/ui/xemu.c b/ui/xemu.c index 675b503062..cc4aae6676 100644 --- a/ui/xemu.c +++ b/ui/xemu.c @@ -137,6 +137,7 @@ static GLuint g_android_blit_vao; static GLuint g_android_blit_vbo; static GLint g_android_blit_tex_loc = -1; static GLint g_android_blit_flip_loc = -1; +static int g_android_display_mode = 0; /* 0=stretch, 1=4:3, 2=16:9 */ static GLuint g_android_cpu_tex = 0; static int g_android_cpu_tex_w = 0; static int g_android_cpu_tex_h = 0; @@ -202,6 +203,11 @@ static GLuint android_gl_compile_shader(GLenum type, const char *src) return shader; } +void xemu_android_set_display_mode_setting(int mode) +{ + g_android_display_mode = mode; +} + static bool android_blit_init(void) { if (g_android_blit_prog) { @@ -291,8 +297,21 @@ static void android_blit_frame(GLuint tex, bool flip) if (w <= 0) w = 1; if (h <= 0) h = 1; + int vx = 0, vy = 0, vw = w, vh = h; + if (g_android_display_mode != 0) { + float target = (g_android_display_mode == 1) ? (4.0f / 3.0f) : (16.0f / 9.0f); + float screen = (float)w / (float)h; + if (screen > target) { + vw = (int)(h * target); + vx = (w - vw) / 2; + } else { + vh = (int)(w / target); + vy = (h - vh) / 2; + } + } + glBindFramebuffer(GL_FRAMEBUFFER, 0); - glViewport(0, 0, w, h); + glViewport(vx, vy, vw, vh); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glDisable(GL_BLEND); glDisable(GL_DEPTH_TEST);