summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt8
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt6
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/AbstractBooleanSetting.kt4
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/AbstractByteSetting.kt (renamed from src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/SettingsViewModel.kt)6
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/AbstractFloatSetting.kt4
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/AbstractIntSetting.kt4
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/AbstractLongSetting.kt10
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/AbstractSetting.kt13
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/AbstractShortSetting.kt10
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/AbstractStringSetting.kt4
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt57
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/ByteSetting.kt25
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/FloatSetting.kt32
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/IntSetting.kt151
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/LongSetting.kt25
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/SettingSection.kt37
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/Settings.kt316
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/ShortSetting.kt25
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/StringSetting.kt36
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/DateTimeSetting.kt18
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt2
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SingleChoiceSetting.kt2
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SliderSetting.kt24
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/StringSingleChoiceSetting.kt2
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SwitchSetting.kt4
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivity.kt30
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivityPresenter.kt15
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivityView.kt19
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsAdapter.kt62
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragment.kt9
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt181
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentView.kt16
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/DateTimeViewHolder.kt2
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/utils/SettingsFile.kt255
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt4
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/BiMap.kt25
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/NativeConfig.kt31
-rw-r--r--src/android/app/src/main/jni/CMakeLists.txt2
-rw-r--r--src/android/app/src/main/jni/config.cpp31
-rw-r--r--src/android/app/src/main/jni/config.h24
-rw-r--r--src/android/app/src/main/jni/native.cpp28
-rw-r--r--src/android/app/src/main/jni/native_config.cpp224
-rw-r--r--src/android/app/src/main/jni/uisettings.cpp10
-rw-r--r--src/android/app/src/main/jni/uisettings.h29
-rw-r--r--src/android/app/src/main/res/values/arrays.xml10
-rw-r--r--src/android/app/src/main/res/values/strings.xml1
-rw-r--r--src/common/settings.cpp2
-rw-r--r--src/common/settings_common.cpp1
-rw-r--r--src/common/settings_common.h2
49 files changed, 869 insertions, 969 deletions
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt
index 9c32e044c..5a7cf4ed7 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt
@@ -219,10 +219,6 @@ object NativeLibrary {
external fun reloadSettings()
- external fun getUserSetting(gameID: String?, Section: String?, Key: String?): String?
-
- external fun setUserSetting(gameID: String?, Section: String?, Key: String?, Value: String?)
-
external fun initGameIni(gameID: String?)
/**
@@ -413,14 +409,17 @@ object NativeLibrary {
details.ifEmpty { emulationActivity.getString(R.string.system_archive_general) }
)
}
+
CoreError.ErrorSavestate -> {
title = emulationActivity.getString(R.string.save_load_error)
message = details
}
+
CoreError.ErrorUnknown -> {
title = emulationActivity.getString(R.string.fatal_error)
message = emulationActivity.getString(R.string.fatal_error_message)
}
+
else -> {
return true
}
@@ -454,6 +453,7 @@ object NativeLibrary {
captionId = R.string.loader_error_video_core
descriptionId = R.string.loader_error_video_core_description
}
+
else -> {
captionId = R.string.loader_error_encrypted
descriptionId = R.string.loader_error_encrypted_roms_description
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt
index 7461fb093..6f52a7a8d 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt
@@ -28,7 +28,6 @@ import android.view.Surface
import android.view.View
import android.view.inputmethod.InputMethodManager
import android.widget.Toast
-import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsCompat
@@ -42,7 +41,6 @@ import org.yuzu.yuzu_emu.databinding.ActivityEmulationBinding
import org.yuzu.yuzu_emu.features.settings.model.BooleanSetting
import org.yuzu.yuzu_emu.features.settings.model.IntSetting
import org.yuzu.yuzu_emu.features.settings.model.Settings
-import org.yuzu.yuzu_emu.features.settings.model.SettingsViewModel
import org.yuzu.yuzu_emu.model.Game
import org.yuzu.yuzu_emu.utils.ControllerMappingHelper
import org.yuzu.yuzu_emu.utils.ForegroundService
@@ -72,8 +70,6 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
private val actionMute = "ACTION_EMULATOR_MUTE"
private val actionUnmute = "ACTION_EMULATOR_UNMUTE"
- private val settingsViewModel: SettingsViewModel by viewModels()
-
override fun onDestroy() {
stopForegroundService(this)
super.onDestroy()
@@ -82,8 +78,6 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
override fun onCreate(savedInstanceState: Bundle?) {
ThemeHelper.setTheme(this)
- settingsViewModel.settings.loadSettings()
-
super.onCreate(savedInstanceState)
binding = ActivityEmulationBinding.inflate(layoutInflater)
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/AbstractBooleanSetting.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/AbstractBooleanSetting.kt
index a6e9833ee..aeda8d222 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/AbstractBooleanSetting.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/AbstractBooleanSetting.kt
@@ -4,5 +4,7 @@
package org.yuzu.yuzu_emu.features.settings.model
interface AbstractBooleanSetting : AbstractSetting {
- var boolean: Boolean
+ val boolean: Boolean
+
+ fun setBoolean(value: Boolean)
}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/SettingsViewModel.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/AbstractByteSetting.kt
index bd9233d62..606519ad8 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/SettingsViewModel.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/AbstractByteSetting.kt
@@ -3,8 +3,8 @@
package org.yuzu.yuzu_emu.features.settings.model
-import androidx.lifecycle.ViewModel
+interface AbstractByteSetting : AbstractSetting {
+ val byte: Byte
-class SettingsViewModel : ViewModel() {
- val settings = Settings()
+ fun setByte(value: Byte)
}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/AbstractFloatSetting.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/AbstractFloatSetting.kt
index 6fe4bc263..974925eed 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/AbstractFloatSetting.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/AbstractFloatSetting.kt
@@ -4,5 +4,7 @@
package org.yuzu.yuzu_emu.features.settings.model
interface AbstractFloatSetting : AbstractSetting {
- var float: Float
+ val float: Float
+
+ fun setFloat(value: Float)
}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/AbstractIntSetting.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/AbstractIntSetting.kt
index 892b7dcfe..89b285b10 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/AbstractIntSetting.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/AbstractIntSetting.kt
@@ -4,5 +4,7 @@
package org.yuzu.yuzu_emu.features.settings.model
interface AbstractIntSetting : AbstractSetting {
- var int: Int
+ val int: Int
+
+ fun setInt(value: Int)
}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/AbstractLongSetting.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/AbstractLongSetting.kt
new file mode 100644
index 000000000..4873942db
--- /dev/null
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/AbstractLongSetting.kt
@@ -0,0 +1,10 @@
+// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.yuzu.yuzu_emu.features.settings.model
+
+interface AbstractLongSetting : AbstractSetting {
+ val long: Long
+
+ fun setLong(value: Long)
+}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/AbstractSetting.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/AbstractSetting.kt
index 258580209..7afed95ad 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/AbstractSetting.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/AbstractSetting.kt
@@ -3,10 +3,17 @@
package org.yuzu.yuzu_emu.features.settings.model
+import org.yuzu.yuzu_emu.utils.NativeConfig
+
interface AbstractSetting {
val key: String?
- val section: String?
- val isRuntimeEditable: Boolean
- val valueAsString: String
+ val category: Settings.Category
val defaultValue: Any
+ val valueAsString: String
+ get() = ""
+
+ val isRuntimeModifiable: Boolean
+ get() = NativeConfig.getIsRuntimeModifiable(key!!)
+
+ fun reset() = run { }
}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/AbstractShortSetting.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/AbstractShortSetting.kt
new file mode 100644
index 000000000..91407ccbb
--- /dev/null
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/AbstractShortSetting.kt
@@ -0,0 +1,10 @@
+// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.yuzu.yuzu_emu.features.settings.model
+
+interface AbstractShortSetting : AbstractSetting {
+ val short: Short
+
+ fun setShort(value: Short)
+}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/AbstractStringSetting.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/AbstractStringSetting.kt
index 0d02c5997..c8935cc48 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/AbstractStringSetting.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/AbstractStringSetting.kt
@@ -4,5 +4,7 @@
package org.yuzu.yuzu_emu.features.settings.model
interface AbstractStringSetting : AbstractSetting {
- var string: String
+ val string: String
+
+ fun setString(value: String)
}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt
index d41933766..f7528642e 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt
@@ -3,41 +3,34 @@
package org.yuzu.yuzu_emu.features.settings.model
+import org.yuzu.yuzu_emu.utils.NativeConfig
+
enum class BooleanSetting(
override val key: String,
- override val section: String,
- override val defaultValue: Boolean
+ override val category: Settings.Category
) : AbstractBooleanSetting {
- CPU_DEBUG_MODE("cpu_debug_mode", Settings.SECTION_CPU, false),
- FASTMEM("cpuopt_fastmem", Settings.SECTION_CPU, true),
- FASTMEM_EXCLUSIVES("cpuopt_fastmem_exclusives", Settings.SECTION_CPU, true),
- PICTURE_IN_PICTURE("picture_in_picture", Settings.SECTION_GENERAL, true),
- USE_CUSTOM_RTC("custom_rtc_enabled", Settings.SECTION_SYSTEM, false);
-
- override var boolean: Boolean = defaultValue
+ CPU_DEBUG_MODE("cpu_debug_mode", Settings.Category.Cpu),
+ FASTMEM("cpuopt_fastmem", Settings.Category.Cpu),
+ FASTMEM_EXCLUSIVES("cpuopt_fastmem_exclusives", Settings.Category.Cpu),
+ RENDERER_USE_SPEED_LIMIT("use_speed_limit", Settings.Category.Core),
+ USE_DOCKED_MODE("use_docked_mode", Settings.Category.System),
+ RENDERER_USE_DISK_SHADER_CACHE("use_disk_shader_cache", Settings.Category.Renderer),
+ RENDERER_FORCE_MAX_CLOCK("force_max_clock", Settings.Category.Renderer),
+ RENDERER_ASYNCHRONOUS_SHADERS("use_asynchronous_shaders", Settings.Category.Renderer),
+ RENDERER_REACTIVE_FLUSHING("use_reactive_flushing", Settings.Category.Renderer),
+ RENDERER_DEBUG("debug", Settings.Category.Renderer),
+ PICTURE_IN_PICTURE("picture_in_picture", Settings.Category.Android),
+ USE_CUSTOM_RTC("custom_rtc_enabled", Settings.Category.System);
+
+ override val boolean: Boolean
+ get() = NativeConfig.getBoolean(key, false)
+
+ override fun setBoolean(value: Boolean) = NativeConfig.setBoolean(key, value)
+
+ override val defaultValue: Boolean by lazy { NativeConfig.getBoolean(key, true) }
override val valueAsString: String
- get() = boolean.toString()
-
- override val isRuntimeEditable: Boolean
- get() {
- for (setting in NOT_RUNTIME_EDITABLE) {
- if (setting == this) {
- return false
- }
- }
- return true
- }
-
- companion object {
- private val NOT_RUNTIME_EDITABLE = listOf(
- PICTURE_IN_PICTURE,
- USE_CUSTOM_RTC
- )
-
- fun from(key: String): BooleanSetting? =
- BooleanSetting.values().firstOrNull { it.key == key }
-
- fun clear() = BooleanSetting.values().forEach { it.boolean = it.defaultValue }
- }
+ get() = if (boolean) "1" else "0"
+
+ override fun reset() = NativeConfig.setBoolean(key, defaultValue)
}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/ByteSetting.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/ByteSetting.kt
new file mode 100644
index 000000000..6ec0a765e
--- /dev/null
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/ByteSetting.kt
@@ -0,0 +1,25 @@
+// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.yuzu.yuzu_emu.features.settings.model
+
+import org.yuzu.yuzu_emu.utils.NativeConfig
+
+enum class ByteSetting(
+ override val key: String,
+ override val category: Settings.Category
+) : AbstractByteSetting {
+ AUDIO_VOLUME("volume", Settings.Category.Audio);
+
+ override val byte: Byte
+ get() = NativeConfig.getByte(key, false)
+
+ override fun setByte(value: Byte) = NativeConfig.setByte(key, value)
+
+ override val defaultValue: Byte by lazy { NativeConfig.getByte(key, true) }
+
+ override val valueAsString: String
+ get() = byte.toString()
+
+ override fun reset() = NativeConfig.setByte(key, defaultValue)
+}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/FloatSetting.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/FloatSetting.kt
index e5545a916..0181d06f2 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/FloatSetting.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/FloatSetting.kt
@@ -3,34 +3,24 @@
package org.yuzu.yuzu_emu.features.settings.model
+import org.yuzu.yuzu_emu.utils.NativeConfig
+
enum class FloatSetting(
override val key: String,
- override val section: String,
- override val defaultValue: Float
+ override val category: Settings.Category
) : AbstractFloatSetting {
// No float settings currently exist
- EMPTY_SETTING("", "", 0f);
-
- override var float: Float = defaultValue
+ EMPTY_SETTING("", Settings.Category.UiGeneral);
- override val valueAsString: String
- get() = float.toString()
+ override val float: Float
+ get() = NativeConfig.getFloat(key, false)
- override val isRuntimeEditable: Boolean
- get() {
- for (setting in NOT_RUNTIME_EDITABLE) {
- if (setting == this) {
- return false
- }
- }
- return true
- }
+ override fun setFloat(value: Float) = NativeConfig.setFloat(key, value)
- companion object {
- private val NOT_RUNTIME_EDITABLE = emptyList<FloatSetting>()
+ override val defaultValue: Float by lazy { NativeConfig.getFloat(key, true) }
- fun from(key: String): FloatSetting? = FloatSetting.values().firstOrNull { it.key == key }
+ override val valueAsString: String
+ get() = float.toString()
- fun clear() = FloatSetting.values().forEach { it.float = it.defaultValue }
- }
+ override fun reset() = NativeConfig.setFloat(key, defaultValue)
}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/IntSetting.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/IntSetting.kt
index 4427a7d9d..a64757207 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/IntSetting.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/IntSetting.kt
@@ -3,139 +3,34 @@
package org.yuzu.yuzu_emu.features.settings.model
+import org.yuzu.yuzu_emu.utils.NativeConfig
+
enum class IntSetting(
override val key: String,
- override val section: String,
- override val defaultValue: Int
+ override val category: Settings.Category
) : AbstractIntSetting {
- RENDERER_USE_SPEED_LIMIT(
- "use_speed_limit",
- Settings.SECTION_RENDERER,
- 1
- ),
- USE_DOCKED_MODE(
- "use_docked_mode",
- Settings.SECTION_SYSTEM,
- 0
- ),
- RENDERER_USE_DISK_SHADER_CACHE(
- "use_disk_shader_cache",
- Settings.SECTION_RENDERER,
- 1
- ),
- RENDERER_FORCE_MAX_CLOCK(
- "force_max_clock",
- Settings.SECTION_RENDERER,
- 0
- ),
- RENDERER_ASYNCHRONOUS_SHADERS(
- "use_asynchronous_shaders",
- Settings.SECTION_RENDERER,
- 0
- ),
- RENDERER_REACTIVE_FLUSHING(
- "use_reactive_flushing",
- Settings.SECTION_RENDERER,
- 0
- ),
- RENDERER_DEBUG(
- "debug",
- Settings.SECTION_RENDERER,
- 0
- ),
- RENDERER_SPEED_LIMIT(
- "speed_limit",
- Settings.SECTION_RENDERER,
- 100
- ),
- CPU_ACCURACY(
- "cpu_accuracy",
- Settings.SECTION_CPU,
- 0
- ),
- REGION_INDEX(
- "region_index",
- Settings.SECTION_SYSTEM,
- -1
- ),
- LANGUAGE_INDEX(
- "language_index",
- Settings.SECTION_SYSTEM,
- 1
- ),
- RENDERER_BACKEND(
- "backend",
- Settings.SECTION_RENDERER,
- 1
- ),
- RENDERER_ACCURACY(
- "gpu_accuracy",
- Settings.SECTION_RENDERER,
- 0
- ),
- RENDERER_RESOLUTION(
- "resolution_setup",
- Settings.SECTION_RENDERER,
- 2
- ),
- RENDERER_VSYNC(
- "use_vsync",
- Settings.SECTION_RENDERER,
- 0
- ),
- RENDERER_SCALING_FILTER(
- "scaling_filter",
- Settings.SECTION_RENDERER,
- 1
- ),
- RENDERER_ANTI_ALIASING(
- "anti_aliasing",
- Settings.SECTION_RENDERER,
- 0
- ),
- RENDERER_SCREEN_LAYOUT(
- "screen_layout",
- Settings.SECTION_RENDERER,
- Settings.LayoutOption_MobileLandscape
- ),
- RENDERER_ASPECT_RATIO(
- "aspect_ratio",
- Settings.SECTION_RENDERER,
- 0
- ),
- AUDIO_VOLUME(
- "volume",
- Settings.SECTION_AUDIO,
- 100
- );
-
- override var int: Int = defaultValue
+ CPU_ACCURACY("cpu_accuracy", Settings.Category.Cpu),
+ REGION_INDEX("region_index", Settings.Category.System),
+ LANGUAGE_INDEX("language_index", Settings.Category.System),
+ RENDERER_BACKEND("backend", Settings.Category.Renderer),
+ RENDERER_ACCURACY("gpu_accuracy", Settings.Category.Renderer),
+ RENDERER_RESOLUTION("resolution_setup", Settings.Category.Renderer),
+ RENDERER_VSYNC("use_vsync", Settings.Category.Renderer),
+ RENDERER_SCALING_FILTER("scaling_filter", Settings.Category.Renderer),
+ RENDERER_ANTI_ALIASING("anti_aliasing", Settings.Category.Renderer),
+ RENDERER_SCREEN_LAYOUT("screen_layout", Settings.Category.Android),
+ RENDERER_ASPECT_RATIO("aspect_ratio", Settings.Category.Renderer),
+ AUDIO_OUTPUT_ENGINE("output_engine", Settings.Category.Audio);
+
+ override val int: Int
+ get() = NativeConfig.getInt(key, false)
+
+ override fun setInt(value: Int) = NativeConfig.setInt(key, value)
+
+ override val defaultValue: Int by lazy { NativeConfig.getInt(key, true) }
override val valueAsString: String
get() = int.toString()
- override val isRuntimeEditable: Boolean
- get() {
- for (setting in NOT_RUNTIME_EDITABLE) {
- if (setting == this) {
- return false
- }
- }
- return true
- }
-
- companion object {
- private val NOT_RUNTIME_EDITABLE = listOf(
- RENDERER_USE_DISK_SHADER_CACHE,
- RENDERER_ASYNCHRONOUS_SHADERS,
- RENDERER_DEBUG,
- RENDERER_BACKEND,
- RENDERER_RESOLUTION,
- RENDERER_VSYNC
- )
-
- fun from(key: String): IntSetting? = IntSetting.values().firstOrNull { it.key == key }
-
- fun clear() = IntSetting.values().forEach { it.int = it.defaultValue }
- }
+ override fun reset() = NativeConfig.setInt(key, defaultValue)
}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/LongSetting.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/LongSetting.kt
new file mode 100644
index 000000000..c526fc4cf
--- /dev/null
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/LongSetting.kt
@@ -0,0 +1,25 @@
+// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.yuzu.yuzu_emu.features.settings.model
+
+import org.yuzu.yuzu_emu.utils.NativeConfig
+
+enum class LongSetting(
+ override val key: String,
+ override val category: Settings.Category
+) : AbstractLongSetting {
+ CUSTOM_RTC("custom_rtc", Settings.Category.System);
+
+ override val long: Long
+ get() = NativeConfig.getLong(key, false)
+
+ override fun setLong(value: Long) = NativeConfig.setLong(key, value)
+
+ override val defaultValue: Long by lazy { NativeConfig.getLong(key, true) }
+
+ override val valueAsString: String
+ get() = long.toString()
+
+ override fun reset() = NativeConfig.setLong(key, defaultValue)
+}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/SettingSection.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/SettingSection.kt
deleted file mode 100644
index 474f598a9..000000000
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/SettingSection.kt
+++ /dev/null
@@ -1,37 +0,0 @@
-// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package org.yuzu.yuzu_emu.features.settings.model
-
-/**
- * A semantically-related group of Settings objects. These Settings are
- * internally stored as a HashMap.
- */
-class SettingSection(val name: String) {
- val settings = HashMap<String, AbstractSetting>()
-
- /**
- * Convenience method; inserts a value directly into the backing HashMap.
- *
- * @param setting The Setting to be inserted.
- */
- fun putSetting(setting: AbstractSetting) {
- settings[setting.key!!] = setting
- }
-
- /**
- * Convenience method; gets a value directly from the backing HashMap.
- *
- * @param key Used to retrieve the Setting.
- * @return A Setting object (you should probably cast this before using)
- */
- fun getSetting(key: String): AbstractSetting? {
- return settings[key]
- }
-
- fun mergeSection(settingSection: SettingSection) {
- for (setting in settingSection.settings.values) {
- putSetting(setting)
- }
- }
-}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/Settings.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/Settings.kt
index a6251bafd..0702236e8 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/Settings.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/Settings.kt
@@ -4,195 +4,151 @@
package org.yuzu.yuzu_emu.features.settings.model
import android.text.TextUtils
-import java.util.*
+import android.widget.Toast
import org.yuzu.yuzu_emu.R
import org.yuzu.yuzu_emu.YuzuApplication
-import org.yuzu.yuzu_emu.features.settings.ui.SettingsActivityView
import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile
-class Settings {
- private var gameId: String? = null
+object Settings {
+ private val context get() = YuzuApplication.appContext
- var isLoaded = false
-
- /**
- * A HashMap<String></String>, SettingSection> that constructs a new SettingSection instead of returning null
- * when getting a key not already in the map
- */
- class SettingsSectionMap : HashMap<String, SettingSection?>() {
- override operator fun get(key: String): SettingSection? {
- if (!super.containsKey(key)) {
- val section = SettingSection(key)
- super.put(key, section)
- return section
- }
- return super.get(key)
- }
- }
-
- var sections: HashMap<String, SettingSection?> = SettingsSectionMap()
-
- fun getSection(sectionName: String): SettingSection? {
- return sections[sectionName]
- }
-
- val isEmpty: Boolean
- get() = sections.isEmpty()
-
- fun loadSettings(view: SettingsActivityView? = null) {
- sections = SettingsSectionMap()
- loadYuzuSettings(view)
- if (!TextUtils.isEmpty(gameId)) {
- loadCustomGameSettings(gameId!!, view)
- }
- isLoaded = true
- }
-
- private fun loadYuzuSettings(view: SettingsActivityView?) {
- for ((fileName) in configFileSectionsMap) {
- sections.putAll(SettingsFile.readFile(fileName, view))
- }
- }
-
- private fun loadCustomGameSettings(gameId: String, view: SettingsActivityView?) {
- // Custom game settings
- mergeSections(SettingsFile.readCustomGameSettings(gameId, view))
- }
-
- private fun mergeSections(updatedSections: HashMap<String, SettingSection?>) {
- for ((key, updatedSection) in updatedSections) {
- if (sections.containsKey(key)) {
- val originalSection = sections[key]
- originalSection!!.mergeSection(updatedSection!!)
- } else {
- sections[key] = updatedSection
- }
- }
- }
-
- fun loadSettings(gameId: String, view: SettingsActivityView) {
- this.gameId = gameId
- loadSettings(view)
- }
-
- fun saveSettings(view: SettingsActivityView) {
+ fun saveSettings(gameId: String = "") {
if (TextUtils.isEmpty(gameId)) {
- view.showToastMessage(
- YuzuApplication.appContext.getString(R.string.ini_saved),
- false
- )
-
- for ((fileName, sectionNames) in configFileSectionsMap) {
- val iniSections = TreeMap<String, SettingSection>()
- for (section in sectionNames) {
- iniSections[section] = sections[section]!!
- }
-
- SettingsFile.saveFile(fileName, iniSections, view)
- }
+ Toast.makeText(
+ context,
+ context.getString(R.string.ini_saved),
+ Toast.LENGTH_SHORT
+ ).show()
+ SettingsFile.saveFile(SettingsFile.FILE_NAME_CONFIG)
} else {
- // Custom game settings
- view.showToastMessage(
- YuzuApplication.appContext.getString(R.string.gameid_saved, gameId),
- false
- )
-
- SettingsFile.saveCustomGameSettings(gameId, sections)
+ // TODO: Save custom game settings
+ Toast.makeText(
+ context,
+ context.getString(R.string.gameid_saved, gameId),
+ Toast.LENGTH_SHORT
+ ).show()
}
}
- companion object {
- const val SECTION_GENERAL = "General"
- const val SECTION_SYSTEM = "System"
- const val SECTION_RENDERER = "Renderer"
- const val SECTION_AUDIO = "Audio"
- const val SECTION_CPU = "Cpu"
- const val SECTION_THEME = "Theme"
- const val SECTION_DEBUG = "Debug"
-
- const val PREF_MEMORY_WARNING_SHOWN = "MemoryWarningShown"
-
- const val PREF_OVERLAY_VERSION = "OverlayVersion"
- const val PREF_LANDSCAPE_OVERLAY_VERSION = "LandscapeOverlayVersion"
- const val PREF_PORTRAIT_OVERLAY_VERSION = "PortraitOverlayVersion"
- const val PREF_FOLDABLE_OVERLAY_VERSION = "FoldableOverlayVersion"
- val overlayLayoutPrefs = listOf(
- PREF_LANDSCAPE_OVERLAY_VERSION,
- PREF_PORTRAIT_OVERLAY_VERSION,
- PREF_FOLDABLE_OVERLAY_VERSION
- )
-
- const val PREF_CONTROL_SCALE = "controlScale"
- const val PREF_CONTROL_OPACITY = "controlOpacity"
- const val PREF_TOUCH_ENABLED = "isTouchEnabled"
- const val PREF_BUTTON_A = "buttonToggle0"
- const val PREF_BUTTON_B = "buttonToggle1"
- const val PREF_BUTTON_X = "buttonToggle2"
- const val PREF_BUTTON_Y = "buttonToggle3"
- const val PREF_BUTTON_L = "buttonToggle4"
- const val PREF_BUTTON_R = "buttonToggle5"
- const val PREF_BUTTON_ZL = "buttonToggle6"
- const val PREF_BUTTON_ZR = "buttonToggle7"
- const val PREF_BUTTON_PLUS = "buttonToggle8"
- const val PREF_BUTTON_MINUS = "buttonToggle9"
- const val PREF_BUTTON_DPAD = "buttonToggle10"
- const val PREF_STICK_L = "buttonToggle11"
- const val PREF_STICK_R = "buttonToggle12"
- const val PREF_BUTTON_STICK_L = "buttonToggle13"
- const val PREF_BUTTON_STICK_R = "buttonToggle14"
- const val PREF_BUTTON_HOME = "buttonToggle15"
- const val PREF_BUTTON_SCREENSHOT = "buttonToggle16"
-
- const val PREF_MENU_SETTINGS_JOYSTICK_REL_CENTER = "EmulationMenuSettings_JoystickRelCenter"
- const val PREF_MENU_SETTINGS_DPAD_SLIDE = "EmulationMenuSettings_DpadSlideEnable"
- const val PREF_MENU_SETTINGS_HAPTICS = "EmulationMenuSettings_Haptics"
- const val PREF_MENU_SETTINGS_SHOW_FPS = "EmulationMenuSettings_ShowFps"
- const val PREF_MENU_SETTINGS_SHOW_OVERLAY = "EmulationMenuSettings_ShowOverlay"
-
- const val PREF_FIRST_APP_LAUNCH = "FirstApplicationLaunch"
- const val PREF_THEME = "Theme"
- const val PREF_THEME_MODE = "ThemeMode"
- const val PREF_BLACK_BACKGROUNDS = "BlackBackgrounds"
-
- private val configFileSectionsMap: MutableMap<String, List<String>> = HashMap()
-
- val overlayPreferences = listOf(
- PREF_OVERLAY_VERSION,
- PREF_CONTROL_SCALE,
- PREF_CONTROL_OPACITY,
- PREF_TOUCH_ENABLED,
- PREF_BUTTON_A,
- PREF_BUTTON_B,
- PREF_BUTTON_X,
- PREF_BUTTON_Y,
- PREF_BUTTON_L,
- PREF_BUTTON_R,
- PREF_BUTTON_ZL,
- PREF_BUTTON_ZR,
- PREF_BUTTON_PLUS,
- PREF_BUTTON_MINUS,
- PREF_BUTTON_DPAD,
- PREF_STICK_L,
- PREF_STICK_R,
- PREF_BUTTON_HOME,
- PREF_BUTTON_SCREENSHOT,
- PREF_BUTTON_STICK_L,
- PREF_BUTTON_STICK_R
- )
-
- const val LayoutOption_Unspecified = 0
- const val LayoutOption_MobilePortrait = 4
- const val LayoutOption_MobileLandscape = 5
-
- init {
- configFileSectionsMap[SettingsFile.FILE_NAME_CONFIG] =
- listOf(
- SECTION_GENERAL,
- SECTION_SYSTEM,
- SECTION_RENDERER,
- SECTION_AUDIO,
- SECTION_CPU
- )
- }
+ enum class Category {
+ Android,
+ Audio,
+ Core,
+ Cpu,
+ CpuDebug,
+ CpuUnsafe,
+ Renderer,
+ RendererAdvanced,
+ RendererDebug,
+ System,
+ SystemAudio,
+ DataStorage,
+ Debugging,
+ DebuggingGraphics,
+ Miscellaneous,
+ Network,
+ WebService,
+ AddOns,
+ Controls,
+ Ui,
+ UiGeneral,
+ UiLayout,
+ UiGameList,
+ Screenshots,
+ Shortcuts,
+ Multiplayer,
+ Services,
+ Paths,
+ MaxEnum
}
+
+ val settingsList = listOf<AbstractSetting>(
+ *BooleanSetting.values(),
+ *ByteSetting.values(),
+ *ShortSetting.values(),
+ *IntSetting.values(),
+ *FloatSetting.values(),
+ *LongSetting.values(),
+ *StringSetting.values()
+ )
+
+ const val SECTION_GENERAL = "General"
+ const val SECTION_SYSTEM = "System"
+ const val SECTION_RENDERER = "Renderer"
+ const val SECTION_AUDIO = "Audio"
+ const val SECTION_CPU = "Cpu"
+ const val SECTION_THEME = "Theme"
+ const val SECTION_DEBUG = "Debug"
+
+ const val PREF_MEMORY_WARNING_SHOWN = "MemoryWarningShown"
+
+ const val PREF_OVERLAY_VERSION = "OverlayVersion"
+ const val PREF_LANDSCAPE_OVERLAY_VERSION = "LandscapeOverlayVersion"
+ const val PREF_PORTRAIT_OVERLAY_VERSION = "PortraitOverlayVersion"
+ const val PREF_FOLDABLE_OVERLAY_VERSION = "FoldableOverlayVersion"
+ val overlayLayoutPrefs = listOf(
+ PREF_LANDSCAPE_OVERLAY_VERSION,
+ PREF_PORTRAIT_OVERLAY_VERSION,
+ PREF_FOLDABLE_OVERLAY_VERSION
+ )
+
+ const val PREF_CONTROL_SCALE = "controlScale"
+ const val PREF_CONTROL_OPACITY = "controlOpacity"
+ const val PREF_TOUCH_ENABLED = "isTouchEnabled"
+ const val PREF_BUTTON_A = "buttonToggle0"
+ const val PREF_BUTTON_B = "buttonToggle1"
+ const val PREF_BUTTON_X = "buttonToggle2"
+ const val PREF_BUTTON_Y = "buttonToggle3"
+ const val PREF_BUTTON_L = "buttonToggle4"
+ const val PREF_BUTTON_R = "buttonToggle5"
+ const val PREF_BUTTON_ZL = "buttonToggle6"
+ const val PREF_BUTTON_ZR = "buttonToggle7"
+ const val PREF_BUTTON_PLUS = "buttonToggle8"
+ const val PREF_BUTTON_MINUS = "buttonToggle9"
+ const val PREF_BUTTON_DPAD = "buttonToggle10"
+ const val PREF_STICK_L = "buttonToggle11"
+ const val PREF_STICK_R = "buttonToggle12"
+ const val PREF_BUTTON_STICK_L = "buttonToggle13"
+ const val PREF_BUTTON_STICK_R = "buttonToggle14"
+ const val PREF_BUTTON_HOME = "buttonToggle15"
+ const val PREF_BUTTON_SCREENSHOT = "buttonToggle16"
+
+ const val PREF_MENU_SETTINGS_JOYSTICK_REL_CENTER = "EmulationMenuSettings_JoystickRelCenter"
+ const val PREF_MENU_SETTINGS_DPAD_SLIDE = "EmulationMenuSettings_DpadSlideEnable"
+ const val PREF_MENU_SETTINGS_HAPTICS = "EmulationMenuSettings_Haptics"
+ const val PREF_MENU_SETTINGS_SHOW_FPS = "EmulationMenuSettings_ShowFps"
+ const val PREF_MENU_SETTINGS_SHOW_OVERLAY = "EmulationMenuSettings_ShowOverlay"
+
+ const val PREF_FIRST_APP_LAUNCH = "FirstApplicationLaunch"
+ const val PREF_THEME = "Theme"
+ const val PREF_THEME_MODE = "ThemeMode"
+ const val PREF_BLACK_BACKGROUNDS = "BlackBackgrounds"
+
+ val overlayPreferences = listOf(
+ PREF_OVERLAY_VERSION,
+ PREF_CONTROL_SCALE,
+ PREF_CONTROL_OPACITY,
+ PREF_TOUCH_ENABLED,
+ PREF_BUTTON_A,
+ PREF_BUTTON_B,
+ PREF_BUTTON_X,
+ PREF_BUTTON_Y,
+ PREF_BUTTON_L,
+ PREF_BUTTON_R,
+ PREF_BUTTON_ZL,
+ PREF_BUTTON_ZR,
+ PREF_BUTTON_PLUS,
+ PREF_BUTTON_MINUS,
+ PREF_BUTTON_DPAD,
+ PREF_STICK_L,
+ PREF_STICK_R,
+ PREF_BUTTON_HOME,
+ PREF_BUTTON_SCREENSHOT,
+ PREF_BUTTON_STICK_L,
+ PREF_BUTTON_STICK_R
+ )
+
+ const val LayoutOption_Unspecified = 0
+ const val LayoutOption_MobilePortrait = 4
+ const val LayoutOption_MobileLandscape = 5
}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/ShortSetting.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/ShortSetting.kt
new file mode 100644
index 000000000..c9a0c664c
--- /dev/null
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/ShortSetting.kt
@@ -0,0 +1,25 @@
+// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.yuzu.yuzu_emu.features.settings.model
+
+import org.yuzu.yuzu_emu.utils.NativeConfig
+
+enum class ShortSetting(
+ override val key: String,
+ override val category: Settings.Category
+) : AbstractShortSetting {
+ RENDERER_SPEED_LIMIT("speed_limit", Settings.Category.Core);
+
+ override val short: Short
+ get() = NativeConfig.getShort(key, false)
+
+ override fun setShort(value: Short) = NativeConfig.setShort(key, value)
+
+ override val defaultValue: Short by lazy { NativeConfig.getShort(key, true) }
+
+ override val valueAsString: String
+ get() = short.toString()
+
+ override fun reset() = NativeConfig.setShort(key, defaultValue)
+}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/StringSetting.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/StringSetting.kt
index 6621289fd..9bb3e66d4 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/StringSetting.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/StringSetting.kt
@@ -3,36 +3,24 @@
package org.yuzu.yuzu_emu.features.settings.model
+import org.yuzu.yuzu_emu.utils.NativeConfig
+
enum class StringSetting(
override val key: String,
- override val section: String,
- override val defaultValue: String
+ override val category: Settings.Category
) : AbstractStringSetting {
- AUDIO_OUTPUT_ENGINE("output_engine", Settings.SECTION_AUDIO, "auto"),
- CUSTOM_RTC("custom_rtc", Settings.SECTION_SYSTEM, "0");
+ // No string settings currently exist
+ EMPTY_SETTING("", Settings.Category.UiGeneral);
+
+ override val string: String
+ get() = NativeConfig.getString(key, false)
+
+ override fun setString(value: String) = NativeConfig.setString(key, value)
- override var string: String = defaultValue
+ override val defaultValue: String by lazy { NativeConfig.getString(key, true) }
override val valueAsString: String
get() = string
- override val isRuntimeEditable: Boolean
- get() {
- for (setting in NOT_RUNTIME_EDITABLE) {
- if (setting == this) {
- return false
- }
- }
- return true
- }
-
- companion object {
- private val NOT_RUNTIME_EDITABLE = listOf(
- CUSTOM_RTC
- )
-
- fun from(key: String): StringSetting? = StringSetting.values().firstOrNull { it.key == key }
-
- fun clear() = StringSetting.values().forEach { it.string = it.defaultValue }
- }
+ override fun reset() = NativeConfig.setString(key, defaultValue)
}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/DateTimeSetting.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/DateTimeSetting.kt
index bc0bf7788..7c858916e 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/DateTimeSetting.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/DateTimeSetting.kt
@@ -3,29 +3,29 @@
package org.yuzu.yuzu_emu.features.settings.model.view
+import org.yuzu.yuzu_emu.features.settings.model.AbstractLongSetting
import org.yuzu.yuzu_emu.features.settings.model.AbstractSetting
-import org.yuzu.yuzu_emu.features.settings.model.AbstractStringSetting
class DateTimeSetting(
setting: AbstractSetting?,
titleId: Int,
descriptionId: Int,
val key: String? = null,
- private val defaultValue: String? = null
+ private val defaultValue: Long? = null
) : SettingsItem(setting, titleId, descriptionId) {
override val type = TYPE_DATETIME_SETTING
- val value: String
+ val value: Long
get() = if (setting != null) {
- val setting = setting as AbstractStringSetting
- setting.string
+ val setting = setting as AbstractLongSetting
+ setting.long
} else {
defaultValue!!
}
- fun setSelectedValue(datetime: String): AbstractStringSetting {
- val stringSetting = setting as AbstractStringSetting
- stringSetting.string = datetime
- return stringSetting
+ fun setSelectedValue(datetime: Long): AbstractLongSetting {
+ val longSetting = setting as AbstractLongSetting
+ longSetting.setLong(datetime)
+ return longSetting
}
}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt
index 07520849e..a6cba977c 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt
@@ -23,7 +23,7 @@ abstract class SettingsItem(
val isEditable: Boolean
get() {
if (!NativeLibrary.isRunning()) return true
- return setting?.isRuntimeEditable ?: false
+ return setting?.isRuntimeModifiable ?: false
}
companion object {
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SingleChoiceSetting.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SingleChoiceSetting.kt
index 7306ec458..b6a8c4612 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SingleChoiceSetting.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SingleChoiceSetting.kt
@@ -33,7 +33,7 @@ class SingleChoiceSetting(
*/
fun setSelectedValue(selection: Int): AbstractIntSetting {
val intSetting = setting as AbstractIntSetting
- intSetting.int = selection
+ intSetting.setInt(selection)
return intSetting
}
}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SliderSetting.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SliderSetting.kt
index 92d0167ae..e71a29e35 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SliderSetting.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SliderSetting.kt
@@ -3,10 +3,12 @@
package org.yuzu.yuzu_emu.features.settings.model.view
+import org.yuzu.yuzu_emu.features.settings.model.AbstractByteSetting
import kotlin.math.roundToInt
import org.yuzu.yuzu_emu.features.settings.model.AbstractFloatSetting
import org.yuzu.yuzu_emu.features.settings.model.AbstractIntSetting
import org.yuzu.yuzu_emu.features.settings.model.AbstractSetting
+import org.yuzu.yuzu_emu.features.settings.model.AbstractShortSetting
import org.yuzu.yuzu_emu.utils.Log
class SliderSetting(
@@ -17,14 +19,16 @@ class SliderSetting(
val max: Int,
val units: String,
val key: String? = null,
- val defaultValue: Int? = null
+ val defaultValue: Any? = null
) : SettingsItem(setting, titleId, descriptionId) {
override val type = TYPE_SLIDER
- val selectedValue: Int
+ val selectedValue: Any
get() {
val setting = setting ?: return defaultValue!!
return when (setting) {
+ is AbstractByteSetting -> setting.byte.toInt()
+ is AbstractShortSetting -> setting.short.toInt()
is AbstractIntSetting -> setting.int
is AbstractFloatSetting -> setting.float.roundToInt()
else -> {
@@ -43,7 +47,7 @@ class SliderSetting(
*/
fun setSelectedValue(selection: Int): AbstractIntSetting {
val intSetting = setting as AbstractIntSetting
- intSetting.int = selection
+ intSetting.setInt(selection)
return intSetting
}
@@ -56,7 +60,19 @@ class SliderSetting(
*/
fun setSelectedValue(selection: Float): AbstractFloatSetting {
val floatSetting = setting as AbstractFloatSetting
- floatSetting.float = selection
+ floatSetting.setFloat(selection)
return floatSetting
}
+
+ fun setSelectedValue(selection: Short): AbstractShortSetting {
+ val shortSetting = setting as AbstractShortSetting
+ shortSetting.setShort(selection)
+ return shortSetting
+ }
+
+ fun setSelectedValue(selection: Byte): AbstractByteSetting {
+ val byteSetting = setting as AbstractByteSetting
+ byteSetting.setByte(selection)
+ return byteSetting
+ }
}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/StringSingleChoiceSetting.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/StringSingleChoiceSetting.kt
index 3b6731dcd..2195641e3 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/StringSingleChoiceSetting.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/StringSingleChoiceSetting.kt
@@ -53,7 +53,7 @@ class StringSingleChoiceSetting(
*/
fun setSelectedValue(selection: String): AbstractStringSetting {
val stringSetting = setting as AbstractStringSetting
- stringSetting.string = selection
+ stringSetting.setString(selection)
return stringSetting
}
}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SwitchSetting.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SwitchSetting.kt
index 90b198718..4ed8070e5 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SwitchSetting.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SwitchSetting.kt
@@ -49,14 +49,14 @@ class SwitchSetting(
// Try integer setting
try {
val setting = setting as AbstractIntSetting
- setting.int = if (checked) 1 else 0
+ setting.setInt(if (checked) 1 else 0)
return setting
} catch (_: ClassCastException) {
}
// Try boolean setting
val setting = setting as AbstractBooleanSetting
- setting.boolean = checked
+ setting.setBoolean(checked)
return setting
}
}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivity.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivity.kt
index e6fffc832..733a53c8c 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivity.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivity.kt
@@ -21,12 +21,7 @@ import com.google.android.material.color.MaterialColors
import java.io.IOException
import org.yuzu.yuzu_emu.R
import org.yuzu.yuzu_emu.databinding.ActivitySettingsBinding
-import org.yuzu.yuzu_emu.features.settings.model.BooleanSetting
-import org.yuzu.yuzu_emu.features.settings.model.FloatSetting
-import org.yuzu.yuzu_emu.features.settings.model.IntSetting
import org.yuzu.yuzu_emu.features.settings.model.Settings
-import org.yuzu.yuzu_emu.features.settings.model.SettingsViewModel
-import org.yuzu.yuzu_emu.features.settings.model.StringSetting
import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile
import org.yuzu.yuzu_emu.utils.*
@@ -35,10 +30,6 @@ class SettingsActivity : AppCompatActivity(), SettingsActivityView {
private lateinit var binding: ActivitySettingsBinding
- private val settingsViewModel: SettingsViewModel by viewModels()
-
- override val settings: Settings get() = settingsViewModel.settings
-
override fun onCreate(savedInstanceState: Bundle?) {
ThemeHelper.setTheme(this)
@@ -171,14 +162,6 @@ class SettingsActivity : AppCompatActivity(), SettingsActivityView {
fragment?.loadSettingsList()
}
- override fun showToastMessage(message: String, is_long: Boolean) {
- Toast.makeText(
- this,
- message,
- if (is_long) Toast.LENGTH_LONG else Toast.LENGTH_SHORT
- ).show()
- }
-
override fun onSettingChanged() {
presenter.onSettingChanged()
}
@@ -187,19 +170,18 @@ class SettingsActivity : AppCompatActivity(), SettingsActivityView {
// Prevents saving to a non-existent settings file
presenter.onSettingsReset()
- // Reset the static memory representation of each setting
- BooleanSetting.clear()
- FloatSetting.clear()
- IntSetting.clear()
- StringSetting.clear()
-
// Delete settings file because the user may have changed values that do not exist in the UI
val settingsFile = SettingsFile.getSettingsFile(SettingsFile.FILE_NAME_CONFIG)
if (!settingsFile.delete()) {
throw IOException("Failed to delete $settingsFile")
}
+ Settings.settingsList.forEach { it.reset() }
- showToastMessage(getString(R.string.settings_reset), true)
+ Toast.makeText(
+ applicationContext,
+ getString(R.string.settings_reset),
+ Toast.LENGTH_LONG
+ ).show()
finish()
}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivityPresenter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivityPresenter.kt
index 93e677b21..fdbad32bf 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivityPresenter.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivityPresenter.kt
@@ -5,7 +5,6 @@ package org.yuzu.yuzu_emu.features.settings.ui
import android.content.Context
import android.os.Bundle
-import android.text.TextUtils
import java.io.File
import org.yuzu.yuzu_emu.NativeLibrary
import org.yuzu.yuzu_emu.features.settings.model.Settings
@@ -14,8 +13,6 @@ import org.yuzu.yuzu_emu.utils.DirectoryInitialization
import org.yuzu.yuzu_emu.utils.Log
class SettingsActivityPresenter(private val activityView: SettingsActivityView) {
- val settings: Settings get() = activityView.settings
-
private var shouldSave = false
private lateinit var menuTag: String
private lateinit var gameId: String
@@ -33,13 +30,7 @@ class SettingsActivityPresenter(private val activityView: SettingsActivityView)
}
private fun loadSettingsUI() {
- if (!settings.isLoaded) {
- if (!TextUtils.isEmpty(gameId)) {
- settings.loadSettings(gameId, activityView)
- } else {
- settings.loadSettings(activityView)
- }
- }
+ // TODO: Load custom settings contextually
activityView.showSettingsFragment(menuTag, false, gameId)
activityView.onSettingsFileLoaded()
}
@@ -67,9 +58,9 @@ class SettingsActivityPresenter(private val activityView: SettingsActivityView)
fun onStop(finishing: Boolean) {
if (finishing && shouldSave) {
Log.debug("[SettingsActivity] Settings activity stopping. Saving settings to INI...")
- settings.saveSettings(activityView)
+ Settings.saveSettings()
+ NativeLibrary.reloadSettings()
}
- NativeLibrary.reloadSettings()
}
fun onSettingChanged() {
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivityView.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivityView.kt
index c186fc388..07a58b4ea 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivityView.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivityView.kt
@@ -3,8 +3,6 @@
package org.yuzu.yuzu_emu.features.settings.ui
-import org.yuzu.yuzu_emu.features.settings.model.Settings
-
/**
* Abstraction for the Activity that manages SettingsFragments.
*/
@@ -18,15 +16,6 @@ interface SettingsActivityView {
fun showSettingsFragment(menuTag: String, addToStack: Boolean, gameId: String)
/**
- * Called by a contained Fragment to get access to the Setting HashMap
- * loaded from disk, so that each Fragment doesn't need to perform its own
- * read operation.
- *
- * @return A HashMap of Settings.
- */
- val settings: Settings
-
- /**
* Called when a load operation completes.
*/
fun onSettingsFileLoaded()
@@ -37,14 +26,6 @@ interface SettingsActivityView {
fun onSettingsFileNotFound()
/**
- * Display a popup text message on screen.
- *
- * @param message The contents of the onscreen message.
- * @param is_long Whether this should be a long Toast or short one.
- */
- fun showToastMessage(message: String, is_long: Boolean)
-
- /**
* End the activity.
*/
fun finish()
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsAdapter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsAdapter.kt
index 9711e2c51..e2e8d8bec 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsAdapter.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsAdapter.kt
@@ -24,12 +24,10 @@ import org.yuzu.yuzu_emu.databinding.DialogSliderBinding
import org.yuzu.yuzu_emu.databinding.ListItemSettingBinding
import org.yuzu.yuzu_emu.databinding.ListItemSettingSwitchBinding
import org.yuzu.yuzu_emu.databinding.ListItemSettingsHeaderBinding
-import org.yuzu.yuzu_emu.features.settings.model.AbstractBooleanSetting
-import org.yuzu.yuzu_emu.features.settings.model.AbstractFloatSetting
-import org.yuzu.yuzu_emu.features.settings.model.AbstractIntSetting
import org.yuzu.yuzu_emu.features.settings.model.AbstractSetting
-import org.yuzu.yuzu_emu.features.settings.model.AbstractStringSetting
+import org.yuzu.yuzu_emu.features.settings.model.ByteSetting
import org.yuzu.yuzu_emu.features.settings.model.FloatSetting
+import org.yuzu.yuzu_emu.features.settings.model.ShortSetting
import org.yuzu.yuzu_emu.features.settings.model.view.*
import org.yuzu.yuzu_emu.features.settings.ui.viewholder.*
@@ -115,8 +113,7 @@ class SettingsAdapter(
}
fun onBooleanClick(item: SwitchSetting, position: Int, checked: Boolean) {
- val setting = item.setChecked(checked)
- fragmentView.putSetting(setting)
+ item.setChecked(checked)
fragmentView.onSettingChanged()
}
@@ -150,7 +147,7 @@ class SettingsAdapter(
fun onDateTimeClick(item: DateTimeSetting, position: Int) {
clickedItem = item
clickedPosition = position
- val storedTime = java.lang.Long.decode(item.value) * 1000
+ val storedTime = item.value * 1000
// Helper to extract hour and minute from epoch time
val calendar: Calendar = Calendar.getInstance()
@@ -183,13 +180,11 @@ class SettingsAdapter(
var epochTime: Long = datePicker.selection!! / 1000
epochTime += timePicker.hour.toLong() * 60 * 60
epochTime += timePicker.minute.toLong() * 60
- val rtcString = epochTime.toString()
- if (item.value != rtcString) {
+ if (item.value != epochTime) {
fragmentView.onSettingChanged()
+ notifyItemChanged(clickedPosition)
+ item.setSelectedValue(epochTime)
}
- notifyItemChanged(clickedPosition)
- val setting = item.setSelectedValue(rtcString)
- fragmentView.putSetting(setting)
clickedItem = null
}
datePicker.show(
@@ -201,7 +196,7 @@ class SettingsAdapter(
fun onSliderClick(item: SliderSetting, position: Int) {
clickedItem = item
clickedPosition = position
- sliderProgress = item.selectedValue
+ sliderProgress = item.selectedValue as Int
val inflater = LayoutInflater.from(context)
val sliderBinding = DialogSliderBinding.inflate(inflater)
@@ -249,8 +244,7 @@ class SettingsAdapter(
}
// Get the backing Setting, which may be null (if for example it was missing from the file)
- val setting = scSetting.setSelectedValue(value)
- fragmentView.putSetting(setting)
+ scSetting.setSelectedValue(value)
closeDialog()
}
@@ -258,8 +252,7 @@ class SettingsAdapter(
val scSetting = clickedItem as StringSingleChoiceSetting
val value = scSetting.getValueAt(which)
if (scSetting.selectedValue != value) fragmentView.onSettingChanged()
- val setting = scSetting.setSelectedValue(value!!)
- fragmentView.putSetting(setting)
+ scSetting.setSelectedValue(value!!)
closeDialog()
}
@@ -268,13 +261,25 @@ class SettingsAdapter(
if (sliderSetting.selectedValue != sliderProgress) {
fragmentView.onSettingChanged()
}
- if (sliderSetting.setting is FloatSetting) {
- val value = sliderProgress.toFloat()
- val setting = sliderSetting.setSelectedValue(value)
- fragmentView.putSetting(setting)
- } else {
- val setting = sliderSetting.setSelectedValue(sliderProgress)
- fragmentView.putSetting(setting)
+ when (sliderSetting.setting) {
+ is ByteSetting -> {
+ val value = sliderProgress.toByte()
+ sliderSetting.setSelectedValue(value)
+ }
+
+ is ShortSetting -> {
+ val value = sliderProgress.toShort()
+ sliderSetting.setSelectedValue(value)
+ }
+
+ is FloatSetting -> {
+ val value = sliderProgress.toFloat()
+ sliderSetting.setSelectedValue(value)
+ }
+
+ else -> {
+ sliderSetting.setSelectedValue(sliderProgress)
+ }
}
closeDialog()
}
@@ -286,13 +291,8 @@ class SettingsAdapter(
fun onLongClick(setting: AbstractSetting, position: Int): Boolean {
MaterialAlertDialogBuilder(context)
.setMessage(R.string.reset_setting_confirmation)
- .setPositiveButton(android.R.string.ok) { dialog: DialogInterface, which: Int ->
- when (setting) {
- is AbstractBooleanSetting -> setting.boolean = setting.defaultValue as Boolean
- is AbstractFloatSetting -> setting.float = setting.defaultValue as Float
- is AbstractIntSetting -> setting.int = setting.defaultValue as Int
- is AbstractStringSetting -> setting.string = setting.defaultValue as String
- }
+ .setPositiveButton(android.R.string.ok) { _: DialogInterface, _: Int ->
+ setting.reset()
notifyItemChanged(position)
fragmentView.onSettingChanged()
}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragment.kt
index 70a74c4dd..dc1bf6eb1 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragment.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragment.kt
@@ -15,7 +15,6 @@ import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.LinearLayoutManager
import com.google.android.material.divider.MaterialDividerItemDecoration
import org.yuzu.yuzu_emu.databinding.FragmentSettingsBinding
-import org.yuzu.yuzu_emu.features.settings.model.AbstractSetting
import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem
class SettingsFragment : Fragment(), SettingsFragmentView {
@@ -89,14 +88,6 @@ class SettingsFragment : Fragment(), SettingsFragmentView {
)
}
- override fun showToastMessage(message: String?, is_long: Boolean) {
- activityView!!.showToastMessage(message!!, is_long)
- }
-
- override fun putSetting(setting: AbstractSetting) {
- fragmentPresenter.putSetting(setting)
- }
-
override fun onSettingChanged() {
activityView!!.onSettingChanged()
}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt
index 59c1d9d54..2bab9e542 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt
@@ -6,16 +6,18 @@ package org.yuzu.yuzu_emu.features.settings.ui
import android.content.SharedPreferences
import android.os.Build
import android.text.TextUtils
+import android.widget.Toast
import androidx.preference.PreferenceManager
import org.yuzu.yuzu_emu.R
import org.yuzu.yuzu_emu.YuzuApplication
import org.yuzu.yuzu_emu.features.settings.model.AbstractBooleanSetting
import org.yuzu.yuzu_emu.features.settings.model.AbstractIntSetting
-import org.yuzu.yuzu_emu.features.settings.model.AbstractSetting
import org.yuzu.yuzu_emu.features.settings.model.BooleanSetting
+import org.yuzu.yuzu_emu.features.settings.model.ByteSetting
import org.yuzu.yuzu_emu.features.settings.model.IntSetting
+import org.yuzu.yuzu_emu.features.settings.model.LongSetting
import org.yuzu.yuzu_emu.features.settings.model.Settings
-import org.yuzu.yuzu_emu.features.settings.model.StringSetting
+import org.yuzu.yuzu_emu.features.settings.model.ShortSetting
import org.yuzu.yuzu_emu.features.settings.model.view.*
import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile
import org.yuzu.yuzu_emu.fragments.ResetSettingsDialogFragment
@@ -27,7 +29,6 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
private var settingsList: ArrayList<SettingsItem>? = null
private val settingsActivity get() = fragmentView.activityView as SettingsActivity
- private val settings get() = fragmentView.activityView!!.settings
private lateinit var preferences: SharedPreferences
@@ -41,17 +42,6 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
loadSettingsList()
}
- fun putSetting(setting: AbstractSetting) {
- if (setting.section == null || setting.key == null) {
- return
- }
-
- val section = settings.getSection(setting.section!!)!!
- if (section.getSetting(setting.key!!) == null) {
- section.putSetting(setting)
- }
- }
-
fun loadSettingsList() {
if (!TextUtils.isEmpty(gameId)) {
settingsActivity.setToolbarTitle("Game Settings: $gameId")
@@ -69,7 +59,12 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
Settings.SECTION_THEME -> addThemeSettings(sl)
Settings.SECTION_DEBUG -> addDebugSettings(sl)
else -> {
- fragmentView.showToastMessage("Unimplemented menu", false)
+ val context = YuzuApplication.appContext
+ Toast.makeText(
+ context,
+ context.getString(R.string.unimplemented_menu),
+ Toast.LENGTH_SHORT
+ ).show()
return
}
}
@@ -135,23 +130,23 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
sl.apply {
add(
SwitchSetting(
- IntSetting.RENDERER_USE_SPEED_LIMIT,
+ BooleanSetting.RENDERER_USE_SPEED_LIMIT,
R.string.frame_limit_enable,
R.string.frame_limit_enable_description,
- IntSetting.RENDERER_USE_SPEED_LIMIT.key,
- IntSetting.RENDERER_USE_SPEED_LIMIT.defaultValue
+ BooleanSetting.RENDERER_USE_SPEED_LIMIT.key,
+ BooleanSetting.RENDERER_USE_SPEED_LIMIT.defaultValue
)
)
add(
SliderSetting(
- IntSetting.RENDERER_SPEED_LIMIT,
+ ShortSetting.RENDERER_SPEED_LIMIT,
R.string.frame_limit_slider,
R.string.frame_limit_slider_description,
1,
200,
"%",
- IntSetting.RENDERER_SPEED_LIMIT.key,
- IntSetting.RENDERER_SPEED_LIMIT.defaultValue
+ ShortSetting.RENDERER_SPEED_LIMIT.key,
+ ShortSetting.RENDERER_SPEED_LIMIT.defaultValue
)
)
add(
@@ -182,11 +177,11 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
sl.apply {
add(
SwitchSetting(
- IntSetting.USE_DOCKED_MODE,
+ BooleanSetting.USE_DOCKED_MODE,
R.string.use_docked_mode,
R.string.use_docked_mode_description,
- IntSetting.USE_DOCKED_MODE.key,
- IntSetting.USE_DOCKED_MODE.defaultValue
+ BooleanSetting.USE_DOCKED_MODE.key,
+ BooleanSetting.USE_DOCKED_MODE.defaultValue
)
)
add(
@@ -222,11 +217,11 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
)
add(
DateTimeSetting(
- StringSetting.CUSTOM_RTC,
+ LongSetting.CUSTOM_RTC,
R.string.set_custom_rtc,
0,
- StringSetting.CUSTOM_RTC.key,
- StringSetting.CUSTOM_RTC.defaultValue
+ LongSetting.CUSTOM_RTC.key,
+ LongSetting.CUSTOM_RTC.defaultValue
)
)
}
@@ -314,38 +309,38 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
)
add(
SwitchSetting(
- IntSetting.RENDERER_USE_DISK_SHADER_CACHE,
+ BooleanSetting.RENDERER_USE_DISK_SHADER_CACHE,
R.string.use_disk_shader_cache,
R.string.use_disk_shader_cache_description,
- IntSetting.RENDERER_USE_DISK_SHADER_CACHE.key,
- IntSetting.RENDERER_USE_DISK_SHADER_CACHE.defaultValue
+ BooleanSetting.RENDERER_USE_DISK_SHADER_CACHE.key,
+ BooleanSetting.RENDERER_USE_DISK_SHADER_CACHE.defaultValue
)
)
add(
SwitchSetting(
- IntSetting.RENDERER_FORCE_MAX_CLOCK,
+ BooleanSetting.RENDERER_FORCE_MAX_CLOCK,
R.string.renderer_force_max_clock,
R.string.renderer_force_max_clock_description,
- IntSetting.RENDERER_FORCE_MAX_CLOCK.key,
- IntSetting.RENDERER_FORCE_MAX_CLOCK.defaultValue
+ BooleanSetting.RENDERER_FORCE_MAX_CLOCK.key,
+ BooleanSetting.RENDERER_FORCE_MAX_CLOCK.defaultValue
)
)
add(
SwitchSetting(
- IntSetting.RENDERER_ASYNCHRONOUS_SHADERS,
+ BooleanSetting.RENDERER_ASYNCHRONOUS_SHADERS,
R.string.renderer_asynchronous_shaders,
R.string.renderer_asynchronous_shaders_description,
- IntSetting.RENDERER_ASYNCHRONOUS_SHADERS.key,
- IntSetting.RENDERER_ASYNCHRONOUS_SHADERS.defaultValue
+ BooleanSetting.RENDERER_ASYNCHRONOUS_SHADERS.key,
+ BooleanSetting.RENDERER_ASYNCHRONOUS_SHADERS.defaultValue
)
)
add(
SwitchSetting(
- IntSetting.RENDERER_REACTIVE_FLUSHING,
+ BooleanSetting.RENDERER_REACTIVE_FLUSHING,
R.string.renderer_reactive_flushing,
R.string.renderer_reactive_flushing_description,
- IntSetting.RENDERER_REACTIVE_FLUSHING.key,
- IntSetting.RENDERER_REACTIVE_FLUSHING.defaultValue
+ BooleanSetting.RENDERER_REACTIVE_FLUSHING.key,
+ BooleanSetting.RENDERER_REACTIVE_FLUSHING.defaultValue
)
)
}
@@ -355,26 +350,26 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
settingsActivity.setToolbarTitle(settingsActivity.getString(R.string.preferences_audio))
sl.apply {
add(
- StringSingleChoiceSetting(
- StringSetting.AUDIO_OUTPUT_ENGINE,
+ SingleChoiceSetting(
+ IntSetting.AUDIO_OUTPUT_ENGINE,
R.string.audio_output_engine,
0,
- settingsActivity.resources.getStringArray(R.array.outputEngineEntries),
- settingsActivity.resources.getStringArray(R.array.outputEngineValues),
- StringSetting.AUDIO_OUTPUT_ENGINE.key,
- StringSetting.AUDIO_OUTPUT_ENGINE.defaultValue
+ R.array.outputEngineEntries,
+ R.array.outputEngineValues,
+ IntSetting.AUDIO_OUTPUT_ENGINE.key,
+ IntSetting.AUDIO_OUTPUT_ENGINE.defaultValue
)
)
add(
SliderSetting(
- IntSetting.AUDIO_VOLUME,
+ ByteSetting.AUDIO_VOLUME,
R.string.audio_volume,
R.string.audio_volume_description,
0,
100,
"%",
- IntSetting.AUDIO_VOLUME.key,
- IntSetting.AUDIO_VOLUME.defaultValue
+ ByteSetting.AUDIO_VOLUME.key,
+ ByteSetting.AUDIO_VOLUME.defaultValue
)
)
}
@@ -384,19 +379,19 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
settingsActivity.setToolbarTitle(settingsActivity.getString(R.string.preferences_theme))
sl.apply {
val theme: AbstractIntSetting = object : AbstractIntSetting {
- override var int: Int
+ override val int: Int
get() = preferences.getInt(Settings.PREF_THEME, 0)
- set(value) {
- preferences.edit()
- .putInt(Settings.PREF_THEME, value)
- .apply()
- settingsActivity.recreate()
- }
+
+ override fun setInt(value: Int) {
+ preferences.edit()
+ .putInt(Settings.PREF_THEME, value)
+ .apply()
+ settingsActivity.recreate()
+ }
+
override val key: String? = null
- override val section: String? = null
- override val isRuntimeEditable: Boolean = false
- override val valueAsString: String
- get() = preferences.getInt(Settings.PREF_THEME, 0).toString()
+ override val category = Settings.Category.UiGeneral
+ override val isRuntimeModifiable: Boolean = false
override val defaultValue: Any = 0
}
@@ -423,19 +418,19 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
}
val themeMode: AbstractIntSetting = object : AbstractIntSetting {
- override var int: Int
+ override val int: Int
get() = preferences.getInt(Settings.PREF_THEME_MODE, -1)
- set(value) {
- preferences.edit()
- .putInt(Settings.PREF_THEME_MODE, value)
- .apply()
- ThemeHelper.setThemeMode(settingsActivity)
- }
+
+ override fun setInt(value: Int) {
+ preferences.edit()
+ .putInt(Settings.PREF_THEME_MODE, value)
+ .apply()
+ ThemeHelper.setThemeMode(settingsActivity)
+ }
+
override val key: String? = null
- override val section: String? = null
- override val isRuntimeEditable: Boolean = false
- override val valueAsString: String
- get() = preferences.getInt(Settings.PREF_THEME_MODE, -1).toString()
+ override val category = Settings.Category.UiGeneral
+ override val isRuntimeModifiable: Boolean = false
override val defaultValue: Any = -1
}
@@ -450,20 +445,19 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
)
val blackBackgrounds: AbstractBooleanSetting = object : AbstractBooleanSetting {
- override var boolean: Boolean
+ override val boolean: Boolean
get() = preferences.getBoolean(Settings.PREF_BLACK_BACKGROUNDS, false)
- set(value) {
- preferences.edit()
- .putBoolean(Settings.PREF_BLACK_BACKGROUNDS, value)
- .apply()
- settingsActivity.recreate()
- }
+
+ override fun setBoolean(value: Boolean) {
+ preferences.edit()
+ .putBoolean(Settings.PREF_BLACK_BACKGROUNDS, value)
+ .apply()
+ settingsActivity.recreate()
+ }
+
override val key: String? = null
- override val section: String? = null
- override val isRuntimeEditable: Boolean = false
- override val valueAsString: String
- get() = preferences.getBoolean(Settings.PREF_BLACK_BACKGROUNDS, false)
- .toString()
+ override val category = Settings.Category.UiGeneral
+ override val isRuntimeModifiable: Boolean = false
override val defaultValue: Any = false
}
@@ -494,11 +488,11 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
)
add(
SwitchSetting(
- IntSetting.RENDERER_DEBUG,
+ BooleanSetting.RENDERER_DEBUG,
R.string.renderer_debug,
R.string.renderer_debug_description,
- IntSetting.RENDERER_DEBUG.key,
- IntSetting.RENDERER_DEBUG.defaultValue
+ BooleanSetting.RENDERER_DEBUG.key,
+ BooleanSetting.RENDERER_DEBUG.defaultValue
)
)
@@ -514,17 +508,18 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
)
val fastmem = object : AbstractBooleanSetting {
- override var boolean: Boolean
+ override val boolean: Boolean
get() =
BooleanSetting.FASTMEM.boolean && BooleanSetting.FASTMEM_EXCLUSIVES.boolean
- set(value) {
- BooleanSetting.FASTMEM.boolean = value
- BooleanSetting.FASTMEM_EXCLUSIVES.boolean = value
- }
+
+ override fun setBoolean(value: Boolean) {
+ BooleanSetting.FASTMEM.setBoolean(value)
+ BooleanSetting.FASTMEM_EXCLUSIVES.setBoolean(value)
+ }
+
override val key: String? = null
- override val section: String = Settings.SECTION_CPU
- override val isRuntimeEditable: Boolean = false
- override val valueAsString: String = ""
+ override val category = Settings.Category.Cpu
+ override val isRuntimeModifiable: Boolean = false
override val defaultValue: Any = true
}
add(
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentView.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentView.kt
index 1ebe35eaa..a4d7a80aa 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentView.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentView.kt
@@ -3,7 +3,6 @@
package org.yuzu.yuzu_emu.features.settings.ui
-import org.yuzu.yuzu_emu.features.settings.model.AbstractSetting
import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem
/**
@@ -37,21 +36,6 @@ interface SettingsFragmentView {
fun loadSubMenu(menuKey: String)
/**
- * Tell the Fragment to tell the containing activity to display a toast message.
- *
- * @param message Text to be shown in the Toast
- * @param is_long Whether this should be a long Toast or short one.
- */
- fun showToastMessage(message: String?, is_long: Boolean)
-
- /**
- * Have the fragment add a setting to the HashMap.
- *
- * @param setting The (possibly previously missing) new setting.
- */
- fun putSetting(setting: AbstractSetting)
-
- /**
* Have the fragment tell the containing Activity that a setting was modified.
*/
fun onSettingChanged()
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/DateTimeViewHolder.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/DateTimeViewHolder.kt
index 79572fc06..eb25ea4fb 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/DateTimeViewHolder.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/DateTimeViewHolder.kt
@@ -29,7 +29,7 @@ class DateTimeViewHolder(val binding: ListItemSettingBinding, adapter: SettingsA
}
binding.textSettingValue.visibility = View.VISIBLE
- val epochTime = setting.value.toLong()
+ val epochTime = setting.value
val instant = Instant.ofEpochMilli(epochTime * 1000)
val zonedTime = ZonedDateTime.ofInstant(instant, ZoneId.of("UTC"))
val dateFormatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM)
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/utils/SettingsFile.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/utils/SettingsFile.kt
index 70a52df5d..2b04d666a 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/utils/SettingsFile.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/utils/SettingsFile.kt
@@ -3,18 +3,15 @@
package org.yuzu.yuzu_emu.features.settings.utils
+import android.widget.Toast
import java.io.*
-import java.util.*
import org.ini4j.Wini
-import org.yuzu.yuzu_emu.NativeLibrary
import org.yuzu.yuzu_emu.R
import org.yuzu.yuzu_emu.YuzuApplication
import org.yuzu.yuzu_emu.features.settings.model.*
-import org.yuzu.yuzu_emu.features.settings.model.Settings.SettingsSectionMap
-import org.yuzu.yuzu_emu.features.settings.ui.SettingsActivityView
-import org.yuzu.yuzu_emu.utils.BiMap
import org.yuzu.yuzu_emu.utils.DirectoryInitialization
import org.yuzu.yuzu_emu.utils.Log
+import org.yuzu.yuzu_emu.utils.NativeConfig
/**
* Contains static methods for interacting with .ini files in which settings are stored.
@@ -22,243 +19,41 @@ import org.yuzu.yuzu_emu.utils.Log
object SettingsFile {
const val FILE_NAME_CONFIG = "config"
- private var sectionsMap = BiMap<String?, String?>()
-
- /**
- * Reads a given .ini file from disk and returns it as a HashMap of Settings, themselves
- * effectively a HashMap of key/value settings. If unsuccessful, outputs an error telling why it
- * failed.
- *
- * @param ini The ini file to load the settings from
- * @param isCustomGame
- * @param view The current view.
- * @return An Observable that emits a HashMap of the file's contents, then completes.
- */
- private fun readFile(
- ini: File?,
- isCustomGame: Boolean,
- view: SettingsActivityView? = null
- ): HashMap<String, SettingSection?> {
- val sections: HashMap<String, SettingSection?> = SettingsSectionMap()
- var reader: BufferedReader? = null
- try {
- reader = BufferedReader(FileReader(ini))
- var current: SettingSection? = null
- var line: String?
- while (reader.readLine().also { line = it } != null) {
- if (line!!.startsWith("[") && line!!.endsWith("]")) {
- current = sectionFromLine(line!!, isCustomGame)
- sections[current.name] = current
- } else if (current != null) {
- val setting = settingFromLine(line!!)
- if (setting != null) {
- current.putSetting(setting)
- }
- }
- }
- } catch (e: FileNotFoundException) {
- Log.error("[SettingsFile] File not found: " + e.message)
- view?.onSettingsFileNotFound()
- } catch (e: IOException) {
- Log.error("[SettingsFile] Error reading from: " + e.message)
- view?.onSettingsFileNotFound()
- } finally {
- if (reader != null) {
- try {
- reader.close()
- } catch (e: IOException) {
- Log.error("[SettingsFile] Error closing: " + e.message)
- }
- }
- }
- return sections
- }
-
- fun readFile(fileName: String, view: SettingsActivityView?): HashMap<String, SettingSection?> {
- return readFile(getSettingsFile(fileName), false, view)
- }
-
- fun readFile(fileName: String): HashMap<String, SettingSection?> =
- readFile(getSettingsFile(fileName), false)
-
- /**
- * Reads a given .ini file from disk and returns it as a HashMap of SettingSections, themselves
- * effectively a HashMap of key/value settings. If unsuccessful, outputs an error telling why it
- * failed.
- *
- * @param gameId the id of the game to load it's settings.
- * @param view The current view.
- */
- fun readCustomGameSettings(
- gameId: String,
- view: SettingsActivityView?
- ): HashMap<String, SettingSection?> {
- return readFile(getCustomGameSettingsFile(gameId), true, view)
- }
-
/**
* Saves a Settings HashMap to a given .ini file on disk. If unsuccessful, outputs an error
* telling why it failed.
*
* @param fileName The target filename without a path or extension.
- * @param sections The HashMap containing the Settings we want to serialize.
- * @param view The current view.
*/
- fun saveFile(
- fileName: String,
- sections: TreeMap<String, SettingSection>,
- view: SettingsActivityView
- ) {
+ fun saveFile(fileName: String) {
val ini = getSettingsFile(fileName)
try {
- val writer = Wini(ini)
- val keySet: Set<String> = sections.keys
- for (key in keySet) {
- val section = sections[key]
- writeSection(writer, section!!)
+ val wini = Wini(ini)
+ for (specificCategory in Settings.Category.values()) {
+ val categoryHeader = NativeConfig.getConfigHeader(specificCategory.ordinal)
+ for (setting in Settings.settingsList) {
+ if (setting.key!!.isEmpty()) continue
+
+ val settingCategoryHeader =
+ NativeConfig.getConfigHeader(setting.category.ordinal)
+ val iniSetting: String? = wini.get(categoryHeader, setting.key)
+ if (iniSetting != null || settingCategoryHeader == categoryHeader) {
+ wini.put(settingCategoryHeader, setting.key, setting.valueAsString)
+ }
+ }
}
- writer.store()
+ wini.store()
} catch (e: IOException) {
Log.error("[SettingsFile] File not found: " + fileName + ".ini: " + e.message)
- view.showToastMessage(
- YuzuApplication.appContext
- .getString(R.string.error_saving, fileName, e.message),
- false
- )
- }
- }
-
- fun saveCustomGameSettings(gameId: String?, sections: HashMap<String, SettingSection?>) {
- val sortedSections: Set<String> = TreeSet(sections.keys)
- for (sectionKey in sortedSections) {
- val section = sections[sectionKey]
- val settings = section!!.settings
- val sortedKeySet: Set<String> = TreeSet(settings.keys)
- for (settingKey in sortedKeySet) {
- val setting = settings[settingKey]
- NativeLibrary.setUserSetting(
- gameId,
- mapSectionNameFromIni(
- section.name
- ),
- setting!!.key,
- setting.valueAsString
- )
- }
- }
- }
-
- private fun mapSectionNameFromIni(generalSectionName: String): String? {
- return if (sectionsMap.getForward(generalSectionName) != null) {
- sectionsMap.getForward(generalSectionName)
- } else {
- generalSectionName
- }
- }
-
- private fun mapSectionNameToIni(generalSectionName: String): String {
- return if (sectionsMap.getBackward(generalSectionName) != null) {
- sectionsMap.getBackward(generalSectionName).toString()
- } else {
- generalSectionName
- }
- }
-
- fun getSettingsFile(fileName: String): File {
- return File(
- DirectoryInitialization.userDirectory + "/config/" + fileName + ".ini"
- )
- }
-
- private fun getCustomGameSettingsFile(gameId: String): File {
- return File(DirectoryInitialization.userDirectory + "/GameSettings/" + gameId + ".ini")
- }
-
- private fun sectionFromLine(line: String, isCustomGame: Boolean): SettingSection {
- var sectionName: String = line.substring(1, line.length - 1)
- if (isCustomGame) {
- sectionName = mapSectionNameToIni(sectionName)
+ val context = YuzuApplication.appContext
+ Toast.makeText(
+ context,
+ context.getString(R.string.error_saving, fileName, e.message),
+ Toast.LENGTH_SHORT
+ ).show()
}
- return SettingSection(sectionName)
}
- /**
- * For a line of text, determines what type of data is being represented, and returns
- * a Setting object containing this data.
- *
- * @param line The line of text being parsed.
- * @return A typed Setting containing the key/value contained in the line.
- */
- private fun settingFromLine(line: String): AbstractSetting? {
- val splitLine = line.split("=".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
- if (splitLine.size != 2) {
- return null
- }
- val key = splitLine[0].trim { it <= ' ' }
- val value = splitLine[1].trim { it <= ' ' }
- if (value.isEmpty()) {
- return null
- }
-
- val booleanSetting = BooleanSetting.from(key)
- if (booleanSetting != null) {
- booleanSetting.boolean = value.toBoolean()
- return booleanSetting
- }
-
- val intSetting = IntSetting.from(key)
- if (intSetting != null) {
- intSetting.int = value.toInt()
- return intSetting
- }
-
- val floatSetting = FloatSetting.from(key)
- if (floatSetting != null) {
- floatSetting.float = value.toFloat()
- return floatSetting
- }
-
- val stringSetting = StringSetting.from(key)
- if (stringSetting != null) {
- stringSetting.string = value
- return stringSetting
- }
-
- return null
- }
-
- /**
- * Writes the contents of a Section HashMap to disk.
- *
- * @param parser A Wini pointed at a file on disk.
- * @param section A section containing settings to be written to the file.
- */
- private fun writeSection(parser: Wini, section: SettingSection) {
- // Write the section header.
- val header = section.name
-
- // Write this section's values.
- val settings = section.settings
- val keySet: Set<String> = settings.keys
- for (key in keySet) {
- val setting = settings[key]
- parser.put(header, setting!!.key, setting.valueAsString)
- }
-
- BooleanSetting.values().forEach {
- if (!keySet.contains(it.key)) {
- parser.put(header, it.key, it.valueAsString)
- }
- }
- IntSetting.values().forEach {
- if (!keySet.contains(it.key)) {
- parser.put(header, it.key, it.valueAsString)
- }
- }
- StringSetting.values().forEach {
- if (!keySet.contains(it.key)) {
- parser.put(header, it.key, it.valueAsString)
- }
- }
- }
+ fun getSettingsFile(fileName: String): File =
+ File(DirectoryInitialization.userDirectory + "/config/" + fileName + ".ini")
}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt
index aaf3a0ec1..d8dbf1f45 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt
@@ -39,7 +39,6 @@ import org.yuzu.yuzu_emu.activities.EmulationActivity
import org.yuzu.yuzu_emu.databinding.ActivityMainBinding
import org.yuzu.yuzu_emu.databinding.DialogProgressBarBinding
import org.yuzu.yuzu_emu.features.settings.model.Settings
-import org.yuzu.yuzu_emu.features.settings.model.SettingsViewModel
import org.yuzu.yuzu_emu.features.settings.ui.SettingsActivity
import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile
import org.yuzu.yuzu_emu.fragments.IndeterminateProgressDialogFragment
@@ -54,7 +53,6 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
private val homeViewModel: HomeViewModel by viewModels()
private val gamesViewModel: GamesViewModel by viewModels()
- private val settingsViewModel: SettingsViewModel by viewModels()
override var themeId: Int = 0
@@ -62,8 +60,6 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
val splashScreen = installSplashScreen()
splashScreen.setKeepOnScreenCondition { !DirectoryInitialization.areDirectoriesReady }
- settingsViewModel.settings.loadSettings()
-
ThemeHelper.setTheme(this)
super.onCreate(savedInstanceState)
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/BiMap.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/BiMap.kt
deleted file mode 100644
index 9cfda74ee..000000000
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/BiMap.kt
+++ /dev/null
@@ -1,25 +0,0 @@
-// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package org.yuzu.yuzu_emu.utils
-
-class BiMap<K, V> {
- private val forward: MutableMap<K, V> = HashMap()
- private val backward: MutableMap<V, K> = HashMap()
-
- @Synchronized
- fun add(key: K, value: V) {
- forward[key] = value
- backward[value] = key
- }
-
- @Synchronized
- fun getForward(key: K): V? {
- return forward[key]
- }
-
- @Synchronized
- fun getBackward(key: V): K? {
- return backward[key]
- }
-}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/NativeConfig.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/NativeConfig.kt
new file mode 100644
index 000000000..d4d981f9e
--- /dev/null
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/NativeConfig.kt
@@ -0,0 +1,31 @@
+// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.yuzu.yuzu_emu.utils
+
+object NativeConfig {
+ external fun getBoolean(key: String, getDefault: Boolean): Boolean
+ external fun setBoolean(key: String, value: Boolean)
+
+ external fun getByte(key: String, getDefault: Boolean): Byte
+ external fun setByte(key: String, value: Byte)
+
+ external fun getShort(key: String, getDefault: Boolean): Short
+ external fun setShort(key: String, value: Short)
+
+ external fun getInt(key: String, getDefault: Boolean): Int
+ external fun setInt(key: String, value: Int)
+
+ external fun getFloat(key: String, getDefault: Boolean): Float
+ external fun setFloat(key: String, value: Float)
+
+ external fun getLong(key: String, getDefault: Boolean): Long
+ external fun setLong(key: String, value: Long)
+
+ external fun getString(key: String, getDefault: Boolean): String
+ external fun setString(key: String, value: String)
+
+ external fun getIsRuntimeModifiable(key: String): Boolean
+
+ external fun getConfigHeader(category: Int): String
+}
diff --git a/src/android/app/src/main/jni/CMakeLists.txt b/src/android/app/src/main/jni/CMakeLists.txt
index e2ed08e9f..e15d1480b 100644
--- a/src/android/app/src/main/jni/CMakeLists.txt
+++ b/src/android/app/src/main/jni/CMakeLists.txt
@@ -14,6 +14,8 @@ add_library(yuzu-android SHARED
id_cache.cpp
id_cache.h
native.cpp
+ native_config.cpp
+ uisettings.cpp
)
set_property(TARGET yuzu-android PROPERTY IMPORTED_LOCATION ${FFmpeg_LIBRARY_DIR})
diff --git a/src/android/app/src/main/jni/config.cpp b/src/android/app/src/main/jni/config.cpp
index 9de9bd93e..34b425cb4 100644
--- a/src/android/app/src/main/jni/config.cpp
+++ b/src/android/app/src/main/jni/config.cpp
@@ -16,18 +16,20 @@
#include "input_common/main.h"
#include "jni/config.h"
#include "jni/default_ini.h"
+#include "uisettings.h"
namespace FS = Common::FS;
-Config::Config(std::optional<std::filesystem::path> config_path)
- : config_loc{config_path.value_or(FS::GetYuzuPath(FS::YuzuPath::ConfigDir) / "config.ini")},
- config{std::make_unique<INIReader>(FS::PathToUTF8String(config_loc))} {
- Reload();
+Config::Config(const std::string& config_name, ConfigType config_type)
+ : type(config_type), global{config_type == ConfigType::GlobalConfig} {
+ Initialize(config_name);
}
Config::~Config() = default;
bool Config::LoadINI(const std::string& default_contents, bool retry) {
+ void(FS::CreateParentDir(config_loc));
+ config = std::make_unique<INIReader>(FS::PathToUTF8String(config_loc));
const auto config_loc_str = FS::PathToUTF8String(config_loc);
if (config->ParseError() < 0) {
if (retry) {
@@ -301,9 +303,28 @@ void Config::ReadValues() {
// Network
ReadSetting("Network", Settings::values.network_interface);
+
+ // Android
+ ReadSetting("Android", AndroidSettings::values.picture_in_picture);
+ ReadSetting("Android", AndroidSettings::values.screen_layout);
}
-void Config::Reload() {
+void Config::Initialize(const std::string& config_name) {
+ const auto fs_config_loc = FS::GetYuzuPath(FS::YuzuPath::ConfigDir);
+ const auto config_file = fmt::format("{}.ini", config_name);
+
+ switch (type) {
+ case ConfigType::GlobalConfig:
+ config_loc = FS::PathToUTF8String(fs_config_loc / config_file);
+ break;
+ case ConfigType::PerGameConfig:
+ config_loc = FS::PathToUTF8String(fs_config_loc / "custom" / FS::ToU8String(config_file));
+ break;
+ case ConfigType::InputProfile:
+ config_loc = FS::PathToUTF8String(fs_config_loc / "input" / config_file);
+ LoadINI(DefaultINI::android_config_file);
+ return;
+ }
LoadINI(DefaultINI::android_config_file);
ReadValues();
}
diff --git a/src/android/app/src/main/jni/config.h b/src/android/app/src/main/jni/config.h
index 0d7d6e94d..e1e8f47ed 100644
--- a/src/android/app/src/main/jni/config.h
+++ b/src/android/app/src/main/jni/config.h
@@ -13,25 +13,35 @@
class INIReader;
class Config {
- std::filesystem::path config_loc;
- std::unique_ptr<INIReader> config;
-
bool LoadINI(const std::string& default_contents = "", bool retry = true);
- void ReadValues();
public:
- explicit Config(std::optional<std::filesystem::path> config_path = std::nullopt);
+ enum class ConfigType {
+ GlobalConfig,
+ PerGameConfig,
+ InputProfile,
+ };
+
+ explicit Config(const std::string& config_name = "config",
+ ConfigType config_type = ConfigType::GlobalConfig);
~Config();
- void Reload();
+ void Initialize(const std::string& config_name);
private:
/**
- * Applies a value read from the sdl2_config to a Setting.
+ * Applies a value read from the config to a Setting.
*
* @param group The name of the INI group
* @param setting The yuzu setting to modify
*/
template <typename Type, bool ranged>
void ReadSetting(const std::string& group, Settings::Setting<Type, ranged>& setting);
+
+ void ReadValues();
+
+ const ConfigType type;
+ std::unique_ptr<INIReader> config;
+ std::string config_loc;
+ const bool global;
};
diff --git a/src/android/app/src/main/jni/native.cpp b/src/android/app/src/main/jni/native.cpp
index 7e17833a0..b2adfdeda 100644
--- a/src/android/app/src/main/jni/native.cpp
+++ b/src/android/app/src/main/jni/native.cpp
@@ -824,34 +824,6 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_reloadSettings(JNIEnv* env, jclass cl
Config{};
}
-jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getUserSetting(JNIEnv* env, jclass clazz,
- jstring j_game_id, jstring j_section,
- jstring j_key) {
- std::string_view game_id = env->GetStringUTFChars(j_game_id, 0);
- std::string_view section = env->GetStringUTFChars(j_section, 0);
- std::string_view key = env->GetStringUTFChars(j_key, 0);
-
- env->ReleaseStringUTFChars(j_game_id, game_id.data());
- env->ReleaseStringUTFChars(j_section, section.data());
- env->ReleaseStringUTFChars(j_key, key.data());
-
- return env->NewStringUTF("");
-}
-
-void Java_org_yuzu_yuzu_1emu_NativeLibrary_setUserSetting(JNIEnv* env, jclass clazz,
- jstring j_game_id, jstring j_section,
- jstring j_key, jstring j_value) {
- std::string_view game_id = env->GetStringUTFChars(j_game_id, 0);
- std::string_view section = env->GetStringUTFChars(j_section, 0);
- std::string_view key = env->GetStringUTFChars(j_key, 0);
- std::string_view value = env->GetStringUTFChars(j_value, 0);
-
- env->ReleaseStringUTFChars(j_game_id, game_id.data());
- env->ReleaseStringUTFChars(j_section, section.data());
- env->ReleaseStringUTFChars(j_key, key.data());
- env->ReleaseStringUTFChars(j_value, value.data());
-}
-
void Java_org_yuzu_yuzu_1emu_NativeLibrary_initGameIni(JNIEnv* env, jclass clazz,
jstring j_game_id) {
std::string_view game_id = env->GetStringUTFChars(j_game_id, 0);
diff --git a/src/android/app/src/main/jni/native_config.cpp b/src/android/app/src/main/jni/native_config.cpp
new file mode 100644
index 000000000..6123b3d08
--- /dev/null
+++ b/src/android/app/src/main/jni/native_config.cpp
@@ -0,0 +1,224 @@
+// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include <string>
+
+#include <jni.h>
+
+#include "common/logging/log.h"
+#include "common/settings.h"
+#include "jni/android_common/android_common.h"
+#include "jni/config.h"
+#include "uisettings.h"
+
+template <typename T>
+Settings::Setting<T>* getSetting(JNIEnv* env, jstring jkey) {
+ auto key = GetJString(env, jkey);
+ auto basicSetting = Settings::values.linkage.by_key[key];
+ auto basicAndroidSetting = AndroidSettings::values.linkage.by_key[key];
+ if (basicSetting != 0) {
+ return static_cast<Settings::Setting<T>*>(basicSetting);
+ }
+ if (basicAndroidSetting != 0) {
+ return static_cast<Settings::Setting<T>*>(basicAndroidSetting);
+ }
+ LOG_ERROR(Frontend, "[Android Native] Could not find setting - {}", key);
+ return nullptr;
+}
+
+extern "C" {
+
+jboolean Java_org_yuzu_yuzu_1emu_utils_NativeConfig_getBoolean(JNIEnv* env, jobject obj,
+ jstring jkey, jboolean getDefault) {
+ auto setting = getSetting<bool>(env, jkey);
+ if (setting == nullptr) {
+ return false;
+ }
+ setting->SetGlobal(true);
+
+ if (static_cast<bool>(getDefault)) {
+ return setting->GetDefault();
+ }
+
+ return setting->GetValue();
+}
+
+void Java_org_yuzu_yuzu_1emu_utils_NativeConfig_setBoolean(JNIEnv* env, jobject obj, jstring jkey,
+ jboolean value) {
+ auto setting = getSetting<bool>(env, jkey);
+ if (setting == nullptr) {
+ return;
+ }
+ setting->SetGlobal(true);
+ setting->SetValue(static_cast<bool>(value));
+}
+
+jbyte Java_org_yuzu_yuzu_1emu_utils_NativeConfig_getByte(JNIEnv* env, jobject obj, jstring jkey,
+ jboolean getDefault) {
+ auto setting = getSetting<u8>(env, jkey);
+ if (setting == nullptr) {
+ return -1;
+ }
+ setting->SetGlobal(true);
+
+ if (static_cast<bool>(getDefault)) {
+ return setting->GetDefault();
+ }
+
+ return setting->GetValue();
+}
+
+void Java_org_yuzu_yuzu_1emu_utils_NativeConfig_setByte(JNIEnv* env, jobject obj, jstring jkey,
+ jbyte value) {
+ auto setting = getSetting<u8>(env, jkey);
+ if (setting == nullptr) {
+ return;
+ }
+ setting->SetGlobal(true);
+ setting->SetValue(value);
+}
+
+jshort Java_org_yuzu_yuzu_1emu_utils_NativeConfig_getShort(JNIEnv* env, jobject obj, jstring jkey,
+ jboolean getDefault) {
+ auto setting = getSetting<u16>(env, jkey);
+ if (setting == nullptr) {
+ return -1;
+ }
+ setting->SetGlobal(true);
+
+ if (static_cast<bool>(getDefault)) {
+ return setting->GetDefault();
+ }
+
+ return setting->GetValue();
+}
+
+void Java_org_yuzu_yuzu_1emu_utils_NativeConfig_setShort(JNIEnv* env, jobject obj, jstring jkey,
+ jshort value) {
+ auto setting = getSetting<u16>(env, jkey);
+ if (setting == nullptr) {
+ return;
+ }
+ setting->SetGlobal(true);
+ setting->SetValue(value);
+}
+
+jint Java_org_yuzu_yuzu_1emu_utils_NativeConfig_getInt(JNIEnv* env, jobject obj, jstring jkey,
+ jboolean getDefault) {
+ auto setting = getSetting<int>(env, jkey);
+ if (setting == nullptr) {
+ return -1;
+ }
+ setting->SetGlobal(true);
+
+ if (static_cast<bool>(getDefault)) {
+ return setting->GetDefault();
+ }
+
+ return setting->GetValue();
+}
+
+void Java_org_yuzu_yuzu_1emu_utils_NativeConfig_setInt(JNIEnv* env, jobject obj, jstring jkey,
+ jint value) {
+ auto setting = getSetting<int>(env, jkey);
+ if (setting == nullptr) {
+ return;
+ }
+ setting->SetGlobal(true);
+ setting->SetValue(value);
+}
+
+jfloat Java_org_yuzu_yuzu_1emu_utils_NativeConfig_getFloat(JNIEnv* env, jobject obj, jstring jkey,
+ jboolean getDefault) {
+ auto setting = getSetting<float>(env, jkey);
+ if (setting == nullptr) {
+ return -1;
+ }
+ setting->SetGlobal(true);
+
+ if (static_cast<bool>(getDefault)) {
+ return setting->GetDefault();
+ }
+
+ return setting->GetValue();
+}
+
+void Java_org_yuzu_yuzu_1emu_utils_NativeConfig_setFloat(JNIEnv* env, jobject obj, jstring jkey,
+ jfloat value) {
+ auto setting = getSetting<float>(env, jkey);
+ if (setting == nullptr) {
+ return;
+ }
+ setting->SetGlobal(true);
+ setting->SetValue(value);
+}
+
+jlong Java_org_yuzu_yuzu_1emu_utils_NativeConfig_getLong(JNIEnv* env, jobject obj, jstring jkey,
+ jboolean getDefault) {
+ auto setting = getSetting<long>(env, jkey);
+ if (setting == nullptr) {
+ return -1;
+ }
+ setting->SetGlobal(true);
+
+ if (static_cast<bool>(getDefault)) {
+ return setting->GetDefault();
+ }
+
+ return setting->GetValue();
+}
+
+void Java_org_yuzu_yuzu_1emu_utils_NativeConfig_setLong(JNIEnv* env, jobject obj, jstring jkey,
+ jlong value) {
+ auto setting = getSetting<long>(env, jkey);
+ if (setting == nullptr) {
+ return;
+ }
+ setting->SetGlobal(true);
+ setting->SetValue(value);
+}
+
+jstring Java_org_yuzu_yuzu_1emu_utils_NativeConfig_getString(JNIEnv* env, jobject obj, jstring jkey,
+ jboolean getDefault) {
+ auto setting = getSetting<std::string>(env, jkey);
+ if (setting == nullptr) {
+ return ToJString(env, "");
+ }
+ setting->SetGlobal(true);
+
+ if (static_cast<bool>(getDefault)) {
+ return ToJString(env, setting->GetDefault());
+ }
+
+ return ToJString(env, setting->GetValue());
+}
+
+void Java_org_yuzu_yuzu_1emu_utils_NativeConfig_setString(JNIEnv* env, jobject obj, jstring jkey,
+ jstring value) {
+ auto setting = getSetting<std::string>(env, jkey);
+ if (setting == nullptr) {
+ return;
+ }
+
+ setting->SetGlobal(true);
+ setting->SetValue(GetJString(env, value));
+}
+
+jboolean Java_org_yuzu_yuzu_1emu_utils_NativeConfig_getIsRuntimeModifiable(JNIEnv* env, jobject obj,
+ jstring jkey) {
+ auto key = GetJString(env, jkey);
+ auto setting = Settings::values.linkage.by_key[key];
+ if (setting != 0) {
+ return setting->RuntimeModfiable();
+ }
+ LOG_ERROR(Frontend, "[Android Native] Could not find setting - {}", key);
+ return true;
+}
+
+jstring Java_org_yuzu_yuzu_1emu_utils_NativeConfig_getConfigHeader(JNIEnv* env, jobject obj,
+ jint jcategory) {
+ auto category = static_cast<Settings::Category>(jcategory);
+ return ToJString(env, Settings::TranslateCategory(category));
+}
+
+} // extern "C"
diff --git a/src/android/app/src/main/jni/uisettings.cpp b/src/android/app/src/main/jni/uisettings.cpp
new file mode 100644
index 000000000..f2f0bad50
--- /dev/null
+++ b/src/android/app/src/main/jni/uisettings.cpp
@@ -0,0 +1,10 @@
+// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "uisettings.h"
+
+namespace AndroidSettings {
+
+Values values;
+
+} // namespace AndroidSettings
diff --git a/src/android/app/src/main/jni/uisettings.h b/src/android/app/src/main/jni/uisettings.h
new file mode 100644
index 000000000..494654af7
--- /dev/null
+++ b/src/android/app/src/main/jni/uisettings.h
@@ -0,0 +1,29 @@
+// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include <common/settings_common.h>
+#include "common/common_types.h"
+#include "common/settings_setting.h"
+
+namespace AndroidSettings {
+
+struct Values {
+ Settings::Linkage linkage;
+
+ // Android
+ Settings::Setting<bool> picture_in_picture{linkage, true, "picture_in_picture",
+ Settings::Category::Android};
+ Settings::Setting<s32> screen_layout{linkage,
+ 5,
+ "screen_layout",
+ Settings::Category::Android,
+ Settings::Specialization::Default,
+ true,
+ true};
+};
+
+extern Values values;
+
+} // namespace AndroidSettings
diff --git a/src/android/app/src/main/res/values/arrays.xml b/src/android/app/src/main/res/values/arrays.xml
index 200b99185..dc10159c9 100644
--- a/src/android/app/src/main/res/values/arrays.xml
+++ b/src/android/app/src/main/res/values/arrays.xml
@@ -243,10 +243,10 @@
<item>@string/cubeb</item>
<item>@string/string_null</item>
</string-array>
- <string-array name="outputEngineValues">
- <item>auto</item>
- <item>cubeb</item>
- <item>null</item>
- </string-array>
+ <integer-array name="outputEngineValues">
+ <item>0</item>
+ <item>1</item>
+ <item>3</item>
+ </integer-array>
</resources>
diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml
index de1b2909b..df76563fc 100644
--- a/src/android/app/src/main/res/values/strings.xml
+++ b/src/android/app/src/main/res/values/strings.xml
@@ -200,6 +200,7 @@
<string name="ini_saved">Saved settings</string>
<string name="gameid_saved">Saved settings for %1$s</string>
<string name="error_saving">Error saving %1$s.ini: %2$s</string>
+ <string name="unimplemented_menu">Unimplemented Menu</string>
<string name="loading">Loading…</string>
<string name="reset_setting_confirmation">Do you want to reset this setting back to its default value?</string>
<string name="reset_to_default">Reset to default</string>
diff --git a/src/common/settings.cpp b/src/common/settings.cpp
index 524056841..4ecaf550b 100644
--- a/src/common/settings.cpp
+++ b/src/common/settings.cpp
@@ -159,6 +159,8 @@ float Volume() {
const char* TranslateCategory(Category category) {
switch (category) {
+ case Category::Android:
+ return "Android";
case Category::Audio:
return "Audio";
case Category::Core:
diff --git a/src/common/settings_common.cpp b/src/common/settings_common.cpp
index 137b65d5f..5960b78aa 100644
--- a/src/common/settings_common.cpp
+++ b/src/common/settings_common.cpp
@@ -14,6 +14,7 @@ BasicSetting::BasicSetting(Linkage& linkage, const std::string& name, enum Categ
: label{name}, category{category_}, id{linkage.count}, save{save_},
runtime_modifiable{runtime_modifiable_}, specialization{specialization_},
other_setting{other_setting_} {
+ linkage.by_key.insert({name, this});
linkage.by_category[category].push_back(this);
linkage.count++;
}
diff --git a/src/common/settings_common.h b/src/common/settings_common.h
index 3082e0ce1..5b170dfd5 100644
--- a/src/common/settings_common.h
+++ b/src/common/settings_common.h
@@ -12,6 +12,7 @@
namespace Settings {
enum class Category : u32 {
+ Android,
Audio,
Core,
Cpu,
@@ -68,6 +69,7 @@ public:
explicit Linkage(u32 initial_count = 0);
~Linkage();
std::map<Category, std::vector<BasicSetting*>> by_category{};
+ std::map<std::string, Settings::BasicSetting*> by_key{};
std::vector<std::function<void()>> restore_functions{};
u32 count;
};