mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
add settings options
This commit is contained in:
@@ -43,5 +43,10 @@
|
||||
android:screenOrientation="fullSensor"
|
||||
android:exported="false" />
|
||||
|
||||
<activity
|
||||
android:name=".SettingsActivity"
|
||||
android:screenOrientation="fullSensor"
|
||||
android:exported="false" />
|
||||
|
||||
</application>
|
||||
</manifest>
|
||||
|
||||
@@ -329,6 +329,80 @@ cleanup:
|
||||
return out;
|
||||
}
|
||||
|
||||
static bool GetPrefBool(JNIEnv* env, jobject activity, const char* key, bool defValue) {
|
||||
if (!env || !activity || !key || key[0] == '\0') {
|
||||
return defValue;
|
||||
}
|
||||
bool out = defValue;
|
||||
jclass activityClass = env->GetObjectClass(activity);
|
||||
if (!activityClass) return defValue;
|
||||
jmethodID getPrefs = env->GetMethodID(activityClass, "getSharedPreferences",
|
||||
"(Ljava/lang/String;I)Landroid/content/SharedPreferences;");
|
||||
env->DeleteLocalRef(activityClass);
|
||||
if (!getPrefs) return defValue;
|
||||
jstring prefsName = env->NewStringUTF(kPrefsName);
|
||||
if (!prefsName) return defValue;
|
||||
jobject prefs = env->CallObjectMethod(activity, getPrefs, prefsName, 0);
|
||||
env->DeleteLocalRef(prefsName);
|
||||
if (HasException(env, "getSharedPreferences") || !prefs) return defValue;
|
||||
jclass prefsClass = env->GetObjectClass(prefs);
|
||||
if (prefsClass) {
|
||||
jmethodID contains = env->GetMethodID(prefsClass, "contains", "(Ljava/lang/String;)Z");
|
||||
jmethodID getBool = env->GetMethodID(prefsClass, "getBoolean", "(Ljava/lang/String;Z)Z");
|
||||
if (contains && getBool) {
|
||||
jstring jkey = env->NewStringUTF(key);
|
||||
if (jkey) {
|
||||
jboolean hasKey = env->CallBooleanMethod(prefs, contains, jkey);
|
||||
if (!HasException(env, "contains") && hasKey) {
|
||||
out = (bool)env->CallBooleanMethod(prefs, getBool, jkey, (jboolean)defValue);
|
||||
HasException(env, "getBoolean");
|
||||
}
|
||||
env->DeleteLocalRef(jkey);
|
||||
}
|
||||
}
|
||||
env->DeleteLocalRef(prefsClass);
|
||||
}
|
||||
env->DeleteLocalRef(prefs);
|
||||
return out;
|
||||
}
|
||||
|
||||
static int GetPrefInt(JNIEnv* env, jobject activity, const char* key, int defValue) {
|
||||
if (!env || !activity || !key || key[0] == '\0') {
|
||||
return defValue;
|
||||
}
|
||||
int out = defValue;
|
||||
jclass activityClass = env->GetObjectClass(activity);
|
||||
if (!activityClass) return defValue;
|
||||
jmethodID getPrefs = env->GetMethodID(activityClass, "getSharedPreferences",
|
||||
"(Ljava/lang/String;I)Landroid/content/SharedPreferences;");
|
||||
env->DeleteLocalRef(activityClass);
|
||||
if (!getPrefs) return defValue;
|
||||
jstring prefsName = env->NewStringUTF(kPrefsName);
|
||||
if (!prefsName) return defValue;
|
||||
jobject prefs = env->CallObjectMethod(activity, getPrefs, prefsName, 0);
|
||||
env->DeleteLocalRef(prefsName);
|
||||
if (HasException(env, "getSharedPreferences") || !prefs) return defValue;
|
||||
jclass prefsClass = env->GetObjectClass(prefs);
|
||||
if (prefsClass) {
|
||||
jmethodID contains = env->GetMethodID(prefsClass, "contains", "(Ljava/lang/String;)Z");
|
||||
jmethodID getInt = env->GetMethodID(prefsClass, "getInt", "(Ljava/lang/String;I)I");
|
||||
if (contains && getInt) {
|
||||
jstring jkey = env->NewStringUTF(key);
|
||||
if (jkey) {
|
||||
jboolean hasKey = env->CallBooleanMethod(prefs, contains, jkey);
|
||||
if (!HasException(env, "contains") && hasKey) {
|
||||
out = (int)env->CallIntMethod(prefs, getInt, jkey, (jint)defValue);
|
||||
HasException(env, "getInt");
|
||||
}
|
||||
env->DeleteLocalRef(jkey);
|
||||
}
|
||||
}
|
||||
env->DeleteLocalRef(prefsClass);
|
||||
}
|
||||
env->DeleteLocalRef(prefs);
|
||||
return out;
|
||||
}
|
||||
|
||||
static bool CopyUriToPath(JNIEnv* env, jobject activity, const std::string& uriString, const std::string& path) {
|
||||
if (!env || !activity || uriString.empty() || path.empty()) return false;
|
||||
|
||||
@@ -488,6 +562,15 @@ cleanup:
|
||||
return success;
|
||||
}
|
||||
|
||||
struct EmulatorSettings {
|
||||
int surface_scale = 1; // 1, 2, or 3
|
||||
std::string tcg_thread = "multi"; // "single" or "multi"
|
||||
bool use_dsp = true;
|
||||
bool hrtf = true;
|
||||
bool cache_shaders = true;
|
||||
bool hard_fpu = true;
|
||||
};
|
||||
|
||||
struct SetupFiles {
|
||||
std::string mcpx;
|
||||
std::string flash;
|
||||
@@ -503,7 +586,8 @@ static bool WriteConfigToml(const std::string& config_path,
|
||||
const std::string& flash,
|
||||
const std::string& hdd,
|
||||
const std::string& dvd,
|
||||
const std::string& eeprom) {
|
||||
const std::string& eeprom,
|
||||
const EmulatorSettings& settings) {
|
||||
if (config_path.empty()) return false;
|
||||
toml::table tbl;
|
||||
|
||||
@@ -527,14 +611,16 @@ static bool WriteConfigToml(const std::string& config_path,
|
||||
|
||||
toml::table* general = EnsureTable(tbl, "general");
|
||||
toml::table* display = EnsureTable(tbl, "display");
|
||||
toml::table* display_quality = EnsureTable(*display, "quality");
|
||||
toml::table* display_window = EnsureTable(*display, "window");
|
||||
toml::table* audio = EnsureTable(tbl, "audio");
|
||||
toml::table* audio_vp = EnsureTable(*audio, "vp");
|
||||
toml::table* android = EnsureTable(tbl, "android");
|
||||
toml::table* sys = EnsureTable(tbl, "sys");
|
||||
toml::table* perf = EnsureTable(tbl, "perf");
|
||||
toml::table* files = EnsureTable(*sys, "files");
|
||||
if (!general || !display || !display_window || !audio || !audio_vp ||
|
||||
!android || !sys || !files) {
|
||||
if (!general || !display || !display_quality || !display_window || !audio ||
|
||||
!audio_vp || !android || !sys || !perf || !files) {
|
||||
LogErrorFmt("Failed to build config tables at %s", config_path.c_str());
|
||||
return false;
|
||||
}
|
||||
@@ -547,12 +633,22 @@ static bool WriteConfigToml(const std::string& config_path,
|
||||
if (!display_window->contains("vsync")) {
|
||||
display_window->insert_or_assign("vsync", false);
|
||||
}
|
||||
// User-controlled settings (always written so they take effect immediately)
|
||||
{
|
||||
int scale = settings.surface_scale;
|
||||
if (scale < 1) scale = 1;
|
||||
if (scale > 3) scale = 3;
|
||||
display_quality->insert_or_assign("surface_scale", scale);
|
||||
}
|
||||
audio->insert_or_assign("use_dsp", settings.use_dsp);
|
||||
audio->insert_or_assign("hrtf", settings.hrtf);
|
||||
perf->insert_or_assign("cache_shaders", settings.cache_shaders);
|
||||
perf->insert_or_assign("hard_fpu", settings.hard_fpu);
|
||||
android->insert_or_assign("tcg_thread",
|
||||
(settings.tcg_thread == "single") ? "single" : "multi");
|
||||
if (!audio_vp->contains("num_workers")) {
|
||||
audio_vp->insert_or_assign("num_workers", 0);
|
||||
}
|
||||
if (!audio->contains("hrtf")) {
|
||||
audio->insert_or_assign("hrtf", true);
|
||||
}
|
||||
if (!audio->contains("volume_limit")) {
|
||||
audio->insert_or_assign("volume_limit", 1.0);
|
||||
}
|
||||
@@ -562,9 +658,6 @@ static bool WriteConfigToml(const std::string& config_path,
|
||||
if (!android->contains("tcg_tuning")) {
|
||||
android->insert_or_assign("tcg_tuning", true);
|
||||
}
|
||||
if (!android->contains("tcg_thread")) {
|
||||
android->insert_or_assign("tcg_thread", "multi");
|
||||
}
|
||||
if (!android->contains("tcg_tb_size")) {
|
||||
android->insert_or_assign("tcg_tb_size", 128);
|
||||
}
|
||||
@@ -681,8 +774,21 @@ static SetupFiles SyncSetupFiles() {
|
||||
}
|
||||
}
|
||||
|
||||
EmulatorSettings emuSettings;
|
||||
emuSettings.surface_scale = GetPrefInt(env, activity, "setting_surface_scale", 1);
|
||||
emuSettings.use_dsp = GetPrefBool(env, activity, "setting_use_dsp", true);
|
||||
emuSettings.hrtf = GetPrefBool(env, activity, "setting_hrtf", true);
|
||||
emuSettings.cache_shaders = GetPrefBool(env, activity, "setting_cache_shaders", true);
|
||||
emuSettings.hard_fpu = GetPrefBool(env, activity, "setting_hard_fpu", true);
|
||||
{
|
||||
std::string tcgThread = GetPrefString(env, activity, "setting_tcg_thread");
|
||||
if (tcgThread == "single") {
|
||||
emuSettings.tcg_thread = "single";
|
||||
}
|
||||
}
|
||||
|
||||
out.config_path = base + "/xemu.toml";
|
||||
WriteConfigToml(out.config_path, out.mcpx, out.flash, out.hdd, out.dvd, out.eeprom);
|
||||
WriteConfigToml(out.config_path, out.mcpx, out.flash, out.hdd, out.dvd, out.eeprom, emuSettings);
|
||||
LogInfoFmt("SyncSetupFiles: config %s", out.config_path.c_str());
|
||||
LogInfoFmt("Resolved mcpx=%s", out.mcpx.c_str());
|
||||
LogInfoFmt("Resolved flash=%s", out.flash.c_str());
|
||||
|
||||
@@ -229,6 +229,7 @@ bool xemu_settings_load(void)
|
||||
// Cache table lookups to avoid repeated traversal
|
||||
auto general = tbl["general"];
|
||||
auto display = tbl["display"];
|
||||
auto display_quality = display["quality"];
|
||||
auto display_window = display["window"];
|
||||
auto audio = tbl["audio"];
|
||||
auto audio_vp = audio["vp"];
|
||||
@@ -253,6 +254,13 @@ bool xemu_settings_load(void)
|
||||
}
|
||||
}
|
||||
|
||||
if (auto surface_scale = display_quality["surface_scale"].value<int64_t>()) {
|
||||
int scale = (int)*surface_scale;
|
||||
if (scale < 1) scale = 1;
|
||||
if (scale > 3) scale = 3;
|
||||
g_config.display.quality.surface_scale = scale;
|
||||
}
|
||||
|
||||
if (auto filtering = display["filtering"].value<std::string>()) {
|
||||
CONFIG_DISPLAY_FILTERING parsed;
|
||||
if (parse_filtering(*filtering, &parsed)) {
|
||||
|
||||
@@ -71,6 +71,7 @@ class GameLibraryActivity : AppCompatActivity() {
|
||||
private lateinit var gamesListContainer: LinearLayout
|
||||
private lateinit var gamesGridContainer: LinearLayout
|
||||
private lateinit var btnChangeFolder: MaterialButton
|
||||
private lateinit var btnSettings: MaterialButton
|
||||
private lateinit var btnConvertIso: MaterialButton
|
||||
private lateinit var btnAbout: ImageButton
|
||||
private lateinit var viewModeToggle: MaterialButtonToggleGroup
|
||||
@@ -110,6 +111,7 @@ class GameLibraryActivity : AppCompatActivity() {
|
||||
gamesListContainer = findViewById(R.id.library_games_container)
|
||||
gamesGridContainer = findViewById(R.id.library_games_grid_container)
|
||||
btnChangeFolder = findViewById(R.id.btn_change_games_folder)
|
||||
btnSettings = findViewById(R.id.btn_settings)
|
||||
btnConvertIso = findViewById(R.id.btn_convert_iso)
|
||||
btnAbout = findViewById(R.id.btn_library_about)
|
||||
viewModeToggle = findViewById(R.id.library_view_mode_toggle)
|
||||
@@ -130,6 +132,9 @@ class GameLibraryActivity : AppCompatActivity() {
|
||||
}
|
||||
pickGamesFolder.launch(gamesFolderUri)
|
||||
}
|
||||
btnSettings.setOnClickListener {
|
||||
startActivity(Intent(this, SettingsActivity::class.java))
|
||||
}
|
||||
btnConvertIso.setOnClickListener {
|
||||
showIsoConversionPicker()
|
||||
}
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
package com.izzy2lost.x1box
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.google.android.material.button.MaterialButton
|
||||
import com.google.android.material.button.MaterialButtonToggleGroup
|
||||
import com.google.android.material.materialswitch.MaterialSwitch
|
||||
|
||||
class SettingsActivity : AppCompatActivity() {
|
||||
|
||||
private val prefs by lazy { getSharedPreferences("x1box_prefs", Context.MODE_PRIVATE) }
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_settings)
|
||||
|
||||
val toggleScale = findViewById<MaterialButtonToggleGroup>(R.id.toggle_resolution_scale)
|
||||
val btn1x = findViewById<MaterialButton>(R.id.btn_scale_1x)
|
||||
val btn2x = findViewById<MaterialButton>(R.id.btn_scale_2x)
|
||||
val btn3x = findViewById<MaterialButton>(R.id.btn_scale_3x)
|
||||
val toggleThread = findViewById<MaterialButtonToggleGroup>(R.id.toggle_tcg_thread)
|
||||
val btnMulti = findViewById<MaterialButton>(R.id.btn_thread_multi)
|
||||
val btnSingle = findViewById<MaterialButton>(R.id.btn_thread_single)
|
||||
val switchDsp = findViewById<MaterialSwitch>(R.id.switch_use_dsp)
|
||||
val switchHrtf = findViewById<MaterialSwitch>(R.id.switch_hrtf)
|
||||
val switchShaders= findViewById<MaterialSwitch>(R.id.switch_cache_shaders)
|
||||
val switchFpu = findViewById<MaterialSwitch>(R.id.switch_hard_fpu)
|
||||
val btnSave = findViewById<MaterialButton>(R.id.btn_settings_save)
|
||||
|
||||
// Load current values
|
||||
val scale = prefs.getInt("setting_surface_scale", 1)
|
||||
when (scale) {
|
||||
2 -> toggleScale.check(R.id.btn_scale_2x)
|
||||
3 -> toggleScale.check(R.id.btn_scale_3x)
|
||||
else -> toggleScale.check(R.id.btn_scale_1x)
|
||||
}
|
||||
|
||||
val tcgThread = prefs.getString("setting_tcg_thread", "multi") ?: "multi"
|
||||
if (tcgThread == "single") {
|
||||
toggleThread.check(R.id.btn_thread_single)
|
||||
} else {
|
||||
toggleThread.check(R.id.btn_thread_multi)
|
||||
}
|
||||
|
||||
switchDsp.isChecked = prefs.getBoolean("setting_use_dsp", true)
|
||||
switchHrtf.isChecked = prefs.getBoolean("setting_hrtf", true)
|
||||
switchShaders.isChecked = prefs.getBoolean("setting_cache_shaders", true)
|
||||
switchFpu.isChecked = prefs.getBoolean("setting_hard_fpu", true)
|
||||
|
||||
btnSave.setOnClickListener {
|
||||
val selectedScale = when (toggleScale.checkedButtonId) {
|
||||
R.id.btn_scale_2x -> 2
|
||||
R.id.btn_scale_3x -> 3
|
||||
else -> 1
|
||||
}
|
||||
val selectedThread = when (toggleThread.checkedButtonId) {
|
||||
R.id.btn_thread_single -> "single"
|
||||
else -> "multi"
|
||||
}
|
||||
|
||||
prefs.edit()
|
||||
.putInt("setting_surface_scale", selectedScale)
|
||||
.putString("setting_tcg_thread", selectedThread)
|
||||
.putBoolean("setting_use_dsp", switchDsp.isChecked)
|
||||
.putBoolean("setting_hrtf", switchHrtf.isChecked)
|
||||
.putBoolean("setting_cache_shaders", switchShaders.isChecked)
|
||||
.putBoolean("setting_hard_fpu", switchFpu.isChecked)
|
||||
.apply()
|
||||
|
||||
Toast.makeText(this, R.string.settings_saved, Toast.LENGTH_SHORT).show()
|
||||
finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -86,6 +86,17 @@
|
||||
app:iconGravity="textStart"
|
||||
app:iconPadding="8dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_settings"
|
||||
style="?attr/materialButtonOutlinedStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="@string/library_settings"
|
||||
app:icon="@android:drawable/ic_menu_preferences"
|
||||
app:iconGravity="textStart"
|
||||
app:iconPadding="8dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_convert_iso"
|
||||
style="?attr/materialButtonOutlinedStyle"
|
||||
|
||||
@@ -0,0 +1,197 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/setup_wizard_background"
|
||||
android:fitsSystemWindows="true">
|
||||
|
||||
<androidx.core.widget.NestedScrollView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:clipToPadding="false"
|
||||
android:fillViewport="true"
|
||||
android:padding="24dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_horizontal"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:cardBackgroundColor="@color/xemu_surface"
|
||||
app:cardCornerRadius="28dp"
|
||||
app:cardElevation="8dp"
|
||||
app:strokeColor="@color/xemu_outline_variant"
|
||||
app:strokeWidth="1dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="24dp">
|
||||
|
||||
<!-- Title -->
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="20dp"
|
||||
android:text="@string/settings_title"
|
||||
android:textAppearance="@style/TextAppearance.Material3.HeadlineMedium" />
|
||||
|
||||
<!-- ── DISPLAY ── -->
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:text="@string/settings_section_display"
|
||||
android:textAppearance="@style/TextAppearance.Material3.LabelLarge"
|
||||
android:textColor="@color/xemu_green" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="6dp"
|
||||
android:text="@string/settings_resolution_scale"
|
||||
android:textAppearance="@style/TextAppearance.Material3.BodyMedium"
|
||||
android:textColor="@color/xemu_text_muted" />
|
||||
|
||||
<com.google.android.material.button.MaterialButtonToggleGroup
|
||||
android:id="@+id/toggle_resolution_scale"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="16dp"
|
||||
app:selectionRequired="true"
|
||||
app:singleSelection="true">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_scale_1x"
|
||||
style="?attr/materialButtonOutlinedStyle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/settings_resolution_scale_1x" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_scale_2x"
|
||||
style="?attr/materialButtonOutlinedStyle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/settings_resolution_scale_2x" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_scale_3x"
|
||||
style="?attr/materialButtonOutlinedStyle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/settings_resolution_scale_3x" />
|
||||
|
||||
</com.google.android.material.button.MaterialButtonToggleGroup>
|
||||
|
||||
<!-- ── PERFORMANCE ── -->
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:text="@string/settings_section_performance"
|
||||
android:textAppearance="@style/TextAppearance.Material3.LabelLarge"
|
||||
android:textColor="@color/xemu_green" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="6dp"
|
||||
android:text="@string/settings_tcg_thread"
|
||||
android:textAppearance="@style/TextAppearance.Material3.BodyMedium"
|
||||
android:textColor="@color/xemu_text_muted" />
|
||||
|
||||
<com.google.android.material.button.MaterialButtonToggleGroup
|
||||
android:id="@+id/toggle_tcg_thread"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
app:selectionRequired="true"
|
||||
app:singleSelection="true">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_thread_multi"
|
||||
style="?attr/materialButtonOutlinedStyle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/settings_tcg_thread_multi" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_thread_single"
|
||||
style="?attr/materialButtonOutlinedStyle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/settings_tcg_thread_single" />
|
||||
|
||||
</com.google.android.material.button.MaterialButtonToggleGroup>
|
||||
|
||||
<com.google.android.material.materialswitch.MaterialSwitch
|
||||
android:id="@+id/switch_hard_fpu"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:text="@string/settings_hard_fpu"
|
||||
android:textColor="@color/xemu_text_muted" />
|
||||
|
||||
<com.google.android.material.materialswitch.MaterialSwitch
|
||||
android:id="@+id/switch_cache_shaders"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:text="@string/settings_cache_shaders"
|
||||
android:textColor="@color/xemu_text_muted" />
|
||||
|
||||
<!-- ── AUDIO ── -->
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:text="@string/settings_section_audio"
|
||||
android:textAppearance="@style/TextAppearance.Material3.LabelLarge"
|
||||
android:textColor="@color/xemu_green" />
|
||||
|
||||
<com.google.android.material.materialswitch.MaterialSwitch
|
||||
android:id="@+id/switch_use_dsp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/settings_use_dsp"
|
||||
android:textColor="@color/xemu_text_muted" />
|
||||
|
||||
<com.google.android.material.materialswitch.MaterialSwitch
|
||||
android:id="@+id/switch_hrtf"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:text="@string/settings_hrtf"
|
||||
android:textColor="@color/xemu_text_muted" />
|
||||
|
||||
<!-- Save button -->
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_settings_save"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp"
|
||||
android:text="@string/settings_save" />
|
||||
|
||||
</LinearLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
</LinearLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -73,6 +73,30 @@
|
||||
<string name="library_about_url_license" translatable="false">https://github.com/izzy2lost/xemu/blob/master/LICENSE</string>
|
||||
<string name="library_about_url_disclaimer" translatable="false">https://github.com/izzy2lost/xemu/blob/master/COPYING</string>
|
||||
|
||||
<string name="library_settings">Settings</string>
|
||||
|
||||
<string name="settings_title">Settings</string>
|
||||
<string name="settings_save">Save</string>
|
||||
|
||||
<string name="settings_section_display">Display</string>
|
||||
<string name="settings_resolution_scale">Internal Resolution Scale</string>
|
||||
<string name="settings_resolution_scale_1x">1x (Native 480p)</string>
|
||||
<string name="settings_resolution_scale_2x">2x (960p)</string>
|
||||
<string name="settings_resolution_scale_3x">3x (1440p)</string>
|
||||
|
||||
<string name="settings_section_performance">Performance</string>
|
||||
<string name="settings_tcg_thread">CPU Threading Mode</string>
|
||||
<string name="settings_tcg_thread_multi">Multi-thread</string>
|
||||
<string name="settings_tcg_thread_single">Single-thread</string>
|
||||
<string name="settings_hard_fpu">Hardware FPU</string>
|
||||
<string name="settings_cache_shaders">Shader Cache</string>
|
||||
|
||||
<string name="settings_section_audio">Audio</string>
|
||||
<string name="settings_use_dsp">Real-time DSP Processing</string>
|
||||
<string name="settings_hrtf">HRTF (3D Audio)</string>
|
||||
|
||||
<string name="settings_saved">Settings saved</string>
|
||||
|
||||
<string name="in_game_menu_title">Game Menu</string>
|
||||
<string name="in_game_menu_resume">Resume</string>
|
||||
<string name="in_game_menu_restart_game">Restart Game</string>
|
||||
|
||||
Reference in New Issue
Block a user