diff options
Diffstat (limited to 'src')
77 files changed, 4629 insertions, 4835 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0696201df..2da983cad 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt | |||
| @@ -35,6 +35,7 @@ if (MSVC) | |||
| 35 | # /volatile:iso - Use strict standards-compliant volatile semantics. | 35 | # /volatile:iso - Use strict standards-compliant volatile semantics. |
| 36 | # /Zc:externConstexpr - Allow extern constexpr variables to have external linkage, like the standard mandates | 36 | # /Zc:externConstexpr - Allow extern constexpr variables to have external linkage, like the standard mandates |
| 37 | # /Zc:inline - Let codegen omit inline functions in object files | 37 | # /Zc:inline - Let codegen omit inline functions in object files |
| 38 | # /Zc:preprocessor - Enable standards-conforming preprocessor | ||
| 38 | # /Zc:throwingNew - Let codegen assume `operator new` (without std::nothrow) will never return null | 39 | # /Zc:throwingNew - Let codegen assume `operator new` (without std::nothrow) will never return null |
| 39 | # /GT - Supports fiber safety for data allocated using static thread-local storage | 40 | # /GT - Supports fiber safety for data allocated using static thread-local storage |
| 40 | add_compile_options( | 41 | add_compile_options( |
| @@ -48,6 +49,7 @@ if (MSVC) | |||
| 48 | /volatile:iso | 49 | /volatile:iso |
| 49 | /Zc:externConstexpr | 50 | /Zc:externConstexpr |
| 50 | /Zc:inline | 51 | /Zc:inline |
| 52 | /Zc:preprocessor | ||
| 51 | /Zc:throwingNew | 53 | /Zc:throwingNew |
| 52 | /GT | 54 | /GT |
| 53 | 55 | ||
diff --git a/src/android/app/src/main/jni/config.cpp b/src/android/app/src/main/jni/config.cpp index 43e8aa72a..5e1f10f99 100644 --- a/src/android/app/src/main/jni/config.cpp +++ b/src/android/app/src/main/jni/config.cpp | |||
| @@ -150,15 +150,17 @@ void Config::ReadValues() { | |||
| 150 | if (rng_seed_enabled) { | 150 | if (rng_seed_enabled) { |
| 151 | Settings::values.rng_seed.SetValue(config->GetInteger("System", "rng_seed", 0)); | 151 | Settings::values.rng_seed.SetValue(config->GetInteger("System", "rng_seed", 0)); |
| 152 | } else { | 152 | } else { |
| 153 | Settings::values.rng_seed.SetValue(std::nullopt); | 153 | Settings::values.rng_seed.SetValue(0); |
| 154 | } | 154 | } |
| 155 | Settings::values.rng_seed_enabled.SetValue(rng_seed_enabled); | ||
| 155 | 156 | ||
| 156 | const auto custom_rtc_enabled = config->GetBoolean("System", "custom_rtc_enabled", false); | 157 | const auto custom_rtc_enabled = config->GetBoolean("System", "custom_rtc_enabled", false); |
| 157 | if (custom_rtc_enabled) { | 158 | if (custom_rtc_enabled) { |
| 158 | Settings::values.custom_rtc = config->GetInteger("System", "custom_rtc", 0); | 159 | Settings::values.custom_rtc = config->GetInteger("System", "custom_rtc", 0); |
| 159 | } else { | 160 | } else { |
| 160 | Settings::values.custom_rtc = std::nullopt; | 161 | Settings::values.custom_rtc = 0; |
| 161 | } | 162 | } |
| 163 | Settings::values.custom_rtc_enabled = custom_rtc_enabled; | ||
| 162 | 164 | ||
| 163 | ReadSetting("System", Settings::values.language_index); | 165 | ReadSetting("System", Settings::values.language_index); |
| 164 | ReadSetting("System", Settings::values.region_index); | 166 | ReadSetting("System", Settings::values.region_index); |
| @@ -167,7 +169,7 @@ void Config::ReadValues() { | |||
| 167 | 169 | ||
| 168 | // Core | 170 | // Core |
| 169 | ReadSetting("Core", Settings::values.use_multi_core); | 171 | ReadSetting("Core", Settings::values.use_multi_core); |
| 170 | ReadSetting("Core", Settings::values.use_unsafe_extended_memory_layout); | 172 | ReadSetting("Core", Settings::values.memory_layout_mode); |
| 171 | 173 | ||
| 172 | // Cpu | 174 | // Cpu |
| 173 | ReadSetting("Cpu", Settings::values.cpu_accuracy); | 175 | ReadSetting("Cpu", Settings::values.cpu_accuracy); |
| @@ -222,14 +224,17 @@ void Config::ReadValues() { | |||
| 222 | ReadSetting("Renderer", Settings::values.bg_blue); | 224 | ReadSetting("Renderer", Settings::values.bg_blue); |
| 223 | 225 | ||
| 224 | // Use GPU accuracy normal by default on Android | 226 | // Use GPU accuracy normal by default on Android |
| 225 | Settings::values.gpu_accuracy = static_cast<Settings::GPUAccuracy>(config->GetInteger( | 227 | Settings::values.gpu_accuracy = static_cast<Settings::GpuAccuracy>(config->GetInteger( |
| 226 | "Renderer", "gpu_accuracy", static_cast<u32>(Settings::GPUAccuracy::Normal))); | 228 | "Renderer", "gpu_accuracy", static_cast<u32>(Settings::GpuAccuracy::Normal))); |
| 227 | 229 | ||
| 228 | // Use GPU default anisotropic filtering on Android | 230 | // Use GPU default anisotropic filtering on Android |
| 229 | Settings::values.max_anisotropy = config->GetInteger("Renderer", "max_anisotropy", 1); | 231 | Settings::values.max_anisotropy = |
| 232 | static_cast<Settings::AnisotropyMode>(config->GetInteger("Renderer", "max_anisotropy", 1)); | ||
| 230 | 233 | ||
| 231 | // Disable ASTC compute by default on Android | 234 | // Disable ASTC compute by default on Android |
| 232 | Settings::values.accelerate_astc = config->GetBoolean("Renderer", "accelerate_astc", false); | 235 | Settings::values.accelerate_astc.SetValue( |
| 236 | config->GetBoolean("Renderer", "accelerate_astc", false) ? Settings::AstcDecodeMode::Gpu | ||
| 237 | : Settings::AstcDecodeMode::Cpu); | ||
| 233 | 238 | ||
| 234 | // Enable asynchronous presentation by default on Android | 239 | // Enable asynchronous presentation by default on Android |
| 235 | Settings::values.async_presentation = | 240 | Settings::values.async_presentation = |
diff --git a/src/audio_core/sink/sink_details.cpp b/src/audio_core/sink/sink_details.cpp index 39ea6d91b..027bfa517 100644 --- a/src/audio_core/sink/sink_details.cpp +++ b/src/audio_core/sink/sink_details.cpp | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | #endif | 15 | #endif |
| 16 | #include "audio_core/sink/null_sink.h" | 16 | #include "audio_core/sink/null_sink.h" |
| 17 | #include "common/logging/log.h" | 17 | #include "common/logging/log.h" |
| 18 | #include "common/settings_enums.h" | ||
| 18 | 19 | ||
| 19 | namespace AudioCore::Sink { | 20 | namespace AudioCore::Sink { |
| 20 | namespace { | 21 | namespace { |
| @@ -24,7 +25,7 @@ struct SinkDetails { | |||
| 24 | using LatencyFn = u32 (*)(); | 25 | using LatencyFn = u32 (*)(); |
| 25 | 26 | ||
| 26 | /// Name for this sink. | 27 | /// Name for this sink. |
| 27 | std::string_view id; | 28 | Settings::AudioEngine id; |
| 28 | /// A method to call to construct an instance of this type of sink. | 29 | /// A method to call to construct an instance of this type of sink. |
| 29 | FactoryFn factory; | 30 | FactoryFn factory; |
| 30 | /// A method to call to list available devices. | 31 | /// A method to call to list available devices. |
| @@ -37,7 +38,7 @@ struct SinkDetails { | |||
| 37 | constexpr SinkDetails sink_details[] = { | 38 | constexpr SinkDetails sink_details[] = { |
| 38 | #ifdef HAVE_CUBEB | 39 | #ifdef HAVE_CUBEB |
| 39 | SinkDetails{ | 40 | SinkDetails{ |
| 40 | "cubeb", | 41 | Settings::AudioEngine::Cubeb, |
| 41 | [](std::string_view device_id) -> std::unique_ptr<Sink> { | 42 | [](std::string_view device_id) -> std::unique_ptr<Sink> { |
| 42 | return std::make_unique<CubebSink>(device_id); | 43 | return std::make_unique<CubebSink>(device_id); |
| 43 | }, | 44 | }, |
| @@ -47,7 +48,7 @@ constexpr SinkDetails sink_details[] = { | |||
| 47 | #endif | 48 | #endif |
| 48 | #ifdef HAVE_SDL2 | 49 | #ifdef HAVE_SDL2 |
| 49 | SinkDetails{ | 50 | SinkDetails{ |
| 50 | "sdl2", | 51 | Settings::AudioEngine::Sdl2, |
| 51 | [](std::string_view device_id) -> std::unique_ptr<Sink> { | 52 | [](std::string_view device_id) -> std::unique_ptr<Sink> { |
| 52 | return std::make_unique<SDLSink>(device_id); | 53 | return std::make_unique<SDLSink>(device_id); |
| 53 | }, | 54 | }, |
| @@ -55,46 +56,47 @@ constexpr SinkDetails sink_details[] = { | |||
| 55 | &GetSDLLatency, | 56 | &GetSDLLatency, |
| 56 | }, | 57 | }, |
| 57 | #endif | 58 | #endif |
| 58 | SinkDetails{"null", | 59 | SinkDetails{Settings::AudioEngine::Null, |
| 59 | [](std::string_view device_id) -> std::unique_ptr<Sink> { | 60 | [](std::string_view device_id) -> std::unique_ptr<Sink> { |
| 60 | return std::make_unique<NullSink>(device_id); | 61 | return std::make_unique<NullSink>(device_id); |
| 61 | }, | 62 | }, |
| 62 | [](bool capture) { return std::vector<std::string>{"null"}; }, []() { return 0u; }}, | 63 | [](bool capture) { return std::vector<std::string>{"null"}; }, []() { return 0u; }}, |
| 63 | }; | 64 | }; |
| 64 | 65 | ||
| 65 | const SinkDetails& GetOutputSinkDetails(std::string_view sink_id) { | 66 | const SinkDetails& GetOutputSinkDetails(Settings::AudioEngine sink_id) { |
| 66 | const auto find_backend{[](std::string_view id) { | 67 | const auto find_backend{[](Settings::AudioEngine id) { |
| 67 | return std::find_if(std::begin(sink_details), std::end(sink_details), | 68 | return std::find_if(std::begin(sink_details), std::end(sink_details), |
| 68 | [&id](const auto& sink_detail) { return sink_detail.id == id; }); | 69 | [&id](const auto& sink_detail) { return sink_detail.id == id; }); |
| 69 | }}; | 70 | }}; |
| 70 | 71 | ||
| 71 | auto iter = find_backend(sink_id); | 72 | auto iter = find_backend(sink_id); |
| 72 | 73 | ||
| 73 | if (sink_id == "auto") { | 74 | if (sink_id == Settings::AudioEngine::Auto) { |
| 74 | // Auto-select a backend. Prefer CubeB, but it may report a large minimum latency which | 75 | // Auto-select a backend. Prefer CubeB, but it may report a large minimum latency which |
| 75 | // causes audio issues, in that case go with SDL. | 76 | // causes audio issues, in that case go with SDL. |
| 76 | #if defined(HAVE_CUBEB) && defined(HAVE_SDL2) | 77 | #if defined(HAVE_CUBEB) && defined(HAVE_SDL2) |
| 77 | iter = find_backend("cubeb"); | 78 | iter = find_backend(Settings::AudioEngine::Cubeb); |
| 78 | if (iter->latency() > TargetSampleCount * 3) { | 79 | if (iter->latency() > TargetSampleCount * 3) { |
| 79 | iter = find_backend("sdl2"); | 80 | iter = find_backend(Settings::AudioEngine::Sdl2); |
| 80 | } | 81 | } |
| 81 | #else | 82 | #else |
| 82 | iter = std::begin(sink_details); | 83 | iter = std::begin(sink_details); |
| 83 | #endif | 84 | #endif |
| 84 | LOG_INFO(Service_Audio, "Auto-selecting the {} backend", iter->id); | 85 | LOG_INFO(Service_Audio, "Auto-selecting the {} backend", |
| 86 | Settings::CanonicalizeEnum(iter->id)); | ||
| 85 | } | 87 | } |
| 86 | 88 | ||
| 87 | if (iter == std::end(sink_details)) { | 89 | if (iter == std::end(sink_details)) { |
| 88 | LOG_ERROR(Audio, "Invalid sink_id {}", sink_id); | 90 | LOG_ERROR(Audio, "Invalid sink_id {}", Settings::CanonicalizeEnum(sink_id)); |
| 89 | iter = find_backend("null"); | 91 | iter = find_backend(Settings::AudioEngine::Null); |
| 90 | } | 92 | } |
| 91 | 93 | ||
| 92 | return *iter; | 94 | return *iter; |
| 93 | } | 95 | } |
| 94 | } // Anonymous namespace | 96 | } // Anonymous namespace |
| 95 | 97 | ||
| 96 | std::vector<std::string_view> GetSinkIDs() { | 98 | std::vector<Settings::AudioEngine> GetSinkIDs() { |
| 97 | std::vector<std::string_view> sink_ids(std::size(sink_details)); | 99 | std::vector<Settings::AudioEngine> sink_ids(std::size(sink_details)); |
| 98 | 100 | ||
| 99 | std::transform(std::begin(sink_details), std::end(sink_details), std::begin(sink_ids), | 101 | std::transform(std::begin(sink_details), std::end(sink_details), std::begin(sink_ids), |
| 100 | [](const auto& sink) { return sink.id; }); | 102 | [](const auto& sink) { return sink.id; }); |
| @@ -102,11 +104,11 @@ std::vector<std::string_view> GetSinkIDs() { | |||
| 102 | return sink_ids; | 104 | return sink_ids; |
| 103 | } | 105 | } |
| 104 | 106 | ||
| 105 | std::vector<std::string> GetDeviceListForSink(std::string_view sink_id, bool capture) { | 107 | std::vector<std::string> GetDeviceListForSink(Settings::AudioEngine sink_id, bool capture) { |
| 106 | return GetOutputSinkDetails(sink_id).list_devices(capture); | 108 | return GetOutputSinkDetails(sink_id).list_devices(capture); |
| 107 | } | 109 | } |
| 108 | 110 | ||
| 109 | std::unique_ptr<Sink> CreateSinkFromID(std::string_view sink_id, std::string_view device_id) { | 111 | std::unique_ptr<Sink> CreateSinkFromID(Settings::AudioEngine sink_id, std::string_view device_id) { |
| 110 | return GetOutputSinkDetails(sink_id).factory(device_id); | 112 | return GetOutputSinkDetails(sink_id).factory(device_id); |
| 111 | } | 113 | } |
| 112 | 114 | ||
diff --git a/src/audio_core/sink/sink_details.h b/src/audio_core/sink/sink_details.h index e75932898..c8498842b 100644 --- a/src/audio_core/sink/sink_details.h +++ b/src/audio_core/sink/sink_details.h | |||
| @@ -3,9 +3,11 @@ | |||
| 3 | 3 | ||
| 4 | #pragma once | 4 | #pragma once |
| 5 | 5 | ||
| 6 | #include <memory> | ||
| 6 | #include <string> | 7 | #include <string> |
| 7 | #include <string_view> | 8 | #include <string_view> |
| 8 | #include <vector> | 9 | #include <vector> |
| 10 | #include "common/settings_enums.h" | ||
| 9 | 11 | ||
| 10 | namespace AudioCore { | 12 | namespace AudioCore { |
| 11 | class AudioManager; | 13 | class AudioManager; |
| @@ -19,7 +21,7 @@ class Sink; | |||
| 19 | * | 21 | * |
| 20 | * @return Vector of available sink names. | 22 | * @return Vector of available sink names. |
| 21 | */ | 23 | */ |
| 22 | std::vector<std::string_view> GetSinkIDs(); | 24 | std::vector<Settings::AudioEngine> GetSinkIDs(); |
| 23 | 25 | ||
| 24 | /** | 26 | /** |
| 25 | * Gets the list of devices for a particular sink identified by the given ID. | 27 | * Gets the list of devices for a particular sink identified by the given ID. |
| @@ -28,7 +30,7 @@ std::vector<std::string_view> GetSinkIDs(); | |||
| 28 | * @param capture - Get capture (input) devices, or output devices? | 30 | * @param capture - Get capture (input) devices, or output devices? |
| 29 | * @return Vector of device names. | 31 | * @return Vector of device names. |
| 30 | */ | 32 | */ |
| 31 | std::vector<std::string> GetDeviceListForSink(std::string_view sink_id, bool capture); | 33 | std::vector<std::string> GetDeviceListForSink(Settings::AudioEngine sink_id, bool capture); |
| 32 | 34 | ||
| 33 | /** | 35 | /** |
| 34 | * Creates an audio sink identified by the given device ID. | 36 | * Creates an audio sink identified by the given device ID. |
| @@ -37,7 +39,7 @@ std::vector<std::string> GetDeviceListForSink(std::string_view sink_id, bool cap | |||
| 37 | * @param device_id - Name of the device to create. | 39 | * @param device_id - Name of the device to create. |
| 38 | * @return Pointer to the created sink. | 40 | * @return Pointer to the created sink. |
| 39 | */ | 41 | */ |
| 40 | std::unique_ptr<Sink> CreateSinkFromID(std::string_view sink_id, std::string_view device_id); | 42 | std::unique_ptr<Sink> CreateSinkFromID(Settings::AudioEngine sink_id, std::string_view device_id); |
| 41 | 43 | ||
| 42 | } // namespace Sink | 44 | } // namespace Sink |
| 43 | } // namespace AudioCore | 45 | } // namespace AudioCore |
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 3adf13a3f..bf97d9ba2 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt | |||
| @@ -110,8 +110,12 @@ add_library(common STATIC | |||
| 110 | scratch_buffer.h | 110 | scratch_buffer.h |
| 111 | settings.cpp | 111 | settings.cpp |
| 112 | settings.h | 112 | settings.h |
| 113 | settings_common.cpp | ||
| 114 | settings_common.h | ||
| 115 | settings_enums.h | ||
| 113 | settings_input.cpp | 116 | settings_input.cpp |
| 114 | settings_input.h | 117 | settings_input.h |
| 118 | settings_setting.h | ||
| 115 | socket_types.h | 119 | socket_types.h |
| 116 | spin_lock.cpp | 120 | spin_lock.cpp |
| 117 | spin_lock.h | 121 | spin_lock.h |
| @@ -193,9 +197,16 @@ if (MSVC) | |||
| 193 | /we4254 # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data | 197 | /we4254 # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data |
| 194 | /we4800 # Implicit conversion from 'type' to bool. Possible information loss | 198 | /we4800 # Implicit conversion from 'type' to bool. Possible information loss |
| 195 | ) | 199 | ) |
| 196 | else() | 200 | endif() |
| 201 | |||
| 202 | if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") | ||
| 197 | target_compile_options(common PRIVATE | 203 | target_compile_options(common PRIVATE |
| 198 | $<$<CXX_COMPILER_ID:Clang>:-fsized-deallocation> | 204 | -fsized-deallocation |
| 205 | -Werror=unreachable-code-aggressive | ||
| 206 | ) | ||
| 207 | target_compile_definitions(common PRIVATE | ||
| 208 | # Clang 14 and earlier have errors when explicitly instantiating Settings::Setting | ||
| 209 | $<$<VERSION_LESS:$<CXX_COMPILER_VERSION>,15>:CANNOT_EXPLICITLY_INSTANTIATE> | ||
| 199 | ) | 210 | ) |
| 200 | endif() | 211 | endif() |
| 201 | 212 | ||
diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp index 6e8e8eb36..d4f27197c 100644 --- a/src/common/logging/backend.cpp +++ b/src/common/logging/backend.cpp | |||
| @@ -108,7 +108,7 @@ public: | |||
| 108 | 108 | ||
| 109 | using namespace Common::Literals; | 109 | using namespace Common::Literals; |
| 110 | // Prevent logs from exceeding a set maximum size in the event that log entries are spammed. | 110 | // Prevent logs from exceeding a set maximum size in the event that log entries are spammed. |
| 111 | const auto write_limit = Settings::values.extended_logging ? 1_GiB : 100_MiB; | 111 | const auto write_limit = Settings::values.extended_logging.GetValue() ? 1_GiB : 100_MiB; |
| 112 | const bool write_limit_exceeded = bytes_written > write_limit; | 112 | const bool write_limit_exceeded = bytes_written > write_limit; |
| 113 | if (entry.log_level >= Level::Error || write_limit_exceeded) { | 113 | if (entry.log_level >= Level::Error || write_limit_exceeded) { |
| 114 | if (write_limit_exceeded) { | 114 | if (write_limit_exceeded) { |
diff --git a/src/common/settings.cpp b/src/common/settings.cpp index d4e55f988..15fd2e222 100644 --- a/src/common/settings.cpp +++ b/src/common/settings.cpp | |||
| @@ -7,9 +7,16 @@ | |||
| 7 | #include <exception> | 7 | #include <exception> |
| 8 | #include <stdexcept> | 8 | #include <stdexcept> |
| 9 | #endif | 9 | #endif |
| 10 | #include <compare> | ||
| 11 | #include <cstddef> | ||
| 12 | #include <filesystem> | ||
| 13 | #include <functional> | ||
| 10 | #include <string_view> | 14 | #include <string_view> |
| 15 | #include <type_traits> | ||
| 16 | #include <fmt/core.h> | ||
| 11 | 17 | ||
| 12 | #include "common/assert.h" | 18 | #include "common/assert.h" |
| 19 | #include "common/fs/fs_util.h" | ||
| 13 | #include "common/fs/path_util.h" | 20 | #include "common/fs/path_util.h" |
| 14 | #include "common/logging/log.h" | 21 | #include "common/logging/log.h" |
| 15 | #include "common/settings.h" | 22 | #include "common/settings.h" |
| @@ -17,11 +24,50 @@ | |||
| 17 | 24 | ||
| 18 | namespace Settings { | 25 | namespace Settings { |
| 19 | 26 | ||
| 27 | // Clang 14 and earlier have errors when explicitly instantiating these classes | ||
| 28 | #ifndef CANNOT_EXPLICITLY_INSTANTIATE | ||
| 29 | #define SETTING(TYPE, RANGED) template class Setting<TYPE, RANGED> | ||
| 30 | #define SWITCHABLE(TYPE, RANGED) template class SwitchableSetting<TYPE, RANGED> | ||
| 31 | |||
| 32 | SETTING(AudioEngine, false); | ||
| 33 | SETTING(bool, false); | ||
| 34 | SETTING(int, false); | ||
| 35 | SETTING(std::string, false); | ||
| 36 | SETTING(u16, false); | ||
| 37 | SWITCHABLE(AnisotropyMode, true); | ||
| 38 | SWITCHABLE(AntiAliasing, false); | ||
| 39 | SWITCHABLE(AspectRatio, true); | ||
| 40 | SWITCHABLE(AstcDecodeMode, true); | ||
| 41 | SWITCHABLE(AstcRecompression, true); | ||
| 42 | SWITCHABLE(AudioMode, true); | ||
| 43 | SWITCHABLE(CpuAccuracy, true); | ||
| 44 | SWITCHABLE(FullscreenMode, true); | ||
| 45 | SWITCHABLE(GpuAccuracy, true); | ||
| 46 | SWITCHABLE(Language, true); | ||
| 47 | SWITCHABLE(NvdecEmulation, false); | ||
| 48 | SWITCHABLE(Region, true); | ||
| 49 | SWITCHABLE(RendererBackend, true); | ||
| 50 | SWITCHABLE(ScalingFilter, false); | ||
| 51 | SWITCHABLE(ShaderBackend, true); | ||
| 52 | SWITCHABLE(TimeZone, true); | ||
| 53 | SETTING(VSyncMode, true); | ||
| 54 | SWITCHABLE(bool, false); | ||
| 55 | SWITCHABLE(int, false); | ||
| 56 | SWITCHABLE(int, true); | ||
| 57 | SWITCHABLE(s64, false); | ||
| 58 | SWITCHABLE(u16, true); | ||
| 59 | SWITCHABLE(u32, false); | ||
| 60 | SWITCHABLE(u8, false); | ||
| 61 | SWITCHABLE(u8, true); | ||
| 62 | |||
| 63 | #undef SETTING | ||
| 64 | #undef SWITCHABLE | ||
| 65 | #endif | ||
| 66 | |||
| 20 | Values values; | 67 | Values values; |
| 21 | static bool configuring_global = true; | ||
| 22 | 68 | ||
| 23 | std::string GetTimeZoneString() { | 69 | std::string GetTimeZoneString(TimeZone time_zone) { |
| 24 | const auto time_zone_index = static_cast<std::size_t>(values.time_zone_index.GetValue()); | 70 | const auto time_zone_index = static_cast<std::size_t>(time_zone); |
| 25 | ASSERT(time_zone_index < Common::TimeZone::GetTimeZoneStrings().size()); | 71 | ASSERT(time_zone_index < Common::TimeZone::GetTimeZoneStrings().size()); |
| 26 | 72 | ||
| 27 | std::string location_name; | 73 | std::string location_name; |
| @@ -61,73 +107,35 @@ void LogSettings() { | |||
| 61 | }; | 107 | }; |
| 62 | 108 | ||
| 63 | LOG_INFO(Config, "yuzu Configuration:"); | 109 | LOG_INFO(Config, "yuzu Configuration:"); |
| 64 | log_setting("Controls_UseDockedMode", values.use_docked_mode.GetValue()); | 110 | for (auto& [category, settings] : values.linkage.by_category) { |
| 65 | log_setting("System_RngSeed", values.rng_seed.GetValue().value_or(0)); | 111 | for (const auto& setting : settings) { |
| 66 | log_setting("System_DeviceName", values.device_name.GetValue()); | 112 | if (setting->Id() == values.yuzu_token.Id()) { |
| 67 | log_setting("System_CurrentUser", values.current_user.GetValue()); | 113 | // Hide the token secret, for security reasons. |
| 68 | log_setting("System_LanguageIndex", values.language_index.GetValue()); | 114 | continue; |
| 69 | log_setting("System_RegionIndex", values.region_index.GetValue()); | 115 | } |
| 70 | log_setting("System_TimeZoneIndex", values.time_zone_index.GetValue()); | 116 | |
| 71 | log_setting("System_UnsafeMemoryLayout", values.use_unsafe_extended_memory_layout.GetValue()); | 117 | const auto name = fmt::format( |
| 72 | log_setting("Core_UseMultiCore", values.use_multi_core.GetValue()); | 118 | "{:c}{:c} {}.{}", setting->ToString() == setting->DefaultToString() ? '-' : 'M', |
| 73 | log_setting("CPU_Accuracy", values.cpu_accuracy.GetValue()); | 119 | setting->UsingGlobal() ? '-' : 'C', TranslateCategory(category), |
| 74 | log_setting("Renderer_UseResolutionScaling", values.resolution_setup.GetValue()); | 120 | setting->GetLabel()); |
| 75 | log_setting("Renderer_ScalingFilter", values.scaling_filter.GetValue()); | 121 | |
| 76 | log_setting("Renderer_FSRSlider", values.fsr_sharpening_slider.GetValue()); | 122 | log_setting(name, setting->Canonicalize()); |
| 77 | log_setting("Renderer_AntiAliasing", values.anti_aliasing.GetValue()); | 123 | } |
| 78 | log_setting("Renderer_UseSpeedLimit", values.use_speed_limit.GetValue()); | 124 | } |
| 79 | log_setting("Renderer_SpeedLimit", values.speed_limit.GetValue()); | ||
| 80 | log_setting("Renderer_UseDiskShaderCache", values.use_disk_shader_cache.GetValue()); | ||
| 81 | log_setting("Renderer_GPUAccuracyLevel", values.gpu_accuracy.GetValue()); | ||
| 82 | log_setting("Renderer_UseAsynchronousGpuEmulation", | ||
| 83 | values.use_asynchronous_gpu_emulation.GetValue()); | ||
| 84 | log_setting("Renderer_NvdecEmulation", values.nvdec_emulation.GetValue()); | ||
| 85 | log_setting("Renderer_AccelerateASTC", values.accelerate_astc.GetValue()); | ||
| 86 | log_setting("Renderer_AsyncASTC", values.async_astc.GetValue()); | ||
| 87 | log_setting("Renderer_AstcRecompression", values.astc_recompression.GetValue()); | ||
| 88 | log_setting("Renderer_UseVsync", values.vsync_mode.GetValue()); | ||
| 89 | log_setting("Renderer_UseReactiveFlushing", values.use_reactive_flushing.GetValue()); | ||
| 90 | log_setting("Renderer_ShaderBackend", values.shader_backend.GetValue()); | ||
| 91 | log_setting("Renderer_UseAsynchronousShaders", values.use_asynchronous_shaders.GetValue()); | ||
| 92 | log_setting("Renderer_AnisotropicFilteringLevel", values.max_anisotropy.GetValue()); | ||
| 93 | log_setting("Audio_OutputEngine", values.sink_id.GetValue()); | ||
| 94 | log_setting("Audio_OutputDevice", values.audio_output_device_id.GetValue()); | ||
| 95 | log_setting("Audio_InputDevice", values.audio_input_device_id.GetValue()); | ||
| 96 | log_setting("DataStorage_UseVirtualSd", values.use_virtual_sd.GetValue()); | ||
| 97 | log_path("DataStorage_CacheDir", Common::FS::GetYuzuPath(Common::FS::YuzuPath::CacheDir)); | 125 | log_path("DataStorage_CacheDir", Common::FS::GetYuzuPath(Common::FS::YuzuPath::CacheDir)); |
| 98 | log_path("DataStorage_ConfigDir", Common::FS::GetYuzuPath(Common::FS::YuzuPath::ConfigDir)); | 126 | log_path("DataStorage_ConfigDir", Common::FS::GetYuzuPath(Common::FS::YuzuPath::ConfigDir)); |
| 99 | log_path("DataStorage_LoadDir", Common::FS::GetYuzuPath(Common::FS::YuzuPath::LoadDir)); | 127 | log_path("DataStorage_LoadDir", Common::FS::GetYuzuPath(Common::FS::YuzuPath::LoadDir)); |
| 100 | log_path("DataStorage_NANDDir", Common::FS::GetYuzuPath(Common::FS::YuzuPath::NANDDir)); | 128 | log_path("DataStorage_NANDDir", Common::FS::GetYuzuPath(Common::FS::YuzuPath::NANDDir)); |
| 101 | log_path("DataStorage_SDMCDir", Common::FS::GetYuzuPath(Common::FS::YuzuPath::SDMCDir)); | 129 | log_path("DataStorage_SDMCDir", Common::FS::GetYuzuPath(Common::FS::YuzuPath::SDMCDir)); |
| 102 | log_setting("Debugging_ProgramArgs", values.program_args.GetValue()); | ||
| 103 | log_setting("Debugging_GDBStub", values.use_gdbstub.GetValue()); | ||
| 104 | log_setting("Input_EnableMotion", values.motion_enabled.GetValue()); | ||
| 105 | log_setting("Input_EnableVibration", values.vibration_enabled.GetValue()); | ||
| 106 | log_setting("Input_EnableTouch", values.touchscreen.enabled); | ||
| 107 | log_setting("Input_EnableMouse", values.mouse_enabled.GetValue()); | ||
| 108 | log_setting("Input_EnableKeyboard", values.keyboard_enabled.GetValue()); | ||
| 109 | log_setting("Input_EnableRingController", values.enable_ring_controller.GetValue()); | ||
| 110 | log_setting("Input_EnableIrSensor", values.enable_ir_sensor.GetValue()); | ||
| 111 | log_setting("Input_EnableCustomJoycon", values.enable_joycon_driver.GetValue()); | ||
| 112 | log_setting("Input_EnableCustomProController", values.enable_procon_driver.GetValue()); | ||
| 113 | log_setting("Input_EnableRawInput", values.enable_raw_input.GetValue()); | ||
| 114 | } | ||
| 115 | |||
| 116 | bool IsConfiguringGlobal() { | ||
| 117 | return configuring_global; | ||
| 118 | } | ||
| 119 | |||
| 120 | void SetConfiguringGlobal(bool is_global) { | ||
| 121 | configuring_global = is_global; | ||
| 122 | } | 130 | } |
| 123 | 131 | ||
| 124 | bool IsGPULevelExtreme() { | 132 | bool IsGPULevelExtreme() { |
| 125 | return values.gpu_accuracy.GetValue() == GPUAccuracy::Extreme; | 133 | return values.gpu_accuracy.GetValue() == GpuAccuracy::Extreme; |
| 126 | } | 134 | } |
| 127 | 135 | ||
| 128 | bool IsGPULevelHigh() { | 136 | bool IsGPULevelHigh() { |
| 129 | return values.gpu_accuracy.GetValue() == GPUAccuracy::Extreme || | 137 | return values.gpu_accuracy.GetValue() == GpuAccuracy::Extreme || |
| 130 | values.gpu_accuracy.GetValue() == GPUAccuracy::High; | 138 | values.gpu_accuracy.GetValue() == GpuAccuracy::High; |
| 131 | } | 139 | } |
| 132 | 140 | ||
| 133 | bool IsFastmemEnabled() { | 141 | bool IsFastmemEnabled() { |
| @@ -144,6 +152,61 @@ float Volume() { | |||
| 144 | return values.volume.GetValue() / static_cast<f32>(values.volume.GetDefault()); | 152 | return values.volume.GetValue() / static_cast<f32>(values.volume.GetDefault()); |
| 145 | } | 153 | } |
| 146 | 154 | ||
| 155 | const char* TranslateCategory(Category category) { | ||
| 156 | switch (category) { | ||
| 157 | case Category::Audio: | ||
| 158 | return "Audio"; | ||
| 159 | case Category::Core: | ||
| 160 | return "Core"; | ||
| 161 | case Category::Cpu: | ||
| 162 | case Category::CpuDebug: | ||
| 163 | case Category::CpuUnsafe: | ||
| 164 | return "Cpu"; | ||
| 165 | case Category::Renderer: | ||
| 166 | case Category::RendererAdvanced: | ||
| 167 | case Category::RendererDebug: | ||
| 168 | return "Renderer"; | ||
| 169 | case Category::System: | ||
| 170 | case Category::SystemAudio: | ||
| 171 | return "System"; | ||
| 172 | case Category::DataStorage: | ||
| 173 | return "Data Storage"; | ||
| 174 | case Category::Debugging: | ||
| 175 | case Category::DebuggingGraphics: | ||
| 176 | return "Debugging"; | ||
| 177 | case Category::Miscellaneous: | ||
| 178 | return "Miscellaneous"; | ||
| 179 | case Category::Network: | ||
| 180 | return "Network"; | ||
| 181 | case Category::WebService: | ||
| 182 | return "WebService"; | ||
| 183 | case Category::AddOns: | ||
| 184 | return "DisabledAddOns"; | ||
| 185 | case Category::Controls: | ||
| 186 | return "Controls"; | ||
| 187 | case Category::Ui: | ||
| 188 | case Category::UiGeneral: | ||
| 189 | return "UI"; | ||
| 190 | case Category::UiLayout: | ||
| 191 | return "UiLayout"; | ||
| 192 | case Category::UiGameList: | ||
| 193 | return "UiGameList"; | ||
| 194 | case Category::Screenshots: | ||
| 195 | return "Screenshots"; | ||
| 196 | case Category::Shortcuts: | ||
| 197 | return "Shortcuts"; | ||
| 198 | case Category::Multiplayer: | ||
| 199 | return "Multiplayer"; | ||
| 200 | case Category::Services: | ||
| 201 | return "Services"; | ||
| 202 | case Category::Paths: | ||
| 203 | return "Paths"; | ||
| 204 | case Category::MaxEnum: | ||
| 205 | break; | ||
| 206 | } | ||
| 207 | return "Miscellaneous"; | ||
| 208 | } | ||
| 209 | |||
| 147 | void UpdateRescalingInfo() { | 210 | void UpdateRescalingInfo() { |
| 148 | const auto setup = values.resolution_setup.GetValue(); | 211 | const auto setup = values.resolution_setup.GetValue(); |
| 149 | auto& info = values.resolution_info; | 212 | auto& info = values.resolution_info; |
| @@ -212,66 +275,19 @@ void RestoreGlobalState(bool is_powered_on) { | |||
| 212 | return; | 275 | return; |
| 213 | } | 276 | } |
| 214 | 277 | ||
| 215 | // Audio | 278 | for (const auto& reset : values.linkage.restore_functions) { |
| 216 | values.volume.SetGlobal(true); | 279 | reset(); |
| 217 | 280 | } | |
| 218 | // Core | 281 | } |
| 219 | values.use_multi_core.SetGlobal(true); | ||
| 220 | values.use_unsafe_extended_memory_layout.SetGlobal(true); | ||
| 221 | |||
| 222 | // CPU | ||
| 223 | values.cpu_accuracy.SetGlobal(true); | ||
| 224 | values.cpuopt_unsafe_unfuse_fma.SetGlobal(true); | ||
| 225 | values.cpuopt_unsafe_reduce_fp_error.SetGlobal(true); | ||
| 226 | values.cpuopt_unsafe_ignore_standard_fpcr.SetGlobal(true); | ||
| 227 | values.cpuopt_unsafe_inaccurate_nan.SetGlobal(true); | ||
| 228 | values.cpuopt_unsafe_fastmem_check.SetGlobal(true); | ||
| 229 | values.cpuopt_unsafe_ignore_global_monitor.SetGlobal(true); | ||
| 230 | 282 | ||
| 231 | // Renderer | 283 | static bool configuring_global = true; |
| 232 | values.fsr_sharpening_slider.SetGlobal(true); | ||
| 233 | values.renderer_backend.SetGlobal(true); | ||
| 234 | values.async_presentation.SetGlobal(true); | ||
| 235 | values.renderer_force_max_clock.SetGlobal(true); | ||
| 236 | values.vulkan_device.SetGlobal(true); | ||
| 237 | values.fullscreen_mode.SetGlobal(true); | ||
| 238 | values.aspect_ratio.SetGlobal(true); | ||
| 239 | values.resolution_setup.SetGlobal(true); | ||
| 240 | values.scaling_filter.SetGlobal(true); | ||
| 241 | values.anti_aliasing.SetGlobal(true); | ||
| 242 | values.max_anisotropy.SetGlobal(true); | ||
| 243 | values.use_speed_limit.SetGlobal(true); | ||
| 244 | values.speed_limit.SetGlobal(true); | ||
| 245 | values.use_disk_shader_cache.SetGlobal(true); | ||
| 246 | values.gpu_accuracy.SetGlobal(true); | ||
| 247 | values.use_asynchronous_gpu_emulation.SetGlobal(true); | ||
| 248 | values.nvdec_emulation.SetGlobal(true); | ||
| 249 | values.accelerate_astc.SetGlobal(true); | ||
| 250 | values.async_astc.SetGlobal(true); | ||
| 251 | values.astc_recompression.SetGlobal(true); | ||
| 252 | values.use_reactive_flushing.SetGlobal(true); | ||
| 253 | values.shader_backend.SetGlobal(true); | ||
| 254 | values.use_asynchronous_shaders.SetGlobal(true); | ||
| 255 | values.use_fast_gpu_time.SetGlobal(true); | ||
| 256 | values.use_vulkan_driver_pipeline_cache.SetGlobal(true); | ||
| 257 | values.bg_red.SetGlobal(true); | ||
| 258 | values.bg_green.SetGlobal(true); | ||
| 259 | values.bg_blue.SetGlobal(true); | ||
| 260 | values.enable_compute_pipelines.SetGlobal(true); | ||
| 261 | values.use_video_framerate.SetGlobal(true); | ||
| 262 | 284 | ||
| 263 | // System | 285 | bool IsConfiguringGlobal() { |
| 264 | values.language_index.SetGlobal(true); | 286 | return configuring_global; |
| 265 | values.region_index.SetGlobal(true); | 287 | } |
| 266 | values.time_zone_index.SetGlobal(true); | ||
| 267 | values.rng_seed.SetGlobal(true); | ||
| 268 | values.sound_index.SetGlobal(true); | ||
| 269 | 288 | ||
| 270 | // Controls | 289 | void SetConfiguringGlobal(bool is_global) { |
| 271 | values.players.SetGlobal(true); | 290 | configuring_global = is_global; |
| 272 | values.use_docked_mode.SetGlobal(true); | ||
| 273 | values.vibration_enabled.SetGlobal(true); | ||
| 274 | values.motion_enabled.SetGlobal(true); | ||
| 275 | } | 291 | } |
| 276 | 292 | ||
| 277 | } // namespace Settings | 293 | } // namespace Settings |
diff --git a/src/common/settings.h b/src/common/settings.h index 59e96e74f..b0bc6519a 100644 --- a/src/common/settings.h +++ b/src/common/settings.h | |||
| @@ -6,95 +6,21 @@ | |||
| 6 | #include <algorithm> | 6 | #include <algorithm> |
| 7 | #include <array> | 7 | #include <array> |
| 8 | #include <map> | 8 | #include <map> |
| 9 | #include <optional> | 9 | #include <memory> |
| 10 | #include <stdexcept> | ||
| 10 | #include <string> | 11 | #include <string> |
| 11 | #include <utility> | 12 | #include <utility> |
| 12 | #include <vector> | 13 | #include <vector> |
| 13 | 14 | ||
| 14 | #include "common/common_types.h" | 15 | #include "common/common_types.h" |
| 16 | #include "common/settings_common.h" | ||
| 17 | #include "common/settings_enums.h" | ||
| 15 | #include "common/settings_input.h" | 18 | #include "common/settings_input.h" |
| 19 | #include "common/settings_setting.h" | ||
| 16 | 20 | ||
| 17 | namespace Settings { | 21 | namespace Settings { |
| 18 | 22 | ||
| 19 | enum class VSyncMode : u32 { | 23 | const char* TranslateCategory(Settings::Category category); |
| 20 | Immediate = 0, | ||
| 21 | Mailbox = 1, | ||
| 22 | FIFO = 2, | ||
| 23 | FIFORelaxed = 3, | ||
| 24 | }; | ||
| 25 | |||
| 26 | enum class RendererBackend : u32 { | ||
| 27 | OpenGL = 0, | ||
| 28 | Vulkan = 1, | ||
| 29 | Null = 2, | ||
| 30 | }; | ||
| 31 | |||
| 32 | enum class ShaderBackend : u32 { | ||
| 33 | GLSL = 0, | ||
| 34 | GLASM = 1, | ||
| 35 | SPIRV = 2, | ||
| 36 | }; | ||
| 37 | |||
| 38 | enum class GPUAccuracy : u32 { | ||
| 39 | Normal = 0, | ||
| 40 | High = 1, | ||
| 41 | Extreme = 2, | ||
| 42 | }; | ||
| 43 | |||
| 44 | enum class CPUAccuracy : u32 { | ||
| 45 | Auto = 0, | ||
| 46 | Accurate = 1, | ||
| 47 | Unsafe = 2, | ||
| 48 | Paranoid = 3, | ||
| 49 | }; | ||
| 50 | |||
| 51 | enum class FullscreenMode : u32 { | ||
| 52 | Borderless = 0, | ||
| 53 | Exclusive = 1, | ||
| 54 | }; | ||
| 55 | |||
| 56 | enum class NvdecEmulation : u32 { | ||
| 57 | Off = 0, | ||
| 58 | CPU = 1, | ||
| 59 | GPU = 2, | ||
| 60 | }; | ||
| 61 | |||
| 62 | enum class ResolutionSetup : u32 { | ||
| 63 | Res1_2X = 0, | ||
| 64 | Res3_4X = 1, | ||
| 65 | Res1X = 2, | ||
| 66 | Res3_2X = 3, | ||
| 67 | Res2X = 4, | ||
| 68 | Res3X = 5, | ||
| 69 | Res4X = 6, | ||
| 70 | Res5X = 7, | ||
| 71 | Res6X = 8, | ||
| 72 | Res7X = 9, | ||
| 73 | Res8X = 10, | ||
| 74 | }; | ||
| 75 | |||
| 76 | enum class ScalingFilter : u32 { | ||
| 77 | NearestNeighbor = 0, | ||
| 78 | Bilinear = 1, | ||
| 79 | Bicubic = 2, | ||
| 80 | Gaussian = 3, | ||
| 81 | ScaleForce = 4, | ||
| 82 | Fsr = 5, | ||
| 83 | LastFilter = Fsr, | ||
| 84 | }; | ||
| 85 | |||
| 86 | enum class AntiAliasing : u32 { | ||
| 87 | None = 0, | ||
| 88 | Fxaa = 1, | ||
| 89 | Smaa = 2, | ||
| 90 | LastAA = Smaa, | ||
| 91 | }; | ||
| 92 | |||
| 93 | enum class AstcRecompression : u32 { | ||
| 94 | Uncompressed = 0, | ||
| 95 | Bc1 = 1, | ||
| 96 | Bc3 = 2, | ||
| 97 | }; | ||
| 98 | 24 | ||
| 99 | struct ResolutionScalingInfo { | 25 | struct ResolutionScalingInfo { |
| 100 | u32 up_scale{1}; | 26 | u32 up_scale{1}; |
| @@ -119,239 +45,47 @@ struct ResolutionScalingInfo { | |||
| 119 | } | 45 | } |
| 120 | }; | 46 | }; |
| 121 | 47 | ||
| 122 | /** The Setting class is a simple resource manager. It defines a label and default value alongside | 48 | #ifndef CANNOT_EXPLICITLY_INSTANTIATE |
| 123 | * the actual value of the setting for simpler and less-error prone use with frontend | 49 | // Instantiate the classes elsewhere (settings.cpp) to reduce compiler/linker work |
| 124 | * configurations. Specifying a default value and label is required. A minimum and maximum range can | 50 | #define SETTING(TYPE, RANGED) extern template class Setting<TYPE, RANGED> |
| 125 | * be specified for sanitization. | 51 | #define SWITCHABLE(TYPE, RANGED) extern template class SwitchableSetting<TYPE, RANGED> |
| 126 | */ | 52 | |
| 127 | template <typename Type, bool ranged = false> | 53 | SETTING(AudioEngine, false); |
| 128 | class Setting { | 54 | SETTING(bool, false); |
| 129 | protected: | 55 | SETTING(int, false); |
| 130 | Setting() = default; | 56 | SETTING(s32, false); |
| 131 | 57 | SETTING(std::string, false); | |
| 132 | /** | 58 | SETTING(std::string, false); |
| 133 | * Only sets the setting to the given initializer, leaving the other members to their default | 59 | SETTING(u16, false); |
| 134 | * initializers. | 60 | SWITCHABLE(AnisotropyMode, true); |
| 135 | * | 61 | SWITCHABLE(AntiAliasing, false); |
| 136 | * @param global_val Initial value of the setting | 62 | SWITCHABLE(AspectRatio, true); |
| 137 | */ | 63 | SWITCHABLE(AstcDecodeMode, true); |
| 138 | explicit Setting(const Type& val) : value{val} {} | 64 | SWITCHABLE(AstcRecompression, true); |
| 139 | 65 | SWITCHABLE(AudioMode, true); | |
| 140 | public: | 66 | SWITCHABLE(CpuAccuracy, true); |
| 141 | /** | 67 | SWITCHABLE(FullscreenMode, true); |
| 142 | * Sets a default value, label, and setting value. | 68 | SWITCHABLE(GpuAccuracy, true); |
| 143 | * | 69 | SWITCHABLE(Language, true); |
| 144 | * @param default_val Initial value of the setting, and default value of the setting | 70 | SWITCHABLE(NvdecEmulation, false); |
| 145 | * @param name Label for the setting | 71 | SWITCHABLE(Region, true); |
| 146 | */ | 72 | SWITCHABLE(RendererBackend, true); |
| 147 | explicit Setting(const Type& default_val, const std::string& name) | 73 | SWITCHABLE(ScalingFilter, false); |
| 148 | requires(!ranged) | 74 | SWITCHABLE(ShaderBackend, true); |
| 149 | : value{default_val}, default_value{default_val}, label{name} {} | 75 | SWITCHABLE(TimeZone, true); |
| 150 | virtual ~Setting() = default; | 76 | SETTING(VSyncMode, true); |
| 151 | 77 | SWITCHABLE(bool, false); | |
| 152 | /** | 78 | SWITCHABLE(int, false); |
| 153 | * Sets a default value, minimum value, maximum value, and label. | 79 | SWITCHABLE(int, true); |
| 154 | * | 80 | SWITCHABLE(s64, false); |
| 155 | * @param default_val Initial value of the setting, and default value of the setting | 81 | SWITCHABLE(u16, true); |
| 156 | * @param min_val Sets the minimum allowed value of the setting | 82 | SWITCHABLE(u32, false); |
| 157 | * @param max_val Sets the maximum allowed value of the setting | 83 | SWITCHABLE(u8, false); |
| 158 | * @param name Label for the setting | 84 | SWITCHABLE(u8, true); |
| 159 | */ | 85 | |
| 160 | explicit Setting(const Type& default_val, const Type& min_val, const Type& max_val, | 86 | #undef SETTING |
| 161 | const std::string& name) | 87 | #undef SWITCHABLE |
| 162 | requires(ranged) | 88 | #endif |
| 163 | : value{default_val}, | ||
| 164 | default_value{default_val}, maximum{max_val}, minimum{min_val}, label{name} {} | ||
| 165 | |||
| 166 | /** | ||
| 167 | * Returns a reference to the setting's value. | ||
| 168 | * | ||
| 169 | * @returns A reference to the setting | ||
| 170 | */ | ||
| 171 | [[nodiscard]] virtual const Type& GetValue() const { | ||
| 172 | return value; | ||
| 173 | } | ||
| 174 | |||
| 175 | /** | ||
| 176 | * Sets the setting to the given value. | ||
| 177 | * | ||
| 178 | * @param val The desired value | ||
| 179 | */ | ||
| 180 | virtual void SetValue(const Type& val) { | ||
| 181 | Type temp{ranged ? std::clamp(val, minimum, maximum) : val}; | ||
| 182 | std::swap(value, temp); | ||
| 183 | } | ||
| 184 | |||
| 185 | /** | ||
| 186 | * Returns the value that this setting was created with. | ||
| 187 | * | ||
| 188 | * @returns A reference to the default value | ||
| 189 | */ | ||
| 190 | [[nodiscard]] const Type& GetDefault() const { | ||
| 191 | return default_value; | ||
| 192 | } | ||
| 193 | |||
| 194 | /** | ||
| 195 | * Returns the label this setting was created with. | ||
| 196 | * | ||
| 197 | * @returns A reference to the label | ||
| 198 | */ | ||
| 199 | [[nodiscard]] const std::string& GetLabel() const { | ||
| 200 | return label; | ||
| 201 | } | ||
| 202 | |||
| 203 | /** | ||
| 204 | * Assigns a value to the setting. | ||
| 205 | * | ||
| 206 | * @param val The desired setting value | ||
| 207 | * | ||
| 208 | * @returns A reference to the setting | ||
| 209 | */ | ||
| 210 | virtual const Type& operator=(const Type& val) { | ||
| 211 | Type temp{ranged ? std::clamp(val, minimum, maximum) : val}; | ||
| 212 | std::swap(value, temp); | ||
| 213 | return value; | ||
| 214 | } | ||
| 215 | |||
| 216 | /** | ||
| 217 | * Returns a reference to the setting. | ||
| 218 | * | ||
| 219 | * @returns A reference to the setting | ||
| 220 | */ | ||
| 221 | explicit virtual operator const Type&() const { | ||
| 222 | return value; | ||
| 223 | } | ||
| 224 | |||
| 225 | protected: | ||
| 226 | Type value{}; ///< The setting | ||
| 227 | const Type default_value{}; ///< The default value | ||
| 228 | const Type maximum{}; ///< Maximum allowed value of the setting | ||
| 229 | const Type minimum{}; ///< Minimum allowed value of the setting | ||
| 230 | const std::string label{}; ///< The setting's label | ||
| 231 | }; | ||
| 232 | |||
| 233 | /** | ||
| 234 | * The SwitchableSetting class is a slightly more complex version of the Setting class. This adds a | ||
| 235 | * custom setting to switch to when a guest application specifically requires it. The effect is that | ||
| 236 | * other components of the emulator can access the setting's intended value without any need for the | ||
| 237 | * component to ask whether the custom or global setting is needed at the moment. | ||
| 238 | * | ||
| 239 | * By default, the global setting is used. | ||
| 240 | */ | ||
| 241 | template <typename Type, bool ranged = false> | ||
| 242 | class SwitchableSetting : virtual public Setting<Type, ranged> { | ||
| 243 | public: | ||
| 244 | /** | ||
| 245 | * Sets a default value, label, and setting value. | ||
| 246 | * | ||
| 247 | * @param default_val Initial value of the setting, and default value of the setting | ||
| 248 | * @param name Label for the setting | ||
| 249 | */ | ||
| 250 | explicit SwitchableSetting(const Type& default_val, const std::string& name) | ||
| 251 | requires(!ranged) | ||
| 252 | : Setting<Type>{default_val, name} {} | ||
| 253 | virtual ~SwitchableSetting() = default; | ||
| 254 | |||
| 255 | /** | ||
| 256 | * Sets a default value, minimum value, maximum value, and label. | ||
| 257 | * | ||
| 258 | * @param default_val Initial value of the setting, and default value of the setting | ||
| 259 | * @param min_val Sets the minimum allowed value of the setting | ||
| 260 | * @param max_val Sets the maximum allowed value of the setting | ||
| 261 | * @param name Label for the setting | ||
| 262 | */ | ||
| 263 | explicit SwitchableSetting(const Type& default_val, const Type& min_val, const Type& max_val, | ||
| 264 | const std::string& name) | ||
| 265 | requires(ranged) | ||
| 266 | : Setting<Type, true>{default_val, min_val, max_val, name} {} | ||
| 267 | |||
| 268 | /** | ||
| 269 | * Tells this setting to represent either the global or custom setting when other member | ||
| 270 | * functions are used. | ||
| 271 | * | ||
| 272 | * @param to_global Whether to use the global or custom setting. | ||
| 273 | */ | ||
| 274 | void SetGlobal(bool to_global) { | ||
| 275 | use_global = to_global; | ||
| 276 | } | ||
| 277 | |||
| 278 | /** | ||
| 279 | * Returns whether this setting is using the global setting or not. | ||
| 280 | * | ||
| 281 | * @returns The global state | ||
| 282 | */ | ||
| 283 | [[nodiscard]] bool UsingGlobal() const { | ||
| 284 | return use_global; | ||
| 285 | } | ||
| 286 | |||
| 287 | /** | ||
| 288 | * Returns either the global or custom setting depending on the values of this setting's global | ||
| 289 | * state or if the global value was specifically requested. | ||
| 290 | * | ||
| 291 | * @param need_global Request global value regardless of setting's state; defaults to false | ||
| 292 | * | ||
| 293 | * @returns The required value of the setting | ||
| 294 | */ | ||
| 295 | [[nodiscard]] virtual const Type& GetValue() const override { | ||
| 296 | if (use_global) { | ||
| 297 | return this->value; | ||
| 298 | } | ||
| 299 | return custom; | ||
| 300 | } | ||
| 301 | [[nodiscard]] virtual const Type& GetValue(bool need_global) const { | ||
| 302 | if (use_global || need_global) { | ||
| 303 | return this->value; | ||
| 304 | } | ||
| 305 | return custom; | ||
| 306 | } | ||
| 307 | |||
| 308 | /** | ||
| 309 | * Sets the current setting value depending on the global state. | ||
| 310 | * | ||
| 311 | * @param val The new value | ||
| 312 | */ | ||
| 313 | void SetValue(const Type& val) override { | ||
| 314 | Type temp{ranged ? std::clamp(val, this->minimum, this->maximum) : val}; | ||
| 315 | if (use_global) { | ||
| 316 | std::swap(this->value, temp); | ||
| 317 | } else { | ||
| 318 | std::swap(custom, temp); | ||
| 319 | } | ||
| 320 | } | ||
| 321 | |||
| 322 | /** | ||
| 323 | * Assigns the current setting value depending on the global state. | ||
| 324 | * | ||
| 325 | * @param val The new value | ||
| 326 | * | ||
| 327 | * @returns A reference to the current setting value | ||
| 328 | */ | ||
| 329 | const Type& operator=(const Type& val) override { | ||
| 330 | Type temp{ranged ? std::clamp(val, this->minimum, this->maximum) : val}; | ||
| 331 | if (use_global) { | ||
| 332 | std::swap(this->value, temp); | ||
| 333 | return this->value; | ||
| 334 | } | ||
| 335 | std::swap(custom, temp); | ||
| 336 | return custom; | ||
| 337 | } | ||
| 338 | |||
| 339 | /** | ||
| 340 | * Returns the current setting value depending on the global state. | ||
| 341 | * | ||
| 342 | * @returns A reference to the current setting value | ||
| 343 | */ | ||
| 344 | virtual explicit operator const Type&() const override { | ||
| 345 | if (use_global) { | ||
| 346 | return this->value; | ||
| 347 | } | ||
| 348 | return custom; | ||
| 349 | } | ||
| 350 | |||
| 351 | protected: | ||
| 352 | bool use_global{true}; ///< The setting's global state | ||
| 353 | Type custom{}; ///< The custom value of the setting | ||
| 354 | }; | ||
| 355 | 89 | ||
| 356 | /** | 90 | /** |
| 357 | * The InputSetting class allows for getting a reference to either the global or custom members. | 91 | * The InputSetting class allows for getting a reference to either the global or custom members. |
| @@ -391,208 +125,388 @@ struct TouchFromButtonMap { | |||
| 391 | }; | 125 | }; |
| 392 | 126 | ||
| 393 | struct Values { | 127 | struct Values { |
| 128 | Linkage linkage{}; | ||
| 129 | |||
| 394 | // Audio | 130 | // Audio |
| 395 | Setting<std::string> sink_id{"auto", "output_engine"}; | 131 | Setting<AudioEngine> sink_id{linkage, AudioEngine::Auto, "output_engine", Category::Audio, |
| 396 | Setting<std::string> audio_output_device_id{"auto", "output_device"}; | 132 | Specialization::RuntimeList}; |
| 397 | Setting<std::string> audio_input_device_id{"auto", "input_device"}; | 133 | Setting<std::string> audio_output_device_id{linkage, "auto", "output_device", Category::Audio, |
| 398 | Setting<bool> audio_muted{false, "audio_muted"}; | 134 | Specialization::RuntimeList}; |
| 399 | SwitchableSetting<u8, true> volume{100, 0, 200, "volume"}; | 135 | Setting<std::string> audio_input_device_id{linkage, "auto", "input_device", Category::Audio, |
| 400 | Setting<bool> dump_audio_commands{false, "dump_audio_commands"}; | 136 | Specialization::RuntimeList}; |
| 137 | SwitchableSetting<AudioMode, true> sound_index{ | ||
| 138 | linkage, AudioMode::Stereo, AudioMode::Mono, AudioMode::Surround, | ||
| 139 | "sound_index", Category::SystemAudio, Specialization::Default, true, | ||
| 140 | true}; | ||
| 141 | SwitchableSetting<u8, true> volume{linkage, | ||
| 142 | 100, | ||
| 143 | 0, | ||
| 144 | 200, | ||
| 145 | "volume", | ||
| 146 | Category::Audio, | ||
| 147 | Specialization::Scalar | Specialization::Percentage, | ||
| 148 | true, | ||
| 149 | true}; | ||
| 150 | Setting<bool, false> audio_muted{ | ||
| 151 | linkage, false, "audio_muted", Category::Audio, Specialization::Default, false, true}; | ||
| 152 | Setting<bool, false> dump_audio_commands{ | ||
| 153 | linkage, false, "dump_audio_commands", Category::Audio, Specialization::Default, false}; | ||
| 401 | 154 | ||
| 402 | // Core | 155 | // Core |
| 403 | SwitchableSetting<bool> use_multi_core{true, "use_multi_core"}; | 156 | SwitchableSetting<bool> use_multi_core{linkage, true, "use_multi_core", Category::Core}; |
| 404 | SwitchableSetting<bool> use_unsafe_extended_memory_layout{false, | 157 | SwitchableSetting<MemoryLayout, true> memory_layout_mode{linkage, |
| 405 | "use_unsafe_extended_memory_layout"}; | 158 | MemoryLayout::Memory_4Gb, |
| 159 | MemoryLayout::Memory_4Gb, | ||
| 160 | MemoryLayout::Memory_8Gb, | ||
| 161 | "memory_layout_mode", | ||
| 162 | Category::Core}; | ||
| 163 | SwitchableSetting<bool> use_speed_limit{ | ||
| 164 | linkage, true, "use_speed_limit", Category::Core, Specialization::Paired, false, true}; | ||
| 165 | SwitchableSetting<u16, true> speed_limit{linkage, | ||
| 166 | 100, | ||
| 167 | 0, | ||
| 168 | 9999, | ||
| 169 | "speed_limit", | ||
| 170 | Category::Core, | ||
| 171 | Specialization::Countable | Specialization::Percentage, | ||
| 172 | true, | ||
| 173 | true, | ||
| 174 | &use_speed_limit}; | ||
| 406 | 175 | ||
| 407 | // Cpu | 176 | // Cpu |
| 408 | SwitchableSetting<CPUAccuracy, true> cpu_accuracy{CPUAccuracy::Auto, CPUAccuracy::Auto, | 177 | SwitchableSetting<CpuAccuracy, true> cpu_accuracy{linkage, CpuAccuracy::Auto, |
| 409 | CPUAccuracy::Paranoid, "cpu_accuracy"}; | 178 | CpuAccuracy::Auto, CpuAccuracy::Paranoid, |
| 410 | // TODO: remove cpu_accuracy_first_time, migration setting added 8 July 2021 | 179 | "cpu_accuracy", Category::Cpu}; |
| 411 | Setting<bool> cpu_accuracy_first_time{true, "cpu_accuracy_first_time"}; | 180 | Setting<bool> cpu_debug_mode{linkage, false, "cpu_debug_mode", Category::CpuDebug}; |
| 412 | Setting<bool> cpu_debug_mode{false, "cpu_debug_mode"}; | 181 | |
| 413 | 182 | Setting<bool> cpuopt_page_tables{linkage, true, "cpuopt_page_tables", Category::CpuDebug}; | |
| 414 | Setting<bool> cpuopt_page_tables{true, "cpuopt_page_tables"}; | 183 | Setting<bool> cpuopt_block_linking{linkage, true, "cpuopt_block_linking", Category::CpuDebug}; |
| 415 | Setting<bool> cpuopt_block_linking{true, "cpuopt_block_linking"}; | 184 | Setting<bool> cpuopt_return_stack_buffer{linkage, true, "cpuopt_return_stack_buffer", |
| 416 | Setting<bool> cpuopt_return_stack_buffer{true, "cpuopt_return_stack_buffer"}; | 185 | Category::CpuDebug}; |
| 417 | Setting<bool> cpuopt_fast_dispatcher{true, "cpuopt_fast_dispatcher"}; | 186 | Setting<bool> cpuopt_fast_dispatcher{linkage, true, "cpuopt_fast_dispatcher", |
| 418 | Setting<bool> cpuopt_context_elimination{true, "cpuopt_context_elimination"}; | 187 | Category::CpuDebug}; |
| 419 | Setting<bool> cpuopt_const_prop{true, "cpuopt_const_prop"}; | 188 | Setting<bool> cpuopt_context_elimination{linkage, true, "cpuopt_context_elimination", |
| 420 | Setting<bool> cpuopt_misc_ir{true, "cpuopt_misc_ir"}; | 189 | Category::CpuDebug}; |
| 421 | Setting<bool> cpuopt_reduce_misalign_checks{true, "cpuopt_reduce_misalign_checks"}; | 190 | Setting<bool> cpuopt_const_prop{linkage, true, "cpuopt_const_prop", Category::CpuDebug}; |
| 422 | Setting<bool> cpuopt_fastmem{true, "cpuopt_fastmem"}; | 191 | Setting<bool> cpuopt_misc_ir{linkage, true, "cpuopt_misc_ir", Category::CpuDebug}; |
| 423 | Setting<bool> cpuopt_fastmem_exclusives{true, "cpuopt_fastmem_exclusives"}; | 192 | Setting<bool> cpuopt_reduce_misalign_checks{linkage, true, "cpuopt_reduce_misalign_checks", |
| 424 | Setting<bool> cpuopt_recompile_exclusives{true, "cpuopt_recompile_exclusives"}; | 193 | Category::CpuDebug}; |
| 425 | Setting<bool> cpuopt_ignore_memory_aborts{true, "cpuopt_ignore_memory_aborts"}; | 194 | Setting<bool> cpuopt_fastmem{linkage, true, "cpuopt_fastmem", Category::CpuDebug}; |
| 426 | 195 | Setting<bool> cpuopt_fastmem_exclusives{linkage, true, "cpuopt_fastmem_exclusives", | |
| 427 | SwitchableSetting<bool> cpuopt_unsafe_unfuse_fma{true, "cpuopt_unsafe_unfuse_fma"}; | 196 | Category::CpuDebug}; |
| 428 | SwitchableSetting<bool> cpuopt_unsafe_reduce_fp_error{true, "cpuopt_unsafe_reduce_fp_error"}; | 197 | Setting<bool> cpuopt_recompile_exclusives{linkage, true, "cpuopt_recompile_exclusives", |
| 198 | Category::CpuDebug}; | ||
| 199 | Setting<bool> cpuopt_ignore_memory_aborts{linkage, true, "cpuopt_ignore_memory_aborts", | ||
| 200 | Category::CpuDebug}; | ||
| 201 | |||
| 202 | SwitchableSetting<bool> cpuopt_unsafe_unfuse_fma{linkage, true, "cpuopt_unsafe_unfuse_fma", | ||
| 203 | Category::CpuUnsafe}; | ||
| 204 | SwitchableSetting<bool> cpuopt_unsafe_reduce_fp_error{ | ||
| 205 | linkage, true, "cpuopt_unsafe_reduce_fp_error", Category::CpuUnsafe}; | ||
| 429 | SwitchableSetting<bool> cpuopt_unsafe_ignore_standard_fpcr{ | 206 | SwitchableSetting<bool> cpuopt_unsafe_ignore_standard_fpcr{ |
| 430 | true, "cpuopt_unsafe_ignore_standard_fpcr"}; | 207 | linkage, true, "cpuopt_unsafe_ignore_standard_fpcr", Category::CpuUnsafe}; |
| 431 | SwitchableSetting<bool> cpuopt_unsafe_inaccurate_nan{true, "cpuopt_unsafe_inaccurate_nan"}; | 208 | SwitchableSetting<bool> cpuopt_unsafe_inaccurate_nan{ |
| 432 | SwitchableSetting<bool> cpuopt_unsafe_fastmem_check{true, "cpuopt_unsafe_fastmem_check"}; | 209 | linkage, true, "cpuopt_unsafe_inaccurate_nan", Category::CpuUnsafe}; |
| 210 | SwitchableSetting<bool> cpuopt_unsafe_fastmem_check{ | ||
| 211 | linkage, true, "cpuopt_unsafe_fastmem_check", Category::CpuUnsafe}; | ||
| 433 | SwitchableSetting<bool> cpuopt_unsafe_ignore_global_monitor{ | 212 | SwitchableSetting<bool> cpuopt_unsafe_ignore_global_monitor{ |
| 434 | true, "cpuopt_unsafe_ignore_global_monitor"}; | 213 | linkage, true, "cpuopt_unsafe_ignore_global_monitor", Category::CpuUnsafe}; |
| 435 | 214 | ||
| 436 | // Renderer | 215 | // Renderer |
| 437 | SwitchableSetting<RendererBackend, true> renderer_backend{ | 216 | SwitchableSetting<RendererBackend, true> renderer_backend{ |
| 438 | RendererBackend::Vulkan, RendererBackend::OpenGL, RendererBackend::Null, "backend"}; | 217 | linkage, RendererBackend::Vulkan, RendererBackend::OpenGL, RendererBackend::Null, |
| 439 | SwitchableSetting<bool> async_presentation{false, "async_presentation"}; | 218 | "backend", Category::Renderer}; |
| 440 | SwitchableSetting<bool> renderer_force_max_clock{false, "force_max_clock"}; | 219 | SwitchableSetting<ShaderBackend, true> shader_backend{ |
| 441 | Setting<bool> renderer_debug{false, "debug"}; | 220 | linkage, ShaderBackend::Glsl, ShaderBackend::Glsl, ShaderBackend::SpirV, |
| 442 | Setting<bool> renderer_shader_feedback{false, "shader_feedback"}; | 221 | "shader_backend", Category::Renderer, Specialization::RuntimeList}; |
| 443 | Setting<bool> enable_nsight_aftermath{false, "nsight_aftermath"}; | 222 | SwitchableSetting<int> vulkan_device{linkage, 0, "vulkan_device", Category::Renderer, |
| 444 | Setting<bool> disable_shader_loop_safety_checks{false, "disable_shader_loop_safety_checks"}; | 223 | Specialization::RuntimeList}; |
| 445 | SwitchableSetting<int> vulkan_device{0, "vulkan_device"}; | 224 | |
| 446 | 225 | SwitchableSetting<bool> use_disk_shader_cache{linkage, true, "use_disk_shader_cache", | |
| 447 | ResolutionScalingInfo resolution_info{}; | 226 | Category::Renderer}; |
| 448 | SwitchableSetting<ResolutionSetup> resolution_setup{ResolutionSetup::Res1X, "resolution_setup"}; | 227 | SwitchableSetting<bool> use_asynchronous_gpu_emulation{ |
| 449 | SwitchableSetting<ScalingFilter> scaling_filter{ScalingFilter::Bilinear, "scaling_filter"}; | 228 | linkage, true, "use_asynchronous_gpu_emulation", Category::Renderer}; |
| 450 | SwitchableSetting<int, true> fsr_sharpening_slider{25, 0, 200, "fsr_sharpening_slider"}; | 229 | SwitchableSetting<AstcDecodeMode, true> accelerate_astc{linkage, |
| 451 | SwitchableSetting<AntiAliasing> anti_aliasing{AntiAliasing::None, "anti_aliasing"}; | 230 | AstcDecodeMode::Gpu, |
| 231 | AstcDecodeMode::Cpu, | ||
| 232 | AstcDecodeMode::CpuAsynchronous, | ||
| 233 | "accelerate_astc", | ||
| 234 | Category::Renderer}; | ||
| 235 | Setting<VSyncMode, true> vsync_mode{ | ||
| 236 | linkage, VSyncMode::Fifo, VSyncMode::Immediate, VSyncMode::FifoRelaxed, | ||
| 237 | "use_vsync", Category::Renderer, Specialization::RuntimeList, true, | ||
| 238 | true}; | ||
| 239 | SwitchableSetting<NvdecEmulation> nvdec_emulation{linkage, NvdecEmulation::Gpu, | ||
| 240 | "nvdec_emulation", Category::Renderer}; | ||
| 452 | // *nix platforms may have issues with the borderless windowed fullscreen mode. | 241 | // *nix platforms may have issues with the borderless windowed fullscreen mode. |
| 453 | // Default to exclusive fullscreen on these platforms for now. | 242 | // Default to exclusive fullscreen on these platforms for now. |
| 454 | SwitchableSetting<FullscreenMode, true> fullscreen_mode{ | 243 | SwitchableSetting<FullscreenMode, true> fullscreen_mode{linkage, |
| 455 | #ifdef _WIN32 | 244 | #ifdef _WIN32 |
| 456 | FullscreenMode::Borderless, | 245 | FullscreenMode::Borderless, |
| 457 | #else | 246 | #else |
| 458 | FullscreenMode::Exclusive, | 247 | FullscreenMode::Exclusive, |
| 459 | #endif | 248 | #endif |
| 460 | FullscreenMode::Borderless, FullscreenMode::Exclusive, "fullscreen_mode"}; | 249 | FullscreenMode::Borderless, |
| 461 | SwitchableSetting<int, true> aspect_ratio{0, 0, 4, "aspect_ratio"}; | 250 | FullscreenMode::Exclusive, |
| 462 | SwitchableSetting<int, true> max_anisotropy{0, 0, 5, "max_anisotropy"}; | 251 | "fullscreen_mode", |
| 463 | SwitchableSetting<bool> use_speed_limit{true, "use_speed_limit"}; | 252 | Category::Renderer, |
| 464 | SwitchableSetting<u16, true> speed_limit{100, 0, 9999, "speed_limit"}; | 253 | Specialization::Default, |
| 465 | SwitchableSetting<bool> use_disk_shader_cache{true, "use_disk_shader_cache"}; | 254 | true, |
| 466 | SwitchableSetting<GPUAccuracy, true> gpu_accuracy{GPUAccuracy::High, GPUAccuracy::Normal, | 255 | true}; |
| 467 | GPUAccuracy::Extreme, "gpu_accuracy"}; | 256 | SwitchableSetting<AspectRatio, true> aspect_ratio{linkage, |
| 468 | SwitchableSetting<bool> use_asynchronous_gpu_emulation{true, "use_asynchronous_gpu_emulation"}; | 257 | AspectRatio::R16_9, |
| 469 | SwitchableSetting<NvdecEmulation> nvdec_emulation{NvdecEmulation::GPU, "nvdec_emulation"}; | 258 | AspectRatio::R16_9, |
| 470 | SwitchableSetting<bool> accelerate_astc{true, "accelerate_astc"}; | 259 | AspectRatio::Stretch, |
| 471 | SwitchableSetting<bool> async_astc{false, "async_astc"}; | 260 | "aspect_ratio", |
| 472 | Setting<VSyncMode, true> vsync_mode{VSyncMode::FIFO, VSyncMode::Immediate, | 261 | Category::Renderer, |
| 473 | VSyncMode::FIFORelaxed, "use_vsync"}; | 262 | Specialization::Default, |
| 474 | SwitchableSetting<bool> use_reactive_flushing{true, "use_reactive_flushing"}; | 263 | true, |
| 475 | SwitchableSetting<ShaderBackend, true> shader_backend{ShaderBackend::GLSL, ShaderBackend::GLSL, | 264 | true}; |
| 476 | ShaderBackend::SPIRV, "shader_backend"}; | 265 | |
| 477 | SwitchableSetting<bool> use_asynchronous_shaders{false, "use_asynchronous_shaders"}; | 266 | ResolutionScalingInfo resolution_info{}; |
| 478 | SwitchableSetting<bool> use_fast_gpu_time{true, "use_fast_gpu_time"}; | 267 | SwitchableSetting<ResolutionSetup> resolution_setup{linkage, ResolutionSetup::Res1X, |
| 479 | SwitchableSetting<bool> use_vulkan_driver_pipeline_cache{true, | 268 | "resolution_setup", Category::Renderer}; |
| 480 | "use_vulkan_driver_pipeline_cache"}; | 269 | SwitchableSetting<ScalingFilter> scaling_filter{linkage, |
| 481 | SwitchableSetting<bool> enable_compute_pipelines{false, "enable_compute_pipelines"}; | 270 | ScalingFilter::Bilinear, |
| 482 | SwitchableSetting<AstcRecompression, true> astc_recompression{ | 271 | "scaling_filter", |
| 483 | AstcRecompression::Uncompressed, AstcRecompression::Uncompressed, AstcRecompression::Bc3, | 272 | Category::Renderer, |
| 484 | "astc_recompression"}; | 273 | Specialization::Default, |
| 485 | SwitchableSetting<bool> use_video_framerate{false, "use_video_framerate"}; | 274 | true, |
| 486 | SwitchableSetting<bool> barrier_feedback_loops{true, "barrier_feedback_loops"}; | 275 | true}; |
| 487 | 276 | SwitchableSetting<AntiAliasing> anti_aliasing{linkage, | |
| 488 | SwitchableSetting<u8> bg_red{0, "bg_red"}; | 277 | AntiAliasing::None, |
| 489 | SwitchableSetting<u8> bg_green{0, "bg_green"}; | 278 | "anti_aliasing", |
| 490 | SwitchableSetting<u8> bg_blue{0, "bg_blue"}; | 279 | Category::Renderer, |
| 280 | Specialization::Default, | ||
| 281 | true, | ||
| 282 | true}; | ||
| 283 | SwitchableSetting<int, true> fsr_sharpening_slider{linkage, | ||
| 284 | 25, | ||
| 285 | 0, | ||
| 286 | 200, | ||
| 287 | "fsr_sharpening_slider", | ||
| 288 | Category::Renderer, | ||
| 289 | Specialization::Scalar | | ||
| 290 | Specialization::Percentage, | ||
| 291 | true, | ||
| 292 | true}; | ||
| 293 | |||
| 294 | SwitchableSetting<u8, false> bg_red{ | ||
| 295 | linkage, 0, "bg_red", Category::Renderer, Specialization::Default, true, true}; | ||
| 296 | SwitchableSetting<u8, false> bg_green{ | ||
| 297 | linkage, 0, "bg_green", Category::Renderer, Specialization::Default, true, true}; | ||
| 298 | SwitchableSetting<u8, false> bg_blue{ | ||
| 299 | linkage, 0, "bg_blue", Category::Renderer, Specialization::Default, true, true}; | ||
| 300 | |||
| 301 | SwitchableSetting<GpuAccuracy, true> gpu_accuracy{linkage, | ||
| 302 | GpuAccuracy::High, | ||
| 303 | GpuAccuracy::Normal, | ||
| 304 | GpuAccuracy::Extreme, | ||
| 305 | "gpu_accuracy", | ||
| 306 | Category::RendererAdvanced, | ||
| 307 | Specialization::Default, | ||
| 308 | true, | ||
| 309 | true}; | ||
| 310 | SwitchableSetting<AnisotropyMode, true> max_anisotropy{ | ||
| 311 | linkage, AnisotropyMode::Automatic, AnisotropyMode::Automatic, AnisotropyMode::X16, | ||
| 312 | "max_anisotropy", Category::RendererAdvanced}; | ||
| 313 | SwitchableSetting<AstcRecompression, true> astc_recompression{linkage, | ||
| 314 | AstcRecompression::Uncompressed, | ||
| 315 | AstcRecompression::Uncompressed, | ||
| 316 | AstcRecompression::Bc3, | ||
| 317 | "astc_recompression", | ||
| 318 | Category::RendererAdvanced}; | ||
| 319 | SwitchableSetting<bool> async_presentation{linkage, false, "async_presentation", | ||
| 320 | Category::RendererAdvanced}; | ||
| 321 | SwitchableSetting<bool> renderer_force_max_clock{linkage, false, "force_max_clock", | ||
| 322 | Category::RendererAdvanced}; | ||
| 323 | SwitchableSetting<bool> use_reactive_flushing{linkage, true, "use_reactive_flushing", | ||
| 324 | Category::RendererAdvanced}; | ||
| 325 | SwitchableSetting<bool> use_asynchronous_shaders{linkage, false, "use_asynchronous_shaders", | ||
| 326 | Category::RendererAdvanced}; | ||
| 327 | SwitchableSetting<bool> use_fast_gpu_time{ | ||
| 328 | linkage, true, "use_fast_gpu_time", Category::RendererAdvanced, Specialization::Default, | ||
| 329 | true, true}; | ||
| 330 | SwitchableSetting<bool> use_vulkan_driver_pipeline_cache{linkage, | ||
| 331 | true, | ||
| 332 | "use_vulkan_driver_pipeline_cache", | ||
| 333 | Category::RendererAdvanced, | ||
| 334 | Specialization::Default, | ||
| 335 | true, | ||
| 336 | true}; | ||
| 337 | SwitchableSetting<bool> enable_compute_pipelines{linkage, false, "enable_compute_pipelines", | ||
| 338 | Category::RendererAdvanced}; | ||
| 339 | SwitchableSetting<bool> use_video_framerate{linkage, false, "use_video_framerate", | ||
| 340 | Category::RendererAdvanced}; | ||
| 341 | SwitchableSetting<bool> barrier_feedback_loops{linkage, true, "barrier_feedback_loops", | ||
| 342 | Category::RendererAdvanced}; | ||
| 343 | |||
| 344 | Setting<bool> renderer_debug{linkage, false, "debug", Category::RendererDebug}; | ||
| 345 | Setting<bool> renderer_shader_feedback{linkage, false, "shader_feedback", | ||
| 346 | Category::RendererDebug}; | ||
| 347 | Setting<bool> enable_nsight_aftermath{linkage, false, "nsight_aftermath", | ||
| 348 | Category::RendererDebug}; | ||
| 349 | Setting<bool> disable_shader_loop_safety_checks{ | ||
| 350 | linkage, false, "disable_shader_loop_safety_checks", Category::RendererDebug}; | ||
| 491 | 351 | ||
| 492 | // System | 352 | // System |
| 493 | SwitchableSetting<std::optional<u32>> rng_seed{std::optional<u32>(), "rng_seed"}; | 353 | SwitchableSetting<Language, true> language_index{linkage, |
| 494 | Setting<std::string> device_name{"Yuzu", "device_name"}; | 354 | Language::EnglishAmerican, |
| 355 | Language::Japanese, | ||
| 356 | Language::PortugueseBrazilian, | ||
| 357 | "language_index", | ||
| 358 | Category::System}; | ||
| 359 | SwitchableSetting<Region, true> region_index{linkage, Region::Usa, Region::Japan, | ||
| 360 | Region::Taiwan, "region_index", Category::System}; | ||
| 361 | SwitchableSetting<TimeZone, true> time_zone_index{linkage, TimeZone::Auto, | ||
| 362 | TimeZone::Auto, TimeZone::Zulu, | ||
| 363 | "time_zone_index", Category::System}; | ||
| 495 | // Measured in seconds since epoch | 364 | // Measured in seconds since epoch |
| 496 | std::optional<s64> custom_rtc; | 365 | SwitchableSetting<bool> custom_rtc_enabled{ |
| 366 | linkage, false, "custom_rtc_enabled", Category::System, Specialization::Paired, true, true}; | ||
| 367 | SwitchableSetting<s64> custom_rtc{ | ||
| 368 | linkage, 0, "custom_rtc", Category::System, Specialization::Time, | ||
| 369 | true, true, &custom_rtc_enabled}; | ||
| 497 | // Set on game boot, reset on stop. Seconds difference between current time and `custom_rtc` | 370 | // Set on game boot, reset on stop. Seconds difference between current time and `custom_rtc` |
| 498 | s64 custom_rtc_differential; | 371 | s64 custom_rtc_differential; |
| 372 | SwitchableSetting<bool> rng_seed_enabled{ | ||
| 373 | linkage, false, "rng_seed_enabled", Category::System, Specialization::Paired, true, true}; | ||
| 374 | SwitchableSetting<u32> rng_seed{ | ||
| 375 | linkage, 0, "rng_seed", Category::System, Specialization::Hex, | ||
| 376 | true, true, &rng_seed_enabled}; | ||
| 377 | Setting<std::string> device_name{ | ||
| 378 | linkage, "yuzu", "device_name", Category::System, Specialization::Default, true, true}; | ||
| 499 | 379 | ||
| 500 | Setting<s32> current_user{0, "current_user"}; | 380 | Setting<s32> current_user{linkage, 0, "current_user", Category::System}; |
| 501 | SwitchableSetting<s32, true> language_index{1, 0, 17, "language_index"}; | 381 | |
| 502 | SwitchableSetting<s32, true> region_index{1, 0, 6, "region_index"}; | 382 | SwitchableSetting<bool> use_docked_mode{linkage, true, "use_docked_mode", Category::System}; |
| 503 | SwitchableSetting<s32, true> time_zone_index{0, 0, 45, "time_zone_index"}; | ||
| 504 | SwitchableSetting<s32, true> sound_index{1, 0, 2, "sound_index"}; | ||
| 505 | 383 | ||
| 506 | // Controls | 384 | // Controls |
| 507 | InputSetting<std::array<PlayerInput, 10>> players; | 385 | InputSetting<std::array<PlayerInput, 10>> players; |
| 508 | 386 | ||
| 509 | SwitchableSetting<bool> use_docked_mode{true, "use_docked_mode"}; | 387 | Setting<bool> enable_raw_input{ |
| 510 | 388 | linkage, false, "enable_raw_input", Category::Controls, Specialization::Default, | |
| 511 | Setting<bool> enable_raw_input{false, "enable_raw_input"}; | 389 | // Only read/write enable_raw_input on Windows platforms |
| 512 | Setting<bool> controller_navigation{true, "controller_navigation"}; | 390 | #ifdef _WIN32 |
| 513 | Setting<bool> enable_joycon_driver{true, "enable_joycon_driver"}; | 391 | true |
| 514 | Setting<bool> enable_procon_driver{false, "enable_procon_driver"}; | 392 | #else |
| 515 | 393 | false | |
| 516 | SwitchableSetting<bool> vibration_enabled{true, "vibration_enabled"}; | 394 | #endif |
| 517 | SwitchableSetting<bool> enable_accurate_vibrations{false, "enable_accurate_vibrations"}; | 395 | }; |
| 518 | 396 | Setting<bool> controller_navigation{linkage, true, "controller_navigation", Category::Controls}; | |
| 519 | SwitchableSetting<bool> motion_enabled{true, "motion_enabled"}; | 397 | Setting<bool> enable_joycon_driver{linkage, true, "enable_joycon_driver", Category::Controls}; |
| 520 | Setting<std::string> udp_input_servers{"127.0.0.1:26760", "udp_input_servers"}; | 398 | Setting<bool> enable_procon_driver{linkage, false, "enable_procon_driver", Category::Controls}; |
| 521 | Setting<bool> enable_udp_controller{false, "enable_udp_controller"}; | 399 | |
| 522 | 400 | SwitchableSetting<bool> vibration_enabled{linkage, true, "vibration_enabled", | |
| 523 | Setting<bool> pause_tas_on_load{true, "pause_tas_on_load"}; | 401 | Category::Controls}; |
| 524 | Setting<bool> tas_enable{false, "tas_enable"}; | 402 | SwitchableSetting<bool> enable_accurate_vibrations{linkage, false, "enable_accurate_vibrations", |
| 525 | Setting<bool> tas_loop{false, "tas_loop"}; | 403 | Category::Controls}; |
| 526 | 404 | ||
| 527 | Setting<bool> mouse_panning{false, "mouse_panning"}; | 405 | SwitchableSetting<bool> motion_enabled{linkage, true, "motion_enabled", Category::Controls}; |
| 528 | Setting<u8, true> mouse_panning_x_sensitivity{50, 1, 100, "mouse_panning_x_sensitivity"}; | 406 | Setting<std::string> udp_input_servers{linkage, "127.0.0.1:26760", "udp_input_servers", |
| 529 | Setting<u8, true> mouse_panning_y_sensitivity{50, 1, 100, "mouse_panning_y_sensitivity"}; | 407 | Category::Controls}; |
| 530 | Setting<u8, true> mouse_panning_deadzone_counterweight{20, 0, 100, | 408 | Setting<bool> enable_udp_controller{linkage, false, "enable_udp_controller", |
| 531 | "mouse_panning_deadzone_counterweight"}; | 409 | Category::Controls}; |
| 532 | Setting<u8, true> mouse_panning_decay_strength{18, 0, 100, "mouse_panning_decay_strength"}; | 410 | |
| 533 | Setting<u8, true> mouse_panning_min_decay{6, 0, 100, "mouse_panning_min_decay"}; | 411 | Setting<bool> pause_tas_on_load{linkage, true, "pause_tas_on_load", Category::Controls}; |
| 534 | 412 | Setting<bool> tas_enable{linkage, false, "tas_enable", Category::Controls}; | |
| 535 | Setting<bool> mouse_enabled{false, "mouse_enabled"}; | 413 | Setting<bool> tas_loop{linkage, false, "tas_loop", Category::Controls}; |
| 536 | Setting<bool> emulate_analog_keyboard{false, "emulate_analog_keyboard"}; | 414 | |
| 537 | Setting<bool> keyboard_enabled{false, "keyboard_enabled"}; | 415 | Setting<bool> mouse_panning{ |
| 538 | 416 | linkage, false, "mouse_panning", Category::Controls, Specialization::Default, false}; | |
| 539 | Setting<bool> debug_pad_enabled{false, "debug_pad_enabled"}; | 417 | Setting<u8, true> mouse_panning_sensitivity{ |
| 418 | linkage, 50, 1, 100, "mouse_panning_sensitivity", Category::Controls}; | ||
| 419 | Setting<bool> mouse_enabled{linkage, false, "mouse_enabled", Category::Controls}; | ||
| 420 | |||
| 421 | Setting<u8, true> mouse_panning_x_sensitivity{ | ||
| 422 | linkage, 50, 1, 100, "mouse_panning_x_sensitivity", Category::Controls}; | ||
| 423 | Setting<u8, true> mouse_panning_y_sensitivity{ | ||
| 424 | linkage, 50, 1, 100, "mouse_panning_y_sensitivity", Category::Controls}; | ||
| 425 | Setting<u8, true> mouse_panning_deadzone_counterweight{ | ||
| 426 | linkage, 20, 0, 100, "mouse_panning_deadzone_counterweight", Category::Controls}; | ||
| 427 | Setting<u8, true> mouse_panning_decay_strength{ | ||
| 428 | linkage, 18, 0, 100, "mouse_panning_decay_strength", Category::Controls}; | ||
| 429 | Setting<u8, true> mouse_panning_min_decay{ | ||
| 430 | linkage, 6, 0, 100, "mouse_panning_min_decay", Category::Controls}; | ||
| 431 | |||
| 432 | Setting<bool> emulate_analog_keyboard{linkage, false, "emulate_analog_keyboard", | ||
| 433 | Category::Controls}; | ||
| 434 | Setting<bool> keyboard_enabled{linkage, false, "keyboard_enabled", Category::Controls}; | ||
| 435 | |||
| 436 | Setting<bool> debug_pad_enabled{linkage, false, "debug_pad_enabled", Category::Controls}; | ||
| 540 | ButtonsRaw debug_pad_buttons; | 437 | ButtonsRaw debug_pad_buttons; |
| 541 | AnalogsRaw debug_pad_analogs; | 438 | AnalogsRaw debug_pad_analogs; |
| 542 | 439 | ||
| 543 | TouchscreenInput touchscreen; | 440 | TouchscreenInput touchscreen; |
| 544 | 441 | ||
| 545 | Setting<std::string> touch_device{"min_x:100,min_y:50,max_x:1800,max_y:850", "touch_device"}; | 442 | Setting<std::string> touch_device{linkage, "min_x:100,min_y:50,max_x:1800,max_y:850", |
| 546 | Setting<int> touch_from_button_map_index{0, "touch_from_button_map"}; | 443 | "touch_device", Category::Controls}; |
| 444 | Setting<int> touch_from_button_map_index{linkage, 0, "touch_from_button_map", | ||
| 445 | Category::Controls}; | ||
| 547 | std::vector<TouchFromButtonMap> touch_from_button_maps; | 446 | std::vector<TouchFromButtonMap> touch_from_button_maps; |
| 548 | 447 | ||
| 549 | Setting<bool> enable_ring_controller{true, "enable_ring_controller"}; | 448 | Setting<bool> enable_ring_controller{linkage, true, "enable_ring_controller", |
| 449 | Category::Controls}; | ||
| 550 | RingconRaw ringcon_analogs; | 450 | RingconRaw ringcon_analogs; |
| 551 | 451 | ||
| 552 | Setting<bool> enable_ir_sensor{false, "enable_ir_sensor"}; | 452 | Setting<bool> enable_ir_sensor{linkage, false, "enable_ir_sensor", Category::Controls}; |
| 553 | Setting<std::string> ir_sensor_device{"auto", "ir_sensor_device"}; | 453 | Setting<std::string> ir_sensor_device{linkage, "auto", "ir_sensor_device", Category::Controls}; |
| 554 | 454 | ||
| 555 | Setting<bool> random_amiibo_id{false, "random_amiibo_id"}; | 455 | Setting<bool> random_amiibo_id{linkage, false, "random_amiibo_id", Category::Controls}; |
| 556 | 456 | ||
| 557 | // Data Storage | 457 | // Data Storage |
| 558 | Setting<bool> use_virtual_sd{true, "use_virtual_sd"}; | 458 | Setting<bool> use_virtual_sd{linkage, true, "use_virtual_sd", Category::DataStorage}; |
| 559 | Setting<bool> gamecard_inserted{false, "gamecard_inserted"}; | 459 | Setting<bool> gamecard_inserted{linkage, false, "gamecard_inserted", Category::DataStorage}; |
| 560 | Setting<bool> gamecard_current_game{false, "gamecard_current_game"}; | 460 | Setting<bool> gamecard_current_game{linkage, false, "gamecard_current_game", |
| 561 | Setting<std::string> gamecard_path{std::string(), "gamecard_path"}; | 461 | Category::DataStorage}; |
| 462 | Setting<std::string> gamecard_path{linkage, std::string(), "gamecard_path", | ||
| 463 | Category::DataStorage}; | ||
| 562 | 464 | ||
| 563 | // Debugging | 465 | // Debugging |
| 564 | bool record_frame_times; | 466 | bool record_frame_times; |
| 565 | Setting<bool> use_gdbstub{false, "use_gdbstub"}; | 467 | Setting<bool> use_gdbstub{linkage, false, "use_gdbstub", Category::Debugging}; |
| 566 | Setting<u16> gdbstub_port{6543, "gdbstub_port"}; | 468 | Setting<u16> gdbstub_port{linkage, 6543, "gdbstub_port", Category::Debugging}; |
| 567 | Setting<std::string> program_args{std::string(), "program_args"}; | 469 | Setting<std::string> program_args{linkage, std::string(), "program_args", Category::Debugging}; |
| 568 | Setting<bool> dump_exefs{false, "dump_exefs"}; | 470 | Setting<bool> dump_exefs{linkage, false, "dump_exefs", Category::Debugging}; |
| 569 | Setting<bool> dump_nso{false, "dump_nso"}; | 471 | Setting<bool> dump_nso{linkage, false, "dump_nso", Category::Debugging}; |
| 570 | Setting<bool> dump_shaders{false, "dump_shaders"}; | 472 | Setting<bool> dump_shaders{ |
| 571 | Setting<bool> dump_macros{false, "dump_macros"}; | 473 | linkage, false, "dump_shaders", Category::DebuggingGraphics, Specialization::Default, |
| 572 | Setting<bool> enable_fs_access_log{false, "enable_fs_access_log"}; | 474 | false}; |
| 573 | Setting<bool> reporting_services{false, "reporting_services"}; | 475 | Setting<bool> dump_macros{ |
| 574 | Setting<bool> quest_flag{false, "quest_flag"}; | 476 | linkage, false, "dump_macros", Category::DebuggingGraphics, Specialization::Default, false}; |
| 575 | Setting<bool> disable_macro_jit{false, "disable_macro_jit"}; | 477 | Setting<bool> enable_fs_access_log{linkage, false, "enable_fs_access_log", Category::Debugging}; |
| 576 | Setting<bool> disable_macro_hle{false, "disable_macro_hle"}; | 478 | Setting<bool> reporting_services{ |
| 577 | Setting<bool> extended_logging{false, "extended_logging"}; | 479 | linkage, false, "reporting_services", Category::Debugging, Specialization::Default, false}; |
| 578 | Setting<bool> use_debug_asserts{false, "use_debug_asserts"}; | 480 | Setting<bool> quest_flag{linkage, false, "quest_flag", Category::Debugging}; |
| 579 | Setting<bool> use_auto_stub{false, "use_auto_stub"}; | 481 | Setting<bool> disable_macro_jit{linkage, false, "disable_macro_jit", |
| 580 | Setting<bool> enable_all_controllers{false, "enable_all_controllers"}; | 482 | Category::DebuggingGraphics}; |
| 581 | Setting<bool> create_crash_dumps{false, "create_crash_dumps"}; | 483 | Setting<bool> disable_macro_hle{linkage, false, "disable_macro_hle", |
| 582 | Setting<bool> perform_vulkan_check{true, "perform_vulkan_check"}; | 484 | Category::DebuggingGraphics}; |
| 485 | Setting<bool> extended_logging{ | ||
| 486 | linkage, false, "extended_logging", Category::Debugging, Specialization::Default, false}; | ||
| 487 | Setting<bool> use_debug_asserts{linkage, false, "use_debug_asserts", Category::Debugging}; | ||
| 488 | Setting<bool> use_auto_stub{ | ||
| 489 | linkage, false, "use_auto_stub", Category::Debugging, Specialization::Default, false}; | ||
| 490 | Setting<bool> enable_all_controllers{linkage, false, "enable_all_controllers", | ||
| 491 | Category::Debugging}; | ||
| 492 | Setting<bool> create_crash_dumps{linkage, false, "create_crash_dumps", Category::Debugging}; | ||
| 493 | Setting<bool> perform_vulkan_check{linkage, true, "perform_vulkan_check", Category::Debugging}; | ||
| 583 | 494 | ||
| 584 | // Miscellaneous | 495 | // Miscellaneous |
| 585 | Setting<std::string> log_filter{"*:Info", "log_filter"}; | 496 | Setting<std::string> log_filter{linkage, "*:Info", "log_filter", Category::Miscellaneous}; |
| 586 | Setting<bool> use_dev_keys{false, "use_dev_keys"}; | 497 | Setting<bool> use_dev_keys{linkage, false, "use_dev_keys", Category::Miscellaneous}; |
| 587 | 498 | ||
| 588 | // Network | 499 | // Network |
| 589 | Setting<std::string> network_interface{std::string(), "network_interface"}; | 500 | Setting<std::string> network_interface{linkage, std::string(), "network_interface", |
| 501 | Category::Network}; | ||
| 590 | 502 | ||
| 591 | // WebService | 503 | // WebService |
| 592 | Setting<bool> enable_telemetry{true, "enable_telemetry"}; | 504 | Setting<bool> enable_telemetry{linkage, true, "enable_telemetry", Category::WebService}; |
| 593 | Setting<std::string> web_api_url{"https://api.yuzu-emu.org", "web_api_url"}; | 505 | Setting<std::string> web_api_url{linkage, "https://api.yuzu-emu.org", "web_api_url", |
| 594 | Setting<std::string> yuzu_username{std::string(), "yuzu_username"}; | 506 | Category::WebService}; |
| 595 | Setting<std::string> yuzu_token{std::string(), "yuzu_token"}; | 507 | Setting<std::string> yuzu_username{linkage, std::string(), "yuzu_username", |
| 508 | Category::WebService}; | ||
| 509 | Setting<std::string> yuzu_token{linkage, std::string(), "yuzu_token", Category::WebService}; | ||
| 596 | 510 | ||
| 597 | // Add-Ons | 511 | // Add-Ons |
| 598 | std::map<u64, std::vector<std::string>> disabled_addons; | 512 | std::map<u64, std::vector<std::string>> disabled_addons; |
| @@ -600,9 +514,6 @@ struct Values { | |||
| 600 | 514 | ||
| 601 | extern Values values; | 515 | extern Values values; |
| 602 | 516 | ||
| 603 | bool IsConfiguringGlobal(); | ||
| 604 | void SetConfiguringGlobal(bool is_global); | ||
| 605 | |||
| 606 | bool IsGPULevelExtreme(); | 517 | bool IsGPULevelExtreme(); |
| 607 | bool IsGPULevelHigh(); | 518 | bool IsGPULevelHigh(); |
| 608 | 519 | ||
| @@ -610,7 +521,7 @@ bool IsFastmemEnabled(); | |||
| 610 | 521 | ||
| 611 | float Volume(); | 522 | float Volume(); |
| 612 | 523 | ||
| 613 | std::string GetTimeZoneString(); | 524 | std::string GetTimeZoneString(TimeZone time_zone); |
| 614 | 525 | ||
| 615 | void LogSettings(); | 526 | void LogSettings(); |
| 616 | 527 | ||
| @@ -619,4 +530,7 @@ void UpdateRescalingInfo(); | |||
| 619 | // Restore the global state of all applicable settings in the Values struct | 530 | // Restore the global state of all applicable settings in the Values struct |
| 620 | void RestoreGlobalState(bool is_powered_on); | 531 | void RestoreGlobalState(bool is_powered_on); |
| 621 | 532 | ||
| 533 | bool IsConfiguringGlobal(); | ||
| 534 | void SetConfiguringGlobal(bool is_global); | ||
| 535 | |||
| 622 | } // namespace Settings | 536 | } // namespace Settings |
diff --git a/src/common/settings_common.cpp b/src/common/settings_common.cpp new file mode 100644 index 000000000..dedf5ef90 --- /dev/null +++ b/src/common/settings_common.cpp | |||
| @@ -0,0 +1,58 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include <string> | ||
| 5 | #include "common/settings_common.h" | ||
| 6 | |||
| 7 | namespace Settings { | ||
| 8 | |||
| 9 | BasicSetting::BasicSetting(Linkage& linkage, const std::string& name, enum Category category_, | ||
| 10 | bool save_, bool runtime_modifiable_, u32 specialization_, | ||
| 11 | BasicSetting* other_setting_) | ||
| 12 | : label{name}, category{category_}, id{linkage.count}, save{save_}, | ||
| 13 | runtime_modifiable{runtime_modifiable_}, specialization{specialization_}, | ||
| 14 | other_setting{other_setting_} { | ||
| 15 | linkage.by_category[category].push_back(this); | ||
| 16 | linkage.count++; | ||
| 17 | } | ||
| 18 | |||
| 19 | BasicSetting::~BasicSetting() = default; | ||
| 20 | |||
| 21 | std::string BasicSetting::ToStringGlobal() const { | ||
| 22 | return this->ToString(); | ||
| 23 | } | ||
| 24 | |||
| 25 | bool BasicSetting::UsingGlobal() const { | ||
| 26 | return true; | ||
| 27 | } | ||
| 28 | |||
| 29 | void BasicSetting::SetGlobal(bool global) {} | ||
| 30 | |||
| 31 | bool BasicSetting::Save() const { | ||
| 32 | return save; | ||
| 33 | } | ||
| 34 | |||
| 35 | bool BasicSetting::RuntimeModfiable() const { | ||
| 36 | return runtime_modifiable; | ||
| 37 | } | ||
| 38 | |||
| 39 | Category BasicSetting::GetCategory() const { | ||
| 40 | return category; | ||
| 41 | } | ||
| 42 | |||
| 43 | u32 BasicSetting::Specialization() const { | ||
| 44 | return specialization; | ||
| 45 | } | ||
| 46 | |||
| 47 | BasicSetting* BasicSetting::PairedSetting() const { | ||
| 48 | return other_setting; | ||
| 49 | } | ||
| 50 | |||
| 51 | const std::string& BasicSetting::GetLabel() const { | ||
| 52 | return label; | ||
| 53 | } | ||
| 54 | |||
| 55 | Linkage::Linkage(u32 initial_count) : count{initial_count} {} | ||
| 56 | Linkage::~Linkage() = default; | ||
| 57 | |||
| 58 | } // namespace Settings | ||
diff --git a/src/common/settings_common.h b/src/common/settings_common.h new file mode 100644 index 000000000..2efb329b0 --- /dev/null +++ b/src/common/settings_common.h | |||
| @@ -0,0 +1,256 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <functional> | ||
| 7 | #include <map> | ||
| 8 | #include <string> | ||
| 9 | #include <typeindex> | ||
| 10 | #include "common/common_types.h" | ||
| 11 | |||
| 12 | namespace Settings { | ||
| 13 | |||
| 14 | enum class Category : u32 { | ||
| 15 | Audio, | ||
| 16 | Core, | ||
| 17 | Cpu, | ||
| 18 | CpuDebug, | ||
| 19 | CpuUnsafe, | ||
| 20 | Renderer, | ||
| 21 | RendererAdvanced, | ||
| 22 | RendererDebug, | ||
| 23 | System, | ||
| 24 | SystemAudio, | ||
| 25 | DataStorage, | ||
| 26 | Debugging, | ||
| 27 | DebuggingGraphics, | ||
| 28 | Miscellaneous, | ||
| 29 | Network, | ||
| 30 | WebService, | ||
| 31 | AddOns, | ||
| 32 | Controls, | ||
| 33 | Ui, | ||
| 34 | UiGeneral, | ||
| 35 | UiLayout, | ||
| 36 | UiGameList, | ||
| 37 | Screenshots, | ||
| 38 | Shortcuts, | ||
| 39 | Multiplayer, | ||
| 40 | Services, | ||
| 41 | Paths, | ||
| 42 | MaxEnum, | ||
| 43 | }; | ||
| 44 | |||
| 45 | constexpr u8 SpecializationTypeMask = 0xf; | ||
| 46 | constexpr u8 SpecializationAttributeMask = 0xf0; | ||
| 47 | constexpr u8 SpecializationAttributeOffset = 4; | ||
| 48 | |||
| 49 | // Scalar and countable could have better names | ||
| 50 | enum Specialization : u8 { | ||
| 51 | Default = 0, | ||
| 52 | Time = 1, // Duration or specific moment in time | ||
| 53 | Hex = 2, // Hexadecimal number | ||
| 54 | List = 3, // Setting has specific members | ||
| 55 | RuntimeList = 4, // Members of the list are determined during runtime | ||
| 56 | Scalar = 5, // Values are continuous | ||
| 57 | Countable = 6, // Can be stepped through | ||
| 58 | Paired = 7, // Another setting is associated with this setting | ||
| 59 | |||
| 60 | Percentage = (1 << SpecializationAttributeOffset), // Should be represented as a percentage | ||
| 61 | }; | ||
| 62 | |||
| 63 | class BasicSetting; | ||
| 64 | |||
| 65 | class Linkage { | ||
| 66 | public: | ||
| 67 | explicit Linkage(u32 initial_count = 0); | ||
| 68 | ~Linkage(); | ||
| 69 | std::map<Category, std::vector<BasicSetting*>> by_category{}; | ||
| 70 | std::vector<std::function<void()>> restore_functions{}; | ||
| 71 | u32 count; | ||
| 72 | }; | ||
| 73 | |||
| 74 | /** | ||
| 75 | * BasicSetting is an abstract class that only keeps track of metadata. The string methods are | ||
| 76 | * available to get data values out. | ||
| 77 | */ | ||
| 78 | class BasicSetting { | ||
| 79 | protected: | ||
| 80 | explicit BasicSetting(Linkage& linkage, const std::string& name, Category category_, bool save_, | ||
| 81 | bool runtime_modifiable_, u32 specialization, | ||
| 82 | BasicSetting* other_setting); | ||
| 83 | |||
| 84 | public: | ||
| 85 | virtual ~BasicSetting(); | ||
| 86 | |||
| 87 | /* | ||
| 88 | * Data retrieval | ||
| 89 | */ | ||
| 90 | |||
| 91 | /** | ||
| 92 | * Returns a string representation of the internal data. If the Setting is Switchable, it | ||
| 93 | * respects the internal global state: it is based on GetValue(). | ||
| 94 | * | ||
| 95 | * @returns A string representation of the internal data. | ||
| 96 | */ | ||
| 97 | [[nodiscard]] virtual std::string ToString() const = 0; | ||
| 98 | |||
| 99 | /** | ||
| 100 | * Returns a string representation of the global version of internal data. If the Setting is | ||
| 101 | * not Switchable, it behaves like ToString. | ||
| 102 | * | ||
| 103 | * @returns A string representation of the global version of internal data. | ||
| 104 | */ | ||
| 105 | [[nodiscard]] virtual std::string ToStringGlobal() const; | ||
| 106 | |||
| 107 | /** | ||
| 108 | * @returns A string representation of the Setting's default value. | ||
| 109 | */ | ||
| 110 | [[nodiscard]] virtual std::string DefaultToString() const = 0; | ||
| 111 | |||
| 112 | /** | ||
| 113 | * Returns a string representation of the minimum value of the setting. If the Setting is not | ||
| 114 | * ranged, the string represents the default initialization of the data type. | ||
| 115 | * | ||
| 116 | * @returns A string representation of the minimum value of the setting. | ||
| 117 | */ | ||
| 118 | [[nodiscard]] virtual std::string MinVal() const = 0; | ||
| 119 | |||
| 120 | /** | ||
| 121 | * Returns a string representation of the maximum value of the setting. If the Setting is not | ||
| 122 | * ranged, the string represents the default initialization of the data type. | ||
| 123 | * | ||
| 124 | * @returns A string representation of the maximum value of the setting. | ||
| 125 | */ | ||
| 126 | [[nodiscard]] virtual std::string MaxVal() const = 0; | ||
| 127 | |||
| 128 | /** | ||
| 129 | * Takes a string input, converts it to the internal data type if necessary, and then runs | ||
| 130 | * SetValue with it. | ||
| 131 | * | ||
| 132 | * @param load String of the input data. | ||
| 133 | */ | ||
| 134 | virtual void LoadString(const std::string& load) = 0; | ||
| 135 | |||
| 136 | /** | ||
| 137 | * Returns a string representation of the data. If the data is an enum, it returns a string of | ||
| 138 | * the enum value. If the internal data type is not an enum, this is equivalent to ToString. | ||
| 139 | * | ||
| 140 | * e.g. renderer_backend.Canonicalize() == "OpenGL" | ||
| 141 | * | ||
| 142 | * @returns Canonicalized string representation of the internal data | ||
| 143 | */ | ||
| 144 | [[nodiscard]] virtual std::string Canonicalize() const = 0; | ||
| 145 | |||
| 146 | /* | ||
| 147 | * Metadata | ||
| 148 | */ | ||
| 149 | |||
| 150 | /** | ||
| 151 | * @returns A unique identifier for the Setting's internal data type. | ||
| 152 | */ | ||
| 153 | [[nodiscard]] virtual std::type_index TypeId() const = 0; | ||
| 154 | |||
| 155 | /** | ||
| 156 | * Returns true if the Setting's internal data type is an enum. | ||
| 157 | * | ||
| 158 | * @returns True if the Setting's internal data type is an enum | ||
| 159 | */ | ||
| 160 | [[nodiscard]] virtual constexpr bool IsEnum() const = 0; | ||
| 161 | |||
| 162 | /** | ||
| 163 | * Returns true if the current setting is Switchable. | ||
| 164 | * | ||
| 165 | * @returns If the setting is a SwitchableSetting | ||
| 166 | */ | ||
| 167 | [[nodiscard]] virtual constexpr bool Switchable() const { | ||
| 168 | return false; | ||
| 169 | } | ||
| 170 | |||
| 171 | /** | ||
| 172 | * Returns true to suggest that a frontend can read or write the setting to a configuration | ||
| 173 | * file. | ||
| 174 | * | ||
| 175 | * @returns The save preference | ||
| 176 | */ | ||
| 177 | [[nodiscard]] bool Save() const; | ||
| 178 | |||
| 179 | /** | ||
| 180 | * @returns true if the current setting can be changed while the guest is running. | ||
| 181 | */ | ||
| 182 | [[nodiscard]] bool RuntimeModfiable() const; | ||
| 183 | |||
| 184 | /** | ||
| 185 | * @returns A unique number corresponding to the setting. | ||
| 186 | */ | ||
| 187 | [[nodiscard]] constexpr u32 Id() const { | ||
| 188 | return id; | ||
| 189 | } | ||
| 190 | |||
| 191 | /** | ||
| 192 | * Returns the setting's category AKA INI group. | ||
| 193 | * | ||
| 194 | * @returns The setting's category | ||
| 195 | */ | ||
| 196 | [[nodiscard]] Category GetCategory() const; | ||
| 197 | |||
| 198 | /** | ||
| 199 | * @returns Extra metadata for data representation in frontend implementations. | ||
| 200 | */ | ||
| 201 | [[nodiscard]] u32 Specialization() const; | ||
| 202 | |||
| 203 | /** | ||
| 204 | * @returns Another BasicSetting if one is paired, or nullptr otherwise. | ||
| 205 | */ | ||
| 206 | [[nodiscard]] BasicSetting* PairedSetting() const; | ||
| 207 | |||
| 208 | /** | ||
| 209 | * Returns the label this setting was created with. | ||
| 210 | * | ||
| 211 | * @returns A reference to the label | ||
| 212 | */ | ||
| 213 | [[nodiscard]] const std::string& GetLabel() const; | ||
| 214 | |||
| 215 | /** | ||
| 216 | * @returns If the Setting checks input values for valid ranges. | ||
| 217 | */ | ||
| 218 | [[nodiscard]] virtual constexpr bool Ranged() const = 0; | ||
| 219 | |||
| 220 | /** | ||
| 221 | * @returns The index of the enum if the underlying setting type is an enum, else max of u32. | ||
| 222 | */ | ||
| 223 | [[nodiscard]] virtual constexpr u32 EnumIndex() const = 0; | ||
| 224 | |||
| 225 | /* | ||
| 226 | * Switchable settings | ||
| 227 | */ | ||
| 228 | |||
| 229 | /** | ||
| 230 | * Sets a setting's global state. True means use the normal setting, false to use a custom | ||
| 231 | * value. Has no effect if the Setting is not Switchable. | ||
| 232 | * | ||
| 233 | * @param global The desired state | ||
| 234 | */ | ||
| 235 | virtual void SetGlobal(bool global); | ||
| 236 | |||
| 237 | /** | ||
| 238 | * Returns true if the setting is using the normal setting value. Always true if the setting is | ||
| 239 | * not Switchable. | ||
| 240 | * | ||
| 241 | * @returns The Setting's global state | ||
| 242 | */ | ||
| 243 | [[nodiscard]] virtual bool UsingGlobal() const; | ||
| 244 | |||
| 245 | private: | ||
| 246 | const std::string label; ///< The setting's label | ||
| 247 | const Category category; ///< The setting's category AKA INI group | ||
| 248 | const u32 id; ///< Unique integer for the setting | ||
| 249 | const bool save; ///< Suggests if the setting should be saved and read to a frontend config | ||
| 250 | const bool | ||
| 251 | runtime_modifiable; ///< Suggests if the setting can be modified while a guest is running | ||
| 252 | const u32 specialization; ///< Extra data to identify representation of a setting | ||
| 253 | BasicSetting* const other_setting; ///< A paired setting | ||
| 254 | }; | ||
| 255 | |||
| 256 | } // namespace Settings | ||
diff --git a/src/common/settings_enums.h b/src/common/settings_enums.h new file mode 100644 index 000000000..a1a29ebf6 --- /dev/null +++ b/src/common/settings_enums.h | |||
| @@ -0,0 +1,214 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <string> | ||
| 7 | #include <utility> | ||
| 8 | #include <vector> | ||
| 9 | #include "common/common_types.h" | ||
| 10 | |||
| 11 | namespace Settings { | ||
| 12 | |||
| 13 | template <typename T> | ||
| 14 | struct EnumMetadata { | ||
| 15 | static constexpr std::vector<std::pair<std::string, T>> Canonicalizations(); | ||
| 16 | static constexpr u32 Index(); | ||
| 17 | }; | ||
| 18 | |||
| 19 | #define PAIR_45(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_46(N, __VA_ARGS__)) | ||
| 20 | #define PAIR_44(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_45(N, __VA_ARGS__)) | ||
| 21 | #define PAIR_43(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_44(N, __VA_ARGS__)) | ||
| 22 | #define PAIR_42(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_43(N, __VA_ARGS__)) | ||
| 23 | #define PAIR_41(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_42(N, __VA_ARGS__)) | ||
| 24 | #define PAIR_40(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_41(N, __VA_ARGS__)) | ||
| 25 | #define PAIR_39(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_40(N, __VA_ARGS__)) | ||
| 26 | #define PAIR_38(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_39(N, __VA_ARGS__)) | ||
| 27 | #define PAIR_37(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_38(N, __VA_ARGS__)) | ||
| 28 | #define PAIR_36(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_37(N, __VA_ARGS__)) | ||
| 29 | #define PAIR_35(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_36(N, __VA_ARGS__)) | ||
| 30 | #define PAIR_34(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_35(N, __VA_ARGS__)) | ||
| 31 | #define PAIR_33(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_34(N, __VA_ARGS__)) | ||
| 32 | #define PAIR_32(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_33(N, __VA_ARGS__)) | ||
| 33 | #define PAIR_31(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_32(N, __VA_ARGS__)) | ||
| 34 | #define PAIR_30(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_31(N, __VA_ARGS__)) | ||
| 35 | #define PAIR_29(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_30(N, __VA_ARGS__)) | ||
| 36 | #define PAIR_28(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_29(N, __VA_ARGS__)) | ||
| 37 | #define PAIR_27(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_28(N, __VA_ARGS__)) | ||
| 38 | #define PAIR_26(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_27(N, __VA_ARGS__)) | ||
| 39 | #define PAIR_25(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_26(N, __VA_ARGS__)) | ||
| 40 | #define PAIR_24(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_25(N, __VA_ARGS__)) | ||
| 41 | #define PAIR_23(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_24(N, __VA_ARGS__)) | ||
| 42 | #define PAIR_22(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_23(N, __VA_ARGS__)) | ||
| 43 | #define PAIR_21(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_22(N, __VA_ARGS__)) | ||
| 44 | #define PAIR_20(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_21(N, __VA_ARGS__)) | ||
| 45 | #define PAIR_19(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_20(N, __VA_ARGS__)) | ||
| 46 | #define PAIR_18(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_19(N, __VA_ARGS__)) | ||
| 47 | #define PAIR_17(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_18(N, __VA_ARGS__)) | ||
| 48 | #define PAIR_16(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_17(N, __VA_ARGS__)) | ||
| 49 | #define PAIR_15(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_16(N, __VA_ARGS__)) | ||
| 50 | #define PAIR_14(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_15(N, __VA_ARGS__)) | ||
| 51 | #define PAIR_13(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_14(N, __VA_ARGS__)) | ||
| 52 | #define PAIR_12(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_13(N, __VA_ARGS__)) | ||
| 53 | #define PAIR_11(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_12(N, __VA_ARGS__)) | ||
| 54 | #define PAIR_10(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_11(N, __VA_ARGS__)) | ||
| 55 | #define PAIR_9(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_10(N, __VA_ARGS__)) | ||
| 56 | #define PAIR_8(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_9(N, __VA_ARGS__)) | ||
| 57 | #define PAIR_7(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_8(N, __VA_ARGS__)) | ||
| 58 | #define PAIR_6(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_7(N, __VA_ARGS__)) | ||
| 59 | #define PAIR_5(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_6(N, __VA_ARGS__)) | ||
| 60 | #define PAIR_4(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_5(N, __VA_ARGS__)) | ||
| 61 | #define PAIR_3(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_4(N, __VA_ARGS__)) | ||
| 62 | #define PAIR_2(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_3(N, __VA_ARGS__)) | ||
| 63 | #define PAIR_1(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_2(N, __VA_ARGS__)) | ||
| 64 | #define PAIR(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_1(N, __VA_ARGS__)) | ||
| 65 | |||
| 66 | #define ENUM(NAME, ...) \ | ||
| 67 | enum class NAME : u32 { __VA_ARGS__ }; \ | ||
| 68 | template <> \ | ||
| 69 | constexpr std::vector<std::pair<std::string, NAME>> EnumMetadata<NAME>::Canonicalizations() { \ | ||
| 70 | return {PAIR(NAME, __VA_ARGS__)}; \ | ||
| 71 | } \ | ||
| 72 | template <> \ | ||
| 73 | constexpr u32 EnumMetadata<NAME>::Index() { \ | ||
| 74 | return __COUNTER__; \ | ||
| 75 | } | ||
| 76 | |||
| 77 | // AudioEngine must be specified discretely due to having existing but slightly different | ||
| 78 | // canonicalizations | ||
| 79 | // TODO (lat9nq): Remove explicit definition of AudioEngine/sink_id | ||
| 80 | enum class AudioEngine : u32 { | ||
| 81 | Auto, | ||
| 82 | Cubeb, | ||
| 83 | Sdl2, | ||
| 84 | Null, | ||
| 85 | }; | ||
| 86 | |||
| 87 | template <> | ||
| 88 | constexpr std::vector<std::pair<std::string, AudioEngine>> | ||
| 89 | EnumMetadata<AudioEngine>::Canonicalizations() { | ||
| 90 | return { | ||
| 91 | {"auto", AudioEngine::Auto}, | ||
| 92 | {"cubeb", AudioEngine::Cubeb}, | ||
| 93 | {"sdl2", AudioEngine::Sdl2}, | ||
| 94 | {"null", AudioEngine::Null}, | ||
| 95 | }; | ||
| 96 | } | ||
| 97 | |||
| 98 | template <> | ||
| 99 | constexpr u32 EnumMetadata<AudioEngine>::Index() { | ||
| 100 | // This is just a sufficiently large number that is more than the number of other enums declared | ||
| 101 | // here | ||
| 102 | return 100; | ||
| 103 | } | ||
| 104 | |||
| 105 | ENUM(AudioMode, Mono, Stereo, Surround); | ||
| 106 | |||
| 107 | ENUM(Language, Japanese, EnglishAmerican, French, German, Italian, Spanish, Chinese, Korean, Dutch, | ||
| 108 | Portuguese, Russian, Taiwanese, EnglishBritish, FrenchCanadian, SpanishLatin, | ||
| 109 | ChineseSimplified, ChineseTraditional, PortugueseBrazilian); | ||
| 110 | |||
| 111 | ENUM(Region, Japan, Usa, Europe, Australia, China, Korea, Taiwan); | ||
| 112 | |||
| 113 | ENUM(TimeZone, Auto, Default, Cet, Cst6Cdt, Cuba, Eet, Egypt, Eire, Est, Est5Edt, Gb, GbEire, Gmt, | ||
| 114 | GmtPlusZero, GmtMinusZero, GmtZero, Greenwich, Hongkong, Hst, Iceland, Iran, Israel, Jamaica, | ||
| 115 | Japan, Kwajalein, Libya, Met, Mst, Mst7Mdt, Navajo, Nz, NzChat, Poland, Portugal, Prc, Pst8Pdt, | ||
| 116 | Roc, Rok, Singapore, Turkey, Uct, Universal, Utc, WSu, Wet, Zulu); | ||
| 117 | |||
| 118 | ENUM(AnisotropyMode, Automatic, Default, X2, X4, X8, X16); | ||
| 119 | |||
| 120 | ENUM(AstcDecodeMode, Cpu, Gpu, CpuAsynchronous); | ||
| 121 | |||
| 122 | ENUM(AstcRecompression, Uncompressed, Bc1, Bc3); | ||
| 123 | |||
| 124 | ENUM(VSyncMode, Immediate, Mailbox, Fifo, FifoRelaxed); | ||
| 125 | |||
| 126 | ENUM(RendererBackend, OpenGL, Vulkan, Null); | ||
| 127 | |||
| 128 | ENUM(ShaderBackend, Glsl, Glasm, SpirV); | ||
| 129 | |||
| 130 | ENUM(GpuAccuracy, Normal, High, Extreme); | ||
| 131 | |||
| 132 | ENUM(CpuAccuracy, Auto, Accurate, Unsafe, Paranoid); | ||
| 133 | |||
| 134 | ENUM(MemoryLayout, Memory_4Gb, Memory_6Gb, Memory_8Gb); | ||
| 135 | |||
| 136 | ENUM(FullscreenMode, Borderless, Exclusive); | ||
| 137 | |||
| 138 | ENUM(NvdecEmulation, Off, Cpu, Gpu); | ||
| 139 | |||
| 140 | ENUM(ResolutionSetup, Res1_2X, Res3_4X, Res1X, Res3_2X, Res2X, Res3X, Res4X, Res5X, Res6X, Res7X, | ||
| 141 | Res8X); | ||
| 142 | |||
| 143 | ENUM(ScalingFilter, NearestNeighbor, Bilinear, Bicubic, Gaussian, ScaleForce, Fsr, MaxEnum); | ||
| 144 | |||
| 145 | ENUM(AntiAliasing, None, Fxaa, Smaa, MaxEnum); | ||
| 146 | |||
| 147 | ENUM(AspectRatio, R16_9, R4_3, R21_9, R16_10, Stretch); | ||
| 148 | |||
| 149 | template <typename Type> | ||
| 150 | constexpr std::string CanonicalizeEnum(Type id) { | ||
| 151 | const auto group = EnumMetadata<Type>::Canonicalizations(); | ||
| 152 | for (auto& [name, value] : group) { | ||
| 153 | if (value == id) { | ||
| 154 | return name; | ||
| 155 | } | ||
| 156 | } | ||
| 157 | return "unknown"; | ||
| 158 | } | ||
| 159 | |||
| 160 | template <typename Type> | ||
| 161 | constexpr Type ToEnum(const std::string& canonicalization) { | ||
| 162 | const auto group = EnumMetadata<Type>::Canonicalizations(); | ||
| 163 | for (auto& [name, value] : group) { | ||
| 164 | if (name == canonicalization) { | ||
| 165 | return value; | ||
| 166 | } | ||
| 167 | } | ||
| 168 | return {}; | ||
| 169 | } | ||
| 170 | } // namespace Settings | ||
| 171 | |||
| 172 | #undef ENUM | ||
| 173 | #undef PAIR | ||
| 174 | #undef PAIR_1 | ||
| 175 | #undef PAIR_2 | ||
| 176 | #undef PAIR_3 | ||
| 177 | #undef PAIR_4 | ||
| 178 | #undef PAIR_5 | ||
| 179 | #undef PAIR_6 | ||
| 180 | #undef PAIR_7 | ||
| 181 | #undef PAIR_8 | ||
| 182 | #undef PAIR_9 | ||
| 183 | #undef PAIR_10 | ||
| 184 | #undef PAIR_12 | ||
| 185 | #undef PAIR_13 | ||
| 186 | #undef PAIR_14 | ||
| 187 | #undef PAIR_15 | ||
| 188 | #undef PAIR_16 | ||
| 189 | #undef PAIR_17 | ||
| 190 | #undef PAIR_18 | ||
| 191 | #undef PAIR_19 | ||
| 192 | #undef PAIR_20 | ||
| 193 | #undef PAIR_22 | ||
| 194 | #undef PAIR_23 | ||
| 195 | #undef PAIR_24 | ||
| 196 | #undef PAIR_25 | ||
| 197 | #undef PAIR_26 | ||
| 198 | #undef PAIR_27 | ||
| 199 | #undef PAIR_28 | ||
| 200 | #undef PAIR_29 | ||
| 201 | #undef PAIR_30 | ||
| 202 | #undef PAIR_32 | ||
| 203 | #undef PAIR_33 | ||
| 204 | #undef PAIR_34 | ||
| 205 | #undef PAIR_35 | ||
| 206 | #undef PAIR_36 | ||
| 207 | #undef PAIR_37 | ||
| 208 | #undef PAIR_38 | ||
| 209 | #undef PAIR_39 | ||
| 210 | #undef PAIR_40 | ||
| 211 | #undef PAIR_42 | ||
| 212 | #undef PAIR_43 | ||
| 213 | #undef PAIR_44 | ||
| 214 | #undef PAIR_45 | ||
diff --git a/src/common/settings_setting.h b/src/common/settings_setting.h new file mode 100644 index 000000000..a8beb06e9 --- /dev/null +++ b/src/common/settings_setting.h | |||
| @@ -0,0 +1,394 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <limits> | ||
| 7 | #include <map> | ||
| 8 | #include <optional> | ||
| 9 | #include <stdexcept> | ||
| 10 | #include <string> | ||
| 11 | #include <typeindex> | ||
| 12 | #include <typeinfo> | ||
| 13 | #include "common/common_types.h" | ||
| 14 | #include "common/settings_common.h" | ||
| 15 | #include "common/settings_enums.h" | ||
| 16 | |||
| 17 | namespace Settings { | ||
| 18 | |||
| 19 | /** The Setting class is a simple resource manager. It defines a label and default value | ||
| 20 | * alongside the actual value of the setting for simpler and less-error prone use with frontend | ||
| 21 | * configurations. Specifying a default value and label is required. A minimum and maximum range | ||
| 22 | * can be specified for sanitization. | ||
| 23 | */ | ||
| 24 | template <typename Type, bool ranged = false> | ||
| 25 | class Setting : public BasicSetting { | ||
| 26 | protected: | ||
| 27 | Setting() = default; | ||
| 28 | |||
| 29 | public: | ||
| 30 | /** | ||
| 31 | * Sets a default value, label, and setting value. | ||
| 32 | * | ||
| 33 | * @param linkage Setting registry | ||
| 34 | * @param default_val Initial value of the setting, and default value of the setting | ||
| 35 | * @param name Label for the setting | ||
| 36 | * @param category_ Category of the setting AKA INI group | ||
| 37 | * @param specialization_ Suggestion for how frontend implementations represent this in a config | ||
| 38 | * @param save_ Suggests that this should or should not be saved to a frontend config file | ||
| 39 | * @param runtime_modifiable_ Suggests whether this is modifiable while a guest is loaded | ||
| 40 | * @param other_setting_ A second Setting to associate to this one in metadata | ||
| 41 | */ | ||
| 42 | explicit Setting(Linkage& linkage, const Type& default_val, const std::string& name, | ||
| 43 | Category category_, u32 specialization_ = Specialization::Default, | ||
| 44 | bool save_ = true, bool runtime_modifiable_ = false, | ||
| 45 | BasicSetting* other_setting_ = nullptr) | ||
| 46 | requires(!ranged) | ||
| 47 | : BasicSetting(linkage, name, category_, save_, runtime_modifiable_, specialization_, | ||
| 48 | other_setting_), | ||
| 49 | value{default_val}, default_value{default_val} {} | ||
| 50 | virtual ~Setting() = default; | ||
| 51 | |||
| 52 | /** | ||
| 53 | * Sets a default value, minimum value, maximum value, and label. | ||
| 54 | * | ||
| 55 | * @param linkage Setting registry | ||
| 56 | * @param default_val Initial value of the setting, and default value of the setting | ||
| 57 | * @param min_val Sets the minimum allowed value of the setting | ||
| 58 | * @param max_val Sets the maximum allowed value of the setting | ||
| 59 | * @param name Label for the setting | ||
| 60 | * @param category_ Category of the setting AKA INI group | ||
| 61 | * @param specialization_ Suggestion for how frontend implementations represent this in a config | ||
| 62 | * @param save_ Suggests that this should or should not be saved to a frontend config file | ||
| 63 | * @param runtime_modifiable_ Suggests whether this is modifiable while a guest is loaded | ||
| 64 | * @param other_setting_ A second Setting to associate to this one in metadata | ||
| 65 | */ | ||
| 66 | explicit Setting(Linkage& linkage, const Type& default_val, const Type& min_val, | ||
| 67 | const Type& max_val, const std::string& name, Category category_, | ||
| 68 | u32 specialization_ = Specialization::Default, bool save_ = true, | ||
| 69 | bool runtime_modifiable_ = false, BasicSetting* other_setting_ = nullptr) | ||
| 70 | requires(ranged) | ||
| 71 | : BasicSetting(linkage, name, category_, save_, runtime_modifiable_, specialization_, | ||
| 72 | other_setting_), | ||
| 73 | value{default_val}, default_value{default_val}, maximum{max_val}, minimum{min_val} {} | ||
| 74 | |||
| 75 | /** | ||
| 76 | * Returns a reference to the setting's value. | ||
| 77 | * | ||
| 78 | * @returns A reference to the setting | ||
| 79 | */ | ||
| 80 | [[nodiscard]] virtual const Type& GetValue() const { | ||
| 81 | return value; | ||
| 82 | } | ||
| 83 | |||
| 84 | /** | ||
| 85 | * Sets the setting to the given value. | ||
| 86 | * | ||
| 87 | * @param val The desired value | ||
| 88 | */ | ||
| 89 | virtual void SetValue(const Type& val) { | ||
| 90 | Type temp{ranged ? std::clamp(val, minimum, maximum) : val}; | ||
| 91 | std::swap(value, temp); | ||
| 92 | } | ||
| 93 | |||
| 94 | /** | ||
| 95 | * Returns the value that this setting was created with. | ||
| 96 | * | ||
| 97 | * @returns A reference to the default value | ||
| 98 | */ | ||
| 99 | [[nodiscard]] const Type& GetDefault() const { | ||
| 100 | return default_value; | ||
| 101 | } | ||
| 102 | |||
| 103 | [[nodiscard]] constexpr bool IsEnum() const override { | ||
| 104 | return std::is_enum_v<Type>; | ||
| 105 | } | ||
| 106 | |||
| 107 | protected: | ||
| 108 | [[nodiscard]] std::string ToString(const Type& value_) const { | ||
| 109 | if constexpr (std::is_same_v<Type, std::string>) { | ||
| 110 | return value_; | ||
| 111 | } else if constexpr (std::is_same_v<Type, std::optional<u32>>) { | ||
| 112 | return value_.has_value() ? std::to_string(*value_) : "none"; | ||
| 113 | } else if constexpr (std::is_same_v<Type, bool>) { | ||
| 114 | return value_ ? "true" : "false"; | ||
| 115 | } else if constexpr (std::is_same_v<Type, AudioEngine>) { | ||
| 116 | // Compatibility with old AudioEngine setting being a string | ||
| 117 | return CanonicalizeEnum(value_); | ||
| 118 | } else { | ||
| 119 | return std::to_string(static_cast<u64>(value_)); | ||
| 120 | } | ||
| 121 | } | ||
| 122 | |||
| 123 | public: | ||
| 124 | /** | ||
| 125 | * Converts the value of the setting to a std::string. Respects the global state if the setting | ||
| 126 | * has one. | ||
| 127 | * | ||
| 128 | * @returns The current setting as a std::string | ||
| 129 | */ | ||
| 130 | [[nodiscard]] std::string ToString() const override { | ||
| 131 | return ToString(this->GetValue()); | ||
| 132 | } | ||
| 133 | |||
| 134 | /** | ||
| 135 | * Returns the default value of the setting as a std::string. | ||
| 136 | * | ||
| 137 | * @returns The default value as a string. | ||
| 138 | */ | ||
| 139 | [[nodiscard]] std::string DefaultToString() const override { | ||
| 140 | return ToString(default_value); | ||
| 141 | } | ||
| 142 | |||
| 143 | /** | ||
| 144 | * Assigns a value to the setting. | ||
| 145 | * | ||
| 146 | * @param val The desired setting value | ||
| 147 | * | ||
| 148 | * @returns A reference to the setting | ||
| 149 | */ | ||
| 150 | virtual const Type& operator=(const Type& val) { | ||
| 151 | Type temp{ranged ? std::clamp(val, minimum, maximum) : val}; | ||
| 152 | std::swap(value, temp); | ||
| 153 | return value; | ||
| 154 | } | ||
| 155 | |||
| 156 | /** | ||
| 157 | * Returns a reference to the setting. | ||
| 158 | * | ||
| 159 | * @returns A reference to the setting | ||
| 160 | */ | ||
| 161 | explicit virtual operator const Type&() const { | ||
| 162 | return value; | ||
| 163 | } | ||
| 164 | |||
| 165 | /** | ||
| 166 | * Converts the given value to the Setting's type of value. Uses SetValue to enter the setting, | ||
| 167 | * thus respecting its constraints. | ||
| 168 | * | ||
| 169 | * @param input The desired value | ||
| 170 | */ | ||
| 171 | void LoadString(const std::string& input) override final { | ||
| 172 | if (input.empty()) { | ||
| 173 | this->SetValue(this->GetDefault()); | ||
| 174 | return; | ||
| 175 | } | ||
| 176 | try { | ||
| 177 | if constexpr (std::is_same_v<Type, std::string>) { | ||
| 178 | this->SetValue(input); | ||
| 179 | } else if constexpr (std::is_same_v<Type, std::optional<u32>>) { | ||
| 180 | this->SetValue(static_cast<u32>(std::stoul(input))); | ||
| 181 | } else if constexpr (std::is_same_v<Type, bool>) { | ||
| 182 | this->SetValue(input == "true"); | ||
| 183 | } else if constexpr (std::is_same_v<Type, AudioEngine>) { | ||
| 184 | this->SetValue(ToEnum<Type>(input)); | ||
| 185 | } else { | ||
| 186 | this->SetValue(static_cast<Type>(std::stoll(input))); | ||
| 187 | } | ||
| 188 | } catch (std::invalid_argument&) { | ||
| 189 | this->SetValue(this->GetDefault()); | ||
| 190 | } | ||
| 191 | } | ||
| 192 | |||
| 193 | [[nodiscard]] std::string constexpr Canonicalize() const override final { | ||
| 194 | if constexpr (std::is_enum_v<Type>) { | ||
| 195 | return CanonicalizeEnum(this->GetValue()); | ||
| 196 | } else { | ||
| 197 | return ToString(this->GetValue()); | ||
| 198 | } | ||
| 199 | } | ||
| 200 | |||
| 201 | /** | ||
| 202 | * Gives us another way to identify the setting without having to go through a string. | ||
| 203 | * | ||
| 204 | * @returns the type_index of the setting's type | ||
| 205 | */ | ||
| 206 | [[nodiscard]] std::type_index TypeId() const override final { | ||
| 207 | return std::type_index(typeid(Type)); | ||
| 208 | } | ||
| 209 | |||
| 210 | [[nodiscard]] constexpr u32 EnumIndex() const override final { | ||
| 211 | if constexpr (std::is_enum_v<Type>) { | ||
| 212 | return EnumMetadata<Type>::Index(); | ||
| 213 | } else { | ||
| 214 | return std::numeric_limits<u32>::max(); | ||
| 215 | } | ||
| 216 | } | ||
| 217 | |||
| 218 | [[nodiscard]] std::string MinVal() const override final { | ||
| 219 | return this->ToString(minimum); | ||
| 220 | } | ||
| 221 | [[nodiscard]] std::string MaxVal() const override final { | ||
| 222 | return this->ToString(maximum); | ||
| 223 | } | ||
| 224 | |||
| 225 | [[nodiscard]] constexpr bool Ranged() const override { | ||
| 226 | return ranged; | ||
| 227 | } | ||
| 228 | |||
| 229 | protected: | ||
| 230 | Type value{}; ///< The setting | ||
| 231 | const Type default_value{}; ///< The default value | ||
| 232 | const Type maximum{}; ///< Maximum allowed value of the setting | ||
| 233 | const Type minimum{}; ///< Minimum allowed value of the setting | ||
| 234 | }; | ||
| 235 | |||
| 236 | /** | ||
| 237 | * The SwitchableSetting class is a slightly more complex version of the Setting class. This adds a | ||
| 238 | * custom setting to switch to when a guest application specifically requires it. The effect is that | ||
| 239 | * other components of the emulator can access the setting's intended value without any need for the | ||
| 240 | * component to ask whether the custom or global setting is needed at the moment. | ||
| 241 | * | ||
| 242 | * By default, the global setting is used. | ||
| 243 | */ | ||
| 244 | template <typename Type, bool ranged = false> | ||
| 245 | class SwitchableSetting : virtual public Setting<Type, ranged> { | ||
| 246 | public: | ||
| 247 | /** | ||
| 248 | * Sets a default value, label, and setting value. | ||
| 249 | * | ||
| 250 | * @param linkage Setting registry | ||
| 251 | * @param default_val Initial value of the setting, and default value of the setting | ||
| 252 | * @param name Label for the setting | ||
| 253 | * @param category_ Category of the setting AKA INI group | ||
| 254 | * @param specialization_ Suggestion for how frontend implementations represent this in a config | ||
| 255 | * @param save_ Suggests that this should or should not be saved to a frontend config file | ||
| 256 | * @param runtime_modifiable_ Suggests whether this is modifiable while a guest is loaded | ||
| 257 | * @param other_setting_ A second Setting to associate to this one in metadata | ||
| 258 | */ | ||
| 259 | explicit SwitchableSetting(Linkage& linkage, const Type& default_val, const std::string& name, | ||
| 260 | Category category_, u32 specialization_ = Specialization::Default, | ||
| 261 | bool save_ = true, bool runtime_modifiable_ = false, | ||
| 262 | BasicSetting* other_setting_ = nullptr) | ||
| 263 | requires(!ranged) | ||
| 264 | : Setting<Type, false>{ | ||
| 265 | linkage, default_val, name, category_, specialization_, | ||
| 266 | save_, runtime_modifiable_, other_setting_} { | ||
| 267 | linkage.restore_functions.emplace_back([this]() { this->SetGlobal(true); }); | ||
| 268 | } | ||
| 269 | virtual ~SwitchableSetting() = default; | ||
| 270 | |||
| 271 | /** | ||
| 272 | * Sets a default value, minimum value, maximum value, and label. | ||
| 273 | * | ||
| 274 | * @param linkage Setting registry | ||
| 275 | * @param default_val Initial value of the setting, and default value of the setting | ||
| 276 | * @param min_val Sets the minimum allowed value of the setting | ||
| 277 | * @param max_val Sets the maximum allowed value of the setting | ||
| 278 | * @param name Label for the setting | ||
| 279 | * @param category_ Category of the setting AKA INI group | ||
| 280 | * @param specialization_ Suggestion for how frontend implementations represent this in a config | ||
| 281 | * @param save_ Suggests that this should or should not be saved to a frontend config file | ||
| 282 | * @param runtime_modifiable_ Suggests whether this is modifiable while a guest is loaded | ||
| 283 | * @param other_setting_ A second Setting to associate to this one in metadata | ||
| 284 | */ | ||
| 285 | explicit SwitchableSetting(Linkage& linkage, const Type& default_val, const Type& min_val, | ||
| 286 | const Type& max_val, const std::string& name, Category category_, | ||
| 287 | u32 specialization_ = Specialization::Default, bool save_ = true, | ||
| 288 | bool runtime_modifiable_ = false, | ||
| 289 | BasicSetting* other_setting_ = nullptr) | ||
| 290 | requires(ranged) | ||
| 291 | : Setting<Type, true>{linkage, default_val, min_val, | ||
| 292 | max_val, name, category_, | ||
| 293 | specialization_, save_, runtime_modifiable_, | ||
| 294 | other_setting_} { | ||
| 295 | linkage.restore_functions.emplace_back([this]() { this->SetGlobal(true); }); | ||
| 296 | } | ||
| 297 | |||
| 298 | /** | ||
| 299 | * Tells this setting to represent either the global or custom setting when other member | ||
| 300 | * functions are used. | ||
| 301 | * | ||
| 302 | * @param to_global Whether to use the global or custom setting. | ||
| 303 | */ | ||
| 304 | void SetGlobal(bool to_global) override final { | ||
| 305 | use_global = to_global; | ||
| 306 | } | ||
| 307 | |||
| 308 | /** | ||
| 309 | * Returns whether this setting is using the global setting or not. | ||
| 310 | * | ||
| 311 | * @returns The global state | ||
| 312 | */ | ||
| 313 | [[nodiscard]] bool UsingGlobal() const override final { | ||
| 314 | return use_global; | ||
| 315 | } | ||
| 316 | |||
| 317 | /** | ||
| 318 | * Returns either the global or custom setting depending on the values of this setting's global | ||
| 319 | * state or if the global value was specifically requested. | ||
| 320 | * | ||
| 321 | * @param need_global Request global value regardless of setting's state; defaults to false | ||
| 322 | * | ||
| 323 | * @returns The required value of the setting | ||
| 324 | */ | ||
| 325 | [[nodiscard]] const Type& GetValue() const override final { | ||
| 326 | if (use_global) { | ||
| 327 | return this->value; | ||
| 328 | } | ||
| 329 | return custom; | ||
| 330 | } | ||
| 331 | [[nodiscard]] const Type& GetValue(bool need_global) const { | ||
| 332 | if (use_global || need_global) { | ||
| 333 | return this->value; | ||
| 334 | } | ||
| 335 | return custom; | ||
| 336 | } | ||
| 337 | |||
| 338 | /** | ||
| 339 | * Sets the current setting value depending on the global state. | ||
| 340 | * | ||
| 341 | * @param val The new value | ||
| 342 | */ | ||
| 343 | void SetValue(const Type& val) override final { | ||
| 344 | Type temp{ranged ? std::clamp(val, this->minimum, this->maximum) : val}; | ||
| 345 | if (use_global) { | ||
| 346 | std::swap(this->value, temp); | ||
| 347 | } else { | ||
| 348 | std::swap(custom, temp); | ||
| 349 | } | ||
| 350 | } | ||
| 351 | |||
| 352 | [[nodiscard]] constexpr bool Switchable() const override final { | ||
| 353 | return true; | ||
| 354 | } | ||
| 355 | |||
| 356 | [[nodiscard]] std::string ToStringGlobal() const override final { | ||
| 357 | return this->ToString(this->value); | ||
| 358 | } | ||
| 359 | |||
| 360 | /** | ||
| 361 | * Assigns the current setting value depending on the global state. | ||
| 362 | * | ||
| 363 | * @param val The new value | ||
| 364 | * | ||
| 365 | * @returns A reference to the current setting value | ||
| 366 | */ | ||
| 367 | const Type& operator=(const Type& val) override final { | ||
| 368 | Type temp{ranged ? std::clamp(val, this->minimum, this->maximum) : val}; | ||
| 369 | if (use_global) { | ||
| 370 | std::swap(this->value, temp); | ||
| 371 | return this->value; | ||
| 372 | } | ||
| 373 | std::swap(custom, temp); | ||
| 374 | return custom; | ||
| 375 | } | ||
| 376 | |||
| 377 | /** | ||
| 378 | * Returns the current setting value depending on the global state. | ||
| 379 | * | ||
| 380 | * @returns A reference to the current setting value | ||
| 381 | */ | ||
| 382 | explicit operator const Type&() const override final { | ||
| 383 | if (use_global) { | ||
| 384 | return this->value; | ||
| 385 | } | ||
| 386 | return custom; | ||
| 387 | } | ||
| 388 | |||
| 389 | protected: | ||
| 390 | bool use_global{true}; ///< The setting's global state | ||
| 391 | Type custom{}; ///< The custom value of the setting | ||
| 392 | }; | ||
| 393 | |||
| 394 | } // namespace Settings | ||
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp index c97158a71..44a297cdc 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp | |||
| @@ -287,7 +287,7 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable* | |||
| 287 | } | 287 | } |
| 288 | } else { | 288 | } else { |
| 289 | // Unsafe optimizations | 289 | // Unsafe optimizations |
| 290 | if (Settings::values.cpu_accuracy.GetValue() == Settings::CPUAccuracy::Unsafe) { | 290 | if (Settings::values.cpu_accuracy.GetValue() == Settings::CpuAccuracy::Unsafe) { |
| 291 | config.unsafe_optimizations = true; | 291 | config.unsafe_optimizations = true; |
| 292 | if (Settings::values.cpuopt_unsafe_unfuse_fma) { | 292 | if (Settings::values.cpuopt_unsafe_unfuse_fma) { |
| 293 | config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA; | 293 | config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA; |
| @@ -307,7 +307,7 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable* | |||
| 307 | } | 307 | } |
| 308 | 308 | ||
| 309 | // Curated optimizations | 309 | // Curated optimizations |
| 310 | if (Settings::values.cpu_accuracy.GetValue() == Settings::CPUAccuracy::Auto) { | 310 | if (Settings::values.cpu_accuracy.GetValue() == Settings::CpuAccuracy::Auto) { |
| 311 | config.unsafe_optimizations = true; | 311 | config.unsafe_optimizations = true; |
| 312 | config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA; | 312 | config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA; |
| 313 | config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_IgnoreStandardFPCRValue; | 313 | config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_IgnoreStandardFPCRValue; |
| @@ -316,7 +316,7 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable* | |||
| 316 | } | 316 | } |
| 317 | 317 | ||
| 318 | // Paranoia mode for debugging optimizations | 318 | // Paranoia mode for debugging optimizations |
| 319 | if (Settings::values.cpu_accuracy.GetValue() == Settings::CPUAccuracy::Paranoid) { | 319 | if (Settings::values.cpu_accuracy.GetValue() == Settings::CpuAccuracy::Paranoid) { |
| 320 | config.unsafe_optimizations = false; | 320 | config.unsafe_optimizations = false; |
| 321 | config.optimizations = Dynarmic::no_optimizations; | 321 | config.optimizations = Dynarmic::no_optimizations; |
| 322 | } | 322 | } |
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp index 791d466ca..2e3674b6d 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp | |||
| @@ -347,7 +347,7 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable* | |||
| 347 | } | 347 | } |
| 348 | } else { | 348 | } else { |
| 349 | // Unsafe optimizations | 349 | // Unsafe optimizations |
| 350 | if (Settings::values.cpu_accuracy.GetValue() == Settings::CPUAccuracy::Unsafe) { | 350 | if (Settings::values.cpu_accuracy.GetValue() == Settings::CpuAccuracy::Unsafe) { |
| 351 | config.unsafe_optimizations = true; | 351 | config.unsafe_optimizations = true; |
| 352 | if (Settings::values.cpuopt_unsafe_unfuse_fma) { | 352 | if (Settings::values.cpuopt_unsafe_unfuse_fma) { |
| 353 | config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA; | 353 | config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA; |
| @@ -367,7 +367,7 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable* | |||
| 367 | } | 367 | } |
| 368 | 368 | ||
| 369 | // Curated optimizations | 369 | // Curated optimizations |
| 370 | if (Settings::values.cpu_accuracy.GetValue() == Settings::CPUAccuracy::Auto) { | 370 | if (Settings::values.cpu_accuracy.GetValue() == Settings::CpuAccuracy::Auto) { |
| 371 | config.unsafe_optimizations = true; | 371 | config.unsafe_optimizations = true; |
| 372 | config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA; | 372 | config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA; |
| 373 | config.fastmem_address_space_bits = 64; | 373 | config.fastmem_address_space_bits = 64; |
| @@ -375,7 +375,7 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable* | |||
| 375 | } | 375 | } |
| 376 | 376 | ||
| 377 | // Paranoia mode for debugging optimizations | 377 | // Paranoia mode for debugging optimizations |
| 378 | if (Settings::values.cpu_accuracy.GetValue() == Settings::CPUAccuracy::Paranoid) { | 378 | if (Settings::values.cpu_accuracy.GetValue() == Settings::CpuAccuracy::Paranoid) { |
| 379 | config.unsafe_optimizations = false; | 379 | config.unsafe_optimizations = false; |
| 380 | config.optimizations = Dynarmic::no_optimizations; | 380 | config.optimizations = Dynarmic::no_optimizations; |
| 381 | } | 381 | } |
diff --git a/src/core/core.cpp b/src/core/core.cpp index 48233d7c8..2f67e60a9 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | #include "common/logging/log.h" | 12 | #include "common/logging/log.h" |
| 13 | #include "common/microprofile.h" | 13 | #include "common/microprofile.h" |
| 14 | #include "common/settings.h" | 14 | #include "common/settings.h" |
| 15 | #include "common/settings_enums.h" | ||
| 15 | #include "common/string_util.h" | 16 | #include "common/string_util.h" |
| 16 | #include "core/arm/exclusive_monitor.h" | 17 | #include "core/arm/exclusive_monitor.h" |
| 17 | #include "core/core.h" | 18 | #include "core/core.h" |
| @@ -140,16 +141,13 @@ struct System::Impl { | |||
| 140 | device_memory = std::make_unique<Core::DeviceMemory>(); | 141 | device_memory = std::make_unique<Core::DeviceMemory>(); |
| 141 | 142 | ||
| 142 | is_multicore = Settings::values.use_multi_core.GetValue(); | 143 | is_multicore = Settings::values.use_multi_core.GetValue(); |
| 143 | extended_memory_layout = Settings::values.use_unsafe_extended_memory_layout.GetValue(); | 144 | extended_memory_layout = |
| 145 | Settings::values.memory_layout_mode.GetValue() != Settings::MemoryLayout::Memory_4Gb; | ||
| 144 | 146 | ||
| 145 | core_timing.SetMulticore(is_multicore); | 147 | core_timing.SetMulticore(is_multicore); |
| 146 | core_timing.Initialize([&system]() { system.RegisterHostThread(); }); | 148 | core_timing.Initialize([&system]() { system.RegisterHostThread(); }); |
| 147 | 149 | ||
| 148 | const auto posix_time = std::chrono::system_clock::now().time_since_epoch(); | 150 | RefreshTime(); |
| 149 | const auto current_time = | ||
| 150 | std::chrono::duration_cast<std::chrono::seconds>(posix_time).count(); | ||
| 151 | Settings::values.custom_rtc_differential = | ||
| 152 | Settings::values.custom_rtc.value_or(current_time) - current_time; | ||
| 153 | 151 | ||
| 154 | // Create a default fs if one doesn't already exist. | 152 | // Create a default fs if one doesn't already exist. |
| 155 | if (virtual_filesystem == nullptr) { | 153 | if (virtual_filesystem == nullptr) { |
| @@ -172,7 +170,8 @@ struct System::Impl { | |||
| 172 | void ReinitializeIfNecessary(System& system) { | 170 | void ReinitializeIfNecessary(System& system) { |
| 173 | const bool must_reinitialize = | 171 | const bool must_reinitialize = |
| 174 | is_multicore != Settings::values.use_multi_core.GetValue() || | 172 | is_multicore != Settings::values.use_multi_core.GetValue() || |
| 175 | extended_memory_layout != Settings::values.use_unsafe_extended_memory_layout.GetValue(); | 173 | extended_memory_layout != (Settings::values.memory_layout_mode.GetValue() != |
| 174 | Settings::MemoryLayout::Memory_4Gb); | ||
| 176 | 175 | ||
| 177 | if (!must_reinitialize) { | 176 | if (!must_reinitialize) { |
| 178 | return; | 177 | return; |
| @@ -181,11 +180,22 @@ struct System::Impl { | |||
| 181 | LOG_DEBUG(Kernel, "Re-initializing"); | 180 | LOG_DEBUG(Kernel, "Re-initializing"); |
| 182 | 181 | ||
| 183 | is_multicore = Settings::values.use_multi_core.GetValue(); | 182 | is_multicore = Settings::values.use_multi_core.GetValue(); |
| 184 | extended_memory_layout = Settings::values.use_unsafe_extended_memory_layout.GetValue(); | 183 | extended_memory_layout = |
| 184 | Settings::values.memory_layout_mode.GetValue() != Settings::MemoryLayout::Memory_4Gb; | ||
| 185 | 185 | ||
| 186 | Initialize(system); | 186 | Initialize(system); |
| 187 | } | 187 | } |
| 188 | 188 | ||
| 189 | void RefreshTime() { | ||
| 190 | const auto posix_time = std::chrono::system_clock::now().time_since_epoch(); | ||
| 191 | const auto current_time = | ||
| 192 | std::chrono::duration_cast<std::chrono::seconds>(posix_time).count(); | ||
| 193 | Settings::values.custom_rtc_differential = | ||
| 194 | (Settings::values.custom_rtc_enabled ? Settings::values.custom_rtc.GetValue() | ||
| 195 | : current_time) - | ||
| 196 | current_time; | ||
| 197 | } | ||
| 198 | |||
| 189 | void Run() { | 199 | void Run() { |
| 190 | std::unique_lock<std::mutex> lk(suspend_guard); | 200 | std::unique_lock<std::mutex> lk(suspend_guard); |
| 191 | 201 | ||
| @@ -1028,6 +1038,8 @@ void System::Exit() { | |||
| 1028 | } | 1038 | } |
| 1029 | 1039 | ||
| 1030 | void System::ApplySettings() { | 1040 | void System::ApplySettings() { |
| 1041 | impl->RefreshTime(); | ||
| 1042 | |||
| 1031 | if (IsPoweredOn()) { | 1043 | if (IsPoweredOn()) { |
| 1032 | Renderer().RefreshBaseSettings(); | 1044 | Renderer().RefreshBaseSettings(); |
| 1033 | } | 1045 | } |
diff --git a/src/core/file_sys/control_metadata.cpp b/src/core/file_sys/control_metadata.cpp index cd9ac2e75..0697c29ae 100644 --- a/src/core/file_sys/control_metadata.cpp +++ b/src/core/file_sys/control_metadata.cpp | |||
| @@ -68,7 +68,8 @@ NACP::NACP(VirtualFile file) { | |||
| 68 | NACP::~NACP() = default; | 68 | NACP::~NACP() = default; |
| 69 | 69 | ||
| 70 | const LanguageEntry& NACP::GetLanguageEntry() const { | 70 | const LanguageEntry& NACP::GetLanguageEntry() const { |
| 71 | Language language = language_to_codes[Settings::values.language_index.GetValue()]; | 71 | Language language = |
| 72 | language_to_codes[static_cast<s32>(Settings::values.language_index.GetValue())]; | ||
| 72 | 73 | ||
| 73 | { | 74 | { |
| 74 | const auto& language_entry = raw.language_entries.at(static_cast<u8>(language)); | 75 | const auto& language_entry = raw.language_entries.at(static_cast<u8>(language)); |
diff --git a/src/core/file_sys/patch_manager.cpp b/src/core/file_sys/patch_manager.cpp index d3286b352..2ba1b34a4 100644 --- a/src/core/file_sys/patch_manager.cpp +++ b/src/core/file_sys/patch_manager.cpp | |||
| @@ -626,8 +626,8 @@ PatchManager::Metadata PatchManager::ParseControlNCA(const NCA& nca) const { | |||
| 626 | auto nacp = nacp_file == nullptr ? nullptr : std::make_unique<NACP>(nacp_file); | 626 | auto nacp = nacp_file == nullptr ? nullptr : std::make_unique<NACP>(nacp_file); |
| 627 | 627 | ||
| 628 | // Get language code from settings | 628 | // Get language code from settings |
| 629 | const auto language_code = | 629 | const auto language_code = Service::Set::GetLanguageCodeFromIndex( |
| 630 | Service::Set::GetLanguageCodeFromIndex(Settings::values.language_index.GetValue()); | 630 | static_cast<u32>(Settings::values.language_index.GetValue())); |
| 631 | 631 | ||
| 632 | // Convert to application language and get priority list | 632 | // Convert to application language and get priority list |
| 633 | const auto application_language = | 633 | const auto application_language = |
diff --git a/src/core/hle/kernel/board/nintendo/nx/k_system_control.cpp b/src/core/hle/kernel/board/nintendo/nx/k_system_control.cpp index 49bdc671e..4cfdf4558 100644 --- a/src/core/hle/kernel/board/nintendo/nx/k_system_control.cpp +++ b/src/core/hle/kernel/board/nintendo/nx/k_system_control.cpp | |||
| @@ -35,13 +35,27 @@ namespace { | |||
| 35 | using namespace Common::Literals; | 35 | using namespace Common::Literals; |
| 36 | 36 | ||
| 37 | u32 GetMemorySizeForInit() { | 37 | u32 GetMemorySizeForInit() { |
| 38 | return Settings::values.use_unsafe_extended_memory_layout ? Smc::MemorySize_8GB | 38 | switch (Settings::values.memory_layout_mode.GetValue()) { |
| 39 | : Smc::MemorySize_4GB; | 39 | case Settings::MemoryLayout::Memory_4Gb: |
| 40 | return Smc::MemorySize_4GB; | ||
| 41 | case Settings::MemoryLayout::Memory_6Gb: | ||
| 42 | return Smc::MemorySize_6GB; | ||
| 43 | case Settings::MemoryLayout::Memory_8Gb: | ||
| 44 | return Smc::MemorySize_8GB; | ||
| 45 | } | ||
| 46 | return Smc::MemorySize_4GB; | ||
| 40 | } | 47 | } |
| 41 | 48 | ||
| 42 | Smc::MemoryArrangement GetMemoryArrangeForInit() { | 49 | Smc::MemoryArrangement GetMemoryArrangeForInit() { |
| 43 | return Settings::values.use_unsafe_extended_memory_layout ? Smc::MemoryArrangement_8GB | 50 | switch (Settings::values.memory_layout_mode.GetValue()) { |
| 44 | : Smc::MemoryArrangement_4GB; | 51 | case Settings::MemoryLayout::Memory_4Gb: |
| 52 | return Smc::MemoryArrangement_4GB; | ||
| 53 | case Settings::MemoryLayout::Memory_6Gb: | ||
| 54 | return Smc::MemoryArrangement_6GB; | ||
| 55 | case Settings::MemoryLayout::Memory_8Gb: | ||
| 56 | return Smc::MemoryArrangement_8GB; | ||
| 57 | } | ||
| 58 | return Smc::MemoryArrangement_4GB; | ||
| 45 | } | 59 | } |
| 46 | } // namespace | 60 | } // namespace |
| 47 | 61 | ||
diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp index 44c7cb22f..e573e2a57 100644 --- a/src/core/hle/kernel/k_process.cpp +++ b/src/core/hle/kernel/k_process.cpp | |||
| @@ -81,7 +81,8 @@ Result KProcess::Initialize(KProcess* process, Core::System& system, std::string | |||
| 81 | process->m_capabilities.InitializeForMetadatalessProcess(); | 81 | process->m_capabilities.InitializeForMetadatalessProcess(); |
| 82 | process->m_is_initialized = true; | 82 | process->m_is_initialized = true; |
| 83 | 83 | ||
| 84 | std::mt19937 rng(Settings::values.rng_seed.GetValue().value_or(std::time(nullptr))); | 84 | std::mt19937 rng(Settings::values.rng_seed_enabled ? Settings::values.rng_seed.GetValue() |
| 85 | : static_cast<u32>(std::time(nullptr))); | ||
| 85 | std::uniform_int_distribution<u64> distribution; | 86 | std::uniform_int_distribution<u64> distribution; |
| 86 | std::generate(process->m_random_entropy.begin(), process->m_random_entropy.end(), | 87 | std::generate(process->m_random_entropy.begin(), process->m_random_entropy.end(), |
| 87 | [&] { return distribution(rng); }); | 88 | [&] { return distribution(rng); }); |
diff --git a/src/core/hle/service/ns/ns.cpp b/src/core/hle/service/ns/ns.cpp index 376067a95..91c5a2182 100644 --- a/src/core/hle/service/ns/ns.cpp +++ b/src/core/hle/service/ns/ns.cpp | |||
| @@ -409,7 +409,7 @@ ResultVal<u8> IApplicationManagerInterface::GetApplicationDesiredLanguage( | |||
| 409 | 409 | ||
| 410 | // Get language code from settings | 410 | // Get language code from settings |
| 411 | const auto language_code = | 411 | const auto language_code = |
| 412 | Set::GetLanguageCodeFromIndex(Settings::values.language_index.GetValue()); | 412 | Set::GetLanguageCodeFromIndex(static_cast<s32>(Settings::values.language_index.GetValue())); |
| 413 | 413 | ||
| 414 | // Convert to application language, get priority list | 414 | // Convert to application language, get priority list |
| 415 | const auto application_language = ConvertToApplicationLanguage(language_code); | 415 | const auto application_language = ConvertToApplicationLanguage(language_code); |
diff --git a/src/core/hle/service/set/set.cpp b/src/core/hle/service/set/set.cpp index f5788b481..83f888c54 100644 --- a/src/core/hle/service/set/set.cpp +++ b/src/core/hle/service/set/set.cpp | |||
| @@ -93,7 +93,8 @@ void GetAvailableLanguageCodesImpl(HLERequestContext& ctx, std::size_t max_entri | |||
| 93 | } | 93 | } |
| 94 | 94 | ||
| 95 | void GetKeyCodeMapImpl(HLERequestContext& ctx) { | 95 | void GetKeyCodeMapImpl(HLERequestContext& ctx) { |
| 96 | const auto language_code = available_language_codes[Settings::values.language_index.GetValue()]; | 96 | const auto language_code = |
| 97 | available_language_codes[static_cast<s32>(Settings::values.language_index.GetValue())]; | ||
| 97 | const auto key_code = | 98 | const auto key_code = |
| 98 | std::find_if(language_to_layout.cbegin(), language_to_layout.cend(), | 99 | std::find_if(language_to_layout.cbegin(), language_to_layout.cend(), |
| 99 | [=](const auto& element) { return element.first == language_code; }); | 100 | [=](const auto& element) { return element.first == language_code; }); |
| @@ -162,7 +163,7 @@ void SET::GetQuestFlag(HLERequestContext& ctx) { | |||
| 162 | 163 | ||
| 163 | IPC::ResponseBuilder rb{ctx, 3}; | 164 | IPC::ResponseBuilder rb{ctx, 3}; |
| 164 | rb.Push(ResultSuccess); | 165 | rb.Push(ResultSuccess); |
| 165 | rb.Push(static_cast<u32>(Settings::values.quest_flag.GetValue())); | 166 | rb.Push(static_cast<s32>(Settings::values.quest_flag.GetValue())); |
| 166 | } | 167 | } |
| 167 | 168 | ||
| 168 | void SET::GetLanguageCode(HLERequestContext& ctx) { | 169 | void SET::GetLanguageCode(HLERequestContext& ctx) { |
| @@ -170,7 +171,8 @@ void SET::GetLanguageCode(HLERequestContext& ctx) { | |||
| 170 | 171 | ||
| 171 | IPC::ResponseBuilder rb{ctx, 4}; | 172 | IPC::ResponseBuilder rb{ctx, 4}; |
| 172 | rb.Push(ResultSuccess); | 173 | rb.Push(ResultSuccess); |
| 173 | rb.PushEnum(available_language_codes[Settings::values.language_index.GetValue()]); | 174 | rb.PushEnum( |
| 175 | available_language_codes[static_cast<s32>(Settings::values.language_index.GetValue())]); | ||
| 174 | } | 176 | } |
| 175 | 177 | ||
| 176 | void SET::GetRegionCode(HLERequestContext& ctx) { | 178 | void SET::GetRegionCode(HLERequestContext& ctx) { |
| @@ -178,7 +180,7 @@ void SET::GetRegionCode(HLERequestContext& ctx) { | |||
| 178 | 180 | ||
| 179 | IPC::ResponseBuilder rb{ctx, 3}; | 181 | IPC::ResponseBuilder rb{ctx, 3}; |
| 180 | rb.Push(ResultSuccess); | 182 | rb.Push(ResultSuccess); |
| 181 | rb.Push(Settings::values.region_index.GetValue()); | 183 | rb.Push(static_cast<u32>(Settings::values.region_index.GetValue())); |
| 182 | } | 184 | } |
| 183 | 185 | ||
| 184 | void SET::GetKeyCodeMap(HLERequestContext& ctx) { | 186 | void SET::GetKeyCodeMap(HLERequestContext& ctx) { |
diff --git a/src/core/hle/service/spl/spl_module.cpp b/src/core/hle/service/spl/spl_module.cpp index 0227d4393..cd631b2ea 100644 --- a/src/core/hle/service/spl/spl_module.cpp +++ b/src/core/hle/service/spl/spl_module.cpp | |||
| @@ -19,7 +19,8 @@ namespace Service::SPL { | |||
| 19 | Module::Interface::Interface(Core::System& system_, std::shared_ptr<Module> module_, | 19 | Module::Interface::Interface(Core::System& system_, std::shared_ptr<Module> module_, |
| 20 | const char* name) | 20 | const char* name) |
| 21 | : ServiceFramework{system_, name}, module{std::move(module_)}, | 21 | : ServiceFramework{system_, name}, module{std::move(module_)}, |
| 22 | rng(Settings::values.rng_seed.GetValue().value_or(std::time(nullptr))) {} | 22 | rng(Settings::values.rng_seed_enabled ? Settings::values.rng_seed.GetValue() |
| 23 | : static_cast<u32>(std::time(nullptr))) {} | ||
| 23 | 24 | ||
| 24 | Module::Interface::~Interface() = default; | 25 | Module::Interface::~Interface() = default; |
| 25 | 26 | ||
diff --git a/src/core/hle/service/time/time_zone_content_manager.cpp b/src/core/hle/service/time/time_zone_content_manager.cpp index 3b6047ad0..1b96de37a 100644 --- a/src/core/hle/service/time/time_zone_content_manager.cpp +++ b/src/core/hle/service/time/time_zone_content_manager.cpp | |||
| @@ -78,7 +78,8 @@ TimeZoneContentManager::TimeZoneContentManager(Core::System& system_) | |||
| 78 | location_name_cache{BuildLocationNameCache(time_zone_binary)} {} | 78 | location_name_cache{BuildLocationNameCache(time_zone_binary)} {} |
| 79 | 79 | ||
| 80 | void TimeZoneContentManager::Initialize(TimeManager& time_manager) { | 80 | void TimeZoneContentManager::Initialize(TimeManager& time_manager) { |
| 81 | const auto timezone_setting = Settings::GetTimeZoneString(); | 81 | const auto timezone_setting = |
| 82 | Settings::GetTimeZoneString(Settings::values.time_zone_index.GetValue()); | ||
| 82 | 83 | ||
| 83 | if (FileSys::VirtualFile vfs_file; | 84 | if (FileSys::VirtualFile vfs_file; |
| 84 | GetTimeZoneInfoFile(timezone_setting, vfs_file) == ResultSuccess) { | 85 | GetTimeZoneInfoFile(timezone_setting, vfs_file) == ResultSuccess) { |
diff --git a/src/core/telemetry_session.cpp b/src/core/telemetry_session.cpp index 7a2f3c90a..62b3f6636 100644 --- a/src/core/telemetry_session.cpp +++ b/src/core/telemetry_session.cpp | |||
| @@ -61,13 +61,13 @@ static const char* TranslateRenderer(Settings::RendererBackend backend) { | |||
| 61 | return "Unknown"; | 61 | return "Unknown"; |
| 62 | } | 62 | } |
| 63 | 63 | ||
| 64 | static const char* TranslateGPUAccuracyLevel(Settings::GPUAccuracy backend) { | 64 | static const char* TranslateGPUAccuracyLevel(Settings::GpuAccuracy backend) { |
| 65 | switch (backend) { | 65 | switch (backend) { |
| 66 | case Settings::GPUAccuracy::Normal: | 66 | case Settings::GpuAccuracy::Normal: |
| 67 | return "Normal"; | 67 | return "Normal"; |
| 68 | case Settings::GPUAccuracy::High: | 68 | case Settings::GpuAccuracy::High: |
| 69 | return "High"; | 69 | return "High"; |
| 70 | case Settings::GPUAccuracy::Extreme: | 70 | case Settings::GpuAccuracy::Extreme: |
| 71 | return "Extreme"; | 71 | return "Extreme"; |
| 72 | } | 72 | } |
| 73 | return "Unknown"; | 73 | return "Unknown"; |
| @@ -77,9 +77,9 @@ static const char* TranslateNvdecEmulation(Settings::NvdecEmulation backend) { | |||
| 77 | switch (backend) { | 77 | switch (backend) { |
| 78 | case Settings::NvdecEmulation::Off: | 78 | case Settings::NvdecEmulation::Off: |
| 79 | return "Off"; | 79 | return "Off"; |
| 80 | case Settings::NvdecEmulation::CPU: | 80 | case Settings::NvdecEmulation::Cpu: |
| 81 | return "CPU"; | 81 | return "CPU"; |
| 82 | case Settings::NvdecEmulation::GPU: | 82 | case Settings::NvdecEmulation::Gpu: |
| 83 | return "GPU"; | 83 | return "GPU"; |
| 84 | } | 84 | } |
| 85 | return "Unknown"; | 85 | return "Unknown"; |
| @@ -91,14 +91,26 @@ static constexpr const char* TranslateVSyncMode(Settings::VSyncMode mode) { | |||
| 91 | return "Immediate"; | 91 | return "Immediate"; |
| 92 | case Settings::VSyncMode::Mailbox: | 92 | case Settings::VSyncMode::Mailbox: |
| 93 | return "Mailbox"; | 93 | return "Mailbox"; |
| 94 | case Settings::VSyncMode::FIFO: | 94 | case Settings::VSyncMode::Fifo: |
| 95 | return "FIFO"; | 95 | return "FIFO"; |
| 96 | case Settings::VSyncMode::FIFORelaxed: | 96 | case Settings::VSyncMode::FifoRelaxed: |
| 97 | return "FIFO Relaxed"; | 97 | return "FIFO Relaxed"; |
| 98 | } | 98 | } |
| 99 | return "Unknown"; | 99 | return "Unknown"; |
| 100 | } | 100 | } |
| 101 | 101 | ||
| 102 | static constexpr const char* TranslateASTCDecodeMode(Settings::AstcDecodeMode mode) { | ||
| 103 | switch (mode) { | ||
| 104 | case Settings::AstcDecodeMode::Cpu: | ||
| 105 | return "CPU"; | ||
| 106 | case Settings::AstcDecodeMode::Gpu: | ||
| 107 | return "GPU"; | ||
| 108 | case Settings::AstcDecodeMode::CpuAsynchronous: | ||
| 109 | return "CPU Asynchronous"; | ||
| 110 | } | ||
| 111 | return "Unknown"; | ||
| 112 | } | ||
| 113 | |||
| 102 | u64 GetTelemetryId() { | 114 | u64 GetTelemetryId() { |
| 103 | u64 telemetry_id{}; | 115 | u64 telemetry_id{}; |
| 104 | const auto filename = Common::FS::GetYuzuPath(Common::FS::YuzuPath::ConfigDir) / "telemetry_id"; | 116 | const auto filename = Common::FS::GetYuzuPath(Common::FS::YuzuPath::ConfigDir) / "telemetry_id"; |
| @@ -240,7 +252,8 @@ void TelemetrySession::AddInitialInfo(Loader::AppLoader& app_loader, | |||
| 240 | 252 | ||
| 241 | // Log user configuration information | 253 | // Log user configuration information |
| 242 | constexpr auto field_type = Telemetry::FieldType::UserConfig; | 254 | constexpr auto field_type = Telemetry::FieldType::UserConfig; |
| 243 | AddField(field_type, "Audio_SinkId", Settings::values.sink_id.GetValue()); | 255 | AddField(field_type, "Audio_SinkId", |
| 256 | Settings::CanonicalizeEnum(Settings::values.sink_id.GetValue())); | ||
| 244 | AddField(field_type, "Core_UseMultiCore", Settings::values.use_multi_core.GetValue()); | 257 | AddField(field_type, "Core_UseMultiCore", Settings::values.use_multi_core.GetValue()); |
| 245 | AddField(field_type, "Renderer_Backend", | 258 | AddField(field_type, "Renderer_Backend", |
| 246 | TranslateRenderer(Settings::values.renderer_backend.GetValue())); | 259 | TranslateRenderer(Settings::values.renderer_backend.GetValue())); |
| @@ -254,7 +267,8 @@ void TelemetrySession::AddInitialInfo(Loader::AppLoader& app_loader, | |||
| 254 | Settings::values.use_asynchronous_gpu_emulation.GetValue()); | 267 | Settings::values.use_asynchronous_gpu_emulation.GetValue()); |
| 255 | AddField(field_type, "Renderer_NvdecEmulation", | 268 | AddField(field_type, "Renderer_NvdecEmulation", |
| 256 | TranslateNvdecEmulation(Settings::values.nvdec_emulation.GetValue())); | 269 | TranslateNvdecEmulation(Settings::values.nvdec_emulation.GetValue())); |
| 257 | AddField(field_type, "Renderer_AccelerateASTC", Settings::values.accelerate_astc.GetValue()); | 270 | AddField(field_type, "Renderer_AccelerateASTC", |
| 271 | TranslateASTCDecodeMode(Settings::values.accelerate_astc.GetValue())); | ||
| 258 | AddField(field_type, "Renderer_UseVsync", | 272 | AddField(field_type, "Renderer_UseVsync", |
| 259 | TranslateVSyncMode(Settings::values.vsync_mode.GetValue())); | 273 | TranslateVSyncMode(Settings::values.vsync_mode.GetValue())); |
| 260 | AddField(field_type, "Renderer_ShaderBackend", | 274 | AddField(field_type, "Renderer_ShaderBackend", |
diff --git a/src/video_core/host1x/codecs/codec.cpp b/src/video_core/host1x/codecs/codec.cpp index da07a556f..220cce28a 100644 --- a/src/video_core/host1x/codecs/codec.cpp +++ b/src/video_core/host1x/codecs/codec.cpp | |||
| @@ -247,7 +247,7 @@ void Codec::Initialize() { | |||
| 247 | av_codec = avcodec_find_decoder(codec); | 247 | av_codec = avcodec_find_decoder(codec); |
| 248 | 248 | ||
| 249 | InitializeAvCodecContext(); | 249 | InitializeAvCodecContext(); |
| 250 | if (Settings::values.nvdec_emulation.GetValue() == Settings::NvdecEmulation::GPU) { | 250 | if (Settings::values.nvdec_emulation.GetValue() == Settings::NvdecEmulation::Gpu) { |
| 251 | InitializeGpuDecoder(); | 251 | InitializeGpuDecoder(); |
| 252 | } | 252 | } |
| 253 | if (const int res = avcodec_open2(av_codec_ctx, av_codec, nullptr); res < 0) { | 253 | if (const int res = avcodec_open2(av_codec_ctx, av_codec, nullptr); res < 0) { |
diff --git a/src/video_core/host1x/codecs/h264.cpp b/src/video_core/host1x/codecs/h264.cpp index 862904e39..ece79b1e2 100644 --- a/src/video_core/host1x/codecs/h264.cpp +++ b/src/video_core/host1x/codecs/h264.cpp | |||
| @@ -84,7 +84,7 @@ std::span<const u8> H264::ComposeFrame(const Host1x::NvdecCommon::NvdecRegisters | |||
| 84 | 84 | ||
| 85 | // TODO (ameerj): Where do we get this number, it seems to be particular for each stream | 85 | // TODO (ameerj): Where do we get this number, it seems to be particular for each stream |
| 86 | const auto nvdec_decoding = Settings::values.nvdec_emulation.GetValue(); | 86 | const auto nvdec_decoding = Settings::values.nvdec_emulation.GetValue(); |
| 87 | const bool uses_gpu_decoding = nvdec_decoding == Settings::NvdecEmulation::GPU; | 87 | const bool uses_gpu_decoding = nvdec_decoding == Settings::NvdecEmulation::Gpu; |
| 88 | const u32 max_num_ref_frames = uses_gpu_decoding ? 6u : 16u; | 88 | const u32 max_num_ref_frames = uses_gpu_decoding ? 6u : 16u; |
| 89 | writer.WriteUe(max_num_ref_frames); | 89 | writer.WriteUe(max_num_ref_frames); |
| 90 | writer.WriteBit(false); | 90 | writer.WriteBit(false); |
diff --git a/src/video_core/renderer_opengl/gl_compute_pipeline.cpp b/src/video_core/renderer_opengl/gl_compute_pipeline.cpp index f9ca55c36..d70501860 100644 --- a/src/video_core/renderer_opengl/gl_compute_pipeline.cpp +++ b/src/video_core/renderer_opengl/gl_compute_pipeline.cpp | |||
| @@ -34,13 +34,13 @@ ComputePipeline::ComputePipeline(const Device& device, TextureCache& texture_cac | |||
| 34 | : texture_cache{texture_cache_}, buffer_cache{buffer_cache_}, | 34 | : texture_cache{texture_cache_}, buffer_cache{buffer_cache_}, |
| 35 | program_manager{program_manager_}, info{info_} { | 35 | program_manager{program_manager_}, info{info_} { |
| 36 | switch (device.GetShaderBackend()) { | 36 | switch (device.GetShaderBackend()) { |
| 37 | case Settings::ShaderBackend::GLSL: | 37 | case Settings::ShaderBackend::Glsl: |
| 38 | source_program = CreateProgram(code, GL_COMPUTE_SHADER); | 38 | source_program = CreateProgram(code, GL_COMPUTE_SHADER); |
| 39 | break; | 39 | break; |
| 40 | case Settings::ShaderBackend::GLASM: | 40 | case Settings::ShaderBackend::Glasm: |
| 41 | assembly_program = CompileProgram(code, GL_COMPUTE_PROGRAM_NV); | 41 | assembly_program = CompileProgram(code, GL_COMPUTE_PROGRAM_NV); |
| 42 | break; | 42 | break; |
| 43 | case Settings::ShaderBackend::SPIRV: | 43 | case Settings::ShaderBackend::SpirV: |
| 44 | source_program = CreateProgram(code_v, GL_COMPUTE_SHADER); | 44 | source_program = CreateProgram(code_v, GL_COMPUTE_SHADER); |
| 45 | break; | 45 | break; |
| 46 | } | 46 | } |
diff --git a/src/video_core/renderer_opengl/gl_device.cpp b/src/video_core/renderer_opengl/gl_device.cpp index 33e63c17d..ee140c9c2 100644 --- a/src/video_core/renderer_opengl/gl_device.cpp +++ b/src/video_core/renderer_opengl/gl_device.cpp | |||
| @@ -177,15 +177,15 @@ Device::Device(Core::Frontend::EmuWindow& emu_window) { | |||
| 177 | has_fast_buffer_sub_data = is_nvidia && !disable_fast_buffer_sub_data; | 177 | has_fast_buffer_sub_data = is_nvidia && !disable_fast_buffer_sub_data; |
| 178 | 178 | ||
| 179 | shader_backend = Settings::values.shader_backend.GetValue(); | 179 | shader_backend = Settings::values.shader_backend.GetValue(); |
| 180 | use_assembly_shaders = shader_backend == Settings::ShaderBackend::GLASM && | 180 | use_assembly_shaders = shader_backend == Settings::ShaderBackend::Glasm && |
| 181 | GLAD_GL_NV_gpu_program5 && GLAD_GL_NV_compute_program5 && | 181 | GLAD_GL_NV_gpu_program5 && GLAD_GL_NV_compute_program5 && |
| 182 | GLAD_GL_NV_transform_feedback && GLAD_GL_NV_transform_feedback2; | 182 | GLAD_GL_NV_transform_feedback && GLAD_GL_NV_transform_feedback2; |
| 183 | if (shader_backend == Settings::ShaderBackend::GLASM && !use_assembly_shaders) { | 183 | if (shader_backend == Settings::ShaderBackend::Glasm && !use_assembly_shaders) { |
| 184 | LOG_ERROR(Render_OpenGL, "Assembly shaders enabled but not supported"); | 184 | LOG_ERROR(Render_OpenGL, "Assembly shaders enabled but not supported"); |
| 185 | shader_backend = Settings::ShaderBackend::GLSL; | 185 | shader_backend = Settings::ShaderBackend::Glsl; |
| 186 | } | 186 | } |
| 187 | 187 | ||
| 188 | if (shader_backend == Settings::ShaderBackend::GLSL && is_nvidia) { | 188 | if (shader_backend == Settings::ShaderBackend::Glsl && is_nvidia) { |
| 189 | const std::string_view driver_version = version.substr(13); | 189 | const std::string_view driver_version = version.substr(13); |
| 190 | const int version_major = | 190 | const int version_major = |
| 191 | std::atoi(driver_version.substr(0, driver_version.find(".")).data()); | 191 | std::atoi(driver_version.substr(0, driver_version.find(".")).data()); |
diff --git a/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp b/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp index 71f720c63..f822fa856 100644 --- a/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp +++ b/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp | |||
| @@ -236,18 +236,18 @@ GraphicsPipeline::GraphicsPipeline(const Device& device, TextureCache& texture_c | |||
| 236 | force_context_flush](ShaderContext::Context*) mutable { | 236 | force_context_flush](ShaderContext::Context*) mutable { |
| 237 | for (size_t stage = 0; stage < 5; ++stage) { | 237 | for (size_t stage = 0; stage < 5; ++stage) { |
| 238 | switch (backend) { | 238 | switch (backend) { |
| 239 | case Settings::ShaderBackend::GLSL: | 239 | case Settings::ShaderBackend::Glsl: |
| 240 | if (!sources_[stage].empty()) { | 240 | if (!sources_[stage].empty()) { |
| 241 | source_programs[stage] = CreateProgram(sources_[stage], Stage(stage)); | 241 | source_programs[stage] = CreateProgram(sources_[stage], Stage(stage)); |
| 242 | } | 242 | } |
| 243 | break; | 243 | break; |
| 244 | case Settings::ShaderBackend::GLASM: | 244 | case Settings::ShaderBackend::Glasm: |
| 245 | if (!sources_[stage].empty()) { | 245 | if (!sources_[stage].empty()) { |
| 246 | assembly_programs[stage] = | 246 | assembly_programs[stage] = |
| 247 | CompileProgram(sources_[stage], AssemblyStage(stage)); | 247 | CompileProgram(sources_[stage], AssemblyStage(stage)); |
| 248 | } | 248 | } |
| 249 | break; | 249 | break; |
| 250 | case Settings::ShaderBackend::SPIRV: | 250 | case Settings::ShaderBackend::SpirV: |
| 251 | if (!sources_spirv_[stage].empty()) { | 251 | if (!sources_spirv_[stage].empty()) { |
| 252 | source_programs[stage] = CreateProgram(sources_spirv_[stage], Stage(stage)); | 252 | source_programs[stage] = CreateProgram(sources_spirv_[stage], Stage(stage)); |
| 253 | } | 253 | } |
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index 7e1d7f92e..618cb6354 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp | |||
| @@ -522,14 +522,14 @@ std::unique_ptr<GraphicsPipeline> ShaderCache::CreateGraphicsPipeline( | |||
| 522 | const auto runtime_info{ | 522 | const auto runtime_info{ |
| 523 | MakeRuntimeInfo(key, program, previous_program, glasm_use_storage_buffers, use_glasm)}; | 523 | MakeRuntimeInfo(key, program, previous_program, glasm_use_storage_buffers, use_glasm)}; |
| 524 | switch (device.GetShaderBackend()) { | 524 | switch (device.GetShaderBackend()) { |
| 525 | case Settings::ShaderBackend::GLSL: | 525 | case Settings::ShaderBackend::Glsl: |
| 526 | ConvertLegacyToGeneric(program, runtime_info); | 526 | ConvertLegacyToGeneric(program, runtime_info); |
| 527 | sources[stage_index] = EmitGLSL(profile, runtime_info, program, binding); | 527 | sources[stage_index] = EmitGLSL(profile, runtime_info, program, binding); |
| 528 | break; | 528 | break; |
| 529 | case Settings::ShaderBackend::GLASM: | 529 | case Settings::ShaderBackend::Glasm: |
| 530 | sources[stage_index] = EmitGLASM(profile, runtime_info, program, binding); | 530 | sources[stage_index] = EmitGLASM(profile, runtime_info, program, binding); |
| 531 | break; | 531 | break; |
| 532 | case Settings::ShaderBackend::SPIRV: | 532 | case Settings::ShaderBackend::SpirV: |
| 533 | ConvertLegacyToGeneric(program, runtime_info); | 533 | ConvertLegacyToGeneric(program, runtime_info); |
| 534 | sources_spirv[stage_index] = EmitSPIRV(profile, runtime_info, program, binding); | 534 | sources_spirv[stage_index] = EmitSPIRV(profile, runtime_info, program, binding); |
| 535 | break; | 535 | break; |
| @@ -582,13 +582,13 @@ std::unique_ptr<ComputePipeline> ShaderCache::CreateComputePipeline( | |||
| 582 | std::string code{}; | 582 | std::string code{}; |
| 583 | std::vector<u32> code_spirv; | 583 | std::vector<u32> code_spirv; |
| 584 | switch (device.GetShaderBackend()) { | 584 | switch (device.GetShaderBackend()) { |
| 585 | case Settings::ShaderBackend::GLSL: | 585 | case Settings::ShaderBackend::Glsl: |
| 586 | code = EmitGLSL(profile, program); | 586 | code = EmitGLSL(profile, program); |
| 587 | break; | 587 | break; |
| 588 | case Settings::ShaderBackend::GLASM: | 588 | case Settings::ShaderBackend::Glasm: |
| 589 | code = EmitGLASM(profile, info, program); | 589 | code = EmitGLASM(profile, info, program); |
| 590 | break; | 590 | break; |
| 591 | case Settings::ShaderBackend::SPIRV: | 591 | case Settings::ShaderBackend::SpirV: |
| 592 | code_spirv = EmitSPIRV(profile, program); | 592 | code_spirv = EmitSPIRV(profile, program); |
| 593 | break; | 593 | break; |
| 594 | } | 594 | } |
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp index 3b446be07..9cafd2983 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.cpp +++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp | |||
| @@ -232,10 +232,9 @@ void ApplySwizzle(GLuint handle, PixelFormat format, std::array<SwizzleSource, 4 | |||
| 232 | [[nodiscard]] bool CanBeAccelerated(const TextureCacheRuntime& runtime, | 232 | [[nodiscard]] bool CanBeAccelerated(const TextureCacheRuntime& runtime, |
| 233 | const VideoCommon::ImageInfo& info) { | 233 | const VideoCommon::ImageInfo& info) { |
| 234 | if (IsPixelFormatASTC(info.format) && info.size.depth == 1 && !runtime.HasNativeASTC()) { | 234 | if (IsPixelFormatASTC(info.format) && info.size.depth == 1 && !runtime.HasNativeASTC()) { |
| 235 | return Settings::values.accelerate_astc.GetValue() && | 235 | return Settings::values.accelerate_astc.GetValue() == Settings::AstcDecodeMode::Gpu && |
| 236 | Settings::values.astc_recompression.GetValue() == | 236 | Settings::values.astc_recompression.GetValue() == |
| 237 | Settings::AstcRecompression::Uncompressed && | 237 | Settings::AstcRecompression::Uncompressed; |
| 238 | !Settings::values.async_astc.GetValue(); | ||
| 239 | } | 238 | } |
| 240 | // Disable other accelerated uploads for now as they don't implement swizzled uploads | 239 | // Disable other accelerated uploads for now as they don't implement swizzled uploads |
| 241 | return false; | 240 | return false; |
| @@ -267,7 +266,8 @@ void ApplySwizzle(GLuint handle, PixelFormat format, std::array<SwizzleSource, 4 | |||
| 267 | [[nodiscard]] bool CanBeDecodedAsync(const TextureCacheRuntime& runtime, | 266 | [[nodiscard]] bool CanBeDecodedAsync(const TextureCacheRuntime& runtime, |
| 268 | const VideoCommon::ImageInfo& info) { | 267 | const VideoCommon::ImageInfo& info) { |
| 269 | if (IsPixelFormatASTC(info.format) && !runtime.HasNativeASTC()) { | 268 | if (IsPixelFormatASTC(info.format) && !runtime.HasNativeASTC()) { |
| 270 | return Settings::values.async_astc.GetValue(); | 269 | return Settings::values.accelerate_astc.GetValue() == |
| 270 | Settings::AstcDecodeMode::CpuAsynchronous; | ||
| 271 | } | 271 | } |
| 272 | return false; | 272 | return false; |
| 273 | } | 273 | } |
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index 2a74c1d05..6b8d4e554 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp | |||
| @@ -473,7 +473,7 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) { | |||
| 473 | glBindTextureUnit(0, screen_info.display_texture); | 473 | glBindTextureUnit(0, screen_info.display_texture); |
| 474 | 474 | ||
| 475 | auto anti_aliasing = Settings::values.anti_aliasing.GetValue(); | 475 | auto anti_aliasing = Settings::values.anti_aliasing.GetValue(); |
| 476 | if (anti_aliasing > Settings::AntiAliasing::LastAA) { | 476 | if (anti_aliasing >= Settings::AntiAliasing::MaxEnum) { |
| 477 | LOG_ERROR(Render_OpenGL, "Invalid antialiasing option selected {}", anti_aliasing); | 477 | LOG_ERROR(Render_OpenGL, "Invalid antialiasing option selected {}", anti_aliasing); |
| 478 | anti_aliasing = Settings::AntiAliasing::None; | 478 | anti_aliasing = Settings::AntiAliasing::None; |
| 479 | Settings::values.anti_aliasing.SetValue(anti_aliasing); | 479 | Settings::values.anti_aliasing.SetValue(anti_aliasing); |
diff --git a/src/video_core/renderer_vulkan/vk_swapchain.cpp b/src/video_core/renderer_vulkan/vk_swapchain.cpp index d3cddac69..81ef98f61 100644 --- a/src/video_core/renderer_vulkan/vk_swapchain.cpp +++ b/src/video_core/renderer_vulkan/vk_swapchain.cpp | |||
| @@ -45,8 +45,8 @@ static VkPresentModeKHR ChooseSwapPresentMode(bool has_imm, bool has_mailbox, | |||
| 45 | return mode; | 45 | return mode; |
| 46 | } | 46 | } |
| 47 | switch (mode) { | 47 | switch (mode) { |
| 48 | case Settings::VSyncMode::FIFO: | 48 | case Settings::VSyncMode::Fifo: |
| 49 | case Settings::VSyncMode::FIFORelaxed: | 49 | case Settings::VSyncMode::FifoRelaxed: |
| 50 | if (has_mailbox) { | 50 | if (has_mailbox) { |
| 51 | return Settings::VSyncMode::Mailbox; | 51 | return Settings::VSyncMode::Mailbox; |
| 52 | } else if (has_imm) { | 52 | } else if (has_imm) { |
| @@ -59,8 +59,8 @@ static VkPresentModeKHR ChooseSwapPresentMode(bool has_imm, bool has_mailbox, | |||
| 59 | }(); | 59 | }(); |
| 60 | if ((setting == Settings::VSyncMode::Mailbox && !has_mailbox) || | 60 | if ((setting == Settings::VSyncMode::Mailbox && !has_mailbox) || |
| 61 | (setting == Settings::VSyncMode::Immediate && !has_imm) || | 61 | (setting == Settings::VSyncMode::Immediate && !has_imm) || |
| 62 | (setting == Settings::VSyncMode::FIFORelaxed && !has_fifo_relaxed)) { | 62 | (setting == Settings::VSyncMode::FifoRelaxed && !has_fifo_relaxed)) { |
| 63 | setting = Settings::VSyncMode::FIFO; | 63 | setting = Settings::VSyncMode::Fifo; |
| 64 | } | 64 | } |
| 65 | 65 | ||
| 66 | switch (setting) { | 66 | switch (setting) { |
| @@ -68,9 +68,9 @@ static VkPresentModeKHR ChooseSwapPresentMode(bool has_imm, bool has_mailbox, | |||
| 68 | return VK_PRESENT_MODE_IMMEDIATE_KHR; | 68 | return VK_PRESENT_MODE_IMMEDIATE_KHR; |
| 69 | case Settings::VSyncMode::Mailbox: | 69 | case Settings::VSyncMode::Mailbox: |
| 70 | return VK_PRESENT_MODE_MAILBOX_KHR; | 70 | return VK_PRESENT_MODE_MAILBOX_KHR; |
| 71 | case Settings::VSyncMode::FIFO: | 71 | case Settings::VSyncMode::Fifo: |
| 72 | return VK_PRESENT_MODE_FIFO_KHR; | 72 | return VK_PRESENT_MODE_FIFO_KHR; |
| 73 | case Settings::VSyncMode::FIFORelaxed: | 73 | case Settings::VSyncMode::FifoRelaxed: |
| 74 | return VK_PRESENT_MODE_FIFO_RELAXED_KHR; | 74 | return VK_PRESENT_MODE_FIFO_RELAXED_KHR; |
| 75 | default: | 75 | default: |
| 76 | return VK_PRESENT_MODE_FIFO_KHR; | 76 | return VK_PRESENT_MODE_FIFO_KHR; |
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index bf6ad6c79..53d749bd4 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp | |||
| @@ -817,7 +817,7 @@ TextureCacheRuntime::TextureCacheRuntime(const Device& device_, Scheduler& sched | |||
| 817 | : device{device_}, scheduler{scheduler_}, memory_allocator{memory_allocator_}, | 817 | : device{device_}, scheduler{scheduler_}, memory_allocator{memory_allocator_}, |
| 818 | staging_buffer_pool{staging_buffer_pool_}, blit_image_helper{blit_image_helper_}, | 818 | staging_buffer_pool{staging_buffer_pool_}, blit_image_helper{blit_image_helper_}, |
| 819 | render_pass_cache{render_pass_cache_}, resolution{Settings::values.resolution_info} { | 819 | render_pass_cache{render_pass_cache_}, resolution{Settings::values.resolution_info} { |
| 820 | if (Settings::values.accelerate_astc) { | 820 | if (Settings::values.accelerate_astc.GetValue() == Settings::AstcDecodeMode::Gpu) { |
| 821 | astc_decoder_pass.emplace(device, scheduler, descriptor_pool, staging_buffer_pool, | 821 | astc_decoder_pass.emplace(device, scheduler, descriptor_pool, staging_buffer_pool, |
| 822 | compute_pass_descriptor_queue, memory_allocator); | 822 | compute_pass_descriptor_queue, memory_allocator); |
| 823 | } | 823 | } |
| @@ -1301,12 +1301,19 @@ Image::Image(TextureCacheRuntime& runtime_, const ImageInfo& info_, GPUVAddr gpu | |||
| 1301 | runtime->ViewFormats(info.format))), | 1301 | runtime->ViewFormats(info.format))), |
| 1302 | aspect_mask(ImageAspectMask(info.format)) { | 1302 | aspect_mask(ImageAspectMask(info.format)) { |
| 1303 | if (IsPixelFormatASTC(info.format) && !runtime->device.IsOptimalAstcSupported()) { | 1303 | if (IsPixelFormatASTC(info.format) && !runtime->device.IsOptimalAstcSupported()) { |
| 1304 | if (Settings::values.async_astc.GetValue()) { | 1304 | switch (Settings::values.accelerate_astc.GetValue()) { |
| 1305 | case Settings::AstcDecodeMode::Gpu: | ||
| 1306 | if (Settings::values.astc_recompression.GetValue() == | ||
| 1307 | Settings::AstcRecompression::Uncompressed && | ||
| 1308 | info.size.depth == 1) { | ||
| 1309 | flags |= VideoCommon::ImageFlagBits::AcceleratedUpload; | ||
| 1310 | } | ||
| 1311 | break; | ||
| 1312 | case Settings::AstcDecodeMode::CpuAsynchronous: | ||
| 1305 | flags |= VideoCommon::ImageFlagBits::AsynchronousDecode; | 1313 | flags |= VideoCommon::ImageFlagBits::AsynchronousDecode; |
| 1306 | } else if (Settings::values.astc_recompression.GetValue() == | 1314 | break; |
| 1307 | Settings::AstcRecompression::Uncompressed && | 1315 | default: |
| 1308 | Settings::values.accelerate_astc.GetValue() && info.size.depth == 1) { | 1316 | break; |
| 1309 | flags |= VideoCommon::ImageFlagBits::AcceleratedUpload; | ||
| 1310 | } | 1317 | } |
| 1311 | flags |= VideoCommon::ImageFlagBits::Converted; | 1318 | flags |= VideoCommon::ImageFlagBits::Converted; |
| 1312 | flags |= VideoCommon::ImageFlagBits::CostlyLoad; | 1319 | flags |= VideoCommon::ImageFlagBits::CostlyLoad; |
diff --git a/src/video_core/textures/texture.cpp b/src/video_core/textures/texture.cpp index d8b88d9bc..39c08b5ae 100644 --- a/src/video_core/textures/texture.cpp +++ b/src/video_core/textures/texture.cpp | |||
| @@ -72,12 +72,12 @@ float TSCEntry::MaxAnisotropy() const noexcept { | |||
| 72 | } | 72 | } |
| 73 | const auto anisotropic_settings = Settings::values.max_anisotropy.GetValue(); | 73 | const auto anisotropic_settings = Settings::values.max_anisotropy.GetValue(); |
| 74 | s32 added_anisotropic{}; | 74 | s32 added_anisotropic{}; |
| 75 | if (anisotropic_settings == 0) { | 75 | if (anisotropic_settings == Settings::AnisotropyMode::Automatic) { |
| 76 | added_anisotropic = Settings::values.resolution_info.up_scale >> | 76 | added_anisotropic = Settings::values.resolution_info.up_scale >> |
| 77 | Settings::values.resolution_info.down_shift; | 77 | Settings::values.resolution_info.down_shift; |
| 78 | added_anisotropic = std::max(added_anisotropic - 1, 0); | 78 | added_anisotropic = std::max(added_anisotropic - 1, 0); |
| 79 | } else { | 79 | } else { |
| 80 | added_anisotropic = Settings::values.max_anisotropy.GetValue() - 1U; | 80 | added_anisotropic = static_cast<u32>(Settings::values.max_anisotropy.GetValue()) - 1U; |
| 81 | } | 81 | } |
| 82 | return static_cast<float>(1U << (max_anisotropy + added_anisotropic)); | 82 | return static_cast<float>(1U << (max_anisotropy + added_anisotropic)); |
| 83 | } | 83 | } |
diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index fe98e3605..2e4da696c 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt | |||
| @@ -143,6 +143,10 @@ add_executable(yuzu | |||
| 143 | configuration/configure_web.ui | 143 | configuration/configure_web.ui |
| 144 | configuration/input_profiles.cpp | 144 | configuration/input_profiles.cpp |
| 145 | configuration/input_profiles.h | 145 | configuration/input_profiles.h |
| 146 | configuration/shared_translation.cpp | ||
| 147 | configuration/shared_translation.h | ||
| 148 | configuration/shared_widget.cpp | ||
| 149 | configuration/shared_widget.h | ||
| 146 | debugger/console.cpp | 150 | debugger/console.cpp |
| 147 | debugger/console.h | 151 | debugger/console.h |
| 148 | debugger/controller.cpp | 152 | debugger/controller.cpp |
| @@ -231,6 +235,12 @@ if (WIN32 AND YUZU_CRASH_DUMPS) | |||
| 231 | target_compile_definitions(yuzu PRIVATE -DYUZU_DBGHELP) | 235 | target_compile_definitions(yuzu PRIVATE -DYUZU_DBGHELP) |
| 232 | endif() | 236 | endif() |
| 233 | 237 | ||
| 238 | if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") | ||
| 239 | target_compile_definitions(yuzu PRIVATE | ||
| 240 | $<$<VERSION_LESS:$<CXX_COMPILER_VERSION>,15>:CANNOT_EXPLICITLY_INSTANTIATE> | ||
| 241 | ) | ||
| 242 | endif() | ||
| 243 | |||
| 234 | file(GLOB COMPAT_LIST | 244 | file(GLOB COMPAT_LIST |
| 235 | ${PROJECT_BINARY_DIR}/dist/compatibility_list/compatibility_list.qrc | 245 | ${PROJECT_BINARY_DIR}/dist/compatibility_list/compatibility_list.qrc |
| 236 | ${PROJECT_BINARY_DIR}/dist/compatibility_list/compatibility_list.json) | 246 | ${PROJECT_BINARY_DIR}/dist/compatibility_list/compatibility_list.json) |
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index 195d3556c..b2405f9b8 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp | |||
| @@ -1,12 +1,14 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2014 Citra Emulator Project | 1 | // SPDX-FileCopyrightText: 2014 Citra Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include <algorithm> | ||
| 4 | #include <array> | 5 | #include <array> |
| 5 | #include <QKeySequence> | 6 | #include <QKeySequence> |
| 6 | #include <QSettings> | 7 | #include <QSettings> |
| 7 | #include "common/fs/fs.h" | 8 | #include "common/fs/fs.h" |
| 8 | #include "common/fs/path_util.h" | 9 | #include "common/fs/path_util.h" |
| 9 | #include "common/settings.h" | 10 | #include "common/settings.h" |
| 11 | #include "common/settings_common.h" | ||
| 10 | #include "core/core.h" | 12 | #include "core/core.h" |
| 11 | #include "core/hle/service/acc/profile_manager.h" | 13 | #include "core/hle/service/acc/profile_manager.h" |
| 12 | #include "core/hle/service/hid/controllers/npad.h" | 14 | #include "core/hle/service/hid/controllers/npad.h" |
| @@ -16,9 +18,8 @@ | |||
| 16 | 18 | ||
| 17 | namespace FS = Common::FS; | 19 | namespace FS = Common::FS; |
| 18 | 20 | ||
| 19 | Config::Config(const std::string& config_name, ConfigType config_type) : type(config_type) { | 21 | Config::Config(const std::string& config_name, ConfigType config_type) |
| 20 | global = config_type == ConfigType::GlobalConfig; | 22 | : type(config_type), global{config_type == ConfigType::GlobalConfig} { |
| 21 | |||
| 22 | Initialize(config_name); | 23 | Initialize(config_name); |
| 23 | } | 24 | } |
| 24 | 25 | ||
| @@ -89,10 +90,10 @@ const std::map<bool, QString> Config::use_docked_mode_texts_map = { | |||
| 89 | {false, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Handheld"))}, | 90 | {false, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Handheld"))}, |
| 90 | }; | 91 | }; |
| 91 | 92 | ||
| 92 | const std::map<Settings::GPUAccuracy, QString> Config::gpu_accuracy_texts_map = { | 93 | const std::map<Settings::GpuAccuracy, QString> Config::gpu_accuracy_texts_map = { |
| 93 | {Settings::GPUAccuracy::Normal, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Normal"))}, | 94 | {Settings::GpuAccuracy::Normal, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Normal"))}, |
| 94 | {Settings::GPUAccuracy::High, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "High"))}, | 95 | {Settings::GpuAccuracy::High, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "High"))}, |
| 95 | {Settings::GPUAccuracy::Extreme, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Extreme"))}, | 96 | {Settings::GpuAccuracy::Extreme, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Extreme"))}, |
| 96 | }; | 97 | }; |
| 97 | 98 | ||
| 98 | const std::map<Settings::RendererBackend, QString> Config::renderer_backend_texts_map = { | 99 | const std::map<Settings::RendererBackend, QString> Config::renderer_backend_texts_map = { |
| @@ -102,9 +103,9 @@ const std::map<Settings::RendererBackend, QString> Config::renderer_backend_text | |||
| 102 | }; | 103 | }; |
| 103 | 104 | ||
| 104 | const std::map<Settings::ShaderBackend, QString> Config::shader_backend_texts_map = { | 105 | const std::map<Settings::ShaderBackend, QString> Config::shader_backend_texts_map = { |
| 105 | {Settings::ShaderBackend::GLSL, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "GLSL"))}, | 106 | {Settings::ShaderBackend::Glsl, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "GLSL"))}, |
| 106 | {Settings::ShaderBackend::GLASM, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "GLASM"))}, | 107 | {Settings::ShaderBackend::Glasm, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "GLASM"))}, |
| 107 | {Settings::ShaderBackend::SPIRV, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "SPIRV"))}, | 108 | {Settings::ShaderBackend::SpirV, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "SPIRV"))}, |
| 108 | }; | 109 | }; |
| 109 | 110 | ||
| 110 | // This shouldn't have anything except static initializers (no functions). So | 111 | // This shouldn't have anything except static initializers (no functions). So |
| @@ -171,66 +172,6 @@ bool Config::IsCustomConfig() { | |||
| 171 | return type == ConfigType::PerGameConfig; | 172 | return type == ConfigType::PerGameConfig; |
| 172 | } | 173 | } |
| 173 | 174 | ||
| 174 | /* {Read,Write}BasicSetting and WriteGlobalSetting templates must be defined here before their | ||
| 175 | * usages later in this file. This allows explicit definition of some types that don't work | ||
| 176 | * nicely with the general version. | ||
| 177 | */ | ||
| 178 | |||
| 179 | // Explicit std::string definition: Qt can't implicitly convert a std::string to a QVariant, nor | ||
| 180 | // can it implicitly convert a QVariant back to a {std::,Q}string | ||
| 181 | template <> | ||
| 182 | void Config::ReadBasicSetting(Settings::Setting<std::string>& setting) { | ||
| 183 | const QString name = QString::fromStdString(setting.GetLabel()); | ||
| 184 | const auto default_value = QString::fromStdString(setting.GetDefault()); | ||
| 185 | if (qt_config->value(name + QStringLiteral("/default"), false).toBool()) { | ||
| 186 | setting.SetValue(default_value.toStdString()); | ||
| 187 | } else { | ||
| 188 | setting.SetValue(qt_config->value(name, default_value).toString().toStdString()); | ||
| 189 | } | ||
| 190 | } | ||
| 191 | |||
| 192 | template <typename Type, bool ranged> | ||
| 193 | void Config::ReadBasicSetting(Settings::Setting<Type, ranged>& setting) { | ||
| 194 | const QString name = QString::fromStdString(setting.GetLabel()); | ||
| 195 | const Type default_value = setting.GetDefault(); | ||
| 196 | if (qt_config->value(name + QStringLiteral("/default"), false).toBool()) { | ||
| 197 | setting.SetValue(default_value); | ||
| 198 | } else { | ||
| 199 | setting.SetValue( | ||
| 200 | static_cast<QVariant>(qt_config->value(name, default_value)).value<Type>()); | ||
| 201 | } | ||
| 202 | } | ||
| 203 | |||
| 204 | // Explicit std::string definition: Qt can't implicitly convert a std::string to a QVariant | ||
| 205 | template <> | ||
| 206 | void Config::WriteBasicSetting(const Settings::Setting<std::string>& setting) { | ||
| 207 | const QString name = QString::fromStdString(setting.GetLabel()); | ||
| 208 | const std::string& value = setting.GetValue(); | ||
| 209 | qt_config->setValue(name + QStringLiteral("/default"), value == setting.GetDefault()); | ||
| 210 | qt_config->setValue(name, QString::fromStdString(value)); | ||
| 211 | } | ||
| 212 | |||
| 213 | template <typename Type, bool ranged> | ||
| 214 | void Config::WriteBasicSetting(const Settings::Setting<Type, ranged>& setting) { | ||
| 215 | const QString name = QString::fromStdString(setting.GetLabel()); | ||
| 216 | const Type value = setting.GetValue(); | ||
| 217 | qt_config->setValue(name + QStringLiteral("/default"), value == setting.GetDefault()); | ||
| 218 | qt_config->setValue(name, value); | ||
| 219 | } | ||
| 220 | |||
| 221 | template <typename Type, bool ranged> | ||
| 222 | void Config::WriteGlobalSetting(const Settings::SwitchableSetting<Type, ranged>& setting) { | ||
| 223 | const QString name = QString::fromStdString(setting.GetLabel()); | ||
| 224 | const Type& value = setting.GetValue(global); | ||
| 225 | if (!global) { | ||
| 226 | qt_config->setValue(name + QStringLiteral("/use_global"), setting.UsingGlobal()); | ||
| 227 | } | ||
| 228 | if (global || !setting.UsingGlobal()) { | ||
| 229 | qt_config->setValue(name + QStringLiteral("/default"), value == setting.GetDefault()); | ||
| 230 | qt_config->setValue(name, value); | ||
| 231 | } | ||
| 232 | } | ||
| 233 | |||
| 234 | void Config::ReadPlayerValue(std::size_t player_index) { | 175 | void Config::ReadPlayerValue(std::size_t player_index) { |
| 235 | const QString player_prefix = [this, player_index] { | 176 | const QString player_prefix = [this, player_index] { |
| 236 | if (type == ConfigType::InputProfile) { | 177 | if (type == ConfigType::InputProfile) { |
| @@ -351,15 +292,9 @@ void Config::ReadPlayerValue(std::size_t player_index) { | |||
| 351 | player_motions = default_param; | 292 | player_motions = default_param; |
| 352 | } | 293 | } |
| 353 | } | 294 | } |
| 354 | |||
| 355 | if (player_index == 0) { | ||
| 356 | ReadMousePanningValues(); | ||
| 357 | } | ||
| 358 | } | 295 | } |
| 359 | 296 | ||
| 360 | void Config::ReadDebugValues() { | 297 | void Config::ReadDebugValues() { |
| 361 | ReadBasicSetting(Settings::values.debug_pad_enabled); | ||
| 362 | |||
| 363 | for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { | 298 | for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { |
| 364 | const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); | 299 | const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); |
| 365 | auto& debug_pad_buttons = Settings::values.debug_pad_buttons[i]; | 300 | auto& debug_pad_buttons = Settings::values.debug_pad_buttons[i]; |
| @@ -393,14 +328,6 @@ void Config::ReadDebugValues() { | |||
| 393 | } | 328 | } |
| 394 | } | 329 | } |
| 395 | 330 | ||
| 396 | void Config::ReadKeyboardValues() { | ||
| 397 | ReadBasicSetting(Settings::values.keyboard_enabled); | ||
| 398 | } | ||
| 399 | |||
| 400 | void Config::ReadMouseValues() { | ||
| 401 | ReadBasicSetting(Settings::values.mouse_enabled); | ||
| 402 | } | ||
| 403 | |||
| 404 | void Config::ReadTouchscreenValues() { | 331 | void Config::ReadTouchscreenValues() { |
| 405 | Settings::values.touchscreen.enabled = | 332 | Settings::values.touchscreen.enabled = |
| 406 | ReadSetting(QStringLiteral("touchscreen_enabled"), true).toBool(); | 333 | ReadSetting(QStringLiteral("touchscreen_enabled"), true).toBool(); |
| @@ -414,9 +341,6 @@ void Config::ReadTouchscreenValues() { | |||
| 414 | } | 341 | } |
| 415 | 342 | ||
| 416 | void Config::ReadHidbusValues() { | 343 | void Config::ReadHidbusValues() { |
| 417 | Settings::values.enable_ring_controller = | ||
| 418 | ReadSetting(QStringLiteral("enable_ring_controller"), true).toBool(); | ||
| 419 | |||
| 420 | const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( | 344 | const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( |
| 421 | 0, 0, default_ringcon_analogs[0], default_ringcon_analogs[1], 0, 0.05f); | 345 | 0, 0, default_ringcon_analogs[0], default_ringcon_analogs[1], 0, 0.05f); |
| 422 | auto& ringcon_analogs = Settings::values.ringcon_analogs; | 346 | auto& ringcon_analogs = Settings::values.ringcon_analogs; |
| @@ -430,20 +354,10 @@ void Config::ReadHidbusValues() { | |||
| 430 | } | 354 | } |
| 431 | } | 355 | } |
| 432 | 356 | ||
| 433 | void Config::ReadIrCameraValues() { | ||
| 434 | ReadBasicSetting(Settings::values.enable_ir_sensor); | ||
| 435 | ReadBasicSetting(Settings::values.ir_sensor_device); | ||
| 436 | } | ||
| 437 | |||
| 438 | void Config::ReadAudioValues() { | 357 | void Config::ReadAudioValues() { |
| 439 | qt_config->beginGroup(QStringLiteral("Audio")); | 358 | qt_config->beginGroup(QStringLiteral("Audio")); |
| 440 | 359 | ||
| 441 | if (global) { | 360 | ReadCategory(Settings::Category::Audio); |
| 442 | ReadBasicSetting(Settings::values.sink_id); | ||
| 443 | ReadBasicSetting(Settings::values.audio_output_device_id); | ||
| 444 | ReadBasicSetting(Settings::values.audio_input_device_id); | ||
| 445 | } | ||
| 446 | ReadGlobalSetting(Settings::values.volume); | ||
| 447 | 361 | ||
| 448 | qt_config->endGroup(); | 362 | qt_config->endGroup(); |
| 449 | } | 363 | } |
| @@ -451,11 +365,12 @@ void Config::ReadAudioValues() { | |||
| 451 | void Config::ReadControlValues() { | 365 | void Config::ReadControlValues() { |
| 452 | qt_config->beginGroup(QStringLiteral("Controls")); | 366 | qt_config->beginGroup(QStringLiteral("Controls")); |
| 453 | 367 | ||
| 368 | ReadCategory(Settings::Category::Controls); | ||
| 369 | |||
| 454 | Settings::values.players.SetGlobal(!IsCustomConfig()); | 370 | Settings::values.players.SetGlobal(!IsCustomConfig()); |
| 455 | for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) { | 371 | for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) { |
| 456 | ReadPlayerValue(p); | 372 | ReadPlayerValue(p); |
| 457 | } | 373 | } |
| 458 | ReadGlobalSetting(Settings::values.use_docked_mode); | ||
| 459 | 374 | ||
| 460 | // Disable docked mode if handheld is selected | 375 | // Disable docked mode if handheld is selected |
| 461 | const auto controller_type = Settings::values.players.GetValue()[0].controller_type; | 376 | const auto controller_type = Settings::values.players.GetValue()[0].controller_type; |
| @@ -464,50 +379,18 @@ void Config::ReadControlValues() { | |||
| 464 | Settings::values.use_docked_mode.SetValue(false); | 379 | Settings::values.use_docked_mode.SetValue(false); |
| 465 | } | 380 | } |
| 466 | 381 | ||
| 467 | ReadGlobalSetting(Settings::values.vibration_enabled); | ||
| 468 | ReadGlobalSetting(Settings::values.enable_accurate_vibrations); | ||
| 469 | ReadGlobalSetting(Settings::values.motion_enabled); | ||
| 470 | if (IsCustomConfig()) { | 382 | if (IsCustomConfig()) { |
| 471 | qt_config->endGroup(); | 383 | qt_config->endGroup(); |
| 472 | return; | 384 | return; |
| 473 | } | 385 | } |
| 474 | ReadDebugValues(); | 386 | ReadDebugValues(); |
| 475 | ReadKeyboardValues(); | ||
| 476 | ReadMouseValues(); | ||
| 477 | ReadTouchscreenValues(); | 387 | ReadTouchscreenValues(); |
| 478 | ReadMousePanningValues(); | ||
| 479 | ReadMotionTouchValues(); | 388 | ReadMotionTouchValues(); |
| 480 | ReadHidbusValues(); | 389 | ReadHidbusValues(); |
| 481 | ReadIrCameraValues(); | ||
| 482 | |||
| 483 | #ifdef _WIN32 | ||
| 484 | ReadBasicSetting(Settings::values.enable_raw_input); | ||
| 485 | #else | ||
| 486 | Settings::values.enable_raw_input = false; | ||
| 487 | #endif | ||
| 488 | ReadBasicSetting(Settings::values.emulate_analog_keyboard); | ||
| 489 | ReadBasicSetting(Settings::values.enable_joycon_driver); | ||
| 490 | ReadBasicSetting(Settings::values.enable_procon_driver); | ||
| 491 | ReadBasicSetting(Settings::values.random_amiibo_id); | ||
| 492 | |||
| 493 | ReadBasicSetting(Settings::values.tas_enable); | ||
| 494 | ReadBasicSetting(Settings::values.tas_loop); | ||
| 495 | ReadBasicSetting(Settings::values.pause_tas_on_load); | ||
| 496 | |||
| 497 | ReadBasicSetting(Settings::values.controller_navigation); | ||
| 498 | 390 | ||
| 499 | qt_config->endGroup(); | 391 | qt_config->endGroup(); |
| 500 | } | 392 | } |
| 501 | 393 | ||
| 502 | void Config::ReadMousePanningValues() { | ||
| 503 | ReadBasicSetting(Settings::values.mouse_panning); | ||
| 504 | ReadBasicSetting(Settings::values.mouse_panning_x_sensitivity); | ||
| 505 | ReadBasicSetting(Settings::values.mouse_panning_y_sensitivity); | ||
| 506 | ReadBasicSetting(Settings::values.mouse_panning_deadzone_counterweight); | ||
| 507 | ReadBasicSetting(Settings::values.mouse_panning_decay_strength); | ||
| 508 | ReadBasicSetting(Settings::values.mouse_panning_min_decay); | ||
| 509 | } | ||
| 510 | |||
| 511 | void Config::ReadMotionTouchValues() { | 394 | void Config::ReadMotionTouchValues() { |
| 512 | int num_touch_from_button_maps = | 395 | int num_touch_from_button_maps = |
| 513 | qt_config->beginReadArray(QStringLiteral("touch_from_button_maps")); | 396 | qt_config->beginReadArray(QStringLiteral("touch_from_button_maps")); |
| @@ -541,19 +424,14 @@ void Config::ReadMotionTouchValues() { | |||
| 541 | } | 424 | } |
| 542 | qt_config->endArray(); | 425 | qt_config->endArray(); |
| 543 | 426 | ||
| 544 | ReadBasicSetting(Settings::values.touch_device); | ||
| 545 | ReadBasicSetting(Settings::values.touch_from_button_map_index); | ||
| 546 | Settings::values.touch_from_button_map_index = std::clamp( | 427 | Settings::values.touch_from_button_map_index = std::clamp( |
| 547 | Settings::values.touch_from_button_map_index.GetValue(), 0, num_touch_from_button_maps - 1); | 428 | Settings::values.touch_from_button_map_index.GetValue(), 0, num_touch_from_button_maps - 1); |
| 548 | ReadBasicSetting(Settings::values.udp_input_servers); | ||
| 549 | ReadBasicSetting(Settings::values.enable_udp_controller); | ||
| 550 | } | 429 | } |
| 551 | 430 | ||
| 552 | void Config::ReadCoreValues() { | 431 | void Config::ReadCoreValues() { |
| 553 | qt_config->beginGroup(QStringLiteral("Core")); | 432 | qt_config->beginGroup(QStringLiteral("Core")); |
| 554 | 433 | ||
| 555 | ReadGlobalSetting(Settings::values.use_multi_core); | 434 | ReadCategory(Settings::Category::Core); |
| 556 | ReadGlobalSetting(Settings::values.use_unsafe_extended_memory_layout); | ||
| 557 | 435 | ||
| 558 | qt_config->endGroup(); | 436 | qt_config->endGroup(); |
| 559 | } | 437 | } |
| @@ -561,7 +439,6 @@ void Config::ReadCoreValues() { | |||
| 561 | void Config::ReadDataStorageValues() { | 439 | void Config::ReadDataStorageValues() { |
| 562 | qt_config->beginGroup(QStringLiteral("Data Storage")); | 440 | qt_config->beginGroup(QStringLiteral("Data Storage")); |
| 563 | 441 | ||
| 564 | ReadBasicSetting(Settings::values.use_virtual_sd); | ||
| 565 | FS::SetYuzuPath( | 442 | FS::SetYuzuPath( |
| 566 | FS::YuzuPath::NANDDir, | 443 | FS::YuzuPath::NANDDir, |
| 567 | qt_config | 444 | qt_config |
| @@ -597,9 +474,7 @@ void Config::ReadDataStorageValues() { | |||
| 597 | .toString() | 474 | .toString() |
| 598 | .toStdString()); | 475 | .toStdString()); |
| 599 | 476 | ||
| 600 | ReadBasicSetting(Settings::values.gamecard_inserted); | 477 | ReadCategory(Settings::Category::DataStorage); |
| 601 | ReadBasicSetting(Settings::values.gamecard_current_game); | ||
| 602 | ReadBasicSetting(Settings::values.gamecard_path); | ||
| 603 | 478 | ||
| 604 | qt_config->endGroup(); | 479 | qt_config->endGroup(); |
| 605 | } | 480 | } |
| @@ -611,29 +486,17 @@ void Config::ReadDebuggingValues() { | |||
| 611 | Settings::values.record_frame_times = | 486 | Settings::values.record_frame_times = |
| 612 | qt_config->value(QStringLiteral("record_frame_times"), false).toBool(); | 487 | qt_config->value(QStringLiteral("record_frame_times"), false).toBool(); |
| 613 | 488 | ||
| 614 | ReadBasicSetting(Settings::values.use_gdbstub); | 489 | ReadCategory(Settings::Category::Debugging); |
| 615 | ReadBasicSetting(Settings::values.gdbstub_port); | 490 | ReadCategory(Settings::Category::DebuggingGraphics); |
| 616 | ReadBasicSetting(Settings::values.program_args); | ||
| 617 | ReadBasicSetting(Settings::values.dump_exefs); | ||
| 618 | ReadBasicSetting(Settings::values.dump_nso); | ||
| 619 | ReadBasicSetting(Settings::values.enable_fs_access_log); | ||
| 620 | ReadBasicSetting(Settings::values.reporting_services); | ||
| 621 | ReadBasicSetting(Settings::values.quest_flag); | ||
| 622 | ReadBasicSetting(Settings::values.disable_macro_jit); | ||
| 623 | ReadBasicSetting(Settings::values.disable_macro_hle); | ||
| 624 | ReadBasicSetting(Settings::values.extended_logging); | ||
| 625 | ReadBasicSetting(Settings::values.use_debug_asserts); | ||
| 626 | ReadBasicSetting(Settings::values.use_auto_stub); | ||
| 627 | ReadBasicSetting(Settings::values.enable_all_controllers); | ||
| 628 | ReadBasicSetting(Settings::values.create_crash_dumps); | ||
| 629 | ReadBasicSetting(Settings::values.perform_vulkan_check); | ||
| 630 | 491 | ||
| 631 | qt_config->endGroup(); | 492 | qt_config->endGroup(); |
| 632 | } | 493 | } |
| 633 | 494 | ||
| 634 | void Config::ReadServiceValues() { | 495 | void Config::ReadServiceValues() { |
| 635 | qt_config->beginGroup(QStringLiteral("Services")); | 496 | qt_config->beginGroup(QStringLiteral("Services")); |
| 636 | ReadBasicSetting(Settings::values.network_interface); | 497 | |
| 498 | ReadCategory(Settings::Category::Services); | ||
| 499 | |||
| 637 | qt_config->endGroup(); | 500 | qt_config->endGroup(); |
| 638 | } | 501 | } |
| 639 | 502 | ||
| @@ -659,8 +522,7 @@ void Config::ReadDisabledAddOnValues() { | |||
| 659 | void Config::ReadMiscellaneousValues() { | 522 | void Config::ReadMiscellaneousValues() { |
| 660 | qt_config->beginGroup(QStringLiteral("Miscellaneous")); | 523 | qt_config->beginGroup(QStringLiteral("Miscellaneous")); |
| 661 | 524 | ||
| 662 | ReadBasicSetting(Settings::values.log_filter); | 525 | ReadCategory(Settings::Category::Miscellaneous); |
| 663 | ReadBasicSetting(Settings::values.use_dev_keys); | ||
| 664 | 526 | ||
| 665 | qt_config->endGroup(); | 527 | qt_config->endGroup(); |
| 666 | } | 528 | } |
| @@ -710,36 +572,9 @@ void Config::ReadPathValues() { | |||
| 710 | void Config::ReadCpuValues() { | 572 | void Config::ReadCpuValues() { |
| 711 | qt_config->beginGroup(QStringLiteral("Cpu")); | 573 | qt_config->beginGroup(QStringLiteral("Cpu")); |
| 712 | 574 | ||
| 713 | ReadBasicSetting(Settings::values.cpu_accuracy_first_time); | 575 | ReadCategory(Settings::Category::Cpu); |
| 714 | if (Settings::values.cpu_accuracy_first_time) { | 576 | ReadCategory(Settings::Category::CpuDebug); |
| 715 | Settings::values.cpu_accuracy.SetValue(Settings::values.cpu_accuracy.GetDefault()); | 577 | ReadCategory(Settings::Category::CpuUnsafe); |
| 716 | Settings::values.cpu_accuracy_first_time.SetValue(false); | ||
| 717 | } else { | ||
| 718 | ReadGlobalSetting(Settings::values.cpu_accuracy); | ||
| 719 | } | ||
| 720 | |||
| 721 | ReadGlobalSetting(Settings::values.cpuopt_unsafe_unfuse_fma); | ||
| 722 | ReadGlobalSetting(Settings::values.cpuopt_unsafe_reduce_fp_error); | ||
| 723 | ReadGlobalSetting(Settings::values.cpuopt_unsafe_ignore_standard_fpcr); | ||
| 724 | ReadGlobalSetting(Settings::values.cpuopt_unsafe_inaccurate_nan); | ||
| 725 | ReadGlobalSetting(Settings::values.cpuopt_unsafe_fastmem_check); | ||
| 726 | ReadGlobalSetting(Settings::values.cpuopt_unsafe_ignore_global_monitor); | ||
| 727 | |||
| 728 | if (global) { | ||
| 729 | ReadBasicSetting(Settings::values.cpu_debug_mode); | ||
| 730 | ReadBasicSetting(Settings::values.cpuopt_page_tables); | ||
| 731 | ReadBasicSetting(Settings::values.cpuopt_block_linking); | ||
| 732 | ReadBasicSetting(Settings::values.cpuopt_return_stack_buffer); | ||
| 733 | ReadBasicSetting(Settings::values.cpuopt_fast_dispatcher); | ||
| 734 | ReadBasicSetting(Settings::values.cpuopt_context_elimination); | ||
| 735 | ReadBasicSetting(Settings::values.cpuopt_const_prop); | ||
| 736 | ReadBasicSetting(Settings::values.cpuopt_misc_ir); | ||
| 737 | ReadBasicSetting(Settings::values.cpuopt_reduce_misalign_checks); | ||
| 738 | ReadBasicSetting(Settings::values.cpuopt_fastmem); | ||
| 739 | ReadBasicSetting(Settings::values.cpuopt_fastmem_exclusives); | ||
| 740 | ReadBasicSetting(Settings::values.cpuopt_recompile_exclusives); | ||
| 741 | ReadBasicSetting(Settings::values.cpuopt_ignore_memory_aborts); | ||
| 742 | } | ||
| 743 | 578 | ||
| 744 | qt_config->endGroup(); | 579 | qt_config->endGroup(); |
| 745 | } | 580 | } |
| @@ -747,47 +582,9 @@ void Config::ReadCpuValues() { | |||
| 747 | void Config::ReadRendererValues() { | 582 | void Config::ReadRendererValues() { |
| 748 | qt_config->beginGroup(QStringLiteral("Renderer")); | 583 | qt_config->beginGroup(QStringLiteral("Renderer")); |
| 749 | 584 | ||
| 750 | ReadGlobalSetting(Settings::values.renderer_backend); | 585 | ReadCategory(Settings::Category::Renderer); |
| 751 | ReadGlobalSetting(Settings::values.async_presentation); | 586 | ReadCategory(Settings::Category::RendererAdvanced); |
| 752 | ReadGlobalSetting(Settings::values.renderer_force_max_clock); | 587 | ReadCategory(Settings::Category::RendererDebug); |
| 753 | ReadGlobalSetting(Settings::values.vulkan_device); | ||
| 754 | ReadGlobalSetting(Settings::values.fullscreen_mode); | ||
| 755 | ReadGlobalSetting(Settings::values.aspect_ratio); | ||
| 756 | ReadGlobalSetting(Settings::values.resolution_setup); | ||
| 757 | ReadGlobalSetting(Settings::values.scaling_filter); | ||
| 758 | ReadGlobalSetting(Settings::values.fsr_sharpening_slider); | ||
| 759 | ReadGlobalSetting(Settings::values.anti_aliasing); | ||
| 760 | ReadGlobalSetting(Settings::values.max_anisotropy); | ||
| 761 | ReadGlobalSetting(Settings::values.speed_limit); | ||
| 762 | ReadGlobalSetting(Settings::values.use_disk_shader_cache); | ||
| 763 | ReadGlobalSetting(Settings::values.gpu_accuracy); | ||
| 764 | ReadGlobalSetting(Settings::values.use_asynchronous_gpu_emulation); | ||
| 765 | ReadGlobalSetting(Settings::values.nvdec_emulation); | ||
| 766 | ReadGlobalSetting(Settings::values.accelerate_astc); | ||
| 767 | ReadGlobalSetting(Settings::values.async_astc); | ||
| 768 | ReadGlobalSetting(Settings::values.astc_recompression); | ||
| 769 | ReadGlobalSetting(Settings::values.use_reactive_flushing); | ||
| 770 | ReadGlobalSetting(Settings::values.shader_backend); | ||
| 771 | ReadGlobalSetting(Settings::values.use_asynchronous_shaders); | ||
| 772 | ReadGlobalSetting(Settings::values.use_fast_gpu_time); | ||
| 773 | ReadGlobalSetting(Settings::values.use_vulkan_driver_pipeline_cache); | ||
| 774 | ReadGlobalSetting(Settings::values.enable_compute_pipelines); | ||
| 775 | ReadGlobalSetting(Settings::values.use_video_framerate); | ||
| 776 | ReadGlobalSetting(Settings::values.barrier_feedback_loops); | ||
| 777 | ReadGlobalSetting(Settings::values.bg_red); | ||
| 778 | ReadGlobalSetting(Settings::values.bg_green); | ||
| 779 | ReadGlobalSetting(Settings::values.bg_blue); | ||
| 780 | |||
| 781 | if (global) { | ||
| 782 | Settings::values.vsync_mode.SetValue(static_cast<Settings::VSyncMode>( | ||
| 783 | ReadSetting(QString::fromStdString(Settings::values.vsync_mode.GetLabel()), | ||
| 784 | static_cast<u32>(Settings::values.vsync_mode.GetDefault())) | ||
| 785 | .value<u32>())); | ||
| 786 | ReadBasicSetting(Settings::values.renderer_debug); | ||
| 787 | ReadBasicSetting(Settings::values.renderer_shader_feedback); | ||
| 788 | ReadBasicSetting(Settings::values.enable_nsight_aftermath); | ||
| 789 | ReadBasicSetting(Settings::values.disable_shader_loop_safety_checks); | ||
| 790 | } | ||
| 791 | 588 | ||
| 792 | qt_config->endGroup(); | 589 | qt_config->endGroup(); |
| 793 | } | 590 | } |
| @@ -834,41 +631,8 @@ void Config::ReadShortcutValues() { | |||
| 834 | void Config::ReadSystemValues() { | 631 | void Config::ReadSystemValues() { |
| 835 | qt_config->beginGroup(QStringLiteral("System")); | 632 | qt_config->beginGroup(QStringLiteral("System")); |
| 836 | 633 | ||
| 837 | ReadGlobalSetting(Settings::values.language_index); | 634 | ReadCategory(Settings::Category::System); |
| 838 | 635 | ReadCategory(Settings::Category::SystemAudio); | |
| 839 | ReadGlobalSetting(Settings::values.region_index); | ||
| 840 | |||
| 841 | ReadGlobalSetting(Settings::values.time_zone_index); | ||
| 842 | |||
| 843 | bool rng_seed_enabled; | ||
| 844 | ReadSettingGlobal(rng_seed_enabled, QStringLiteral("rng_seed_enabled"), false); | ||
| 845 | bool rng_seed_global = | ||
| 846 | global || qt_config->value(QStringLiteral("rng_seed/use_global"), true).toBool(); | ||
| 847 | Settings::values.rng_seed.SetGlobal(rng_seed_global); | ||
| 848 | if (global || !rng_seed_global) { | ||
| 849 | if (rng_seed_enabled) { | ||
| 850 | Settings::values.rng_seed.SetValue(ReadSetting(QStringLiteral("rng_seed"), 0).toUInt()); | ||
| 851 | } else { | ||
| 852 | Settings::values.rng_seed.SetValue(std::nullopt); | ||
| 853 | } | ||
| 854 | } | ||
| 855 | |||
| 856 | if (global) { | ||
| 857 | ReadBasicSetting(Settings::values.current_user); | ||
| 858 | Settings::values.current_user = std::clamp<int>(Settings::values.current_user.GetValue(), 0, | ||
| 859 | Service::Account::MAX_USERS - 1); | ||
| 860 | |||
| 861 | const auto custom_rtc_enabled = | ||
| 862 | ReadSetting(QStringLiteral("custom_rtc_enabled"), false).toBool(); | ||
| 863 | if (custom_rtc_enabled) { | ||
| 864 | Settings::values.custom_rtc = ReadSetting(QStringLiteral("custom_rtc"), 0).toLongLong(); | ||
| 865 | } else { | ||
| 866 | Settings::values.custom_rtc = std::nullopt; | ||
| 867 | } | ||
| 868 | ReadBasicSetting(Settings::values.device_name); | ||
| 869 | } | ||
| 870 | |||
| 871 | ReadGlobalSetting(Settings::values.sound_index); | ||
| 872 | 636 | ||
| 873 | qt_config->endGroup(); | 637 | qt_config->endGroup(); |
| 874 | } | 638 | } |
| @@ -881,8 +645,6 @@ void Config::ReadUIValues() { | |||
| 881 | QStringLiteral("theme"), | 645 | QStringLiteral("theme"), |
| 882 | QString::fromUtf8(UISettings::themes[static_cast<size_t>(default_theme)].second)) | 646 | QString::fromUtf8(UISettings::themes[static_cast<size_t>(default_theme)].second)) |
| 883 | .toString(); | 647 | .toString(); |
| 884 | ReadBasicSetting(UISettings::values.enable_discord_presence); | ||
| 885 | ReadBasicSetting(UISettings::values.select_user_on_boot); | ||
| 886 | 648 | ||
| 887 | ReadUIGamelistValues(); | 649 | ReadUIGamelistValues(); |
| 888 | ReadUILayoutValues(); | 650 | ReadUILayoutValues(); |
| @@ -891,20 +653,8 @@ void Config::ReadUIValues() { | |||
| 891 | ReadShortcutValues(); | 653 | ReadShortcutValues(); |
| 892 | ReadMultiplayerValues(); | 654 | ReadMultiplayerValues(); |
| 893 | 655 | ||
| 894 | ReadBasicSetting(UISettings::values.single_window_mode); | 656 | ReadCategory(Settings::Category::Ui); |
| 895 | ReadBasicSetting(UISettings::values.fullscreen); | 657 | ReadCategory(Settings::Category::UiGeneral); |
| 896 | ReadBasicSetting(UISettings::values.display_titlebar); | ||
| 897 | ReadBasicSetting(UISettings::values.show_filter_bar); | ||
| 898 | ReadBasicSetting(UISettings::values.show_status_bar); | ||
| 899 | ReadBasicSetting(UISettings::values.confirm_before_closing); | ||
| 900 | ReadBasicSetting(UISettings::values.first_start); | ||
| 901 | ReadBasicSetting(UISettings::values.callout_flags); | ||
| 902 | ReadBasicSetting(UISettings::values.show_console); | ||
| 903 | ReadBasicSetting(UISettings::values.pause_when_in_background); | ||
| 904 | ReadBasicSetting(UISettings::values.mute_when_in_background); | ||
| 905 | ReadBasicSetting(UISettings::values.hide_mouse); | ||
| 906 | ReadBasicSetting(UISettings::values.controller_applet_disabled); | ||
| 907 | ReadBasicSetting(UISettings::values.disable_web_applet); | ||
| 908 | 658 | ||
| 909 | qt_config->endGroup(); | 659 | qt_config->endGroup(); |
| 910 | } | 660 | } |
| @@ -912,16 +662,8 @@ void Config::ReadUIValues() { | |||
| 912 | void Config::ReadUIGamelistValues() { | 662 | void Config::ReadUIGamelistValues() { |
| 913 | qt_config->beginGroup(QStringLiteral("UIGameList")); | 663 | qt_config->beginGroup(QStringLiteral("UIGameList")); |
| 914 | 664 | ||
| 915 | ReadBasicSetting(UISettings::values.show_add_ons); | 665 | ReadCategory(Settings::Category::UiGameList); |
| 916 | ReadBasicSetting(UISettings::values.show_compat); | 666 | |
| 917 | ReadBasicSetting(UISettings::values.show_size); | ||
| 918 | ReadBasicSetting(UISettings::values.show_types); | ||
| 919 | ReadBasicSetting(UISettings::values.game_icon_size); | ||
| 920 | ReadBasicSetting(UISettings::values.folder_icon_size); | ||
| 921 | ReadBasicSetting(UISettings::values.row_1_text_id); | ||
| 922 | ReadBasicSetting(UISettings::values.row_2_text_id); | ||
| 923 | ReadBasicSetting(UISettings::values.cache_game_list); | ||
| 924 | ReadBasicSetting(UISettings::values.favorites_expanded); | ||
| 925 | const int favorites_size = qt_config->beginReadArray(QStringLiteral("favorites")); | 667 | const int favorites_size = qt_config->beginReadArray(QStringLiteral("favorites")); |
| 926 | for (int i = 0; i < favorites_size; i++) { | 668 | for (int i = 0; i < favorites_size; i++) { |
| 927 | qt_config->setArrayIndex(i); | 669 | qt_config->setArrayIndex(i); |
| @@ -944,7 +686,8 @@ void Config::ReadUILayoutValues() { | |||
| 944 | ReadSetting(QStringLiteral("gameListHeaderState")).toByteArray(); | 686 | ReadSetting(QStringLiteral("gameListHeaderState")).toByteArray(); |
| 945 | UISettings::values.microprofile_geometry = | 687 | UISettings::values.microprofile_geometry = |
| 946 | ReadSetting(QStringLiteral("microProfileDialogGeometry")).toByteArray(); | 688 | ReadSetting(QStringLiteral("microProfileDialogGeometry")).toByteArray(); |
| 947 | ReadBasicSetting(UISettings::values.microprofile_visible); | 689 | |
| 690 | ReadCategory(Settings::Category::UiLayout); | ||
| 948 | 691 | ||
| 949 | qt_config->endGroup(); | 692 | qt_config->endGroup(); |
| 950 | } | 693 | } |
| @@ -952,10 +695,7 @@ void Config::ReadUILayoutValues() { | |||
| 952 | void Config::ReadWebServiceValues() { | 695 | void Config::ReadWebServiceValues() { |
| 953 | qt_config->beginGroup(QStringLiteral("WebService")); | 696 | qt_config->beginGroup(QStringLiteral("WebService")); |
| 954 | 697 | ||
| 955 | ReadBasicSetting(Settings::values.enable_telemetry); | 698 | ReadCategory(Settings::Category::WebService); |
| 956 | ReadBasicSetting(Settings::values.web_api_url); | ||
| 957 | ReadBasicSetting(Settings::values.yuzu_username); | ||
| 958 | ReadBasicSetting(Settings::values.yuzu_token); | ||
| 959 | 699 | ||
| 960 | qt_config->endGroup(); | 700 | qt_config->endGroup(); |
| 961 | } | 701 | } |
| @@ -963,17 +703,7 @@ void Config::ReadWebServiceValues() { | |||
| 963 | void Config::ReadMultiplayerValues() { | 703 | void Config::ReadMultiplayerValues() { |
| 964 | qt_config->beginGroup(QStringLiteral("Multiplayer")); | 704 | qt_config->beginGroup(QStringLiteral("Multiplayer")); |
| 965 | 705 | ||
| 966 | ReadBasicSetting(UISettings::values.multiplayer_nickname); | 706 | ReadCategory(Settings::Category::Multiplayer); |
| 967 | ReadBasicSetting(UISettings::values.multiplayer_ip); | ||
| 968 | ReadBasicSetting(UISettings::values.multiplayer_port); | ||
| 969 | ReadBasicSetting(UISettings::values.multiplayer_room_nickname); | ||
| 970 | ReadBasicSetting(UISettings::values.multiplayer_room_name); | ||
| 971 | ReadBasicSetting(UISettings::values.multiplayer_room_port); | ||
| 972 | ReadBasicSetting(UISettings::values.multiplayer_host_type); | ||
| 973 | ReadBasicSetting(UISettings::values.multiplayer_port); | ||
| 974 | ReadBasicSetting(UISettings::values.multiplayer_max_player); | ||
| 975 | ReadBasicSetting(UISettings::values.multiplayer_game_id); | ||
| 976 | ReadBasicSetting(UISettings::values.multiplayer_room_description); | ||
| 977 | 707 | ||
| 978 | // Read ban list back | 708 | // Read ban list back |
| 979 | int size = qt_config->beginReadArray(QStringLiteral("username_ban_list")); | 709 | int size = qt_config->beginReadArray(QStringLiteral("username_ban_list")); |
| @@ -996,11 +726,20 @@ void Config::ReadMultiplayerValues() { | |||
| 996 | qt_config->endGroup(); | 726 | qt_config->endGroup(); |
| 997 | } | 727 | } |
| 998 | 728 | ||
| 729 | void Config::ReadNetworkValues() { | ||
| 730 | qt_config->beginGroup(QString::fromStdString("Services")); | ||
| 731 | |||
| 732 | ReadCategory(Settings::Category::Network); | ||
| 733 | |||
| 734 | qt_config->endGroup(); | ||
| 735 | } | ||
| 736 | |||
| 999 | void Config::ReadValues() { | 737 | void Config::ReadValues() { |
| 1000 | if (global) { | 738 | if (global) { |
| 1001 | ReadDataStorageValues(); | 739 | ReadDataStorageValues(); |
| 1002 | ReadDebuggingValues(); | 740 | ReadDebuggingValues(); |
| 1003 | ReadDisabledAddOnValues(); | 741 | ReadDisabledAddOnValues(); |
| 742 | ReadNetworkValues(); | ||
| 1004 | ReadServiceValues(); | 743 | ReadServiceValues(); |
| 1005 | ReadUIValues(); | 744 | ReadUIValues(); |
| 1006 | ReadWebServiceValues(); | 745 | ReadWebServiceValues(); |
| @@ -1077,14 +816,9 @@ void Config::SavePlayerValue(std::size_t player_index) { | |||
| 1077 | QString::fromStdString(player.motions[i]), | 816 | QString::fromStdString(player.motions[i]), |
| 1078 | QString::fromStdString(default_param)); | 817 | QString::fromStdString(default_param)); |
| 1079 | } | 818 | } |
| 1080 | |||
| 1081 | if (player_index == 0) { | ||
| 1082 | SaveMousePanningValues(); | ||
| 1083 | } | ||
| 1084 | } | 819 | } |
| 1085 | 820 | ||
| 1086 | void Config::SaveDebugValues() { | 821 | void Config::SaveDebugValues() { |
| 1087 | WriteBasicSetting(Settings::values.debug_pad_enabled); | ||
| 1088 | for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { | 822 | for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { |
| 1089 | const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); | 823 | const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); |
| 1090 | WriteSetting(QStringLiteral("debug_pad_") + | 824 | WriteSetting(QStringLiteral("debug_pad_") + |
| @@ -1103,10 +837,6 @@ void Config::SaveDebugValues() { | |||
| 1103 | } | 837 | } |
| 1104 | } | 838 | } |
| 1105 | 839 | ||
| 1106 | void Config::SaveMouseValues() { | ||
| 1107 | WriteBasicSetting(Settings::values.mouse_enabled); | ||
| 1108 | } | ||
| 1109 | |||
| 1110 | void Config::SaveTouchscreenValues() { | 840 | void Config::SaveTouchscreenValues() { |
| 1111 | const auto& touchscreen = Settings::values.touchscreen; | 841 | const auto& touchscreen = Settings::values.touchscreen; |
| 1112 | 842 | ||
| @@ -1117,21 +847,7 @@ void Config::SaveTouchscreenValues() { | |||
| 1117 | WriteSetting(QStringLiteral("touchscreen_diameter_y"), touchscreen.diameter_y, 15); | 847 | WriteSetting(QStringLiteral("touchscreen_diameter_y"), touchscreen.diameter_y, 15); |
| 1118 | } | 848 | } |
| 1119 | 849 | ||
| 1120 | void Config::SaveMousePanningValues() { | ||
| 1121 | // Don't overwrite values.mouse_panning | ||
| 1122 | WriteBasicSetting(Settings::values.mouse_panning_x_sensitivity); | ||
| 1123 | WriteBasicSetting(Settings::values.mouse_panning_y_sensitivity); | ||
| 1124 | WriteBasicSetting(Settings::values.mouse_panning_deadzone_counterweight); | ||
| 1125 | WriteBasicSetting(Settings::values.mouse_panning_decay_strength); | ||
| 1126 | WriteBasicSetting(Settings::values.mouse_panning_min_decay); | ||
| 1127 | } | ||
| 1128 | |||
| 1129 | void Config::SaveMotionTouchValues() { | 850 | void Config::SaveMotionTouchValues() { |
| 1130 | WriteBasicSetting(Settings::values.touch_device); | ||
| 1131 | WriteBasicSetting(Settings::values.touch_from_button_map_index); | ||
| 1132 | WriteBasicSetting(Settings::values.udp_input_servers); | ||
| 1133 | WriteBasicSetting(Settings::values.enable_udp_controller); | ||
| 1134 | |||
| 1135 | qt_config->beginWriteArray(QStringLiteral("touch_from_button_maps")); | 851 | qt_config->beginWriteArray(QStringLiteral("touch_from_button_maps")); |
| 1136 | for (std::size_t p = 0; p < Settings::values.touch_from_button_maps.size(); ++p) { | 852 | for (std::size_t p = 0; p < Settings::values.touch_from_button_maps.size(); ++p) { |
| 1137 | qt_config->setArrayIndex(static_cast<int>(p)); | 853 | qt_config->setArrayIndex(static_cast<int>(p)); |
| @@ -1152,8 +868,6 @@ void Config::SaveMotionTouchValues() { | |||
| 1152 | } | 868 | } |
| 1153 | 869 | ||
| 1154 | void Config::SaveHidbusValues() { | 870 | void Config::SaveHidbusValues() { |
| 1155 | WriteBasicSetting(Settings::values.enable_ring_controller); | ||
| 1156 | |||
| 1157 | const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( | 871 | const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( |
| 1158 | 0, 0, default_ringcon_analogs[0], default_ringcon_analogs[1], 0, 0.05f); | 872 | 0, 0, default_ringcon_analogs[0], default_ringcon_analogs[1], 0, 0.05f); |
| 1159 | WriteSetting(QStringLiteral("ring_controller"), | 873 | WriteSetting(QStringLiteral("ring_controller"), |
| @@ -1161,11 +875,6 @@ void Config::SaveHidbusValues() { | |||
| 1161 | QString::fromStdString(default_param)); | 875 | QString::fromStdString(default_param)); |
| 1162 | } | 876 | } |
| 1163 | 877 | ||
| 1164 | void Config::SaveIrCameraValues() { | ||
| 1165 | WriteBasicSetting(Settings::values.enable_ir_sensor); | ||
| 1166 | WriteBasicSetting(Settings::values.ir_sensor_device); | ||
| 1167 | } | ||
| 1168 | |||
| 1169 | void Config::SaveValues() { | 878 | void Config::SaveValues() { |
| 1170 | if (global) { | 879 | if (global) { |
| 1171 | SaveDataStorageValues(); | 880 | SaveDataStorageValues(); |
| @@ -1182,18 +891,14 @@ void Config::SaveValues() { | |||
| 1182 | SaveRendererValues(); | 891 | SaveRendererValues(); |
| 1183 | SaveAudioValues(); | 892 | SaveAudioValues(); |
| 1184 | SaveSystemValues(); | 893 | SaveSystemValues(); |
| 894 | |||
| 1185 | qt_config->sync(); | 895 | qt_config->sync(); |
| 1186 | } | 896 | } |
| 1187 | 897 | ||
| 1188 | void Config::SaveAudioValues() { | 898 | void Config::SaveAudioValues() { |
| 1189 | qt_config->beginGroup(QStringLiteral("Audio")); | 899 | qt_config->beginGroup(QStringLiteral("Audio")); |
| 1190 | 900 | ||
| 1191 | if (global) { | 901 | WriteCategory(Settings::Category::Audio); |
| 1192 | WriteBasicSetting(Settings::values.sink_id); | ||
| 1193 | WriteBasicSetting(Settings::values.audio_output_device_id); | ||
| 1194 | WriteBasicSetting(Settings::values.audio_input_device_id); | ||
| 1195 | } | ||
| 1196 | WriteGlobalSetting(Settings::values.volume); | ||
| 1197 | 902 | ||
| 1198 | qt_config->endGroup(); | 903 | qt_config->endGroup(); |
| 1199 | } | 904 | } |
| @@ -1201,6 +906,8 @@ void Config::SaveAudioValues() { | |||
| 1201 | void Config::SaveControlValues() { | 906 | void Config::SaveControlValues() { |
| 1202 | qt_config->beginGroup(QStringLiteral("Controls")); | 907 | qt_config->beginGroup(QStringLiteral("Controls")); |
| 1203 | 908 | ||
| 909 | WriteCategory(Settings::Category::Controls); | ||
| 910 | |||
| 1204 | Settings::values.players.SetGlobal(!IsCustomConfig()); | 911 | Settings::values.players.SetGlobal(!IsCustomConfig()); |
| 1205 | for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) { | 912 | for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) { |
| 1206 | SavePlayerValue(p); | 913 | SavePlayerValue(p); |
| @@ -1210,28 +917,9 @@ void Config::SaveControlValues() { | |||
| 1210 | return; | 917 | return; |
| 1211 | } | 918 | } |
| 1212 | SaveDebugValues(); | 919 | SaveDebugValues(); |
| 1213 | SaveMouseValues(); | ||
| 1214 | SaveTouchscreenValues(); | 920 | SaveTouchscreenValues(); |
| 1215 | SaveMousePanningValues(); | ||
| 1216 | SaveMotionTouchValues(); | 921 | SaveMotionTouchValues(); |
| 1217 | SaveHidbusValues(); | 922 | SaveHidbusValues(); |
| 1218 | SaveIrCameraValues(); | ||
| 1219 | |||
| 1220 | WriteGlobalSetting(Settings::values.use_docked_mode); | ||
| 1221 | WriteGlobalSetting(Settings::values.vibration_enabled); | ||
| 1222 | WriteGlobalSetting(Settings::values.enable_accurate_vibrations); | ||
| 1223 | WriteGlobalSetting(Settings::values.motion_enabled); | ||
| 1224 | WriteBasicSetting(Settings::values.enable_raw_input); | ||
| 1225 | WriteBasicSetting(Settings::values.enable_joycon_driver); | ||
| 1226 | WriteBasicSetting(Settings::values.enable_procon_driver); | ||
| 1227 | WriteBasicSetting(Settings::values.random_amiibo_id); | ||
| 1228 | WriteBasicSetting(Settings::values.keyboard_enabled); | ||
| 1229 | WriteBasicSetting(Settings::values.emulate_analog_keyboard); | ||
| 1230 | WriteBasicSetting(Settings::values.controller_navigation); | ||
| 1231 | |||
| 1232 | WriteBasicSetting(Settings::values.tas_enable); | ||
| 1233 | WriteBasicSetting(Settings::values.tas_loop); | ||
| 1234 | WriteBasicSetting(Settings::values.pause_tas_on_load); | ||
| 1235 | 923 | ||
| 1236 | qt_config->endGroup(); | 924 | qt_config->endGroup(); |
| 1237 | } | 925 | } |
| @@ -1239,8 +927,7 @@ void Config::SaveControlValues() { | |||
| 1239 | void Config::SaveCoreValues() { | 927 | void Config::SaveCoreValues() { |
| 1240 | qt_config->beginGroup(QStringLiteral("Core")); | 928 | qt_config->beginGroup(QStringLiteral("Core")); |
| 1241 | 929 | ||
| 1242 | WriteGlobalSetting(Settings::values.use_multi_core); | 930 | WriteCategory(Settings::Category::Core); |
| 1243 | WriteGlobalSetting(Settings::values.use_unsafe_extended_memory_layout); | ||
| 1244 | 931 | ||
| 1245 | qt_config->endGroup(); | 932 | qt_config->endGroup(); |
| 1246 | } | 933 | } |
| @@ -1248,7 +935,6 @@ void Config::SaveCoreValues() { | |||
| 1248 | void Config::SaveDataStorageValues() { | 935 | void Config::SaveDataStorageValues() { |
| 1249 | qt_config->beginGroup(QStringLiteral("Data Storage")); | 936 | qt_config->beginGroup(QStringLiteral("Data Storage")); |
| 1250 | 937 | ||
| 1251 | WriteBasicSetting(Settings::values.use_virtual_sd); | ||
| 1252 | WriteSetting(QStringLiteral("nand_directory"), | 938 | WriteSetting(QStringLiteral("nand_directory"), |
| 1253 | QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::NANDDir)), | 939 | QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::NANDDir)), |
| 1254 | QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::NANDDir))); | 940 | QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::NANDDir))); |
| @@ -1265,9 +951,7 @@ void Config::SaveDataStorageValues() { | |||
| 1265 | QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::TASDir)), | 951 | QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::TASDir)), |
| 1266 | QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::TASDir))); | 952 | QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::TASDir))); |
| 1267 | 953 | ||
| 1268 | WriteBasicSetting(Settings::values.gamecard_inserted); | 954 | WriteCategory(Settings::Category::DataStorage); |
| 1269 | WriteBasicSetting(Settings::values.gamecard_current_game); | ||
| 1270 | WriteBasicSetting(Settings::values.gamecard_path); | ||
| 1271 | 955 | ||
| 1272 | qt_config->endGroup(); | 956 | qt_config->endGroup(); |
| 1273 | } | 957 | } |
| @@ -1277,19 +961,9 @@ void Config::SaveDebuggingValues() { | |||
| 1277 | 961 | ||
| 1278 | // Intentionally not using the QT default setting as this is intended to be changed in the ini | 962 | // Intentionally not using the QT default setting as this is intended to be changed in the ini |
| 1279 | qt_config->setValue(QStringLiteral("record_frame_times"), Settings::values.record_frame_times); | 963 | qt_config->setValue(QStringLiteral("record_frame_times"), Settings::values.record_frame_times); |
| 1280 | WriteBasicSetting(Settings::values.use_gdbstub); | 964 | |
| 1281 | WriteBasicSetting(Settings::values.gdbstub_port); | 965 | WriteCategory(Settings::Category::Debugging); |
| 1282 | WriteBasicSetting(Settings::values.program_args); | 966 | WriteCategory(Settings::Category::DebuggingGraphics); |
| 1283 | WriteBasicSetting(Settings::values.dump_exefs); | ||
| 1284 | WriteBasicSetting(Settings::values.dump_nso); | ||
| 1285 | WriteBasicSetting(Settings::values.enable_fs_access_log); | ||
| 1286 | WriteBasicSetting(Settings::values.quest_flag); | ||
| 1287 | WriteBasicSetting(Settings::values.use_debug_asserts); | ||
| 1288 | WriteBasicSetting(Settings::values.disable_macro_jit); | ||
| 1289 | WriteBasicSetting(Settings::values.disable_macro_hle); | ||
| 1290 | WriteBasicSetting(Settings::values.enable_all_controllers); | ||
| 1291 | WriteBasicSetting(Settings::values.create_crash_dumps); | ||
| 1292 | WriteBasicSetting(Settings::values.perform_vulkan_check); | ||
| 1293 | 967 | ||
| 1294 | qt_config->endGroup(); | 968 | qt_config->endGroup(); |
| 1295 | } | 969 | } |
| @@ -1297,7 +971,7 @@ void Config::SaveDebuggingValues() { | |||
| 1297 | void Config::SaveNetworkValues() { | 971 | void Config::SaveNetworkValues() { |
| 1298 | qt_config->beginGroup(QStringLiteral("Services")); | 972 | qt_config->beginGroup(QStringLiteral("Services")); |
| 1299 | 973 | ||
| 1300 | WriteBasicSetting(Settings::values.network_interface); | 974 | WriteCategory(Settings::Category::Network); |
| 1301 | 975 | ||
| 1302 | qt_config->endGroup(); | 976 | qt_config->endGroup(); |
| 1303 | } | 977 | } |
| @@ -1324,8 +998,7 @@ void Config::SaveDisabledAddOnValues() { | |||
| 1324 | void Config::SaveMiscellaneousValues() { | 998 | void Config::SaveMiscellaneousValues() { |
| 1325 | qt_config->beginGroup(QStringLiteral("Miscellaneous")); | 999 | qt_config->beginGroup(QStringLiteral("Miscellaneous")); |
| 1326 | 1000 | ||
| 1327 | WriteBasicSetting(Settings::values.log_filter); | 1001 | WriteCategory(Settings::Category::Miscellaneous); |
| 1328 | WriteBasicSetting(Settings::values.use_dev_keys); | ||
| 1329 | 1002 | ||
| 1330 | qt_config->endGroup(); | 1003 | qt_config->endGroup(); |
| 1331 | } | 1004 | } |
| @@ -1353,34 +1026,9 @@ void Config::SavePathValues() { | |||
| 1353 | void Config::SaveCpuValues() { | 1026 | void Config::SaveCpuValues() { |
| 1354 | qt_config->beginGroup(QStringLiteral("Cpu")); | 1027 | qt_config->beginGroup(QStringLiteral("Cpu")); |
| 1355 | 1028 | ||
| 1356 | WriteBasicSetting(Settings::values.cpu_accuracy_first_time); | 1029 | WriteCategory(Settings::Category::Cpu); |
| 1357 | WriteSetting(QStringLiteral("cpu_accuracy"), | 1030 | WriteCategory(Settings::Category::CpuDebug); |
| 1358 | static_cast<u32>(Settings::values.cpu_accuracy.GetValue(global)), | 1031 | WriteCategory(Settings::Category::CpuUnsafe); |
| 1359 | static_cast<u32>(Settings::values.cpu_accuracy.GetDefault()), | ||
| 1360 | Settings::values.cpu_accuracy.UsingGlobal()); | ||
| 1361 | |||
| 1362 | WriteGlobalSetting(Settings::values.cpuopt_unsafe_unfuse_fma); | ||
| 1363 | WriteGlobalSetting(Settings::values.cpuopt_unsafe_reduce_fp_error); | ||
| 1364 | WriteGlobalSetting(Settings::values.cpuopt_unsafe_ignore_standard_fpcr); | ||
| 1365 | WriteGlobalSetting(Settings::values.cpuopt_unsafe_inaccurate_nan); | ||
| 1366 | WriteGlobalSetting(Settings::values.cpuopt_unsafe_fastmem_check); | ||
| 1367 | WriteGlobalSetting(Settings::values.cpuopt_unsafe_ignore_global_monitor); | ||
| 1368 | |||
| 1369 | if (global) { | ||
| 1370 | WriteBasicSetting(Settings::values.cpu_debug_mode); | ||
| 1371 | WriteBasicSetting(Settings::values.cpuopt_page_tables); | ||
| 1372 | WriteBasicSetting(Settings::values.cpuopt_block_linking); | ||
| 1373 | WriteBasicSetting(Settings::values.cpuopt_return_stack_buffer); | ||
| 1374 | WriteBasicSetting(Settings::values.cpuopt_fast_dispatcher); | ||
| 1375 | WriteBasicSetting(Settings::values.cpuopt_context_elimination); | ||
| 1376 | WriteBasicSetting(Settings::values.cpuopt_const_prop); | ||
| 1377 | WriteBasicSetting(Settings::values.cpuopt_misc_ir); | ||
| 1378 | WriteBasicSetting(Settings::values.cpuopt_reduce_misalign_checks); | ||
| 1379 | WriteBasicSetting(Settings::values.cpuopt_fastmem); | ||
| 1380 | WriteBasicSetting(Settings::values.cpuopt_fastmem_exclusives); | ||
| 1381 | WriteBasicSetting(Settings::values.cpuopt_recompile_exclusives); | ||
| 1382 | WriteBasicSetting(Settings::values.cpuopt_ignore_memory_aborts); | ||
| 1383 | } | ||
| 1384 | 1032 | ||
| 1385 | qt_config->endGroup(); | 1033 | qt_config->endGroup(); |
| 1386 | } | 1034 | } |
| @@ -1388,76 +1036,9 @@ void Config::SaveCpuValues() { | |||
| 1388 | void Config::SaveRendererValues() { | 1036 | void Config::SaveRendererValues() { |
| 1389 | qt_config->beginGroup(QStringLiteral("Renderer")); | 1037 | qt_config->beginGroup(QStringLiteral("Renderer")); |
| 1390 | 1038 | ||
| 1391 | WriteSetting(QString::fromStdString(Settings::values.renderer_backend.GetLabel()), | 1039 | WriteCategory(Settings::Category::Renderer); |
| 1392 | static_cast<u32>(Settings::values.renderer_backend.GetValue(global)), | 1040 | WriteCategory(Settings::Category::RendererAdvanced); |
| 1393 | static_cast<u32>(Settings::values.renderer_backend.GetDefault()), | 1041 | WriteCategory(Settings::Category::RendererDebug); |
| 1394 | Settings::values.renderer_backend.UsingGlobal()); | ||
| 1395 | WriteGlobalSetting(Settings::values.async_presentation); | ||
| 1396 | WriteGlobalSetting(Settings::values.renderer_force_max_clock); | ||
| 1397 | WriteGlobalSetting(Settings::values.vulkan_device); | ||
| 1398 | WriteSetting(QString::fromStdString(Settings::values.fullscreen_mode.GetLabel()), | ||
| 1399 | static_cast<u32>(Settings::values.fullscreen_mode.GetValue(global)), | ||
| 1400 | static_cast<u32>(Settings::values.fullscreen_mode.GetDefault()), | ||
| 1401 | Settings::values.fullscreen_mode.UsingGlobal()); | ||
| 1402 | WriteGlobalSetting(Settings::values.aspect_ratio); | ||
| 1403 | WriteSetting(QString::fromStdString(Settings::values.resolution_setup.GetLabel()), | ||
| 1404 | static_cast<u32>(Settings::values.resolution_setup.GetValue(global)), | ||
| 1405 | static_cast<u32>(Settings::values.resolution_setup.GetDefault()), | ||
| 1406 | Settings::values.resolution_setup.UsingGlobal()); | ||
| 1407 | WriteSetting(QString::fromStdString(Settings::values.scaling_filter.GetLabel()), | ||
| 1408 | static_cast<u32>(Settings::values.scaling_filter.GetValue(global)), | ||
| 1409 | static_cast<u32>(Settings::values.scaling_filter.GetDefault()), | ||
| 1410 | Settings::values.scaling_filter.UsingGlobal()); | ||
| 1411 | WriteSetting(QString::fromStdString(Settings::values.fsr_sharpening_slider.GetLabel()), | ||
| 1412 | static_cast<u32>(Settings::values.fsr_sharpening_slider.GetValue(global)), | ||
| 1413 | static_cast<u32>(Settings::values.fsr_sharpening_slider.GetDefault()), | ||
| 1414 | Settings::values.fsr_sharpening_slider.UsingGlobal()); | ||
| 1415 | WriteSetting(QString::fromStdString(Settings::values.anti_aliasing.GetLabel()), | ||
| 1416 | static_cast<u32>(Settings::values.anti_aliasing.GetValue(global)), | ||
| 1417 | static_cast<u32>(Settings::values.anti_aliasing.GetDefault()), | ||
| 1418 | Settings::values.anti_aliasing.UsingGlobal()); | ||
| 1419 | WriteGlobalSetting(Settings::values.max_anisotropy); | ||
| 1420 | WriteGlobalSetting(Settings::values.speed_limit); | ||
| 1421 | WriteGlobalSetting(Settings::values.use_disk_shader_cache); | ||
| 1422 | WriteSetting(QString::fromStdString(Settings::values.gpu_accuracy.GetLabel()), | ||
| 1423 | static_cast<u32>(Settings::values.gpu_accuracy.GetValue(global)), | ||
| 1424 | static_cast<u32>(Settings::values.gpu_accuracy.GetDefault()), | ||
| 1425 | Settings::values.gpu_accuracy.UsingGlobal()); | ||
| 1426 | WriteGlobalSetting(Settings::values.use_asynchronous_gpu_emulation); | ||
| 1427 | WriteSetting(QString::fromStdString(Settings::values.nvdec_emulation.GetLabel()), | ||
| 1428 | static_cast<u32>(Settings::values.nvdec_emulation.GetValue(global)), | ||
| 1429 | static_cast<u32>(Settings::values.nvdec_emulation.GetDefault()), | ||
| 1430 | Settings::values.nvdec_emulation.UsingGlobal()); | ||
| 1431 | WriteGlobalSetting(Settings::values.accelerate_astc); | ||
| 1432 | WriteGlobalSetting(Settings::values.async_astc); | ||
| 1433 | WriteSetting(QString::fromStdString(Settings::values.astc_recompression.GetLabel()), | ||
| 1434 | static_cast<u32>(Settings::values.astc_recompression.GetValue(global)), | ||
| 1435 | static_cast<u32>(Settings::values.astc_recompression.GetDefault()), | ||
| 1436 | Settings::values.astc_recompression.UsingGlobal()); | ||
| 1437 | WriteGlobalSetting(Settings::values.use_reactive_flushing); | ||
| 1438 | WriteSetting(QString::fromStdString(Settings::values.shader_backend.GetLabel()), | ||
| 1439 | static_cast<u32>(Settings::values.shader_backend.GetValue(global)), | ||
| 1440 | static_cast<u32>(Settings::values.shader_backend.GetDefault()), | ||
| 1441 | Settings::values.shader_backend.UsingGlobal()); | ||
| 1442 | WriteGlobalSetting(Settings::values.use_asynchronous_shaders); | ||
| 1443 | WriteGlobalSetting(Settings::values.use_fast_gpu_time); | ||
| 1444 | WriteGlobalSetting(Settings::values.use_vulkan_driver_pipeline_cache); | ||
| 1445 | WriteGlobalSetting(Settings::values.enable_compute_pipelines); | ||
| 1446 | WriteGlobalSetting(Settings::values.use_video_framerate); | ||
| 1447 | WriteGlobalSetting(Settings::values.barrier_feedback_loops); | ||
| 1448 | WriteGlobalSetting(Settings::values.bg_red); | ||
| 1449 | WriteGlobalSetting(Settings::values.bg_green); | ||
| 1450 | WriteGlobalSetting(Settings::values.bg_blue); | ||
| 1451 | |||
| 1452 | if (global) { | ||
| 1453 | WriteSetting(QString::fromStdString(Settings::values.vsync_mode.GetLabel()), | ||
| 1454 | static_cast<u32>(Settings::values.vsync_mode.GetValue()), | ||
| 1455 | static_cast<u32>(Settings::values.vsync_mode.GetDefault())); | ||
| 1456 | WriteBasicSetting(Settings::values.renderer_debug); | ||
| 1457 | WriteBasicSetting(Settings::values.renderer_shader_feedback); | ||
| 1458 | WriteBasicSetting(Settings::values.enable_nsight_aftermath); | ||
| 1459 | WriteBasicSetting(Settings::values.disable_shader_loop_safety_checks); | ||
| 1460 | } | ||
| 1461 | 1042 | ||
| 1462 | qt_config->endGroup(); | 1043 | qt_config->endGroup(); |
| 1463 | } | 1044 | } |
| @@ -1465,9 +1046,9 @@ void Config::SaveRendererValues() { | |||
| 1465 | void Config::SaveScreenshotValues() { | 1046 | void Config::SaveScreenshotValues() { |
| 1466 | qt_config->beginGroup(QStringLiteral("Screenshots")); | 1047 | qt_config->beginGroup(QStringLiteral("Screenshots")); |
| 1467 | 1048 | ||
| 1468 | WriteBasicSetting(UISettings::values.enable_screenshot_save_as); | ||
| 1469 | WriteSetting(QStringLiteral("screenshot_path"), | 1049 | WriteSetting(QStringLiteral("screenshot_path"), |
| 1470 | QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::ScreenshotsDir))); | 1050 | QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::ScreenshotsDir))); |
| 1051 | WriteCategory(Settings::Category::Screenshots); | ||
| 1471 | 1052 | ||
| 1472 | qt_config->endGroup(); | 1053 | qt_config->endGroup(); |
| 1473 | } | 1054 | } |
| @@ -1498,27 +1079,8 @@ void Config::SaveShortcutValues() { | |||
| 1498 | void Config::SaveSystemValues() { | 1079 | void Config::SaveSystemValues() { |
| 1499 | qt_config->beginGroup(QStringLiteral("System")); | 1080 | qt_config->beginGroup(QStringLiteral("System")); |
| 1500 | 1081 | ||
| 1501 | WriteGlobalSetting(Settings::values.language_index); | 1082 | WriteCategory(Settings::Category::System); |
| 1502 | WriteGlobalSetting(Settings::values.region_index); | 1083 | WriteCategory(Settings::Category::SystemAudio); |
| 1503 | WriteGlobalSetting(Settings::values.time_zone_index); | ||
| 1504 | |||
| 1505 | WriteSetting(QStringLiteral("rng_seed_enabled"), | ||
| 1506 | Settings::values.rng_seed.GetValue(global).has_value(), false, | ||
| 1507 | Settings::values.rng_seed.UsingGlobal()); | ||
| 1508 | WriteSetting(QStringLiteral("rng_seed"), Settings::values.rng_seed.GetValue(global).value_or(0), | ||
| 1509 | 0, Settings::values.rng_seed.UsingGlobal()); | ||
| 1510 | |||
| 1511 | if (global) { | ||
| 1512 | WriteBasicSetting(Settings::values.current_user); | ||
| 1513 | |||
| 1514 | WriteSetting(QStringLiteral("custom_rtc_enabled"), Settings::values.custom_rtc.has_value(), | ||
| 1515 | false); | ||
| 1516 | WriteSetting(QStringLiteral("custom_rtc"), | ||
| 1517 | QVariant::fromValue<long long>(Settings::values.custom_rtc.value_or(0)), 0); | ||
| 1518 | WriteBasicSetting(Settings::values.device_name); | ||
| 1519 | } | ||
| 1520 | |||
| 1521 | WriteGlobalSetting(Settings::values.sound_index); | ||
| 1522 | 1084 | ||
| 1523 | qt_config->endGroup(); | 1085 | qt_config->endGroup(); |
| 1524 | } | 1086 | } |
| @@ -1526,10 +1088,11 @@ void Config::SaveSystemValues() { | |||
| 1526 | void Config::SaveUIValues() { | 1088 | void Config::SaveUIValues() { |
| 1527 | qt_config->beginGroup(QStringLiteral("UI")); | 1089 | qt_config->beginGroup(QStringLiteral("UI")); |
| 1528 | 1090 | ||
| 1091 | WriteCategory(Settings::Category::Ui); | ||
| 1092 | WriteCategory(Settings::Category::UiGeneral); | ||
| 1093 | |||
| 1529 | WriteSetting(QStringLiteral("theme"), UISettings::values.theme, | 1094 | WriteSetting(QStringLiteral("theme"), UISettings::values.theme, |
| 1530 | QString::fromUtf8(UISettings::themes[static_cast<size_t>(default_theme)].second)); | 1095 | QString::fromUtf8(UISettings::themes[static_cast<size_t>(default_theme)].second)); |
| 1531 | WriteBasicSetting(UISettings::values.enable_discord_presence); | ||
| 1532 | WriteBasicSetting(UISettings::values.select_user_on_boot); | ||
| 1533 | 1096 | ||
| 1534 | SaveUIGamelistValues(); | 1097 | SaveUIGamelistValues(); |
| 1535 | SaveUILayoutValues(); | 1098 | SaveUILayoutValues(); |
| @@ -1538,37 +1101,14 @@ void Config::SaveUIValues() { | |||
| 1538 | SaveShortcutValues(); | 1101 | SaveShortcutValues(); |
| 1539 | SaveMultiplayerValues(); | 1102 | SaveMultiplayerValues(); |
| 1540 | 1103 | ||
| 1541 | WriteBasicSetting(UISettings::values.single_window_mode); | ||
| 1542 | WriteBasicSetting(UISettings::values.fullscreen); | ||
| 1543 | WriteBasicSetting(UISettings::values.display_titlebar); | ||
| 1544 | WriteBasicSetting(UISettings::values.show_filter_bar); | ||
| 1545 | WriteBasicSetting(UISettings::values.show_status_bar); | ||
| 1546 | WriteBasicSetting(UISettings::values.confirm_before_closing); | ||
| 1547 | WriteBasicSetting(UISettings::values.first_start); | ||
| 1548 | WriteBasicSetting(UISettings::values.callout_flags); | ||
| 1549 | WriteBasicSetting(UISettings::values.show_console); | ||
| 1550 | WriteBasicSetting(UISettings::values.pause_when_in_background); | ||
| 1551 | WriteBasicSetting(UISettings::values.mute_when_in_background); | ||
| 1552 | WriteBasicSetting(UISettings::values.hide_mouse); | ||
| 1553 | WriteBasicSetting(UISettings::values.controller_applet_disabled); | ||
| 1554 | WriteBasicSetting(UISettings::values.disable_web_applet); | ||
| 1555 | |||
| 1556 | qt_config->endGroup(); | 1104 | qt_config->endGroup(); |
| 1557 | } | 1105 | } |
| 1558 | 1106 | ||
| 1559 | void Config::SaveUIGamelistValues() { | 1107 | void Config::SaveUIGamelistValues() { |
| 1560 | qt_config->beginGroup(QStringLiteral("UIGameList")); | 1108 | qt_config->beginGroup(QStringLiteral("UIGameList")); |
| 1561 | 1109 | ||
| 1562 | WriteBasicSetting(UISettings::values.show_add_ons); | 1110 | WriteCategory(Settings::Category::UiGameList); |
| 1563 | WriteBasicSetting(UISettings::values.show_compat); | 1111 | |
| 1564 | WriteBasicSetting(UISettings::values.show_size); | ||
| 1565 | WriteBasicSetting(UISettings::values.show_types); | ||
| 1566 | WriteBasicSetting(UISettings::values.game_icon_size); | ||
| 1567 | WriteBasicSetting(UISettings::values.folder_icon_size); | ||
| 1568 | WriteBasicSetting(UISettings::values.row_1_text_id); | ||
| 1569 | WriteBasicSetting(UISettings::values.row_2_text_id); | ||
| 1570 | WriteBasicSetting(UISettings::values.cache_game_list); | ||
| 1571 | WriteBasicSetting(UISettings::values.favorites_expanded); | ||
| 1572 | qt_config->beginWriteArray(QStringLiteral("favorites")); | 1112 | qt_config->beginWriteArray(QStringLiteral("favorites")); |
| 1573 | for (int i = 0; i < UISettings::values.favorited_ids.size(); i++) { | 1113 | for (int i = 0; i < UISettings::values.favorited_ids.size(); i++) { |
| 1574 | qt_config->setArrayIndex(i); | 1114 | qt_config->setArrayIndex(i); |
| @@ -1589,7 +1129,8 @@ void Config::SaveUILayoutValues() { | |||
| 1589 | WriteSetting(QStringLiteral("gameListHeaderState"), UISettings::values.gamelist_header_state); | 1129 | WriteSetting(QStringLiteral("gameListHeaderState"), UISettings::values.gamelist_header_state); |
| 1590 | WriteSetting(QStringLiteral("microProfileDialogGeometry"), | 1130 | WriteSetting(QStringLiteral("microProfileDialogGeometry"), |
| 1591 | UISettings::values.microprofile_geometry); | 1131 | UISettings::values.microprofile_geometry); |
| 1592 | WriteBasicSetting(UISettings::values.microprofile_visible); | 1132 | |
| 1133 | WriteCategory(Settings::Category::UiLayout); | ||
| 1593 | 1134 | ||
| 1594 | qt_config->endGroup(); | 1135 | qt_config->endGroup(); |
| 1595 | } | 1136 | } |
| @@ -1597,10 +1138,7 @@ void Config::SaveUILayoutValues() { | |||
| 1597 | void Config::SaveWebServiceValues() { | 1138 | void Config::SaveWebServiceValues() { |
| 1598 | qt_config->beginGroup(QStringLiteral("WebService")); | 1139 | qt_config->beginGroup(QStringLiteral("WebService")); |
| 1599 | 1140 | ||
| 1600 | WriteBasicSetting(Settings::values.enable_telemetry); | 1141 | WriteCategory(Settings::Category::WebService); |
| 1601 | WriteBasicSetting(Settings::values.web_api_url); | ||
| 1602 | WriteBasicSetting(Settings::values.yuzu_username); | ||
| 1603 | WriteBasicSetting(Settings::values.yuzu_token); | ||
| 1604 | 1142 | ||
| 1605 | qt_config->endGroup(); | 1143 | qt_config->endGroup(); |
| 1606 | } | 1144 | } |
| @@ -1608,17 +1146,7 @@ void Config::SaveWebServiceValues() { | |||
| 1608 | void Config::SaveMultiplayerValues() { | 1146 | void Config::SaveMultiplayerValues() { |
| 1609 | qt_config->beginGroup(QStringLiteral("Multiplayer")); | 1147 | qt_config->beginGroup(QStringLiteral("Multiplayer")); |
| 1610 | 1148 | ||
| 1611 | WriteBasicSetting(UISettings::values.multiplayer_nickname); | 1149 | WriteCategory(Settings::Category::Multiplayer); |
| 1612 | WriteBasicSetting(UISettings::values.multiplayer_ip); | ||
| 1613 | WriteBasicSetting(UISettings::values.multiplayer_port); | ||
| 1614 | WriteBasicSetting(UISettings::values.multiplayer_room_nickname); | ||
| 1615 | WriteBasicSetting(UISettings::values.multiplayer_room_name); | ||
| 1616 | WriteBasicSetting(UISettings::values.multiplayer_room_port); | ||
| 1617 | WriteBasicSetting(UISettings::values.multiplayer_host_type); | ||
| 1618 | WriteBasicSetting(UISettings::values.multiplayer_port); | ||
| 1619 | WriteBasicSetting(UISettings::values.multiplayer_max_player); | ||
| 1620 | WriteBasicSetting(UISettings::values.multiplayer_game_id); | ||
| 1621 | WriteBasicSetting(UISettings::values.multiplayer_room_description); | ||
| 1622 | 1150 | ||
| 1623 | // Write ban list | 1151 | // Write ban list |
| 1624 | qt_config->beginWriteArray(QStringLiteral("username_ban_list")); | 1152 | qt_config->beginWriteArray(QStringLiteral("username_ban_list")); |
| @@ -1653,27 +1181,6 @@ QVariant Config::ReadSetting(const QString& name, const QVariant& default_value) | |||
| 1653 | return result; | 1181 | return result; |
| 1654 | } | 1182 | } |
| 1655 | 1183 | ||
| 1656 | template <typename Type, bool ranged> | ||
| 1657 | void Config::ReadGlobalSetting(Settings::SwitchableSetting<Type, ranged>& setting) { | ||
| 1658 | QString name = QString::fromStdString(setting.GetLabel()); | ||
| 1659 | const bool use_global = qt_config->value(name + QStringLiteral("/use_global"), true).toBool(); | ||
| 1660 | setting.SetGlobal(use_global); | ||
| 1661 | if (global || !use_global) { | ||
| 1662 | setting.SetValue(static_cast<QVariant>( | ||
| 1663 | ReadSetting(name, QVariant::fromValue<Type>(setting.GetDefault()))) | ||
| 1664 | .value<Type>()); | ||
| 1665 | } | ||
| 1666 | } | ||
| 1667 | |||
| 1668 | template <typename Type> | ||
| 1669 | void Config::ReadSettingGlobal(Type& setting, const QString& name, | ||
| 1670 | const QVariant& default_value) const { | ||
| 1671 | const bool use_global = qt_config->value(name + QStringLiteral("/use_global"), true).toBool(); | ||
| 1672 | if (global || !use_global) { | ||
| 1673 | setting = ReadSetting(name, default_value).value<Type>(); | ||
| 1674 | } | ||
| 1675 | } | ||
| 1676 | |||
| 1677 | void Config::WriteSetting(const QString& name, const QVariant& value) { | 1184 | void Config::WriteSetting(const QString& name, const QVariant& value) { |
| 1678 | qt_config->setValue(name, value); | 1185 | qt_config->setValue(name, value); |
| 1679 | } | 1186 | } |
| @@ -1727,3 +1234,72 @@ void Config::ClearControlPlayerValues() { | |||
| 1727 | const std::string& Config::GetConfigFilePath() const { | 1234 | const std::string& Config::GetConfigFilePath() const { |
| 1728 | return qt_config_loc; | 1235 | return qt_config_loc; |
| 1729 | } | 1236 | } |
| 1237 | |||
| 1238 | static auto FindRelevantList(Settings::Category category) { | ||
| 1239 | auto& map = Settings::values.linkage.by_category; | ||
| 1240 | if (map.contains(category)) { | ||
| 1241 | return Settings::values.linkage.by_category[category]; | ||
| 1242 | } | ||
| 1243 | return UISettings::values.linkage.by_category[category]; | ||
| 1244 | } | ||
| 1245 | |||
| 1246 | void Config::ReadCategory(Settings::Category category) { | ||
| 1247 | const auto& settings = FindRelevantList(category); | ||
| 1248 | std::for_each(settings.begin(), settings.end(), | ||
| 1249 | [&](const auto& setting) { ReadSettingGeneric(setting); }); | ||
| 1250 | } | ||
| 1251 | |||
| 1252 | void Config::WriteCategory(Settings::Category category) { | ||
| 1253 | const auto& settings = FindRelevantList(category); | ||
| 1254 | std::for_each(settings.begin(), settings.end(), | ||
| 1255 | [&](const auto& setting) { WriteSettingGeneric(setting); }); | ||
| 1256 | } | ||
| 1257 | |||
| 1258 | void Config::ReadSettingGeneric(Settings::BasicSetting* const setting) { | ||
| 1259 | if (!setting->Save() || (!setting->Switchable() && !global)) { | ||
| 1260 | return; | ||
| 1261 | } | ||
| 1262 | const QString name = QString::fromStdString(setting->GetLabel()); | ||
| 1263 | const auto default_value = | ||
| 1264 | QVariant::fromValue<QString>(QString::fromStdString(setting->DefaultToString())); | ||
| 1265 | |||
| 1266 | bool use_global = true; | ||
| 1267 | if (setting->Switchable() && !global) { | ||
| 1268 | use_global = qt_config->value(name + QStringLiteral("/use_global"), true).value<bool>(); | ||
| 1269 | setting->SetGlobal(use_global); | ||
| 1270 | } | ||
| 1271 | |||
| 1272 | if (global || !use_global) { | ||
| 1273 | const bool is_default = | ||
| 1274 | qt_config->value(name + QStringLiteral("/default"), true).value<bool>(); | ||
| 1275 | if (!is_default) { | ||
| 1276 | setting->LoadString( | ||
| 1277 | qt_config->value(name, default_value).value<QString>().toStdString()); | ||
| 1278 | } else { | ||
| 1279 | // Empty string resets the Setting to default | ||
| 1280 | setting->LoadString(""); | ||
| 1281 | } | ||
| 1282 | } | ||
| 1283 | } | ||
| 1284 | |||
| 1285 | void Config::WriteSettingGeneric(Settings::BasicSetting* const setting) const { | ||
| 1286 | if (!setting->Save()) { | ||
| 1287 | return; | ||
| 1288 | } | ||
| 1289 | const QVariant value = QVariant::fromValue(QString::fromStdString(setting->ToString())); | ||
| 1290 | const QVariant default_value = | ||
| 1291 | QVariant::fromValue(QString::fromStdString(setting->DefaultToString())); | ||
| 1292 | const QString label = QString::fromStdString(setting->GetLabel()); | ||
| 1293 | if (setting->Switchable()) { | ||
| 1294 | if (!global) { | ||
| 1295 | qt_config->setValue(label + QStringLiteral("/use_global"), setting->UsingGlobal()); | ||
| 1296 | } | ||
| 1297 | if (global || !setting->UsingGlobal()) { | ||
| 1298 | qt_config->setValue(label + QStringLiteral("/default"), value == default_value); | ||
| 1299 | qt_config->setValue(label, value); | ||
| 1300 | } | ||
| 1301 | } else if (global) { | ||
| 1302 | qt_config->setValue(label + QStringLiteral("/default"), value == default_value); | ||
| 1303 | qt_config->setValue(label, value); | ||
| 1304 | } | ||
| 1305 | } | ||
diff --git a/src/yuzu/configuration/config.h b/src/yuzu/configuration/config.h index 1211389d2..0ac74c8e7 100644 --- a/src/yuzu/configuration/config.h +++ b/src/yuzu/configuration/config.h | |||
| @@ -52,7 +52,7 @@ public: | |||
| 52 | static const std::map<Settings::AntiAliasing, QString> anti_aliasing_texts_map; | 52 | static const std::map<Settings::AntiAliasing, QString> anti_aliasing_texts_map; |
| 53 | static const std::map<Settings::ScalingFilter, QString> scaling_filter_texts_map; | 53 | static const std::map<Settings::ScalingFilter, QString> scaling_filter_texts_map; |
| 54 | static const std::map<bool, QString> use_docked_mode_texts_map; | 54 | static const std::map<bool, QString> use_docked_mode_texts_map; |
| 55 | static const std::map<Settings::GPUAccuracy, QString> gpu_accuracy_texts_map; | 55 | static const std::map<Settings::GpuAccuracy, QString> gpu_accuracy_texts_map; |
| 56 | static const std::map<Settings::RendererBackend, QString> renderer_backend_texts_map; | 56 | static const std::map<Settings::RendererBackend, QString> renderer_backend_texts_map; |
| 57 | static const std::map<Settings::ShaderBackend, QString> shader_backend_texts_map; | 57 | static const std::map<Settings::ShaderBackend, QString> shader_backend_texts_map; |
| 58 | 58 | ||
| @@ -74,7 +74,6 @@ private: | |||
| 74 | void ReadKeyboardValues(); | 74 | void ReadKeyboardValues(); |
| 75 | void ReadMouseValues(); | 75 | void ReadMouseValues(); |
| 76 | void ReadTouchscreenValues(); | 76 | void ReadTouchscreenValues(); |
| 77 | void ReadMousePanningValues(); | ||
| 78 | void ReadMotionTouchValues(); | 77 | void ReadMotionTouchValues(); |
| 79 | void ReadHidbusValues(); | 78 | void ReadHidbusValues(); |
| 80 | void ReadIrCameraValues(); | 79 | void ReadIrCameraValues(); |
| @@ -99,13 +98,13 @@ private: | |||
| 99 | void ReadUILayoutValues(); | 98 | void ReadUILayoutValues(); |
| 100 | void ReadWebServiceValues(); | 99 | void ReadWebServiceValues(); |
| 101 | void ReadMultiplayerValues(); | 100 | void ReadMultiplayerValues(); |
| 101 | void ReadNetworkValues(); | ||
| 102 | 102 | ||
| 103 | void SaveValues(); | 103 | void SaveValues(); |
| 104 | void SavePlayerValue(std::size_t player_index); | 104 | void SavePlayerValue(std::size_t player_index); |
| 105 | void SaveDebugValues(); | 105 | void SaveDebugValues(); |
| 106 | void SaveMouseValues(); | 106 | void SaveMouseValues(); |
| 107 | void SaveTouchscreenValues(); | 107 | void SaveTouchscreenValues(); |
| 108 | void SaveMousePanningValues(); | ||
| 109 | void SaveMotionTouchValues(); | 108 | void SaveMotionTouchValues(); |
| 110 | void SaveHidbusValues(); | 109 | void SaveHidbusValues(); |
| 111 | void SaveIrCameraValues(); | 110 | void SaveIrCameraValues(); |
| @@ -141,18 +140,6 @@ private: | |||
| 141 | QVariant ReadSetting(const QString& name, const QVariant& default_value) const; | 140 | QVariant ReadSetting(const QString& name, const QVariant& default_value) const; |
| 142 | 141 | ||
| 143 | /** | 142 | /** |
| 144 | * Only reads a setting from the qt_config if the current config is a global config, or if the | ||
| 145 | * current config is a custom config and the setting is overriding the global setting. Otherwise | ||
| 146 | * it does nothing. | ||
| 147 | * | ||
| 148 | * @param setting The variable to be modified | ||
| 149 | * @param name The setting's identifier | ||
| 150 | * @param default_value The value to use when the setting is not already present in the config | ||
| 151 | */ | ||
| 152 | template <typename Type> | ||
| 153 | void ReadSettingGlobal(Type& setting, const QString& name, const QVariant& default_value) const; | ||
| 154 | |||
| 155 | /** | ||
| 156 | * Writes a setting to the qt_config. | 143 | * Writes a setting to the qt_config. |
| 157 | * | 144 | * |
| 158 | * @param name The setting's idetentifier | 145 | * @param name The setting's idetentifier |
| @@ -166,50 +153,20 @@ private: | |||
| 166 | void WriteSetting(const QString& name, const QVariant& value, const QVariant& default_value, | 153 | void WriteSetting(const QString& name, const QVariant& value, const QVariant& default_value, |
| 167 | bool use_global); | 154 | bool use_global); |
| 168 | 155 | ||
| 169 | /** | 156 | void ReadCategory(Settings::Category category); |
| 170 | * Reads a value from the qt_config and applies it to the setting, using its label and default | 157 | void WriteCategory(Settings::Category category); |
| 171 | * value. If the config is a custom config, this will also read the global state of the setting | 158 | void ReadSettingGeneric(Settings::BasicSetting* const setting); |
| 172 | * and apply that information to it. | 159 | void WriteSettingGeneric(Settings::BasicSetting* const setting) const; |
| 173 | * | ||
| 174 | * @param The setting | ||
| 175 | */ | ||
| 176 | template <typename Type, bool ranged> | ||
| 177 | void ReadGlobalSetting(Settings::SwitchableSetting<Type, ranged>& setting); | ||
| 178 | |||
| 179 | /** | ||
| 180 | * Sets a value to the qt_config using the setting's label and default value. If the config is a | ||
| 181 | * custom config, it will apply the global state, and the custom value if needed. | ||
| 182 | * | ||
| 183 | * @param The setting | ||
| 184 | */ | ||
| 185 | template <typename Type, bool ranged> | ||
| 186 | void WriteGlobalSetting(const Settings::SwitchableSetting<Type, ranged>& setting); | ||
| 187 | |||
| 188 | /** | ||
| 189 | * Reads a value from the qt_config using the setting's label and default value and applies the | ||
| 190 | * value to the setting. | ||
| 191 | * | ||
| 192 | * @param The setting | ||
| 193 | */ | ||
| 194 | template <typename Type, bool ranged> | ||
| 195 | void ReadBasicSetting(Settings::Setting<Type, ranged>& setting); | ||
| 196 | |||
| 197 | /** Sets a value from the setting in the qt_config using the setting's label and default value. | ||
| 198 | * | ||
| 199 | * @param The setting | ||
| 200 | */ | ||
| 201 | template <typename Type, bool ranged> | ||
| 202 | void WriteBasicSetting(const Settings::Setting<Type, ranged>& setting); | ||
| 203 | 160 | ||
| 204 | ConfigType type; | 161 | const ConfigType type; |
| 205 | std::unique_ptr<QSettings> qt_config; | 162 | std::unique_ptr<QSettings> qt_config; |
| 206 | std::string qt_config_loc; | 163 | std::string qt_config_loc; |
| 207 | bool global; | 164 | const bool global; |
| 208 | }; | 165 | }; |
| 209 | 166 | ||
| 210 | // These metatype declarations cannot be in common/settings.h because core is devoid of QT | 167 | // These metatype declarations cannot be in common/settings.h because core is devoid of QT |
| 211 | Q_DECLARE_METATYPE(Settings::CPUAccuracy); | 168 | Q_DECLARE_METATYPE(Settings::CpuAccuracy); |
| 212 | Q_DECLARE_METATYPE(Settings::GPUAccuracy); | 169 | Q_DECLARE_METATYPE(Settings::GpuAccuracy); |
| 213 | Q_DECLARE_METATYPE(Settings::FullscreenMode); | 170 | Q_DECLARE_METATYPE(Settings::FullscreenMode); |
| 214 | Q_DECLARE_METATYPE(Settings::NvdecEmulation); | 171 | Q_DECLARE_METATYPE(Settings::NvdecEmulation); |
| 215 | Q_DECLARE_METATYPE(Settings::ResolutionSetup); | 172 | Q_DECLARE_METATYPE(Settings::ResolutionSetup); |
| @@ -218,3 +175,4 @@ Q_DECLARE_METATYPE(Settings::AntiAliasing); | |||
| 218 | Q_DECLARE_METATYPE(Settings::RendererBackend); | 175 | Q_DECLARE_METATYPE(Settings::RendererBackend); |
| 219 | Q_DECLARE_METATYPE(Settings::ShaderBackend); | 176 | Q_DECLARE_METATYPE(Settings::ShaderBackend); |
| 220 | Q_DECLARE_METATYPE(Settings::AstcRecompression); | 177 | Q_DECLARE_METATYPE(Settings::AstcRecompression); |
| 178 | Q_DECLARE_METATYPE(Settings::AstcDecodeMode); | ||
diff --git a/src/yuzu/configuration/configuration_shared.cpp b/src/yuzu/configuration/configuration_shared.cpp index ac42cc7fc..0ed6146a0 100644 --- a/src/yuzu/configuration/configuration_shared.cpp +++ b/src/yuzu/configuration/configuration_shared.cpp | |||
| @@ -1,104 +1,19 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2016 Citra Emulator Project | 1 | // SPDX-FileCopyrightText: 2016 Citra Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include <QCheckBox> | 4 | #include <memory> |
| 5 | #include <QObject> | 5 | #include <type_traits> |
| 6 | #include <QString> | 6 | #include <vector> |
| 7 | #include "common/settings.h" | ||
| 8 | #include "yuzu/configuration/configuration_shared.h" | 7 | #include "yuzu/configuration/configuration_shared.h" |
| 9 | #include "yuzu/configuration/configure_per_game.h" | ||
| 10 | 8 | ||
| 11 | void ConfigurationShared::ApplyPerGameSetting(Settings::SwitchableSetting<bool>* setting, | 9 | namespace ConfigurationShared { |
| 12 | const QCheckBox* checkbox, | ||
| 13 | const CheckState& tracker) { | ||
| 14 | if (Settings::IsConfiguringGlobal() && setting->UsingGlobal()) { | ||
| 15 | setting->SetValue(checkbox->checkState()); | ||
| 16 | } else if (!Settings::IsConfiguringGlobal()) { | ||
| 17 | if (tracker == CheckState::Global) { | ||
| 18 | setting->SetGlobal(true); | ||
| 19 | } else { | ||
| 20 | setting->SetGlobal(false); | ||
| 21 | setting->SetValue(checkbox->checkState()); | ||
| 22 | } | ||
| 23 | } | ||
| 24 | } | ||
| 25 | 10 | ||
| 26 | void ConfigurationShared::SetPerGameSetting(QCheckBox* checkbox, | 11 | Tab::Tab(std::shared_ptr<std::vector<Tab*>> group, QWidget* parent) : QWidget(parent) { |
| 27 | const Settings::SwitchableSetting<bool>* setting) { | 12 | if (group != nullptr) { |
| 28 | if (setting->UsingGlobal()) { | 13 | group->push_back(this); |
| 29 | checkbox->setCheckState(Qt::PartiallyChecked); | ||
| 30 | } else { | ||
| 31 | checkbox->setCheckState(setting->GetValue() ? Qt::Checked : Qt::Unchecked); | ||
| 32 | } | 14 | } |
| 33 | } | 15 | } |
| 34 | 16 | ||
| 35 | void ConfigurationShared::SetHighlight(QWidget* widget, bool highlighted) { | 17 | Tab::~Tab() = default; |
| 36 | if (highlighted) { | ||
| 37 | widget->setStyleSheet(QStringLiteral("QWidget#%1 { background-color:rgba(0,203,255,0.5) }") | ||
| 38 | .arg(widget->objectName())); | ||
| 39 | } else { | ||
| 40 | widget->setStyleSheet(QStringLiteral("QWidget#%1 { background-color:rgba(0,0,0,0) }") | ||
| 41 | .arg(widget->objectName())); | ||
| 42 | } | ||
| 43 | widget->show(); | ||
| 44 | } | ||
| 45 | 18 | ||
| 46 | void ConfigurationShared::SetColoredTristate(QCheckBox* checkbox, | 19 | } // namespace ConfigurationShared |
| 47 | const Settings::SwitchableSetting<bool>& setting, | ||
| 48 | CheckState& tracker) { | ||
| 49 | if (setting.UsingGlobal()) { | ||
| 50 | tracker = CheckState::Global; | ||
| 51 | } else { | ||
| 52 | tracker = (setting.GetValue() == setting.GetValue(true)) ? CheckState::On : CheckState::Off; | ||
| 53 | } | ||
| 54 | SetHighlight(checkbox, tracker != CheckState::Global); | ||
| 55 | QObject::connect(checkbox, &QCheckBox::clicked, checkbox, [checkbox, setting, &tracker] { | ||
| 56 | tracker = static_cast<CheckState>((static_cast<int>(tracker) + 1) % | ||
| 57 | static_cast<int>(CheckState::Count)); | ||
| 58 | if (tracker == CheckState::Global) { | ||
| 59 | checkbox->setChecked(setting.GetValue(true)); | ||
| 60 | } | ||
| 61 | SetHighlight(checkbox, tracker != CheckState::Global); | ||
| 62 | }); | ||
| 63 | } | ||
| 64 | |||
| 65 | void ConfigurationShared::SetColoredTristate(QCheckBox* checkbox, bool global, bool state, | ||
| 66 | bool global_state, CheckState& tracker) { | ||
| 67 | if (global) { | ||
| 68 | tracker = CheckState::Global; | ||
| 69 | } else { | ||
| 70 | tracker = (state == global_state) ? CheckState::On : CheckState::Off; | ||
| 71 | } | ||
| 72 | SetHighlight(checkbox, tracker != CheckState::Global); | ||
| 73 | QObject::connect(checkbox, &QCheckBox::clicked, checkbox, [checkbox, global_state, &tracker] { | ||
| 74 | tracker = static_cast<CheckState>((static_cast<int>(tracker) + 1) % | ||
| 75 | static_cast<int>(CheckState::Count)); | ||
| 76 | if (tracker == CheckState::Global) { | ||
| 77 | checkbox->setChecked(global_state); | ||
| 78 | } | ||
| 79 | SetHighlight(checkbox, tracker != CheckState::Global); | ||
| 80 | }); | ||
| 81 | } | ||
| 82 | |||
| 83 | void ConfigurationShared::SetColoredComboBox(QComboBox* combobox, QWidget* target, int global) { | ||
| 84 | InsertGlobalItem(combobox, global); | ||
| 85 | QObject::connect(combobox, qOverload<int>(&QComboBox::activated), target, | ||
| 86 | [target](int index) { SetHighlight(target, index != 0); }); | ||
| 87 | } | ||
| 88 | |||
| 89 | void ConfigurationShared::InsertGlobalItem(QComboBox* combobox, int global_index) { | ||
| 90 | const QString use_global_text = | ||
| 91 | ConfigurePerGame::tr("Use global configuration (%1)").arg(combobox->itemText(global_index)); | ||
| 92 | combobox->insertItem(ConfigurationShared::USE_GLOBAL_INDEX, use_global_text); | ||
| 93 | combobox->insertSeparator(ConfigurationShared::USE_GLOBAL_SEPARATOR_INDEX); | ||
| 94 | } | ||
| 95 | |||
| 96 | int ConfigurationShared::GetComboboxIndex(int global_setting_index, const QComboBox* combobox) { | ||
| 97 | if (Settings::IsConfiguringGlobal()) { | ||
| 98 | return combobox->currentIndex(); | ||
| 99 | } | ||
| 100 | if (combobox->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) { | ||
| 101 | return global_setting_index; | ||
| 102 | } | ||
| 103 | return combobox->currentIndex() - ConfigurationShared::USE_GLOBAL_OFFSET; | ||
| 104 | } | ||
diff --git a/src/yuzu/configuration/configuration_shared.h b/src/yuzu/configuration/configuration_shared.h index 04c88758c..31897a6b0 100644 --- a/src/yuzu/configuration/configuration_shared.h +++ b/src/yuzu/configuration/configuration_shared.h | |||
| @@ -3,73 +3,25 @@ | |||
| 3 | 3 | ||
| 4 | #pragma once | 4 | #pragma once |
| 5 | 5 | ||
| 6 | #include <QCheckBox> | 6 | #include <memory> |
| 7 | #include <QComboBox> | 7 | #include <vector> |
| 8 | #include "common/settings.h" | 8 | #include <QString> |
| 9 | #include <QWidget> | ||
| 10 | #include <qobjectdefs.h> | ||
| 9 | 11 | ||
| 10 | namespace ConfigurationShared { | 12 | class QObject; |
| 11 | |||
| 12 | constexpr int USE_GLOBAL_INDEX = 0; | ||
| 13 | constexpr int USE_GLOBAL_SEPARATOR_INDEX = 1; | ||
| 14 | constexpr int USE_GLOBAL_OFFSET = 2; | ||
| 15 | |||
| 16 | // CheckBoxes require a tracker for their state since we emulate a tristate CheckBox | ||
| 17 | enum class CheckState { | ||
| 18 | Off, // Checkbox overrides to off/false | ||
| 19 | On, // Checkbox overrides to on/true | ||
| 20 | Global, // Checkbox defers to the global state | ||
| 21 | Count, // Simply the number of states, not a valid checkbox state | ||
| 22 | }; | ||
| 23 | |||
| 24 | // Global-aware apply and set functions | ||
| 25 | |||
| 26 | // ApplyPerGameSetting, given a Settings::Setting and a Qt UI element, properly applies a Setting | ||
| 27 | void ApplyPerGameSetting(Settings::SwitchableSetting<bool>* setting, const QCheckBox* checkbox, | ||
| 28 | const CheckState& tracker); | ||
| 29 | template <typename Type, bool ranged> | ||
| 30 | void ApplyPerGameSetting(Settings::SwitchableSetting<Type, ranged>* setting, | ||
| 31 | const QComboBox* combobox) { | ||
| 32 | if (Settings::IsConfiguringGlobal() && setting->UsingGlobal()) { | ||
| 33 | setting->SetValue(static_cast<Type>(combobox->currentIndex())); | ||
| 34 | } else if (!Settings::IsConfiguringGlobal()) { | ||
| 35 | if (combobox->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) { | ||
| 36 | setting->SetGlobal(true); | ||
| 37 | } else { | ||
| 38 | setting->SetGlobal(false); | ||
| 39 | setting->SetValue(static_cast<Type>(combobox->currentIndex() - | ||
| 40 | ConfigurationShared::USE_GLOBAL_OFFSET)); | ||
| 41 | } | ||
| 42 | } | ||
| 43 | } | ||
| 44 | 13 | ||
| 45 | // Sets a Qt UI element given a Settings::Setting | 14 | namespace ConfigurationShared { |
| 46 | void SetPerGameSetting(QCheckBox* checkbox, const Settings::SwitchableSetting<bool>* setting); | ||
| 47 | |||
| 48 | template <typename Type, bool ranged> | ||
| 49 | void SetPerGameSetting(QComboBox* combobox, | ||
| 50 | const Settings::SwitchableSetting<Type, ranged>* setting) { | ||
| 51 | combobox->setCurrentIndex(setting->UsingGlobal() ? ConfigurationShared::USE_GLOBAL_INDEX | ||
| 52 | : static_cast<int>(setting->GetValue()) + | ||
| 53 | ConfigurationShared::USE_GLOBAL_OFFSET); | ||
| 54 | } | ||
| 55 | |||
| 56 | // (Un)highlights a Qt UI element | ||
| 57 | void SetHighlight(QWidget* widget, bool highlighted); | ||
| 58 | |||
| 59 | // Sets up a QCheckBox like a tristate one, given a Setting | ||
| 60 | void SetColoredTristate(QCheckBox* checkbox, const Settings::SwitchableSetting<bool>& setting, | ||
| 61 | CheckState& tracker); | ||
| 62 | void SetColoredTristate(QCheckBox* checkbox, bool global, bool state, bool global_state, | ||
| 63 | CheckState& tracker); | ||
| 64 | 15 | ||
| 65 | // Sets up coloring of a QWidget `target` based on the state of a QComboBox, and calls | 16 | class Tab : public QWidget { |
| 66 | // InsertGlobalItem | 17 | Q_OBJECT |
| 67 | void SetColoredComboBox(QComboBox* combobox, QWidget* target, int global); | ||
| 68 | 18 | ||
| 69 | // Adds the "Use Global Configuration" selection and separator to the beginning of a QComboBox | 19 | public: |
| 70 | void InsertGlobalItem(QComboBox* combobox, int global_index); | 20 | explicit Tab(std::shared_ptr<std::vector<Tab*>> group, QWidget* parent = nullptr); |
| 21 | ~Tab(); | ||
| 71 | 22 | ||
| 72 | // Returns the correct index of a QComboBox taking into account global configuration | 23 | virtual void ApplyConfiguration() = 0; |
| 73 | int GetComboboxIndex(int global_setting_index, const QComboBox* combobox); | 24 | virtual void SetConfiguration() = 0; |
| 25 | }; | ||
| 74 | 26 | ||
| 75 | } // namespace ConfigurationShared | 27 | } // namespace ConfigurationShared |
diff --git a/src/yuzu/configuration/configure.ui b/src/yuzu/configuration/configure.ui index eb8078467..573c40801 100644 --- a/src/yuzu/configuration/configure.ui +++ b/src/yuzu/configuration/configure.ui | |||
| @@ -48,11 +48,34 @@ | |||
| 48 | </layout> | 48 | </layout> |
| 49 | </item> | 49 | </item> |
| 50 | <item> | 50 | <item> |
| 51 | <widget class="QDialogButtonBox" name="buttonBox"> | 51 | <layout class="QHBoxLayout" name="horizontalLayout_2"> |
| 52 | <property name="standardButtons"> | 52 | <property name="leftMargin"> |
| 53 | <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> | 53 | <number>0</number> |
| 54 | </property> | 54 | </property> |
| 55 | </widget> | 55 | <property name="topMargin"> |
| 56 | <number>0</number> | ||
| 57 | </property> | ||
| 58 | <property name="rightMargin"> | ||
| 59 | <number>0</number> | ||
| 60 | </property> | ||
| 61 | <property name="bottomMargin"> | ||
| 62 | <number>0</number> | ||
| 63 | </property> | ||
| 64 | <item> | ||
| 65 | <widget class="QLabel" name="label"> | ||
| 66 | <property name="text"> | ||
| 67 | <string>Some settings are only available when a game is not running.</string> | ||
| 68 | </property> | ||
| 69 | </widget> | ||
| 70 | </item> | ||
| 71 | <item> | ||
| 72 | <widget class="QDialogButtonBox" name="buttonBox"> | ||
| 73 | <property name="standardButtons"> | ||
| 74 | <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> | ||
| 75 | </property> | ||
| 76 | </widget> | ||
| 77 | </item> | ||
| 78 | </layout> | ||
| 56 | </item> | 79 | </item> |
| 57 | </layout> | 80 | </layout> |
| 58 | </widget> | 81 | </widget> |
diff --git a/src/yuzu/configuration/configure_audio.cpp b/src/yuzu/configuration/configure_audio.cpp index fcd6d61a0..9ccfb2435 100644 --- a/src/yuzu/configuration/configure_audio.cpp +++ b/src/yuzu/configuration/configure_audio.cpp | |||
| @@ -1,87 +1,112 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include <map> | ||
| 4 | #include <memory> | 5 | #include <memory> |
| 6 | #include <vector> | ||
| 7 | #include <QComboBox> | ||
| 5 | 8 | ||
| 6 | #include "audio_core/sink/sink.h" | 9 | #include "audio_core/sink/sink.h" |
| 7 | #include "audio_core/sink/sink_details.h" | 10 | #include "audio_core/sink/sink_details.h" |
| 11 | #include "common/common_types.h" | ||
| 8 | #include "common/settings.h" | 12 | #include "common/settings.h" |
| 13 | #include "common/settings_common.h" | ||
| 9 | #include "core/core.h" | 14 | #include "core/core.h" |
| 10 | #include "ui_configure_audio.h" | 15 | #include "ui_configure_audio.h" |
| 11 | #include "yuzu/configuration/configuration_shared.h" | 16 | #include "yuzu/configuration/configuration_shared.h" |
| 12 | #include "yuzu/configuration/configure_audio.h" | 17 | #include "yuzu/configuration/configure_audio.h" |
| 18 | #include "yuzu/configuration/shared_translation.h" | ||
| 19 | #include "yuzu/configuration/shared_widget.h" | ||
| 13 | #include "yuzu/uisettings.h" | 20 | #include "yuzu/uisettings.h" |
| 14 | 21 | ||
| 15 | ConfigureAudio::ConfigureAudio(const Core::System& system_, QWidget* parent) | 22 | ConfigureAudio::ConfigureAudio(const Core::System& system_, |
| 16 | : QWidget(parent), ui(std::make_unique<Ui::ConfigureAudio>()), system{system_} { | 23 | std::shared_ptr<std::vector<ConfigurationShared::Tab*>> group_, |
| 24 | const ConfigurationShared::Builder& builder, QWidget* parent) | ||
| 25 | : Tab(group_, parent), ui(std::make_unique<Ui::ConfigureAudio>()), system{system_} { | ||
| 17 | ui->setupUi(this); | 26 | ui->setupUi(this); |
| 27 | Setup(builder); | ||
| 18 | 28 | ||
| 19 | InitializeAudioSinkComboBox(); | 29 | SetConfiguration(); |
| 30 | } | ||
| 20 | 31 | ||
| 21 | connect(ui->volume_slider, &QSlider::valueChanged, this, | 32 | ConfigureAudio::~ConfigureAudio() = default; |
| 22 | &ConfigureAudio::SetVolumeIndicatorText); | ||
| 23 | connect(ui->sink_combo_box, qOverload<int>(&QComboBox::currentIndexChanged), this, | ||
| 24 | &ConfigureAudio::UpdateAudioDevices); | ||
| 25 | 33 | ||
| 26 | ui->volume_label->setVisible(Settings::IsConfiguringGlobal()); | 34 | void ConfigureAudio::Setup(const ConfigurationShared::Builder& builder) { |
| 27 | ui->volume_combo_box->setVisible(!Settings::IsConfiguringGlobal()); | 35 | auto& layout = *ui->audio_widget->layout(); |
| 28 | 36 | ||
| 29 | SetupPerGameUI(); | 37 | std::vector<Settings::BasicSetting*> settings; |
| 30 | 38 | ||
| 31 | SetConfiguration(); | 39 | std::map<u32, QWidget*> hold; |
| 32 | 40 | ||
| 33 | const bool is_powered_on = system_.IsPoweredOn(); | 41 | auto push = [&](Settings::Category category) { |
| 34 | ui->sink_combo_box->setEnabled(!is_powered_on); | 42 | for (auto* setting : Settings::values.linkage.by_category[category]) { |
| 35 | ui->output_combo_box->setEnabled(!is_powered_on); | 43 | settings.push_back(setting); |
| 36 | ui->input_combo_box->setEnabled(!is_powered_on); | 44 | } |
| 37 | } | 45 | }; |
| 38 | 46 | ||
| 39 | ConfigureAudio::~ConfigureAudio() = default; | 47 | push(Settings::Category::Audio); |
| 48 | push(Settings::Category::SystemAudio); | ||
| 40 | 49 | ||
| 41 | void ConfigureAudio::SetConfiguration() { | 50 | for (auto* setting : settings) { |
| 42 | SetOutputSinkFromSinkID(); | 51 | auto* widget = builder.BuildWidget(setting, apply_funcs); |
| 43 | 52 | ||
| 44 | // The device list cannot be pre-populated (nor listed) until the output sink is known. | 53 | if (widget == nullptr) { |
| 45 | UpdateAudioDevices(ui->sink_combo_box->currentIndex()); | 54 | continue; |
| 55 | } | ||
| 56 | if (!widget->Valid()) { | ||
| 57 | widget->deleteLater(); | ||
| 58 | continue; | ||
| 59 | } | ||
| 46 | 60 | ||
| 47 | SetAudioDevicesFromDeviceID(); | 61 | hold.emplace(std::pair{setting->Id(), widget}); |
| 62 | |||
| 63 | if (setting->Id() == Settings::values.sink_id.Id()) { | ||
| 64 | // TODO (lat9nq): Let the system manage sink_id | ||
| 65 | sink_combo_box = widget->combobox; | ||
| 66 | InitializeAudioSinkComboBox(); | ||
| 67 | |||
| 68 | connect(sink_combo_box, qOverload<int>(&QComboBox::currentIndexChanged), this, | ||
| 69 | &ConfigureAudio::UpdateAudioDevices); | ||
| 70 | } else if (setting->Id() == Settings::values.audio_output_device_id.Id()) { | ||
| 71 | // Keep track of output (and input) device comboboxes to populate them with system | ||
| 72 | // devices, which are determined at run time | ||
| 73 | output_device_combo_box = widget->combobox; | ||
| 74 | } else if (setting->Id() == Settings::values.audio_input_device_id.Id()) { | ||
| 75 | input_device_combo_box = widget->combobox; | ||
| 76 | } | ||
| 77 | } | ||
| 48 | 78 | ||
| 49 | const auto volume_value = static_cast<int>(Settings::values.volume.GetValue()); | 79 | for (const auto& [id, widget] : hold) { |
| 50 | ui->volume_slider->setValue(volume_value); | 80 | layout.addWidget(widget); |
| 51 | ui->toggle_background_mute->setChecked(UISettings::values.mute_when_in_background.GetValue()); | 81 | } |
| 82 | } | ||
| 52 | 83 | ||
| 84 | void ConfigureAudio::SetConfiguration() { | ||
| 53 | if (!Settings::IsConfiguringGlobal()) { | 85 | if (!Settings::IsConfiguringGlobal()) { |
| 54 | if (Settings::values.volume.UsingGlobal()) { | 86 | return; |
| 55 | ui->volume_combo_box->setCurrentIndex(0); | ||
| 56 | ui->volume_slider->setEnabled(false); | ||
| 57 | } else { | ||
| 58 | ui->volume_combo_box->setCurrentIndex(1); | ||
| 59 | ui->volume_slider->setEnabled(true); | ||
| 60 | } | ||
| 61 | ConfigurationShared::SetPerGameSetting(ui->combo_sound, &Settings::values.sound_index); | ||
| 62 | ConfigurationShared::SetHighlight(ui->mode_label, | ||
| 63 | !Settings::values.sound_index.UsingGlobal()); | ||
| 64 | ConfigurationShared::SetHighlight(ui->volume_layout, | ||
| 65 | !Settings::values.volume.UsingGlobal()); | ||
| 66 | } else { | ||
| 67 | ui->combo_sound->setCurrentIndex(Settings::values.sound_index.GetValue()); | ||
| 68 | } | 87 | } |
| 69 | SetVolumeIndicatorText(ui->volume_slider->sliderPosition()); | 88 | |
| 89 | SetOutputSinkFromSinkID(); | ||
| 90 | |||
| 91 | // The device list cannot be pre-populated (nor listed) until the output sink is known. | ||
| 92 | UpdateAudioDevices(sink_combo_box->currentIndex()); | ||
| 93 | |||
| 94 | SetAudioDevicesFromDeviceID(); | ||
| 70 | } | 95 | } |
| 71 | 96 | ||
| 72 | void ConfigureAudio::SetOutputSinkFromSinkID() { | 97 | void ConfigureAudio::SetOutputSinkFromSinkID() { |
| 73 | [[maybe_unused]] const QSignalBlocker blocker(ui->sink_combo_box); | 98 | [[maybe_unused]] const QSignalBlocker blocker(sink_combo_box); |
| 74 | 99 | ||
| 75 | int new_sink_index = 0; | 100 | int new_sink_index = 0; |
| 76 | const QString sink_id = QString::fromStdString(Settings::values.sink_id.GetValue()); | 101 | const QString sink_id = QString::fromStdString(Settings::values.sink_id.ToString()); |
| 77 | for (int index = 0; index < ui->sink_combo_box->count(); index++) { | 102 | for (int index = 0; index < sink_combo_box->count(); index++) { |
| 78 | if (ui->sink_combo_box->itemText(index) == sink_id) { | 103 | if (sink_combo_box->itemText(index) == sink_id) { |
| 79 | new_sink_index = index; | 104 | new_sink_index = index; |
| 80 | break; | 105 | break; |
| 81 | } | 106 | } |
| 82 | } | 107 | } |
| 83 | 108 | ||
| 84 | ui->sink_combo_box->setCurrentIndex(new_sink_index); | 109 | sink_combo_box->setCurrentIndex(new_sink_index); |
| 85 | } | 110 | } |
| 86 | 111 | ||
| 87 | void ConfigureAudio::SetAudioDevicesFromDeviceID() { | 112 | void ConfigureAudio::SetAudioDevicesFromDeviceID() { |
| @@ -89,57 +114,42 @@ void ConfigureAudio::SetAudioDevicesFromDeviceID() { | |||
| 89 | 114 | ||
| 90 | const QString output_device_id = | 115 | const QString output_device_id = |
| 91 | QString::fromStdString(Settings::values.audio_output_device_id.GetValue()); | 116 | QString::fromStdString(Settings::values.audio_output_device_id.GetValue()); |
| 92 | for (int index = 0; index < ui->output_combo_box->count(); index++) { | 117 | for (int index = 0; index < output_device_combo_box->count(); index++) { |
| 93 | if (ui->output_combo_box->itemText(index) == output_device_id) { | 118 | if (output_device_combo_box->itemText(index) == output_device_id) { |
| 94 | new_device_index = index; | 119 | new_device_index = index; |
| 95 | break; | 120 | break; |
| 96 | } | 121 | } |
| 97 | } | 122 | } |
| 98 | 123 | ||
| 99 | ui->output_combo_box->setCurrentIndex(new_device_index); | 124 | output_device_combo_box->setCurrentIndex(new_device_index); |
| 100 | 125 | ||
| 101 | new_device_index = -1; | 126 | new_device_index = -1; |
| 102 | const QString input_device_id = | 127 | const QString input_device_id = |
| 103 | QString::fromStdString(Settings::values.audio_input_device_id.GetValue()); | 128 | QString::fromStdString(Settings::values.audio_input_device_id.GetValue()); |
| 104 | for (int index = 0; index < ui->input_combo_box->count(); index++) { | 129 | for (int index = 0; index < input_device_combo_box->count(); index++) { |
| 105 | if (ui->input_combo_box->itemText(index) == input_device_id) { | 130 | if (input_device_combo_box->itemText(index) == input_device_id) { |
| 106 | new_device_index = index; | 131 | new_device_index = index; |
| 107 | break; | 132 | break; |
| 108 | } | 133 | } |
| 109 | } | 134 | } |
| 110 | 135 | ||
| 111 | ui->input_combo_box->setCurrentIndex(new_device_index); | 136 | input_device_combo_box->setCurrentIndex(new_device_index); |
| 112 | } | ||
| 113 | |||
| 114 | void ConfigureAudio::SetVolumeIndicatorText(int percentage) { | ||
| 115 | ui->volume_indicator->setText(tr("%1%", "Volume percentage (e.g. 50%)").arg(percentage)); | ||
| 116 | } | 137 | } |
| 117 | 138 | ||
| 118 | void ConfigureAudio::ApplyConfiguration() { | 139 | void ConfigureAudio::ApplyConfiguration() { |
| 119 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.sound_index, ui->combo_sound); | 140 | const bool is_powered_on = system.IsPoweredOn(); |
| 141 | for (const auto& apply_func : apply_funcs) { | ||
| 142 | apply_func(is_powered_on); | ||
| 143 | } | ||
| 120 | 144 | ||
| 121 | if (Settings::IsConfiguringGlobal()) { | 145 | if (Settings::IsConfiguringGlobal()) { |
| 122 | Settings::values.sink_id = | 146 | Settings::values.sink_id.LoadString( |
| 123 | ui->sink_combo_box->itemText(ui->sink_combo_box->currentIndex()).toStdString(); | 147 | sink_combo_box->itemText(sink_combo_box->currentIndex()).toStdString()); |
| 124 | Settings::values.audio_output_device_id.SetValue( | 148 | Settings::values.audio_output_device_id.SetValue( |
| 125 | ui->output_combo_box->itemText(ui->output_combo_box->currentIndex()).toStdString()); | 149 | output_device_combo_box->itemText(output_device_combo_box->currentIndex()) |
| 150 | .toStdString()); | ||
| 126 | Settings::values.audio_input_device_id.SetValue( | 151 | Settings::values.audio_input_device_id.SetValue( |
| 127 | ui->input_combo_box->itemText(ui->input_combo_box->currentIndex()).toStdString()); | 152 | input_device_combo_box->itemText(input_device_combo_box->currentIndex()).toStdString()); |
| 128 | UISettings::values.mute_when_in_background = ui->toggle_background_mute->isChecked(); | ||
| 129 | |||
| 130 | // Guard if during game and set to game-specific value | ||
| 131 | if (Settings::values.volume.UsingGlobal()) { | ||
| 132 | const auto volume = static_cast<u8>(ui->volume_slider->value()); | ||
| 133 | Settings::values.volume.SetValue(volume); | ||
| 134 | } | ||
| 135 | } else { | ||
| 136 | if (ui->volume_combo_box->currentIndex() == 0) { | ||
| 137 | Settings::values.volume.SetGlobal(true); | ||
| 138 | } else { | ||
| 139 | Settings::values.volume.SetGlobal(false); | ||
| 140 | const auto volume = static_cast<u8>(ui->volume_slider->value()); | ||
| 141 | Settings::values.volume.SetValue(volume); | ||
| 142 | } | ||
| 143 | } | 153 | } |
| 144 | } | 154 | } |
| 145 | 155 | ||
| @@ -152,54 +162,31 @@ void ConfigureAudio::changeEvent(QEvent* event) { | |||
| 152 | } | 162 | } |
| 153 | 163 | ||
| 154 | void ConfigureAudio::UpdateAudioDevices(int sink_index) { | 164 | void ConfigureAudio::UpdateAudioDevices(int sink_index) { |
| 155 | ui->output_combo_box->clear(); | 165 | output_device_combo_box->clear(); |
| 156 | ui->output_combo_box->addItem(QString::fromUtf8(AudioCore::Sink::auto_device_name)); | 166 | output_device_combo_box->addItem(QString::fromUtf8(AudioCore::Sink::auto_device_name)); |
| 157 | 167 | ||
| 158 | const std::string sink_id = ui->sink_combo_box->itemText(sink_index).toStdString(); | 168 | const auto sink_id = |
| 169 | Settings::ToEnum<Settings::AudioEngine>(sink_combo_box->itemText(sink_index).toStdString()); | ||
| 159 | for (const auto& device : AudioCore::Sink::GetDeviceListForSink(sink_id, false)) { | 170 | for (const auto& device : AudioCore::Sink::GetDeviceListForSink(sink_id, false)) { |
| 160 | ui->output_combo_box->addItem(QString::fromStdString(device)); | 171 | output_device_combo_box->addItem(QString::fromStdString(device)); |
| 161 | } | 172 | } |
| 162 | 173 | ||
| 163 | ui->input_combo_box->clear(); | 174 | input_device_combo_box->clear(); |
| 164 | ui->input_combo_box->addItem(QString::fromUtf8(AudioCore::Sink::auto_device_name)); | 175 | input_device_combo_box->addItem(QString::fromUtf8(AudioCore::Sink::auto_device_name)); |
| 165 | for (const auto& device : AudioCore::Sink::GetDeviceListForSink(sink_id, true)) { | 176 | for (const auto& device : AudioCore::Sink::GetDeviceListForSink(sink_id, true)) { |
| 166 | ui->input_combo_box->addItem(QString::fromStdString(device)); | 177 | input_device_combo_box->addItem(QString::fromStdString(device)); |
| 167 | } | 178 | } |
| 168 | } | 179 | } |
| 169 | 180 | ||
| 170 | void ConfigureAudio::InitializeAudioSinkComboBox() { | 181 | void ConfigureAudio::InitializeAudioSinkComboBox() { |
| 171 | ui->sink_combo_box->clear(); | 182 | sink_combo_box->clear(); |
| 172 | ui->sink_combo_box->addItem(QString::fromUtf8(AudioCore::Sink::auto_device_name)); | 183 | sink_combo_box->addItem(QString::fromUtf8(AudioCore::Sink::auto_device_name)); |
| 173 | 184 | ||
| 174 | for (const auto& id : AudioCore::Sink::GetSinkIDs()) { | 185 | for (const auto& id : AudioCore::Sink::GetSinkIDs()) { |
| 175 | ui->sink_combo_box->addItem(QString::fromUtf8(id.data(), static_cast<s32>(id.length()))); | 186 | sink_combo_box->addItem(QString::fromStdString(Settings::CanonicalizeEnum(id))); |
| 176 | } | 187 | } |
| 177 | } | 188 | } |
| 178 | 189 | ||
| 179 | void ConfigureAudio::RetranslateUI() { | 190 | void ConfigureAudio::RetranslateUI() { |
| 180 | ui->retranslateUi(this); | 191 | ui->retranslateUi(this); |
| 181 | SetVolumeIndicatorText(ui->volume_slider->sliderPosition()); | ||
| 182 | } | ||
| 183 | |||
| 184 | void ConfigureAudio::SetupPerGameUI() { | ||
| 185 | if (Settings::IsConfiguringGlobal()) { | ||
| 186 | ui->combo_sound->setEnabled(Settings::values.sound_index.UsingGlobal()); | ||
| 187 | ui->volume_slider->setEnabled(Settings::values.volume.UsingGlobal()); | ||
| 188 | return; | ||
| 189 | } | ||
| 190 | |||
| 191 | ConfigurationShared::SetColoredComboBox(ui->combo_sound, ui->mode_label, | ||
| 192 | Settings::values.sound_index.GetValue(true)); | ||
| 193 | |||
| 194 | connect(ui->volume_combo_box, qOverload<int>(&QComboBox::activated), this, [this](int index) { | ||
| 195 | ui->volume_slider->setEnabled(index == 1); | ||
| 196 | ConfigurationShared::SetHighlight(ui->volume_layout, index == 1); | ||
| 197 | }); | ||
| 198 | |||
| 199 | ui->sink_combo_box->setVisible(false); | ||
| 200 | ui->sink_label->setVisible(false); | ||
| 201 | ui->output_combo_box->setVisible(false); | ||
| 202 | ui->output_label->setVisible(false); | ||
| 203 | ui->input_combo_box->setVisible(false); | ||
| 204 | ui->input_label->setVisible(false); | ||
| 205 | } | 192 | } |
diff --git a/src/yuzu/configuration/configure_audio.h b/src/yuzu/configuration/configure_audio.h index 0d03aae1d..79538e81c 100644 --- a/src/yuzu/configuration/configure_audio.h +++ b/src/yuzu/configuration/configure_audio.h | |||
| @@ -3,30 +3,35 @@ | |||
| 3 | 3 | ||
| 4 | #pragma once | 4 | #pragma once |
| 5 | 5 | ||
| 6 | #include <functional> | ||
| 6 | #include <memory> | 7 | #include <memory> |
| 8 | #include <vector> | ||
| 7 | #include <QWidget> | 9 | #include <QWidget> |
| 10 | #include "yuzu/configuration/configuration_shared.h" | ||
| 11 | |||
| 12 | class QComboBox; | ||
| 8 | 13 | ||
| 9 | namespace Core { | 14 | namespace Core { |
| 10 | class System; | 15 | class System; |
| 11 | } | 16 | } |
| 12 | 17 | ||
| 13 | namespace ConfigurationShared { | ||
| 14 | enum class CheckState; | ||
| 15 | } | ||
| 16 | |||
| 17 | namespace Ui { | 18 | namespace Ui { |
| 18 | class ConfigureAudio; | 19 | class ConfigureAudio; |
| 19 | } | 20 | } |
| 20 | 21 | ||
| 21 | class ConfigureAudio : public QWidget { | 22 | namespace ConfigurationShared { |
| 22 | Q_OBJECT | 23 | class Builder; |
| 24 | } | ||
| 23 | 25 | ||
| 26 | class ConfigureAudio : public ConfigurationShared::Tab { | ||
| 24 | public: | 27 | public: |
| 25 | explicit ConfigureAudio(const Core::System& system_, QWidget* parent = nullptr); | 28 | explicit ConfigureAudio(const Core::System& system_, |
| 29 | std::shared_ptr<std::vector<ConfigurationShared::Tab*>> group, | ||
| 30 | const ConfigurationShared::Builder& builder, QWidget* parent = nullptr); | ||
| 26 | ~ConfigureAudio() override; | 31 | ~ConfigureAudio() override; |
| 27 | 32 | ||
| 28 | void ApplyConfiguration(); | 33 | void ApplyConfiguration() override; |
| 29 | void SetConfiguration(); | 34 | void SetConfiguration() override; |
| 30 | 35 | ||
| 31 | private: | 36 | private: |
| 32 | void changeEvent(QEvent* event) override; | 37 | void changeEvent(QEvent* event) override; |
| @@ -39,11 +44,16 @@ private: | |||
| 39 | 44 | ||
| 40 | void SetOutputSinkFromSinkID(); | 45 | void SetOutputSinkFromSinkID(); |
| 41 | void SetAudioDevicesFromDeviceID(); | 46 | void SetAudioDevicesFromDeviceID(); |
| 42 | void SetVolumeIndicatorText(int percentage); | ||
| 43 | 47 | ||
| 44 | void SetupPerGameUI(); | 48 | void Setup(const ConfigurationShared::Builder& builder); |
| 45 | 49 | ||
| 46 | std::unique_ptr<Ui::ConfigureAudio> ui; | 50 | std::unique_ptr<Ui::ConfigureAudio> ui; |
| 47 | 51 | ||
| 48 | const Core::System& system; | 52 | const Core::System& system; |
| 53 | |||
| 54 | std::vector<std::function<void(bool)>> apply_funcs{}; | ||
| 55 | |||
| 56 | QComboBox* sink_combo_box; | ||
| 57 | QComboBox* output_device_combo_box; | ||
| 58 | QComboBox* input_device_combo_box; | ||
| 49 | }; | 59 | }; |
diff --git a/src/yuzu/configuration/configure_audio.ui b/src/yuzu/configuration/configure_audio.ui index 4128c83ad..1181aeb00 100644 --- a/src/yuzu/configuration/configure_audio.ui +++ b/src/yuzu/configuration/configure_audio.ui | |||
| @@ -21,80 +21,14 @@ | |||
| 21 | </property> | 21 | </property> |
| 22 | <layout class="QVBoxLayout"> | 22 | <layout class="QVBoxLayout"> |
| 23 | <item> | 23 | <item> |
| 24 | <layout class="QHBoxLayout" name="engine_layout"> | 24 | <widget class="QWidget" name="audio_widget" native="true"> |
| 25 | <item> | 25 | <property name="maximumSize"> |
| 26 | <widget class="QLabel" name="sink_label"> | 26 | <size> |
| 27 | <property name="text"> | 27 | <width>16777215</width> |
| 28 | <string>Output Engine:</string> | 28 | <height>16777213</height> |
| 29 | </property> | 29 | </size> |
| 30 | </widget> | 30 | </property> |
| 31 | </item> | 31 | <layout class="QVBoxLayout" name="verticalLayout"> |
| 32 | <item> | ||
| 33 | <widget class="QComboBox" name="sink_combo_box"/> | ||
| 34 | </item> | ||
| 35 | </layout> | ||
| 36 | </item> | ||
| 37 | <item> | ||
| 38 | <layout class="QHBoxLayout" name="output_layout"> | ||
| 39 | <item> | ||
| 40 | <widget class="QLabel" name="output_label"> | ||
| 41 | <property name="text"> | ||
| 42 | <string>Output Device:</string> | ||
| 43 | </property> | ||
| 44 | </widget> | ||
| 45 | </item> | ||
| 46 | <item> | ||
| 47 | <widget class="QComboBox" name="output_combo_box"/> | ||
| 48 | </item> | ||
| 49 | </layout> | ||
| 50 | </item> | ||
| 51 | <item> | ||
| 52 | <layout class="QHBoxLayout" name="input_layout"> | ||
| 53 | <item> | ||
| 54 | <widget class="QLabel" name="input_label"> | ||
| 55 | <property name="text"> | ||
| 56 | <string>Input Device:</string> | ||
| 57 | </property> | ||
| 58 | </widget> | ||
| 59 | </item> | ||
| 60 | <item> | ||
| 61 | <widget class="QComboBox" name="input_combo_box"/> | ||
| 62 | </item> | ||
| 63 | </layout> | ||
| 64 | </item> | ||
| 65 | <item> | ||
| 66 | <layout class="QHBoxLayout" name="mode_layout"> | ||
| 67 | <item> | ||
| 68 | <widget class="QLabel" name="mode_label"> | ||
| 69 | <property name="text"> | ||
| 70 | <string>Sound Output Mode:</string> | ||
| 71 | </property> | ||
| 72 | </widget> | ||
| 73 | </item> | ||
| 74 | <item> | ||
| 75 | <widget class="QComboBox" name="combo_sound"> | ||
| 76 | <item> | ||
| 77 | <property name="text"> | ||
| 78 | <string>Mono</string> | ||
| 79 | </property> | ||
| 80 | </item> | ||
| 81 | <item> | ||
| 82 | <property name="text"> | ||
| 83 | <string>Stereo</string> | ||
| 84 | </property> | ||
| 85 | </item> | ||
| 86 | <item> | ||
| 87 | <property name="text"> | ||
| 88 | <string>Surround</string> | ||
| 89 | </property> | ||
| 90 | </item> | ||
| 91 | </widget> | ||
| 92 | </item> | ||
| 93 | </layout> | ||
| 94 | </item> | ||
| 95 | <item> | ||
| 96 | <widget class="QWidget" name="volume_layout" native="true"> | ||
| 97 | <layout class="QHBoxLayout" name="horizontalLayout_2"> | ||
| 98 | <property name="leftMargin"> | 32 | <property name="leftMargin"> |
| 99 | <number>0</number> | 33 | <number>0</number> |
| 100 | </property> | 34 | </property> |
| @@ -107,89 +41,9 @@ | |||
| 107 | <property name="bottomMargin"> | 41 | <property name="bottomMargin"> |
| 108 | <number>0</number> | 42 | <number>0</number> |
| 109 | </property> | 43 | </property> |
| 110 | <item> | ||
| 111 | <widget class="QComboBox" name="volume_combo_box"> | ||
| 112 | <item> | ||
| 113 | <property name="text"> | ||
| 114 | <string>Use global volume</string> | ||
| 115 | </property> | ||
| 116 | </item> | ||
| 117 | <item> | ||
| 118 | <property name="text"> | ||
| 119 | <string>Set volume:</string> | ||
| 120 | </property> | ||
| 121 | </item> | ||
| 122 | </widget> | ||
| 123 | </item> | ||
| 124 | <item> | ||
| 125 | <widget class="QLabel" name="volume_label"> | ||
| 126 | <property name="text"> | ||
| 127 | <string>Volume:</string> | ||
| 128 | </property> | ||
| 129 | </widget> | ||
| 130 | </item> | ||
| 131 | <item> | ||
| 132 | <spacer name="horizontalSpacer"> | ||
| 133 | <property name="orientation"> | ||
| 134 | <enum>Qt::Horizontal</enum> | ||
| 135 | </property> | ||
| 136 | <property name="sizeHint" stdset="0"> | ||
| 137 | <size> | ||
| 138 | <width>30</width> | ||
| 139 | <height>20</height> | ||
| 140 | </size> | ||
| 141 | </property> | ||
| 142 | </spacer> | ||
| 143 | </item> | ||
| 144 | <item> | ||
| 145 | <widget class="QSlider" name="volume_slider"> | ||
| 146 | <property name="sizePolicy"> | ||
| 147 | <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> | ||
| 148 | <horstretch>0</horstretch> | ||
| 149 | <verstretch>0</verstretch> | ||
| 150 | </sizepolicy> | ||
| 151 | </property> | ||
| 152 | <property name="maximum"> | ||
| 153 | <number>200</number> | ||
| 154 | </property> | ||
| 155 | <property name="pageStep"> | ||
| 156 | <number>5</number> | ||
| 157 | </property> | ||
| 158 | <property name="orientation"> | ||
| 159 | <enum>Qt::Horizontal</enum> | ||
| 160 | </property> | ||
| 161 | </widget> | ||
| 162 | </item> | ||
| 163 | <item> | ||
| 164 | <widget class="QLabel" name="volume_indicator"> | ||
| 165 | <property name="minimumSize"> | ||
| 166 | <size> | ||
| 167 | <width>32</width> | ||
| 168 | <height>0</height> | ||
| 169 | </size> | ||
| 170 | </property> | ||
| 171 | <property name="text"> | ||
| 172 | <string>0 %</string> | ||
| 173 | </property> | ||
| 174 | <property name="alignment"> | ||
| 175 | <set>Qt::AlignCenter</set> | ||
| 176 | </property> | ||
| 177 | </widget> | ||
| 178 | </item> | ||
| 179 | </layout> | 44 | </layout> |
| 180 | </widget> | 45 | </widget> |
| 181 | </item> | 46 | </item> |
| 182 | <item> | ||
| 183 | <layout class="QHBoxLayout" name="mute_layout"> | ||
| 184 | <item> | ||
| 185 | <widget class="QCheckBox" name="toggle_background_mute"> | ||
| 186 | <property name="text"> | ||
| 187 | <string>Mute audio when in background</string> | ||
| 188 | </property> | ||
| 189 | </widget> | ||
| 190 | </item> | ||
| 191 | </layout> | ||
| 192 | </item> | ||
| 193 | </layout> | 47 | </layout> |
| 194 | </widget> | 48 | </widget> |
| 195 | </item> | 49 | </item> |
diff --git a/src/yuzu/configuration/configure_cpu.cpp b/src/yuzu/configuration/configure_cpu.cpp index 3d69fb03f..a51359903 100644 --- a/src/yuzu/configuration/configure_cpu.cpp +++ b/src/yuzu/configuration/configure_cpu.cpp | |||
| @@ -1,88 +1,92 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include <memory> | ||
| 5 | #include <typeinfo> | ||
| 6 | #include <vector> | ||
| 7 | #include <QComboBox> | ||
| 4 | #include "common/common_types.h" | 8 | #include "common/common_types.h" |
| 5 | #include "common/settings.h" | 9 | #include "common/settings.h" |
| 10 | #include "common/settings_enums.h" | ||
| 11 | #include "configuration/shared_widget.h" | ||
| 6 | #include "core/core.h" | 12 | #include "core/core.h" |
| 7 | #include "ui_configure_cpu.h" | 13 | #include "ui_configure_cpu.h" |
| 8 | #include "yuzu/configuration/configuration_shared.h" | 14 | #include "yuzu/configuration/configuration_shared.h" |
| 9 | #include "yuzu/configuration/configure_cpu.h" | 15 | #include "yuzu/configuration/configure_cpu.h" |
| 10 | 16 | ||
| 11 | ConfigureCpu::ConfigureCpu(const Core::System& system_, QWidget* parent) | 17 | ConfigureCpu::ConfigureCpu(const Core::System& system_, |
| 12 | : QWidget(parent), ui{std::make_unique<Ui::ConfigureCpu>()}, system{system_} { | 18 | std::shared_ptr<std::vector<ConfigurationShared::Tab*>> group_, |
| 19 | const ConfigurationShared::Builder& builder, QWidget* parent) | ||
| 20 | : Tab(group_, parent), ui{std::make_unique<Ui::ConfigureCpu>()}, system{system_}, | ||
| 21 | combobox_translations(builder.ComboboxTranslations()) { | ||
| 13 | ui->setupUi(this); | 22 | ui->setupUi(this); |
| 14 | 23 | ||
| 15 | SetupPerGameUI(); | 24 | Setup(builder); |
| 16 | 25 | ||
| 17 | SetConfiguration(); | 26 | SetConfiguration(); |
| 18 | 27 | ||
| 19 | connect(ui->accuracy, qOverload<int>(&QComboBox::currentIndexChanged), this, | 28 | connect(accuracy_combobox, qOverload<int>(&QComboBox::currentIndexChanged), this, |
| 20 | &ConfigureCpu::UpdateGroup); | 29 | &ConfigureCpu::UpdateGroup); |
| 21 | } | 30 | } |
| 22 | 31 | ||
| 23 | ConfigureCpu::~ConfigureCpu() = default; | 32 | ConfigureCpu::~ConfigureCpu() = default; |
| 24 | 33 | ||
| 25 | void ConfigureCpu::SetConfiguration() { | 34 | void ConfigureCpu::SetConfiguration() {} |
| 26 | const bool runtime_lock = !system.IsPoweredOn(); | 35 | void ConfigureCpu::Setup(const ConfigurationShared::Builder& builder) { |
| 27 | 36 | auto* accuracy_layout = ui->widget_accuracy->layout(); | |
| 28 | ui->accuracy->setEnabled(runtime_lock); | 37 | auto* unsafe_layout = ui->unsafe_widget->layout(); |
| 29 | ui->cpuopt_unsafe_unfuse_fma->setEnabled(runtime_lock); | 38 | std::map<u32, QWidget*> unsafe_hold{}; |
| 30 | ui->cpuopt_unsafe_reduce_fp_error->setEnabled(runtime_lock); | 39 | |
| 31 | ui->cpuopt_unsafe_ignore_standard_fpcr->setEnabled(runtime_lock); | 40 | std::vector<Settings::BasicSetting*> settings; |
| 32 | ui->cpuopt_unsafe_inaccurate_nan->setEnabled(runtime_lock); | 41 | const auto push = [&](Settings::Category category) { |
| 33 | ui->cpuopt_unsafe_fastmem_check->setEnabled(runtime_lock); | 42 | for (const auto setting : Settings::values.linkage.by_category[category]) { |
| 34 | ui->cpuopt_unsafe_ignore_global_monitor->setEnabled(runtime_lock); | 43 | settings.push_back(setting); |
| 35 | 44 | } | |
| 36 | ui->cpuopt_unsafe_unfuse_fma->setChecked(Settings::values.cpuopt_unsafe_unfuse_fma.GetValue()); | 45 | }; |
| 37 | ui->cpuopt_unsafe_reduce_fp_error->setChecked( | 46 | |
| 38 | Settings::values.cpuopt_unsafe_reduce_fp_error.GetValue()); | 47 | push(Settings::Category::Cpu); |
| 39 | ui->cpuopt_unsafe_ignore_standard_fpcr->setChecked( | 48 | push(Settings::Category::CpuUnsafe); |
| 40 | Settings::values.cpuopt_unsafe_ignore_standard_fpcr.GetValue()); | 49 | |
| 41 | ui->cpuopt_unsafe_inaccurate_nan->setChecked( | 50 | for (const auto setting : settings) { |
| 42 | Settings::values.cpuopt_unsafe_inaccurate_nan.GetValue()); | 51 | auto* widget = builder.BuildWidget(setting, apply_funcs); |
| 43 | ui->cpuopt_unsafe_fastmem_check->setChecked( | 52 | |
| 44 | Settings::values.cpuopt_unsafe_fastmem_check.GetValue()); | 53 | if (widget == nullptr) { |
| 45 | ui->cpuopt_unsafe_ignore_global_monitor->setChecked( | 54 | continue; |
| 46 | Settings::values.cpuopt_unsafe_ignore_global_monitor.GetValue()); | 55 | } |
| 47 | 56 | if (!widget->Valid()) { | |
| 48 | if (Settings::IsConfiguringGlobal()) { | 57 | widget->deleteLater(); |
| 49 | ui->accuracy->setCurrentIndex(static_cast<int>(Settings::values.cpu_accuracy.GetValue())); | 58 | continue; |
| 50 | } else { | 59 | } |
| 51 | ConfigurationShared::SetPerGameSetting(ui->accuracy, &Settings::values.cpu_accuracy); | 60 | |
| 52 | ConfigurationShared::SetHighlight(ui->widget_accuracy, | 61 | if (setting->Id() == Settings::values.cpu_accuracy.Id()) { |
| 53 | !Settings::values.cpu_accuracy.UsingGlobal()); | 62 | // Keep track of cpu_accuracy combobox to display/hide the unsafe settings |
| 63 | accuracy_layout->addWidget(widget); | ||
| 64 | accuracy_combobox = widget->combobox; | ||
| 65 | } else { | ||
| 66 | // Presently, all other settings here are unsafe checkboxes | ||
| 67 | unsafe_hold.insert({setting->Id(), widget}); | ||
| 68 | } | ||
| 54 | } | 69 | } |
| 55 | UpdateGroup(ui->accuracy->currentIndex()); | 70 | |
| 71 | for (const auto& [label, widget] : unsafe_hold) { | ||
| 72 | unsafe_layout->addWidget(widget); | ||
| 73 | } | ||
| 74 | |||
| 75 | UpdateGroup(accuracy_combobox->currentIndex()); | ||
| 56 | } | 76 | } |
| 57 | 77 | ||
| 58 | void ConfigureCpu::UpdateGroup(int index) { | 78 | void ConfigureCpu::UpdateGroup(int index) { |
| 59 | if (!Settings::IsConfiguringGlobal()) { | 79 | const auto accuracy = static_cast<Settings::CpuAccuracy>( |
| 60 | index -= ConfigurationShared::USE_GLOBAL_OFFSET; | 80 | combobox_translations.at(Settings::EnumMetadata<Settings::CpuAccuracy>::Index())[index] |
| 61 | } | 81 | .first); |
| 62 | const auto accuracy = static_cast<Settings::CPUAccuracy>(index); | 82 | ui->unsafe_group->setVisible(accuracy == Settings::CpuAccuracy::Unsafe); |
| 63 | ui->unsafe_group->setVisible(accuracy == Settings::CPUAccuracy::Unsafe); | ||
| 64 | } | 83 | } |
| 65 | 84 | ||
| 66 | void ConfigureCpu::ApplyConfiguration() { | 85 | void ConfigureCpu::ApplyConfiguration() { |
| 67 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.cpu_accuracy, ui->accuracy); | 86 | const bool is_powered_on = system.IsPoweredOn(); |
| 68 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.cpuopt_unsafe_unfuse_fma, | 87 | for (const auto& apply_func : apply_funcs) { |
| 69 | ui->cpuopt_unsafe_unfuse_fma, | 88 | apply_func(is_powered_on); |
| 70 | cpuopt_unsafe_unfuse_fma); | 89 | } |
| 71 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.cpuopt_unsafe_reduce_fp_error, | ||
| 72 | ui->cpuopt_unsafe_reduce_fp_error, | ||
| 73 | cpuopt_unsafe_reduce_fp_error); | ||
| 74 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.cpuopt_unsafe_ignore_standard_fpcr, | ||
| 75 | ui->cpuopt_unsafe_ignore_standard_fpcr, | ||
| 76 | cpuopt_unsafe_ignore_standard_fpcr); | ||
| 77 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.cpuopt_unsafe_inaccurate_nan, | ||
| 78 | ui->cpuopt_unsafe_inaccurate_nan, | ||
| 79 | cpuopt_unsafe_inaccurate_nan); | ||
| 80 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.cpuopt_unsafe_fastmem_check, | ||
| 81 | ui->cpuopt_unsafe_fastmem_check, | ||
| 82 | cpuopt_unsafe_fastmem_check); | ||
| 83 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.cpuopt_unsafe_ignore_global_monitor, | ||
| 84 | ui->cpuopt_unsafe_ignore_global_monitor, | ||
| 85 | cpuopt_unsafe_ignore_global_monitor); | ||
| 86 | } | 90 | } |
| 87 | 91 | ||
| 88 | void ConfigureCpu::changeEvent(QEvent* event) { | 92 | void ConfigureCpu::changeEvent(QEvent* event) { |
| @@ -96,32 +100,3 @@ void ConfigureCpu::changeEvent(QEvent* event) { | |||
| 96 | void ConfigureCpu::RetranslateUI() { | 100 | void ConfigureCpu::RetranslateUI() { |
| 97 | ui->retranslateUi(this); | 101 | ui->retranslateUi(this); |
| 98 | } | 102 | } |
| 99 | |||
| 100 | void ConfigureCpu::SetupPerGameUI() { | ||
| 101 | if (Settings::IsConfiguringGlobal()) { | ||
| 102 | return; | ||
| 103 | } | ||
| 104 | |||
| 105 | ConfigurationShared::SetColoredComboBox( | ||
| 106 | ui->accuracy, ui->widget_accuracy, | ||
| 107 | static_cast<u32>(Settings::values.cpu_accuracy.GetValue(true))); | ||
| 108 | |||
| 109 | ConfigurationShared::SetColoredTristate(ui->cpuopt_unsafe_unfuse_fma, | ||
| 110 | Settings::values.cpuopt_unsafe_unfuse_fma, | ||
| 111 | cpuopt_unsafe_unfuse_fma); | ||
| 112 | ConfigurationShared::SetColoredTristate(ui->cpuopt_unsafe_reduce_fp_error, | ||
| 113 | Settings::values.cpuopt_unsafe_reduce_fp_error, | ||
| 114 | cpuopt_unsafe_reduce_fp_error); | ||
| 115 | ConfigurationShared::SetColoredTristate(ui->cpuopt_unsafe_ignore_standard_fpcr, | ||
| 116 | Settings::values.cpuopt_unsafe_ignore_standard_fpcr, | ||
| 117 | cpuopt_unsafe_ignore_standard_fpcr); | ||
| 118 | ConfigurationShared::SetColoredTristate(ui->cpuopt_unsafe_inaccurate_nan, | ||
| 119 | Settings::values.cpuopt_unsafe_inaccurate_nan, | ||
| 120 | cpuopt_unsafe_inaccurate_nan); | ||
| 121 | ConfigurationShared::SetColoredTristate(ui->cpuopt_unsafe_fastmem_check, | ||
| 122 | Settings::values.cpuopt_unsafe_fastmem_check, | ||
| 123 | cpuopt_unsafe_fastmem_check); | ||
| 124 | ConfigurationShared::SetColoredTristate(ui->cpuopt_unsafe_ignore_global_monitor, | ||
| 125 | Settings::values.cpuopt_unsafe_ignore_global_monitor, | ||
| 126 | cpuopt_unsafe_ignore_global_monitor); | ||
| 127 | } | ||
diff --git a/src/yuzu/configuration/configure_cpu.h b/src/yuzu/configuration/configure_cpu.h index 86d928ca3..61a6de7aa 100644 --- a/src/yuzu/configuration/configure_cpu.h +++ b/src/yuzu/configuration/configure_cpu.h | |||
| @@ -4,29 +4,34 @@ | |||
| 4 | #pragma once | 4 | #pragma once |
| 5 | 5 | ||
| 6 | #include <memory> | 6 | #include <memory> |
| 7 | #include <vector> | ||
| 7 | #include <QWidget> | 8 | #include <QWidget> |
| 9 | #include "yuzu/configuration/configuration_shared.h" | ||
| 10 | #include "yuzu/configuration/shared_translation.h" | ||
| 11 | |||
| 12 | class QComboBox; | ||
| 8 | 13 | ||
| 9 | namespace Core { | 14 | namespace Core { |
| 10 | class System; | 15 | class System; |
| 11 | } | 16 | } |
| 12 | 17 | ||
| 13 | namespace ConfigurationShared { | ||
| 14 | enum class CheckState; | ||
| 15 | } | ||
| 16 | |||
| 17 | namespace Ui { | 18 | namespace Ui { |
| 18 | class ConfigureCpu; | 19 | class ConfigureCpu; |
| 19 | } | 20 | } |
| 20 | 21 | ||
| 21 | class ConfigureCpu : public QWidget { | 22 | namespace ConfigurationShared { |
| 22 | Q_OBJECT | 23 | class Builder; |
| 24 | } | ||
| 23 | 25 | ||
| 26 | class ConfigureCpu : public ConfigurationShared::Tab { | ||
| 24 | public: | 27 | public: |
| 25 | explicit ConfigureCpu(const Core::System& system_, QWidget* parent = nullptr); | 28 | explicit ConfigureCpu(const Core::System& system_, |
| 29 | std::shared_ptr<std::vector<ConfigurationShared::Tab*>> group, | ||
| 30 | const ConfigurationShared::Builder& builder, QWidget* parent = nullptr); | ||
| 26 | ~ConfigureCpu() override; | 31 | ~ConfigureCpu() override; |
| 27 | 32 | ||
| 28 | void ApplyConfiguration(); | 33 | void ApplyConfiguration() override; |
| 29 | void SetConfiguration(); | 34 | void SetConfiguration() override; |
| 30 | 35 | ||
| 31 | private: | 36 | private: |
| 32 | void changeEvent(QEvent* event) override; | 37 | void changeEvent(QEvent* event) override; |
| @@ -34,16 +39,14 @@ private: | |||
| 34 | 39 | ||
| 35 | void UpdateGroup(int index); | 40 | void UpdateGroup(int index); |
| 36 | 41 | ||
| 37 | void SetupPerGameUI(); | 42 | void Setup(const ConfigurationShared::Builder& builder); |
| 38 | 43 | ||
| 39 | std::unique_ptr<Ui::ConfigureCpu> ui; | 44 | std::unique_ptr<Ui::ConfigureCpu> ui; |
| 40 | 45 | ||
| 41 | ConfigurationShared::CheckState cpuopt_unsafe_unfuse_fma; | ||
| 42 | ConfigurationShared::CheckState cpuopt_unsafe_reduce_fp_error; | ||
| 43 | ConfigurationShared::CheckState cpuopt_unsafe_ignore_standard_fpcr; | ||
| 44 | ConfigurationShared::CheckState cpuopt_unsafe_inaccurate_nan; | ||
| 45 | ConfigurationShared::CheckState cpuopt_unsafe_fastmem_check; | ||
| 46 | ConfigurationShared::CheckState cpuopt_unsafe_ignore_global_monitor; | ||
| 47 | |||
| 48 | const Core::System& system; | 46 | const Core::System& system; |
| 47 | |||
| 48 | const ConfigurationShared::ComboboxTranslationMap& combobox_translations; | ||
| 49 | std::vector<std::function<void(bool)>> apply_funcs{}; | ||
| 50 | |||
| 51 | QComboBox* accuracy_combobox; | ||
| 49 | }; | 52 | }; |
diff --git a/src/yuzu/configuration/configure_cpu.ui b/src/yuzu/configuration/configure_cpu.ui index 8ae569ee6..f734e842e 100644 --- a/src/yuzu/configuration/configure_cpu.ui +++ b/src/yuzu/configuration/configure_cpu.ui | |||
| @@ -16,9 +16,12 @@ | |||
| 16 | <property name="accessibleName"> | 16 | <property name="accessibleName"> |
| 17 | <string>CPU</string> | 17 | <string>CPU</string> |
| 18 | </property> | 18 | </property> |
| 19 | <layout class="QVBoxLayout"> | 19 | <layout class="QVBoxLayout" name="vboxlayout_2" stretch="0"> |
| 20 | <item> | 20 | <item> |
| 21 | <layout class="QVBoxLayout"> | 21 | <layout class="QVBoxLayout" name="vboxlayout"> |
| 22 | <property name="bottomMargin"> | ||
| 23 | <number>0</number> | ||
| 24 | </property> | ||
| 22 | <item> | 25 | <item> |
| 23 | <widget class="QGroupBox" name="groupBox"> | 26 | <widget class="QGroupBox" name="groupBox"> |
| 24 | <property name="title"> | 27 | <property name="title"> |
| @@ -27,38 +30,19 @@ | |||
| 27 | <layout class="QVBoxLayout"> | 30 | <layout class="QVBoxLayout"> |
| 28 | <item> | 31 | <item> |
| 29 | <widget class="QWidget" name="widget_accuracy" native="true"> | 32 | <widget class="QWidget" name="widget_accuracy" native="true"> |
| 30 | <layout class="QHBoxLayout" name="layout_accuracy"> | 33 | <layout class="QVBoxLayout" name="verticalLayout"> |
| 31 | <item> | 34 | <property name="leftMargin"> |
| 32 | <widget class="QLabel" name="label_accuracy"> | 35 | <number>0</number> |
| 33 | <property name="text"> | 36 | </property> |
| 34 | <string>Accuracy:</string> | 37 | <property name="topMargin"> |
| 35 | </property> | 38 | <number>0</number> |
| 36 | </widget> | 39 | </property> |
| 37 | </item> | 40 | <property name="rightMargin"> |
| 38 | <item> | 41 | <number>0</number> |
| 39 | <widget class="QComboBox" name="accuracy"> | 42 | </property> |
| 40 | <item> | 43 | <property name="bottomMargin"> |
| 41 | <property name="text"> | 44 | <number>0</number> |
| 42 | <string>Auto</string> | 45 | </property> |
| 43 | </property> | ||
| 44 | </item> | ||
| 45 | <item> | ||
| 46 | <property name="text"> | ||
| 47 | <string>Accurate</string> | ||
| 48 | </property> | ||
| 49 | </item> | ||
| 50 | <item> | ||
| 51 | <property name="text"> | ||
| 52 | <string>Unsafe</string> | ||
| 53 | </property> | ||
| 54 | </item> | ||
| 55 | <item> | ||
| 56 | <property name="text"> | ||
| 57 | <string>Paranoid (disables most optimizations)</string> | ||
| 58 | </property> | ||
| 59 | </item> | ||
| 60 | </widget> | ||
| 61 | </item> | ||
| 62 | </layout> | 46 | </layout> |
| 63 | </widget> | 47 | </widget> |
| 64 | </item> | 48 | </item> |
| @@ -75,10 +59,6 @@ | |||
| 75 | </layout> | 59 | </layout> |
| 76 | </widget> | 60 | </widget> |
| 77 | </item> | 61 | </item> |
| 78 | </layout> | ||
| 79 | </item> | ||
| 80 | <item> | ||
| 81 | <layout class="QVBoxLayout"> | ||
| 82 | <item> | 62 | <item> |
| 83 | <widget class="QGroupBox" name="unsafe_group"> | 63 | <widget class="QGroupBox" name="unsafe_group"> |
| 84 | <property name="title"> | 64 | <property name="title"> |
| @@ -96,105 +76,44 @@ | |||
| 96 | </widget> | 76 | </widget> |
| 97 | </item> | 77 | </item> |
| 98 | <item> | 78 | <item> |
| 99 | <widget class="QCheckBox" name="cpuopt_unsafe_unfuse_fma"> | 79 | <widget class="QWidget" name="unsafe_widget" native="true"> |
| 100 | <property name="toolTip"> | 80 | <layout class="QVBoxLayout" name="unsafe_layout"> |
| 101 | <string> | 81 | <property name="leftMargin"> |
| 102 | <div>This option improves speed by reducing accuracy of fused-multiply-add instructions on CPUs without native FMA support.</div> | 82 | <number>0</number> |
| 103 | </string> | 83 | </property> |
| 104 | </property> | 84 | <property name="topMargin"> |
| 105 | <property name="text"> | 85 | <number>0</number> |
| 106 | <string>Unfuse FMA (improve performance on CPUs without FMA)</string> | 86 | </property> |
| 107 | </property> | 87 | <property name="rightMargin"> |
| 108 | </widget> | 88 | <number>0</number> |
| 109 | </item> | 89 | </property> |
| 110 | <item> | 90 | <property name="bottomMargin"> |
| 111 | <widget class="QCheckBox" name="cpuopt_unsafe_reduce_fp_error"> | 91 | <number>0</number> |
| 112 | <property name="toolTip"> | 92 | </property> |
| 113 | <string> | 93 | </layout> |
| 114 | <div>This option improves the speed of some approximate floating-point functions by using less accurate native approximations.</div> | ||
| 115 | </string> | ||
| 116 | </property> | ||
| 117 | <property name="text"> | ||
| 118 | <string>Faster FRSQRTE and FRECPE</string> | ||
| 119 | </property> | ||
| 120 | </widget> | ||
| 121 | </item> | ||
| 122 | <item> | ||
| 123 | <widget class="QCheckBox" name="cpuopt_unsafe_ignore_standard_fpcr"> | ||
| 124 | <property name="toolTip"> | ||
| 125 | <string> | ||
| 126 | <div>This option improves the speed of 32 bits ASIMD floating-point functions by running with incorrect rounding modes.</div> | ||
| 127 | </string> | ||
| 128 | </property> | ||
| 129 | <property name="text"> | ||
| 130 | <string>Faster ASIMD instructions (32 bits only)</string> | ||
| 131 | </property> | ||
| 132 | </widget> | ||
| 133 | </item> | ||
| 134 | <item> | ||
| 135 | <widget class="QCheckBox" name="cpuopt_unsafe_inaccurate_nan"> | ||
| 136 | <property name="toolTip"> | ||
| 137 | <string> | ||
| 138 | <div>This option improves speed by removing NaN checking. Please note this also reduces accuracy of certain floating-point instructions.</div> | ||
| 139 | </string> | ||
| 140 | </property> | ||
| 141 | <property name="text"> | ||
| 142 | <string>Inaccurate NaN handling</string> | ||
| 143 | </property> | ||
| 144 | </widget> | ||
| 145 | </item> | ||
| 146 | <item> | ||
| 147 | <widget class="QCheckBox" name="cpuopt_unsafe_fastmem_check"> | ||
| 148 | <property name="toolTip"> | ||
| 149 | <string> | ||
| 150 | <div>This option improves speed by eliminating a safety check before every memory read/write in guest. Disabling it may allow a game to read/write the emulator's memory.</div> | ||
| 151 | </string> | ||
| 152 | </property> | ||
| 153 | <property name="text"> | ||
| 154 | <string>Disable address space checks</string> | ||
| 155 | </property> | ||
| 156 | </widget> | ||
| 157 | </item> | ||
| 158 | <item> | ||
| 159 | <widget class="QCheckBox" name="cpuopt_unsafe_ignore_global_monitor"> | ||
| 160 | <property name="toolTip"> | ||
| 161 | <string> | ||
| 162 | <div>This option improves speed by relying only on the semantics of cmpxchg to ensure safety of exclusive access instructions. Please note this may result in deadlocks and other race conditions.</div> | ||
| 163 | </string> | ||
| 164 | </property> | ||
| 165 | <property name="text"> | ||
| 166 | <string>Ignore global monitor</string> | ||
| 167 | </property> | ||
| 168 | </widget> | 94 | </widget> |
| 169 | </item> | 95 | </item> |
| 170 | </layout> | 96 | </layout> |
| 171 | </widget> | 97 | </widget> |
| 172 | </item> | 98 | </item> |
| 99 | <item> | ||
| 100 | <spacer name="verticalSpacer"> | ||
| 101 | <property name="orientation"> | ||
| 102 | <enum>Qt::Vertical</enum> | ||
| 103 | </property> | ||
| 104 | <property name="sizeType"> | ||
| 105 | <enum>QSizePolicy::Expanding</enum> | ||
| 106 | </property> | ||
| 107 | <property name="sizeHint" stdset="0"> | ||
| 108 | <size> | ||
| 109 | <width>20</width> | ||
| 110 | <height>40</height> | ||
| 111 | </size> | ||
| 112 | </property> | ||
| 113 | </spacer> | ||
| 114 | </item> | ||
| 173 | </layout> | 115 | </layout> |
| 174 | </item> | 116 | </item> |
| 175 | <item> | ||
| 176 | <spacer name="verticalSpacer"> | ||
| 177 | <property name="orientation"> | ||
| 178 | <enum>Qt::Vertical</enum> | ||
| 179 | </property> | ||
| 180 | <property name="sizeHint" stdset="0"> | ||
| 181 | <size> | ||
| 182 | <width>20</width> | ||
| 183 | <height>40</height> | ||
| 184 | </size> | ||
| 185 | </property> | ||
| 186 | </spacer> | ||
| 187 | </item> | ||
| 188 | <item> | ||
| 189 | <widget class="QLabel" name="label_disable_info"> | ||
| 190 | <property name="text"> | ||
| 191 | <string>CPU settings are available only when game is not running.</string> | ||
| 192 | </property> | ||
| 193 | <property name="wordWrap"> | ||
| 194 | <bool>true</bool> | ||
| 195 | </property> | ||
| 196 | </widget> | ||
| 197 | </item> | ||
| 198 | </layout> | 117 | </layout> |
| 199 | </widget> | 118 | </widget> |
| 200 | <resources/> | 119 | <resources/> |
diff --git a/src/yuzu/configuration/configure_debug.ui b/src/yuzu/configuration/configure_debug.ui index 15acefe33..97c7d9022 100644 --- a/src/yuzu/configuration/configure_debug.ui +++ b/src/yuzu/configuration/configure_debug.ui | |||
| @@ -2,360 +2,549 @@ | |||
| 2 | <ui version="4.0"> | 2 | <ui version="4.0"> |
| 3 | <class>ConfigureDebug</class> | 3 | <class>ConfigureDebug</class> |
| 4 | <widget class="QScrollArea" name="ConfigureDebug"> | 4 | <widget class="QScrollArea" name="ConfigureDebug"> |
| 5 | <property name="geometry"> | ||
| 6 | <rect> | ||
| 7 | <x>0</x> | ||
| 8 | <y>0</y> | ||
| 9 | <width>831</width> | ||
| 10 | <height>760</height> | ||
| 11 | </rect> | ||
| 12 | </property> | ||
| 5 | <property name="widgetResizable"> | 13 | <property name="widgetResizable"> |
| 6 | <bool>true</bool> | 14 | <bool>true</bool> |
| 7 | </property> | 15 | </property> |
| 8 | <widget class="QWidget"> | 16 | <widget class="QWidget" name="widget"> |
| 9 | <layout class="QVBoxLayout" name="verticalLayout_1"> | 17 | <property name="geometry"> |
| 10 | <item> | 18 | <rect> |
| 11 | <layout class="QVBoxLayout" name="verticalLayout_2"> | 19 | <x>0</x> |
| 12 | <item> | 20 | <y>0</y> |
| 13 | <widget class="QGroupBox" name="groupBox"> | 21 | <width>829</width> |
| 14 | <property name="title"> | 22 | <height>758</height> |
| 15 | <string>Debugger</string> | 23 | </rect> |
| 16 | </property> | 24 | </property> |
| 17 | <layout class="QVBoxLayout" name="verticalLayout_3"> | 25 | <layout class="QVBoxLayout" name="verticalLayout_1"> |
| 18 | <item> | 26 | <item> |
| 19 | <layout class="QHBoxLayout" name="horizontalLayout_11"> | 27 | <layout class="QHBoxLayout" name="horizontalLayout"> |
| 20 | <item> | 28 | <property name="topMargin"> |
| 21 | <widget class="QCheckBox" name="toggle_gdbstub"> | 29 | <number>0</number> |
| 22 | <property name="text"> | 30 | </property> |
| 23 | <string>Enable GDB Stub</string> | 31 | <item> |
| 24 | </property> | 32 | <widget class="QGroupBox" name="groupBox"> |
| 25 | </widget> | 33 | <property name="sizePolicy"> |
| 26 | </item> | 34 | <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> |
| 27 | <item> | 35 | <horstretch>0</horstretch> |
| 28 | <spacer name="horizontalSpacer"> | 36 | <verstretch>0</verstretch> |
| 29 | <property name="orientation"> | 37 | </sizepolicy> |
| 30 | <enum>Qt::Horizontal</enum> | 38 | </property> |
| 39 | <property name="title"> | ||
| 40 | <string>Debugger</string> | ||
| 41 | </property> | ||
| 42 | <property name="alignment"> | ||
| 43 | <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> | ||
| 44 | </property> | ||
| 45 | <property name="flat"> | ||
| 46 | <bool>false</bool> | ||
| 47 | </property> | ||
| 48 | <property name="checkable"> | ||
| 49 | <bool>false</bool> | ||
| 50 | </property> | ||
| 51 | <layout class="QVBoxLayout" name="verticalLayout_3"> | ||
| 52 | <item> | ||
| 53 | <widget class="QWidget" name="debug_widget" native="true"> | ||
| 54 | <property name="sizePolicy"> | ||
| 55 | <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> | ||
| 56 | <horstretch>0</horstretch> | ||
| 57 | <verstretch>0</verstretch> | ||
| 58 | </sizepolicy> | ||
| 59 | </property> | ||
| 60 | <layout class="QVBoxLayout" name="verticalLayout"> | ||
| 61 | <property name="sizeConstraint"> | ||
| 62 | <enum>QLayout::SetDefaultConstraint</enum> | ||
| 31 | </property> | 63 | </property> |
| 32 | <property name="sizeHint" stdset="0"> | 64 | <property name="leftMargin"> |
| 33 | <size> | 65 | <number>0</number> |
| 34 | <width>40</width> | ||
| 35 | <height>20</height> | ||
| 36 | </size> | ||
| 37 | </property> | 66 | </property> |
| 38 | </spacer> | 67 | <property name="topMargin"> |
| 39 | </item> | 68 | <number>0</number> |
| 40 | <item> | ||
| 41 | <widget class="QLabel" name="label_11"> | ||
| 42 | <property name="text"> | ||
| 43 | <string>Port:</string> | ||
| 44 | </property> | 69 | </property> |
| 45 | </widget> | 70 | <property name="rightMargin"> |
| 46 | </item> | 71 | <number>0</number> |
| 47 | <item> | ||
| 48 | <widget class="QSpinBox" name="gdbport_spinbox"> | ||
| 49 | <property name="minimum"> | ||
| 50 | <number>1024</number> | ||
| 51 | </property> | 72 | </property> |
| 52 | <property name="maximum"> | 73 | <property name="bottomMargin"> |
| 53 | <number>65535</number> | 74 | <number>0</number> |
| 54 | </property> | 75 | </property> |
| 55 | </widget> | 76 | <item> |
| 56 | </item> | 77 | <widget class="QCheckBox" name="toggle_gdbstub"> |
| 57 | </layout> | 78 | <property name="sizePolicy"> |
| 58 | </item> | 79 | <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> |
| 59 | </layout> | 80 | <horstretch>0</horstretch> |
| 60 | </widget> | 81 | <verstretch>0</verstretch> |
| 61 | </item> | 82 | </sizepolicy> |
| 62 | </layout> | 83 | </property> |
| 63 | </item> | 84 | <property name="text"> |
| 64 | <item> | 85 | <string>Enable GDB Stub</string> |
| 65 | <widget class="QGroupBox" name="groupBox_2"> | 86 | </property> |
| 66 | <property name="title"> | 87 | </widget> |
| 67 | <string>Logging</string> | 88 | </item> |
| 68 | </property> | 89 | <item> |
| 69 | <layout class="QGridLayout" name="gridLayout_1"> | 90 | <widget class="QWidget" name="horizontalWidget_3" native="true"> |
| 70 | <item row="0" column="0" colspan="2"> | 91 | <property name="sizePolicy"> |
| 71 | <layout class="QHBoxLayout" name="horizontalLayout_1"> | 92 | <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> |
| 72 | <item> | 93 | <horstretch>0</horstretch> |
| 73 | <widget class="QLabel" name="label_1"> | 94 | <verstretch>0</verstretch> |
| 74 | <property name="text"> | 95 | </sizepolicy> |
| 75 | <string>Global Log Filter</string> | 96 | </property> |
| 76 | </property> | 97 | <layout class="QHBoxLayout" name="horizontalLayout_3"> |
| 77 | </widget> | 98 | <property name="leftMargin"> |
| 78 | </item> | 99 | <number>0</number> |
| 79 | <item> | 100 | </property> |
| 80 | <widget class="QLineEdit" name="log_filter_edit"/> | 101 | <property name="topMargin"> |
| 81 | </item> | 102 | <number>0</number> |
| 82 | </layout> | 103 | </property> |
| 83 | </item> | 104 | <property name="rightMargin"> |
| 84 | <item row="1" column="0"> | 105 | <number>0</number> |
| 85 | <widget class="QCheckBox" name="toggle_console"> | 106 | </property> |
| 86 | <property name="text"> | 107 | <property name="bottomMargin"> |
| 87 | <string>Show Log in Console</string> | 108 | <number>0</number> |
| 88 | </property> | 109 | </property> |
| 89 | </widget> | 110 | <item> |
| 90 | </item> | 111 | <widget class="QLabel" name="label_11"> |
| 91 | <item row="1" column="1"> | 112 | <property name="sizePolicy"> |
| 92 | <widget class="QPushButton" name="open_log_button"> | 113 | <sizepolicy hsizetype="Minimum" vsizetype="Maximum"> |
| 93 | <property name="text"> | 114 | <horstretch>0</horstretch> |
| 94 | <string>Open Log Location</string> | 115 | <verstretch>0</verstretch> |
| 95 | </property> | 116 | </sizepolicy> |
| 117 | </property> | ||
| 118 | <property name="text"> | ||
| 119 | <string>Port:</string> | ||
| 120 | </property> | ||
| 121 | </widget> | ||
| 122 | </item> | ||
| 123 | <item> | ||
| 124 | <widget class="QSpinBox" name="gdbport_spinbox"> | ||
| 125 | <property name="sizePolicy"> | ||
| 126 | <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> | ||
| 127 | <horstretch>0</horstretch> | ||
| 128 | <verstretch>0</verstretch> | ||
| 129 | </sizepolicy> | ||
| 130 | </property> | ||
| 131 | <property name="minimum"> | ||
| 132 | <number>1024</number> | ||
| 133 | </property> | ||
| 134 | <property name="maximum"> | ||
| 135 | <number>65535</number> | ||
| 136 | </property> | ||
| 137 | </widget> | ||
| 138 | </item> | ||
| 139 | </layout> | ||
| 140 | </widget> | ||
| 141 | </item> | ||
| 142 | </layout> | ||
| 143 | </widget> | ||
| 144 | </item> | ||
| 145 | </layout> | ||
| 96 | </widget> | 146 | </widget> |
| 97 | </item> | 147 | </item> |
| 98 | <item row="2" column="0"> | ||
| 99 | <widget class="QCheckBox" name="extended_logging"> | ||
| 100 | <property name="enabled"> | ||
| 101 | <bool>true</bool> | ||
| 102 | </property> | ||
| 103 | <property name="toolTip"> | ||
| 104 | <string>When checked, the max size of the log increases from 100 MB to 1 GB</string> | ||
| 105 | </property> | ||
| 106 | <property name="text"> | ||
| 107 | <string>Enable Extended Logging**</string> | ||
| 108 | </property> | ||
| 109 | </widget> | ||
| 110 | </item> | ||
| 111 | </layout> | ||
| 112 | </widget> | ||
| 113 | </item> | ||
| 114 | <item> | ||
| 115 | <widget class="QGroupBox" name="groupBox_3"> | ||
| 116 | <property name="title"> | ||
| 117 | <string>Homebrew</string> | ||
| 118 | </property> | ||
| 119 | <layout class="QVBoxLayout" name="verticalLayout_5"> | ||
| 120 | <item> | 148 | <item> |
| 121 | <layout class="QHBoxLayout" name="horizontalLayout_4"> | 149 | <widget class="QGroupBox" name="groupBox_2"> |
| 122 | <item> | 150 | <property name="sizePolicy"> |
| 123 | <widget class="QLabel" name="label_3"> | 151 | <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> |
| 124 | <property name="text"> | 152 | <horstretch>0</horstretch> |
| 125 | <string>Arguments String</string> | 153 | <verstretch>0</verstretch> |
| 126 | </property> | 154 | </sizepolicy> |
| 127 | </widget> | 155 | </property> |
| 128 | </item> | 156 | <property name="title"> |
| 129 | <item> | 157 | <string>Logging</string> |
| 130 | <widget class="QLineEdit" name="homebrew_args_edit"/> | 158 | </property> |
| 131 | </item> | 159 | <layout class="QGridLayout" name="gridLayout_1"> |
| 132 | </layout> | 160 | <item row="1" column="1"> |
| 133 | </item> | 161 | <widget class="QPushButton" name="open_log_button"> |
| 134 | </layout> | 162 | <property name="text"> |
| 135 | </widget> | 163 | <string>Open Log Location</string> |
| 136 | </item> | 164 | </property> |
| 137 | <item> | 165 | </widget> |
| 138 | <widget class="QGroupBox" name="groupBox_4"> | 166 | </item> |
| 139 | <property name="title"> | 167 | <item row="0" column="0" colspan="2"> |
| 140 | <string>Graphics</string> | 168 | <widget class="QWidget" name="logging_widget" native="true"> |
| 141 | </property> | 169 | <property name="sizePolicy"> |
| 142 | <layout class="QGridLayout" name="gridLayout_2"> | 170 | <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> |
| 143 | <item row="0" column="0"> | 171 | <horstretch>0</horstretch> |
| 144 | <widget class="QCheckBox" name="enable_graphics_debugging"> | 172 | <verstretch>0</verstretch> |
| 145 | <property name="enabled"> | 173 | </sizepolicy> |
| 146 | <bool>true</bool> | 174 | </property> |
| 147 | </property> | 175 | <layout class="QHBoxLayout" name="horizontalLayout_1"> |
| 148 | <property name="toolTip"> | 176 | <property name="leftMargin"> |
| 149 | <string>When checked, the graphics API enters a slower debugging mode</string> | 177 | <number>0</number> |
| 150 | </property> | 178 | </property> |
| 151 | <property name="text"> | 179 | <property name="topMargin"> |
| 152 | <string>Enable Graphics Debugging</string> | 180 | <number>0</number> |
| 153 | </property> | 181 | </property> |
| 154 | </widget> | 182 | <property name="rightMargin"> |
| 155 | </item> | 183 | <number>0</number> |
| 156 | <item row="2" column="0"> | 184 | </property> |
| 157 | <widget class="QCheckBox" name="enable_nsight_aftermath"> | 185 | <property name="bottomMargin"> |
| 158 | <property name="toolTip"> | 186 | <number>0</number> |
| 159 | <string>When checked, it enables Nsight Aftermath crash dumps</string> | 187 | </property> |
| 160 | </property> | 188 | <item> |
| 161 | <property name="text"> | 189 | <widget class="QLabel" name="label_1"> |
| 162 | <string>Enable Nsight Aftermath</string> | 190 | <property name="sizePolicy"> |
| 163 | </property> | 191 | <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> |
| 164 | </widget> | 192 | <horstretch>0</horstretch> |
| 165 | </item> | 193 | <verstretch>0</verstretch> |
| 166 | <item row="2" column="1"> | 194 | </sizepolicy> |
| 167 | <widget class="QCheckBox" name="dump_shaders"> | 195 | </property> |
| 168 | <property name="enabled"> | 196 | <property name="text"> |
| 169 | <bool>true</bool> | 197 | <string>Global Log Filter</string> |
| 170 | </property> | 198 | </property> |
| 171 | <property name="toolTip"> | 199 | </widget> |
| 172 | <string>When checked, it will dump all the original assembler shaders from the disk shader cache or game as found</string> | 200 | </item> |
| 173 | </property> | 201 | <item> |
| 174 | <property name="text"> | 202 | <widget class="QLineEdit" name="log_filter_edit"/> |
| 175 | <string>Dump Game Shaders</string> | 203 | </item> |
| 176 | </property> | 204 | </layout> |
| 177 | </widget> | 205 | </widget> |
| 178 | </item> | 206 | </item> |
| 179 | <item row="1" column="2"> | 207 | <item row="2" column="0"> |
| 180 | <widget class="QCheckBox" name="dump_macros"> | 208 | <widget class="QCheckBox" name="extended_logging"> |
| 181 | <property name="enabled"> | 209 | <property name="enabled"> |
| 182 | <bool>true</bool> | 210 | <bool>true</bool> |
| 183 | </property> | 211 | </property> |
| 184 | <property name="toolTip"> | 212 | <property name="toolTip"> |
| 185 | <string>When checked, it will dump all the macro programs of the GPU</string> | 213 | <string>When checked, the max size of the log increases from 100 MB to 1 GB</string> |
| 186 | </property> | 214 | </property> |
| 187 | <property name="text"> | 215 | <property name="text"> |
| 188 | <string>Dump Maxwell Macros</string> | 216 | <string>Enable Extended Logging**</string> |
| 189 | </property> | 217 | </property> |
| 190 | </widget> | 218 | </widget> |
| 191 | </item> | 219 | </item> |
| 192 | <item row="0" column="1"> | 220 | <item row="1" column="0"> |
| 193 | <widget class="QCheckBox" name="disable_macro_jit"> | 221 | <widget class="QCheckBox" name="toggle_console"> |
| 194 | <property name="enabled"> | 222 | <property name="text"> |
| 195 | <bool>true</bool> | 223 | <string>Show Log in Console</string> |
| 196 | </property> | 224 | </property> |
| 197 | <property name="toolTip"> | 225 | </widget> |
| 198 | <string>When checked, it disables the macro Just In Time compiler. Enabling this makes games run slower</string> | 226 | </item> |
| 199 | </property> | 227 | </layout> |
| 200 | <property name="text"> | ||
| 201 | <string>Disable Macro JIT</string> | ||
| 202 | </property> | ||
| 203 | </widget> | ||
| 204 | </item> | ||
| 205 | <item row="0" column="2"> | ||
| 206 | <widget class="QCheckBox" name="disable_macro_hle"> | ||
| 207 | <property name="enabled"> | ||
| 208 | <bool>true</bool> | ||
| 209 | </property> | ||
| 210 | <property name="toolTip"> | ||
| 211 | <string>When checked, it disables the macro HLE functions. Enabling this makes games run slower</string> | ||
| 212 | </property> | ||
| 213 | <property name="text"> | ||
| 214 | <string>Disable Macro HLE</string> | ||
| 215 | </property> | ||
| 216 | </widget> | ||
| 217 | </item> | ||
| 218 | <item row="1" column="0"> | ||
| 219 | <widget class="QCheckBox" name="enable_shader_feedback"> | ||
| 220 | <property name="toolTip"> | ||
| 221 | <string>When checked, yuzu will log statistics about the compiled pipeline cache</string> | ||
| 222 | </property> | ||
| 223 | <property name="text"> | ||
| 224 | <string>Enable Shader Feedback</string> | ||
| 225 | </property> | ||
| 226 | </widget> | ||
| 227 | </item> | ||
| 228 | <item row="1" column="1"> | ||
| 229 | <widget class="QCheckBox" name="disable_loop_safety_checks"> | ||
| 230 | <property name="toolTip"> | ||
| 231 | <string>When checked, it executes shaders without loop logic changes</string> | ||
| 232 | </property> | ||
| 233 | <property name="text"> | ||
| 234 | <string>Disable Loop safety checks</string> | ||
| 235 | </property> | ||
| 236 | </widget> | ||
| 237 | </item> | ||
| 238 | </layout> | ||
| 239 | </widget> | ||
| 240 | </item> | ||
| 241 | <item> | ||
| 242 | <widget class="QGroupBox" name="groupBox_5"> | ||
| 243 | <property name="title"> | ||
| 244 | <string>Debugging</string> | ||
| 245 | </property> | ||
| 246 | <layout class="QGridLayout" name="gridLayout_3"> | ||
| 247 | <item row="2" column="0"> | ||
| 248 | <widget class="QCheckBox" name="reporting_services"> | ||
| 249 | <property name="text"> | ||
| 250 | <string>Enable Verbose Reporting Services**</string> | ||
| 251 | </property> | ||
| 252 | </widget> | ||
| 253 | </item> | ||
| 254 | <item row="0" column="0"> | ||
| 255 | <widget class="QCheckBox" name="fs_access_log"> | ||
| 256 | <property name="text"> | ||
| 257 | <string>Enable FS Access Log</string> | ||
| 258 | </property> | ||
| 259 | </widget> | ||
| 260 | </item> | ||
| 261 | <item row="0" column="1"> | ||
| 262 | <widget class="QCheckBox" name="dump_audio_commands"> | ||
| 263 | <property name="toolTip"> | ||
| 264 | <string>Enable this to output the latest generated audio command list to the console. Only affects games using the audio renderer.</string> | ||
| 265 | </property> | ||
| 266 | <property name="text"> | ||
| 267 | <string>Dump Audio Commands To Console**</string> | ||
| 268 | </property> | ||
| 269 | </widget> | ||
| 270 | </item> | ||
| 271 | <item row="2" column="1"> | ||
| 272 | <widget class="QCheckBox" name="create_crash_dumps"> | ||
| 273 | <property name="text"> | ||
| 274 | <string>Create Minidump After Crash</string> | ||
| 275 | </property> | ||
| 276 | </widget> | 228 | </widget> |
| 277 | </item> | 229 | </item> |
| 278 | </layout> | 230 | </layout> |
| 279 | </widget> | 231 | </item> |
| 280 | </item> | 232 | <item> |
| 281 | <item> | 233 | <widget class="QGroupBox" name="groupBox_3"> |
| 282 | <widget class="QGroupBox" name="groupBox_6"> | 234 | <property name="title"> |
| 283 | <property name="title"> | 235 | <string>Homebrew</string> |
| 284 | <string>Advanced</string> | 236 | </property> |
| 285 | </property> | 237 | <layout class="QVBoxLayout" name="verticalLayout_5"> |
| 286 | <layout class="QGridLayout" name="gridLayout_4"> | 238 | <item> |
| 287 | <item row="0" column="0"> | 239 | <layout class="QHBoxLayout" name="horizontalLayout_4"> |
| 288 | <widget class="QCheckBox" name="quest_flag"> | 240 | <item> |
| 289 | <property name="text"> | 241 | <widget class="QLabel" name="label_3"> |
| 290 | <string>Kiosk (Quest) Mode</string> | 242 | <property name="text"> |
| 291 | </property> | 243 | <string>Arguments String</string> |
| 292 | </widget> | 244 | </property> |
| 293 | </item> | 245 | </widget> |
| 294 | <item row="1" column="0"> | 246 | </item> |
| 295 | <widget class="QCheckBox" name="enable_cpu_debugging"> | 247 | <item> |
| 296 | <property name="text"> | 248 | <widget class="QLineEdit" name="homebrew_args_edit"/> |
| 297 | <string>Enable CPU Debugging</string> | 249 | </item> |
| 298 | </property> | 250 | </layout> |
| 299 | </widget> | 251 | </item> |
| 300 | </item> | 252 | </layout> |
| 301 | <item row="2" column="0"> | 253 | </widget> |
| 302 | <widget class="QCheckBox" name="use_debug_asserts"> | 254 | </item> |
| 303 | <property name="text"> | 255 | <item> |
| 304 | <string>Enable Debug Asserts</string> | 256 | <layout class="QHBoxLayout" name="horizontalLayout_2"> |
| 305 | </property> | 257 | <item> |
| 306 | </widget> | 258 | <widget class="QGroupBox" name="groupBox_4"> |
| 307 | </item> | 259 | <property name="title"> |
| 308 | <item row="0" column="1"> | 260 | <string>Graphics</string> |
| 309 | <widget class="QCheckBox" name="use_auto_stub"> | 261 | </property> |
| 310 | <property name="text"> | 262 | <layout class="QGridLayout" name="gridLayout_2"> |
| 311 | <string>Enable Auto-Stub**</string> | 263 | <item row="3" column="0"> |
| 312 | </property> | 264 | <widget class="QCheckBox" name="disable_loop_safety_checks"> |
| 313 | </widget> | 265 | <property name="toolTip"> |
| 314 | </item> | 266 | <string>When checked, it executes shaders without loop logic changes</string> |
| 315 | <item row="1" column="1"> | 267 | </property> |
| 316 | <widget class="QCheckBox" name="enable_all_controllers"> | 268 | <property name="text"> |
| 317 | <property name="text"> | 269 | <string>Disable Loop safety checks</string> |
| 318 | <string>Enable All Controller Types</string> | 270 | </property> |
| 319 | </property> | 271 | </widget> |
| 272 | </item> | ||
| 273 | <item row="4" column="0"> | ||
| 274 | <widget class="QCheckBox" name="dump_shaders"> | ||
| 275 | <property name="enabled"> | ||
| 276 | <bool>true</bool> | ||
| 277 | </property> | ||
| 278 | <property name="toolTip"> | ||
| 279 | <string>When checked, it will dump all the original assembler shaders from the disk shader cache or game as found</string> | ||
| 280 | </property> | ||
| 281 | <property name="text"> | ||
| 282 | <string>Dump Game Shaders</string> | ||
| 283 | </property> | ||
| 284 | </widget> | ||
| 285 | </item> | ||
| 286 | <item row="7" column="0"> | ||
| 287 | <widget class="QCheckBox" name="disable_macro_hle"> | ||
| 288 | <property name="enabled"> | ||
| 289 | <bool>true</bool> | ||
| 290 | </property> | ||
| 291 | <property name="toolTip"> | ||
| 292 | <string>When checked, it disables the macro HLE functions. Enabling this makes games run slower</string> | ||
| 293 | </property> | ||
| 294 | <property name="text"> | ||
| 295 | <string>Disable Macro HLE</string> | ||
| 296 | </property> | ||
| 297 | </widget> | ||
| 298 | </item> | ||
| 299 | <item row="5" column="0"> | ||
| 300 | <widget class="QCheckBox" name="disable_macro_jit"> | ||
| 301 | <property name="enabled"> | ||
| 302 | <bool>true</bool> | ||
| 303 | </property> | ||
| 304 | <property name="toolTip"> | ||
| 305 | <string>When checked, it disables the macro Just In Time compiler. Enabling this makes games run slower</string> | ||
| 306 | </property> | ||
| 307 | <property name="text"> | ||
| 308 | <string>Disable Macro JIT</string> | ||
| 309 | </property> | ||
| 310 | </widget> | ||
| 311 | </item> | ||
| 312 | <item row="0" column="0"> | ||
| 313 | <widget class="QCheckBox" name="enable_graphics_debugging"> | ||
| 314 | <property name="enabled"> | ||
| 315 | <bool>true</bool> | ||
| 316 | </property> | ||
| 317 | <property name="toolTip"> | ||
| 318 | <string>When checked, the graphics API enters a slower debugging mode</string> | ||
| 319 | </property> | ||
| 320 | <property name="text"> | ||
| 321 | <string>Enable Graphics Debugging</string> | ||
| 322 | </property> | ||
| 323 | </widget> | ||
| 324 | </item> | ||
| 325 | <item row="6" column="0"> | ||
| 326 | <widget class="QCheckBox" name="dump_macros"> | ||
| 327 | <property name="enabled"> | ||
| 328 | <bool>true</bool> | ||
| 329 | </property> | ||
| 330 | <property name="toolTip"> | ||
| 331 | <string>When checked, it will dump all the macro programs of the GPU</string> | ||
| 332 | </property> | ||
| 333 | <property name="text"> | ||
| 334 | <string>Dump Maxwell Macros</string> | ||
| 335 | </property> | ||
| 336 | </widget> | ||
| 337 | </item> | ||
| 338 | <item row="1" column="0"> | ||
| 339 | <widget class="QCheckBox" name="enable_shader_feedback"> | ||
| 340 | <property name="toolTip"> | ||
| 341 | <string>When checked, yuzu will log statistics about the compiled pipeline cache</string> | ||
| 342 | </property> | ||
| 343 | <property name="text"> | ||
| 344 | <string>Enable Shader Feedback</string> | ||
| 345 | </property> | ||
| 346 | </widget> | ||
| 347 | </item> | ||
| 348 | <item row="2" column="0"> | ||
| 349 | <widget class="QCheckBox" name="enable_nsight_aftermath"> | ||
| 350 | <property name="toolTip"> | ||
| 351 | <string>When checked, it enables Nsight Aftermath crash dumps</string> | ||
| 352 | </property> | ||
| 353 | <property name="text"> | ||
| 354 | <string>Enable Nsight Aftermath</string> | ||
| 355 | </property> | ||
| 356 | </widget> | ||
| 357 | </item> | ||
| 358 | <item row="8" column="0"> | ||
| 359 | <spacer name="verticalSpacer_5"> | ||
| 360 | <property name="orientation"> | ||
| 361 | <enum>Qt::Vertical</enum> | ||
| 362 | </property> | ||
| 363 | <property name="sizeType"> | ||
| 364 | <enum>QSizePolicy::Preferred</enum> | ||
| 365 | </property> | ||
| 366 | <property name="sizeHint" stdset="0"> | ||
| 367 | <size> | ||
| 368 | <width>20</width> | ||
| 369 | <height>0</height> | ||
| 370 | </size> | ||
| 371 | </property> | ||
| 372 | </spacer> | ||
| 373 | </item> | ||
| 374 | </layout> | ||
| 320 | </widget> | 375 | </widget> |
| 321 | </item> | 376 | </item> |
| 322 | <item row="2" column="1"> | 377 | <item> |
| 323 | <widget class="QCheckBox" name="disable_web_applet"> | 378 | <widget class="QGroupBox" name="groupBox_6"> |
| 324 | <property name="text"> | 379 | <property name="title"> |
| 325 | <string>Disable Web Applet</string> | 380 | <string>Advanced</string> |
| 326 | </property> | 381 | </property> |
| 382 | <layout class="QGridLayout" name="gridLayout_4"> | ||
| 383 | <item row="3" column="0"> | ||
| 384 | <widget class="QCheckBox" name="perform_vulkan_check"> | ||
| 385 | <property name="toolTip"> | ||
| 386 | <string>Enables yuzu to check for a working Vulkan environment when the program starts up. Disable this if this is causing issues with external programs seeing yuzu.</string> | ||
| 387 | </property> | ||
| 388 | <property name="text"> | ||
| 389 | <string>Perform Startup Vulkan Check</string> | ||
| 390 | </property> | ||
| 391 | </widget> | ||
| 392 | </item> | ||
| 393 | <item row="4" column="0"> | ||
| 394 | <widget class="QCheckBox" name="disable_web_applet"> | ||
| 395 | <property name="text"> | ||
| 396 | <string>Disable Web Applet</string> | ||
| 397 | </property> | ||
| 398 | </widget> | ||
| 399 | </item> | ||
| 400 | <item row="5" column="0"> | ||
| 401 | <widget class="QCheckBox" name="enable_all_controllers"> | ||
| 402 | <property name="text"> | ||
| 403 | <string>Enable All Controller Types</string> | ||
| 404 | </property> | ||
| 405 | </widget> | ||
| 406 | </item> | ||
| 407 | <item row="6" column="0"> | ||
| 408 | <widget class="QCheckBox" name="use_auto_stub"> | ||
| 409 | <property name="text"> | ||
| 410 | <string>Enable Auto-Stub**</string> | ||
| 411 | </property> | ||
| 412 | </widget> | ||
| 413 | </item> | ||
| 414 | <item row="0" column="0"> | ||
| 415 | <widget class="QCheckBox" name="quest_flag"> | ||
| 416 | <property name="text"> | ||
| 417 | <string>Kiosk (Quest) Mode</string> | ||
| 418 | </property> | ||
| 419 | </widget> | ||
| 420 | </item> | ||
| 421 | <item row="1" column="0"> | ||
| 422 | <widget class="QCheckBox" name="enable_cpu_debugging"> | ||
| 423 | <property name="text"> | ||
| 424 | <string>Enable CPU Debugging</string> | ||
| 425 | </property> | ||
| 426 | </widget> | ||
| 427 | </item> | ||
| 428 | <item row="2" column="0"> | ||
| 429 | <widget class="QCheckBox" name="use_debug_asserts"> | ||
| 430 | <property name="text"> | ||
| 431 | <string>Enable Debug Asserts</string> | ||
| 432 | </property> | ||
| 433 | </widget> | ||
| 434 | </item> | ||
| 435 | <item row="7" column="0"> | ||
| 436 | <spacer name="verticalSpacer_4"> | ||
| 437 | <property name="orientation"> | ||
| 438 | <enum>Qt::Vertical</enum> | ||
| 439 | </property> | ||
| 440 | <property name="sizeType"> | ||
| 441 | <enum>QSizePolicy::Expanding</enum> | ||
| 442 | </property> | ||
| 443 | <property name="sizeHint" stdset="0"> | ||
| 444 | <size> | ||
| 445 | <width>20</width> | ||
| 446 | <height>0</height> | ||
| 447 | </size> | ||
| 448 | </property> | ||
| 449 | </spacer> | ||
| 450 | </item> | ||
| 451 | </layout> | ||
| 327 | </widget> | 452 | </widget> |
| 328 | </item> | 453 | </item> |
| 329 | <item row="3" column="0"> | 454 | <item> |
| 330 | <widget class="QCheckBox" name="perform_vulkan_check"> | 455 | <widget class="QGroupBox" name="groupBox_5"> |
| 331 | <property name="toolTip"> | 456 | <property name="title"> |
| 332 | <string>Enables yuzu to check for a working Vulkan environment when the program starts up. Disable this if this is causing issues with external programs seeing yuzu.</string> | 457 | <string>Debugging</string> |
| 333 | </property> | 458 | </property> |
| 334 | <property name="text"> | 459 | <layout class="QGridLayout" name="gridLayout_3"> |
| 335 | <string>Perform Startup Vulkan Check</string> | 460 | <item row="0" column="0"> |
| 336 | </property> | 461 | <widget class="QCheckBox" name="fs_access_log"> |
| 462 | <property name="text"> | ||
| 463 | <string>Enable FS Access Log</string> | ||
| 464 | </property> | ||
| 465 | </widget> | ||
| 466 | </item> | ||
| 467 | <item row="4" column="0"> | ||
| 468 | <widget class="QCheckBox" name="create_crash_dumps"> | ||
| 469 | <property name="text"> | ||
| 470 | <string>Create Minidump After Crash</string> | ||
| 471 | </property> | ||
| 472 | </widget> | ||
| 473 | </item> | ||
| 474 | <item row="3" column="0"> | ||
| 475 | <widget class="QCheckBox" name="dump_audio_commands"> | ||
| 476 | <property name="toolTip"> | ||
| 477 | <string>Enable this to output the latest generated audio command list to the console. Only affects games using the audio renderer.</string> | ||
| 478 | </property> | ||
| 479 | <property name="text"> | ||
| 480 | <string>Dump Audio Commands To Console**</string> | ||
| 481 | </property> | ||
| 482 | </widget> | ||
| 483 | </item> | ||
| 484 | <item row="2" column="0"> | ||
| 485 | <widget class="QCheckBox" name="reporting_services"> | ||
| 486 | <property name="text"> | ||
| 487 | <string>Enable Verbose Reporting Services**</string> | ||
| 488 | </property> | ||
| 489 | </widget> | ||
| 490 | </item> | ||
| 491 | <item row="5" column="0"> | ||
| 492 | <spacer name="verticalSpacer_3"> | ||
| 493 | <property name="orientation"> | ||
| 494 | <enum>Qt::Vertical</enum> | ||
| 495 | </property> | ||
| 496 | <property name="sizeType"> | ||
| 497 | <enum>QSizePolicy::Expanding</enum> | ||
| 498 | </property> | ||
| 499 | <property name="sizeHint" stdset="0"> | ||
| 500 | <size> | ||
| 501 | <width>20</width> | ||
| 502 | <height>0</height> | ||
| 503 | </size> | ||
| 504 | </property> | ||
| 505 | </spacer> | ||
| 506 | </item> | ||
| 507 | </layout> | ||
| 337 | </widget> | 508 | </widget> |
| 338 | </item> | 509 | </item> |
| 339 | </layout> | 510 | </layout> |
| 340 | </widget> | 511 | </item> |
| 341 | </item> | 512 | <item> |
| 342 | <item> | 513 | <spacer name="verticalSpacer"> |
| 343 | <widget class="QLabel" name="label_5"> | 514 | <property name="orientation"> |
| 344 | <property name="font"> | 515 | <enum>Qt::Vertical</enum> |
| 345 | <font> | 516 | </property> |
| 346 | <italic>true</italic> | 517 | <property name="sizeHint" stdset="0"> |
| 347 | </font> | 518 | <size> |
| 348 | </property> | 519 | <width>20</width> |
| 349 | <property name="text"> | 520 | <height>0</height> |
| 350 | <string>**This will be reset automatically when yuzu closes.</string> | 521 | </size> |
| 351 | </property> | 522 | </property> |
| 352 | <property name="indent"> | 523 | </spacer> |
| 353 | <number>20</number> | 524 | </item> |
| 354 | </property> | 525 | <item> |
| 355 | </widget> | 526 | <widget class="QLabel" name="label_5"> |
| 356 | </item> | 527 | <property name="sizePolicy"> |
| 357 | </layout> | 528 | <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> |
| 358 | </widget> | 529 | <horstretch>0</horstretch> |
| 530 | <verstretch>0</verstretch> | ||
| 531 | </sizepolicy> | ||
| 532 | </property> | ||
| 533 | <property name="font"> | ||
| 534 | <font> | ||
| 535 | <italic>true</italic> | ||
| 536 | </font> | ||
| 537 | </property> | ||
| 538 | <property name="text"> | ||
| 539 | <string>**This will be reset automatically when yuzu closes.</string> | ||
| 540 | </property> | ||
| 541 | <property name="indent"> | ||
| 542 | <number>20</number> | ||
| 543 | </property> | ||
| 544 | </widget> | ||
| 545 | </item> | ||
| 546 | </layout> | ||
| 547 | </widget> | ||
| 359 | </widget> | 548 | </widget> |
| 360 | <tabstops> | 549 | <tabstops> |
| 361 | <tabstop>log_filter_edit</tabstop> | 550 | <tabstop>log_filter_edit</tabstop> |
| @@ -366,14 +555,11 @@ | |||
| 366 | <tabstop>enable_graphics_debugging</tabstop> | 555 | <tabstop>enable_graphics_debugging</tabstop> |
| 367 | <tabstop>enable_shader_feedback</tabstop> | 556 | <tabstop>enable_shader_feedback</tabstop> |
| 368 | <tabstop>enable_nsight_aftermath</tabstop> | 557 | <tabstop>enable_nsight_aftermath</tabstop> |
| 369 | <tabstop>disable_macro_jit</tabstop> | ||
| 370 | <tabstop>disable_loop_safety_checks</tabstop> | ||
| 371 | <tabstop>fs_access_log</tabstop> | 558 | <tabstop>fs_access_log</tabstop> |
| 372 | <tabstop>reporting_services</tabstop> | 559 | <tabstop>reporting_services</tabstop> |
| 373 | <tabstop>quest_flag</tabstop> | 560 | <tabstop>quest_flag</tabstop> |
| 374 | <tabstop>enable_cpu_debugging</tabstop> | 561 | <tabstop>enable_cpu_debugging</tabstop> |
| 375 | <tabstop>use_debug_asserts</tabstop> | 562 | <tabstop>use_debug_asserts</tabstop> |
| 376 | <tabstop>use_auto_stub</tabstop> | ||
| 377 | </tabstops> | 563 | </tabstops> |
| 378 | <resources/> | 564 | <resources/> |
| 379 | <connections/> | 565 | <connections/> |
diff --git a/src/yuzu/configuration/configure_dialog.cpp b/src/yuzu/configuration/configure_dialog.cpp index bdf83ebfe..3c6bb3eb1 100644 --- a/src/yuzu/configuration/configure_dialog.cpp +++ b/src/yuzu/configuration/configure_dialog.cpp | |||
| @@ -32,21 +32,23 @@ ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry_, | |||
| 32 | std::vector<VkDeviceInfo::Record>& vk_device_records, | 32 | std::vector<VkDeviceInfo::Record>& vk_device_records, |
| 33 | Core::System& system_, bool enable_web_config) | 33 | Core::System& system_, bool enable_web_config) |
| 34 | : QDialog(parent), ui{std::make_unique<Ui::ConfigureDialog>()}, | 34 | : QDialog(parent), ui{std::make_unique<Ui::ConfigureDialog>()}, |
| 35 | registry(registry_), system{system_}, audio_tab{std::make_unique<ConfigureAudio>(system_, | 35 | registry(registry_), system{system_}, builder{std::make_unique<ConfigurationShared::Builder>( |
| 36 | this)}, | 36 | this, !system_.IsPoweredOn())}, |
| 37 | cpu_tab{std::make_unique<ConfigureCpu>(system_, this)}, | 37 | audio_tab{std::make_unique<ConfigureAudio>(system_, nullptr, *builder, this)}, |
| 38 | cpu_tab{std::make_unique<ConfigureCpu>(system_, nullptr, *builder, this)}, | ||
| 38 | debug_tab_tab{std::make_unique<ConfigureDebugTab>(system_, this)}, | 39 | debug_tab_tab{std::make_unique<ConfigureDebugTab>(system_, this)}, |
| 39 | filesystem_tab{std::make_unique<ConfigureFilesystem>(this)}, | 40 | filesystem_tab{std::make_unique<ConfigureFilesystem>(this)}, |
| 40 | general_tab{std::make_unique<ConfigureGeneral>(system_, this)}, | 41 | general_tab{std::make_unique<ConfigureGeneral>(system_, nullptr, *builder, this)}, |
| 41 | graphics_advanced_tab{std::make_unique<ConfigureGraphicsAdvanced>(system_, this)}, | 42 | graphics_advanced_tab{ |
| 43 | std::make_unique<ConfigureGraphicsAdvanced>(system_, nullptr, *builder, this)}, | ||
| 42 | graphics_tab{std::make_unique<ConfigureGraphics>( | 44 | graphics_tab{std::make_unique<ConfigureGraphics>( |
| 43 | system_, vk_device_records, [&]() { graphics_advanced_tab->ExposeComputeOption(); }, | 45 | system_, vk_device_records, [&]() { graphics_advanced_tab->ExposeComputeOption(); }, |
| 44 | this)}, | 46 | nullptr, *builder, this)}, |
| 45 | hotkeys_tab{std::make_unique<ConfigureHotkeys>(system_.HIDCore(), this)}, | 47 | hotkeys_tab{std::make_unique<ConfigureHotkeys>(system_.HIDCore(), this)}, |
| 46 | input_tab{std::make_unique<ConfigureInput>(system_, this)}, | 48 | input_tab{std::make_unique<ConfigureInput>(system_, this)}, |
| 47 | network_tab{std::make_unique<ConfigureNetwork>(system_, this)}, | 49 | network_tab{std::make_unique<ConfigureNetwork>(system_, this)}, |
| 48 | profile_tab{std::make_unique<ConfigureProfileManager>(system_, this)}, | 50 | profile_tab{std::make_unique<ConfigureProfileManager>(system_, this)}, |
| 49 | system_tab{std::make_unique<ConfigureSystem>(system_, this)}, | 51 | system_tab{std::make_unique<ConfigureSystem>(system_, nullptr, *builder, this)}, |
| 50 | ui_tab{std::make_unique<ConfigureUi>(system_, this)}, web_tab{std::make_unique<ConfigureWeb>( | 52 | ui_tab{std::make_unique<ConfigureUi>(system_, this)}, web_tab{std::make_unique<ConfigureWeb>( |
| 51 | this)} { | 53 | this)} { |
| 52 | Settings::SetConfiguringGlobal(true); | 54 | Settings::SetConfiguringGlobal(true); |
| @@ -95,6 +97,9 @@ ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry_, | |||
| 95 | 97 | ||
| 96 | adjustSize(); | 98 | adjustSize(); |
| 97 | ui->selectorList->setCurrentRow(0); | 99 | ui->selectorList->setCurrentRow(0); |
| 100 | |||
| 101 | // Selects the leftmost button on the bottom bar (Cancel as of writing) | ||
| 102 | ui->buttonBox->setFocus(); | ||
| 98 | } | 103 | } |
| 99 | 104 | ||
| 100 | ConfigureDialog::~ConfigureDialog() = default; | 105 | ConfigureDialog::~ConfigureDialog() = default; |
diff --git a/src/yuzu/configuration/configure_dialog.h b/src/yuzu/configuration/configure_dialog.h index 2a08b7fee..96e9a8c3e 100644 --- a/src/yuzu/configuration/configure_dialog.h +++ b/src/yuzu/configuration/configure_dialog.h | |||
| @@ -6,6 +6,9 @@ | |||
| 6 | #include <memory> | 6 | #include <memory> |
| 7 | #include <vector> | 7 | #include <vector> |
| 8 | #include <QDialog> | 8 | #include <QDialog> |
| 9 | #include "configuration/shared_widget.h" | ||
| 10 | #include "yuzu/configuration/configuration_shared.h" | ||
| 11 | #include "yuzu/configuration/shared_translation.h" | ||
| 9 | #include "yuzu/vk_device_info.h" | 12 | #include "yuzu/vk_device_info.h" |
| 10 | 13 | ||
| 11 | namespace Core { | 14 | namespace Core { |
| @@ -69,6 +72,8 @@ private: | |||
| 69 | HotkeyRegistry& registry; | 72 | HotkeyRegistry& registry; |
| 70 | 73 | ||
| 71 | Core::System& system; | 74 | Core::System& system; |
| 75 | std::unique_ptr<ConfigurationShared::Builder> builder; | ||
| 76 | std::vector<ConfigurationShared::Tab*> tab_group; | ||
| 72 | 77 | ||
| 73 | std::unique_ptr<ConfigureAudio> audio_tab; | 78 | std::unique_ptr<ConfigureAudio> audio_tab; |
| 74 | std::unique_ptr<ConfigureCpu> cpu_tab; | 79 | std::unique_ptr<ConfigureCpu> cpu_tab; |
diff --git a/src/yuzu/configuration/configure_general.cpp b/src/yuzu/configuration/configure_general.cpp index 2f55159f5..c727fadd1 100644 --- a/src/yuzu/configuration/configure_general.cpp +++ b/src/yuzu/configuration/configure_general.cpp | |||
| @@ -3,57 +3,60 @@ | |||
| 3 | 3 | ||
| 4 | #include <functional> | 4 | #include <functional> |
| 5 | #include <utility> | 5 | #include <utility> |
| 6 | #include <vector> | ||
| 6 | #include <QMessageBox> | 7 | #include <QMessageBox> |
| 7 | #include "common/settings.h" | 8 | #include "common/settings.h" |
| 8 | #include "core/core.h" | 9 | #include "core/core.h" |
| 9 | #include "ui_configure_general.h" | 10 | #include "ui_configure_general.h" |
| 10 | #include "yuzu/configuration/configuration_shared.h" | 11 | #include "yuzu/configuration/configuration_shared.h" |
| 11 | #include "yuzu/configuration/configure_general.h" | 12 | #include "yuzu/configuration/configure_general.h" |
| 13 | #include "yuzu/configuration/shared_widget.h" | ||
| 12 | #include "yuzu/uisettings.h" | 14 | #include "yuzu/uisettings.h" |
| 13 | 15 | ||
| 14 | ConfigureGeneral::ConfigureGeneral(const Core::System& system_, QWidget* parent) | 16 | ConfigureGeneral::ConfigureGeneral(const Core::System& system_, |
| 15 | : QWidget(parent), ui{std::make_unique<Ui::ConfigureGeneral>()}, system{system_} { | 17 | std::shared_ptr<std::vector<ConfigurationShared::Tab*>> group_, |
| 18 | const ConfigurationShared::Builder& builder, QWidget* parent) | ||
| 19 | : Tab(group_, parent), ui{std::make_unique<Ui::ConfigureGeneral>()}, system{system_} { | ||
| 16 | ui->setupUi(this); | 20 | ui->setupUi(this); |
| 17 | 21 | ||
| 18 | SetupPerGameUI(); | 22 | Setup(builder); |
| 19 | 23 | ||
| 20 | SetConfiguration(); | 24 | SetConfiguration(); |
| 21 | 25 | ||
| 22 | if (Settings::IsConfiguringGlobal()) { | ||
| 23 | connect(ui->toggle_speed_limit, &QCheckBox::clicked, ui->speed_limit, | ||
| 24 | [this]() { ui->speed_limit->setEnabled(ui->toggle_speed_limit->isChecked()); }); | ||
| 25 | } | ||
| 26 | |||
| 27 | connect(ui->button_reset_defaults, &QPushButton::clicked, this, | 26 | connect(ui->button_reset_defaults, &QPushButton::clicked, this, |
| 28 | &ConfigureGeneral::ResetDefaults); | 27 | &ConfigureGeneral::ResetDefaults); |
| 28 | |||
| 29 | if (!Settings::IsConfiguringGlobal()) { | ||
| 30 | ui->button_reset_defaults->setVisible(false); | ||
| 31 | } | ||
| 29 | } | 32 | } |
| 30 | 33 | ||
| 31 | ConfigureGeneral::~ConfigureGeneral() = default; | 34 | ConfigureGeneral::~ConfigureGeneral() = default; |
| 32 | 35 | ||
| 33 | void ConfigureGeneral::SetConfiguration() { | 36 | void ConfigureGeneral::SetConfiguration() {} |
| 34 | const bool runtime_lock = !system.IsPoweredOn(); | 37 | |
| 38 | void ConfigureGeneral::Setup(const ConfigurationShared::Builder& builder) { | ||
| 39 | QLayout& layout = *ui->general_widget->layout(); | ||
| 35 | 40 | ||
| 36 | ui->use_multi_core->setEnabled(runtime_lock); | 41 | std::map<u32, QWidget*> hold{}; |
| 37 | ui->use_multi_core->setChecked(Settings::values.use_multi_core.GetValue()); | ||
| 38 | 42 | ||
| 39 | ui->toggle_check_exit->setChecked(UISettings::values.confirm_before_closing.GetValue()); | 43 | for (const auto setting : |
| 40 | ui->toggle_user_on_boot->setChecked(UISettings::values.select_user_on_boot.GetValue()); | 44 | UISettings::values.linkage.by_category[Settings::Category::UiGeneral]) { |
| 41 | ui->toggle_background_pause->setChecked(UISettings::values.pause_when_in_background.GetValue()); | 45 | auto* widget = builder.BuildWidget(setting, apply_funcs); |
| 42 | ui->toggle_hide_mouse->setChecked(UISettings::values.hide_mouse.GetValue()); | ||
| 43 | ui->toggle_controller_applet_disabled->setEnabled(runtime_lock); | ||
| 44 | ui->toggle_controller_applet_disabled->setChecked( | ||
| 45 | UISettings::values.controller_applet_disabled.GetValue()); | ||
| 46 | 46 | ||
| 47 | ui->toggle_speed_limit->setChecked(Settings::values.use_speed_limit.GetValue()); | 47 | if (widget == nullptr) { |
| 48 | ui->speed_limit->setValue(Settings::values.speed_limit.GetValue()); | 48 | continue; |
| 49 | } | ||
| 50 | if (!widget->Valid()) { | ||
| 51 | widget->deleteLater(); | ||
| 52 | continue; | ||
| 53 | } | ||
| 49 | 54 | ||
| 50 | ui->button_reset_defaults->setEnabled(runtime_lock); | 55 | hold.emplace(setting->Id(), widget); |
| 56 | } | ||
| 51 | 57 | ||
| 52 | if (Settings::IsConfiguringGlobal()) { | 58 | for (const auto& [id, widget] : hold) { |
| 53 | ui->speed_limit->setEnabled(Settings::values.use_speed_limit.GetValue()); | 59 | layout.addWidget(widget); |
| 54 | } else { | ||
| 55 | ui->speed_limit->setEnabled(Settings::values.use_speed_limit.GetValue() && | ||
| 56 | use_speed_limit != ConfigurationShared::CheckState::Global); | ||
| 57 | } | 60 | } |
| 58 | } | 61 | } |
| 59 | 62 | ||
| @@ -77,32 +80,9 @@ void ConfigureGeneral::ResetDefaults() { | |||
| 77 | } | 80 | } |
| 78 | 81 | ||
| 79 | void ConfigureGeneral::ApplyConfiguration() { | 82 | void ConfigureGeneral::ApplyConfiguration() { |
| 80 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_multi_core, ui->use_multi_core, | 83 | bool powered_on = system.IsPoweredOn(); |
| 81 | use_multi_core); | 84 | for (const auto& func : apply_funcs) { |
| 82 | 85 | func(powered_on); | |
| 83 | if (Settings::IsConfiguringGlobal()) { | ||
| 84 | UISettings::values.confirm_before_closing = ui->toggle_check_exit->isChecked(); | ||
| 85 | UISettings::values.select_user_on_boot = ui->toggle_user_on_boot->isChecked(); | ||
| 86 | UISettings::values.pause_when_in_background = ui->toggle_background_pause->isChecked(); | ||
| 87 | UISettings::values.hide_mouse = ui->toggle_hide_mouse->isChecked(); | ||
| 88 | UISettings::values.controller_applet_disabled = | ||
| 89 | ui->toggle_controller_applet_disabled->isChecked(); | ||
| 90 | |||
| 91 | // Guard if during game and set to game-specific value | ||
| 92 | if (Settings::values.use_speed_limit.UsingGlobal()) { | ||
| 93 | Settings::values.use_speed_limit.SetValue(ui->toggle_speed_limit->checkState() == | ||
| 94 | Qt::Checked); | ||
| 95 | Settings::values.speed_limit.SetValue(ui->speed_limit->value()); | ||
| 96 | } | ||
| 97 | } else { | ||
| 98 | bool global_speed_limit = use_speed_limit == ConfigurationShared::CheckState::Global; | ||
| 99 | Settings::values.use_speed_limit.SetGlobal(global_speed_limit); | ||
| 100 | Settings::values.speed_limit.SetGlobal(global_speed_limit); | ||
| 101 | if (!global_speed_limit) { | ||
| 102 | Settings::values.use_speed_limit.SetValue(ui->toggle_speed_limit->checkState() == | ||
| 103 | Qt::Checked); | ||
| 104 | Settings::values.speed_limit.SetValue(ui->speed_limit->value()); | ||
| 105 | } | ||
| 106 | } | 86 | } |
| 107 | } | 87 | } |
| 108 | 88 | ||
| @@ -117,33 +97,3 @@ void ConfigureGeneral::changeEvent(QEvent* event) { | |||
| 117 | void ConfigureGeneral::RetranslateUI() { | 97 | void ConfigureGeneral::RetranslateUI() { |
| 118 | ui->retranslateUi(this); | 98 | ui->retranslateUi(this); |
| 119 | } | 99 | } |
| 120 | |||
| 121 | void ConfigureGeneral::SetupPerGameUI() { | ||
| 122 | if (Settings::IsConfiguringGlobal()) { | ||
| 123 | // Disables each setting if: | ||
| 124 | // - A game is running (thus settings in use), and | ||
| 125 | // - A non-global setting is applied. | ||
| 126 | ui->toggle_speed_limit->setEnabled(Settings::values.use_speed_limit.UsingGlobal()); | ||
| 127 | ui->speed_limit->setEnabled(Settings::values.speed_limit.UsingGlobal()); | ||
| 128 | |||
| 129 | return; | ||
| 130 | } | ||
| 131 | |||
| 132 | ui->toggle_check_exit->setVisible(false); | ||
| 133 | ui->toggle_user_on_boot->setVisible(false); | ||
| 134 | ui->toggle_background_pause->setVisible(false); | ||
| 135 | ui->toggle_hide_mouse->setVisible(false); | ||
| 136 | ui->toggle_controller_applet_disabled->setVisible(false); | ||
| 137 | |||
| 138 | ui->button_reset_defaults->setVisible(false); | ||
| 139 | |||
| 140 | ConfigurationShared::SetColoredTristate(ui->toggle_speed_limit, | ||
| 141 | Settings::values.use_speed_limit, use_speed_limit); | ||
| 142 | ConfigurationShared::SetColoredTristate(ui->use_multi_core, Settings::values.use_multi_core, | ||
| 143 | use_multi_core); | ||
| 144 | |||
| 145 | connect(ui->toggle_speed_limit, &QCheckBox::clicked, ui->speed_limit, [this]() { | ||
| 146 | ui->speed_limit->setEnabled(ui->toggle_speed_limit->isChecked() && | ||
| 147 | (use_speed_limit != ConfigurationShared::CheckState::Global)); | ||
| 148 | }); | ||
| 149 | } | ||
diff --git a/src/yuzu/configuration/configure_general.h b/src/yuzu/configuration/configure_general.h index 7ff63f425..2d953f679 100644 --- a/src/yuzu/configuration/configure_general.h +++ b/src/yuzu/configuration/configure_general.h | |||
| @@ -5,48 +5,49 @@ | |||
| 5 | 5 | ||
| 6 | #include <functional> | 6 | #include <functional> |
| 7 | #include <memory> | 7 | #include <memory> |
| 8 | #include <vector> | ||
| 8 | #include <QWidget> | 9 | #include <QWidget> |
| 10 | #include "yuzu/configuration/configuration_shared.h" | ||
| 9 | 11 | ||
| 10 | namespace Core { | 12 | namespace Core { |
| 11 | class System; | 13 | class System; |
| 12 | } | 14 | } |
| 13 | 15 | ||
| 14 | class ConfigureDialog; | 16 | class ConfigureDialog; |
| 15 | |||
| 16 | namespace ConfigurationShared { | ||
| 17 | enum class CheckState; | ||
| 18 | } | ||
| 19 | |||
| 20 | class HotkeyRegistry; | 17 | class HotkeyRegistry; |
| 21 | 18 | ||
| 22 | namespace Ui { | 19 | namespace Ui { |
| 23 | class ConfigureGeneral; | 20 | class ConfigureGeneral; |
| 24 | } | 21 | } |
| 25 | 22 | ||
| 26 | class ConfigureGeneral : public QWidget { | 23 | namespace ConfigurationShared { |
| 27 | Q_OBJECT | 24 | class Builder; |
| 25 | } | ||
| 28 | 26 | ||
| 27 | class ConfigureGeneral : public ConfigurationShared::Tab { | ||
| 29 | public: | 28 | public: |
| 30 | explicit ConfigureGeneral(const Core::System& system_, QWidget* parent = nullptr); | 29 | explicit ConfigureGeneral(const Core::System& system_, |
| 30 | std::shared_ptr<std::vector<ConfigurationShared::Tab*>> group, | ||
| 31 | const ConfigurationShared::Builder& builder, | ||
| 32 | QWidget* parent = nullptr); | ||
| 31 | ~ConfigureGeneral() override; | 33 | ~ConfigureGeneral() override; |
| 32 | 34 | ||
| 33 | void SetResetCallback(std::function<void()> callback); | 35 | void SetResetCallback(std::function<void()> callback); |
| 34 | void ResetDefaults(); | 36 | void ResetDefaults(); |
| 35 | void ApplyConfiguration(); | 37 | void ApplyConfiguration() override; |
| 36 | void SetConfiguration(); | 38 | void SetConfiguration() override; |
| 37 | 39 | ||
| 38 | private: | 40 | private: |
| 41 | void Setup(const ConfigurationShared::Builder& builder); | ||
| 42 | |||
| 39 | void changeEvent(QEvent* event) override; | 43 | void changeEvent(QEvent* event) override; |
| 40 | void RetranslateUI(); | 44 | void RetranslateUI(); |
| 41 | 45 | ||
| 42 | void SetupPerGameUI(); | ||
| 43 | |||
| 44 | std::function<void()> reset_callback; | 46 | std::function<void()> reset_callback; |
| 45 | 47 | ||
| 46 | std::unique_ptr<Ui::ConfigureGeneral> ui; | 48 | std::unique_ptr<Ui::ConfigureGeneral> ui; |
| 47 | 49 | ||
| 48 | ConfigurationShared::CheckState use_speed_limit; | 50 | std::vector<std::function<void(bool)>> apply_funcs{}; |
| 49 | ConfigurationShared::CheckState use_multi_core; | ||
| 50 | 51 | ||
| 51 | const Core::System& system; | 52 | const Core::System& system; |
| 52 | }; | 53 | }; |
diff --git a/src/yuzu/configuration/configure_general.ui b/src/yuzu/configuration/configure_general.ui index fe757d011..a10e7d3a5 100644 --- a/src/yuzu/configuration/configure_general.ui +++ b/src/yuzu/configuration/configure_general.ui | |||
| @@ -26,77 +26,22 @@ | |||
| 26 | </property> | 26 | </property> |
| 27 | <layout class="QHBoxLayout" name="GeneralHorizontalLayout"> | 27 | <layout class="QHBoxLayout" name="GeneralHorizontalLayout"> |
| 28 | <item> | 28 | <item> |
| 29 | <layout class="QVBoxLayout" name="GeneralVerticalLayout"> | 29 | <widget class="QWidget" name="general_widget" native="true"> |
| 30 | <item> | 30 | <layout class="QVBoxLayout" name="GeneralVerticalLayout"> |
| 31 | <layout class="QHBoxLayout" name="horizontalLayout_2"> | 31 | <property name="leftMargin"> |
| 32 | <item> | 32 | <number>0</number> |
| 33 | <widget class="QCheckBox" name="toggle_speed_limit"> | 33 | </property> |
| 34 | <property name="text"> | 34 | <property name="topMargin"> |
| 35 | <string>Limit Speed Percent</string> | 35 | <number>0</number> |
| 36 | </property> | 36 | </property> |
| 37 | </widget> | 37 | <property name="rightMargin"> |
| 38 | </item> | 38 | <number>0</number> |
| 39 | <item> | 39 | </property> |
| 40 | <widget class="QSpinBox" name="speed_limit"> | 40 | <property name="bottomMargin"> |
| 41 | <property name="suffix"> | 41 | <number>0</number> |
| 42 | <string>%</string> | 42 | </property> |
| 43 | </property> | 43 | </layout> |
| 44 | <property name="minimum"> | 44 | </widget> |
| 45 | <number>1</number> | ||
| 46 | </property> | ||
| 47 | <property name="maximum"> | ||
| 48 | <number>9999</number> | ||
| 49 | </property> | ||
| 50 | <property name="value"> | ||
| 51 | <number>100</number> | ||
| 52 | </property> | ||
| 53 | </widget> | ||
| 54 | </item> | ||
| 55 | </layout> | ||
| 56 | </item> | ||
| 57 | <item> | ||
| 58 | <widget class="QCheckBox" name="use_multi_core"> | ||
| 59 | <property name="text"> | ||
| 60 | <string>Multicore CPU Emulation</string> | ||
| 61 | </property> | ||
| 62 | </widget> | ||
| 63 | </item> | ||
| 64 | <item> | ||
| 65 | <widget class="QCheckBox" name="toggle_check_exit"> | ||
| 66 | <property name="text"> | ||
| 67 | <string>Confirm exit while emulation is running</string> | ||
| 68 | </property> | ||
| 69 | </widget> | ||
| 70 | </item> | ||
| 71 | <item> | ||
| 72 | <widget class="QCheckBox" name="toggle_user_on_boot"> | ||
| 73 | <property name="text"> | ||
| 74 | <string>Prompt for user on game boot</string> | ||
| 75 | </property> | ||
| 76 | </widget> | ||
| 77 | </item> | ||
| 78 | <item> | ||
| 79 | <widget class="QCheckBox" name="toggle_background_pause"> | ||
| 80 | <property name="text"> | ||
| 81 | <string>Pause emulation when in background</string> | ||
| 82 | </property> | ||
| 83 | </widget> | ||
| 84 | </item> | ||
| 85 | <item> | ||
| 86 | <widget class="QCheckBox" name="toggle_hide_mouse"> | ||
| 87 | <property name="text"> | ||
| 88 | <string>Hide mouse on inactivity</string> | ||
| 89 | </property> | ||
| 90 | </widget> | ||
| 91 | </item> | ||
| 92 | <item> | ||
| 93 | <widget class="QCheckBox" name="toggle_controller_applet_disabled"> | ||
| 94 | <property name="text"> | ||
| 95 | <string>Disable controller applet</string> | ||
| 96 | </property> | ||
| 97 | </widget> | ||
| 98 | </item> | ||
| 99 | </layout> | ||
| 100 | </item> | 45 | </item> |
| 101 | </layout> | 46 | </layout> |
| 102 | </widget> | 47 | </widget> |
diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp index a4965524a..a94fbc89a 100644 --- a/src/yuzu/configuration/configure_graphics.cpp +++ b/src/yuzu/configuration/configure_graphics.cpp | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include <iterator> | 7 | #include <iterator> |
| 8 | #include <string> | 8 | #include <string> |
| 9 | #include <tuple> | 9 | #include <tuple> |
| 10 | #include <typeinfo> | ||
| 10 | #include <utility> | 11 | #include <utility> |
| 11 | #include <vector> | 12 | #include <vector> |
| 12 | #include <QBoxLayout> | 13 | #include <QBoxLayout> |
| @@ -15,23 +16,29 @@ | |||
| 15 | #include <QComboBox> | 16 | #include <QComboBox> |
| 16 | #include <QIcon> | 17 | #include <QIcon> |
| 17 | #include <QLabel> | 18 | #include <QLabel> |
| 19 | #include <QLineEdit> | ||
| 18 | #include <QPixmap> | 20 | #include <QPixmap> |
| 19 | #include <QPushButton> | 21 | #include <QPushButton> |
| 20 | #include <QSlider> | 22 | #include <QSlider> |
| 21 | #include <QStringLiteral> | 23 | #include <QStringLiteral> |
| 22 | #include <QtCore/qobjectdefs.h> | 24 | #include <QtCore/qobjectdefs.h> |
| 25 | #include <qabstractbutton.h> | ||
| 26 | #include <qboxlayout.h> | ||
| 23 | #include <qcoreevent.h> | 27 | #include <qcoreevent.h> |
| 24 | #include <qglobal.h> | 28 | #include <qglobal.h> |
| 29 | #include <qgridlayout.h> | ||
| 25 | #include <vulkan/vulkan_core.h> | 30 | #include <vulkan/vulkan_core.h> |
| 26 | 31 | ||
| 27 | #include "common/common_types.h" | 32 | #include "common/common_types.h" |
| 28 | #include "common/dynamic_library.h" | 33 | #include "common/dynamic_library.h" |
| 29 | #include "common/logging/log.h" | 34 | #include "common/logging/log.h" |
| 30 | #include "common/settings.h" | 35 | #include "common/settings.h" |
| 36 | #include "common/settings_enums.h" | ||
| 31 | #include "core/core.h" | 37 | #include "core/core.h" |
| 32 | #include "ui_configure_graphics.h" | 38 | #include "ui_configure_graphics.h" |
| 33 | #include "yuzu/configuration/configuration_shared.h" | 39 | #include "yuzu/configuration/configuration_shared.h" |
| 34 | #include "yuzu/configuration/configure_graphics.h" | 40 | #include "yuzu/configuration/configure_graphics.h" |
| 41 | #include "yuzu/configuration/shared_widget.h" | ||
| 35 | #include "yuzu/qt_common.h" | 42 | #include "yuzu/qt_common.h" |
| 36 | #include "yuzu/uisettings.h" | 43 | #include "yuzu/uisettings.h" |
| 37 | #include "yuzu/vk_device_info.h" | 44 | #include "yuzu/vk_device_info.h" |
| @@ -46,9 +53,9 @@ static constexpr VkPresentModeKHR VSyncSettingToMode(Settings::VSyncMode mode) { | |||
| 46 | return VK_PRESENT_MODE_IMMEDIATE_KHR; | 53 | return VK_PRESENT_MODE_IMMEDIATE_KHR; |
| 47 | case Settings::VSyncMode::Mailbox: | 54 | case Settings::VSyncMode::Mailbox: |
| 48 | return VK_PRESENT_MODE_MAILBOX_KHR; | 55 | return VK_PRESENT_MODE_MAILBOX_KHR; |
| 49 | case Settings::VSyncMode::FIFO: | 56 | case Settings::VSyncMode::Fifo: |
| 50 | return VK_PRESENT_MODE_FIFO_KHR; | 57 | return VK_PRESENT_MODE_FIFO_KHR; |
| 51 | case Settings::VSyncMode::FIFORelaxed: | 58 | case Settings::VSyncMode::FifoRelaxed: |
| 52 | return VK_PRESENT_MODE_FIFO_RELAXED_KHR; | 59 | return VK_PRESENT_MODE_FIFO_RELAXED_KHR; |
| 53 | default: | 60 | default: |
| 54 | return VK_PRESENT_MODE_FIFO_KHR; | 61 | return VK_PRESENT_MODE_FIFO_KHR; |
| @@ -62,50 +69,67 @@ static constexpr Settings::VSyncMode PresentModeToSetting(VkPresentModeKHR mode) | |||
| 62 | case VK_PRESENT_MODE_MAILBOX_KHR: | 69 | case VK_PRESENT_MODE_MAILBOX_KHR: |
| 63 | return Settings::VSyncMode::Mailbox; | 70 | return Settings::VSyncMode::Mailbox; |
| 64 | case VK_PRESENT_MODE_FIFO_KHR: | 71 | case VK_PRESENT_MODE_FIFO_KHR: |
| 65 | return Settings::VSyncMode::FIFO; | 72 | return Settings::VSyncMode::Fifo; |
| 66 | case VK_PRESENT_MODE_FIFO_RELAXED_KHR: | 73 | case VK_PRESENT_MODE_FIFO_RELAXED_KHR: |
| 67 | return Settings::VSyncMode::FIFORelaxed; | 74 | return Settings::VSyncMode::FifoRelaxed; |
| 68 | default: | 75 | default: |
| 69 | return Settings::VSyncMode::FIFO; | 76 | return Settings::VSyncMode::Fifo; |
| 70 | } | 77 | } |
| 71 | } | 78 | } |
| 72 | 79 | ||
| 73 | ConfigureGraphics::ConfigureGraphics(const Core::System& system_, | 80 | ConfigureGraphics::ConfigureGraphics(const Core::System& system_, |
| 74 | std::vector<VkDeviceInfo::Record>& records_, | 81 | std::vector<VkDeviceInfo::Record>& records_, |
| 75 | const std::function<void()>& expose_compute_option_, | 82 | const std::function<void()>& expose_compute_option_, |
| 76 | QWidget* parent) | 83 | std::shared_ptr<std::vector<ConfigurationShared::Tab*>> group_, |
| 77 | : QWidget(parent), ui{std::make_unique<Ui::ConfigureGraphics>()}, records{records_}, | 84 | const ConfigurationShared::Builder& builder, QWidget* parent) |
| 78 | expose_compute_option{expose_compute_option_}, system{system_} { | 85 | : ConfigurationShared::Tab(group_, parent), ui{std::make_unique<Ui::ConfigureGraphics>()}, |
| 86 | records{records_}, expose_compute_option{expose_compute_option_}, system{system_}, | ||
| 87 | combobox_translations{builder.ComboboxTranslations()}, | ||
| 88 | shader_mapping{ | ||
| 89 | combobox_translations.at(Settings::EnumMetadata<Settings::ShaderBackend>::Index())} { | ||
| 79 | vulkan_device = Settings::values.vulkan_device.GetValue(); | 90 | vulkan_device = Settings::values.vulkan_device.GetValue(); |
| 80 | RetrieveVulkanDevices(); | 91 | RetrieveVulkanDevices(); |
| 81 | 92 | ||
| 82 | ui->setupUi(this); | 93 | ui->setupUi(this); |
| 83 | 94 | ||
| 95 | Setup(builder); | ||
| 96 | |||
| 84 | for (const auto& device : vulkan_devices) { | 97 | for (const auto& device : vulkan_devices) { |
| 85 | ui->device->addItem(device); | 98 | vulkan_device_combobox->addItem(device); |
| 86 | } | 99 | } |
| 87 | 100 | ||
| 88 | ui->backend->addItem(QStringLiteral("GLSL")); | 101 | UpdateBackgroundColorButton(QColor::fromRgb(Settings::values.bg_red.GetValue(), |
| 89 | ui->backend->addItem(tr("GLASM (Assembly Shaders, NVIDIA Only)")); | 102 | Settings::values.bg_green.GetValue(), |
| 90 | ui->backend->addItem(tr("SPIR-V (Experimental, Mesa Only)")); | 103 | Settings::values.bg_blue.GetValue())); |
| 91 | 104 | UpdateAPILayout(); | |
| 92 | SetupPerGameUI(); | 105 | PopulateVSyncModeSelection(); //< must happen after UpdateAPILayout |
| 93 | 106 | ||
| 94 | SetConfiguration(); | 107 | // VSync setting needs to be determined after populating the VSync combobox |
| 108 | if (Settings::IsConfiguringGlobal()) { | ||
| 109 | const auto vsync_mode_setting = Settings::values.vsync_mode.GetValue(); | ||
| 110 | const auto vsync_mode = VSyncSettingToMode(vsync_mode_setting); | ||
| 111 | int index{}; | ||
| 112 | for (const auto mode : vsync_mode_combobox_enum_map) { | ||
| 113 | if (mode == vsync_mode) { | ||
| 114 | break; | ||
| 115 | } | ||
| 116 | index++; | ||
| 117 | } | ||
| 118 | if (static_cast<unsigned long>(index) < vsync_mode_combobox_enum_map.size()) { | ||
| 119 | vsync_mode_combobox->setCurrentIndex(index); | ||
| 120 | } | ||
| 121 | } | ||
| 95 | 122 | ||
| 96 | connect(ui->api, qOverload<int>(&QComboBox::currentIndexChanged), this, [this] { | 123 | connect(api_combobox, qOverload<int>(&QComboBox::activated), this, [this] { |
| 97 | UpdateAPILayout(); | 124 | UpdateAPILayout(); |
| 98 | PopulateVSyncModeSelection(); | 125 | PopulateVSyncModeSelection(); |
| 99 | if (!Settings::IsConfiguringGlobal()) { | ||
| 100 | ConfigurationShared::SetHighlight( | ||
| 101 | ui->api_widget, ui->api->currentIndex() != ConfigurationShared::USE_GLOBAL_INDEX); | ||
| 102 | } | ||
| 103 | }); | 126 | }); |
| 104 | connect(ui->device, qOverload<int>(&QComboBox::activated), this, [this](int device) { | 127 | connect(vulkan_device_combobox, qOverload<int>(&QComboBox::activated), this, |
| 105 | UpdateDeviceSelection(device); | 128 | [this](int device) { |
| 106 | PopulateVSyncModeSelection(); | 129 | UpdateDeviceSelection(device); |
| 107 | }); | 130 | PopulateVSyncModeSelection(); |
| 108 | connect(ui->backend, qOverload<int>(&QComboBox::activated), this, | 131 | }); |
| 132 | connect(shader_backend_combobox, qOverload<int>(&QComboBox::activated), this, | ||
| 109 | [this](int backend) { UpdateShaderBackendSelection(backend); }); | 133 | [this](int backend) { UpdateShaderBackendSelection(backend); }); |
| 110 | 134 | ||
| 111 | connect(ui->bg_button, &QPushButton::clicked, this, [this] { | 135 | connect(ui->bg_button, &QPushButton::clicked, this, [this] { |
| @@ -116,39 +140,45 @@ ConfigureGraphics::ConfigureGraphics(const Core::System& system_, | |||
| 116 | UpdateBackgroundColorButton(new_bg_color); | 140 | UpdateBackgroundColorButton(new_bg_color); |
| 117 | }); | 141 | }); |
| 118 | 142 | ||
| 119 | ui->api->setEnabled(!UISettings::values.has_broken_vulkan && ui->api->isEnabled()); | 143 | api_combobox->setEnabled(!UISettings::values.has_broken_vulkan && api_combobox->isEnabled()); |
| 120 | ui->api_widget->setEnabled( | 144 | ui->api_widget->setEnabled( |
| 121 | (!UISettings::values.has_broken_vulkan || Settings::IsConfiguringGlobal()) && | 145 | (!UISettings::values.has_broken_vulkan || Settings::IsConfiguringGlobal()) && |
| 122 | ui->api_widget->isEnabled()); | 146 | ui->api_widget->isEnabled()); |
| 123 | ui->bg_label->setVisible(Settings::IsConfiguringGlobal()); | ||
| 124 | ui->bg_combobox->setVisible(!Settings::IsConfiguringGlobal()); | ||
| 125 | 147 | ||
| 126 | connect(ui->fsr_sharpening_slider, &QSlider::valueChanged, this, | 148 | if (Settings::IsConfiguringGlobal()) { |
| 127 | &ConfigureGraphics::SetFSRIndicatorText); | 149 | ui->bg_widget->setEnabled(Settings::values.bg_red.UsingGlobal()); |
| 128 | ui->fsr_sharpening_combobox->setVisible(!Settings::IsConfiguringGlobal()); | 150 | } |
| 129 | ui->fsr_sharpening_label->setVisible(Settings::IsConfiguringGlobal()); | ||
| 130 | } | 151 | } |
| 131 | 152 | ||
| 132 | void ConfigureGraphics::PopulateVSyncModeSelection() { | 153 | void ConfigureGraphics::PopulateVSyncModeSelection() { |
| 154 | if (!Settings::IsConfiguringGlobal()) { | ||
| 155 | return; | ||
| 156 | } | ||
| 157 | |||
| 133 | const Settings::RendererBackend backend{GetCurrentGraphicsBackend()}; | 158 | const Settings::RendererBackend backend{GetCurrentGraphicsBackend()}; |
| 134 | if (backend == Settings::RendererBackend::Null) { | 159 | if (backend == Settings::RendererBackend::Null) { |
| 135 | ui->vsync_mode_combobox->setEnabled(false); | 160 | vsync_mode_combobox->setEnabled(false); |
| 136 | return; | 161 | return; |
| 137 | } | 162 | } |
| 138 | ui->vsync_mode_combobox->setEnabled(true); | 163 | vsync_mode_combobox->setEnabled(true); |
| 139 | 164 | ||
| 140 | const int current_index = //< current selected vsync mode from combobox | 165 | const int current_index = //< current selected vsync mode from combobox |
| 141 | ui->vsync_mode_combobox->currentIndex(); | 166 | vsync_mode_combobox->currentIndex(); |
| 142 | const auto current_mode = //< current selected vsync mode as a VkPresentModeKHR | 167 | const auto current_mode = //< current selected vsync mode as a VkPresentModeKHR |
| 143 | current_index == -1 ? VSyncSettingToMode(Settings::values.vsync_mode.GetValue()) | 168 | current_index == -1 ? VSyncSettingToMode(Settings::values.vsync_mode.GetValue()) |
| 144 | : vsync_mode_combobox_enum_map[current_index]; | 169 | : vsync_mode_combobox_enum_map[current_index]; |
| 145 | int index{}; | 170 | int index{}; |
| 146 | const int device{ui->device->currentIndex()}; //< current selected Vulkan device | 171 | const int device{vulkan_device_combobox->currentIndex()}; //< current selected Vulkan device |
| 172 | if (device == -1) { | ||
| 173 | // Invalid device | ||
| 174 | return; | ||
| 175 | } | ||
| 176 | |||
| 147 | const auto& present_modes = //< relevant vector of present modes for the selected device or API | 177 | const auto& present_modes = //< relevant vector of present modes for the selected device or API |
| 148 | backend == Settings::RendererBackend::Vulkan ? device_present_modes[device] | 178 | backend == Settings::RendererBackend::Vulkan ? device_present_modes[device] |
| 149 | : default_present_modes; | 179 | : default_present_modes; |
| 150 | 180 | ||
| 151 | ui->vsync_mode_combobox->clear(); | 181 | vsync_mode_combobox->clear(); |
| 152 | vsync_mode_combobox_enum_map.clear(); | 182 | vsync_mode_combobox_enum_map.clear(); |
| 153 | vsync_mode_combobox_enum_map.reserve(present_modes.size()); | 183 | vsync_mode_combobox_enum_map.reserve(present_modes.size()); |
| 154 | for (const auto present_mode : present_modes) { | 184 | for (const auto present_mode : present_modes) { |
| @@ -157,10 +187,10 @@ void ConfigureGraphics::PopulateVSyncModeSelection() { | |||
| 157 | continue; | 187 | continue; |
| 158 | } | 188 | } |
| 159 | 189 | ||
| 160 | ui->vsync_mode_combobox->insertItem(index, mode_name); | 190 | vsync_mode_combobox->insertItem(index, mode_name); |
| 161 | vsync_mode_combobox_enum_map.push_back(present_mode); | 191 | vsync_mode_combobox_enum_map.push_back(present_mode); |
| 162 | if (present_mode == current_mode) { | 192 | if (present_mode == current_mode) { |
| 163 | ui->vsync_mode_combobox->setCurrentIndex(index); | 193 | vsync_mode_combobox->setCurrentIndex(index); |
| 164 | } | 194 | } |
| 165 | index++; | 195 | index++; |
| 166 | } | 196 | } |
| @@ -186,112 +216,124 @@ void ConfigureGraphics::UpdateShaderBackendSelection(int backend) { | |||
| 186 | 216 | ||
| 187 | ConfigureGraphics::~ConfigureGraphics() = default; | 217 | ConfigureGraphics::~ConfigureGraphics() = default; |
| 188 | 218 | ||
| 189 | void ConfigureGraphics::SetConfiguration() { | 219 | void ConfigureGraphics::SetConfiguration() {} |
| 190 | const bool runtime_lock = !system.IsPoweredOn(); | 220 | |
| 191 | 221 | void ConfigureGraphics::Setup(const ConfigurationShared::Builder& builder) { | |
| 192 | ui->api_widget->setEnabled(runtime_lock); | 222 | QLayout* api_layout = ui->api_widget->layout(); |
| 193 | ui->use_asynchronous_gpu_emulation->setEnabled(runtime_lock); | 223 | QWidget* api_grid_widget = new QWidget(this); |
| 194 | ui->use_disk_shader_cache->setEnabled(runtime_lock); | 224 | QVBoxLayout* api_grid_layout = new QVBoxLayout(api_grid_widget); |
| 195 | ui->nvdec_emulation_widget->setEnabled(runtime_lock); | 225 | api_grid_layout->setContentsMargins(0, 0, 0, 0); |
| 196 | ui->resolution_combobox->setEnabled(runtime_lock); | 226 | api_layout->addWidget(api_grid_widget); |
| 197 | ui->accelerate_astc->setEnabled(runtime_lock); | 227 | |
| 198 | ui->vsync_mode_layout->setEnabled(runtime_lock || | 228 | QLayout& graphics_layout = *ui->graphics_widget->layout(); |
| 199 | Settings::values.renderer_backend.GetValue() == | 229 | |
| 200 | Settings::RendererBackend::Vulkan); | 230 | std::map<u32, QWidget*> hold_graphics; |
| 201 | ui->use_disk_shader_cache->setChecked(Settings::values.use_disk_shader_cache.GetValue()); | 231 | std::vector<QWidget*> hold_api; |
| 202 | ui->use_asynchronous_gpu_emulation->setChecked( | 232 | |
| 203 | Settings::values.use_asynchronous_gpu_emulation.GetValue()); | 233 | for (const auto setting : Settings::values.linkage.by_category[Settings::Category::Renderer]) { |
| 204 | ui->accelerate_astc->setChecked(Settings::values.accelerate_astc.GetValue()); | 234 | ConfigurationShared::Widget* widget = [&]() { |
| 235 | if (setting->Id() == Settings::values.fsr_sharpening_slider.Id()) { | ||
| 236 | // FSR needs a reversed slider and a 0.5 multiplier | ||
| 237 | return builder.BuildWidget( | ||
| 238 | setting, apply_funcs, ConfigurationShared::RequestType::ReverseSlider, true, | ||
| 239 | 0.5f, nullptr, tr("%", "FSR sharpening percentage (e.g. 50%)")); | ||
| 240 | } else { | ||
| 241 | return builder.BuildWidget(setting, apply_funcs); | ||
| 242 | } | ||
| 243 | }(); | ||
| 205 | 244 | ||
| 206 | if (Settings::IsConfiguringGlobal()) { | 245 | if (widget == nullptr) { |
| 207 | ui->api->setCurrentIndex(static_cast<int>(Settings::values.renderer_backend.GetValue())); | 246 | continue; |
| 208 | ui->fullscreen_mode_combobox->setCurrentIndex( | 247 | } |
| 209 | static_cast<int>(Settings::values.fullscreen_mode.GetValue())); | 248 | if (!widget->Valid()) { |
| 210 | ui->nvdec_emulation->setCurrentIndex( | 249 | widget->deleteLater(); |
| 211 | static_cast<int>(Settings::values.nvdec_emulation.GetValue())); | 250 | continue; |
| 212 | ui->aspect_ratio_combobox->setCurrentIndex(Settings::values.aspect_ratio.GetValue()); | 251 | } |
| 213 | ui->resolution_combobox->setCurrentIndex( | ||
| 214 | static_cast<int>(Settings::values.resolution_setup.GetValue())); | ||
| 215 | ui->scaling_filter_combobox->setCurrentIndex( | ||
| 216 | static_cast<int>(Settings::values.scaling_filter.GetValue())); | ||
| 217 | ui->fsr_sharpening_slider->setValue(Settings::values.fsr_sharpening_slider.GetValue()); | ||
| 218 | ui->anti_aliasing_combobox->setCurrentIndex( | ||
| 219 | static_cast<int>(Settings::values.anti_aliasing.GetValue())); | ||
| 220 | } else { | ||
| 221 | ConfigurationShared::SetPerGameSetting(ui->api, &Settings::values.renderer_backend); | ||
| 222 | ConfigurationShared::SetHighlight(ui->api_widget, | ||
| 223 | !Settings::values.renderer_backend.UsingGlobal()); | ||
| 224 | |||
| 225 | ConfigurationShared::SetPerGameSetting(ui->nvdec_emulation, | ||
| 226 | &Settings::values.nvdec_emulation); | ||
| 227 | ConfigurationShared::SetHighlight(ui->nvdec_emulation_widget, | ||
| 228 | !Settings::values.nvdec_emulation.UsingGlobal()); | ||
| 229 | |||
| 230 | ConfigurationShared::SetPerGameSetting(ui->fullscreen_mode_combobox, | ||
| 231 | &Settings::values.fullscreen_mode); | ||
| 232 | ConfigurationShared::SetHighlight(ui->fullscreen_mode_label, | ||
| 233 | !Settings::values.fullscreen_mode.UsingGlobal()); | ||
| 234 | |||
| 235 | ConfigurationShared::SetPerGameSetting(ui->aspect_ratio_combobox, | ||
| 236 | &Settings::values.aspect_ratio); | ||
| 237 | ConfigurationShared::SetHighlight(ui->ar_label, | ||
| 238 | !Settings::values.aspect_ratio.UsingGlobal()); | ||
| 239 | |||
| 240 | ConfigurationShared::SetPerGameSetting(ui->resolution_combobox, | ||
| 241 | &Settings::values.resolution_setup); | ||
| 242 | ConfigurationShared::SetHighlight(ui->resolution_label, | ||
| 243 | !Settings::values.resolution_setup.UsingGlobal()); | ||
| 244 | |||
| 245 | ConfigurationShared::SetPerGameSetting(ui->scaling_filter_combobox, | ||
| 246 | &Settings::values.scaling_filter); | ||
| 247 | ConfigurationShared::SetHighlight(ui->scaling_filter_label, | ||
| 248 | !Settings::values.scaling_filter.UsingGlobal()); | ||
| 249 | |||
| 250 | ConfigurationShared::SetPerGameSetting(ui->anti_aliasing_combobox, | ||
| 251 | &Settings::values.anti_aliasing); | ||
| 252 | ConfigurationShared::SetHighlight(ui->anti_aliasing_label, | ||
| 253 | !Settings::values.anti_aliasing.UsingGlobal()); | ||
| 254 | |||
| 255 | ui->fsr_sharpening_combobox->setCurrentIndex( | ||
| 256 | Settings::values.fsr_sharpening_slider.UsingGlobal() ? 0 : 1); | ||
| 257 | ui->fsr_sharpening_slider->setEnabled( | ||
| 258 | !Settings::values.fsr_sharpening_slider.UsingGlobal()); | ||
| 259 | ui->fsr_sharpening_value->setEnabled(!Settings::values.fsr_sharpening_slider.UsingGlobal()); | ||
| 260 | ConfigurationShared::SetHighlight(ui->fsr_sharpening_layout, | ||
| 261 | !Settings::values.fsr_sharpening_slider.UsingGlobal()); | ||
| 262 | ui->fsr_sharpening_slider->setValue(Settings::values.fsr_sharpening_slider.GetValue()); | ||
| 263 | |||
| 264 | ui->bg_combobox->setCurrentIndex(Settings::values.bg_red.UsingGlobal() ? 0 : 1); | ||
| 265 | ui->bg_button->setEnabled(!Settings::values.bg_red.UsingGlobal()); | ||
| 266 | ConfigurationShared::SetHighlight(ui->bg_layout, !Settings::values.bg_red.UsingGlobal()); | ||
| 267 | } | ||
| 268 | UpdateBackgroundColorButton(QColor::fromRgb(Settings::values.bg_red.GetValue(), | ||
| 269 | Settings::values.bg_green.GetValue(), | ||
| 270 | Settings::values.bg_blue.GetValue())); | ||
| 271 | UpdateAPILayout(); | ||
| 272 | PopulateVSyncModeSelection(); //< must happen after UpdateAPILayout | ||
| 273 | SetFSRIndicatorText(ui->fsr_sharpening_slider->sliderPosition()); | ||
| 274 | 252 | ||
| 275 | // VSync setting needs to be determined after populating the VSync combobox | 253 | if (setting->Id() == Settings::values.renderer_backend.Id()) { |
| 276 | if (Settings::IsConfiguringGlobal()) { | 254 | // Add the renderer combobox now so it's at the top |
| 277 | const auto vsync_mode_setting = Settings::values.vsync_mode.GetValue(); | 255 | api_grid_layout->addWidget(widget); |
| 278 | const auto vsync_mode = VSyncSettingToMode(vsync_mode_setting); | 256 | api_combobox = widget->combobox; |
| 279 | int index{}; | 257 | api_restore_global_button = widget->restore_button; |
| 280 | for (const auto mode : vsync_mode_combobox_enum_map) { | 258 | |
| 281 | if (mode == vsync_mode) { | 259 | if (!Settings::IsConfiguringGlobal()) { |
| 282 | break; | 260 | QObject::connect(api_restore_global_button, &QAbstractButton::clicked, |
| 261 | [this](bool) { UpdateAPILayout(); }); | ||
| 262 | |||
| 263 | // Detach API's restore button and place it where we want | ||
| 264 | // Lets us put it on the side, and it will automatically scale if there's a | ||
| 265 | // second combobox (shader_backend, vulkan_device) | ||
| 266 | widget->layout()->removeWidget(api_restore_global_button); | ||
| 267 | api_layout->addWidget(api_restore_global_button); | ||
| 283 | } | 268 | } |
| 284 | index++; | 269 | } else if (setting->Id() == Settings::values.vulkan_device.Id()) { |
| 285 | } | 270 | // Keep track of vulkan_device's combobox so we can populate it |
| 286 | if (static_cast<unsigned long>(index) < vsync_mode_combobox_enum_map.size()) { | 271 | hold_api.push_back(widget); |
| 287 | ui->vsync_mode_combobox->setCurrentIndex(index); | 272 | vulkan_device_combobox = widget->combobox; |
| 273 | vulkan_device_widget = widget; | ||
| 274 | } else if (setting->Id() == Settings::values.shader_backend.Id()) { | ||
| 275 | // Keep track of shader_backend's combobox so we can populate it | ||
| 276 | hold_api.push_back(widget); | ||
| 277 | shader_backend_combobox = widget->combobox; | ||
| 278 | shader_backend_widget = widget; | ||
| 279 | } else if (setting->Id() == Settings::values.vsync_mode.Id()) { | ||
| 280 | // Keep track of vsync_mode's combobox so we can populate it | ||
| 281 | vsync_mode_combobox = widget->combobox; | ||
| 282 | hold_graphics.emplace(setting->Id(), widget); | ||
| 283 | } else { | ||
| 284 | hold_graphics.emplace(setting->Id(), widget); | ||
| 288 | } | 285 | } |
| 289 | } | 286 | } |
| 290 | } | ||
| 291 | 287 | ||
| 292 | void ConfigureGraphics::SetFSRIndicatorText(int percentage) { | 288 | for (const auto& [id, widget] : hold_graphics) { |
| 293 | ui->fsr_sharpening_value->setText( | 289 | graphics_layout.addWidget(widget); |
| 294 | tr("%1%", "FSR sharpening percentage (e.g. 50%)").arg(100 - (percentage / 2))); | 290 | } |
| 291 | |||
| 292 | for (auto widget : hold_api) { | ||
| 293 | api_grid_layout->addWidget(widget); | ||
| 294 | } | ||
| 295 | |||
| 296 | // Background color is too specific to build into the new system, so we manage it here | ||
| 297 | // (3 settings, all collected into a single widget with a QColor to manage on top) | ||
| 298 | if (Settings::IsConfiguringGlobal()) { | ||
| 299 | apply_funcs.push_back([this](bool powered_on) { | ||
| 300 | Settings::values.bg_red.SetValue(static_cast<u8>(bg_color.red())); | ||
| 301 | Settings::values.bg_green.SetValue(static_cast<u8>(bg_color.green())); | ||
| 302 | Settings::values.bg_blue.SetValue(static_cast<u8>(bg_color.blue())); | ||
| 303 | }); | ||
| 304 | } else { | ||
| 305 | QPushButton* bg_restore_button = ConfigurationShared::Widget::CreateRestoreGlobalButton( | ||
| 306 | Settings::values.bg_red.UsingGlobal(), ui->bg_widget); | ||
| 307 | ui->bg_widget->layout()->addWidget(bg_restore_button); | ||
| 308 | |||
| 309 | QObject::connect(bg_restore_button, &QAbstractButton::clicked, | ||
| 310 | [bg_restore_button, this](bool) { | ||
| 311 | const int r = Settings::values.bg_red.GetValue(true); | ||
| 312 | const int g = Settings::values.bg_green.GetValue(true); | ||
| 313 | const int b = Settings::values.bg_blue.GetValue(true); | ||
| 314 | UpdateBackgroundColorButton(QColor::fromRgb(r, g, b)); | ||
| 315 | |||
| 316 | bg_restore_button->setVisible(false); | ||
| 317 | bg_restore_button->setEnabled(false); | ||
| 318 | }); | ||
| 319 | |||
| 320 | QObject::connect(ui->bg_button, &QAbstractButton::clicked, [bg_restore_button](bool) { | ||
| 321 | bg_restore_button->setVisible(true); | ||
| 322 | bg_restore_button->setEnabled(true); | ||
| 323 | }); | ||
| 324 | |||
| 325 | apply_funcs.push_back([bg_restore_button, this](bool powered_on) { | ||
| 326 | const bool using_global = !bg_restore_button->isEnabled(); | ||
| 327 | Settings::values.bg_red.SetGlobal(using_global); | ||
| 328 | Settings::values.bg_green.SetGlobal(using_global); | ||
| 329 | Settings::values.bg_blue.SetGlobal(using_global); | ||
| 330 | if (!using_global) { | ||
| 331 | Settings::values.bg_red.SetValue(static_cast<u8>(bg_color.red())); | ||
| 332 | Settings::values.bg_green.SetValue(static_cast<u8>(bg_color.green())); | ||
| 333 | Settings::values.bg_blue.SetValue(static_cast<u8>(bg_color.blue())); | ||
| 334 | } | ||
| 335 | }); | ||
| 336 | } | ||
| 295 | } | 337 | } |
| 296 | 338 | ||
| 297 | const QString ConfigureGraphics::TranslateVSyncMode(VkPresentModeKHR mode, | 339 | const QString ConfigureGraphics::TranslateVSyncMode(VkPresentModeKHR mode, |
| @@ -315,130 +357,48 @@ const QString ConfigureGraphics::TranslateVSyncMode(VkPresentModeKHR mode, | |||
| 315 | } | 357 | } |
| 316 | } | 358 | } |
| 317 | 359 | ||
| 360 | int ConfigureGraphics::FindIndex(u32 enumeration, int value) const { | ||
| 361 | for (u32 i = 0; i < combobox_translations.at(enumeration).size(); i++) { | ||
| 362 | if (combobox_translations.at(enumeration)[i].first == static_cast<u32>(value)) { | ||
| 363 | return i; | ||
| 364 | } | ||
| 365 | } | ||
| 366 | return -1; | ||
| 367 | } | ||
| 368 | |||
| 318 | void ConfigureGraphics::ApplyConfiguration() { | 369 | void ConfigureGraphics::ApplyConfiguration() { |
| 319 | const auto resolution_setup = static_cast<Settings::ResolutionSetup>( | 370 | const bool powered_on = system.IsPoweredOn(); |
| 320 | ui->resolution_combobox->currentIndex() - | 371 | for (const auto& func : apply_funcs) { |
| 321 | ((Settings::IsConfiguringGlobal()) ? 0 : ConfigurationShared::USE_GLOBAL_OFFSET)); | 372 | func(powered_on); |
| 322 | 373 | } | |
| 323 | const auto scaling_filter = static_cast<Settings::ScalingFilter>( | ||
| 324 | ui->scaling_filter_combobox->currentIndex() - | ||
| 325 | ((Settings::IsConfiguringGlobal()) ? 0 : ConfigurationShared::USE_GLOBAL_OFFSET)); | ||
| 326 | |||
| 327 | const auto anti_aliasing = static_cast<Settings::AntiAliasing>( | ||
| 328 | ui->anti_aliasing_combobox->currentIndex() - | ||
| 329 | ((Settings::IsConfiguringGlobal()) ? 0 : ConfigurationShared::USE_GLOBAL_OFFSET)); | ||
| 330 | |||
| 331 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.fullscreen_mode, | ||
| 332 | ui->fullscreen_mode_combobox); | ||
| 333 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.aspect_ratio, | ||
| 334 | ui->aspect_ratio_combobox); | ||
| 335 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_disk_shader_cache, | ||
| 336 | ui->use_disk_shader_cache, use_disk_shader_cache); | ||
| 337 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_asynchronous_gpu_emulation, | ||
| 338 | ui->use_asynchronous_gpu_emulation, | ||
| 339 | use_asynchronous_gpu_emulation); | ||
| 340 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.accelerate_astc, ui->accelerate_astc, | ||
| 341 | accelerate_astc); | ||
| 342 | 374 | ||
| 343 | if (Settings::IsConfiguringGlobal()) { | 375 | if (Settings::IsConfiguringGlobal()) { |
| 344 | // Guard if during game and set to game-specific value | 376 | const auto mode = vsync_mode_combobox_enum_map[vsync_mode_combobox->currentIndex()]; |
| 345 | if (Settings::values.renderer_backend.UsingGlobal()) { | ||
| 346 | Settings::values.renderer_backend.SetValue(GetCurrentGraphicsBackend()); | ||
| 347 | } | ||
| 348 | if (Settings::values.nvdec_emulation.UsingGlobal()) { | ||
| 349 | Settings::values.nvdec_emulation.SetValue(GetCurrentNvdecEmulation()); | ||
| 350 | } | ||
| 351 | if (Settings::values.shader_backend.UsingGlobal()) { | ||
| 352 | Settings::values.shader_backend.SetValue(shader_backend); | ||
| 353 | } | ||
| 354 | if (Settings::values.vulkan_device.UsingGlobal()) { | ||
| 355 | Settings::values.vulkan_device.SetValue(vulkan_device); | ||
| 356 | } | ||
| 357 | if (Settings::values.bg_red.UsingGlobal()) { | ||
| 358 | Settings::values.bg_red.SetValue(static_cast<u8>(bg_color.red())); | ||
| 359 | Settings::values.bg_green.SetValue(static_cast<u8>(bg_color.green())); | ||
| 360 | Settings::values.bg_blue.SetValue(static_cast<u8>(bg_color.blue())); | ||
| 361 | } | ||
| 362 | if (Settings::values.resolution_setup.UsingGlobal()) { | ||
| 363 | Settings::values.resolution_setup.SetValue(resolution_setup); | ||
| 364 | } | ||
| 365 | if (Settings::values.scaling_filter.UsingGlobal()) { | ||
| 366 | Settings::values.scaling_filter.SetValue(scaling_filter); | ||
| 367 | } | ||
| 368 | if (Settings::values.anti_aliasing.UsingGlobal()) { | ||
| 369 | Settings::values.anti_aliasing.SetValue(anti_aliasing); | ||
| 370 | } | ||
| 371 | Settings::values.fsr_sharpening_slider.SetValue(ui->fsr_sharpening_slider->value()); | ||
| 372 | |||
| 373 | const auto mode = vsync_mode_combobox_enum_map[ui->vsync_mode_combobox->currentIndex()]; | ||
| 374 | const auto vsync_mode = PresentModeToSetting(mode); | 377 | const auto vsync_mode = PresentModeToSetting(mode); |
| 375 | Settings::values.vsync_mode.SetValue(vsync_mode); | 378 | Settings::values.vsync_mode.SetValue(vsync_mode); |
| 376 | } else { | 379 | } |
| 377 | if (ui->resolution_combobox->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) { | ||
| 378 | Settings::values.resolution_setup.SetGlobal(true); | ||
| 379 | } else { | ||
| 380 | Settings::values.resolution_setup.SetGlobal(false); | ||
| 381 | Settings::values.resolution_setup.SetValue(resolution_setup); | ||
| 382 | } | ||
| 383 | if (ui->scaling_filter_combobox->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) { | ||
| 384 | Settings::values.scaling_filter.SetGlobal(true); | ||
| 385 | } else { | ||
| 386 | Settings::values.scaling_filter.SetGlobal(false); | ||
| 387 | Settings::values.scaling_filter.SetValue(scaling_filter); | ||
| 388 | } | ||
| 389 | if (ui->anti_aliasing_combobox->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) { | ||
| 390 | Settings::values.anti_aliasing.SetGlobal(true); | ||
| 391 | } else { | ||
| 392 | Settings::values.anti_aliasing.SetGlobal(false); | ||
| 393 | Settings::values.anti_aliasing.SetValue(anti_aliasing); | ||
| 394 | } | ||
| 395 | if (ui->api->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) { | ||
| 396 | Settings::values.renderer_backend.SetGlobal(true); | ||
| 397 | Settings::values.shader_backend.SetGlobal(true); | ||
| 398 | Settings::values.vulkan_device.SetGlobal(true); | ||
| 399 | } else { | ||
| 400 | Settings::values.renderer_backend.SetGlobal(false); | ||
| 401 | Settings::values.renderer_backend.SetValue(GetCurrentGraphicsBackend()); | ||
| 402 | switch (GetCurrentGraphicsBackend()) { | ||
| 403 | case Settings::RendererBackend::OpenGL: | ||
| 404 | case Settings::RendererBackend::Null: | ||
| 405 | Settings::values.shader_backend.SetGlobal(false); | ||
| 406 | Settings::values.vulkan_device.SetGlobal(true); | ||
| 407 | Settings::values.shader_backend.SetValue(shader_backend); | ||
| 408 | break; | ||
| 409 | case Settings::RendererBackend::Vulkan: | ||
| 410 | Settings::values.shader_backend.SetGlobal(true); | ||
| 411 | Settings::values.vulkan_device.SetGlobal(false); | ||
| 412 | Settings::values.vulkan_device.SetValue(vulkan_device); | ||
| 413 | break; | ||
| 414 | } | ||
| 415 | } | ||
| 416 | |||
| 417 | if (ui->nvdec_emulation->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) { | ||
| 418 | Settings::values.nvdec_emulation.SetGlobal(true); | ||
| 419 | } else { | ||
| 420 | Settings::values.nvdec_emulation.SetGlobal(false); | ||
| 421 | Settings::values.nvdec_emulation.SetValue(GetCurrentNvdecEmulation()); | ||
| 422 | } | ||
| 423 | |||
| 424 | if (ui->bg_combobox->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) { | ||
| 425 | Settings::values.bg_red.SetGlobal(true); | ||
| 426 | Settings::values.bg_green.SetGlobal(true); | ||
| 427 | Settings::values.bg_blue.SetGlobal(true); | ||
| 428 | } else { | ||
| 429 | Settings::values.bg_red.SetGlobal(false); | ||
| 430 | Settings::values.bg_green.SetGlobal(false); | ||
| 431 | Settings::values.bg_blue.SetGlobal(false); | ||
| 432 | Settings::values.bg_red.SetValue(static_cast<u8>(bg_color.red())); | ||
| 433 | Settings::values.bg_green.SetValue(static_cast<u8>(bg_color.green())); | ||
| 434 | Settings::values.bg_blue.SetValue(static_cast<u8>(bg_color.blue())); | ||
| 435 | } | ||
| 436 | 380 | ||
| 437 | if (ui->fsr_sharpening_combobox->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) { | 381 | Settings::values.vulkan_device.SetGlobal(true); |
| 438 | Settings::values.fsr_sharpening_slider.SetGlobal(true); | 382 | Settings::values.shader_backend.SetGlobal(true); |
| 439 | } else { | 383 | if (Settings::IsConfiguringGlobal() || |
| 440 | Settings::values.fsr_sharpening_slider.SetGlobal(false); | 384 | (!Settings::IsConfiguringGlobal() && api_restore_global_button->isEnabled())) { |
| 441 | Settings::values.fsr_sharpening_slider.SetValue(ui->fsr_sharpening_slider->value()); | 385 | auto backend = static_cast<Settings::RendererBackend>( |
| 386 | combobox_translations | ||
| 387 | .at(Settings::EnumMetadata< | ||
| 388 | Settings::RendererBackend>::Index())[api_combobox->currentIndex()] | ||
| 389 | .first); | ||
| 390 | switch (backend) { | ||
| 391 | case Settings::RendererBackend::OpenGL: | ||
| 392 | Settings::values.shader_backend.SetGlobal(Settings::IsConfiguringGlobal()); | ||
| 393 | Settings::values.shader_backend.SetValue(static_cast<Settings::ShaderBackend>( | ||
| 394 | shader_mapping[shader_backend_combobox->currentIndex()].first)); | ||
| 395 | break; | ||
| 396 | case Settings::RendererBackend::Vulkan: | ||
| 397 | Settings::values.vulkan_device.SetGlobal(Settings::IsConfiguringGlobal()); | ||
| 398 | Settings::values.vulkan_device.SetValue(vulkan_device_combobox->currentIndex()); | ||
| 399 | break; | ||
| 400 | case Settings::RendererBackend::Null: | ||
| 401 | break; | ||
| 442 | } | 402 | } |
| 443 | } | 403 | } |
| 444 | } | 404 | } |
| @@ -466,36 +426,26 @@ void ConfigureGraphics::UpdateBackgroundColorButton(QColor color) { | |||
| 466 | } | 426 | } |
| 467 | 427 | ||
| 468 | void ConfigureGraphics::UpdateAPILayout() { | 428 | void ConfigureGraphics::UpdateAPILayout() { |
| 469 | if (!Settings::IsConfiguringGlobal() && | 429 | bool runtime_lock = !system.IsPoweredOn(); |
| 470 | ui->api->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) { | 430 | bool need_global = !(Settings::IsConfiguringGlobal() || api_restore_global_button->isEnabled()); |
| 471 | vulkan_device = Settings::values.vulkan_device.GetValue(true); | 431 | vulkan_device = Settings::values.vulkan_device.GetValue(need_global); |
| 472 | shader_backend = Settings::values.shader_backend.GetValue(true); | 432 | shader_backend = Settings::values.shader_backend.GetValue(need_global); |
| 473 | ui->device_widget->setEnabled(false); | 433 | vulkan_device_widget->setEnabled(!need_global && runtime_lock); |
| 474 | ui->backend_widget->setEnabled(false); | 434 | shader_backend_widget->setEnabled(!need_global && runtime_lock); |
| 475 | } else { | 435 | |
| 476 | vulkan_device = Settings::values.vulkan_device.GetValue(); | 436 | const auto current_backend = GetCurrentGraphicsBackend(); |
| 477 | shader_backend = Settings::values.shader_backend.GetValue(); | 437 | const bool is_opengl = current_backend == Settings::RendererBackend::OpenGL; |
| 478 | ui->device_widget->setEnabled(true); | 438 | const bool is_vulkan = current_backend == Settings::RendererBackend::Vulkan; |
| 479 | ui->backend_widget->setEnabled(true); | 439 | |
| 480 | } | 440 | vulkan_device_widget->setVisible(is_vulkan); |
| 481 | 441 | shader_backend_widget->setVisible(is_opengl); | |
| 482 | switch (GetCurrentGraphicsBackend()) { | 442 | |
| 483 | case Settings::RendererBackend::OpenGL: | 443 | if (is_opengl) { |
| 484 | ui->backend->setCurrentIndex(static_cast<u32>(shader_backend)); | 444 | shader_backend_combobox->setCurrentIndex( |
| 485 | ui->device_widget->setVisible(false); | 445 | FindIndex(Settings::EnumMetadata<Settings::ShaderBackend>::Index(), |
| 486 | ui->backend_widget->setVisible(true); | 446 | static_cast<int>(shader_backend))); |
| 487 | break; | 447 | } else if (is_vulkan && static_cast<int>(vulkan_device) < vulkan_device_combobox->count()) { |
| 488 | case Settings::RendererBackend::Vulkan: | 448 | vulkan_device_combobox->setCurrentIndex(vulkan_device); |
| 489 | if (static_cast<int>(vulkan_device) < ui->device->count()) { | ||
| 490 | ui->device->setCurrentIndex(vulkan_device); | ||
| 491 | } | ||
| 492 | ui->device_widget->setVisible(true); | ||
| 493 | ui->backend_widget->setVisible(false); | ||
| 494 | break; | ||
| 495 | case Settings::RendererBackend::Null: | ||
| 496 | ui->device_widget->setVisible(false); | ||
| 497 | ui->backend_widget->setVisible(false); | ||
| 498 | break; | ||
| 499 | } | 449 | } |
| 500 | } | 450 | } |
| 501 | 451 | ||
| @@ -515,92 +465,11 @@ void ConfigureGraphics::RetrieveVulkanDevices() { | |||
| 515 | } | 465 | } |
| 516 | 466 | ||
| 517 | Settings::RendererBackend ConfigureGraphics::GetCurrentGraphicsBackend() const { | 467 | Settings::RendererBackend ConfigureGraphics::GetCurrentGraphicsBackend() const { |
| 518 | if (Settings::IsConfiguringGlobal()) { | 468 | if (!Settings::IsConfiguringGlobal() && !api_restore_global_button->isEnabled()) { |
| 519 | return static_cast<Settings::RendererBackend>(ui->api->currentIndex()); | 469 | return Settings::values.renderer_backend.GetValue(true); |
| 520 | } | ||
| 521 | |||
| 522 | if (ui->api->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) { | ||
| 523 | Settings::values.renderer_backend.SetGlobal(true); | ||
| 524 | return Settings::values.renderer_backend.GetValue(); | ||
| 525 | } | 470 | } |
| 526 | Settings::values.renderer_backend.SetGlobal(false); | 471 | return static_cast<Settings::RendererBackend>( |
| 527 | return static_cast<Settings::RendererBackend>(ui->api->currentIndex() - | 472 | combobox_translations.at(Settings::EnumMetadata<Settings::RendererBackend>::Index()) |
| 528 | ConfigurationShared::USE_GLOBAL_OFFSET); | 473 | .at(api_combobox->currentIndex()) |
| 529 | } | 474 | .first); |
| 530 | |||
| 531 | Settings::NvdecEmulation ConfigureGraphics::GetCurrentNvdecEmulation() const { | ||
| 532 | if (Settings::IsConfiguringGlobal()) { | ||
| 533 | return static_cast<Settings::NvdecEmulation>(ui->nvdec_emulation->currentIndex()); | ||
| 534 | } | ||
| 535 | |||
| 536 | if (ui->nvdec_emulation->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) { | ||
| 537 | Settings::values.nvdec_emulation.SetGlobal(true); | ||
| 538 | return Settings::values.nvdec_emulation.GetValue(); | ||
| 539 | } | ||
| 540 | Settings::values.nvdec_emulation.SetGlobal(false); | ||
| 541 | return static_cast<Settings::NvdecEmulation>(ui->nvdec_emulation->currentIndex() - | ||
| 542 | ConfigurationShared::USE_GLOBAL_OFFSET); | ||
| 543 | } | ||
| 544 | |||
| 545 | void ConfigureGraphics::SetupPerGameUI() { | ||
| 546 | if (Settings::IsConfiguringGlobal()) { | ||
| 547 | ui->api->setEnabled(Settings::values.renderer_backend.UsingGlobal()); | ||
| 548 | ui->device->setEnabled(Settings::values.renderer_backend.UsingGlobal()); | ||
| 549 | ui->fullscreen_mode_combobox->setEnabled(Settings::values.fullscreen_mode.UsingGlobal()); | ||
| 550 | ui->aspect_ratio_combobox->setEnabled(Settings::values.aspect_ratio.UsingGlobal()); | ||
| 551 | ui->resolution_combobox->setEnabled(Settings::values.resolution_setup.UsingGlobal()); | ||
| 552 | ui->scaling_filter_combobox->setEnabled(Settings::values.scaling_filter.UsingGlobal()); | ||
| 553 | ui->fsr_sharpening_slider->setEnabled(Settings::values.fsr_sharpening_slider.UsingGlobal()); | ||
| 554 | ui->anti_aliasing_combobox->setEnabled(Settings::values.anti_aliasing.UsingGlobal()); | ||
| 555 | ui->use_asynchronous_gpu_emulation->setEnabled( | ||
| 556 | Settings::values.use_asynchronous_gpu_emulation.UsingGlobal()); | ||
| 557 | ui->nvdec_emulation->setEnabled(Settings::values.nvdec_emulation.UsingGlobal()); | ||
| 558 | ui->accelerate_astc->setEnabled(Settings::values.accelerate_astc.UsingGlobal()); | ||
| 559 | ui->use_disk_shader_cache->setEnabled(Settings::values.use_disk_shader_cache.UsingGlobal()); | ||
| 560 | ui->bg_button->setEnabled(Settings::values.bg_red.UsingGlobal()); | ||
| 561 | ui->fsr_slider_layout->setEnabled(Settings::values.fsr_sharpening_slider.UsingGlobal()); | ||
| 562 | |||
| 563 | return; | ||
| 564 | } | ||
| 565 | |||
| 566 | connect(ui->bg_combobox, qOverload<int>(&QComboBox::activated), this, [this](int index) { | ||
| 567 | ui->bg_button->setEnabled(index == 1); | ||
| 568 | ConfigurationShared::SetHighlight(ui->bg_layout, index == 1); | ||
| 569 | }); | ||
| 570 | |||
| 571 | connect(ui->fsr_sharpening_combobox, qOverload<int>(&QComboBox::activated), this, | ||
| 572 | [this](int index) { | ||
| 573 | ui->fsr_sharpening_slider->setEnabled(index == 1); | ||
| 574 | ui->fsr_sharpening_value->setEnabled(index == 1); | ||
| 575 | ConfigurationShared::SetHighlight(ui->fsr_sharpening_layout, index == 1); | ||
| 576 | }); | ||
| 577 | |||
| 578 | ConfigurationShared::SetColoredTristate( | ||
| 579 | ui->use_disk_shader_cache, Settings::values.use_disk_shader_cache, use_disk_shader_cache); | ||
| 580 | ConfigurationShared::SetColoredTristate(ui->accelerate_astc, Settings::values.accelerate_astc, | ||
| 581 | accelerate_astc); | ||
| 582 | ConfigurationShared::SetColoredTristate(ui->use_asynchronous_gpu_emulation, | ||
| 583 | Settings::values.use_asynchronous_gpu_emulation, | ||
| 584 | use_asynchronous_gpu_emulation); | ||
| 585 | |||
| 586 | ConfigurationShared::SetColoredComboBox(ui->aspect_ratio_combobox, ui->ar_label, | ||
| 587 | Settings::values.aspect_ratio.GetValue(true)); | ||
| 588 | ConfigurationShared::SetColoredComboBox( | ||
| 589 | ui->fullscreen_mode_combobox, ui->fullscreen_mode_label, | ||
| 590 | static_cast<int>(Settings::values.fullscreen_mode.GetValue(true))); | ||
| 591 | ConfigurationShared::SetColoredComboBox( | ||
| 592 | ui->resolution_combobox, ui->resolution_label, | ||
| 593 | static_cast<int>(Settings::values.resolution_setup.GetValue(true))); | ||
| 594 | ConfigurationShared::SetColoredComboBox( | ||
| 595 | ui->scaling_filter_combobox, ui->scaling_filter_label, | ||
| 596 | static_cast<int>(Settings::values.scaling_filter.GetValue(true))); | ||
| 597 | ConfigurationShared::SetColoredComboBox( | ||
| 598 | ui->anti_aliasing_combobox, ui->anti_aliasing_label, | ||
| 599 | static_cast<int>(Settings::values.anti_aliasing.GetValue(true))); | ||
| 600 | ConfigurationShared::InsertGlobalItem( | ||
| 601 | ui->api, static_cast<int>(Settings::values.renderer_backend.GetValue(true))); | ||
| 602 | ConfigurationShared::InsertGlobalItem( | ||
| 603 | ui->nvdec_emulation, static_cast<int>(Settings::values.nvdec_emulation.GetValue(true))); | ||
| 604 | |||
| 605 | ui->vsync_mode_layout->setVisible(false); | ||
| 606 | } | 475 | } |
diff --git a/src/yuzu/configuration/configure_graphics.h b/src/yuzu/configuration/configure_graphics.h index be9310b74..02d9b00f1 100644 --- a/src/yuzu/configuration/configure_graphics.h +++ b/src/yuzu/configuration/configure_graphics.h | |||
| @@ -5,6 +5,8 @@ | |||
| 5 | 5 | ||
| 6 | #include <functional> | 6 | #include <functional> |
| 7 | #include <memory> | 7 | #include <memory> |
| 8 | #include <type_traits> | ||
| 9 | #include <typeindex> | ||
| 8 | #include <vector> | 10 | #include <vector> |
| 9 | #include <QColor> | 11 | #include <QColor> |
| 10 | #include <QString> | 12 | #include <QString> |
| @@ -12,10 +14,14 @@ | |||
| 12 | #include <qobjectdefs.h> | 14 | #include <qobjectdefs.h> |
| 13 | #include <vulkan/vulkan_core.h> | 15 | #include <vulkan/vulkan_core.h> |
| 14 | #include "common/common_types.h" | 16 | #include "common/common_types.h" |
| 17 | #include "configuration/shared_translation.h" | ||
| 15 | #include "vk_device_info.h" | 18 | #include "vk_device_info.h" |
| 19 | #include "yuzu/configuration/configuration_shared.h" | ||
| 16 | 20 | ||
| 21 | class QPushButton; | ||
| 17 | class QEvent; | 22 | class QEvent; |
| 18 | class QObject; | 23 | class QObject; |
| 24 | class QComboBox; | ||
| 19 | 25 | ||
| 20 | namespace Settings { | 26 | namespace Settings { |
| 21 | enum class NvdecEmulation : u32; | 27 | enum class NvdecEmulation : u32; |
| @@ -27,31 +33,33 @@ namespace Core { | |||
| 27 | class System; | 33 | class System; |
| 28 | } | 34 | } |
| 29 | 35 | ||
| 30 | namespace ConfigurationShared { | ||
| 31 | enum class CheckState; | ||
| 32 | } | ||
| 33 | |||
| 34 | namespace Ui { | 36 | namespace Ui { |
| 35 | class ConfigureGraphics; | 37 | class ConfigureGraphics; |
| 36 | } | 38 | } |
| 37 | 39 | ||
| 38 | class ConfigureGraphics : public QWidget { | 40 | namespace ConfigurationShared { |
| 39 | Q_OBJECT | 41 | class Builder; |
| 42 | } | ||
| 40 | 43 | ||
| 44 | class ConfigureGraphics : public ConfigurationShared::Tab { | ||
| 41 | public: | 45 | public: |
| 42 | explicit ConfigureGraphics(const Core::System& system_, | 46 | explicit ConfigureGraphics(const Core::System& system_, |
| 43 | std::vector<VkDeviceInfo::Record>& records, | 47 | std::vector<VkDeviceInfo::Record>& records, |
| 44 | const std::function<void()>& expose_compute_option_, | 48 | const std::function<void()>& expose_compute_option_, |
| 49 | std::shared_ptr<std::vector<ConfigurationShared::Tab*>> group, | ||
| 50 | const ConfigurationShared::Builder& builder, | ||
| 45 | QWidget* parent = nullptr); | 51 | QWidget* parent = nullptr); |
| 46 | ~ConfigureGraphics() override; | 52 | ~ConfigureGraphics() override; |
| 47 | 53 | ||
| 48 | void ApplyConfiguration(); | 54 | void ApplyConfiguration() override; |
| 49 | void SetConfiguration(); | 55 | void SetConfiguration() override; |
| 50 | 56 | ||
| 51 | private: | 57 | private: |
| 52 | void changeEvent(QEvent* event) override; | 58 | void changeEvent(QEvent* event) override; |
| 53 | void RetranslateUI(); | 59 | void RetranslateUI(); |
| 54 | 60 | ||
| 61 | void Setup(const ConfigurationShared::Builder& builder); | ||
| 62 | |||
| 55 | void PopulateVSyncModeSelection(); | 63 | void PopulateVSyncModeSelection(); |
| 56 | void UpdateBackgroundColorButton(QColor color); | 64 | void UpdateBackgroundColorButton(QColor color); |
| 57 | void UpdateAPILayout(); | 65 | void UpdateAPILayout(); |
| @@ -60,34 +68,40 @@ private: | |||
| 60 | 68 | ||
| 61 | void RetrieveVulkanDevices(); | 69 | void RetrieveVulkanDevices(); |
| 62 | 70 | ||
| 63 | void SetFSRIndicatorText(int percentage); | ||
| 64 | /* Turns a Vulkan present mode into a textual string for a UI | 71 | /* Turns a Vulkan present mode into a textual string for a UI |
| 65 | * (and eventually for a human to read) */ | 72 | * (and eventually for a human to read) */ |
| 66 | const QString TranslateVSyncMode(VkPresentModeKHR mode, | 73 | const QString TranslateVSyncMode(VkPresentModeKHR mode, |
| 67 | Settings::RendererBackend backend) const; | 74 | Settings::RendererBackend backend) const; |
| 68 | 75 | ||
| 69 | void SetupPerGameUI(); | ||
| 70 | |||
| 71 | Settings::RendererBackend GetCurrentGraphicsBackend() const; | 76 | Settings::RendererBackend GetCurrentGraphicsBackend() const; |
| 72 | Settings::NvdecEmulation GetCurrentNvdecEmulation() const; | 77 | |
| 78 | int FindIndex(u32 enumeration, int value) const; | ||
| 73 | 79 | ||
| 74 | std::unique_ptr<Ui::ConfigureGraphics> ui; | 80 | std::unique_ptr<Ui::ConfigureGraphics> ui; |
| 75 | QColor bg_color; | 81 | QColor bg_color; |
| 76 | 82 | ||
| 77 | ConfigurationShared::CheckState use_nvdec_emulation; | 83 | std::vector<std::function<void(bool)>> apply_funcs{}; |
| 78 | ConfigurationShared::CheckState accelerate_astc; | ||
| 79 | ConfigurationShared::CheckState use_disk_shader_cache; | ||
| 80 | ConfigurationShared::CheckState use_asynchronous_gpu_emulation; | ||
| 81 | 84 | ||
| 82 | std::vector<VkDeviceInfo::Record>& records; | 85 | std::vector<VkDeviceInfo::Record>& records; |
| 83 | std::vector<QString> vulkan_devices; | 86 | std::vector<QString> vulkan_devices; |
| 84 | std::vector<std::vector<VkPresentModeKHR>> device_present_modes; | 87 | std::vector<std::vector<VkPresentModeKHR>> device_present_modes; |
| 85 | std::vector<VkPresentModeKHR> | 88 | std::vector<VkPresentModeKHR> |
| 86 | vsync_mode_combobox_enum_map; //< Keeps track of which present mode corresponds to which | 89 | vsync_mode_combobox_enum_map{}; //< Keeps track of which present mode corresponds to which |
| 87 | // selection in the combobox | 90 | // selection in the combobox |
| 88 | u32 vulkan_device{}; | 91 | u32 vulkan_device{}; |
| 89 | Settings::ShaderBackend shader_backend{}; | 92 | Settings::ShaderBackend shader_backend{}; |
| 90 | const std::function<void()>& expose_compute_option; | 93 | const std::function<void()>& expose_compute_option; |
| 91 | 94 | ||
| 92 | const Core::System& system; | 95 | const Core::System& system; |
| 96 | const ConfigurationShared::ComboboxTranslationMap& combobox_translations; | ||
| 97 | const std::vector<std::pair<u32, QString>>& shader_mapping; | ||
| 98 | |||
| 99 | QPushButton* api_restore_global_button; | ||
| 100 | QComboBox* vulkan_device_combobox; | ||
| 101 | QComboBox* api_combobox; | ||
| 102 | QComboBox* shader_backend_combobox; | ||
| 103 | QComboBox* vsync_mode_combobox; | ||
| 104 | QWidget* vulkan_device_widget; | ||
| 105 | QWidget* api_widget; | ||
| 106 | QWidget* shader_backend_widget; | ||
| 93 | }; | 107 | }; |
diff --git a/src/yuzu/configuration/configure_graphics.ui b/src/yuzu/configuration/configure_graphics.ui index 39f70e406..d09415d70 100644 --- a/src/yuzu/configuration/configure_graphics.ui +++ b/src/yuzu/configuration/configure_graphics.ui | |||
| @@ -27,7 +27,7 @@ | |||
| 27 | <layout class="QVBoxLayout" name="verticalLayout_3"> | 27 | <layout class="QVBoxLayout" name="verticalLayout_3"> |
| 28 | <item> | 28 | <item> |
| 29 | <widget class="QWidget" name="api_widget" native="true"> | 29 | <widget class="QWidget" name="api_widget" native="true"> |
| 30 | <layout class="QGridLayout" name="gridLayout"> | 30 | <layout class="QHBoxLayout" name="horizontalLayout"> |
| 31 | <property name="leftMargin"> | 31 | <property name="leftMargin"> |
| 32 | <number>0</number> | 32 | <number>0</number> |
| 33 | </property> | 33 | </property> |
| @@ -40,115 +40,6 @@ | |||
| 40 | <property name="bottomMargin"> | 40 | <property name="bottomMargin"> |
| 41 | <number>0</number> | 41 | <number>0</number> |
| 42 | </property> | 42 | </property> |
| 43 | <property name="horizontalSpacing"> | ||
| 44 | <number>6</number> | ||
| 45 | </property> | ||
| 46 | <item row="4" column="0"> | ||
| 47 | <widget class="QWidget" name="backend_widget" native="true"> | ||
| 48 | <layout class="QHBoxLayout" name="backend_layout"> | ||
| 49 | <property name="leftMargin"> | ||
| 50 | <number>0</number> | ||
| 51 | </property> | ||
| 52 | <property name="topMargin"> | ||
| 53 | <number>0</number> | ||
| 54 | </property> | ||
| 55 | <property name="rightMargin"> | ||
| 56 | <number>0</number> | ||
| 57 | </property> | ||
| 58 | <property name="bottomMargin"> | ||
| 59 | <number>0</number> | ||
| 60 | </property> | ||
| 61 | <item> | ||
| 62 | <widget class="QLabel" name="backend_label"> | ||
| 63 | <property name="text"> | ||
| 64 | <string>Shader Backend:</string> | ||
| 65 | </property> | ||
| 66 | </widget> | ||
| 67 | </item> | ||
| 68 | <item> | ||
| 69 | <widget class="QComboBox" name="backend"/> | ||
| 70 | </item> | ||
| 71 | </layout> | ||
| 72 | </widget> | ||
| 73 | </item> | ||
| 74 | <item row="2" column="0"> | ||
| 75 | <widget class="QWidget" name="device_widget" native="true"> | ||
| 76 | <layout class="QHBoxLayout" name="device_layout"> | ||
| 77 | <property name="leftMargin"> | ||
| 78 | <number>0</number> | ||
| 79 | </property> | ||
| 80 | <property name="topMargin"> | ||
| 81 | <number>0</number> | ||
| 82 | </property> | ||
| 83 | <property name="rightMargin"> | ||
| 84 | <number>0</number> | ||
| 85 | </property> | ||
| 86 | <property name="bottomMargin"> | ||
| 87 | <number>0</number> | ||
| 88 | </property> | ||
| 89 | <item> | ||
| 90 | <widget class="QLabel" name="device_label"> | ||
| 91 | <property name="text"> | ||
| 92 | <string>Device:</string> | ||
| 93 | </property> | ||
| 94 | </widget> | ||
| 95 | </item> | ||
| 96 | <item> | ||
| 97 | <widget class="QComboBox" name="device"/> | ||
| 98 | </item> | ||
| 99 | </layout> | ||
| 100 | </widget> | ||
| 101 | </item> | ||
| 102 | <item row="0" column="0"> | ||
| 103 | <widget class="QWidget" name="api_layout_2" native="true"> | ||
| 104 | <layout class="QHBoxLayout" name="api_layout"> | ||
| 105 | <property name="leftMargin"> | ||
| 106 | <number>0</number> | ||
| 107 | </property> | ||
| 108 | <property name="topMargin"> | ||
| 109 | <number>0</number> | ||
| 110 | </property> | ||
| 111 | <property name="rightMargin"> | ||
| 112 | <number>0</number> | ||
| 113 | </property> | ||
| 114 | <property name="bottomMargin"> | ||
| 115 | <number>0</number> | ||
| 116 | </property> | ||
| 117 | <item> | ||
| 118 | <widget class="QLabel" name="api_label"> | ||
| 119 | <property name="text"> | ||
| 120 | <string>API:</string> | ||
| 121 | </property> | ||
| 122 | </widget> | ||
| 123 | </item> | ||
| 124 | <item> | ||
| 125 | <widget class="QComboBox" name="api"> | ||
| 126 | <property name="sizePolicy"> | ||
| 127 | <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> | ||
| 128 | <horstretch>0</horstretch> | ||
| 129 | <verstretch>0</verstretch> | ||
| 130 | </sizepolicy> | ||
| 131 | </property> | ||
| 132 | <item> | ||
| 133 | <property name="text"> | ||
| 134 | <string notr="true">OpenGL</string> | ||
| 135 | </property> | ||
| 136 | </item> | ||
| 137 | <item> | ||
| 138 | <property name="text"> | ||
| 139 | <string notr="true">Vulkan</string> | ||
| 140 | </property> | ||
| 141 | </item> | ||
| 142 | <item> | ||
| 143 | <property name="text"> | ||
| 144 | <string>None</string> | ||
| 145 | </property> | ||
| 146 | </item> | ||
| 147 | </widget> | ||
| 148 | </item> | ||
| 149 | </layout> | ||
| 150 | </widget> | ||
| 151 | </item> | ||
| 152 | </layout> | 43 | </layout> |
| 153 | </widget> | 44 | </widget> |
| 154 | </item> | 45 | </item> |
| @@ -168,111 +59,8 @@ | |||
| 168 | </property> | 59 | </property> |
| 169 | <layout class="QVBoxLayout" name="verticalLayout_4"> | 60 | <layout class="QVBoxLayout" name="verticalLayout_4"> |
| 170 | <item> | 61 | <item> |
| 171 | <widget class="QCheckBox" name="use_disk_shader_cache"> | 62 | <widget class="QWidget" name="graphics_widget" native="true"> |
| 172 | <property name="text"> | 63 | <layout class="QVBoxLayout" name="verticalLayout"> |
| 173 | <string>Use disk pipeline cache</string> | ||
| 174 | </property> | ||
| 175 | </widget> | ||
| 176 | </item> | ||
| 177 | <item> | ||
| 178 | <widget class="QCheckBox" name="use_asynchronous_gpu_emulation"> | ||
| 179 | <property name="text"> | ||
| 180 | <string>Use asynchronous GPU emulation</string> | ||
| 181 | </property> | ||
| 182 | </widget> | ||
| 183 | </item> | ||
| 184 | <item> | ||
| 185 | <widget class="QCheckBox" name="accelerate_astc"> | ||
| 186 | <property name="text"> | ||
| 187 | <string>Accelerate ASTC texture decoding</string> | ||
| 188 | </property> | ||
| 189 | </widget> | ||
| 190 | </item> | ||
| 191 | <item> | ||
| 192 | <widget class="QWidget" name="vsync_mode_layout" native="true"> | ||
| 193 | <layout class="QHBoxLayout" name="horizontalLayout_4"> | ||
| 194 | <property name="leftMargin"> | ||
| 195 | <number>0</number> | ||
| 196 | </property> | ||
| 197 | <property name="topMargin"> | ||
| 198 | <number>0</number> | ||
| 199 | </property> | ||
| 200 | <property name="rightMargin"> | ||
| 201 | <number>0</number> | ||
| 202 | </property> | ||
| 203 | <property name="bottomMargin"> | ||
| 204 | <number>0</number> | ||
| 205 | </property> | ||
| 206 | <item> | ||
| 207 | <widget class="QLabel" name="vsync_mode_label"> | ||
| 208 | <property name="text"> | ||
| 209 | <string>VSync Mode:</string> | ||
| 210 | </property> | ||
| 211 | </widget> | ||
| 212 | </item> | ||
| 213 | <item> | ||
| 214 | <widget class="QComboBox" name="vsync_mode_combobox"> | ||
| 215 | <property name="toolTip"> | ||
| 216 | <string>FIFO (VSync) does not drop frames or exhibit tearing but is limited by the screen refresh rate. | ||
| 217 | FIFO Relaxed is similar to FIFO but allows tearing as it recovers from a slow down. | ||
| 218 | Mailbox can have lower latency than FIFO and does not tear but may drop frames. | ||
| 219 | Immediate (no synchronization) just presents whatever is available and can exhibit tearing.</string> | ||
| 220 | </property> | ||
| 221 | <property name="currentText"> | ||
| 222 | <string/> | ||
| 223 | </property> | ||
| 224 | </widget> | ||
| 225 | </item> | ||
| 226 | </layout> | ||
| 227 | </widget> | ||
| 228 | </item> | ||
| 229 | <item> | ||
| 230 | <widget class="QWidget" name="nvdec_emulation_widget" native="true"> | ||
| 231 | <layout class="QHBoxLayout" name="nvdec_emulation_layout"> | ||
| 232 | <property name="leftMargin"> | ||
| 233 | <number>0</number> | ||
| 234 | </property> | ||
| 235 | <property name="topMargin"> | ||
| 236 | <number>0</number> | ||
| 237 | </property> | ||
| 238 | <property name="rightMargin"> | ||
| 239 | <number>0</number> | ||
| 240 | </property> | ||
| 241 | <property name="bottomMargin"> | ||
| 242 | <number>0</number> | ||
| 243 | </property> | ||
| 244 | <item> | ||
| 245 | <widget class="QLabel" name="nvdec_emulation_label"> | ||
| 246 | <property name="text"> | ||
| 247 | <string>NVDEC emulation:</string> | ||
| 248 | </property> | ||
| 249 | </widget> | ||
| 250 | </item> | ||
| 251 | <item> | ||
| 252 | <widget class="QComboBox" name="nvdec_emulation"> | ||
| 253 | <item> | ||
| 254 | <property name="text"> | ||
| 255 | <string>No Video Output</string> | ||
| 256 | </property> | ||
| 257 | </item> | ||
| 258 | <item> | ||
| 259 | <property name="text"> | ||
| 260 | <string>CPU Video Decoding</string> | ||
| 261 | </property> | ||
| 262 | </item> | ||
| 263 | <item> | ||
| 264 | <property name="text"> | ||
| 265 | <string>GPU Video Decoding (Default)</string> | ||
| 266 | </property> | ||
| 267 | </item> | ||
| 268 | </widget> | ||
| 269 | </item> | ||
| 270 | </layout> | ||
| 271 | </widget> | ||
| 272 | </item> | ||
| 273 | <item> | ||
| 274 | <widget class="QWidget" name="fullscreen_mode_layout" native="true"> | ||
| 275 | <layout class="QHBoxLayout" name="horizontalLayout_1"> | ||
| 276 | <property name="leftMargin"> | 64 | <property name="leftMargin"> |
| 277 | <number>0</number> | 65 | <number>0</number> |
| 278 | </property> | 66 | </property> |
| @@ -285,33 +73,12 @@ Immediate (no synchronization) just presents whatever is available and can exhib | |||
| 285 | <property name="bottomMargin"> | 73 | <property name="bottomMargin"> |
| 286 | <number>0</number> | 74 | <number>0</number> |
| 287 | </property> | 75 | </property> |
| 288 | <item> | ||
| 289 | <widget class="QLabel" name="fullscreen_mode_label"> | ||
| 290 | <property name="text"> | ||
| 291 | <string>Fullscreen Mode:</string> | ||
| 292 | </property> | ||
| 293 | </widget> | ||
| 294 | </item> | ||
| 295 | <item> | ||
| 296 | <widget class="QComboBox" name="fullscreen_mode_combobox"> | ||
| 297 | <item> | ||
| 298 | <property name="text"> | ||
| 299 | <string>Borderless Windowed</string> | ||
| 300 | </property> | ||
| 301 | </item> | ||
| 302 | <item> | ||
| 303 | <property name="text"> | ||
| 304 | <string>Exclusive Fullscreen</string> | ||
| 305 | </property> | ||
| 306 | </item> | ||
| 307 | </widget> | ||
| 308 | </item> | ||
| 309 | </layout> | 76 | </layout> |
| 310 | </widget> | 77 | </widget> |
| 311 | </item> | 78 | </item> |
| 312 | <item> | 79 | <item> |
| 313 | <widget class="QWidget" name="aspect_ratio_layout" native="true"> | 80 | <widget class="QWidget" name="bg_widget" native="true"> |
| 314 | <layout class="QHBoxLayout" name="horizontalLayout_2"> | 81 | <layout class="QHBoxLayout" name="bg_layout"> |
| 315 | <property name="leftMargin"> | 82 | <property name="leftMargin"> |
| 316 | <number>0</number> | 83 | <number>0</number> |
| 317 | </property> | 84 | </property> |
| @@ -325,452 +92,35 @@ Immediate (no synchronization) just presents whatever is available and can exhib | |||
| 325 | <number>0</number> | 92 | <number>0</number> |
| 326 | </property> | 93 | </property> |
| 327 | <item> | 94 | <item> |
| 328 | <widget class="QLabel" name="ar_label"> | 95 | <widget class="QLabel" name="label"> |
| 329 | <property name="text"> | 96 | <property name="sizePolicy"> |
| 330 | <string>Aspect Ratio:</string> | 97 | <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> |
| 98 | <horstretch>0</horstretch> | ||
| 99 | <verstretch>0</verstretch> | ||
| 100 | </sizepolicy> | ||
| 331 | </property> | 101 | </property> |
| 332 | </widget> | ||
| 333 | </item> | ||
| 334 | <item> | ||
| 335 | <widget class="QComboBox" name="aspect_ratio_combobox"> | ||
| 336 | <item> | ||
| 337 | <property name="text"> | ||
| 338 | <string>Default (16:9)</string> | ||
| 339 | </property> | ||
| 340 | </item> | ||
| 341 | <item> | ||
| 342 | <property name="text"> | ||
| 343 | <string>Force 4:3</string> | ||
| 344 | </property> | ||
| 345 | </item> | ||
| 346 | <item> | ||
| 347 | <property name="text"> | ||
| 348 | <string>Force 21:9</string> | ||
| 349 | </property> | ||
| 350 | </item> | ||
| 351 | <item> | ||
| 352 | <property name="text"> | ||
| 353 | <string>Force 16:10</string> | ||
| 354 | </property> | ||
| 355 | </item> | ||
| 356 | <item> | ||
| 357 | <property name="text"> | ||
| 358 | <string>Stretch to Window</string> | ||
| 359 | </property> | ||
| 360 | </item> | ||
| 361 | </widget> | ||
| 362 | </item> | ||
| 363 | </layout> | ||
| 364 | </widget> | ||
| 365 | </item> | ||
| 366 | <item> | ||
| 367 | <widget class="QWidget" name="resolution_layout" native="true"> | ||
| 368 | <layout class="QHBoxLayout" name="horizontalLayout_5"> | ||
| 369 | <property name="leftMargin"> | ||
| 370 | <number>0</number> | ||
| 371 | </property> | ||
| 372 | <property name="topMargin"> | ||
| 373 | <number>0</number> | ||
| 374 | </property> | ||
| 375 | <property name="rightMargin"> | ||
| 376 | <number>0</number> | ||
| 377 | </property> | ||
| 378 | <property name="bottomMargin"> | ||
| 379 | <number>0</number> | ||
| 380 | </property> | ||
| 381 | <item> | ||
| 382 | <widget class="QLabel" name="resolution_label"> | ||
| 383 | <property name="text"> | ||
| 384 | <string>Resolution:</string> | ||
| 385 | </property> | ||
| 386 | </widget> | ||
| 387 | </item> | ||
| 388 | <item> | ||
| 389 | <widget class="QComboBox" name="resolution_combobox"> | ||
| 390 | <item> | ||
| 391 | <property name="text"> | ||
| 392 | <string>0.5X (360p/540p) [EXPERIMENTAL]</string> | ||
| 393 | </property> | ||
| 394 | </item> | ||
| 395 | <item> | ||
| 396 | <property name="text"> | ||
| 397 | <string>0.75X (540p/810p) [EXPERIMENTAL]</string> | ||
| 398 | </property> | ||
| 399 | </item> | ||
| 400 | <item> | ||
| 401 | <property name="text"> | ||
| 402 | <string>1X (720p/1080p)</string> | ||
| 403 | </property> | ||
| 404 | </item> | ||
| 405 | <item> | ||
| 406 | <property name="text"> | ||
| 407 | <string>1.5X (1080p/1620p) [EXPERIMENTAL]</string> | ||
| 408 | </property> | ||
| 409 | </item> | ||
| 410 | <item> | ||
| 411 | <property name="text"> | ||
| 412 | <string>2X (1440p/2160p)</string> | ||
| 413 | </property> | ||
| 414 | </item> | ||
| 415 | <item> | ||
| 416 | <property name="text"> | ||
| 417 | <string>3X (2160p/3240p)</string> | ||
| 418 | </property> | ||
| 419 | </item> | ||
| 420 | <item> | ||
| 421 | <property name="text"> | ||
| 422 | <string>4X (2880p/4320p)</string> | ||
| 423 | </property> | ||
| 424 | </item> | ||
| 425 | <item> | ||
| 426 | <property name="text"> | ||
| 427 | <string>5X (3600p/5400p)</string> | ||
| 428 | </property> | ||
| 429 | </item> | ||
| 430 | <item> | ||
| 431 | <property name="text"> | ||
| 432 | <string>6X (4320p/6480p)</string> | ||
| 433 | </property> | ||
| 434 | </item> | ||
| 435 | <item> | ||
| 436 | <property name="text"> | ||
| 437 | <string>7X (5040p/7560p)</string> | ||
| 438 | </property> | ||
| 439 | </item> | ||
| 440 | <item> | ||
| 441 | <property name="text"> | ||
| 442 | <string>8X (5760p/8640p)</string> | ||
| 443 | </property> | ||
| 444 | </item> | ||
| 445 | </widget> | ||
| 446 | </item> | ||
| 447 | </layout> | ||
| 448 | </widget> | ||
| 449 | </item> | ||
| 450 | <item> | ||
| 451 | <widget class="QWidget" name="scaling_filter_layout" native="true"> | ||
| 452 | <layout class="QHBoxLayout" name="horizontalLayout_6"> | ||
| 453 | <property name="leftMargin"> | ||
| 454 | <number>0</number> | ||
| 455 | </property> | ||
| 456 | <property name="topMargin"> | ||
| 457 | <number>0</number> | ||
| 458 | </property> | ||
| 459 | <property name="rightMargin"> | ||
| 460 | <number>0</number> | ||
| 461 | </property> | ||
| 462 | <property name="bottomMargin"> | ||
| 463 | <number>0</number> | ||
| 464 | </property> | ||
| 465 | <item> | ||
| 466 | <widget class="QLabel" name="scaling_filter_label"> | ||
| 467 | <property name="text"> | ||
| 468 | <string>Window Adapting Filter:</string> | ||
| 469 | </property> | ||
| 470 | </widget> | ||
| 471 | </item> | ||
| 472 | <item> | ||
| 473 | <widget class="QComboBox" name="scaling_filter_combobox"> | ||
| 474 | <item> | ||
| 475 | <property name="text"> | ||
| 476 | <string>Nearest Neighbor</string> | ||
| 477 | </property> | ||
| 478 | </item> | ||
| 479 | <item> | ||
| 480 | <property name="text"> | ||
| 481 | <string>Bilinear</string> | ||
| 482 | </property> | ||
| 483 | </item> | ||
| 484 | <item> | ||
| 485 | <property name="text"> | ||
| 486 | <string>Bicubic</string> | ||
| 487 | </property> | ||
| 488 | </item> | ||
| 489 | <item> | ||
| 490 | <property name="text"> | ||
| 491 | <string>Gaussian</string> | ||
| 492 | </property> | ||
| 493 | </item> | ||
| 494 | <item> | ||
| 495 | <property name="text"> | ||
| 496 | <string>ScaleForce</string> | ||
| 497 | </property> | ||
| 498 | </item> | ||
| 499 | <item> | ||
| 500 | <property name="text"> | ||
| 501 | <string>AMD FidelityFX™️ Super Resolution</string> | ||
| 502 | </property> | ||
| 503 | </item> | ||
| 504 | </widget> | ||
| 505 | </item> | ||
| 506 | </layout> | ||
| 507 | </widget> | ||
| 508 | </item> | ||
| 509 | <item> | ||
| 510 | <widget class="QWidget" name="anti_aliasing_layout" native="true"> | ||
| 511 | <layout class="QHBoxLayout" name="horizontalLayout_7"> | ||
| 512 | <property name="leftMargin"> | ||
| 513 | <number>0</number> | ||
| 514 | </property> | ||
| 515 | <property name="topMargin"> | ||
| 516 | <number>0</number> | ||
| 517 | </property> | ||
| 518 | <property name="rightMargin"> | ||
| 519 | <number>0</number> | ||
| 520 | </property> | ||
| 521 | <property name="bottomMargin"> | ||
| 522 | <number>0</number> | ||
| 523 | </property> | ||
| 524 | <item> | ||
| 525 | <widget class="QLabel" name="anti_aliasing_label"> | ||
| 526 | <property name="text"> | ||
| 527 | <string>Anti-Aliasing Method:</string> | ||
| 528 | </property> | ||
| 529 | </widget> | ||
| 530 | </item> | ||
| 531 | <item> | ||
| 532 | <widget class="QComboBox" name="anti_aliasing_combobox"> | ||
| 533 | <item> | ||
| 534 | <property name="text"> | ||
| 535 | <string>None</string> | ||
| 536 | </property> | ||
| 537 | </item> | ||
| 538 | <item> | ||
| 539 | <property name="text"> | ||
| 540 | <string>FXAA</string> | ||
| 541 | </property> | ||
| 542 | </item> | ||
| 543 | <item> | ||
| 544 | <property name="text"> | ||
| 545 | <string>SMAA</string> | ||
| 546 | </property> | ||
| 547 | </item> | ||
| 548 | </widget> | ||
| 549 | </item> | ||
| 550 | </layout> | ||
| 551 | </widget> | ||
| 552 | </item> | ||
| 553 | <item> | ||
| 554 | <widget class="QWidget" name="fsr_sharpening_layout" native="true"> | ||
| 555 | <property name="enabled"> | ||
| 556 | <bool>true</bool> | ||
| 557 | </property> | ||
| 558 | <property name="sizePolicy"> | ||
| 559 | <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> | ||
| 560 | <horstretch>0</horstretch> | ||
| 561 | <verstretch>0</verstretch> | ||
| 562 | </sizepolicy> | ||
| 563 | </property> | ||
| 564 | <layout class="QHBoxLayout" name="horizontalLayout"> | ||
| 565 | <property name="spacing"> | ||
| 566 | <number>6</number> | ||
| 567 | </property> | ||
| 568 | <property name="sizeConstraint"> | ||
| 569 | <enum>QLayout::SetDefaultConstraint</enum> | ||
| 570 | </property> | ||
| 571 | <property name="leftMargin"> | ||
| 572 | <number>0</number> | ||
| 573 | </property> | ||
| 574 | <property name="topMargin"> | ||
| 575 | <number>0</number> | ||
| 576 | </property> | ||
| 577 | <property name="rightMargin"> | ||
| 578 | <number>0</number> | ||
| 579 | </property> | ||
| 580 | <property name="bottomMargin"> | ||
| 581 | <number>0</number> | ||
| 582 | </property> | ||
| 583 | <item> | ||
| 584 | <layout class="QHBoxLayout" name="fsr_sharpening_label_group"> | ||
| 585 | <property name="rightMargin"> | ||
| 586 | <number>0</number> | ||
| 587 | </property> | ||
| 588 | <property name="bottomMargin"> | ||
| 589 | <number>0</number> | ||
| 590 | </property> | ||
| 591 | <item> | ||
| 592 | <widget class="QComboBox" name="fsr_sharpening_combobox"> | ||
| 593 | <property name="sizePolicy"> | ||
| 594 | <sizepolicy hsizetype="Maximum" vsizetype="Fixed"> | ||
| 595 | <horstretch>0</horstretch> | ||
| 596 | <verstretch>0</verstretch> | ||
| 597 | </sizepolicy> | ||
| 598 | </property> | ||
| 599 | <item> | ||
| 600 | <property name="text"> | ||
| 601 | <string>Use global FSR Sharpness</string> | ||
| 602 | </property> | ||
| 603 | </item> | ||
| 604 | <item> | ||
| 605 | <property name="text"> | ||
| 606 | <string>Set FSR Sharpness</string> | ||
| 607 | </property> | ||
| 608 | </item> | ||
| 609 | </widget> | ||
| 610 | </item> | ||
| 611 | <item> | ||
| 612 | <widget class="QLabel" name="fsr_sharpening_label"> | ||
| 613 | <property name="sizePolicy"> | ||
| 614 | <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> | ||
| 615 | <horstretch>0</horstretch> | ||
| 616 | <verstretch>0</verstretch> | ||
| 617 | </sizepolicy> | ||
| 618 | </property> | ||
| 619 | <property name="text"> | ||
| 620 | <string>FSR Sharpness:</string> | ||
| 621 | </property> | ||
| 622 | </widget> | ||
| 623 | </item> | ||
| 624 | <item> | ||
| 625 | <spacer name="horizontalSpacer_2"> | ||
| 626 | <property name="orientation"> | ||
| 627 | <enum>Qt::Horizontal</enum> | ||
| 628 | </property> | ||
| 629 | <property name="sizeHint" stdset="0"> | ||
| 630 | <size> | ||
| 631 | <width>40</width> | ||
| 632 | <height>20</height> | ||
| 633 | </size> | ||
| 634 | </property> | ||
| 635 | </spacer> | ||
| 636 | </item> | ||
| 637 | </layout> | ||
| 638 | </item> | ||
| 639 | <item> | ||
| 640 | <layout class="QHBoxLayout" name="fsr_slider_layout"> | ||
| 641 | <property name="spacing"> | ||
| 642 | <number>6</number> | ||
| 643 | </property> | ||
| 644 | <item> | ||
| 645 | <widget class="QSlider" name="fsr_sharpening_slider"> | ||
| 646 | <property name="sizePolicy"> | ||
| 647 | <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred"> | ||
| 648 | <horstretch>0</horstretch> | ||
| 649 | <verstretch>0</verstretch> | ||
| 650 | </sizepolicy> | ||
| 651 | </property> | ||
| 652 | <property name="baseSize"> | ||
| 653 | <size> | ||
| 654 | <width>0</width> | ||
| 655 | <height>0</height> | ||
| 656 | </size> | ||
| 657 | </property> | ||
| 658 | <property name="maximum"> | ||
| 659 | <number>200</number> | ||
| 660 | </property> | ||
| 661 | <property name="sliderPosition"> | ||
| 662 | <number>25</number> | ||
| 663 | </property> | ||
| 664 | <property name="orientation"> | ||
| 665 | <enum>Qt::Horizontal</enum> | ||
| 666 | </property> | ||
| 667 | <property name="invertedAppearance"> | ||
| 668 | <bool>true</bool> | ||
| 669 | </property> | ||
| 670 | </widget> | ||
| 671 | </item> | ||
| 672 | <item> | ||
| 673 | <widget class="QLabel" name="fsr_sharpening_value"> | ||
| 674 | <property name="sizePolicy"> | ||
| 675 | <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> | ||
| 676 | <horstretch>0</horstretch> | ||
| 677 | <verstretch>0</verstretch> | ||
| 678 | </sizepolicy> | ||
| 679 | </property> | ||
| 680 | <property name="minimumSize"> | ||
| 681 | <size> | ||
| 682 | <width>32</width> | ||
| 683 | <height>0</height> | ||
| 684 | </size> | ||
| 685 | </property> | ||
| 686 | <property name="text"> | ||
| 687 | <string>100%</string> | ||
| 688 | </property> | ||
| 689 | <property name="alignment"> | ||
| 690 | <set>Qt::AlignCenter</set> | ||
| 691 | </property> | ||
| 692 | </widget> | ||
| 693 | </item> | ||
| 694 | </layout> | ||
| 695 | </item> | ||
| 696 | </layout> | ||
| 697 | </widget> | ||
| 698 | </item> | ||
| 699 | <item> | ||
| 700 | <widget class="QWidget" name="bg_layout" native="true"> | ||
| 701 | <property name="sizePolicy"> | ||
| 702 | <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> | ||
| 703 | <horstretch>0</horstretch> | ||
| 704 | <verstretch>0</verstretch> | ||
| 705 | </sizepolicy> | ||
| 706 | </property> | ||
| 707 | <layout class="QHBoxLayout" name="horizontalLayout_3"> | ||
| 708 | <property name="spacing"> | ||
| 709 | <number>6</number> | ||
| 710 | </property> | ||
| 711 | <property name="leftMargin"> | ||
| 712 | <number>0</number> | ||
| 713 | </property> | ||
| 714 | <property name="topMargin"> | ||
| 715 | <number>0</number> | ||
| 716 | </property> | ||
| 717 | <property name="rightMargin"> | ||
| 718 | <number>0</number> | ||
| 719 | </property> | ||
| 720 | <property name="bottomMargin"> | ||
| 721 | <number>0</number> | ||
| 722 | </property> | ||
| 723 | <item> | ||
| 724 | <widget class="QComboBox" name="bg_combobox"> | ||
| 725 | <property name="currentText"> | ||
| 726 | <string>Use global background color</string> | ||
| 727 | </property> | ||
| 728 | <property name="currentIndex"> | ||
| 729 | <number>0</number> | ||
| 730 | </property> | ||
| 731 | <property name="maxVisibleItems"> | ||
| 732 | <number>10</number> | ||
| 733 | </property> | ||
| 734 | <item> | ||
| 735 | <property name="text"> | ||
| 736 | <string>Use global background color</string> | ||
| 737 | </property> | ||
| 738 | </item> | ||
| 739 | <item> | ||
| 740 | <property name="text"> | ||
| 741 | <string>Set background color:</string> | ||
| 742 | </property> | ||
| 743 | </item> | ||
| 744 | </widget> | ||
| 745 | </item> | ||
| 746 | <item> | ||
| 747 | <widget class="QLabel" name="bg_label"> | ||
| 748 | <property name="text"> | 102 | <property name="text"> |
| 749 | <string>Background Color:</string> | 103 | <string>Background Color:</string> |
| 750 | </property> | 104 | </property> |
| 751 | </widget> | 105 | </widget> |
| 752 | </item> | 106 | </item> |
| 753 | <item> | 107 | <item> |
| 754 | <spacer name="horizontalSpacer"> | ||
| 755 | <property name="orientation"> | ||
| 756 | <enum>Qt::Horizontal</enum> | ||
| 757 | </property> | ||
| 758 | <property name="sizeHint" stdset="0"> | ||
| 759 | <size> | ||
| 760 | <width>40</width> | ||
| 761 | <height>20</height> | ||
| 762 | </size> | ||
| 763 | </property> | ||
| 764 | </spacer> | ||
| 765 | </item> | ||
| 766 | <item> | ||
| 767 | <widget class="QPushButton" name="bg_button"> | 108 | <widget class="QPushButton" name="bg_button"> |
| 109 | <property name="sizePolicy"> | ||
| 110 | <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> | ||
| 111 | <horstretch>0</horstretch> | ||
| 112 | <verstretch>0</verstretch> | ||
| 113 | </sizepolicy> | ||
| 114 | </property> | ||
| 768 | <property name="maximumSize"> | 115 | <property name="maximumSize"> |
| 769 | <size> | 116 | <size> |
| 770 | <width>40</width> | 117 | <width>40</width> |
| 771 | <height>16777215</height> | 118 | <height>16777215</height> |
| 772 | </size> | 119 | </size> |
| 773 | </property> | 120 | </property> |
| 121 | <property name="text"> | ||
| 122 | <string/> | ||
| 123 | </property> | ||
| 774 | </widget> | 124 | </widget> |
| 775 | </item> | 125 | </item> |
| 776 | </layout> | 126 | </layout> |
diff --git a/src/yuzu/configuration/configure_graphics_advanced.cpp b/src/yuzu/configuration/configure_graphics_advanced.cpp index c0a044767..4db18673d 100644 --- a/src/yuzu/configuration/configure_graphics_advanced.cpp +++ b/src/yuzu/configuration/configure_graphics_advanced.cpp | |||
| @@ -1,104 +1,68 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include <vector> | ||
| 5 | #include <QLabel> | ||
| 6 | #include <qnamespace.h> | ||
| 4 | #include "common/settings.h" | 7 | #include "common/settings.h" |
| 5 | #include "core/core.h" | 8 | #include "core/core.h" |
| 6 | #include "ui_configure_graphics_advanced.h" | 9 | #include "ui_configure_graphics_advanced.h" |
| 7 | #include "yuzu/configuration/configuration_shared.h" | 10 | #include "yuzu/configuration/configuration_shared.h" |
| 8 | #include "yuzu/configuration/configure_graphics_advanced.h" | 11 | #include "yuzu/configuration/configure_graphics_advanced.h" |
| 12 | #include "yuzu/configuration/shared_translation.h" | ||
| 13 | #include "yuzu/configuration/shared_widget.h" | ||
| 9 | 14 | ||
| 10 | ConfigureGraphicsAdvanced::ConfigureGraphicsAdvanced(const Core::System& system_, QWidget* parent) | 15 | ConfigureGraphicsAdvanced::ConfigureGraphicsAdvanced( |
| 11 | : QWidget(parent), ui{std::make_unique<Ui::ConfigureGraphicsAdvanced>()}, system{system_} { | 16 | const Core::System& system_, std::shared_ptr<std::vector<ConfigurationShared::Tab*>> group_, |
| 17 | const ConfigurationShared::Builder& builder, QWidget* parent) | ||
| 18 | : Tab(group_, parent), ui{std::make_unique<Ui::ConfigureGraphicsAdvanced>()}, system{system_} { | ||
| 12 | 19 | ||
| 13 | ui->setupUi(this); | 20 | ui->setupUi(this); |
| 14 | 21 | ||
| 15 | SetupPerGameUI(); | 22 | Setup(builder); |
| 16 | 23 | ||
| 17 | SetConfiguration(); | 24 | SetConfiguration(); |
| 18 | 25 | ||
| 19 | ui->enable_compute_pipelines_checkbox->setVisible(false); | 26 | checkbox_enable_compute_pipelines->setVisible(false); |
| 20 | } | 27 | } |
| 21 | 28 | ||
| 22 | ConfigureGraphicsAdvanced::~ConfigureGraphicsAdvanced() = default; | 29 | ConfigureGraphicsAdvanced::~ConfigureGraphicsAdvanced() = default; |
| 23 | 30 | ||
| 24 | void ConfigureGraphicsAdvanced::SetConfiguration() { | 31 | void ConfigureGraphicsAdvanced::SetConfiguration() {} |
| 25 | const bool runtime_lock = !system.IsPoweredOn(); | 32 | |
| 26 | ui->use_reactive_flushing->setEnabled(runtime_lock); | 33 | void ConfigureGraphicsAdvanced::Setup(const ConfigurationShared::Builder& builder) { |
| 27 | ui->async_present->setEnabled(runtime_lock); | 34 | auto& layout = *ui->populate_target->layout(); |
| 28 | ui->renderer_force_max_clock->setEnabled(runtime_lock); | 35 | std::map<u32, QWidget*> hold{}; // A map will sort the data for us |
| 29 | ui->async_astc->setEnabled(runtime_lock); | 36 | |
| 30 | ui->astc_recompression_combobox->setEnabled(runtime_lock); | 37 | for (auto setting : |
| 31 | ui->use_asynchronous_shaders->setEnabled(runtime_lock); | 38 | Settings::values.linkage.by_category[Settings::Category::RendererAdvanced]) { |
| 32 | ui->anisotropic_filtering_combobox->setEnabled(runtime_lock); | 39 | ConfigurationShared::Widget* widget = builder.BuildWidget(setting, apply_funcs); |
| 33 | ui->enable_compute_pipelines_checkbox->setEnabled(runtime_lock); | 40 | |
| 34 | 41 | if (widget == nullptr) { | |
| 35 | ui->async_present->setChecked(Settings::values.async_presentation.GetValue()); | 42 | continue; |
| 36 | ui->renderer_force_max_clock->setChecked(Settings::values.renderer_force_max_clock.GetValue()); | 43 | } |
| 37 | ui->use_reactive_flushing->setChecked(Settings::values.use_reactive_flushing.GetValue()); | 44 | if (!widget->Valid()) { |
| 38 | ui->async_astc->setChecked(Settings::values.async_astc.GetValue()); | 45 | widget->deleteLater(); |
| 39 | ui->use_asynchronous_shaders->setChecked(Settings::values.use_asynchronous_shaders.GetValue()); | 46 | continue; |
| 40 | ui->use_fast_gpu_time->setChecked(Settings::values.use_fast_gpu_time.GetValue()); | 47 | } |
| 41 | ui->use_vulkan_driver_pipeline_cache->setChecked( | 48 | |
| 42 | Settings::values.use_vulkan_driver_pipeline_cache.GetValue()); | 49 | hold.emplace(setting->Id(), widget); |
| 43 | ui->enable_compute_pipelines_checkbox->setChecked( | 50 | |
| 44 | Settings::values.enable_compute_pipelines.GetValue()); | 51 | // Keep track of enable_compute_pipelines so we can display it when needed |
| 45 | ui->use_video_framerate_checkbox->setChecked(Settings::values.use_video_framerate.GetValue()); | 52 | if (setting->Id() == Settings::values.enable_compute_pipelines.Id()) { |
| 46 | ui->barrier_feedback_loops_checkbox->setChecked( | 53 | checkbox_enable_compute_pipelines = widget; |
| 47 | Settings::values.barrier_feedback_loops.GetValue()); | 54 | } |
| 48 | 55 | } | |
| 49 | if (Settings::IsConfiguringGlobal()) { | 56 | for (const auto& [id, widget] : hold) { |
| 50 | ui->gpu_accuracy->setCurrentIndex( | 57 | layout.addWidget(widget); |
| 51 | static_cast<int>(Settings::values.gpu_accuracy.GetValue())); | ||
| 52 | ui->anisotropic_filtering_combobox->setCurrentIndex( | ||
| 53 | Settings::values.max_anisotropy.GetValue()); | ||
| 54 | ui->astc_recompression_combobox->setCurrentIndex( | ||
| 55 | static_cast<int>(Settings::values.astc_recompression.GetValue())); | ||
| 56 | } else { | ||
| 57 | ConfigurationShared::SetPerGameSetting(ui->gpu_accuracy, &Settings::values.gpu_accuracy); | ||
| 58 | ConfigurationShared::SetPerGameSetting(ui->anisotropic_filtering_combobox, | ||
| 59 | &Settings::values.max_anisotropy); | ||
| 60 | ConfigurationShared::SetPerGameSetting(ui->astc_recompression_combobox, | ||
| 61 | &Settings::values.astc_recompression); | ||
| 62 | ConfigurationShared::SetHighlight(ui->label_gpu_accuracy, | ||
| 63 | !Settings::values.gpu_accuracy.UsingGlobal()); | ||
| 64 | ConfigurationShared::SetHighlight(ui->af_label, | ||
| 65 | !Settings::values.max_anisotropy.UsingGlobal()); | ||
| 66 | ConfigurationShared::SetHighlight(ui->label_astc_recompression, | ||
| 67 | !Settings::values.astc_recompression.UsingGlobal()); | ||
| 68 | } | 58 | } |
| 69 | } | 59 | } |
| 70 | 60 | ||
| 71 | void ConfigureGraphicsAdvanced::ApplyConfiguration() { | 61 | void ConfigureGraphicsAdvanced::ApplyConfiguration() { |
| 72 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.gpu_accuracy, ui->gpu_accuracy); | 62 | const bool is_powered_on = system.IsPoweredOn(); |
| 73 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.async_presentation, | 63 | for (const auto& func : apply_funcs) { |
| 74 | ui->async_present, async_present); | 64 | func(is_powered_on); |
| 75 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.renderer_force_max_clock, | 65 | } |
| 76 | ui->renderer_force_max_clock, | ||
| 77 | renderer_force_max_clock); | ||
| 78 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.max_anisotropy, | ||
| 79 | ui->anisotropic_filtering_combobox); | ||
| 80 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_reactive_flushing, | ||
| 81 | ui->use_reactive_flushing, use_reactive_flushing); | ||
| 82 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.async_astc, ui->async_astc, | ||
| 83 | async_astc); | ||
| 84 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.astc_recompression, | ||
| 85 | ui->astc_recompression_combobox); | ||
| 86 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_asynchronous_shaders, | ||
| 87 | ui->use_asynchronous_shaders, | ||
| 88 | use_asynchronous_shaders); | ||
| 89 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_fast_gpu_time, | ||
| 90 | ui->use_fast_gpu_time, use_fast_gpu_time); | ||
| 91 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_vulkan_driver_pipeline_cache, | ||
| 92 | ui->use_vulkan_driver_pipeline_cache, | ||
| 93 | use_vulkan_driver_pipeline_cache); | ||
| 94 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.enable_compute_pipelines, | ||
| 95 | ui->enable_compute_pipelines_checkbox, | ||
| 96 | enable_compute_pipelines); | ||
| 97 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_video_framerate, | ||
| 98 | ui->use_video_framerate_checkbox, use_video_framerate); | ||
| 99 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.barrier_feedback_loops, | ||
| 100 | ui->barrier_feedback_loops_checkbox, | ||
| 101 | barrier_feedback_loops); | ||
| 102 | } | 66 | } |
| 103 | 67 | ||
| 104 | void ConfigureGraphicsAdvanced::changeEvent(QEvent* event) { | 68 | void ConfigureGraphicsAdvanced::changeEvent(QEvent* event) { |
| @@ -113,71 +77,6 @@ void ConfigureGraphicsAdvanced::RetranslateUI() { | |||
| 113 | ui->retranslateUi(this); | 77 | ui->retranslateUi(this); |
| 114 | } | 78 | } |
| 115 | 79 | ||
| 116 | void ConfigureGraphicsAdvanced::SetupPerGameUI() { | ||
| 117 | // Disable if not global (only happens during game) | ||
| 118 | if (Settings::IsConfiguringGlobal()) { | ||
| 119 | ui->gpu_accuracy->setEnabled(Settings::values.gpu_accuracy.UsingGlobal()); | ||
| 120 | ui->async_present->setEnabled(Settings::values.async_presentation.UsingGlobal()); | ||
| 121 | ui->renderer_force_max_clock->setEnabled( | ||
| 122 | Settings::values.renderer_force_max_clock.UsingGlobal()); | ||
| 123 | ui->use_reactive_flushing->setEnabled(Settings::values.use_reactive_flushing.UsingGlobal()); | ||
| 124 | ui->async_astc->setEnabled(Settings::values.async_astc.UsingGlobal()); | ||
| 125 | ui->astc_recompression_combobox->setEnabled( | ||
| 126 | Settings::values.astc_recompression.UsingGlobal()); | ||
| 127 | ui->use_asynchronous_shaders->setEnabled( | ||
| 128 | Settings::values.use_asynchronous_shaders.UsingGlobal()); | ||
| 129 | ui->use_fast_gpu_time->setEnabled(Settings::values.use_fast_gpu_time.UsingGlobal()); | ||
| 130 | ui->use_vulkan_driver_pipeline_cache->setEnabled( | ||
| 131 | Settings::values.use_vulkan_driver_pipeline_cache.UsingGlobal()); | ||
| 132 | ui->anisotropic_filtering_combobox->setEnabled( | ||
| 133 | Settings::values.max_anisotropy.UsingGlobal()); | ||
| 134 | ui->enable_compute_pipelines_checkbox->setEnabled( | ||
| 135 | Settings::values.enable_compute_pipelines.UsingGlobal()); | ||
| 136 | ui->use_video_framerate_checkbox->setEnabled( | ||
| 137 | Settings::values.use_video_framerate.UsingGlobal()); | ||
| 138 | ui->barrier_feedback_loops_checkbox->setEnabled( | ||
| 139 | Settings::values.barrier_feedback_loops.UsingGlobal()); | ||
| 140 | |||
| 141 | return; | ||
| 142 | } | ||
| 143 | |||
| 144 | ConfigurationShared::SetColoredTristate(ui->async_present, Settings::values.async_presentation, | ||
| 145 | async_present); | ||
| 146 | ConfigurationShared::SetColoredTristate(ui->renderer_force_max_clock, | ||
| 147 | Settings::values.renderer_force_max_clock, | ||
| 148 | renderer_force_max_clock); | ||
| 149 | ConfigurationShared::SetColoredTristate( | ||
| 150 | ui->use_reactive_flushing, Settings::values.use_reactive_flushing, use_reactive_flushing); | ||
| 151 | ConfigurationShared::SetColoredTristate(ui->async_astc, Settings::values.async_astc, | ||
| 152 | async_astc); | ||
| 153 | ConfigurationShared::SetColoredTristate(ui->use_asynchronous_shaders, | ||
| 154 | Settings::values.use_asynchronous_shaders, | ||
| 155 | use_asynchronous_shaders); | ||
| 156 | ConfigurationShared::SetColoredTristate(ui->use_fast_gpu_time, | ||
| 157 | Settings::values.use_fast_gpu_time, use_fast_gpu_time); | ||
| 158 | ConfigurationShared::SetColoredTristate(ui->use_vulkan_driver_pipeline_cache, | ||
| 159 | Settings::values.use_vulkan_driver_pipeline_cache, | ||
| 160 | use_vulkan_driver_pipeline_cache); | ||
| 161 | ConfigurationShared::SetColoredTristate(ui->enable_compute_pipelines_checkbox, | ||
| 162 | Settings::values.enable_compute_pipelines, | ||
| 163 | enable_compute_pipelines); | ||
| 164 | ConfigurationShared::SetColoredTristate(ui->use_video_framerate_checkbox, | ||
| 165 | Settings::values.use_video_framerate, | ||
| 166 | use_video_framerate); | ||
| 167 | ConfigurationShared::SetColoredTristate(ui->barrier_feedback_loops_checkbox, | ||
| 168 | Settings::values.barrier_feedback_loops, | ||
| 169 | barrier_feedback_loops); | ||
| 170 | ConfigurationShared::SetColoredComboBox( | ||
| 171 | ui->gpu_accuracy, ui->label_gpu_accuracy, | ||
| 172 | static_cast<int>(Settings::values.gpu_accuracy.GetValue(true))); | ||
| 173 | ConfigurationShared::SetColoredComboBox( | ||
| 174 | ui->anisotropic_filtering_combobox, ui->af_label, | ||
| 175 | static_cast<int>(Settings::values.max_anisotropy.GetValue(true))); | ||
| 176 | ConfigurationShared::SetColoredComboBox( | ||
| 177 | ui->astc_recompression_combobox, ui->label_astc_recompression, | ||
| 178 | static_cast<int>(Settings::values.astc_recompression.GetValue(true))); | ||
| 179 | } | ||
| 180 | |||
| 181 | void ConfigureGraphicsAdvanced::ExposeComputeOption() { | 80 | void ConfigureGraphicsAdvanced::ExposeComputeOption() { |
| 182 | ui->enable_compute_pipelines_checkbox->setVisible(true); | 81 | checkbox_enable_compute_pipelines->setVisible(true); |
| 183 | } | 82 | } |
diff --git a/src/yuzu/configuration/configure_graphics_advanced.h b/src/yuzu/configuration/configure_graphics_advanced.h index 369a7c83e..78b5389c3 100644 --- a/src/yuzu/configuration/configure_graphics_advanced.h +++ b/src/yuzu/configuration/configure_graphics_advanced.h | |||
| @@ -4,51 +4,44 @@ | |||
| 4 | #pragma once | 4 | #pragma once |
| 5 | 5 | ||
| 6 | #include <memory> | 6 | #include <memory> |
| 7 | #include <vector> | ||
| 7 | #include <QWidget> | 8 | #include <QWidget> |
| 9 | #include "yuzu/configuration/configuration_shared.h" | ||
| 8 | 10 | ||
| 9 | namespace Core { | 11 | namespace Core { |
| 10 | class System; | 12 | class System; |
| 11 | } | 13 | } |
| 12 | 14 | ||
| 13 | namespace ConfigurationShared { | ||
| 14 | enum class CheckState; | ||
| 15 | } | ||
| 16 | |||
| 17 | namespace Ui { | 15 | namespace Ui { |
| 18 | class ConfigureGraphicsAdvanced; | 16 | class ConfigureGraphicsAdvanced; |
| 19 | } | 17 | } |
| 20 | 18 | ||
| 21 | class ConfigureGraphicsAdvanced : public QWidget { | 19 | namespace ConfigurationShared { |
| 22 | Q_OBJECT | 20 | class Builder; |
| 21 | } | ||
| 23 | 22 | ||
| 23 | class ConfigureGraphicsAdvanced : public ConfigurationShared::Tab { | ||
| 24 | public: | 24 | public: |
| 25 | explicit ConfigureGraphicsAdvanced(const Core::System& system_, QWidget* parent = nullptr); | 25 | explicit ConfigureGraphicsAdvanced( |
| 26 | const Core::System& system_, std::shared_ptr<std::vector<ConfigurationShared::Tab*>> group, | ||
| 27 | const ConfigurationShared::Builder& builder, QWidget* parent = nullptr); | ||
| 26 | ~ConfigureGraphicsAdvanced() override; | 28 | ~ConfigureGraphicsAdvanced() override; |
| 27 | 29 | ||
| 28 | void ApplyConfiguration(); | 30 | void ApplyConfiguration() override; |
| 29 | void SetConfiguration(); | 31 | void SetConfiguration() override; |
| 30 | 32 | ||
| 31 | void ExposeComputeOption(); | 33 | void ExposeComputeOption(); |
| 32 | 34 | ||
| 33 | private: | 35 | private: |
| 36 | void Setup(const ConfigurationShared::Builder& builder); | ||
| 34 | void changeEvent(QEvent* event) override; | 37 | void changeEvent(QEvent* event) override; |
| 35 | void RetranslateUI(); | 38 | void RetranslateUI(); |
| 36 | 39 | ||
| 37 | void SetupPerGameUI(); | ||
| 38 | |||
| 39 | std::unique_ptr<Ui::ConfigureGraphicsAdvanced> ui; | 40 | std::unique_ptr<Ui::ConfigureGraphicsAdvanced> ui; |
| 40 | 41 | ||
| 41 | ConfigurationShared::CheckState async_present; | ||
| 42 | ConfigurationShared::CheckState renderer_force_max_clock; | ||
| 43 | ConfigurationShared::CheckState use_vsync; | ||
| 44 | ConfigurationShared::CheckState async_astc; | ||
| 45 | ConfigurationShared::CheckState use_reactive_flushing; | ||
| 46 | ConfigurationShared::CheckState use_asynchronous_shaders; | ||
| 47 | ConfigurationShared::CheckState use_fast_gpu_time; | ||
| 48 | ConfigurationShared::CheckState use_vulkan_driver_pipeline_cache; | ||
| 49 | ConfigurationShared::CheckState enable_compute_pipelines; | ||
| 50 | ConfigurationShared::CheckState use_video_framerate; | ||
| 51 | ConfigurationShared::CheckState barrier_feedback_loops; | ||
| 52 | |||
| 53 | const Core::System& system; | 42 | const Core::System& system; |
| 43 | |||
| 44 | std::vector<std::function<void(bool)>> apply_funcs; | ||
| 45 | |||
| 46 | QWidget* checkbox_enable_compute_pipelines{}; | ||
| 54 | }; | 47 | }; |
diff --git a/src/yuzu/configuration/configure_graphics_advanced.ui b/src/yuzu/configuration/configure_graphics_advanced.ui index d527a6f38..37a854ca3 100644 --- a/src/yuzu/configuration/configure_graphics_advanced.ui +++ b/src/yuzu/configuration/configure_graphics_advanced.ui | |||
| @@ -26,8 +26,8 @@ | |||
| 26 | </property> | 26 | </property> |
| 27 | <layout class="QVBoxLayout" name="verticalLayout_3"> | 27 | <layout class="QVBoxLayout" name="verticalLayout_3"> |
| 28 | <item> | 28 | <item> |
| 29 | <widget class="QWidget" name="gpu_accuracy_layout" native="true"> | 29 | <widget class="QWidget" name="populate_target" native="true"> |
| 30 | <layout class="QHBoxLayout" name="horizontalLayout_2"> | 30 | <layout class="QVBoxLayout" name="verticalLayout"> |
| 31 | <property name="leftMargin"> | 31 | <property name="leftMargin"> |
| 32 | <number>0</number> | 32 | <number>0</number> |
| 33 | </property> | 33 | </property> |
| @@ -40,233 +40,6 @@ | |||
| 40 | <property name="bottomMargin"> | 40 | <property name="bottomMargin"> |
| 41 | <number>0</number> | 41 | <number>0</number> |
| 42 | </property> | 42 | </property> |
| 43 | <item> | ||
| 44 | <widget class="QLabel" name="label_gpu_accuracy"> | ||
| 45 | <property name="text"> | ||
| 46 | <string>Accuracy Level:</string> | ||
| 47 | </property> | ||
| 48 | </widget> | ||
| 49 | </item> | ||
| 50 | <item> | ||
| 51 | <widget class="QComboBox" name="gpu_accuracy"> | ||
| 52 | <item> | ||
| 53 | <property name="text"> | ||
| 54 | <string notr="true">Normal</string> | ||
| 55 | </property> | ||
| 56 | </item> | ||
| 57 | <item> | ||
| 58 | <property name="text"> | ||
| 59 | <string notr="true">High</string> | ||
| 60 | </property> | ||
| 61 | </item> | ||
| 62 | <item> | ||
| 63 | <property name="text"> | ||
| 64 | <string notr="true">Extreme(very slow)</string> | ||
| 65 | </property> | ||
| 66 | </item> | ||
| 67 | </widget> | ||
| 68 | </item> | ||
| 69 | </layout> | ||
| 70 | </widget> | ||
| 71 | </item> | ||
| 72 | <item> | ||
| 73 | <widget class="QWidget" name="astc_recompression_layout" native="true"> | ||
| 74 | <layout class="QHBoxLayout" name="horizontalLayout_3"> | ||
| 75 | <property name="leftMargin"> | ||
| 76 | <number>0</number> | ||
| 77 | </property> | ||
| 78 | <property name="topMargin"> | ||
| 79 | <number>0</number> | ||
| 80 | </property> | ||
| 81 | <property name="rightMargin"> | ||
| 82 | <number>0</number> | ||
| 83 | </property> | ||
| 84 | <property name="bottomMargin"> | ||
| 85 | <number>0</number> | ||
| 86 | </property> | ||
| 87 | <item> | ||
| 88 | <widget class="QLabel" name="label_astc_recompression"> | ||
| 89 | <property name="text"> | ||
| 90 | <string>ASTC recompression:</string> | ||
| 91 | </property> | ||
| 92 | </widget> | ||
| 93 | </item> | ||
| 94 | <item> | ||
| 95 | <widget class="QComboBox" name="astc_recompression_combobox"> | ||
| 96 | <item> | ||
| 97 | <property name="text"> | ||
| 98 | <string>Uncompressed (Best quality)</string> | ||
| 99 | </property> | ||
| 100 | </item> | ||
| 101 | <item> | ||
| 102 | <property name="text"> | ||
| 103 | <string>BC1 (Low quality)</string> | ||
| 104 | </property> | ||
| 105 | </item> | ||
| 106 | <item> | ||
| 107 | <property name="text"> | ||
| 108 | <string>BC3 (Medium quality)</string> | ||
| 109 | </property> | ||
| 110 | </item> | ||
| 111 | </widget> | ||
| 112 | </item> | ||
| 113 | </layout> | ||
| 114 | </widget> | ||
| 115 | </item> | ||
| 116 | <item> | ||
| 117 | <widget class="QCheckBox" name="async_present"> | ||
| 118 | <property name="text"> | ||
| 119 | <string>Enable asynchronous presentation (Vulkan only)</string> | ||
| 120 | </property> | ||
| 121 | </widget> | ||
| 122 | </item> | ||
| 123 | <item> | ||
| 124 | <widget class="QCheckBox" name="renderer_force_max_clock"> | ||
| 125 | <property name="toolTip"> | ||
| 126 | <string>Runs work in the background while waiting for graphics commands to keep the GPU from lowering its clock speed.</string> | ||
| 127 | </property> | ||
| 128 | <property name="text"> | ||
| 129 | <string>Force maximum clocks (Vulkan only)</string> | ||
| 130 | </property> | ||
| 131 | </widget> | ||
| 132 | </item> | ||
| 133 | <item> | ||
| 134 | <widget class="QCheckBox" name="async_astc"> | ||
| 135 | <property name="toolTip"> | ||
| 136 | <string>Enables asynchronous ASTC texture decoding, which may reduce load time stutter. This feature is experimental.</string> | ||
| 137 | </property> | ||
| 138 | <property name="text"> | ||
| 139 | <string>Decode ASTC textures asynchronously (Hack)</string> | ||
| 140 | </property> | ||
| 141 | </widget> | ||
| 142 | </item> | ||
| 143 | <item> | ||
| 144 | <widget class="QCheckBox" name="use_reactive_flushing"> | ||
| 145 | <property name="toolTip"> | ||
| 146 | <string>Uses reactive flushing instead of predictive flushing. Allowing a more accurate syncing of memory.</string> | ||
| 147 | </property> | ||
| 148 | <property name="text"> | ||
| 149 | <string>Enable Reactive Flushing</string> | ||
| 150 | </property> | ||
| 151 | </widget> | ||
| 152 | </item> | ||
| 153 | <item> | ||
| 154 | <widget class="QCheckBox" name="use_asynchronous_shaders"> | ||
| 155 | <property name="toolTip"> | ||
| 156 | <string>Enables asynchronous shader compilation, which may reduce shader stutter. This feature is experimental.</string> | ||
| 157 | </property> | ||
| 158 | <property name="text"> | ||
| 159 | <string>Use asynchronous shader building (Hack)</string> | ||
| 160 | </property> | ||
| 161 | </widget> | ||
| 162 | </item> | ||
| 163 | <item> | ||
| 164 | <widget class="QCheckBox" name="use_fast_gpu_time"> | ||
| 165 | <property name="toolTip"> | ||
| 166 | <string>Enables Fast GPU Time. This option will force most games to run at their highest native resolution.</string> | ||
| 167 | </property> | ||
| 168 | <property name="text"> | ||
| 169 | <string>Use Fast GPU Time (Hack)</string> | ||
| 170 | </property> | ||
| 171 | </widget> | ||
| 172 | </item> | ||
| 173 | <item> | ||
| 174 | <widget class="QCheckBox" name="use_vulkan_driver_pipeline_cache"> | ||
| 175 | <property name="toolTip"> | ||
| 176 | <string>Enables GPU vendor-specific pipeline cache. This option can improve shader loading time significantly in cases where the Vulkan driver does not store pipeline cache files internally.</string> | ||
| 177 | </property> | ||
| 178 | <property name="text"> | ||
| 179 | <string>Use Vulkan pipeline cache</string> | ||
| 180 | </property> | ||
| 181 | </widget> | ||
| 182 | </item> | ||
| 183 | <item> | ||
| 184 | <widget class="QCheckBox" name="enable_compute_pipelines_checkbox"> | ||
| 185 | <property name="toolTip"> | ||
| 186 | <string>Enable compute pipelines, required by some games. This setting only exists for Intel proprietary drivers, and may crash if enabled. | ||
| 187 | Compute pipelines are always enabled on all other drivers.</string> | ||
| 188 | </property> | ||
| 189 | <property name="text"> | ||
| 190 | <string>Enable Compute Pipelines (Intel Vulkan only)</string> | ||
| 191 | </property> | ||
| 192 | </widget> | ||
| 193 | </item> | ||
| 194 | <item> | ||
| 195 | <widget class="QCheckBox" name="use_video_framerate_checkbox"> | ||
| 196 | <property name="toolTip"> | ||
| 197 | <string>Run the game at normal speed during video playback, even when the framerate is unlocked.</string> | ||
| 198 | </property> | ||
| 199 | <property name="text"> | ||
| 200 | <string>Sync to framerate of video playback</string> | ||
| 201 | </property> | ||
| 202 | </widget> | ||
| 203 | </item> | ||
| 204 | <item> | ||
| 205 | <widget class="QCheckBox" name="barrier_feedback_loops_checkbox"> | ||
| 206 | <property name="toolTip"> | ||
| 207 | <string>Improves rendering of transparency effects in specific games.</string> | ||
| 208 | </property> | ||
| 209 | <property name="text"> | ||
| 210 | <string>Barrier feedback loops</string> | ||
| 211 | </property> | ||
| 212 | </widget> | ||
| 213 | </item> | ||
| 214 | <item> | ||
| 215 | <widget class="QWidget" name="af_layout" native="true"> | ||
| 216 | <layout class="QHBoxLayout" name="horizontalLayout_1"> | ||
| 217 | <property name="leftMargin"> | ||
| 218 | <number>0</number> | ||
| 219 | </property> | ||
| 220 | <property name="topMargin"> | ||
| 221 | <number>0</number> | ||
| 222 | </property> | ||
| 223 | <property name="rightMargin"> | ||
| 224 | <number>0</number> | ||
| 225 | </property> | ||
| 226 | <property name="bottomMargin"> | ||
| 227 | <number>0</number> | ||
| 228 | </property> | ||
| 229 | <item> | ||
| 230 | <widget class="QLabel" name="af_label"> | ||
| 231 | <property name="text"> | ||
| 232 | <string>Anisotropic Filtering:</string> | ||
| 233 | </property> | ||
| 234 | </widget> | ||
| 235 | </item> | ||
| 236 | <item> | ||
| 237 | <widget class="QComboBox" name="anisotropic_filtering_combobox"> | ||
| 238 | <item> | ||
| 239 | <property name="text"> | ||
| 240 | <string>Automatic</string> | ||
| 241 | </property> | ||
| 242 | </item> | ||
| 243 | <item> | ||
| 244 | <property name="text"> | ||
| 245 | <string>Default</string> | ||
| 246 | </property> | ||
| 247 | </item> | ||
| 248 | <item> | ||
| 249 | <property name="text"> | ||
| 250 | <string>2x</string> | ||
| 251 | </property> | ||
| 252 | </item> | ||
| 253 | <item> | ||
| 254 | <property name="text"> | ||
| 255 | <string>4x</string> | ||
| 256 | </property> | ||
| 257 | </item> | ||
| 258 | <item> | ||
| 259 | <property name="text"> | ||
| 260 | <string>8x</string> | ||
| 261 | </property> | ||
| 262 | </item> | ||
| 263 | <item> | ||
| 264 | <property name="text"> | ||
| 265 | <string>16x</string> | ||
| 266 | </property> | ||
| 267 | </item> | ||
| 268 | </widget> | ||
| 269 | </item> | ||
| 270 | </layout> | 43 | </layout> |
| 271 | </widget> | 44 | </widget> |
| 272 | </item> | 45 | </item> |
diff --git a/src/yuzu/configuration/configure_per_game.cpp b/src/yuzu/configuration/configure_per_game.cpp index eb96e6068..cd8b3012e 100644 --- a/src/yuzu/configuration/configure_per_game.cpp +++ b/src/yuzu/configuration/configure_per_game.cpp | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | #include <QTimer> | 17 | #include <QTimer> |
| 18 | 18 | ||
| 19 | #include "common/fs/fs_util.h" | 19 | #include "common/fs/fs_util.h" |
| 20 | #include "configuration/shared_widget.h" | ||
| 20 | #include "core/core.h" | 21 | #include "core/core.h" |
| 21 | #include "core/file_sys/control_metadata.h" | 22 | #include "core/file_sys/control_metadata.h" |
| 22 | #include "core/file_sys/patch_manager.h" | 23 | #include "core/file_sys/patch_manager.h" |
| @@ -24,9 +25,9 @@ | |||
| 24 | #include "core/loader/loader.h" | 25 | #include "core/loader/loader.h" |
| 25 | #include "ui_configure_per_game.h" | 26 | #include "ui_configure_per_game.h" |
| 26 | #include "yuzu/configuration/config.h" | 27 | #include "yuzu/configuration/config.h" |
| 28 | #include "yuzu/configuration/configuration_shared.h" | ||
| 27 | #include "yuzu/configuration/configure_audio.h" | 29 | #include "yuzu/configuration/configure_audio.h" |
| 28 | #include "yuzu/configuration/configure_cpu.h" | 30 | #include "yuzu/configuration/configure_cpu.h" |
| 29 | #include "yuzu/configuration/configure_general.h" | ||
| 30 | #include "yuzu/configuration/configure_graphics.h" | 31 | #include "yuzu/configuration/configure_graphics.h" |
| 31 | #include "yuzu/configuration/configure_graphics_advanced.h" | 32 | #include "yuzu/configuration/configure_graphics_advanced.h" |
| 32 | #include "yuzu/configuration/configure_input_per_game.h" | 33 | #include "yuzu/configuration/configure_input_per_game.h" |
| @@ -41,26 +42,28 @@ ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id_, const std::st | |||
| 41 | std::vector<VkDeviceInfo::Record>& vk_device_records, | 42 | std::vector<VkDeviceInfo::Record>& vk_device_records, |
| 42 | Core::System& system_) | 43 | Core::System& system_) |
| 43 | : QDialog(parent), | 44 | : QDialog(parent), |
| 44 | ui(std::make_unique<Ui::ConfigurePerGame>()), title_id{title_id_}, system{system_} { | 45 | ui(std::make_unique<Ui::ConfigurePerGame>()), title_id{title_id_}, system{system_}, |
| 46 | builder{std::make_unique<ConfigurationShared::Builder>(this, !system_.IsPoweredOn())}, | ||
| 47 | tab_group{std::make_shared<std::vector<ConfigurationShared::Tab*>>()} { | ||
| 45 | const auto file_path = std::filesystem::path(Common::FS::ToU8String(file_name)); | 48 | const auto file_path = std::filesystem::path(Common::FS::ToU8String(file_name)); |
| 46 | const auto config_file_name = title_id == 0 ? Common::FS::PathToUTF8String(file_path.filename()) | 49 | const auto config_file_name = title_id == 0 ? Common::FS::PathToUTF8String(file_path.filename()) |
| 47 | : fmt::format("{:016X}", title_id); | 50 | : fmt::format("{:016X}", title_id); |
| 48 | game_config = std::make_unique<Config>(config_file_name, Config::ConfigType::PerGameConfig); | 51 | game_config = std::make_unique<Config>(config_file_name, Config::ConfigType::PerGameConfig); |
| 49 | 52 | ||
| 50 | addons_tab = std::make_unique<ConfigurePerGameAddons>(system_, this); | 53 | addons_tab = std::make_unique<ConfigurePerGameAddons>(system_, this); |
| 51 | audio_tab = std::make_unique<ConfigureAudio>(system_, this); | 54 | audio_tab = std::make_unique<ConfigureAudio>(system_, tab_group, *builder, this); |
| 52 | cpu_tab = std::make_unique<ConfigureCpu>(system_, this); | 55 | cpu_tab = std::make_unique<ConfigureCpu>(system_, tab_group, *builder, this); |
| 53 | general_tab = std::make_unique<ConfigureGeneral>(system_, this); | 56 | graphics_advanced_tab = |
| 54 | graphics_advanced_tab = std::make_unique<ConfigureGraphicsAdvanced>(system_, this); | 57 | std::make_unique<ConfigureGraphicsAdvanced>(system_, tab_group, *builder, this); |
| 55 | graphics_tab = std::make_unique<ConfigureGraphics>( | 58 | graphics_tab = std::make_unique<ConfigureGraphics>( |
| 56 | system_, vk_device_records, [&]() { graphics_advanced_tab->ExposeComputeOption(); }, this); | 59 | system_, vk_device_records, [&]() { graphics_advanced_tab->ExposeComputeOption(); }, |
| 60 | tab_group, *builder, this); | ||
| 57 | input_tab = std::make_unique<ConfigureInputPerGame>(system_, game_config.get(), this); | 61 | input_tab = std::make_unique<ConfigureInputPerGame>(system_, game_config.get(), this); |
| 58 | system_tab = std::make_unique<ConfigureSystem>(system_, this); | 62 | system_tab = std::make_unique<ConfigureSystem>(system_, tab_group, *builder, this); |
| 59 | 63 | ||
| 60 | ui->setupUi(this); | 64 | ui->setupUi(this); |
| 61 | 65 | ||
| 62 | ui->tabWidget->addTab(addons_tab.get(), tr("Add-Ons")); | 66 | ui->tabWidget->addTab(addons_tab.get(), tr("Add-Ons")); |
| 63 | ui->tabWidget->addTab(general_tab.get(), tr("General")); | ||
| 64 | ui->tabWidget->addTab(system_tab.get(), tr("System")); | 67 | ui->tabWidget->addTab(system_tab.get(), tr("System")); |
| 65 | ui->tabWidget->addTab(cpu_tab.get(), tr("CPU")); | 68 | ui->tabWidget->addTab(cpu_tab.get(), tr("CPU")); |
| 66 | ui->tabWidget->addTab(graphics_tab.get(), tr("Graphics")); | 69 | ui->tabWidget->addTab(graphics_tab.get(), tr("Graphics")); |
| @@ -88,13 +91,10 @@ ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id_, const std::st | |||
| 88 | ConfigurePerGame::~ConfigurePerGame() = default; | 91 | ConfigurePerGame::~ConfigurePerGame() = default; |
| 89 | 92 | ||
| 90 | void ConfigurePerGame::ApplyConfiguration() { | 93 | void ConfigurePerGame::ApplyConfiguration() { |
| 94 | for (const auto tab : *tab_group) { | ||
| 95 | tab->ApplyConfiguration(); | ||
| 96 | } | ||
| 91 | addons_tab->ApplyConfiguration(); | 97 | addons_tab->ApplyConfiguration(); |
| 92 | general_tab->ApplyConfiguration(); | ||
| 93 | cpu_tab->ApplyConfiguration(); | ||
| 94 | system_tab->ApplyConfiguration(); | ||
| 95 | graphics_tab->ApplyConfiguration(); | ||
| 96 | graphics_advanced_tab->ApplyConfiguration(); | ||
| 97 | audio_tab->ApplyConfiguration(); | ||
| 98 | input_tab->ApplyConfiguration(); | 98 | input_tab->ApplyConfiguration(); |
| 99 | 99 | ||
| 100 | system.ApplySettings(); | 100 | system.ApplySettings(); |
diff --git a/src/yuzu/configuration/configure_per_game.h b/src/yuzu/configuration/configure_per_game.h index 7ec1ded06..1a727f32c 100644 --- a/src/yuzu/configuration/configure_per_game.h +++ b/src/yuzu/configuration/configure_per_game.h | |||
| @@ -10,9 +10,12 @@ | |||
| 10 | #include <QDialog> | 10 | #include <QDialog> |
| 11 | #include <QList> | 11 | #include <QList> |
| 12 | 12 | ||
| 13 | #include "configuration/shared_widget.h" | ||
| 13 | #include "core/file_sys/vfs_types.h" | 14 | #include "core/file_sys/vfs_types.h" |
| 14 | #include "vk_device_info.h" | 15 | #include "vk_device_info.h" |
| 15 | #include "yuzu/configuration/config.h" | 16 | #include "yuzu/configuration/config.h" |
| 17 | #include "yuzu/configuration/configuration_shared.h" | ||
| 18 | #include "yuzu/configuration/shared_translation.h" | ||
| 16 | 19 | ||
| 17 | namespace Core { | 20 | namespace Core { |
| 18 | class System; | 21 | class System; |
| @@ -25,7 +28,6 @@ class InputSubsystem; | |||
| 25 | class ConfigurePerGameAddons; | 28 | class ConfigurePerGameAddons; |
| 26 | class ConfigureAudio; | 29 | class ConfigureAudio; |
| 27 | class ConfigureCpu; | 30 | class ConfigureCpu; |
| 28 | class ConfigureGeneral; | ||
| 29 | class ConfigureGraphics; | 31 | class ConfigureGraphics; |
| 30 | class ConfigureGraphicsAdvanced; | 32 | class ConfigureGraphicsAdvanced; |
| 31 | class ConfigureInputPerGame; | 33 | class ConfigureInputPerGame; |
| @@ -73,11 +75,12 @@ private: | |||
| 73 | std::unique_ptr<Config> game_config; | 75 | std::unique_ptr<Config> game_config; |
| 74 | 76 | ||
| 75 | Core::System& system; | 77 | Core::System& system; |
| 78 | std::unique_ptr<ConfigurationShared::Builder> builder; | ||
| 79 | std::shared_ptr<std::vector<ConfigurationShared::Tab*>> tab_group; | ||
| 76 | 80 | ||
| 77 | std::unique_ptr<ConfigurePerGameAddons> addons_tab; | 81 | std::unique_ptr<ConfigurePerGameAddons> addons_tab; |
| 78 | std::unique_ptr<ConfigureAudio> audio_tab; | 82 | std::unique_ptr<ConfigureAudio> audio_tab; |
| 79 | std::unique_ptr<ConfigureCpu> cpu_tab; | 83 | std::unique_ptr<ConfigureCpu> cpu_tab; |
| 80 | std::unique_ptr<ConfigureGeneral> general_tab; | ||
| 81 | std::unique_ptr<ConfigureGraphicsAdvanced> graphics_advanced_tab; | 84 | std::unique_ptr<ConfigureGraphicsAdvanced> graphics_advanced_tab; |
| 82 | std::unique_ptr<ConfigureGraphics> graphics_tab; | 85 | std::unique_ptr<ConfigureGraphics> graphics_tab; |
| 83 | std::unique_ptr<ConfigureInputPerGame> input_tab; | 86 | std::unique_ptr<ConfigureInputPerGame> input_tab; |
diff --git a/src/yuzu/configuration/configure_per_game.ui b/src/yuzu/configuration/configure_per_game.ui index 85c86e107..99ba2fd18 100644 --- a/src/yuzu/configuration/configure_per_game.ui +++ b/src/yuzu/configuration/configure_per_game.ui | |||
| @@ -2,6 +2,14 @@ | |||
| 2 | <ui version="4.0"> | 2 | <ui version="4.0"> |
| 3 | <class>ConfigurePerGame</class> | 3 | <class>ConfigurePerGame</class> |
| 4 | <widget class="QDialog" name="ConfigurePerGame"> | 4 | <widget class="QDialog" name="ConfigurePerGame"> |
| 5 | <property name="geometry"> | ||
| 6 | <rect> | ||
| 7 | <x>0</x> | ||
| 8 | <y>0</y> | ||
| 9 | <width>900</width> | ||
| 10 | <height>607</height> | ||
| 11 | </rect> | ||
| 12 | </property> | ||
| 5 | <property name="minimumSize"> | 13 | <property name="minimumSize"> |
| 6 | <size> | 14 | <size> |
| 7 | <width>900</width> | 15 | <width>900</width> |
| @@ -225,20 +233,31 @@ | |||
| 225 | </layout> | 233 | </layout> |
| 226 | </item> | 234 | </item> |
| 227 | <item> | 235 | <item> |
| 228 | <widget class="QDialogButtonBox" name="buttonBox"> | 236 | <layout class="QHBoxLayout" name="horizontalLayout_2"> |
| 229 | <property name="sizePolicy"> | 237 | <item> |
| 230 | <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> | 238 | <widget class="QLabel" name="label_8"> |
| 231 | <horstretch>0</horstretch> | 239 | <property name="text"> |
| 232 | <verstretch>0</verstretch> | 240 | <string>Some settings are only available when a game is not running.</string> |
| 233 | </sizepolicy> | 241 | </property> |
| 234 | </property> | 242 | </widget> |
| 235 | <property name="orientation"> | 243 | </item> |
| 236 | <enum>Qt::Horizontal</enum> | 244 | <item> |
| 237 | </property> | 245 | <widget class="QDialogButtonBox" name="buttonBox"> |
| 238 | <property name="standardButtons"> | 246 | <property name="sizePolicy"> |
| 239 | <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> | 247 | <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> |
| 240 | </property> | 248 | <horstretch>0</horstretch> |
| 241 | </widget> | 249 | <verstretch>0</verstretch> |
| 250 | </sizepolicy> | ||
| 251 | </property> | ||
| 252 | <property name="orientation"> | ||
| 253 | <enum>Qt::Horizontal</enum> | ||
| 254 | </property> | ||
| 255 | <property name="standardButtons"> | ||
| 256 | <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> | ||
| 257 | </property> | ||
| 258 | </widget> | ||
| 259 | </item> | ||
| 260 | </layout> | ||
| 242 | </item> | 261 | </item> |
| 243 | </layout> | 262 | </layout> |
| 244 | </widget> | 263 | </widget> |
diff --git a/src/yuzu/configuration/configure_system.cpp b/src/yuzu/configuration/configure_system.cpp index f1ae312c6..c4833f4e7 100644 --- a/src/yuzu/configuration/configure_system.cpp +++ b/src/yuzu/configuration/configure_system.cpp | |||
| @@ -3,16 +3,23 @@ | |||
| 3 | 3 | ||
| 4 | #include <chrono> | 4 | #include <chrono> |
| 5 | #include <optional> | 5 | #include <optional> |
| 6 | #include <vector> | ||
| 6 | 7 | ||
| 8 | #include <QCheckBox> | ||
| 9 | #include <QComboBox> | ||
| 10 | #include <QDateTimeEdit> | ||
| 7 | #include <QFileDialog> | 11 | #include <QFileDialog> |
| 8 | #include <QGraphicsItem> | 12 | #include <QGraphicsItem> |
| 13 | #include <QLineEdit> | ||
| 9 | #include <QMessageBox> | 14 | #include <QMessageBox> |
| 10 | #include "common/settings.h" | 15 | #include "common/settings.h" |
| 11 | #include "core/core.h" | 16 | #include "core/core.h" |
| 12 | #include "core/hle/service/time/time_manager.h" | 17 | #include "core/hle/service/time/time_manager.h" |
| 13 | #include "ui_configure_system.h" | 18 | #include "ui_configure_system.h" |
| 19 | #include "yuzu/configuration/config.h" | ||
| 14 | #include "yuzu/configuration/configuration_shared.h" | 20 | #include "yuzu/configuration/configuration_shared.h" |
| 15 | #include "yuzu/configuration/configure_system.h" | 21 | #include "yuzu/configuration/configure_system.h" |
| 22 | #include "yuzu/configuration/shared_widget.h" | ||
| 16 | 23 | ||
| 17 | constexpr std::array<u32, 7> LOCALE_BLOCKLIST{ | 24 | constexpr std::array<u32, 7> LOCALE_BLOCKLIST{ |
| 18 | // pzzefezrpnkzeidfej | 25 | // pzzefezrpnkzeidfej |
| @@ -37,44 +44,32 @@ static bool IsValidLocale(u32 region_index, u32 language_index) { | |||
| 37 | return ((LOCALE_BLOCKLIST.at(region_index) >> language_index) & 1) == 0; | 44 | return ((LOCALE_BLOCKLIST.at(region_index) >> language_index) & 1) == 0; |
| 38 | } | 45 | } |
| 39 | 46 | ||
| 40 | ConfigureSystem::ConfigureSystem(Core::System& system_, QWidget* parent) | 47 | ConfigureSystem::ConfigureSystem(Core::System& system_, |
| 41 | : QWidget(parent), ui{std::make_unique<Ui::ConfigureSystem>()}, system{system_} { | 48 | std::shared_ptr<std::vector<ConfigurationShared::Tab*>> group_, |
| 49 | const ConfigurationShared::Builder& builder, QWidget* parent) | ||
| 50 | : Tab(group_, parent), ui{std::make_unique<Ui::ConfigureSystem>()}, system{system_} { | ||
| 42 | ui->setupUi(this); | 51 | ui->setupUi(this); |
| 43 | 52 | ||
| 44 | connect(ui->rng_seed_checkbox, &QCheckBox::stateChanged, this, [this](int state) { | 53 | Setup(builder); |
| 45 | ui->rng_seed_edit->setEnabled(state == Qt::Checked); | ||
| 46 | if (state != Qt::Checked) { | ||
| 47 | ui->rng_seed_edit->setText(QStringLiteral("00000000")); | ||
| 48 | } | ||
| 49 | }); | ||
| 50 | |||
| 51 | connect(ui->custom_rtc_checkbox, &QCheckBox::stateChanged, this, [this](int state) { | ||
| 52 | ui->custom_rtc_edit->setEnabled(state == Qt::Checked); | ||
| 53 | if (state != Qt::Checked) { | ||
| 54 | ui->custom_rtc_edit->setDateTime(QDateTime::currentDateTime()); | ||
| 55 | } | ||
| 56 | }); | ||
| 57 | 54 | ||
| 58 | const auto locale_check = [this](int index) { | 55 | const auto locale_check = [this]() { |
| 59 | const auto region_index = ConfigurationShared::GetComboboxIndex( | 56 | const auto region_index = combo_region->currentIndex(); |
| 60 | Settings::values.region_index.GetValue(true), ui->combo_region); | 57 | const auto language_index = combo_language->currentIndex(); |
| 61 | const auto language_index = ConfigurationShared::GetComboboxIndex( | ||
| 62 | Settings::values.language_index.GetValue(true), ui->combo_language); | ||
| 63 | const bool valid_locale = IsValidLocale(region_index, language_index); | 58 | const bool valid_locale = IsValidLocale(region_index, language_index); |
| 64 | ui->label_warn_invalid_locale->setVisible(!valid_locale); | 59 | ui->label_warn_invalid_locale->setVisible(!valid_locale); |
| 65 | if (!valid_locale) { | 60 | if (!valid_locale) { |
| 66 | ui->label_warn_invalid_locale->setText( | 61 | ui->label_warn_invalid_locale->setText( |
| 67 | tr("Warning: \"%1\" is not a valid language for region \"%2\"") | 62 | tr("Warning: \"%1\" is not a valid language for region \"%2\"") |
| 68 | .arg(ui->combo_language->currentText()) | 63 | .arg(combo_language->currentText()) |
| 69 | .arg(ui->combo_region->currentText())); | 64 | .arg(combo_region->currentText())); |
| 70 | } | 65 | } |
| 71 | }; | 66 | }; |
| 72 | 67 | ||
| 73 | connect(ui->combo_language, qOverload<int>(&QComboBox::currentIndexChanged), this, | 68 | connect(combo_language, qOverload<int>(&QComboBox::currentIndexChanged), this, locale_check); |
| 74 | locale_check); | 69 | connect(combo_region, qOverload<int>(&QComboBox::currentIndexChanged), this, locale_check); |
| 75 | connect(ui->combo_region, qOverload<int>(&QComboBox::currentIndexChanged), this, locale_check); | ||
| 76 | 70 | ||
| 77 | SetupPerGameUI(); | 71 | ui->label_warn_invalid_locale->setVisible(false); |
| 72 | locale_check(); | ||
| 78 | 73 | ||
| 79 | SetConfiguration(); | 74 | SetConfiguration(); |
| 80 | } | 75 | } |
| @@ -93,137 +88,66 @@ void ConfigureSystem::RetranslateUI() { | |||
| 93 | ui->retranslateUi(this); | 88 | ui->retranslateUi(this); |
| 94 | } | 89 | } |
| 95 | 90 | ||
| 96 | void ConfigureSystem::SetConfiguration() { | 91 | void ConfigureSystem::Setup(const ConfigurationShared::Builder& builder) { |
| 97 | enabled = !system.IsPoweredOn(); | 92 | auto& core_layout = *ui->core_widget->layout(); |
| 98 | const auto rng_seed = | 93 | auto& system_layout = *ui->system_widget->layout(); |
| 99 | QStringLiteral("%1") | ||
| 100 | .arg(Settings::values.rng_seed.GetValue().value_or(0), 8, 16, QLatin1Char{'0'}) | ||
| 101 | .toUpper(); | ||
| 102 | const auto rtc_time = Settings::values.custom_rtc.value_or(QDateTime::currentSecsSinceEpoch()); | ||
| 103 | |||
| 104 | ui->rng_seed_checkbox->setChecked(Settings::values.rng_seed.GetValue().has_value()); | ||
| 105 | ui->rng_seed_edit->setEnabled(Settings::values.rng_seed.GetValue().has_value() && | ||
| 106 | Settings::values.rng_seed.UsingGlobal()); | ||
| 107 | ui->rng_seed_edit->setText(rng_seed); | ||
| 108 | |||
| 109 | ui->custom_rtc_checkbox->setChecked(Settings::values.custom_rtc.has_value()); | ||
| 110 | ui->custom_rtc_edit->setEnabled(Settings::values.custom_rtc.has_value()); | ||
| 111 | ui->custom_rtc_edit->setDateTime(QDateTime::fromSecsSinceEpoch(rtc_time)); | ||
| 112 | ui->device_name_edit->setText( | ||
| 113 | QString::fromUtf8(Settings::values.device_name.GetValue().c_str())); | ||
| 114 | ui->use_unsafe_extended_memory_layout->setEnabled(enabled); | ||
| 115 | ui->use_unsafe_extended_memory_layout->setChecked( | ||
| 116 | Settings::values.use_unsafe_extended_memory_layout.GetValue()); | ||
| 117 | |||
| 118 | if (Settings::IsConfiguringGlobal()) { | ||
| 119 | ui->combo_language->setCurrentIndex(Settings::values.language_index.GetValue()); | ||
| 120 | ui->combo_region->setCurrentIndex(Settings::values.region_index.GetValue()); | ||
| 121 | ui->combo_time_zone->setCurrentIndex(Settings::values.time_zone_index.GetValue()); | ||
| 122 | } else { | ||
| 123 | ConfigurationShared::SetPerGameSetting(ui->combo_language, | ||
| 124 | &Settings::values.language_index); | ||
| 125 | ConfigurationShared::SetPerGameSetting(ui->combo_region, &Settings::values.region_index); | ||
| 126 | ConfigurationShared::SetPerGameSetting(ui->combo_time_zone, | ||
| 127 | &Settings::values.time_zone_index); | ||
| 128 | |||
| 129 | ConfigurationShared::SetHighlight(ui->label_language, | ||
| 130 | !Settings::values.language_index.UsingGlobal()); | ||
| 131 | ConfigurationShared::SetHighlight(ui->label_region, | ||
| 132 | !Settings::values.region_index.UsingGlobal()); | ||
| 133 | ConfigurationShared::SetHighlight(ui->label_timezone, | ||
| 134 | !Settings::values.time_zone_index.UsingGlobal()); | ||
| 135 | } | ||
| 136 | } | ||
| 137 | 94 | ||
| 138 | void ConfigureSystem::ReadSystemSettings() {} | 95 | std::map<u32, QWidget*> core_hold{}; |
| 96 | std::map<u32, QWidget*> system_hold{}; | ||
| 139 | 97 | ||
| 140 | void ConfigureSystem::ApplyConfiguration() { | 98 | std::vector<Settings::BasicSetting*> settings; |
| 141 | // Allow setting custom RTC even if system is powered on, | 99 | auto push = [&settings](auto& list) { |
| 142 | // to allow in-game time to be fast forwarded | 100 | for (auto setting : list) { |
| 143 | if (Settings::IsConfiguringGlobal()) { | 101 | settings.push_back(setting); |
| 144 | if (ui->custom_rtc_checkbox->isChecked()) { | ||
| 145 | Settings::values.custom_rtc = ui->custom_rtc_edit->dateTime().toSecsSinceEpoch(); | ||
| 146 | if (system.IsPoweredOn()) { | ||
| 147 | const s64 posix_time{*Settings::values.custom_rtc}; | ||
| 148 | system.GetTimeManager().UpdateLocalSystemClockTime(posix_time); | ||
| 149 | } | ||
| 150 | } else { | ||
| 151 | Settings::values.custom_rtc = std::nullopt; | ||
| 152 | } | 102 | } |
| 153 | } | 103 | }; |
| 154 | 104 | ||
| 155 | Settings::values.device_name = ui->device_name_edit->text().toStdString(); | 105 | push(Settings::values.linkage.by_category[Settings::Category::Core]); |
| 106 | push(Settings::values.linkage.by_category[Settings::Category::System]); | ||
| 156 | 107 | ||
| 157 | if (!enabled) { | 108 | for (auto setting : settings) { |
| 158 | return; | 109 | ConfigurationShared::Widget* widget = builder.BuildWidget(setting, apply_funcs); |
| 159 | } | ||
| 160 | 110 | ||
| 161 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.language_index, ui->combo_language); | 111 | if (widget == nullptr) { |
| 162 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.region_index, ui->combo_region); | 112 | continue; |
| 163 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.time_zone_index, | ||
| 164 | ui->combo_time_zone); | ||
| 165 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_unsafe_extended_memory_layout, | ||
| 166 | ui->use_unsafe_extended_memory_layout, | ||
| 167 | use_unsafe_extended_memory_layout); | ||
| 168 | |||
| 169 | if (Settings::IsConfiguringGlobal()) { | ||
| 170 | // Guard if during game and set to game-specific value | ||
| 171 | if (Settings::values.rng_seed.UsingGlobal()) { | ||
| 172 | if (ui->rng_seed_checkbox->isChecked()) { | ||
| 173 | Settings::values.rng_seed.SetValue(ui->rng_seed_edit->text().toUInt(nullptr, 16)); | ||
| 174 | } else { | ||
| 175 | Settings::values.rng_seed.SetValue(std::nullopt); | ||
| 176 | } | ||
| 177 | } | 113 | } |
| 178 | } else { | 114 | if (!widget->Valid()) { |
| 179 | switch (use_rng_seed) { | 115 | widget->deleteLater(); |
| 180 | case ConfigurationShared::CheckState::On: | 116 | continue; |
| 181 | case ConfigurationShared::CheckState::Off: | 117 | } |
| 182 | Settings::values.rng_seed.SetGlobal(false); | 118 | |
| 183 | if (ui->rng_seed_checkbox->isChecked()) { | 119 | if (setting->Id() == Settings::values.region_index.Id()) { |
| 184 | Settings::values.rng_seed.SetValue(ui->rng_seed_edit->text().toUInt(nullptr, 16)); | 120 | // Keep track of the region_index (and langauge_index) combobox to validate the selected |
| 185 | } else { | 121 | // settings |
| 186 | Settings::values.rng_seed.SetValue(std::nullopt); | 122 | combo_region = widget->combobox; |
| 187 | } | 123 | } else if (setting->Id() == Settings::values.language_index.Id()) { |
| 188 | break; | 124 | combo_language = widget->combobox; |
| 189 | case ConfigurationShared::CheckState::Global: | 125 | } |
| 190 | Settings::values.rng_seed.SetGlobal(false); | 126 | |
| 191 | Settings::values.rng_seed.SetValue(std::nullopt); | 127 | switch (setting->GetCategory()) { |
| 192 | Settings::values.rng_seed.SetGlobal(true); | 128 | case Settings::Category::Core: |
| 129 | core_hold.emplace(setting->Id(), widget); | ||
| 193 | break; | 130 | break; |
| 194 | case ConfigurationShared::CheckState::Count: | 131 | case Settings::Category::System: |
| 132 | system_hold.emplace(setting->Id(), widget); | ||
| 195 | break; | 133 | break; |
| 134 | default: | ||
| 135 | widget->deleteLater(); | ||
| 196 | } | 136 | } |
| 197 | } | 137 | } |
| 138 | for (const auto& [label, widget] : core_hold) { | ||
| 139 | core_layout.addWidget(widget); | ||
| 140 | } | ||
| 141 | for (const auto& [id, widget] : system_hold) { | ||
| 142 | system_layout.addWidget(widget); | ||
| 143 | } | ||
| 198 | } | 144 | } |
| 199 | 145 | ||
| 200 | void ConfigureSystem::SetupPerGameUI() { | 146 | void ConfigureSystem::SetConfiguration() {} |
| 201 | if (Settings::IsConfiguringGlobal()) { | ||
| 202 | ui->combo_language->setEnabled(Settings::values.language_index.UsingGlobal()); | ||
| 203 | ui->combo_region->setEnabled(Settings::values.region_index.UsingGlobal()); | ||
| 204 | ui->combo_time_zone->setEnabled(Settings::values.time_zone_index.UsingGlobal()); | ||
| 205 | ui->rng_seed_checkbox->setEnabled(Settings::values.rng_seed.UsingGlobal()); | ||
| 206 | ui->rng_seed_edit->setEnabled(Settings::values.rng_seed.UsingGlobal()); | ||
| 207 | 147 | ||
| 208 | return; | 148 | void ConfigureSystem::ApplyConfiguration() { |
| 149 | const bool powered_on = system.IsPoweredOn(); | ||
| 150 | for (const auto& func : apply_funcs) { | ||
| 151 | func(powered_on); | ||
| 209 | } | 152 | } |
| 210 | |||
| 211 | ConfigurationShared::SetColoredComboBox(ui->combo_language, ui->label_language, | ||
| 212 | Settings::values.language_index.GetValue(true)); | ||
| 213 | ConfigurationShared::SetColoredComboBox(ui->combo_region, ui->label_region, | ||
| 214 | Settings::values.region_index.GetValue(true)); | ||
| 215 | ConfigurationShared::SetColoredComboBox(ui->combo_time_zone, ui->label_timezone, | ||
| 216 | Settings::values.time_zone_index.GetValue(true)); | ||
| 217 | |||
| 218 | ConfigurationShared::SetColoredTristate( | ||
| 219 | ui->rng_seed_checkbox, Settings::values.rng_seed.UsingGlobal(), | ||
| 220 | Settings::values.rng_seed.GetValue().has_value(), | ||
| 221 | Settings::values.rng_seed.GetValue(true).has_value(), use_rng_seed); | ||
| 222 | |||
| 223 | ConfigurationShared::SetColoredTristate(ui->use_unsafe_extended_memory_layout, | ||
| 224 | Settings::values.use_unsafe_extended_memory_layout, | ||
| 225 | use_unsafe_extended_memory_layout); | ||
| 226 | |||
| 227 | ui->custom_rtc_checkbox->setVisible(false); | ||
| 228 | ui->custom_rtc_edit->setVisible(false); | ||
| 229 | } | 153 | } |
diff --git a/src/yuzu/configuration/configure_system.h b/src/yuzu/configuration/configure_system.h index ce1a91601..eab99a48a 100644 --- a/src/yuzu/configuration/configure_system.h +++ b/src/yuzu/configuration/configure_system.h | |||
| @@ -3,45 +3,53 @@ | |||
| 3 | 3 | ||
| 4 | #pragma once | 4 | #pragma once |
| 5 | 5 | ||
| 6 | #include <functional> | ||
| 6 | #include <memory> | 7 | #include <memory> |
| 8 | #include <vector> | ||
| 7 | 9 | ||
| 8 | #include <QWidget> | 10 | #include <QWidget> |
| 11 | #include "yuzu/configuration/configuration_shared.h" | ||
| 9 | 12 | ||
| 13 | class QCheckBox; | ||
| 14 | class QLineEdit; | ||
| 15 | class QComboBox; | ||
| 16 | class QDateTimeEdit; | ||
| 10 | namespace Core { | 17 | namespace Core { |
| 11 | class System; | 18 | class System; |
| 12 | } | 19 | } |
| 13 | 20 | ||
| 14 | namespace ConfigurationShared { | ||
| 15 | enum class CheckState; | ||
| 16 | } | ||
| 17 | |||
| 18 | namespace Ui { | 21 | namespace Ui { |
| 19 | class ConfigureSystem; | 22 | class ConfigureSystem; |
| 20 | } | 23 | } |
| 21 | 24 | ||
| 22 | class ConfigureSystem : public QWidget { | 25 | namespace ConfigurationShared { |
| 23 | Q_OBJECT | 26 | class Builder; |
| 27 | } | ||
| 24 | 28 | ||
| 29 | class ConfigureSystem : public ConfigurationShared::Tab { | ||
| 25 | public: | 30 | public: |
| 26 | explicit ConfigureSystem(Core::System& system_, QWidget* parent = nullptr); | 31 | explicit ConfigureSystem(Core::System& system_, |
| 32 | std::shared_ptr<std::vector<ConfigurationShared::Tab*>> group, | ||
| 33 | const ConfigurationShared::Builder& builder, | ||
| 34 | QWidget* parent = nullptr); | ||
| 27 | ~ConfigureSystem() override; | 35 | ~ConfigureSystem() override; |
| 28 | 36 | ||
| 29 | void ApplyConfiguration(); | 37 | void ApplyConfiguration() override; |
| 30 | void SetConfiguration(); | 38 | void SetConfiguration() override; |
| 31 | 39 | ||
| 32 | private: | 40 | private: |
| 33 | void changeEvent(QEvent* event) override; | 41 | void changeEvent(QEvent* event) override; |
| 34 | void RetranslateUI(); | 42 | void RetranslateUI(); |
| 35 | 43 | ||
| 36 | void ReadSystemSettings(); | 44 | void Setup(const ConfigurationShared::Builder& builder); |
| 37 | 45 | ||
| 38 | void SetupPerGameUI(); | 46 | std::vector<std::function<void(bool)>> apply_funcs{}; |
| 39 | 47 | ||
| 40 | std::unique_ptr<Ui::ConfigureSystem> ui; | 48 | std::unique_ptr<Ui::ConfigureSystem> ui; |
| 41 | bool enabled = false; | 49 | bool enabled = false; |
| 42 | 50 | ||
| 43 | ConfigurationShared::CheckState use_rng_seed; | ||
| 44 | ConfigurationShared::CheckState use_unsafe_extended_memory_layout; | ||
| 45 | |||
| 46 | Core::System& system; | 51 | Core::System& system; |
| 52 | |||
| 53 | QComboBox* combo_region; | ||
| 54 | QComboBox* combo_language; | ||
| 47 | }; | 55 | }; |
diff --git a/src/yuzu/configuration/configure_system.ui b/src/yuzu/configuration/configure_system.ui index e0caecd5e..2a735836e 100644 --- a/src/yuzu/configuration/configure_system.ui +++ b/src/yuzu/configuration/configure_system.ui | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | <rect> | 6 | <rect> |
| 7 | <x>0</x> | 7 | <x>0</x> |
| 8 | <y>0</y> | 8 | <y>0</y> |
| 9 | <width>366</width> | 9 | <width>605</width> |
| 10 | <height>483</height> | 10 | <height>483</height> |
| 11 | </rect> | 11 | </rect> |
| 12 | </property> | 12 | </property> |
| @@ -22,470 +22,63 @@ | |||
| 22 | <item> | 22 | <item> |
| 23 | <widget class="QGroupBox" name="group_system_settings"> | 23 | <widget class="QGroupBox" name="group_system_settings"> |
| 24 | <property name="title"> | 24 | <property name="title"> |
| 25 | <string>System Settings</string> | 25 | <string>System</string> |
| 26 | </property> | 26 | </property> |
| 27 | <layout class="QVBoxLayout" name="verticalLayout_2"> | 27 | <layout class="QVBoxLayout" name="verticalLayout_2"> |
| 28 | <item> | 28 | <item> |
| 29 | <layout class="QGridLayout" name="gridLayout_2"> | 29 | <widget class="QWidget" name="system_widget" native="true"> |
| 30 | <item row="1" column="0"> | 30 | <layout class="QVBoxLayout" name="verticalLayout_3"> |
| 31 | <widget class="QLabel" name="label_region"> | 31 | <property name="leftMargin"> |
| 32 | <property name="text"> | 32 | <number>0</number> |
| 33 | <string>Region:</string> | 33 | </property> |
| 34 | </property> | 34 | <property name="topMargin"> |
| 35 | </widget> | 35 | <number>0</number> |
| 36 | </item> | 36 | </property> |
| 37 | <item row="2" column="1"> | 37 | <property name="rightMargin"> |
| 38 | <widget class="QComboBox" name="combo_time_zone"> | 38 | <number>0</number> |
| 39 | <item> | 39 | </property> |
| 40 | <property name="text"> | 40 | <property name="bottomMargin"> |
| 41 | <string>Auto</string> | 41 | <number>0</number> |
| 42 | </property> | 42 | </property> |
| 43 | </item> | 43 | </layout> |
| 44 | <item> | 44 | </widget> |
| 45 | <property name="text"> | 45 | </item> |
| 46 | <string>Default</string> | 46 | <item> |
| 47 | </property> | 47 | <widget class="QLabel" name="label_warn_invalid_locale"> |
| 48 | </item> | 48 | <property name="text"> |
| 49 | <item> | 49 | <string/> |
| 50 | <property name="text"> | 50 | </property> |
| 51 | <string>CET</string> | 51 | <property name="wordWrap"> |
| 52 | </property> | 52 | <bool>true</bool> |
| 53 | </item> | 53 | </property> |
| 54 | <item> | 54 | </widget> |
| 55 | <property name="text"> | 55 | </item> |
| 56 | <string>CST6CDT</string> | 56 | </layout> |
| 57 | </property> | 57 | </widget> |
| 58 | </item> | 58 | </item> |
| 59 | <item> | 59 | <item> |
| 60 | <property name="text"> | 60 | <widget class="QGroupBox" name="groupBox"> |
| 61 | <string>Cuba</string> | 61 | <property name="title"> |
| 62 | </property> | 62 | <string>Core</string> |
| 63 | </item> | 63 | </property> |
| 64 | <item> | 64 | <layout class="QVBoxLayout" name="verticalLayout_6"> |
| 65 | <property name="text"> | 65 | <item> |
| 66 | <string>EET</string> | 66 | <widget class="QWidget" name="core_widget" native="true"> |
| 67 | </property> | 67 | <layout class="QVBoxLayout" name="verticalLayout_5"> |
| 68 | </item> | 68 | <property name="leftMargin"> |
| 69 | <item> | 69 | <number>0</number> |
| 70 | <property name="text"> | 70 | </property> |
| 71 | <string>Egypt</string> | 71 | <property name="topMargin"> |
| 72 | </property> | 72 | <number>0</number> |
| 73 | </item> | 73 | </property> |
| 74 | <item> | 74 | <property name="rightMargin"> |
| 75 | <property name="text"> | 75 | <number>0</number> |
| 76 | <string>Eire</string> | 76 | </property> |
| 77 | </property> | 77 | <property name="bottomMargin"> |
| 78 | </item> | 78 | <number>0</number> |
| 79 | <item> | 79 | </property> |
| 80 | <property name="text"> | 80 | </layout> |
| 81 | <string>EST</string> | 81 | </widget> |
| 82 | </property> | ||
| 83 | </item> | ||
| 84 | <item> | ||
| 85 | <property name="text"> | ||
| 86 | <string>EST5EDT</string> | ||
| 87 | </property> | ||
| 88 | </item> | ||
| 89 | <item> | ||
| 90 | <property name="text"> | ||
| 91 | <string>GB</string> | ||
| 92 | </property> | ||
| 93 | </item> | ||
| 94 | <item> | ||
| 95 | <property name="text"> | ||
| 96 | <string>GB-Eire</string> | ||
| 97 | </property> | ||
| 98 | </item> | ||
| 99 | <item> | ||
| 100 | <property name="text"> | ||
| 101 | <string>GMT</string> | ||
| 102 | </property> | ||
| 103 | </item> | ||
| 104 | <item> | ||
| 105 | <property name="text"> | ||
| 106 | <string>GMT+0</string> | ||
| 107 | </property> | ||
| 108 | </item> | ||
| 109 | <item> | ||
| 110 | <property name="text"> | ||
| 111 | <string>GMT-0</string> | ||
| 112 | </property> | ||
| 113 | </item> | ||
| 114 | <item> | ||
| 115 | <property name="text"> | ||
| 116 | <string>GMT0</string> | ||
| 117 | </property> | ||
| 118 | </item> | ||
| 119 | <item> | ||
| 120 | <property name="text"> | ||
| 121 | <string>Greenwich</string> | ||
| 122 | </property> | ||
| 123 | </item> | ||
| 124 | <item> | ||
| 125 | <property name="text"> | ||
| 126 | <string>Hongkong</string> | ||
| 127 | </property> | ||
| 128 | </item> | ||
| 129 | <item> | ||
| 130 | <property name="text"> | ||
| 131 | <string>HST</string> | ||
| 132 | </property> | ||
| 133 | </item> | ||
| 134 | <item> | ||
| 135 | <property name="text"> | ||
| 136 | <string>Iceland</string> | ||
| 137 | </property> | ||
| 138 | </item> | ||
| 139 | <item> | ||
| 140 | <property name="text"> | ||
| 141 | <string>Iran</string> | ||
| 142 | </property> | ||
| 143 | </item> | ||
| 144 | <item> | ||
| 145 | <property name="text"> | ||
| 146 | <string>Israel</string> | ||
| 147 | </property> | ||
| 148 | </item> | ||
| 149 | <item> | ||
| 150 | <property name="text"> | ||
| 151 | <string>Jamaica</string> | ||
| 152 | </property> | ||
| 153 | </item> | ||
| 154 | <item> | ||
| 155 | <property name="text"> | ||
| 156 | <string>Japan</string> | ||
| 157 | </property> | ||
| 158 | </item> | ||
| 159 | <item> | ||
| 160 | <property name="text"> | ||
| 161 | <string>Kwajalein</string> | ||
| 162 | </property> | ||
| 163 | </item> | ||
| 164 | <item> | ||
| 165 | <property name="text"> | ||
| 166 | <string>Libya</string> | ||
| 167 | </property> | ||
| 168 | </item> | ||
| 169 | <item> | ||
| 170 | <property name="text"> | ||
| 171 | <string>MET</string> | ||
| 172 | </property> | ||
| 173 | </item> | ||
| 174 | <item> | ||
| 175 | <property name="text"> | ||
| 176 | <string>MST</string> | ||
| 177 | </property> | ||
| 178 | </item> | ||
| 179 | <item> | ||
| 180 | <property name="text"> | ||
| 181 | <string>MST7MDT</string> | ||
| 182 | </property> | ||
| 183 | </item> | ||
| 184 | <item> | ||
| 185 | <property name="text"> | ||
| 186 | <string>Navajo</string> | ||
| 187 | </property> | ||
| 188 | </item> | ||
| 189 | <item> | ||
| 190 | <property name="text"> | ||
| 191 | <string>NZ</string> | ||
| 192 | </property> | ||
| 193 | </item> | ||
| 194 | <item> | ||
| 195 | <property name="text"> | ||
| 196 | <string>NZ-CHAT</string> | ||
| 197 | </property> | ||
| 198 | </item> | ||
| 199 | <item> | ||
| 200 | <property name="text"> | ||
| 201 | <string>Poland</string> | ||
| 202 | </property> | ||
| 203 | </item> | ||
| 204 | <item> | ||
| 205 | <property name="text"> | ||
| 206 | <string>Portugal</string> | ||
| 207 | </property> | ||
| 208 | </item> | ||
| 209 | <item> | ||
| 210 | <property name="text"> | ||
| 211 | <string>PRC</string> | ||
| 212 | </property> | ||
| 213 | </item> | ||
| 214 | <item> | ||
| 215 | <property name="text"> | ||
| 216 | <string>PST8PDT</string> | ||
| 217 | </property> | ||
| 218 | </item> | ||
| 219 | <item> | ||
| 220 | <property name="text"> | ||
| 221 | <string>ROC</string> | ||
| 222 | </property> | ||
| 223 | </item> | ||
| 224 | <item> | ||
| 225 | <property name="text"> | ||
| 226 | <string>ROK</string> | ||
| 227 | </property> | ||
| 228 | </item> | ||
| 229 | <item> | ||
| 230 | <property name="text"> | ||
| 231 | <string>Singapore</string> | ||
| 232 | </property> | ||
| 233 | </item> | ||
| 234 | <item> | ||
| 235 | <property name="text"> | ||
| 236 | <string>Turkey</string> | ||
| 237 | </property> | ||
| 238 | </item> | ||
| 239 | <item> | ||
| 240 | <property name="text"> | ||
| 241 | <string>UCT</string> | ||
| 242 | </property> | ||
| 243 | </item> | ||
| 244 | <item> | ||
| 245 | <property name="text"> | ||
| 246 | <string>Universal</string> | ||
| 247 | </property> | ||
| 248 | </item> | ||
| 249 | <item> | ||
| 250 | <property name="text"> | ||
| 251 | <string>UTC</string> | ||
| 252 | </property> | ||
| 253 | </item> | ||
| 254 | <item> | ||
| 255 | <property name="text"> | ||
| 256 | <string>W-SU</string> | ||
| 257 | </property> | ||
| 258 | </item> | ||
| 259 | <item> | ||
| 260 | <property name="text"> | ||
| 261 | <string>WET</string> | ||
| 262 | </property> | ||
| 263 | </item> | ||
| 264 | <item> | ||
| 265 | <property name="text"> | ||
| 266 | <string>Zulu</string> | ||
| 267 | </property> | ||
| 268 | </item> | ||
| 269 | </widget> | ||
| 270 | </item> | ||
| 271 | <item row="1" column="1"> | ||
| 272 | <widget class="QComboBox" name="combo_region"> | ||
| 273 | <item> | ||
| 274 | <property name="text"> | ||
| 275 | <string>Japan</string> | ||
| 276 | </property> | ||
| 277 | </item> | ||
| 278 | <item> | ||
| 279 | <property name="text"> | ||
| 280 | <string>USA</string> | ||
| 281 | </property> | ||
| 282 | </item> | ||
| 283 | <item> | ||
| 284 | <property name="text"> | ||
| 285 | <string>Europe</string> | ||
| 286 | </property> | ||
| 287 | </item> | ||
| 288 | <item> | ||
| 289 | <property name="text"> | ||
| 290 | <string>Australia</string> | ||
| 291 | </property> | ||
| 292 | </item> | ||
| 293 | <item> | ||
| 294 | <property name="text"> | ||
| 295 | <string>China</string> | ||
| 296 | </property> | ||
| 297 | </item> | ||
| 298 | <item> | ||
| 299 | <property name="text"> | ||
| 300 | <string>Korea</string> | ||
| 301 | </property> | ||
| 302 | </item> | ||
| 303 | <item> | ||
| 304 | <property name="text"> | ||
| 305 | <string>Taiwan</string> | ||
| 306 | </property> | ||
| 307 | </item> | ||
| 308 | </widget> | ||
| 309 | </item> | ||
| 310 | <item row="2" column="0"> | ||
| 311 | <widget class="QLabel" name="label_timezone"> | ||
| 312 | <property name="text"> | ||
| 313 | <string>Time Zone:</string> | ||
| 314 | </property> | ||
| 315 | </widget> | ||
| 316 | </item> | ||
| 317 | <item row="0" column="1"> | ||
| 318 | <widget class="QComboBox" name="combo_language"> | ||
| 319 | <property name="toolTip"> | ||
| 320 | <string>Note: this can be overridden when region setting is auto-select</string> | ||
| 321 | </property> | ||
| 322 | <item> | ||
| 323 | <property name="text"> | ||
| 324 | <string>Japanese (日本語)</string> | ||
| 325 | </property> | ||
| 326 | </item> | ||
| 327 | <item> | ||
| 328 | <property name="text"> | ||
| 329 | <string>American English</string> | ||
| 330 | </property> | ||
| 331 | </item> | ||
| 332 | <item> | ||
| 333 | <property name="text"> | ||
| 334 | <string>French (français)</string> | ||
| 335 | </property> | ||
| 336 | </item> | ||
| 337 | <item> | ||
| 338 | <property name="text"> | ||
| 339 | <string>German (Deutsch)</string> | ||
| 340 | </property> | ||
| 341 | </item> | ||
| 342 | <item> | ||
| 343 | <property name="text"> | ||
| 344 | <string>Italian (italiano)</string> | ||
| 345 | </property> | ||
| 346 | </item> | ||
| 347 | <item> | ||
| 348 | <property name="text"> | ||
| 349 | <string>Spanish (español)</string> | ||
| 350 | </property> | ||
| 351 | </item> | ||
| 352 | <item> | ||
| 353 | <property name="text"> | ||
| 354 | <string>Chinese</string> | ||
| 355 | </property> | ||
| 356 | </item> | ||
| 357 | <item> | ||
| 358 | <property name="text"> | ||
| 359 | <string>Korean (한국어)</string> | ||
| 360 | </property> | ||
| 361 | </item> | ||
| 362 | <item> | ||
| 363 | <property name="text"> | ||
| 364 | <string>Dutch (Nederlands)</string> | ||
| 365 | </property> | ||
| 366 | </item> | ||
| 367 | <item> | ||
| 368 | <property name="text"> | ||
| 369 | <string>Portuguese (português)</string> | ||
| 370 | </property> | ||
| 371 | </item> | ||
| 372 | <item> | ||
| 373 | <property name="text"> | ||
| 374 | <string>Russian (Русский)</string> | ||
| 375 | </property> | ||
| 376 | </item> | ||
| 377 | <item> | ||
| 378 | <property name="text"> | ||
| 379 | <string>Taiwanese</string> | ||
| 380 | </property> | ||
| 381 | </item> | ||
| 382 | <item> | ||
| 383 | <property name="text"> | ||
| 384 | <string>British English</string> | ||
| 385 | </property> | ||
| 386 | </item> | ||
| 387 | <item> | ||
| 388 | <property name="text"> | ||
| 389 | <string>Canadian French</string> | ||
| 390 | </property> | ||
| 391 | </item> | ||
| 392 | <item> | ||
| 393 | <property name="text"> | ||
| 394 | <string>Latin American Spanish</string> | ||
| 395 | </property> | ||
| 396 | </item> | ||
| 397 | <item> | ||
| 398 | <property name="text"> | ||
| 399 | <string>Simplified Chinese</string> | ||
| 400 | </property> | ||
| 401 | </item> | ||
| 402 | <item> | ||
| 403 | <property name="text"> | ||
| 404 | <string>Traditional Chinese (正體中文)</string> | ||
| 405 | </property> | ||
| 406 | </item> | ||
| 407 | <item> | ||
| 408 | <property name="text"> | ||
| 409 | <string>Brazilian Portuguese (português do Brasil)</string> | ||
| 410 | </property> | ||
| 411 | </item> | ||
| 412 | </widget> | ||
| 413 | </item> | ||
| 414 | <item row="4" column="0"> | ||
| 415 | <widget class="QCheckBox" name="custom_rtc_checkbox"> | ||
| 416 | <property name="text"> | ||
| 417 | <string>Custom RTC</string> | ||
| 418 | </property> | ||
| 419 | </widget> | ||
| 420 | </item> | ||
| 421 | <item row="0" column="0"> | ||
| 422 | <widget class="QLabel" name="label_language"> | ||
| 423 | <property name="text"> | ||
| 424 | <string>Language</string> | ||
| 425 | </property> | ||
| 426 | </widget> | ||
| 427 | </item> | ||
| 428 | <item row="5" column="0"> | ||
| 429 | <widget class="QCheckBox" name="rng_seed_checkbox"> | ||
| 430 | <property name="text"> | ||
| 431 | <string>RNG Seed</string> | ||
| 432 | </property> | ||
| 433 | </widget> | ||
| 434 | </item> | ||
| 435 | <item row="6" column="0"> | ||
| 436 | <widget class="QLabel" name="device_name_label"> | ||
| 437 | <property name="text"> | ||
| 438 | <string>Device Name</string> | ||
| 439 | </property> | ||
| 440 | </widget> | ||
| 441 | </item> | ||
| 442 | <item row="4" column="1"> | ||
| 443 | <widget class="QDateTimeEdit" name="custom_rtc_edit"> | ||
| 444 | <property name="minimumDate"> | ||
| 445 | <date> | ||
| 446 | <year>1970</year> | ||
| 447 | <month>1</month> | ||
| 448 | <day>1</day> | ||
| 449 | </date> | ||
| 450 | </property> | ||
| 451 | </widget> | ||
| 452 | </item> | ||
| 453 | <item row="6" column="1"> | ||
| 454 | <widget class="QLineEdit" name="device_name_edit"> | ||
| 455 | <property name="maxLength"> | ||
| 456 | <number>128</number> | ||
| 457 | </property> | ||
| 458 | </widget> | ||
| 459 | </item> | ||
| 460 | <item row="5" column="1"> | ||
| 461 | <widget class="QLineEdit" name="rng_seed_edit"> | ||
| 462 | <property name="sizePolicy"> | ||
| 463 | <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> | ||
| 464 | <horstretch>0</horstretch> | ||
| 465 | <verstretch>0</verstretch> | ||
| 466 | </sizepolicy> | ||
| 467 | </property> | ||
| 468 | <property name="font"> | ||
| 469 | <font> | ||
| 470 | <family>Lucida Console</family> | ||
| 471 | </font> | ||
| 472 | </property> | ||
| 473 | <property name="inputMask"> | ||
| 474 | <string notr="true">HHHHHHHH</string> | ||
| 475 | </property> | ||
| 476 | <property name="maxLength"> | ||
| 477 | <number>8</number> | ||
| 478 | </property> | ||
| 479 | </widget> | ||
| 480 | </item> | ||
| 481 | <item row="7" column="0"> | ||
| 482 | <widget class="QCheckBox" name="use_unsafe_extended_memory_layout"> | ||
| 483 | <property name="text"> | ||
| 484 | <string>Unsafe extended memory layout (8GB DRAM)</string> | ||
| 485 | </property> | ||
| 486 | </widget> | ||
| 487 | </item> | ||
| 488 | </layout> | ||
| 489 | </item> | 82 | </item> |
| 490 | </layout> | 83 | </layout> |
| 491 | </widget> | 84 | </widget> |
| @@ -503,26 +96,6 @@ | |||
| 503 | </property> | 96 | </property> |
| 504 | </spacer> | 97 | </spacer> |
| 505 | </item> | 98 | </item> |
| 506 | <item> | ||
| 507 | <widget class="QLabel" name="label_warn_invalid_locale"> | ||
| 508 | <property name="text"> | ||
| 509 | <string></string> | ||
| 510 | </property> | ||
| 511 | <property name="wordWrap"> | ||
| 512 | <bool>true</bool> | ||
| 513 | </property> | ||
| 514 | </widget> | ||
| 515 | </item> | ||
| 516 | <item> | ||
| 517 | <widget class="QLabel" name="label_disable_info"> | ||
| 518 | <property name="text"> | ||
| 519 | <string>System settings are available only when game is not running.</string> | ||
| 520 | </property> | ||
| 521 | <property name="wordWrap"> | ||
| 522 | <bool>true</bool> | ||
| 523 | </property> | ||
| 524 | </widget> | ||
| 525 | </item> | ||
| 526 | </layout> | 99 | </layout> |
| 527 | </item> | 100 | </item> |
| 528 | </layout> | 101 | </layout> |
diff --git a/src/yuzu/configuration/shared_translation.cpp b/src/yuzu/configuration/shared_translation.cpp new file mode 100644 index 000000000..335810788 --- /dev/null +++ b/src/yuzu/configuration/shared_translation.cpp | |||
| @@ -0,0 +1,388 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "common/time_zone.h" | ||
| 5 | #include "yuzu/configuration/shared_translation.h" | ||
| 6 | |||
| 7 | #include <map> | ||
| 8 | #include <memory> | ||
| 9 | #include <tuple> | ||
| 10 | #include <utility> | ||
| 11 | #include <QWidget> | ||
| 12 | #include "common/settings.h" | ||
| 13 | #include "common/settings_enums.h" | ||
| 14 | #include "common/settings_setting.h" | ||
| 15 | #include "yuzu/uisettings.h" | ||
| 16 | |||
| 17 | namespace ConfigurationShared { | ||
| 18 | |||
| 19 | std::unique_ptr<TranslationMap> InitializeTranslations(QWidget* parent) { | ||
| 20 | std::unique_ptr<TranslationMap> translations = std::make_unique<TranslationMap>(); | ||
| 21 | const auto& tr = [parent](const char* text) -> QString { return parent->tr(text); }; | ||
| 22 | |||
| 23 | #define INSERT(SETTINGS, ID, NAME, TOOLTIP) \ | ||
| 24 | translations->insert(std::pair{SETTINGS::values.ID.Id(), std::pair{tr((NAME)), tr((TOOLTIP))}}) | ||
| 25 | |||
| 26 | // A setting can be ignored by giving it a blank name | ||
| 27 | |||
| 28 | // Audio | ||
| 29 | INSERT(Settings, sink_id, "Output Engine:", ""); | ||
| 30 | INSERT(Settings, audio_output_device_id, "Output Device:", ""); | ||
| 31 | INSERT(Settings, audio_input_device_id, "Input Device:", ""); | ||
| 32 | INSERT(Settings, audio_muted, "Mute audio when in background", ""); | ||
| 33 | INSERT(Settings, volume, "Volume:", ""); | ||
| 34 | INSERT(Settings, dump_audio_commands, "", ""); | ||
| 35 | |||
| 36 | // Core | ||
| 37 | INSERT(Settings, use_multi_core, "Multicore CPU Emulation", ""); | ||
| 38 | INSERT(Settings, memory_layout_mode, "Memory Layout", ""); | ||
| 39 | INSERT(Settings, use_speed_limit, "", ""); | ||
| 40 | INSERT(Settings, speed_limit, "Limit Speed Percent", ""); | ||
| 41 | |||
| 42 | // Cpu | ||
| 43 | INSERT(Settings, cpu_accuracy, "Accuracy:", ""); | ||
| 44 | |||
| 45 | // Cpu Debug | ||
| 46 | |||
| 47 | // Cpu Unsafe | ||
| 48 | INSERT(Settings, cpuopt_unsafe_unfuse_fma, | ||
| 49 | "Unfuse FMA (improve performance on CPUs without FMA)", | ||
| 50 | "This option improves speed by reducing accuracy of fused-multiply-add instructions on " | ||
| 51 | "CPUs without native FMA support."); | ||
| 52 | INSERT(Settings, cpuopt_unsafe_reduce_fp_error, "Faster FRSQRTE and FRECPE", | ||
| 53 | "This option improves the speed of some approximate floating-point functions by using " | ||
| 54 | "less accurate native approximations."); | ||
| 55 | INSERT(Settings, cpuopt_unsafe_ignore_standard_fpcr, "Faster ASIMD instructions (32 bits only)", | ||
| 56 | "This option improves the speed of 32 bits ASIMD floating-point functions by running " | ||
| 57 | "with incorrect rounding modes."); | ||
| 58 | INSERT(Settings, cpuopt_unsafe_inaccurate_nan, "Inaccurate NaN handling", | ||
| 59 | "This option improves speed by removing NaN checking. Please note this also reduces " | ||
| 60 | "accuracy of certain floating-point instructions."); | ||
| 61 | INSERT( | ||
| 62 | Settings, cpuopt_unsafe_fastmem_check, "Disable address space checks", | ||
| 63 | "This option improves speed by eliminating a safety check before every memory read/write " | ||
| 64 | "in guest. Disabling it may allow a game to read/write the emulator's memory."); | ||
| 65 | INSERT(Settings, cpuopt_unsafe_ignore_global_monitor, "Ignore global monitor", | ||
| 66 | "This option improves speed by relying only on the semantics of cmpxchg to ensure " | ||
| 67 | "safety of exclusive access instructions. Please note this may result in deadlocks and " | ||
| 68 | "other race conditions."); | ||
| 69 | |||
| 70 | // Renderer | ||
| 71 | INSERT(Settings, renderer_backend, "API:", ""); | ||
| 72 | INSERT(Settings, vulkan_device, "Device:", ""); | ||
| 73 | INSERT(Settings, shader_backend, "Shader Backend:", ""); | ||
| 74 | INSERT(Settings, resolution_setup, "Resolution:", ""); | ||
| 75 | INSERT(Settings, scaling_filter, "Window Adapting Filter:", ""); | ||
| 76 | INSERT(Settings, fsr_sharpening_slider, "FSR Sharpness:", ""); | ||
| 77 | INSERT(Settings, anti_aliasing, "Anti-Aliasing Method:", ""); | ||
| 78 | INSERT(Settings, fullscreen_mode, "Fullscreen Mode:", ""); | ||
| 79 | INSERT(Settings, aspect_ratio, "Aspect Ratio:", ""); | ||
| 80 | INSERT(Settings, use_disk_shader_cache, "Use disk pipeline cache", ""); | ||
| 81 | INSERT(Settings, use_asynchronous_gpu_emulation, "Use asynchronous GPU emulation", ""); | ||
| 82 | INSERT(Settings, nvdec_emulation, "NVDEC emulation:", ""); | ||
| 83 | INSERT(Settings, accelerate_astc, "ASTC Decoding Method:", ""); | ||
| 84 | INSERT(Settings, astc_recompression, "ASTC Recompression Method:", ""); | ||
| 85 | INSERT(Settings, vsync_mode, "VSync Mode:", | ||
| 86 | "FIFO (VSync) does not drop frames or exhibit tearing but is limited by the screen " | ||
| 87 | "refresh rate.\nFIFO Relaxed is similar to FIFO but allows tearing as it recovers from " | ||
| 88 | "a slow down.\nMailbox can have lower latency than FIFO and does not tear but may drop " | ||
| 89 | "frames.\nImmediate (no synchronization) just presents whatever is available and can " | ||
| 90 | "exhibit tearing."); | ||
| 91 | INSERT(Settings, bg_red, "", ""); | ||
| 92 | INSERT(Settings, bg_green, "", ""); | ||
| 93 | INSERT(Settings, bg_blue, "", ""); | ||
| 94 | |||
| 95 | // Renderer (Advanced Graphics) | ||
| 96 | INSERT(Settings, async_presentation, "Enable asynchronous presentation (Vulkan only)", ""); | ||
| 97 | INSERT(Settings, renderer_force_max_clock, "Force maximum clocks (Vulkan only)", | ||
| 98 | "Runs work in the background while waiting for graphics commands to keep the GPU from " | ||
| 99 | "lowering its clock speed."); | ||
| 100 | INSERT(Settings, max_anisotropy, "Anisotropic Filtering:", ""); | ||
| 101 | INSERT(Settings, gpu_accuracy, "Accuracy Level:", ""); | ||
| 102 | INSERT(Settings, use_asynchronous_shaders, "Use asynchronous shader building (Hack)", | ||
| 103 | "Enables asynchronous shader compilation, which may reduce shader stutter. This feature " | ||
| 104 | "is experimental."); | ||
| 105 | INSERT(Settings, use_fast_gpu_time, "Use Fast GPU Time (Hack)", | ||
| 106 | "Enables Fast GPU Time. This option will force most games to run at their highest " | ||
| 107 | "native resolution."); | ||
| 108 | INSERT(Settings, use_vulkan_driver_pipeline_cache, "Use Vulkan pipeline cache", | ||
| 109 | "Enables GPU vendor-specific pipeline cache. This option can improve shader loading " | ||
| 110 | "time significantly in cases where the Vulkan driver does not store pipeline cache " | ||
| 111 | "files internally."); | ||
| 112 | INSERT(Settings, enable_compute_pipelines, "Enable Compute Pipelines (Intel Vulkan Only)", | ||
| 113 | "Enable compute pipelines, required by some games.\nThis setting only exists for Intel " | ||
| 114 | "proprietary drivers, and may crash if enabled.\nCompute pipelines are always enabled " | ||
| 115 | "on all other drivers."); | ||
| 116 | INSERT(Settings, use_reactive_flushing, "Enable Reactive Flushing", | ||
| 117 | "Uses reactive flushing instead of predictive flushing, allowing more accurate memory " | ||
| 118 | "syncing."); | ||
| 119 | INSERT(Settings, use_video_framerate, "Sync to framerate of video playback", | ||
| 120 | "Run the game at normal speed during video playback, even when the framerate is " | ||
| 121 | "unlocked."); | ||
| 122 | INSERT(Settings, barrier_feedback_loops, "Barrier feedback loops", | ||
| 123 | "Improves rendering of transparency effects in specific games."); | ||
| 124 | |||
| 125 | // Renderer (Debug) | ||
| 126 | |||
| 127 | // System | ||
| 128 | INSERT(Settings, rng_seed, "RNG Seed", ""); | ||
| 129 | INSERT(Settings, rng_seed_enabled, "", ""); | ||
| 130 | INSERT(Settings, device_name, "Device Name", ""); | ||
| 131 | INSERT(Settings, custom_rtc, "Custom RTC", ""); | ||
| 132 | INSERT(Settings, custom_rtc_enabled, "", ""); | ||
| 133 | INSERT(Settings, language_index, | ||
| 134 | "Language:", "Note: this can be overridden when region setting is auto-select"); | ||
| 135 | INSERT(Settings, region_index, "Region:", ""); | ||
| 136 | INSERT(Settings, time_zone_index, "Time Zone:", ""); | ||
| 137 | INSERT(Settings, sound_index, "Sound Output Mode:", ""); | ||
| 138 | INSERT(Settings, use_docked_mode, "", ""); | ||
| 139 | INSERT(Settings, current_user, "", ""); | ||
| 140 | |||
| 141 | // Controls | ||
| 142 | |||
| 143 | // Data Storage | ||
| 144 | |||
| 145 | // Debugging | ||
| 146 | |||
| 147 | // Debugging Graphics | ||
| 148 | |||
| 149 | // Network | ||
| 150 | |||
| 151 | // Web Service | ||
| 152 | |||
| 153 | // Ui | ||
| 154 | |||
| 155 | // Ui General | ||
| 156 | INSERT(UISettings, select_user_on_boot, "Prompt for user on game boot", ""); | ||
| 157 | INSERT(UISettings, pause_when_in_background, "Pause emulation when in background", ""); | ||
| 158 | INSERT(UISettings, confirm_before_closing, "Confirm exit while emulation is running", ""); | ||
| 159 | INSERT(UISettings, hide_mouse, "Hide mouse on inactivity", ""); | ||
| 160 | INSERT(UISettings, controller_applet_disabled, "Disable controller applet", ""); | ||
| 161 | |||
| 162 | // Ui Debugging | ||
| 163 | |||
| 164 | // Ui Multiplayer | ||
| 165 | |||
| 166 | // Ui Games list | ||
| 167 | |||
| 168 | #undef INSERT | ||
| 169 | |||
| 170 | return translations; | ||
| 171 | } | ||
| 172 | |||
| 173 | std::unique_ptr<ComboboxTranslationMap> ComboboxEnumeration(QWidget* parent) { | ||
| 174 | std::unique_ptr<ComboboxTranslationMap> translations = | ||
| 175 | std::make_unique<ComboboxTranslationMap>(); | ||
| 176 | const auto& tr = [&](const char* text, const char* context = "") { | ||
| 177 | return parent->tr(text, context); | ||
| 178 | }; | ||
| 179 | |||
| 180 | #define PAIR(ENUM, VALUE, TRANSLATION) \ | ||
| 181 | { static_cast<u32>(Settings::ENUM::VALUE), tr(TRANSLATION) } | ||
| 182 | #define CTX_PAIR(ENUM, VALUE, TRANSLATION, CONTEXT) \ | ||
| 183 | { static_cast<u32>(Settings::ENUM::VALUE), tr(TRANSLATION, CONTEXT) } | ||
| 184 | |||
| 185 | // Intentionally skipping VSyncMode to let the UI fill that one out | ||
| 186 | |||
| 187 | translations->insert({Settings::EnumMetadata<Settings::AstcDecodeMode>::Index(), | ||
| 188 | { | ||
| 189 | PAIR(AstcDecodeMode, Cpu, "CPU"), | ||
| 190 | PAIR(AstcDecodeMode, Gpu, "GPU"), | ||
| 191 | PAIR(AstcDecodeMode, CpuAsynchronous, "CPU Asynchronous"), | ||
| 192 | }}); | ||
| 193 | translations->insert({Settings::EnumMetadata<Settings::AstcRecompression>::Index(), | ||
| 194 | { | ||
| 195 | PAIR(AstcRecompression, Uncompressed, "Uncompressed (Best quality)"), | ||
| 196 | PAIR(AstcRecompression, Bc1, "BC1 (Low quality)"), | ||
| 197 | PAIR(AstcRecompression, Bc3, "BC3 (Medium quality)"), | ||
| 198 | }}); | ||
| 199 | translations->insert({Settings::EnumMetadata<Settings::RendererBackend>::Index(), | ||
| 200 | { | ||
| 201 | #ifdef HAS_OPENGL | ||
| 202 | PAIR(RendererBackend, OpenGL, "OpenGL"), | ||
| 203 | #endif | ||
| 204 | PAIR(RendererBackend, Vulkan, "Vulkan"), | ||
| 205 | PAIR(RendererBackend, Null, "Null"), | ||
| 206 | }}); | ||
| 207 | translations->insert({Settings::EnumMetadata<Settings::ShaderBackend>::Index(), | ||
| 208 | { | ||
| 209 | PAIR(ShaderBackend, Glsl, "GLSL"), | ||
| 210 | PAIR(ShaderBackend, Glasm, "GLASM (Assembly Shaders, NVIDIA Only)"), | ||
| 211 | PAIR(ShaderBackend, SpirV, "SPIR-V (Experimental, Mesa Only)"), | ||
| 212 | }}); | ||
| 213 | translations->insert({Settings::EnumMetadata<Settings::GpuAccuracy>::Index(), | ||
| 214 | { | ||
| 215 | PAIR(GpuAccuracy, Normal, "Normal"), | ||
| 216 | PAIR(GpuAccuracy, High, "High"), | ||
| 217 | PAIR(GpuAccuracy, Extreme, "Extreme"), | ||
| 218 | }}); | ||
| 219 | translations->insert({Settings::EnumMetadata<Settings::CpuAccuracy>::Index(), | ||
| 220 | { | ||
| 221 | PAIR(CpuAccuracy, Auto, "Auto"), | ||
| 222 | PAIR(CpuAccuracy, Accurate, "Accurate"), | ||
| 223 | PAIR(CpuAccuracy, Unsafe, "Unsafe"), | ||
| 224 | PAIR(CpuAccuracy, Paranoid, "Paranoid (disables most optimizations)"), | ||
| 225 | }}); | ||
| 226 | translations->insert({Settings::EnumMetadata<Settings::FullscreenMode>::Index(), | ||
| 227 | { | ||
| 228 | PAIR(FullscreenMode, Borderless, "Borderless Windowed"), | ||
| 229 | PAIR(FullscreenMode, Exclusive, "Exclusive Fullscreen"), | ||
| 230 | }}); | ||
| 231 | translations->insert({Settings::EnumMetadata<Settings::NvdecEmulation>::Index(), | ||
| 232 | { | ||
| 233 | PAIR(NvdecEmulation, Off, "No Video Output"), | ||
| 234 | PAIR(NvdecEmulation, Cpu, "CPU Video Decoding"), | ||
| 235 | PAIR(NvdecEmulation, Gpu, "GPU Video Decoding (Default)"), | ||
| 236 | }}); | ||
| 237 | translations->insert({Settings::EnumMetadata<Settings::ResolutionSetup>::Index(), | ||
| 238 | { | ||
| 239 | PAIR(ResolutionSetup, Res1_2X, "0.5X (360p/540p) [EXPERIMENTAL]"), | ||
| 240 | PAIR(ResolutionSetup, Res3_4X, "0.75X (540p/810p) [EXPERIMENTAL]"), | ||
| 241 | PAIR(ResolutionSetup, Res1X, "1X (720p/1080p)"), | ||
| 242 | PAIR(ResolutionSetup, Res3_2X, "1.5X (1080p/1620p) [EXPERIMENTAL]"), | ||
| 243 | PAIR(ResolutionSetup, Res2X, "2X (1440p/2160p)"), | ||
| 244 | PAIR(ResolutionSetup, Res3X, "3X (2160p/3240p)"), | ||
| 245 | PAIR(ResolutionSetup, Res4X, "4X (2880p/4320p)"), | ||
| 246 | PAIR(ResolutionSetup, Res5X, "5X (3600p/5400p)"), | ||
| 247 | PAIR(ResolutionSetup, Res6X, "6X (4320p/6480p)"), | ||
| 248 | PAIR(ResolutionSetup, Res7X, "7X (5040p/7560p)"), | ||
| 249 | PAIR(ResolutionSetup, Res8X, "8X (5760p/8640p)"), | ||
| 250 | }}); | ||
| 251 | translations->insert({Settings::EnumMetadata<Settings::ScalingFilter>::Index(), | ||
| 252 | { | ||
| 253 | PAIR(ScalingFilter, NearestNeighbor, "Nearest Neighbor"), | ||
| 254 | PAIR(ScalingFilter, Bilinear, "Bilinear"), | ||
| 255 | PAIR(ScalingFilter, Bicubic, "Bicubic"), | ||
| 256 | PAIR(ScalingFilter, Gaussian, "Gaussian"), | ||
| 257 | PAIR(ScalingFilter, ScaleForce, "ScaleForce"), | ||
| 258 | PAIR(ScalingFilter, Fsr, "AMD FidelityFX™️ Super Resolution"), | ||
| 259 | }}); | ||
| 260 | translations->insert({Settings::EnumMetadata<Settings::AntiAliasing>::Index(), | ||
| 261 | { | ||
| 262 | PAIR(AntiAliasing, None, "None"), | ||
| 263 | PAIR(AntiAliasing, Fxaa, "FXAA"), | ||
| 264 | PAIR(AntiAliasing, Smaa, "SMAA"), | ||
| 265 | }}); | ||
| 266 | translations->insert({Settings::EnumMetadata<Settings::AspectRatio>::Index(), | ||
| 267 | { | ||
| 268 | PAIR(AspectRatio, R16_9, "Default (16:9)"), | ||
| 269 | PAIR(AspectRatio, R4_3, "Force 4:3"), | ||
| 270 | PAIR(AspectRatio, R21_9, "Force 21:9"), | ||
| 271 | PAIR(AspectRatio, R16_10, "Force 16:10"), | ||
| 272 | PAIR(AspectRatio, Stretch, "Stretch to Window"), | ||
| 273 | }}); | ||
| 274 | translations->insert({Settings::EnumMetadata<Settings::AnisotropyMode>::Index(), | ||
| 275 | { | ||
| 276 | PAIR(AnisotropyMode, Automatic, "Automatic"), | ||
| 277 | PAIR(AnisotropyMode, Default, "Default"), | ||
| 278 | PAIR(AnisotropyMode, X2, "2x"), | ||
| 279 | PAIR(AnisotropyMode, X4, "4x"), | ||
| 280 | PAIR(AnisotropyMode, X8, "8x"), | ||
| 281 | PAIR(AnisotropyMode, X16, "16x"), | ||
| 282 | }}); | ||
| 283 | translations->insert( | ||
| 284 | {Settings::EnumMetadata<Settings::Language>::Index(), | ||
| 285 | { | ||
| 286 | PAIR(Language, Japanese, "Japanese (日本語)"), | ||
| 287 | PAIR(Language, EnglishAmerican, "American English"), | ||
| 288 | PAIR(Language, French, "French (français)"), | ||
| 289 | PAIR(Language, German, "German (Deutsch)"), | ||
| 290 | PAIR(Language, Italian, "Italian (italiano)"), | ||
| 291 | PAIR(Language, Spanish, "Spanish (español)"), | ||
| 292 | PAIR(Language, Chinese, "Chinese"), | ||
| 293 | PAIR(Language, Korean, "Korean (한국어)"), | ||
| 294 | PAIR(Language, Dutch, "Dutch (Nederlands)"), | ||
| 295 | PAIR(Language, Portuguese, "Portuguese (português)"), | ||
| 296 | PAIR(Language, Russian, "Russian (Русский)"), | ||
| 297 | PAIR(Language, Taiwanese, "Taiwanese"), | ||
| 298 | PAIR(Language, EnglishBritish, "British English"), | ||
| 299 | PAIR(Language, FrenchCanadian, "Canadian French"), | ||
| 300 | PAIR(Language, SpanishLatin, "Latin American Spanish"), | ||
| 301 | PAIR(Language, ChineseSimplified, "Simplified Chinese"), | ||
| 302 | PAIR(Language, ChineseTraditional, "Traditional Chinese (正體中文)"), | ||
| 303 | PAIR(Language, PortugueseBrazilian, "Brazilian Portuguese (português do Brasil)"), | ||
| 304 | }}); | ||
| 305 | translations->insert({Settings::EnumMetadata<Settings::Region>::Index(), | ||
| 306 | { | ||
| 307 | PAIR(Region, Japan, "Japan"), | ||
| 308 | PAIR(Region, Usa, "USA"), | ||
| 309 | PAIR(Region, Europe, "Europe"), | ||
| 310 | PAIR(Region, Australia, "Australia"), | ||
| 311 | PAIR(Region, China, "China"), | ||
| 312 | PAIR(Region, Korea, "Korea"), | ||
| 313 | PAIR(Region, Taiwan, "Taiwan"), | ||
| 314 | }}); | ||
| 315 | translations->insert( | ||
| 316 | {Settings::EnumMetadata<Settings::TimeZone>::Index(), | ||
| 317 | { | ||
| 318 | {static_cast<u32>(Settings::TimeZone::Auto), | ||
| 319 | tr("Auto (%1)", "Auto select time zone") | ||
| 320 | .arg(QString::fromStdString( | ||
| 321 | Settings::GetTimeZoneString(Settings::TimeZone::Auto)))}, | ||
| 322 | {static_cast<u32>(Settings::TimeZone::Default), | ||
| 323 | tr("Default (%1)", "Default time zone") | ||
| 324 | .arg(QString::fromStdString(Common::TimeZone::GetDefaultTimeZone()))}, | ||
| 325 | PAIR(TimeZone, Cet, "CET"), | ||
| 326 | PAIR(TimeZone, Cst6Cdt, "CST6CDT"), | ||
| 327 | PAIR(TimeZone, Cuba, "Cuba"), | ||
| 328 | PAIR(TimeZone, Eet, "EET"), | ||
| 329 | PAIR(TimeZone, Egypt, "Egypt"), | ||
| 330 | PAIR(TimeZone, Eire, "Eire"), | ||
| 331 | PAIR(TimeZone, Est, "EST"), | ||
| 332 | PAIR(TimeZone, Est5Edt, "EST5EDT"), | ||
| 333 | PAIR(TimeZone, Gb, "GB"), | ||
| 334 | PAIR(TimeZone, GbEire, "GB-Eire"), | ||
| 335 | PAIR(TimeZone, Gmt, "GMT"), | ||
| 336 | PAIR(TimeZone, GmtPlusZero, "GMT+0"), | ||
| 337 | PAIR(TimeZone, GmtMinusZero, "GMT-0"), | ||
| 338 | PAIR(TimeZone, GmtZero, "GMT0"), | ||
| 339 | PAIR(TimeZone, Greenwich, "Greenwich"), | ||
| 340 | PAIR(TimeZone, Hongkong, "Hongkong"), | ||
| 341 | PAIR(TimeZone, Hst, "HST"), | ||
| 342 | PAIR(TimeZone, Iceland, "Iceland"), | ||
| 343 | PAIR(TimeZone, Iran, "Iran"), | ||
| 344 | PAIR(TimeZone, Israel, "Israel"), | ||
| 345 | PAIR(TimeZone, Jamaica, "Jamaica"), | ||
| 346 | PAIR(TimeZone, Japan, "Japan"), | ||
| 347 | PAIR(TimeZone, Kwajalein, "Kwajalein"), | ||
| 348 | PAIR(TimeZone, Libya, "Libya"), | ||
| 349 | PAIR(TimeZone, Met, "MET"), | ||
| 350 | PAIR(TimeZone, Mst, "MST"), | ||
| 351 | PAIR(TimeZone, Mst7Mdt, "MST7MDT"), | ||
| 352 | PAIR(TimeZone, Navajo, "Navajo"), | ||
| 353 | PAIR(TimeZone, Nz, "NZ"), | ||
| 354 | PAIR(TimeZone, NzChat, "NZ-CHAT"), | ||
| 355 | PAIR(TimeZone, Poland, "Poland"), | ||
| 356 | PAIR(TimeZone, Portugal, "Portugal"), | ||
| 357 | PAIR(TimeZone, Prc, "PRC"), | ||
| 358 | PAIR(TimeZone, Pst8Pdt, "PST8PDT"), | ||
| 359 | PAIR(TimeZone, Roc, "ROC"), | ||
| 360 | PAIR(TimeZone, Rok, "ROK"), | ||
| 361 | PAIR(TimeZone, Singapore, "Singapore"), | ||
| 362 | PAIR(TimeZone, Turkey, "Turkey"), | ||
| 363 | PAIR(TimeZone, Uct, "UCT"), | ||
| 364 | PAIR(TimeZone, Universal, "Universal"), | ||
| 365 | PAIR(TimeZone, Utc, "UTC"), | ||
| 366 | PAIR(TimeZone, WSu, "W-SU"), | ||
| 367 | PAIR(TimeZone, Wet, "WET"), | ||
| 368 | PAIR(TimeZone, Zulu, "Zulu"), | ||
| 369 | }}); | ||
| 370 | translations->insert({Settings::EnumMetadata<Settings::AudioMode>::Index(), | ||
| 371 | { | ||
| 372 | PAIR(AudioMode, Mono, "Mono"), | ||
| 373 | PAIR(AudioMode, Stereo, "Stereo"), | ||
| 374 | PAIR(AudioMode, Surround, "Surround"), | ||
| 375 | }}); | ||
| 376 | translations->insert({Settings::EnumMetadata<Settings::MemoryLayout>::Index(), | ||
| 377 | { | ||
| 378 | PAIR(MemoryLayout, Memory_4Gb, "4GB DRAM (Default)"), | ||
| 379 | PAIR(MemoryLayout, Memory_6Gb, "6GB DRAM (Unsafe)"), | ||
| 380 | PAIR(MemoryLayout, Memory_8Gb, "8GB DRAM (Unsafe)"), | ||
| 381 | }}); | ||
| 382 | |||
| 383 | #undef PAIR | ||
| 384 | #undef CTX_PAIR | ||
| 385 | |||
| 386 | return translations; | ||
| 387 | } | ||
| 388 | } // namespace ConfigurationShared | ||
diff --git a/src/yuzu/configuration/shared_translation.h b/src/yuzu/configuration/shared_translation.h new file mode 100644 index 000000000..99a0e808c --- /dev/null +++ b/src/yuzu/configuration/shared_translation.h | |||
| @@ -0,0 +1,25 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <map> | ||
| 7 | #include <memory> | ||
| 8 | #include <typeindex> | ||
| 9 | #include <utility> | ||
| 10 | #include <vector> | ||
| 11 | #include <QString> | ||
| 12 | #include "common/common_types.h" | ||
| 13 | |||
| 14 | class QWidget; | ||
| 15 | |||
| 16 | namespace ConfigurationShared { | ||
| 17 | using TranslationMap = std::map<u32, std::pair<QString, QString>>; | ||
| 18 | using ComboboxTranslations = std::vector<std::pair<u32, QString>>; | ||
| 19 | using ComboboxTranslationMap = std::map<u32, ComboboxTranslations>; | ||
| 20 | |||
| 21 | std::unique_ptr<TranslationMap> InitializeTranslations(QWidget* parent); | ||
| 22 | |||
| 23 | std::unique_ptr<ComboboxTranslationMap> ComboboxEnumeration(QWidget* parent); | ||
| 24 | |||
| 25 | } // namespace ConfigurationShared | ||
diff --git a/src/yuzu/configuration/shared_widget.cpp b/src/yuzu/configuration/shared_widget.cpp new file mode 100644 index 000000000..bdb38c8ea --- /dev/null +++ b/src/yuzu/configuration/shared_widget.cpp | |||
| @@ -0,0 +1,642 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "yuzu/configuration/shared_widget.h" | ||
| 5 | |||
| 6 | #include <functional> | ||
| 7 | #include <limits> | ||
| 8 | #include <typeindex> | ||
| 9 | #include <typeinfo> | ||
| 10 | #include <utility> | ||
| 11 | #include <vector> | ||
| 12 | |||
| 13 | #include <QAbstractButton> | ||
| 14 | #include <QAbstractSlider> | ||
| 15 | #include <QBoxLayout> | ||
| 16 | #include <QCheckBox> | ||
| 17 | #include <QComboBox> | ||
| 18 | #include <QDateTime> | ||
| 19 | #include <QDateTimeEdit> | ||
| 20 | #include <QIcon> | ||
| 21 | #include <QLabel> | ||
| 22 | #include <QLayout> | ||
| 23 | #include <QLineEdit> | ||
| 24 | #include <QObject> | ||
| 25 | #include <QPushButton> | ||
| 26 | #include <QRegularExpression> | ||
| 27 | #include <QSizePolicy> | ||
| 28 | #include <QSlider> | ||
| 29 | #include <QSpinBox> | ||
| 30 | #include <QStyle> | ||
| 31 | #include <QValidator> | ||
| 32 | #include <QVariant> | ||
| 33 | #include <QtCore/qglobal.h> | ||
| 34 | #include <QtCore/qobjectdefs.h> | ||
| 35 | #include <fmt/core.h> | ||
| 36 | #include <qglobal.h> | ||
| 37 | #include <qnamespace.h> | ||
| 38 | |||
| 39 | #include "common/assert.h" | ||
| 40 | #include "common/common_types.h" | ||
| 41 | #include "common/logging/log.h" | ||
| 42 | #include "common/settings.h" | ||
| 43 | #include "common/settings_common.h" | ||
| 44 | #include "yuzu/configuration/shared_translation.h" | ||
| 45 | |||
| 46 | namespace ConfigurationShared { | ||
| 47 | |||
| 48 | static int restore_button_count = 0; | ||
| 49 | |||
| 50 | static std::string RelevantDefault(const Settings::BasicSetting& setting) { | ||
| 51 | return Settings::IsConfiguringGlobal() ? setting.DefaultToString() : setting.ToStringGlobal(); | ||
| 52 | } | ||
| 53 | |||
| 54 | static QString DefaultSuffix(QWidget* parent, Settings::BasicSetting& setting) { | ||
| 55 | const auto tr = [parent](const char* text, const char* context) { | ||
| 56 | return parent->tr(text, context); | ||
| 57 | }; | ||
| 58 | |||
| 59 | if ((setting.Specialization() & Settings::SpecializationAttributeMask) == | ||
| 60 | Settings::Specialization::Percentage) { | ||
| 61 | std::string context{fmt::format("{} percentage (e.g. 50%)", setting.GetLabel())}; | ||
| 62 | return tr("%", context.c_str()); | ||
| 63 | } | ||
| 64 | |||
| 65 | return QStringLiteral(""); | ||
| 66 | } | ||
| 67 | |||
| 68 | QPushButton* Widget::CreateRestoreGlobalButton(bool using_global, QWidget* parent) { | ||
| 69 | restore_button_count++; | ||
| 70 | |||
| 71 | QStyle* style = parent->style(); | ||
| 72 | QIcon* icon = new QIcon(style->standardIcon(QStyle::SP_LineEditClearButton)); | ||
| 73 | QPushButton* restore_button = new QPushButton(*icon, QStringLiteral(""), parent); | ||
| 74 | restore_button->setObjectName(QStringLiteral("RestoreButton%1").arg(restore_button_count)); | ||
| 75 | restore_button->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); | ||
| 76 | |||
| 77 | // Workaround for dark theme causing min-width to be much larger than 0 | ||
| 78 | restore_button->setStyleSheet( | ||
| 79 | QStringLiteral("QAbstractButton#%1 { min-width: 0px }").arg(restore_button->objectName())); | ||
| 80 | |||
| 81 | QSizePolicy sp_retain = restore_button->sizePolicy(); | ||
| 82 | sp_retain.setRetainSizeWhenHidden(true); | ||
| 83 | restore_button->setSizePolicy(sp_retain); | ||
| 84 | |||
| 85 | restore_button->setEnabled(!using_global); | ||
| 86 | restore_button->setVisible(!using_global); | ||
| 87 | |||
| 88 | return restore_button; | ||
| 89 | } | ||
| 90 | |||
| 91 | QLabel* Widget::CreateLabel(const QString& text) { | ||
| 92 | QLabel* qt_label = new QLabel(text, this->parent); | ||
| 93 | qt_label->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); | ||
| 94 | return qt_label; | ||
| 95 | } | ||
| 96 | |||
| 97 | QWidget* Widget::CreateCheckBox(Settings::BasicSetting* bool_setting, const QString& label, | ||
| 98 | std::function<std::string()>& serializer, | ||
| 99 | std::function<void()>& restore_func, | ||
| 100 | const std::function<void()>& touch) { | ||
| 101 | checkbox = new QCheckBox(label, this); | ||
| 102 | checkbox->setCheckState(bool_setting->ToString() == "true" ? Qt::CheckState::Checked | ||
| 103 | : Qt::CheckState::Unchecked); | ||
| 104 | checkbox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); | ||
| 105 | |||
| 106 | if (!bool_setting->Save() && !Settings::IsConfiguringGlobal() && runtime_lock) { | ||
| 107 | checkbox->setEnabled(false); | ||
| 108 | } | ||
| 109 | |||
| 110 | serializer = [this]() { | ||
| 111 | return checkbox->checkState() == Qt::CheckState::Checked ? "true" : "false"; | ||
| 112 | }; | ||
| 113 | |||
| 114 | restore_func = [this, bool_setting]() { | ||
| 115 | checkbox->setCheckState(RelevantDefault(*bool_setting) == "true" ? Qt::Checked | ||
| 116 | : Qt::Unchecked); | ||
| 117 | }; | ||
| 118 | |||
| 119 | if (!Settings::IsConfiguringGlobal()) { | ||
| 120 | QObject::connect(checkbox, &QCheckBox::clicked, [touch]() { touch(); }); | ||
| 121 | } | ||
| 122 | |||
| 123 | return checkbox; | ||
| 124 | } | ||
| 125 | |||
| 126 | QWidget* Widget::CreateCombobox(std::function<std::string()>& serializer, | ||
| 127 | std::function<void()>& restore_func, | ||
| 128 | const std::function<void()>& touch) { | ||
| 129 | const auto type = setting.EnumIndex(); | ||
| 130 | |||
| 131 | combobox = new QComboBox(this); | ||
| 132 | combobox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); | ||
| 133 | |||
| 134 | const ComboboxTranslations* enumeration{nullptr}; | ||
| 135 | if (combobox_enumerations.contains(type)) { | ||
| 136 | enumeration = &combobox_enumerations.at(type); | ||
| 137 | for (const auto& [id, name] : *enumeration) { | ||
| 138 | combobox->addItem(name); | ||
| 139 | } | ||
| 140 | } else { | ||
| 141 | return combobox; | ||
| 142 | } | ||
| 143 | |||
| 144 | const auto find_index = [=](u32 value) -> int { | ||
| 145 | for (u32 i = 0; i < enumeration->size(); i++) { | ||
| 146 | if (enumeration->at(i).first == value) { | ||
| 147 | return i; | ||
| 148 | } | ||
| 149 | } | ||
| 150 | return -1; | ||
| 151 | }; | ||
| 152 | |||
| 153 | const u32 setting_value = std::stoi(setting.ToString()); | ||
| 154 | combobox->setCurrentIndex(find_index(setting_value)); | ||
| 155 | |||
| 156 | serializer = [this, enumeration]() { | ||
| 157 | int current = combobox->currentIndex(); | ||
| 158 | return std::to_string(enumeration->at(current).first); | ||
| 159 | }; | ||
| 160 | |||
| 161 | restore_func = [this, find_index]() { | ||
| 162 | const u32 global_value = std::stoi(RelevantDefault(setting)); | ||
| 163 | combobox->setCurrentIndex(find_index(global_value)); | ||
| 164 | }; | ||
| 165 | |||
| 166 | if (!Settings::IsConfiguringGlobal()) { | ||
| 167 | QObject::connect(combobox, QOverload<int>::of(&QComboBox::activated), | ||
| 168 | [touch]() { touch(); }); | ||
| 169 | } | ||
| 170 | |||
| 171 | return combobox; | ||
| 172 | } | ||
| 173 | |||
| 174 | QWidget* Widget::CreateLineEdit(std::function<std::string()>& serializer, | ||
| 175 | std::function<void()>& restore_func, | ||
| 176 | const std::function<void()>& touch, bool managed) { | ||
| 177 | const QString text = QString::fromStdString(setting.ToString()); | ||
| 178 | line_edit = new QLineEdit(this); | ||
| 179 | line_edit->setText(text); | ||
| 180 | |||
| 181 | serializer = [this]() { return line_edit->text().toStdString(); }; | ||
| 182 | |||
| 183 | if (!managed) { | ||
| 184 | return line_edit; | ||
| 185 | } | ||
| 186 | |||
| 187 | restore_func = [this]() { | ||
| 188 | line_edit->setText(QString::fromStdString(RelevantDefault(setting))); | ||
| 189 | }; | ||
| 190 | |||
| 191 | if (!Settings::IsConfiguringGlobal()) { | ||
| 192 | QObject::connect(line_edit, &QLineEdit::textChanged, [touch]() { touch(); }); | ||
| 193 | } | ||
| 194 | |||
| 195 | return line_edit; | ||
| 196 | } | ||
| 197 | |||
| 198 | QWidget* Widget::CreateSlider(bool reversed, float multiplier, const QString& given_suffix, | ||
| 199 | std::function<std::string()>& serializer, | ||
| 200 | std::function<void()>& restore_func, | ||
| 201 | const std::function<void()>& touch) { | ||
| 202 | if (!setting.Ranged()) { | ||
| 203 | LOG_ERROR(Frontend, "\"{}\" is not a ranged setting, but a slider was requested.", | ||
| 204 | setting.GetLabel()); | ||
| 205 | return nullptr; | ||
| 206 | } | ||
| 207 | |||
| 208 | QWidget* container = new QWidget(this); | ||
| 209 | QHBoxLayout* layout = new QHBoxLayout(container); | ||
| 210 | |||
| 211 | slider = new QSlider(Qt::Horizontal, this); | ||
| 212 | QLabel* feedback = new QLabel(this); | ||
| 213 | |||
| 214 | layout->addWidget(slider); | ||
| 215 | layout->addWidget(feedback); | ||
| 216 | |||
| 217 | container->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); | ||
| 218 | |||
| 219 | layout->setContentsMargins(0, 0, 0, 0); | ||
| 220 | |||
| 221 | int max_val = std::stoi(setting.MaxVal()); | ||
| 222 | |||
| 223 | QString suffix = | ||
| 224 | given_suffix == QStringLiteral("") ? DefaultSuffix(this, setting) : given_suffix; | ||
| 225 | |||
| 226 | const QString use_format = QStringLiteral("%1").append(suffix); | ||
| 227 | |||
| 228 | QObject::connect(slider, &QAbstractSlider::valueChanged, [=](int value) { | ||
| 229 | int present = (reversed ? max_val - value : value) * multiplier + 0.5f; | ||
| 230 | feedback->setText(use_format.arg(QVariant::fromValue(present).value<QString>())); | ||
| 231 | }); | ||
| 232 | |||
| 233 | slider->setMinimum(std::stoi(setting.MinVal())); | ||
| 234 | slider->setMaximum(max_val); | ||
| 235 | slider->setValue(std::stoi(setting.ToString())); | ||
| 236 | |||
| 237 | slider->setInvertedAppearance(reversed); | ||
| 238 | |||
| 239 | serializer = [this]() { return std::to_string(slider->value()); }; | ||
| 240 | restore_func = [this]() { slider->setValue(std::stoi(RelevantDefault(setting))); }; | ||
| 241 | |||
| 242 | if (!Settings::IsConfiguringGlobal()) { | ||
| 243 | QObject::connect(slider, &QAbstractSlider::actionTriggered, [touch]() { touch(); }); | ||
| 244 | } | ||
| 245 | |||
| 246 | return container; | ||
| 247 | } | ||
| 248 | |||
| 249 | QWidget* Widget::CreateSpinBox(const QString& given_suffix, | ||
| 250 | std::function<std::string()>& serializer, | ||
| 251 | std::function<void()>& restore_func, | ||
| 252 | const std::function<void()>& touch) { | ||
| 253 | const int min_val = | ||
| 254 | setting.Ranged() ? std::stoi(setting.MinVal()) : std::numeric_limits<int>::min(); | ||
| 255 | const int max_val = | ||
| 256 | setting.Ranged() ? std::stoi(setting.MaxVal()) : std::numeric_limits<int>::max(); | ||
| 257 | const int default_val = std::stoi(setting.ToString()); | ||
| 258 | |||
| 259 | QString suffix = | ||
| 260 | given_suffix == QStringLiteral("") ? DefaultSuffix(this, setting) : given_suffix; | ||
| 261 | |||
| 262 | spinbox = new QSpinBox(this); | ||
| 263 | spinbox->setRange(min_val, max_val); | ||
| 264 | spinbox->setValue(default_val); | ||
| 265 | spinbox->setSuffix(suffix); | ||
| 266 | spinbox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); | ||
| 267 | |||
| 268 | serializer = [this]() { return std::to_string(spinbox->value()); }; | ||
| 269 | |||
| 270 | restore_func = [this]() { | ||
| 271 | auto value{std::stol(RelevantDefault(setting))}; | ||
| 272 | spinbox->setValue(value); | ||
| 273 | }; | ||
| 274 | |||
| 275 | if (!Settings::IsConfiguringGlobal()) { | ||
| 276 | QObject::connect(spinbox, QOverload<int>::of(&QSpinBox::valueChanged), [this, touch]() { | ||
| 277 | if (spinbox->value() != std::stoi(setting.ToStringGlobal())) { | ||
| 278 | touch(); | ||
| 279 | } | ||
| 280 | }); | ||
| 281 | } | ||
| 282 | |||
| 283 | return spinbox; | ||
| 284 | } | ||
| 285 | |||
| 286 | QWidget* Widget::CreateHexEdit(std::function<std::string()>& serializer, | ||
| 287 | std::function<void()>& restore_func, | ||
| 288 | const std::function<void()>& touch) { | ||
| 289 | auto* data_component = CreateLineEdit(serializer, restore_func, touch, false); | ||
| 290 | if (data_component == nullptr) { | ||
| 291 | return nullptr; | ||
| 292 | } | ||
| 293 | |||
| 294 | auto to_hex = [=](const std::string& input) { | ||
| 295 | return QString::fromStdString(fmt::format("{:08x}", std::stoul(input))); | ||
| 296 | }; | ||
| 297 | |||
| 298 | QRegularExpressionValidator* regex = new QRegularExpressionValidator( | ||
| 299 | QRegularExpression{QStringLiteral("^[0-9a-fA-F]{0,8}$")}, line_edit); | ||
| 300 | |||
| 301 | const QString default_val = to_hex(setting.ToString()); | ||
| 302 | |||
| 303 | line_edit->setText(default_val); | ||
| 304 | line_edit->setMaxLength(8); | ||
| 305 | line_edit->setValidator(regex); | ||
| 306 | |||
| 307 | auto hex_to_dec = [this]() -> std::string { | ||
| 308 | return std::to_string(std::stoul(line_edit->text().toStdString(), nullptr, 16)); | ||
| 309 | }; | ||
| 310 | |||
| 311 | serializer = [hex_to_dec]() { return hex_to_dec(); }; | ||
| 312 | |||
| 313 | restore_func = [this, to_hex]() { line_edit->setText(to_hex(RelevantDefault(setting))); }; | ||
| 314 | |||
| 315 | if (!Settings::IsConfiguringGlobal()) { | ||
| 316 | |||
| 317 | QObject::connect(line_edit, &QLineEdit::textChanged, [touch]() { touch(); }); | ||
| 318 | } | ||
| 319 | |||
| 320 | return line_edit; | ||
| 321 | } | ||
| 322 | |||
| 323 | QWidget* Widget::CreateDateTimeEdit(bool disabled, bool restrict, | ||
| 324 | std::function<std::string()>& serializer, | ||
| 325 | std::function<void()>& restore_func, | ||
| 326 | const std::function<void()>& touch) { | ||
| 327 | const long long current_time = QDateTime::currentSecsSinceEpoch(); | ||
| 328 | const s64 the_time = disabled ? current_time : std::stoll(setting.ToString()); | ||
| 329 | const auto default_val = QDateTime::fromSecsSinceEpoch(the_time); | ||
| 330 | |||
| 331 | date_time_edit = new QDateTimeEdit(this); | ||
| 332 | date_time_edit->setDateTime(default_val); | ||
| 333 | date_time_edit->setMinimumDateTime(QDateTime::fromSecsSinceEpoch(0)); | ||
| 334 | date_time_edit->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); | ||
| 335 | |||
| 336 | serializer = [this]() { return std::to_string(date_time_edit->dateTime().toSecsSinceEpoch()); }; | ||
| 337 | |||
| 338 | auto get_clear_val = [this, restrict, current_time]() { | ||
| 339 | return QDateTime::fromSecsSinceEpoch([this, restrict, current_time]() { | ||
| 340 | if (restrict && checkbox->checkState() == Qt::Checked) { | ||
| 341 | return std::stoll(RelevantDefault(setting)); | ||
| 342 | } | ||
| 343 | return current_time; | ||
| 344 | }()); | ||
| 345 | }; | ||
| 346 | |||
| 347 | restore_func = [this, get_clear_val]() { date_time_edit->setDateTime(get_clear_val()); }; | ||
| 348 | |||
| 349 | if (!Settings::IsConfiguringGlobal()) { | ||
| 350 | QObject::connect(date_time_edit, &QDateTimeEdit::editingFinished, | ||
| 351 | [this, get_clear_val, touch]() { | ||
| 352 | if (date_time_edit->dateTime() != get_clear_val()) { | ||
| 353 | touch(); | ||
| 354 | } | ||
| 355 | }); | ||
| 356 | } | ||
| 357 | |||
| 358 | return date_time_edit; | ||
| 359 | } | ||
| 360 | |||
| 361 | void Widget::SetupComponent(const QString& label, std::function<void()>& load_func, bool managed, | ||
| 362 | RequestType request, float multiplier, | ||
| 363 | Settings::BasicSetting* other_setting, const QString& suffix) { | ||
| 364 | created = true; | ||
| 365 | const auto type = setting.TypeId(); | ||
| 366 | |||
| 367 | QLayout* layout = new QHBoxLayout(this); | ||
| 368 | layout->setContentsMargins(0, 0, 0, 0); | ||
| 369 | |||
| 370 | if (other_setting == nullptr) { | ||
| 371 | other_setting = setting.PairedSetting(); | ||
| 372 | } | ||
| 373 | |||
| 374 | const bool require_checkbox = | ||
| 375 | other_setting != nullptr && other_setting->TypeId() == typeid(bool); | ||
| 376 | |||
| 377 | if (other_setting != nullptr && other_setting->TypeId() != typeid(bool)) { | ||
| 378 | LOG_WARNING( | ||
| 379 | Frontend, | ||
| 380 | "Extra setting \"{}\" specified but is not bool, refusing to create checkbox for it.", | ||
| 381 | other_setting->GetLabel()); | ||
| 382 | } | ||
| 383 | |||
| 384 | std::function<std::string()> checkbox_serializer = []() -> std::string { return {}; }; | ||
| 385 | std::function<void()> checkbox_restore_func = []() {}; | ||
| 386 | |||
| 387 | std::function<void()> touch = []() {}; | ||
| 388 | std::function<std::string()> serializer = []() -> std::string { return {}; }; | ||
| 389 | std::function<void()> restore_func = []() {}; | ||
| 390 | |||
| 391 | QWidget* data_component{nullptr}; | ||
| 392 | |||
| 393 | request = [&]() { | ||
| 394 | if (request != RequestType::Default) { | ||
| 395 | return request; | ||
| 396 | } | ||
| 397 | switch (setting.Specialization() & Settings::SpecializationTypeMask) { | ||
| 398 | case Settings::Specialization::Default: | ||
| 399 | return RequestType::Default; | ||
| 400 | case Settings::Specialization::Time: | ||
| 401 | return RequestType::DateTimeEdit; | ||
| 402 | case Settings::Specialization::Hex: | ||
| 403 | return RequestType::HexEdit; | ||
| 404 | case Settings::Specialization::RuntimeList: | ||
| 405 | managed = false; | ||
| 406 | [[fallthrough]]; | ||
| 407 | case Settings::Specialization::List: | ||
| 408 | return RequestType::ComboBox; | ||
| 409 | case Settings::Specialization::Scalar: | ||
| 410 | return RequestType::Slider; | ||
| 411 | case Settings::Specialization::Countable: | ||
| 412 | return RequestType::SpinBox; | ||
| 413 | default: | ||
| 414 | break; | ||
| 415 | } | ||
| 416 | return request; | ||
| 417 | }(); | ||
| 418 | |||
| 419 | if (!Settings::IsConfiguringGlobal() && managed) { | ||
| 420 | restore_button = CreateRestoreGlobalButton(setting.UsingGlobal(), this); | ||
| 421 | |||
| 422 | touch = [this]() { | ||
| 423 | LOG_DEBUG(Frontend, "Enabling custom setting for \"{}\"", setting.GetLabel()); | ||
| 424 | restore_button->setEnabled(true); | ||
| 425 | restore_button->setVisible(true); | ||
| 426 | }; | ||
| 427 | } | ||
| 428 | |||
| 429 | if (require_checkbox) { | ||
| 430 | QWidget* lhs = | ||
| 431 | CreateCheckBox(other_setting, label, checkbox_serializer, checkbox_restore_func, touch); | ||
| 432 | layout->addWidget(lhs); | ||
| 433 | } else if (setting.TypeId() != typeid(bool)) { | ||
| 434 | QLabel* qt_label = CreateLabel(label); | ||
| 435 | layout->addWidget(qt_label); | ||
| 436 | } | ||
| 437 | |||
| 438 | if (setting.TypeId() == typeid(bool)) { | ||
| 439 | data_component = CreateCheckBox(&setting, label, serializer, restore_func, touch); | ||
| 440 | } else if (setting.IsEnum()) { | ||
| 441 | data_component = CreateCombobox(serializer, restore_func, touch); | ||
| 442 | } else if (type == typeid(u32) || type == typeid(int) || type == typeid(u16) || | ||
| 443 | type == typeid(s64) || type == typeid(u8)) { | ||
| 444 | switch (request) { | ||
| 445 | case RequestType::Slider: | ||
| 446 | case RequestType::ReverseSlider: | ||
| 447 | data_component = CreateSlider(request == RequestType::ReverseSlider, multiplier, suffix, | ||
| 448 | serializer, restore_func, touch); | ||
| 449 | break; | ||
| 450 | case RequestType::Default: | ||
| 451 | case RequestType::LineEdit: | ||
| 452 | data_component = CreateLineEdit(serializer, restore_func, touch); | ||
| 453 | break; | ||
| 454 | case RequestType::DateTimeEdit: | ||
| 455 | data_component = CreateDateTimeEdit(other_setting->ToString() != "true", true, | ||
| 456 | serializer, restore_func, touch); | ||
| 457 | break; | ||
| 458 | case RequestType::SpinBox: | ||
| 459 | data_component = CreateSpinBox(suffix, serializer, restore_func, touch); | ||
| 460 | break; | ||
| 461 | case RequestType::HexEdit: | ||
| 462 | data_component = CreateHexEdit(serializer, restore_func, touch); | ||
| 463 | break; | ||
| 464 | case RequestType::ComboBox: | ||
| 465 | data_component = CreateCombobox(serializer, restore_func, touch); | ||
| 466 | break; | ||
| 467 | default: | ||
| 468 | UNIMPLEMENTED(); | ||
| 469 | } | ||
| 470 | } else if (type == typeid(std::string)) { | ||
| 471 | switch (request) { | ||
| 472 | case RequestType::Default: | ||
| 473 | case RequestType::LineEdit: | ||
| 474 | data_component = CreateLineEdit(serializer, restore_func, touch); | ||
| 475 | break; | ||
| 476 | case RequestType::ComboBox: | ||
| 477 | data_component = CreateCombobox(serializer, restore_func, touch); | ||
| 478 | break; | ||
| 479 | default: | ||
| 480 | UNIMPLEMENTED(); | ||
| 481 | } | ||
| 482 | } | ||
| 483 | |||
| 484 | if (data_component == nullptr) { | ||
| 485 | LOG_ERROR(Frontend, "Failed to create widget for \"{}\"", setting.GetLabel()); | ||
| 486 | created = false; | ||
| 487 | return; | ||
| 488 | } | ||
| 489 | |||
| 490 | layout->addWidget(data_component); | ||
| 491 | |||
| 492 | if (!managed) { | ||
| 493 | return; | ||
| 494 | } | ||
| 495 | |||
| 496 | if (Settings::IsConfiguringGlobal()) { | ||
| 497 | load_func = [this, serializer, checkbox_serializer, require_checkbox, other_setting]() { | ||
| 498 | if (require_checkbox && other_setting->UsingGlobal()) { | ||
| 499 | other_setting->LoadString(checkbox_serializer()); | ||
| 500 | } | ||
| 501 | if (setting.UsingGlobal()) { | ||
| 502 | setting.LoadString(serializer()); | ||
| 503 | } | ||
| 504 | }; | ||
| 505 | } else { | ||
| 506 | layout->addWidget(restore_button); | ||
| 507 | |||
| 508 | QObject::connect(restore_button, &QAbstractButton::clicked, | ||
| 509 | [this, restore_func, checkbox_restore_func](bool) { | ||
| 510 | LOG_DEBUG(Frontend, "Restore global state for \"{}\"", | ||
| 511 | setting.GetLabel()); | ||
| 512 | |||
| 513 | restore_button->setEnabled(false); | ||
| 514 | restore_button->setVisible(false); | ||
| 515 | |||
| 516 | checkbox_restore_func(); | ||
| 517 | restore_func(); | ||
| 518 | }); | ||
| 519 | |||
| 520 | load_func = [this, serializer, require_checkbox, checkbox_serializer, other_setting]() { | ||
| 521 | bool using_global = !restore_button->isEnabled(); | ||
| 522 | setting.SetGlobal(using_global); | ||
| 523 | if (!using_global) { | ||
| 524 | setting.LoadString(serializer()); | ||
| 525 | } | ||
| 526 | if (require_checkbox) { | ||
| 527 | other_setting->SetGlobal(using_global); | ||
| 528 | if (!using_global) { | ||
| 529 | other_setting->LoadString(checkbox_serializer()); | ||
| 530 | } | ||
| 531 | } | ||
| 532 | }; | ||
| 533 | } | ||
| 534 | |||
| 535 | if (other_setting != nullptr) { | ||
| 536 | const auto reset = [restore_func, data_component](int state) { | ||
| 537 | data_component->setEnabled(state == Qt::Checked); | ||
| 538 | if (state != Qt::Checked) { | ||
| 539 | restore_func(); | ||
| 540 | } | ||
| 541 | }; | ||
| 542 | connect(checkbox, &QCheckBox::stateChanged, reset); | ||
| 543 | reset(checkbox->checkState()); | ||
| 544 | } | ||
| 545 | } | ||
| 546 | |||
| 547 | bool Widget::Valid() const { | ||
| 548 | return created; | ||
| 549 | } | ||
| 550 | |||
| 551 | Widget::~Widget() = default; | ||
| 552 | |||
| 553 | Widget::Widget(Settings::BasicSetting* setting_, const TranslationMap& translations_, | ||
| 554 | const ComboboxTranslationMap& combobox_translations_, QWidget* parent_, | ||
| 555 | bool runtime_lock_, std::vector<std::function<void(bool)>>& apply_funcs_, | ||
| 556 | RequestType request, bool managed, float multiplier, | ||
| 557 | Settings::BasicSetting* other_setting, const QString& suffix) | ||
| 558 | : QWidget(parent_), parent{parent_}, translations{translations_}, | ||
| 559 | combobox_enumerations{combobox_translations_}, setting{*setting_}, apply_funcs{apply_funcs_}, | ||
| 560 | runtime_lock{runtime_lock_} { | ||
| 561 | if (!Settings::IsConfiguringGlobal() && !setting.Switchable()) { | ||
| 562 | LOG_DEBUG(Frontend, "\"{}\" is not switchable, skipping...", setting.GetLabel()); | ||
| 563 | return; | ||
| 564 | } | ||
| 565 | |||
| 566 | const int id = setting.Id(); | ||
| 567 | |||
| 568 | const auto [label, tooltip] = [&]() { | ||
| 569 | const auto& setting_label = setting.GetLabel(); | ||
| 570 | if (translations.contains(id)) { | ||
| 571 | return std::pair{translations.at(id).first, translations.at(id).second}; | ||
| 572 | } | ||
| 573 | LOG_WARNING(Frontend, "Translation table lacks entry for \"{}\"", setting_label); | ||
| 574 | return std::pair{QString::fromStdString(setting_label), QStringLiteral("")}; | ||
| 575 | }(); | ||
| 576 | |||
| 577 | if (label == QStringLiteral("")) { | ||
| 578 | LOG_DEBUG(Frontend, "Translation table has empty entry for \"{}\", skipping...", | ||
| 579 | setting.GetLabel()); | ||
| 580 | return; | ||
| 581 | } | ||
| 582 | |||
| 583 | std::function<void()> load_func = []() {}; | ||
| 584 | |||
| 585 | SetupComponent(label, load_func, managed, request, multiplier, other_setting, suffix); | ||
| 586 | |||
| 587 | if (!created) { | ||
| 588 | LOG_WARNING(Frontend, "No widget was created for \"{}\"", setting.GetLabel()); | ||
| 589 | return; | ||
| 590 | } | ||
| 591 | |||
| 592 | apply_funcs.push_back([load_func, setting_](bool powered_on) { | ||
| 593 | if (setting_->RuntimeModfiable() || !powered_on) { | ||
| 594 | load_func(); | ||
| 595 | } | ||
| 596 | }); | ||
| 597 | |||
| 598 | bool enable = runtime_lock || setting.RuntimeModfiable(); | ||
| 599 | if (setting.Switchable() && Settings::IsConfiguringGlobal() && !runtime_lock) { | ||
| 600 | enable &= setting.UsingGlobal(); | ||
| 601 | } | ||
| 602 | this->setEnabled(enable); | ||
| 603 | |||
| 604 | this->setToolTip(tooltip); | ||
| 605 | } | ||
| 606 | |||
| 607 | Builder::Builder(QWidget* parent_, bool runtime_lock_) | ||
| 608 | : translations{InitializeTranslations(parent_)}, | ||
| 609 | combobox_translations{ComboboxEnumeration(parent_)}, parent{parent_}, runtime_lock{ | ||
| 610 | runtime_lock_} {} | ||
| 611 | |||
| 612 | Builder::~Builder() = default; | ||
| 613 | |||
| 614 | Widget* Builder::BuildWidget(Settings::BasicSetting* setting, | ||
| 615 | std::vector<std::function<void(bool)>>& apply_funcs, | ||
| 616 | RequestType request, bool managed, float multiplier, | ||
| 617 | Settings::BasicSetting* other_setting, const QString& suffix) const { | ||
| 618 | if (!Settings::IsConfiguringGlobal() && !setting->Switchable()) { | ||
| 619 | return nullptr; | ||
| 620 | } | ||
| 621 | |||
| 622 | if (setting->Specialization() == Settings::Specialization::Paired) { | ||
| 623 | LOG_DEBUG(Frontend, "\"{}\" has specialization Paired: ignoring", setting->GetLabel()); | ||
| 624 | return nullptr; | ||
| 625 | } | ||
| 626 | |||
| 627 | return new Widget(setting, *translations, *combobox_translations, parent, runtime_lock, | ||
| 628 | apply_funcs, request, managed, multiplier, other_setting, suffix); | ||
| 629 | } | ||
| 630 | |||
| 631 | Widget* Builder::BuildWidget(Settings::BasicSetting* setting, | ||
| 632 | std::vector<std::function<void(bool)>>& apply_funcs, | ||
| 633 | Settings::BasicSetting* other_setting, RequestType request, | ||
| 634 | const QString& suffix) const { | ||
| 635 | return BuildWidget(setting, apply_funcs, request, true, 1.0f, other_setting, suffix); | ||
| 636 | } | ||
| 637 | |||
| 638 | const ComboboxTranslationMap& Builder::ComboboxTranslations() const { | ||
| 639 | return *combobox_translations; | ||
| 640 | } | ||
| 641 | |||
| 642 | } // namespace ConfigurationShared | ||
diff --git a/src/yuzu/configuration/shared_widget.h b/src/yuzu/configuration/shared_widget.h new file mode 100644 index 000000000..e64693bab --- /dev/null +++ b/src/yuzu/configuration/shared_widget.h | |||
| @@ -0,0 +1,161 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <functional> | ||
| 7 | #include <memory> | ||
| 8 | #include <string> | ||
| 9 | #include <vector> | ||
| 10 | #include <QString> | ||
| 11 | #include <QStringLiteral> | ||
| 12 | #include <QWidget> | ||
| 13 | #include <qobjectdefs.h> | ||
| 14 | #include "yuzu/configuration/shared_translation.h" | ||
| 15 | |||
| 16 | class QCheckBox; | ||
| 17 | class QComboBox; | ||
| 18 | class QDateTimeEdit; | ||
| 19 | class QLabel; | ||
| 20 | class QLineEdit; | ||
| 21 | class QObject; | ||
| 22 | class QPushButton; | ||
| 23 | class QSlider; | ||
| 24 | class QSpinBox; | ||
| 25 | |||
| 26 | namespace Settings { | ||
| 27 | class BasicSetting; | ||
| 28 | } // namespace Settings | ||
| 29 | |||
| 30 | namespace ConfigurationShared { | ||
| 31 | |||
| 32 | enum class RequestType { | ||
| 33 | Default, | ||
| 34 | ComboBox, | ||
| 35 | SpinBox, | ||
| 36 | Slider, | ||
| 37 | ReverseSlider, | ||
| 38 | LineEdit, | ||
| 39 | HexEdit, | ||
| 40 | DateTimeEdit, | ||
| 41 | MaxEnum, | ||
| 42 | }; | ||
| 43 | |||
| 44 | class Widget : public QWidget { | ||
| 45 | Q_OBJECT | ||
| 46 | |||
| 47 | public: | ||
| 48 | /** | ||
| 49 | * @param setting The primary Setting to create the Widget for | ||
| 50 | * @param translations Map of translations to display on the left side label/checkbox | ||
| 51 | * @param combobox_translations Map of translations for enumerating combo boxes | ||
| 52 | * @param parent Qt parent | ||
| 53 | * @param runtime_lock Emulated guest powered on state, for use on settings that should be | ||
| 54 | * configured during guest execution | ||
| 55 | * @param apply_funcs_ List to append, functions to run to apply the widget state to the setting | ||
| 56 | * @param request What type of data representation component to create -- not always respected | ||
| 57 | * for the Setting data type | ||
| 58 | * @param managed Set true if the caller will set up component data and handling | ||
| 59 | * @param multiplier Value to multiply the slider feedback label | ||
| 60 | * @param other_setting Second setting to modify, to replace the label with a checkbox | ||
| 61 | * @param suffix Set to specify formats for Slider feedback labels or SpinBox | ||
| 62 | */ | ||
| 63 | explicit Widget(Settings::BasicSetting* setting, const TranslationMap& translations, | ||
| 64 | const ComboboxTranslationMap& combobox_translations, QWidget* parent, | ||
| 65 | bool runtime_lock, std::vector<std::function<void(bool)>>& apply_funcs_, | ||
| 66 | RequestType request = RequestType::Default, bool managed = true, | ||
| 67 | float multiplier = 1.0f, Settings::BasicSetting* other_setting = nullptr, | ||
| 68 | const QString& suffix = QStringLiteral("")); | ||
| 69 | virtual ~Widget(); | ||
| 70 | |||
| 71 | /** | ||
| 72 | * @returns True if the Widget successfully created the components for the setting | ||
| 73 | */ | ||
| 74 | bool Valid() const; | ||
| 75 | |||
| 76 | /** | ||
| 77 | * Creates a button to appear when a setting has been modified. This exists for custom | ||
| 78 | * configurations and wasn't designed to work for the global configuration. It has public access | ||
| 79 | * for settings that need to be unmanaged but can be custom. | ||
| 80 | * | ||
| 81 | * @param using_global The global state of the setting this button is for | ||
| 82 | * @param parent QWidget parent | ||
| 83 | */ | ||
| 84 | [[nodiscard]] static QPushButton* CreateRestoreGlobalButton(bool using_global, QWidget* parent); | ||
| 85 | |||
| 86 | // Direct handles to sub components created | ||
| 87 | QPushButton* restore_button{}; ///< Restore button for custom configurations | ||
| 88 | QLineEdit* line_edit{}; ///< QLineEdit, used for LineEdit and HexEdit | ||
| 89 | QSpinBox* spinbox{}; | ||
| 90 | QCheckBox* checkbox{}; | ||
| 91 | QSlider* slider{}; | ||
| 92 | QComboBox* combobox{}; | ||
| 93 | QDateTimeEdit* date_time_edit{}; | ||
| 94 | |||
| 95 | private: | ||
| 96 | void SetupComponent(const QString& label, std::function<void()>& load_func, bool managed, | ||
| 97 | RequestType request, float multiplier, | ||
| 98 | Settings::BasicSetting* other_setting, const QString& suffix); | ||
| 99 | |||
| 100 | QLabel* CreateLabel(const QString& text); | ||
| 101 | QWidget* CreateCheckBox(Settings::BasicSetting* bool_setting, const QString& label, | ||
| 102 | std::function<std::string()>& serializer, | ||
| 103 | std::function<void()>& restore_func, | ||
| 104 | const std::function<void()>& touch); | ||
| 105 | |||
| 106 | QWidget* CreateCombobox(std::function<std::string()>& serializer, | ||
| 107 | std::function<void()>& restore_func, | ||
| 108 | const std::function<void()>& touch); | ||
| 109 | QWidget* CreateLineEdit(std::function<std::string()>& serializer, | ||
| 110 | std::function<void()>& restore_func, const std::function<void()>& touch, | ||
| 111 | bool managed = true); | ||
| 112 | QWidget* CreateHexEdit(std::function<std::string()>& serializer, | ||
| 113 | std::function<void()>& restore_func, const std::function<void()>& touch); | ||
| 114 | QWidget* CreateSlider(bool reversed, float multiplier, const QString& suffix, | ||
| 115 | std::function<std::string()>& serializer, | ||
| 116 | std::function<void()>& restore_func, const std::function<void()>& touch); | ||
| 117 | QWidget* CreateDateTimeEdit(bool disabled, bool restrict, | ||
| 118 | std::function<std::string()>& serializer, | ||
| 119 | std::function<void()>& restore_func, | ||
| 120 | const std::function<void()>& touch); | ||
| 121 | QWidget* CreateSpinBox(const QString& suffix, std::function<std::string()>& serializer, | ||
| 122 | std::function<void()>& restore_func, const std::function<void()>& touch); | ||
| 123 | |||
| 124 | QWidget* parent; | ||
| 125 | const TranslationMap& translations; | ||
| 126 | const ComboboxTranslationMap& combobox_enumerations; | ||
| 127 | Settings::BasicSetting& setting; | ||
| 128 | std::vector<std::function<void(bool)>>& apply_funcs; | ||
| 129 | |||
| 130 | bool created{false}; | ||
| 131 | bool runtime_lock{false}; | ||
| 132 | }; | ||
| 133 | |||
| 134 | class Builder { | ||
| 135 | public: | ||
| 136 | explicit Builder(QWidget* parent, bool runtime_lock); | ||
| 137 | ~Builder(); | ||
| 138 | |||
| 139 | Widget* BuildWidget(Settings::BasicSetting* setting, | ||
| 140 | std::vector<std::function<void(bool)>>& apply_funcs, | ||
| 141 | RequestType request = RequestType::Default, bool managed = true, | ||
| 142 | float multiplier = 1.0f, Settings::BasicSetting* other_setting = nullptr, | ||
| 143 | const QString& suffix = QStringLiteral("")) const; | ||
| 144 | |||
| 145 | Widget* BuildWidget(Settings::BasicSetting* setting, | ||
| 146 | std::vector<std::function<void(bool)>>& apply_funcs, | ||
| 147 | Settings::BasicSetting* other_setting, | ||
| 148 | RequestType request = RequestType::Default, | ||
| 149 | const QString& suffix = QStringLiteral("")) const; | ||
| 150 | |||
| 151 | const ComboboxTranslationMap& ComboboxTranslations() const; | ||
| 152 | |||
| 153 | private: | ||
| 154 | std::unique_ptr<TranslationMap> translations; | ||
| 155 | std::unique_ptr<ComboboxTranslationMap> combobox_translations; | ||
| 156 | |||
| 157 | QWidget* parent; | ||
| 158 | const bool runtime_lock; | ||
| 159 | }; | ||
| 160 | |||
| 161 | } // namespace ConfigurationShared | ||
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 6cd557c29..97ae9e49a 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | #include "applets/qt_software_keyboard.h" | 24 | #include "applets/qt_software_keyboard.h" |
| 25 | #include "applets/qt_web_browser.h" | 25 | #include "applets/qt_web_browser.h" |
| 26 | #include "common/nvidia_flags.h" | 26 | #include "common/nvidia_flags.h" |
| 27 | #include "common/settings_enums.h" | ||
| 27 | #include "configuration/configure_input.h" | 28 | #include "configuration/configure_input.h" |
| 28 | #include "configuration/configure_per_game.h" | 29 | #include "configuration/configure_per_game.h" |
| 29 | #include "configuration/configure_tas.h" | 30 | #include "configuration/configure_tas.h" |
| @@ -1095,10 +1096,9 @@ void GMainWindow::InitializeWidgets() { | |||
| 1095 | aa_status_button->setFocusPolicy(Qt::NoFocus); | 1096 | aa_status_button->setFocusPolicy(Qt::NoFocus); |
| 1096 | connect(aa_status_button, &QPushButton::clicked, [&] { | 1097 | connect(aa_status_button, &QPushButton::clicked, [&] { |
| 1097 | auto aa_mode = Settings::values.anti_aliasing.GetValue(); | 1098 | auto aa_mode = Settings::values.anti_aliasing.GetValue(); |
| 1098 | if (aa_mode == Settings::AntiAliasing::LastAA) { | 1099 | aa_mode = static_cast<Settings::AntiAliasing>(static_cast<u32>(aa_mode) + 1); |
| 1100 | if (aa_mode == Settings::AntiAliasing::MaxEnum) { | ||
| 1099 | aa_mode = Settings::AntiAliasing::None; | 1101 | aa_mode = Settings::AntiAliasing::None; |
| 1100 | } else { | ||
| 1101 | aa_mode = static_cast<Settings::AntiAliasing>(static_cast<u32>(aa_mode) + 1); | ||
| 1102 | } | 1102 | } |
| 1103 | Settings::values.anti_aliasing.SetValue(aa_mode); | 1103 | Settings::values.anti_aliasing.SetValue(aa_mode); |
| 1104 | aa_status_button->setChecked(true); | 1104 | aa_status_button->setChecked(true); |
| @@ -1183,7 +1183,7 @@ void GMainWindow::InitializeWidgets() { | |||
| 1183 | QMenu context_menu; | 1183 | QMenu context_menu; |
| 1184 | 1184 | ||
| 1185 | for (auto const& gpu_accuracy_pair : Config::gpu_accuracy_texts_map) { | 1185 | for (auto const& gpu_accuracy_pair : Config::gpu_accuracy_texts_map) { |
| 1186 | if (gpu_accuracy_pair.first == Settings::GPUAccuracy::Extreme) { | 1186 | if (gpu_accuracy_pair.first == Settings::GpuAccuracy::Extreme) { |
| 1187 | continue; | 1187 | continue; |
| 1188 | } | 1188 | } |
| 1189 | context_menu.addAction(gpu_accuracy_pair.second, [this, gpu_accuracy_pair] { | 1189 | context_menu.addAction(gpu_accuracy_pair.second, [this, gpu_accuracy_pair] { |
| @@ -3651,14 +3651,14 @@ void GMainWindow::OnToggleDockedMode() { | |||
| 3651 | 3651 | ||
| 3652 | void GMainWindow::OnToggleGpuAccuracy() { | 3652 | void GMainWindow::OnToggleGpuAccuracy() { |
| 3653 | switch (Settings::values.gpu_accuracy.GetValue()) { | 3653 | switch (Settings::values.gpu_accuracy.GetValue()) { |
| 3654 | case Settings::GPUAccuracy::High: { | 3654 | case Settings::GpuAccuracy::High: { |
| 3655 | Settings::values.gpu_accuracy.SetValue(Settings::GPUAccuracy::Normal); | 3655 | Settings::values.gpu_accuracy.SetValue(Settings::GpuAccuracy::Normal); |
| 3656 | break; | 3656 | break; |
| 3657 | } | 3657 | } |
| 3658 | case Settings::GPUAccuracy::Normal: | 3658 | case Settings::GpuAccuracy::Normal: |
| 3659 | case Settings::GPUAccuracy::Extreme: | 3659 | case Settings::GpuAccuracy::Extreme: |
| 3660 | default: { | 3660 | default: { |
| 3661 | Settings::values.gpu_accuracy.SetValue(Settings::GPUAccuracy::High); | 3661 | Settings::values.gpu_accuracy.SetValue(Settings::GpuAccuracy::High); |
| 3662 | break; | 3662 | break; |
| 3663 | } | 3663 | } |
| 3664 | } | 3664 | } |
| @@ -3702,10 +3702,9 @@ void GMainWindow::OnIncreaseVolume() { | |||
| 3702 | 3702 | ||
| 3703 | void GMainWindow::OnToggleAdaptingFilter() { | 3703 | void GMainWindow::OnToggleAdaptingFilter() { |
| 3704 | auto filter = Settings::values.scaling_filter.GetValue(); | 3704 | auto filter = Settings::values.scaling_filter.GetValue(); |
| 3705 | if (filter == Settings::ScalingFilter::LastFilter) { | 3705 | filter = static_cast<Settings::ScalingFilter>(static_cast<u32>(filter) + 1); |
| 3706 | if (filter == Settings::ScalingFilter::MaxEnum) { | ||
| 3706 | filter = Settings::ScalingFilter::NearestNeighbor; | 3707 | filter = Settings::ScalingFilter::NearestNeighbor; |
| 3707 | } else { | ||
| 3708 | filter = static_cast<Settings::ScalingFilter>(static_cast<u32>(filter) + 1); | ||
| 3709 | } | 3708 | } |
| 3710 | Settings::values.scaling_filter.SetValue(filter); | 3709 | Settings::values.scaling_filter.SetValue(filter); |
| 3711 | filter_status_button->setChecked(true); | 3710 | filter_status_button->setChecked(true); |
| @@ -4071,7 +4070,7 @@ void GMainWindow::UpdateGPUAccuracyButton() { | |||
| 4071 | const auto gpu_accuracy = Settings::values.gpu_accuracy.GetValue(); | 4070 | const auto gpu_accuracy = Settings::values.gpu_accuracy.GetValue(); |
| 4072 | const auto gpu_accuracy_text = Config::gpu_accuracy_texts_map.find(gpu_accuracy)->second; | 4071 | const auto gpu_accuracy_text = Config::gpu_accuracy_texts_map.find(gpu_accuracy)->second; |
| 4073 | gpu_accuracy_button->setText(gpu_accuracy_text.toUpper()); | 4072 | gpu_accuracy_button->setText(gpu_accuracy_text.toUpper()); |
| 4074 | gpu_accuracy_button->setChecked(gpu_accuracy != Settings::GPUAccuracy::Normal); | 4073 | gpu_accuracy_button->setChecked(gpu_accuracy != Settings::GpuAccuracy::Normal); |
| 4075 | } | 4074 | } |
| 4076 | 4075 | ||
| 4077 | void GMainWindow::UpdateDockedButton() { | 4076 | void GMainWindow::UpdateDockedButton() { |
diff --git a/src/yuzu/multiplayer/direct_connect.cpp b/src/yuzu/multiplayer/direct_connect.cpp index d71cc23a7..a415a953f 100644 --- a/src/yuzu/multiplayer/direct_connect.cpp +++ b/src/yuzu/multiplayer/direct_connect.cpp | |||
| @@ -34,13 +34,14 @@ DirectConnectWindow::DirectConnectWindow(Core::System& system_, QWidget* parent) | |||
| 34 | connect(watcher, &QFutureWatcher<void>::finished, this, &DirectConnectWindow::OnConnection); | 34 | connect(watcher, &QFutureWatcher<void>::finished, this, &DirectConnectWindow::OnConnection); |
| 35 | 35 | ||
| 36 | ui->nickname->setValidator(validation.GetNickname()); | 36 | ui->nickname->setValidator(validation.GetNickname()); |
| 37 | ui->nickname->setText(UISettings::values.multiplayer_nickname.GetValue()); | 37 | ui->nickname->setText( |
| 38 | QString::fromStdString(UISettings::values.multiplayer_nickname.GetValue())); | ||
| 38 | if (ui->nickname->text().isEmpty() && !Settings::values.yuzu_username.GetValue().empty()) { | 39 | if (ui->nickname->text().isEmpty() && !Settings::values.yuzu_username.GetValue().empty()) { |
| 39 | // Use yuzu Web Service user name as nickname by default | 40 | // Use yuzu Web Service user name as nickname by default |
| 40 | ui->nickname->setText(QString::fromStdString(Settings::values.yuzu_username.GetValue())); | 41 | ui->nickname->setText(QString::fromStdString(Settings::values.yuzu_username.GetValue())); |
| 41 | } | 42 | } |
| 42 | ui->ip->setValidator(validation.GetIP()); | 43 | ui->ip->setValidator(validation.GetIP()); |
| 43 | ui->ip->setText(UISettings::values.multiplayer_ip.GetValue()); | 44 | ui->ip->setText(QString::fromStdString(UISettings::values.multiplayer_ip.GetValue())); |
| 44 | ui->port->setValidator(validation.GetPort()); | 45 | ui->port->setValidator(validation.GetPort()); |
| 45 | ui->port->setText(QString::number(UISettings::values.multiplayer_port.GetValue())); | 46 | ui->port->setText(QString::number(UISettings::values.multiplayer_port.GetValue())); |
| 46 | 47 | ||
| @@ -91,8 +92,8 @@ void DirectConnectWindow::Connect() { | |||
| 91 | } | 92 | } |
| 92 | 93 | ||
| 93 | // Store settings | 94 | // Store settings |
| 94 | UISettings::values.multiplayer_nickname = ui->nickname->text(); | 95 | UISettings::values.multiplayer_nickname = ui->nickname->text().toStdString(); |
| 95 | UISettings::values.multiplayer_ip = ui->ip->text(); | 96 | UISettings::values.multiplayer_ip = ui->ip->text().toStdString(); |
| 96 | if (ui->port->isModified() && !ui->port->text().isEmpty()) { | 97 | if (ui->port->isModified() && !ui->port->text().isEmpty()) { |
| 97 | UISettings::values.multiplayer_port = ui->port->text().toInt(); | 98 | UISettings::values.multiplayer_port = ui->port->text().toInt(); |
| 98 | } else { | 99 | } else { |
diff --git a/src/yuzu/multiplayer/host_room.cpp b/src/yuzu/multiplayer/host_room.cpp index a8faa5b24..ef364ee43 100644 --- a/src/yuzu/multiplayer/host_room.cpp +++ b/src/yuzu/multiplayer/host_room.cpp | |||
| @@ -55,12 +55,14 @@ HostRoomWindow::HostRoomWindow(QWidget* parent, QStandardItemModel* list, | |||
| 55 | connect(ui->host, &QPushButton::clicked, this, &HostRoomWindow::Host); | 55 | connect(ui->host, &QPushButton::clicked, this, &HostRoomWindow::Host); |
| 56 | 56 | ||
| 57 | // Restore the settings: | 57 | // Restore the settings: |
| 58 | ui->username->setText(UISettings::values.multiplayer_room_nickname.GetValue()); | 58 | ui->username->setText( |
| 59 | QString::fromStdString(UISettings::values.multiplayer_room_nickname.GetValue())); | ||
| 59 | if (ui->username->text().isEmpty() && !Settings::values.yuzu_username.GetValue().empty()) { | 60 | if (ui->username->text().isEmpty() && !Settings::values.yuzu_username.GetValue().empty()) { |
| 60 | // Use yuzu Web Service user name as nickname by default | 61 | // Use yuzu Web Service user name as nickname by default |
| 61 | ui->username->setText(QString::fromStdString(Settings::values.yuzu_username.GetValue())); | 62 | ui->username->setText(QString::fromStdString(Settings::values.yuzu_username.GetValue())); |
| 62 | } | 63 | } |
| 63 | ui->room_name->setText(UISettings::values.multiplayer_room_name.GetValue()); | 64 | ui->room_name->setText( |
| 65 | QString::fromStdString(UISettings::values.multiplayer_room_name.GetValue())); | ||
| 64 | ui->port->setText(QString::number(UISettings::values.multiplayer_room_port.GetValue())); | 66 | ui->port->setText(QString::number(UISettings::values.multiplayer_room_port.GetValue())); |
| 65 | ui->max_player->setValue(UISettings::values.multiplayer_max_player.GetValue()); | 67 | ui->max_player->setValue(UISettings::values.multiplayer_max_player.GetValue()); |
| 66 | int index = UISettings::values.multiplayer_host_type.GetValue(); | 68 | int index = UISettings::values.multiplayer_host_type.GetValue(); |
| @@ -72,7 +74,8 @@ HostRoomWindow::HostRoomWindow(QWidget* parent, QStandardItemModel* list, | |||
| 72 | if (index != -1) { | 74 | if (index != -1) { |
| 73 | ui->game_list->setCurrentIndex(index); | 75 | ui->game_list->setCurrentIndex(index); |
| 74 | } | 76 | } |
| 75 | ui->room_description->setText(UISettings::values.multiplayer_room_description.GetValue()); | 77 | ui->room_description->setText( |
| 78 | QString::fromStdString(UISettings::values.multiplayer_room_description.GetValue())); | ||
| 76 | } | 79 | } |
| 77 | 80 | ||
| 78 | HostRoomWindow::~HostRoomWindow() = default; | 81 | HostRoomWindow::~HostRoomWindow() = default; |
| @@ -218,8 +221,8 @@ void HostRoomWindow::Host() { | |||
| 218 | Network::NoPreferredIP, password, token); | 221 | Network::NoPreferredIP, password, token); |
| 219 | 222 | ||
| 220 | // Store settings | 223 | // Store settings |
| 221 | UISettings::values.multiplayer_room_nickname = ui->username->text(); | 224 | UISettings::values.multiplayer_room_nickname = ui->username->text().toStdString(); |
| 222 | UISettings::values.multiplayer_room_name = ui->room_name->text(); | 225 | UISettings::values.multiplayer_room_name = ui->room_name->text().toStdString(); |
| 223 | UISettings::values.multiplayer_game_id = | 226 | UISettings::values.multiplayer_game_id = |
| 224 | ui->game_list->currentData(GameListItemPath::ProgramIdRole).toLongLong(); | 227 | ui->game_list->currentData(GameListItemPath::ProgramIdRole).toLongLong(); |
| 225 | UISettings::values.multiplayer_max_player = ui->max_player->value(); | 228 | UISettings::values.multiplayer_max_player = ui->max_player->value(); |
| @@ -230,7 +233,8 @@ void HostRoomWindow::Host() { | |||
| 230 | } else { | 233 | } else { |
| 231 | UISettings::values.multiplayer_room_port = Network::DefaultRoomPort; | 234 | UISettings::values.multiplayer_room_port = Network::DefaultRoomPort; |
| 232 | } | 235 | } |
| 233 | UISettings::values.multiplayer_room_description = ui->room_description->toPlainText(); | 236 | UISettings::values.multiplayer_room_description = |
| 237 | ui->room_description->toPlainText().toStdString(); | ||
| 234 | ui->host->setEnabled(true); | 238 | ui->host->setEnabled(true); |
| 235 | emit SaveConfig(); | 239 | emit SaveConfig(); |
| 236 | close(); | 240 | close(); |
diff --git a/src/yuzu/multiplayer/lobby.cpp b/src/yuzu/multiplayer/lobby.cpp index 387f6f7c9..603e9ae3d 100644 --- a/src/yuzu/multiplayer/lobby.cpp +++ b/src/yuzu/multiplayer/lobby.cpp | |||
| @@ -60,7 +60,8 @@ Lobby::Lobby(QWidget* parent, QStandardItemModel* list, | |||
| 60 | ui->room_list->setContextMenuPolicy(Qt::CustomContextMenu); | 60 | ui->room_list->setContextMenuPolicy(Qt::CustomContextMenu); |
| 61 | 61 | ||
| 62 | ui->nickname->setValidator(validation.GetNickname()); | 62 | ui->nickname->setValidator(validation.GetNickname()); |
| 63 | ui->nickname->setText(UISettings::values.multiplayer_nickname.GetValue()); | 63 | ui->nickname->setText( |
| 64 | QString::fromStdString(UISettings::values.multiplayer_nickname.GetValue())); | ||
| 64 | 65 | ||
| 65 | // Try find the best nickname by default | 66 | // Try find the best nickname by default |
| 66 | if (ui->nickname->text().isEmpty() || ui->nickname->text() == QStringLiteral("yuzu")) { | 67 | if (ui->nickname->text().isEmpty() || ui->nickname->text() == QStringLiteral("yuzu")) { |
| @@ -202,9 +203,9 @@ void Lobby::OnJoinRoom(const QModelIndex& source) { | |||
| 202 | // TODO(jroweboy): disable widgets and display a connecting while we wait | 203 | // TODO(jroweboy): disable widgets and display a connecting while we wait |
| 203 | 204 | ||
| 204 | // Save settings | 205 | // Save settings |
| 205 | UISettings::values.multiplayer_nickname = ui->nickname->text(); | 206 | UISettings::values.multiplayer_nickname = ui->nickname->text().toStdString(); |
| 206 | UISettings::values.multiplayer_ip = | 207 | UISettings::values.multiplayer_ip = |
| 207 | proxy->data(connection_index, LobbyItemHost::HostIPRole).toString(); | 208 | proxy->data(connection_index, LobbyItemHost::HostIPRole).value<QString>().toStdString(); |
| 208 | UISettings::values.multiplayer_port = | 209 | UISettings::values.multiplayer_port = |
| 209 | proxy->data(connection_index, LobbyItemHost::HostPortRole).toInt(); | 210 | proxy->data(connection_index, LobbyItemHost::HostPortRole).toInt(); |
| 210 | emit SaveConfig(); | 211 | emit SaveConfig(); |
diff --git a/src/yuzu/uisettings.cpp b/src/yuzu/uisettings.cpp index 2c1b547fb..f03dc01dd 100644 --- a/src/yuzu/uisettings.cpp +++ b/src/yuzu/uisettings.cpp | |||
| @@ -3,6 +3,18 @@ | |||
| 3 | 3 | ||
| 4 | #include "yuzu/uisettings.h" | 4 | #include "yuzu/uisettings.h" |
| 5 | 5 | ||
| 6 | #ifndef CANNOT_EXPLICITLY_INSTANTIATE | ||
| 7 | namespace Settings { | ||
| 8 | template class Setting<bool>; | ||
| 9 | template class Setting<std::string>; | ||
| 10 | template class Setting<u16, true>; | ||
| 11 | template class Setting<u32>; | ||
| 12 | template class Setting<u8, true>; | ||
| 13 | template class Setting<u8>; | ||
| 14 | template class Setting<unsigned long long>; | ||
| 15 | } // namespace Settings | ||
| 16 | #endif | ||
| 17 | |||
| 6 | namespace UISettings { | 18 | namespace UISettings { |
| 7 | 19 | ||
| 8 | const Themes themes{{ | 20 | const Themes themes{{ |
diff --git a/src/yuzu/uisettings.h b/src/yuzu/uisettings.h index 20a517d34..c9c89cee4 100644 --- a/src/yuzu/uisettings.h +++ b/src/yuzu/uisettings.h | |||
| @@ -14,6 +14,21 @@ | |||
| 14 | #include "common/common_types.h" | 14 | #include "common/common_types.h" |
| 15 | #include "common/settings.h" | 15 | #include "common/settings.h" |
| 16 | 16 | ||
| 17 | using Settings::Category; | ||
| 18 | using Settings::Setting; | ||
| 19 | |||
| 20 | #ifndef CANNOT_EXPLICITLY_INSTANTIATE | ||
| 21 | namespace Settings { | ||
| 22 | extern template class Setting<bool>; | ||
| 23 | extern template class Setting<std::string>; | ||
| 24 | extern template class Setting<u16, true>; | ||
| 25 | extern template class Setting<u32>; | ||
| 26 | extern template class Setting<u8, true>; | ||
| 27 | extern template class Setting<u8>; | ||
| 28 | extern template class Setting<unsigned long long>; | ||
| 29 | } // namespace Settings | ||
| 30 | #endif | ||
| 31 | |||
| 17 | namespace UISettings { | 32 | namespace UISettings { |
| 18 | 33 | ||
| 19 | bool IsDarkTheme(); | 34 | bool IsDarkTheme(); |
| @@ -56,6 +71,8 @@ struct GameDir { | |||
| 56 | }; | 71 | }; |
| 57 | 72 | ||
| 58 | struct Values { | 73 | struct Values { |
| 74 | Settings::Linkage linkage{1000}; | ||
| 75 | |||
| 59 | QByteArray geometry; | 76 | QByteArray geometry; |
| 60 | QByteArray state; | 77 | QByteArray state; |
| 61 | 78 | ||
| @@ -64,30 +81,54 @@ struct Values { | |||
| 64 | QByteArray gamelist_header_state; | 81 | QByteArray gamelist_header_state; |
| 65 | 82 | ||
| 66 | QByteArray microprofile_geometry; | 83 | QByteArray microprofile_geometry; |
| 67 | Settings::Setting<bool> microprofile_visible{false, "microProfileDialogVisible"}; | 84 | Setting<bool> microprofile_visible{linkage, false, "microProfileDialogVisible", |
| 68 | 85 | Category::UiLayout}; | |
| 69 | Settings::Setting<bool> single_window_mode{true, "singleWindowMode"}; | 86 | |
| 70 | Settings::Setting<bool> fullscreen{false, "fullscreen"}; | 87 | Setting<bool> single_window_mode{linkage, true, "singleWindowMode", Category::Ui}; |
| 71 | Settings::Setting<bool> display_titlebar{true, "displayTitleBars"}; | 88 | Setting<bool> fullscreen{linkage, false, "fullscreen", Category::Ui}; |
| 72 | Settings::Setting<bool> show_filter_bar{true, "showFilterBar"}; | 89 | Setting<bool> display_titlebar{linkage, true, "displayTitleBars", Category::Ui}; |
| 73 | Settings::Setting<bool> show_status_bar{true, "showStatusBar"}; | 90 | Setting<bool> show_filter_bar{linkage, true, "showFilterBar", Category::Ui}; |
| 74 | 91 | Setting<bool> show_status_bar{linkage, true, "showStatusBar", Category::Ui}; | |
| 75 | Settings::Setting<bool> confirm_before_closing{true, "confirmClose"}; | 92 | |
| 76 | Settings::Setting<bool> first_start{true, "firstStart"}; | 93 | Setting<bool> confirm_before_closing{ |
| 77 | Settings::Setting<bool> pause_when_in_background{false, "pauseWhenInBackground"}; | 94 | linkage, true, "confirmClose", Category::UiGeneral, Settings::Specialization::Default, |
| 78 | Settings::Setting<bool> mute_when_in_background{false, "muteWhenInBackground"}; | 95 | true, true}; |
| 79 | Settings::Setting<bool> hide_mouse{true, "hideInactiveMouse"}; | 96 | Setting<bool> first_start{linkage, true, "firstStart", Category::Ui}; |
| 80 | Settings::Setting<bool> controller_applet_disabled{false, "disableControllerApplet"}; | 97 | Setting<bool> pause_when_in_background{linkage, |
| 81 | 98 | false, | |
| 99 | "pauseWhenInBackground", | ||
| 100 | Category::UiGeneral, | ||
| 101 | Settings::Specialization::Default, | ||
| 102 | true, | ||
| 103 | true}; | ||
| 104 | Setting<bool> mute_when_in_background{ | ||
| 105 | linkage, false, "muteWhenInBackground", Category::Ui, Settings::Specialization::Default, | ||
| 106 | true, true}; | ||
| 107 | Setting<bool> hide_mouse{ | ||
| 108 | linkage, true, "hideInactiveMouse", Category::UiGeneral, Settings::Specialization::Default, | ||
| 109 | true, true}; | ||
| 110 | Setting<bool> controller_applet_disabled{linkage, false, "disableControllerApplet", | ||
| 111 | Category::UiGeneral}; | ||
| 82 | // Set when Vulkan is known to crash the application | 112 | // Set when Vulkan is known to crash the application |
| 83 | bool has_broken_vulkan = false; | 113 | bool has_broken_vulkan = false; |
| 84 | 114 | ||
| 85 | Settings::Setting<bool> select_user_on_boot{false, "select_user_on_boot"}; | 115 | Setting<bool> select_user_on_boot{linkage, |
| 116 | false, | ||
| 117 | "select_user_on_boot", | ||
| 118 | Category::UiGeneral, | ||
| 119 | Settings::Specialization::Default, | ||
| 120 | true, | ||
| 121 | true}; | ||
| 122 | Setting<bool> disable_web_applet{linkage, true, "disable_web_applet", Category::Ui}; | ||
| 86 | 123 | ||
| 87 | // Discord RPC | 124 | // Discord RPC |
| 88 | Settings::Setting<bool> enable_discord_presence{true, "enable_discord_presence"}; | 125 | Setting<bool> enable_discord_presence{linkage, true, "enable_discord_presence", Category::Ui}; |
| 89 | 126 | ||
| 90 | Settings::Setting<bool> enable_screenshot_save_as{true, "enable_screenshot_save_as"}; | 127 | // logging |
| 128 | Setting<bool> show_console{linkage, false, "showConsole", Category::Ui}; | ||
| 129 | |||
| 130 | Setting<bool> enable_screenshot_save_as{linkage, true, "enable_screenshot_save_as", | ||
| 131 | Category::Screenshots}; | ||
| 91 | 132 | ||
| 92 | QString roms_path; | 133 | QString roms_path; |
| 93 | QString symbols_path; | 134 | QString symbols_path; |
| @@ -102,47 +143,46 @@ struct Values { | |||
| 102 | // Shortcut name <Shortcut, context> | 143 | // Shortcut name <Shortcut, context> |
| 103 | std::vector<Shortcut> shortcuts; | 144 | std::vector<Shortcut> shortcuts; |
| 104 | 145 | ||
| 105 | Settings::Setting<uint32_t> callout_flags{0, "calloutFlags"}; | 146 | Setting<u32> callout_flags{linkage, 0, "calloutFlags", Category::Ui}; |
| 106 | 147 | ||
| 107 | // multiplayer settings | 148 | // multiplayer settings |
| 108 | Settings::Setting<QString> multiplayer_nickname{{}, "nickname"}; | 149 | Setting<std::string> multiplayer_nickname{linkage, {}, "nickname", Category::Multiplayer}; |
| 109 | Settings::Setting<QString> multiplayer_ip{{}, "ip"}; | 150 | Setting<std::string> multiplayer_ip{linkage, {}, "ip", Category::Multiplayer}; |
| 110 | Settings::SwitchableSetting<uint, true> multiplayer_port{24872, 0, UINT16_MAX, "port"}; | 151 | Setting<u16, true> multiplayer_port{linkage, 24872, 0, |
| 111 | Settings::Setting<QString> multiplayer_room_nickname{{}, "room_nickname"}; | 152 | UINT16_MAX, "port", Category::Multiplayer}; |
| 112 | Settings::Setting<QString> multiplayer_room_name{{}, "room_name"}; | 153 | Setting<std::string> multiplayer_room_nickname{ |
| 113 | Settings::SwitchableSetting<uint, true> multiplayer_max_player{8, 0, 8, "max_player"}; | 154 | linkage, {}, "room_nickname", Category::Multiplayer}; |
| 114 | Settings::SwitchableSetting<uint, true> multiplayer_room_port{24872, 0, UINT16_MAX, | 155 | Setting<std::string> multiplayer_room_name{linkage, {}, "room_name", Category::Multiplayer}; |
| 115 | "room_port"}; | 156 | Setting<u8, true> multiplayer_max_player{linkage, 8, 0, 8, "max_player", Category::Multiplayer}; |
| 116 | Settings::SwitchableSetting<uint, true> multiplayer_host_type{0, 0, 1, "host_type"}; | 157 | Setting<u16, true> multiplayer_room_port{linkage, 24872, 0, |
| 117 | Settings::Setting<qulonglong> multiplayer_game_id{{}, "game_id"}; | 158 | UINT16_MAX, "room_port", Category::Multiplayer}; |
| 118 | Settings::Setting<QString> multiplayer_room_description{{}, "room_description"}; | 159 | Setting<u8, true> multiplayer_host_type{linkage, 0, 0, 1, "host_type", Category::Multiplayer}; |
| 160 | Setting<unsigned long long> multiplayer_game_id{linkage, {}, "game_id", Category::Multiplayer}; | ||
| 161 | Setting<std::string> multiplayer_room_description{ | ||
| 162 | linkage, {}, "room_description", Category::Multiplayer}; | ||
| 119 | std::pair<std::vector<std::string>, std::vector<std::string>> multiplayer_ban_list; | 163 | std::pair<std::vector<std::string>, std::vector<std::string>> multiplayer_ban_list; |
| 120 | 164 | ||
| 121 | // logging | ||
| 122 | Settings::Setting<bool> show_console{false, "showConsole"}; | ||
| 123 | |||
| 124 | // Game List | 165 | // Game List |
| 125 | Settings::Setting<bool> show_add_ons{true, "show_add_ons"}; | 166 | Setting<bool> show_add_ons{linkage, true, "show_add_ons", Category::UiGameList}; |
| 126 | Settings::Setting<uint32_t> game_icon_size{64, "game_icon_size"}; | 167 | Setting<u32> game_icon_size{linkage, 64, "game_icon_size", Category::UiGameList}; |
| 127 | Settings::Setting<uint32_t> folder_icon_size{48, "folder_icon_size"}; | 168 | Setting<u32> folder_icon_size{linkage, 48, "folder_icon_size", Category::UiGameList}; |
| 128 | Settings::Setting<uint8_t> row_1_text_id{3, "row_1_text_id"}; | 169 | Setting<u8> row_1_text_id{linkage, 3, "row_1_text_id", Category::UiGameList}; |
| 129 | Settings::Setting<uint8_t> row_2_text_id{2, "row_2_text_id"}; | 170 | Setting<u8> row_2_text_id{linkage, 2, "row_2_text_id", Category::UiGameList}; |
| 130 | std::atomic_bool is_game_list_reload_pending{false}; | 171 | std::atomic_bool is_game_list_reload_pending{false}; |
| 131 | Settings::Setting<bool> cache_game_list{true, "cache_game_list"}; | 172 | Setting<bool> cache_game_list{linkage, true, "cache_game_list", Category::UiGameList}; |
| 132 | Settings::Setting<bool> favorites_expanded{true, "favorites_expanded"}; | 173 | Setting<bool> favorites_expanded{linkage, true, "favorites_expanded", Category::UiGameList}; |
| 133 | QVector<u64> favorited_ids; | 174 | QVector<u64> favorited_ids; |
| 134 | 175 | ||
| 135 | // Compatibility List | 176 | // Compatibility List |
| 136 | Settings::Setting<bool> show_compat{false, "show_compat"}; | 177 | Setting<bool> show_compat{linkage, false, "show_compat", Category::UiGameList}; |
| 137 | 178 | ||
| 138 | // Size & File Types Column | 179 | // Size & File Types Column |
| 139 | Settings::Setting<bool> show_size{true, "show_size"}; | 180 | Setting<bool> show_size{linkage, true, "show_size", Category::UiGameList}; |
| 140 | Settings::Setting<bool> show_types{true, "show_types"}; | 181 | Setting<bool> show_types{linkage, true, "show_types", Category::UiGameList}; |
| 141 | 182 | ||
| 142 | bool configuration_applied; | 183 | bool configuration_applied; |
| 143 | bool reset_to_defaults; | 184 | bool reset_to_defaults; |
| 144 | bool shortcut_already_warned{false}; | 185 | bool shortcut_already_warned{false}; |
| 145 | Settings::Setting<bool> disable_web_applet{true, "disable_web_applet"}; | ||
| 146 | }; | 186 | }; |
| 147 | 187 | ||
| 148 | extern Values values; | 188 | extern Values values; |
diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp index c5bc472ca..c42d98709 100644 --- a/src/yuzu_cmd/config.cpp +++ b/src/yuzu_cmd/config.cpp | |||
| @@ -98,8 +98,26 @@ void Config::ReadSetting(const std::string& group, Settings::Setting<Type, range | |||
| 98 | static_cast<long>(setting.GetDefault()))); | 98 | static_cast<long>(setting.GetDefault()))); |
| 99 | } | 99 | } |
| 100 | 100 | ||
| 101 | void Config::ReadCategory(Settings::Category category) { | ||
| 102 | for (const auto setting : Settings::values.linkage.by_category[category]) { | ||
| 103 | const char* category_name = [&]() { | ||
| 104 | if (category == Settings::Category::Controls) { | ||
| 105 | // For compatibility with older configs | ||
| 106 | return "ControlsGeneral"; | ||
| 107 | } else { | ||
| 108 | return Settings::TranslateCategory(category); | ||
| 109 | } | ||
| 110 | }(); | ||
| 111 | std::string setting_value = | ||
| 112 | sdl2_config->Get(category_name, setting->GetLabel(), setting->DefaultToString()); | ||
| 113 | setting->LoadString(setting_value); | ||
| 114 | } | ||
| 115 | } | ||
| 116 | |||
| 101 | void Config::ReadValues() { | 117 | void Config::ReadValues() { |
| 102 | // Controls | 118 | // Controls |
| 119 | ReadCategory(Settings::Category::Controls); | ||
| 120 | |||
| 103 | for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) { | 121 | for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) { |
| 104 | auto& player = Settings::values.players.GetValue()[p]; | 122 | auto& player = Settings::values.players.GetValue()[p]; |
| 105 | 123 | ||
| @@ -139,13 +157,6 @@ void Config::ReadValues() { | |||
| 139 | player.connected = sdl2_config->GetBoolean(group, "connected", false); | 157 | player.connected = sdl2_config->GetBoolean(group, "connected", false); |
| 140 | } | 158 | } |
| 141 | 159 | ||
| 142 | ReadSetting("ControlsGeneral", Settings::values.mouse_enabled); | ||
| 143 | |||
| 144 | ReadSetting("ControlsGeneral", Settings::values.touch_device); | ||
| 145 | |||
| 146 | ReadSetting("ControlsGeneral", Settings::values.keyboard_enabled); | ||
| 147 | |||
| 148 | ReadSetting("ControlsGeneral", Settings::values.debug_pad_enabled); | ||
| 149 | for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { | 160 | for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { |
| 150 | std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); | 161 | std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); |
| 151 | Settings::values.debug_pad_buttons[i] = sdl2_config->Get( | 162 | Settings::values.debug_pad_buttons[i] = sdl2_config->Get( |
| @@ -166,14 +177,6 @@ void Config::ReadValues() { | |||
| 166 | Settings::values.debug_pad_analogs[i] = default_param; | 177 | Settings::values.debug_pad_analogs[i] = default_param; |
| 167 | } | 178 | } |
| 168 | 179 | ||
| 169 | ReadSetting("ControlsGeneral", Settings::values.enable_raw_input); | ||
| 170 | ReadSetting("ControlsGeneral", Settings::values.enable_joycon_driver); | ||
| 171 | ReadSetting("ControlsGeneral", Settings::values.enable_procon_driver); | ||
| 172 | ReadSetting("ControlsGeneral", Settings::values.random_amiibo_id); | ||
| 173 | ReadSetting("ControlsGeneral", Settings::values.emulate_analog_keyboard); | ||
| 174 | ReadSetting("ControlsGeneral", Settings::values.vibration_enabled); | ||
| 175 | ReadSetting("ControlsGeneral", Settings::values.enable_accurate_vibrations); | ||
| 176 | ReadSetting("ControlsGeneral", Settings::values.motion_enabled); | ||
| 177 | Settings::values.touchscreen.enabled = | 180 | Settings::values.touchscreen.enabled = |
| 178 | sdl2_config->GetBoolean("ControlsGeneral", "touch_enabled", true); | 181 | sdl2_config->GetBoolean("ControlsGeneral", "touch_enabled", true); |
| 179 | Settings::values.touchscreen.rotation_angle = | 182 | Settings::values.touchscreen.rotation_angle = |
| @@ -217,10 +220,24 @@ void Config::ReadValues() { | |||
| 217 | Settings::values.touch_from_button_map_index = std::clamp( | 220 | Settings::values.touch_from_button_map_index = std::clamp( |
| 218 | Settings::values.touch_from_button_map_index.GetValue(), 0, num_touch_from_button_maps - 1); | 221 | Settings::values.touch_from_button_map_index.GetValue(), 0, num_touch_from_button_maps - 1); |
| 219 | 222 | ||
| 220 | ReadSetting("ControlsGeneral", Settings::values.udp_input_servers); | 223 | ReadCategory(Settings::Category::Audio); |
| 224 | ReadCategory(Settings::Category::Core); | ||
| 225 | ReadCategory(Settings::Category::Cpu); | ||
| 226 | ReadCategory(Settings::Category::CpuDebug); | ||
| 227 | ReadCategory(Settings::Category::CpuUnsafe); | ||
| 228 | ReadCategory(Settings::Category::Renderer); | ||
| 229 | ReadCategory(Settings::Category::RendererAdvanced); | ||
| 230 | ReadCategory(Settings::Category::RendererDebug); | ||
| 231 | ReadCategory(Settings::Category::System); | ||
| 232 | ReadCategory(Settings::Category::SystemAudio); | ||
| 233 | ReadCategory(Settings::Category::DataStorage); | ||
| 234 | ReadCategory(Settings::Category::Debugging); | ||
| 235 | ReadCategory(Settings::Category::DebuggingGraphics); | ||
| 236 | ReadCategory(Settings::Category::Miscellaneous); | ||
| 237 | ReadCategory(Settings::Category::Network); | ||
| 238 | ReadCategory(Settings::Category::WebService); | ||
| 221 | 239 | ||
| 222 | // Data Storage | 240 | // Data Storage |
| 223 | ReadSetting("Data Storage", Settings::values.use_virtual_sd); | ||
| 224 | FS::SetYuzuPath(FS::YuzuPath::NANDDir, | 241 | FS::SetYuzuPath(FS::YuzuPath::NANDDir, |
| 225 | sdl2_config->Get("Data Storage", "nand_directory", | 242 | sdl2_config->Get("Data Storage", "nand_directory", |
| 226 | FS::GetYuzuPathString(FS::YuzuPath::NANDDir))); | 243 | FS::GetYuzuPathString(FS::YuzuPath::NANDDir))); |
| @@ -233,124 +250,10 @@ void Config::ReadValues() { | |||
| 233 | FS::SetYuzuPath(FS::YuzuPath::DumpDir, | 250 | FS::SetYuzuPath(FS::YuzuPath::DumpDir, |
| 234 | sdl2_config->Get("Data Storage", "dump_directory", | 251 | sdl2_config->Get("Data Storage", "dump_directory", |
| 235 | FS::GetYuzuPathString(FS::YuzuPath::DumpDir))); | 252 | FS::GetYuzuPathString(FS::YuzuPath::DumpDir))); |
| 236 | ReadSetting("Data Storage", Settings::values.gamecard_inserted); | ||
| 237 | ReadSetting("Data Storage", Settings::values.gamecard_current_game); | ||
| 238 | ReadSetting("Data Storage", Settings::values.gamecard_path); | ||
| 239 | |||
| 240 | // System | ||
| 241 | ReadSetting("System", Settings::values.use_docked_mode); | ||
| 242 | |||
| 243 | ReadSetting("System", Settings::values.current_user); | ||
| 244 | Settings::values.current_user = std::clamp<int>(Settings::values.current_user.GetValue(), 0, | ||
| 245 | Service::Account::MAX_USERS - 1); | ||
| 246 | |||
| 247 | const auto rng_seed_enabled = sdl2_config->GetBoolean("System", "rng_seed_enabled", false); | ||
| 248 | if (rng_seed_enabled) { | ||
| 249 | Settings::values.rng_seed.SetValue(sdl2_config->GetInteger("System", "rng_seed", 0)); | ||
| 250 | } else { | ||
| 251 | Settings::values.rng_seed.SetValue(std::nullopt); | ||
| 252 | } | ||
| 253 | |||
| 254 | const auto custom_rtc_enabled = sdl2_config->GetBoolean("System", "custom_rtc_enabled", false); | ||
| 255 | if (custom_rtc_enabled) { | ||
| 256 | Settings::values.custom_rtc = sdl2_config->GetInteger("System", "custom_rtc", 0); | ||
| 257 | } else { | ||
| 258 | Settings::values.custom_rtc = std::nullopt; | ||
| 259 | } | ||
| 260 | |||
| 261 | ReadSetting("System", Settings::values.language_index); | ||
| 262 | ReadSetting("System", Settings::values.region_index); | ||
| 263 | ReadSetting("System", Settings::values.time_zone_index); | ||
| 264 | ReadSetting("System", Settings::values.sound_index); | ||
| 265 | |||
| 266 | // Core | ||
| 267 | ReadSetting("Core", Settings::values.use_multi_core); | ||
| 268 | ReadSetting("Core", Settings::values.use_unsafe_extended_memory_layout); | ||
| 269 | |||
| 270 | // Cpu | ||
| 271 | ReadSetting("Cpu", Settings::values.cpu_accuracy); | ||
| 272 | ReadSetting("Cpu", Settings::values.cpu_debug_mode); | ||
| 273 | ReadSetting("Cpu", Settings::values.cpuopt_page_tables); | ||
| 274 | ReadSetting("Cpu", Settings::values.cpuopt_block_linking); | ||
| 275 | ReadSetting("Cpu", Settings::values.cpuopt_return_stack_buffer); | ||
| 276 | ReadSetting("Cpu", Settings::values.cpuopt_fast_dispatcher); | ||
| 277 | ReadSetting("Cpu", Settings::values.cpuopt_context_elimination); | ||
| 278 | ReadSetting("Cpu", Settings::values.cpuopt_const_prop); | ||
| 279 | ReadSetting("Cpu", Settings::values.cpuopt_misc_ir); | ||
| 280 | ReadSetting("Cpu", Settings::values.cpuopt_reduce_misalign_checks); | ||
| 281 | ReadSetting("Cpu", Settings::values.cpuopt_fastmem); | ||
| 282 | ReadSetting("Cpu", Settings::values.cpuopt_fastmem_exclusives); | ||
| 283 | ReadSetting("Cpu", Settings::values.cpuopt_recompile_exclusives); | ||
| 284 | ReadSetting("Cpu", Settings::values.cpuopt_ignore_memory_aborts); | ||
| 285 | ReadSetting("Cpu", Settings::values.cpuopt_unsafe_unfuse_fma); | ||
| 286 | ReadSetting("Cpu", Settings::values.cpuopt_unsafe_reduce_fp_error); | ||
| 287 | ReadSetting("Cpu", Settings::values.cpuopt_unsafe_ignore_standard_fpcr); | ||
| 288 | ReadSetting("Cpu", Settings::values.cpuopt_unsafe_inaccurate_nan); | ||
| 289 | ReadSetting("Cpu", Settings::values.cpuopt_unsafe_fastmem_check); | ||
| 290 | ReadSetting("Cpu", Settings::values.cpuopt_unsafe_ignore_global_monitor); | ||
| 291 | |||
| 292 | // Renderer | ||
| 293 | ReadSetting("Renderer", Settings::values.renderer_backend); | ||
| 294 | ReadSetting("Renderer", Settings::values.async_presentation); | ||
| 295 | ReadSetting("Renderer", Settings::values.renderer_force_max_clock); | ||
| 296 | ReadSetting("Renderer", Settings::values.renderer_debug); | ||
| 297 | ReadSetting("Renderer", Settings::values.renderer_shader_feedback); | ||
| 298 | ReadSetting("Renderer", Settings::values.enable_nsight_aftermath); | ||
| 299 | ReadSetting("Renderer", Settings::values.disable_shader_loop_safety_checks); | ||
| 300 | ReadSetting("Renderer", Settings::values.vulkan_device); | ||
| 301 | |||
| 302 | ReadSetting("Renderer", Settings::values.resolution_setup); | ||
| 303 | ReadSetting("Renderer", Settings::values.scaling_filter); | ||
| 304 | ReadSetting("Renderer", Settings::values.fsr_sharpening_slider); | ||
| 305 | ReadSetting("Renderer", Settings::values.anti_aliasing); | ||
| 306 | ReadSetting("Renderer", Settings::values.fullscreen_mode); | ||
| 307 | ReadSetting("Renderer", Settings::values.aspect_ratio); | ||
| 308 | ReadSetting("Renderer", Settings::values.max_anisotropy); | ||
| 309 | ReadSetting("Renderer", Settings::values.use_speed_limit); | ||
| 310 | ReadSetting("Renderer", Settings::values.speed_limit); | ||
| 311 | ReadSetting("Renderer", Settings::values.use_disk_shader_cache); | ||
| 312 | ReadSetting("Renderer", Settings::values.gpu_accuracy); | ||
| 313 | ReadSetting("Renderer", Settings::values.use_asynchronous_gpu_emulation); | ||
| 314 | ReadSetting("Renderer", Settings::values.vsync_mode); | ||
| 315 | ReadSetting("Renderer", Settings::values.shader_backend); | ||
| 316 | ReadSetting("Renderer", Settings::values.use_reactive_flushing); | ||
| 317 | ReadSetting("Renderer", Settings::values.use_asynchronous_shaders); | ||
| 318 | ReadSetting("Renderer", Settings::values.nvdec_emulation); | ||
| 319 | ReadSetting("Renderer", Settings::values.accelerate_astc); | ||
| 320 | ReadSetting("Renderer", Settings::values.async_astc); | ||
| 321 | ReadSetting("Renderer", Settings::values.astc_recompression); | ||
| 322 | ReadSetting("Renderer", Settings::values.use_fast_gpu_time); | ||
| 323 | ReadSetting("Renderer", Settings::values.use_vulkan_driver_pipeline_cache); | ||
| 324 | |||
| 325 | ReadSetting("Renderer", Settings::values.bg_red); | ||
| 326 | ReadSetting("Renderer", Settings::values.bg_green); | ||
| 327 | ReadSetting("Renderer", Settings::values.bg_blue); | ||
| 328 | |||
| 329 | // Audio | ||
| 330 | ReadSetting("Audio", Settings::values.sink_id); | ||
| 331 | ReadSetting("Audio", Settings::values.audio_output_device_id); | ||
| 332 | ReadSetting("Audio", Settings::values.volume); | ||
| 333 | |||
| 334 | // Miscellaneous | ||
| 335 | // log_filter has a different default here than from common | ||
| 336 | Settings::values.log_filter = | ||
| 337 | sdl2_config->Get("Miscellaneous", Settings::values.log_filter.GetLabel(), "*:Trace"); | ||
| 338 | ReadSetting("Miscellaneous", Settings::values.use_dev_keys); | ||
| 339 | 253 | ||
| 340 | // Debugging | 254 | // Debugging |
| 341 | Settings::values.record_frame_times = | 255 | Settings::values.record_frame_times = |
| 342 | sdl2_config->GetBoolean("Debugging", "record_frame_times", false); | 256 | sdl2_config->GetBoolean("Debugging", "record_frame_times", false); |
| 343 | ReadSetting("Debugging", Settings::values.dump_exefs); | ||
| 344 | ReadSetting("Debugging", Settings::values.dump_nso); | ||
| 345 | ReadSetting("Debugging", Settings::values.enable_fs_access_log); | ||
| 346 | ReadSetting("Debugging", Settings::values.reporting_services); | ||
| 347 | ReadSetting("Debugging", Settings::values.quest_flag); | ||
| 348 | ReadSetting("Debugging", Settings::values.use_debug_asserts); | ||
| 349 | ReadSetting("Debugging", Settings::values.use_auto_stub); | ||
| 350 | ReadSetting("Debugging", Settings::values.disable_macro_jit); | ||
| 351 | ReadSetting("Debugging", Settings::values.disable_macro_hle); | ||
| 352 | ReadSetting("Debugging", Settings::values.use_gdbstub); | ||
| 353 | ReadSetting("Debugging", Settings::values.gdbstub_port); | ||
| 354 | 257 | ||
| 355 | const auto title_list = sdl2_config->Get("AddOns", "title_ids", ""); | 258 | const auto title_list = sdl2_config->Get("AddOns", "title_ids", ""); |
| 356 | std::stringstream ss(title_list); | 259 | std::stringstream ss(title_list); |
| @@ -368,15 +271,6 @@ void Config::ReadValues() { | |||
| 368 | 271 | ||
| 369 | Settings::values.disabled_addons.insert_or_assign(title_id, out); | 272 | Settings::values.disabled_addons.insert_or_assign(title_id, out); |
| 370 | } | 273 | } |
| 371 | |||
| 372 | // Web Service | ||
| 373 | ReadSetting("WebService", Settings::values.enable_telemetry); | ||
| 374 | ReadSetting("WebService", Settings::values.web_api_url); | ||
| 375 | ReadSetting("WebService", Settings::values.yuzu_username); | ||
| 376 | ReadSetting("WebService", Settings::values.yuzu_token); | ||
| 377 | |||
| 378 | // Network | ||
| 379 | ReadSetting("Network", Settings::values.network_interface); | ||
| 380 | } | 274 | } |
| 381 | 275 | ||
| 382 | void Config::Reload() { | 276 | void Config::Reload() { |
diff --git a/src/yuzu_cmd/config.h b/src/yuzu_cmd/config.h index 021438b17..512591a39 100644 --- a/src/yuzu_cmd/config.h +++ b/src/yuzu_cmd/config.h | |||
| @@ -34,4 +34,5 @@ private: | |||
| 34 | */ | 34 | */ |
| 35 | template <typename Type, bool ranged> | 35 | template <typename Type, bool ranged> |
| 36 | void ReadSetting(const std::string& group, Settings::Setting<Type, ranged>& setting); | 36 | void ReadSetting(const std::string& group, Settings::Setting<Type, ranged>& setting); |
| 37 | void ReadCategory(Settings::Category category); | ||
| 37 | }; | 38 | }; |