diff options
57 files changed, 1942 insertions, 835 deletions
diff --git a/src/audio_core/cubeb_sink.cpp b/src/audio_core/cubeb_sink.cpp index c4e0e30fe..41bf5cd4d 100644 --- a/src/audio_core/cubeb_sink.cpp +++ b/src/audio_core/cubeb_sink.cpp | |||
| @@ -193,7 +193,7 @@ long CubebSinkStream::DataCallback(cubeb_stream* stream, void* user_data, const | |||
| 193 | const std::size_t samples_to_write = num_channels * num_frames; | 193 | const std::size_t samples_to_write = num_channels * num_frames; |
| 194 | std::size_t samples_written; | 194 | std::size_t samples_written; |
| 195 | 195 | ||
| 196 | if (Settings::values.enable_audio_stretching) { | 196 | if (Settings::values.enable_audio_stretching.GetValue()) { |
| 197 | const std::vector<s16> in{impl->queue.Pop()}; | 197 | const std::vector<s16> in{impl->queue.Pop()}; |
| 198 | const std::size_t num_in{in.size() / num_channels}; | 198 | const std::size_t num_in{in.size() / num_channels}; |
| 199 | s16* const out{reinterpret_cast<s16*>(buffer)}; | 199 | s16* const out{reinterpret_cast<s16*>(buffer)}; |
diff --git a/src/audio_core/stream.cpp b/src/audio_core/stream.cpp index 22e8df373..aab3e979a 100644 --- a/src/audio_core/stream.cpp +++ b/src/audio_core/stream.cpp | |||
| @@ -105,9 +105,10 @@ void Stream::PlayNextBuffer(s64 cycles_late) { | |||
| 105 | 105 | ||
| 106 | sink_stream.EnqueueSamples(GetNumChannels(), active_buffer->GetSamples()); | 106 | sink_stream.EnqueueSamples(GetNumChannels(), active_buffer->GetSamples()); |
| 107 | 107 | ||
| 108 | core_timing.ScheduleEvent(GetBufferReleaseNS(*active_buffer) - | 108 | core_timing.ScheduleEvent( |
| 109 | (Settings::values.enable_audio_stretching ? 0 : cycles_late), | 109 | GetBufferReleaseNS(*active_buffer) - |
| 110 | release_event, {}); | 110 | (Settings::values.enable_audio_stretching.GetValue() ? 0 : cycles_late), |
| 111 | release_event, {}); | ||
| 111 | } | 112 | } |
| 112 | 113 | ||
| 113 | void Stream::ReleaseActiveBuffer(s64 cycles_late) { | 114 | void Stream::ReleaseActiveBuffer(s64 cycles_late) { |
diff --git a/src/core/core.cpp b/src/core/core.cpp index 1a243c515..69a1aa0a5 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp | |||
| @@ -147,8 +147,8 @@ struct System::Impl { | |||
| 147 | 147 | ||
| 148 | device_memory = std::make_unique<Core::DeviceMemory>(system); | 148 | device_memory = std::make_unique<Core::DeviceMemory>(system); |
| 149 | 149 | ||
| 150 | is_multicore = Settings::values.use_multi_core; | 150 | is_multicore = Settings::values.use_multi_core.GetValue(); |
| 151 | is_async_gpu = is_multicore || Settings::values.use_asynchronous_gpu_emulation; | 151 | is_async_gpu = is_multicore || Settings::values.use_asynchronous_gpu_emulation.GetValue(); |
| 152 | 152 | ||
| 153 | kernel.SetMulticore(is_multicore); | 153 | kernel.SetMulticore(is_multicore); |
| 154 | cpu_manager.SetMulticore(is_multicore); | 154 | cpu_manager.SetMulticore(is_multicore); |
| @@ -162,7 +162,7 @@ struct System::Impl { | |||
| 162 | const auto current_time = std::chrono::duration_cast<std::chrono::seconds>( | 162 | const auto current_time = std::chrono::duration_cast<std::chrono::seconds>( |
| 163 | std::chrono::system_clock::now().time_since_epoch()); | 163 | std::chrono::system_clock::now().time_since_epoch()); |
| 164 | Settings::values.custom_rtc_differential = | 164 | Settings::values.custom_rtc_differential = |
| 165 | Settings::values.custom_rtc.value_or(current_time) - current_time; | 165 | Settings::values.custom_rtc.GetValue().value_or(current_time) - current_time; |
| 166 | 166 | ||
| 167 | // Create a default fs if one doesn't already exist. | 167 | // Create a default fs if one doesn't already exist. |
| 168 | if (virtual_filesystem == nullptr) | 168 | if (virtual_filesystem == nullptr) |
diff --git a/src/core/frontend/framebuffer_layout.cpp b/src/core/frontend/framebuffer_layout.cpp index d0c43447c..c1fbc235b 100644 --- a/src/core/frontend/framebuffer_layout.cpp +++ b/src/core/frontend/framebuffer_layout.cpp | |||
| @@ -29,7 +29,7 @@ FramebufferLayout DefaultFrameLayout(u32 width, u32 height) { | |||
| 29 | 29 | ||
| 30 | const float window_aspect_ratio = static_cast<float>(height) / width; | 30 | const float window_aspect_ratio = static_cast<float>(height) / width; |
| 31 | const float emulation_aspect_ratio = EmulationAspectRatio( | 31 | const float emulation_aspect_ratio = EmulationAspectRatio( |
| 32 | static_cast<AspectRatio>(Settings::values.aspect_ratio), window_aspect_ratio); | 32 | static_cast<AspectRatio>(Settings::values.aspect_ratio.GetValue()), window_aspect_ratio); |
| 33 | 33 | ||
| 34 | const Common::Rectangle<u32> screen_window_area{0, 0, width, height}; | 34 | const Common::Rectangle<u32> screen_window_area{0, 0, width, height}; |
| 35 | Common::Rectangle<u32> screen = MaxRectangle(screen_window_area, emulation_aspect_ratio); | 35 | Common::Rectangle<u32> screen = MaxRectangle(screen_window_area, emulation_aspect_ratio); |
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index f9d7c024d..c6fcb56ad 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp | |||
| @@ -123,7 +123,7 @@ std::shared_ptr<Process> Process::Create(Core::System& system, std::string name, | |||
| 123 | : kernel.CreateNewUserProcessID(); | 123 | : kernel.CreateNewUserProcessID(); |
| 124 | process->capabilities.InitializeForMetadatalessProcess(); | 124 | process->capabilities.InitializeForMetadatalessProcess(); |
| 125 | 125 | ||
| 126 | std::mt19937 rng(Settings::values.rng_seed.value_or(0)); | 126 | std::mt19937 rng(Settings::values.rng_seed.GetValue().value_or(0)); |
| 127 | std::uniform_int_distribution<u64> distribution; | 127 | std::uniform_int_distribution<u64> distribution; |
| 128 | std::generate(process->random_entropy.begin(), process->random_entropy.end(), | 128 | std::generate(process->random_entropy.begin(), process->random_entropy.end(), |
| 129 | [&] { return distribution(rng); }); | 129 | [&] { return distribution(rng); }); |
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index c688d6d98..256449aa7 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp | |||
| @@ -749,14 +749,14 @@ void ICommonStateGetter::GetDefaultDisplayResolution(Kernel::HLERequestContext& | |||
| 749 | 749 | ||
| 750 | if (Settings::values.use_docked_mode) { | 750 | if (Settings::values.use_docked_mode) { |
| 751 | rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedWidth) * | 751 | rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedWidth) * |
| 752 | static_cast<u32>(Settings::values.resolution_factor)); | 752 | static_cast<u32>(Settings::values.resolution_factor.GetValue())); |
| 753 | rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedHeight) * | 753 | rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedHeight) * |
| 754 | static_cast<u32>(Settings::values.resolution_factor)); | 754 | static_cast<u32>(Settings::values.resolution_factor.GetValue())); |
| 755 | } else { | 755 | } else { |
| 756 | rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedWidth) * | 756 | rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedWidth) * |
| 757 | static_cast<u32>(Settings::values.resolution_factor)); | 757 | static_cast<u32>(Settings::values.resolution_factor.GetValue())); |
| 758 | rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedHeight) * | 758 | rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedHeight) * |
| 759 | static_cast<u32>(Settings::values.resolution_factor)); | 759 | static_cast<u32>(Settings::values.resolution_factor.GetValue())); |
| 760 | } | 760 | } |
| 761 | } | 761 | } |
| 762 | 762 | ||
diff --git a/src/core/hle/service/ns/ns.cpp b/src/core/hle/service/ns/ns.cpp index 7e5ceccdb..6cfa9666d 100644 --- a/src/core/hle/service/ns/ns.cpp +++ b/src/core/hle/service/ns/ns.cpp | |||
| @@ -366,7 +366,8 @@ ResultVal<u8> IApplicationManagerInterface::GetApplicationDesiredLanguage( | |||
| 366 | LOG_DEBUG(Service_NS, "called with supported_languages={:08X}", supported_languages); | 366 | LOG_DEBUG(Service_NS, "called with supported_languages={:08X}", supported_languages); |
| 367 | 367 | ||
| 368 | // Get language code from settings | 368 | // Get language code from settings |
| 369 | const auto language_code = Set::GetLanguageCodeFromIndex(Settings::values.language_index); | 369 | const auto language_code = |
| 370 | Set::GetLanguageCodeFromIndex(Settings::values.language_index.GetValue()); | ||
| 370 | 371 | ||
| 371 | // Convert to application language, get priority list | 372 | // Convert to application language, get priority list |
| 372 | const auto application_language = ConvertToApplicationLanguage(language_code); | 373 | 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 e5cfd2101..34fe2fd82 100644 --- a/src/core/hle/service/set/set.cpp +++ b/src/core/hle/service/set/set.cpp | |||
| @@ -91,7 +91,7 @@ void GetAvailableLanguageCodesImpl(Kernel::HLERequestContext& ctx, std::size_t m | |||
| 91 | } | 91 | } |
| 92 | 92 | ||
| 93 | void GetKeyCodeMapImpl(Kernel::HLERequestContext& ctx) { | 93 | void GetKeyCodeMapImpl(Kernel::HLERequestContext& ctx) { |
| 94 | const auto language_code = available_language_codes[Settings::values.language_index]; | 94 | const auto language_code = available_language_codes[Settings::values.language_index.GetValue()]; |
| 95 | const auto key_code = | 95 | const auto key_code = |
| 96 | std::find_if(language_to_layout.cbegin(), language_to_layout.cend(), | 96 | std::find_if(language_to_layout.cbegin(), language_to_layout.cend(), |
| 97 | [=](const auto& element) { return element.first == language_code; }); | 97 | [=](const auto& element) { return element.first == language_code; }); |
| @@ -99,7 +99,7 @@ void GetKeyCodeMapImpl(Kernel::HLERequestContext& ctx) { | |||
| 99 | if (key_code == language_to_layout.cend()) { | 99 | if (key_code == language_to_layout.cend()) { |
| 100 | LOG_ERROR(Service_SET, | 100 | LOG_ERROR(Service_SET, |
| 101 | "Could not find keyboard layout for language index {}, defaulting to English us", | 101 | "Could not find keyboard layout for language index {}, defaulting to English us", |
| 102 | Settings::values.language_index); | 102 | Settings::values.language_index.GetValue()); |
| 103 | } else { | 103 | } else { |
| 104 | layout = key_code->second; | 104 | layout = key_code->second; |
| 105 | } | 105 | } |
| @@ -163,11 +163,11 @@ void SET::GetQuestFlag(Kernel::HLERequestContext& ctx) { | |||
| 163 | } | 163 | } |
| 164 | 164 | ||
| 165 | void SET::GetLanguageCode(Kernel::HLERequestContext& ctx) { | 165 | void SET::GetLanguageCode(Kernel::HLERequestContext& ctx) { |
| 166 | LOG_DEBUG(Service_SET, "called {}", Settings::values.language_index); | 166 | LOG_DEBUG(Service_SET, "called {}", Settings::values.language_index.GetValue()); |
| 167 | 167 | ||
| 168 | IPC::ResponseBuilder rb{ctx, 4}; | 168 | IPC::ResponseBuilder rb{ctx, 4}; |
| 169 | rb.Push(RESULT_SUCCESS); | 169 | rb.Push(RESULT_SUCCESS); |
| 170 | rb.PushEnum(available_language_codes[Settings::values.language_index]); | 170 | rb.PushEnum(available_language_codes[Settings::values.language_index.GetValue()]); |
| 171 | } | 171 | } |
| 172 | 172 | ||
| 173 | void SET::GetRegionCode(Kernel::HLERequestContext& ctx) { | 173 | void SET::GetRegionCode(Kernel::HLERequestContext& ctx) { |
| @@ -175,7 +175,7 @@ void SET::GetRegionCode(Kernel::HLERequestContext& ctx) { | |||
| 175 | 175 | ||
| 176 | IPC::ResponseBuilder rb{ctx, 3}; | 176 | IPC::ResponseBuilder rb{ctx, 3}; |
| 177 | rb.Push(RESULT_SUCCESS); | 177 | rb.Push(RESULT_SUCCESS); |
| 178 | rb.Push(Settings::values.region_index); | 178 | rb.Push(Settings::values.region_index.GetValue()); |
| 179 | } | 179 | } |
| 180 | 180 | ||
| 181 | void SET::GetKeyCodeMap(Kernel::HLERequestContext& ctx) { | 181 | void SET::GetKeyCodeMap(Kernel::HLERequestContext& ctx) { |
diff --git a/src/core/hle/service/spl/module.cpp b/src/core/hle/service/spl/module.cpp index e724d4ab8..865ed3b91 100644 --- a/src/core/hle/service/spl/module.cpp +++ b/src/core/hle/service/spl/module.cpp | |||
| @@ -19,7 +19,7 @@ namespace Service::SPL { | |||
| 19 | 19 | ||
| 20 | Module::Interface::Interface(std::shared_ptr<Module> module, const char* name) | 20 | Module::Interface::Interface(std::shared_ptr<Module> module, const char* name) |
| 21 | : ServiceFramework(name), module(std::move(module)), | 21 | : ServiceFramework(name), module(std::move(module)), |
| 22 | rng(Settings::values.rng_seed.value_or(std::time(nullptr))) {} | 22 | rng(Settings::values.rng_seed.GetValue().value_or(std::time(nullptr))) {} |
| 23 | 23 | ||
| 24 | Module::Interface::~Interface() = default; | 24 | Module::Interface::~Interface() = default; |
| 25 | 25 | ||
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index 157092074..552a5e4ef 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp | |||
| @@ -519,9 +519,9 @@ private: | |||
| 519 | IGBPConnectRequestParcel request{ctx.ReadBuffer()}; | 519 | IGBPConnectRequestParcel request{ctx.ReadBuffer()}; |
| 520 | IGBPConnectResponseParcel response{ | 520 | IGBPConnectResponseParcel response{ |
| 521 | static_cast<u32>(static_cast<u32>(DisplayResolution::UndockedWidth) * | 521 | static_cast<u32>(static_cast<u32>(DisplayResolution::UndockedWidth) * |
| 522 | Settings::values.resolution_factor), | 522 | Settings::values.resolution_factor.GetValue()), |
| 523 | static_cast<u32>(static_cast<u32>(DisplayResolution::UndockedHeight) * | 523 | static_cast<u32>(static_cast<u32>(DisplayResolution::UndockedHeight) * |
| 524 | Settings::values.resolution_factor)}; | 524 | Settings::values.resolution_factor.GetValue())}; |
| 525 | ctx.WriteBuffer(response.Serialize()); | 525 | ctx.WriteBuffer(response.Serialize()); |
| 526 | break; | 526 | break; |
| 527 | } | 527 | } |
| @@ -748,14 +748,14 @@ private: | |||
| 748 | 748 | ||
| 749 | if (Settings::values.use_docked_mode) { | 749 | if (Settings::values.use_docked_mode) { |
| 750 | rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedWidth) * | 750 | rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedWidth) * |
| 751 | static_cast<u32>(Settings::values.resolution_factor)); | 751 | static_cast<u32>(Settings::values.resolution_factor.GetValue())); |
| 752 | rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedHeight) * | 752 | rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedHeight) * |
| 753 | static_cast<u32>(Settings::values.resolution_factor)); | 753 | static_cast<u32>(Settings::values.resolution_factor.GetValue())); |
| 754 | } else { | 754 | } else { |
| 755 | rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedWidth) * | 755 | rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedWidth) * |
| 756 | static_cast<u32>(Settings::values.resolution_factor)); | 756 | static_cast<u32>(Settings::values.resolution_factor.GetValue())); |
| 757 | rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedHeight) * | 757 | rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedHeight) * |
| 758 | static_cast<u32>(Settings::values.resolution_factor)); | 758 | static_cast<u32>(Settings::values.resolution_factor.GetValue())); |
| 759 | } | 759 | } |
| 760 | 760 | ||
| 761 | rb.PushRaw<float>(60.0f); // This wouldn't seem to be correct for 30 fps games. | 761 | rb.PushRaw<float>(60.0f); // This wouldn't seem to be correct for 30 fps games. |
| @@ -1029,9 +1029,9 @@ private: | |||
| 1029 | // between docked and undocked dimensions. We take the liberty of applying | 1029 | // between docked and undocked dimensions. We take the liberty of applying |
| 1030 | // the resolution scaling factor here. | 1030 | // the resolution scaling factor here. |
| 1031 | rb.Push(static_cast<u64>(DisplayResolution::UndockedWidth) * | 1031 | rb.Push(static_cast<u64>(DisplayResolution::UndockedWidth) * |
| 1032 | static_cast<u32>(Settings::values.resolution_factor)); | 1032 | static_cast<u32>(Settings::values.resolution_factor.GetValue())); |
| 1033 | rb.Push(static_cast<u64>(DisplayResolution::UndockedHeight) * | 1033 | rb.Push(static_cast<u64>(DisplayResolution::UndockedHeight) * |
| 1034 | static_cast<u32>(Settings::values.resolution_factor)); | 1034 | static_cast<u32>(Settings::values.resolution_factor.GetValue())); |
| 1035 | } | 1035 | } |
| 1036 | 1036 | ||
| 1037 | void SetLayerScalingMode(Kernel::HLERequestContext& ctx) { | 1037 | void SetLayerScalingMode(Kernel::HLERequestContext& ctx) { |
| @@ -1064,8 +1064,8 @@ private: | |||
| 1064 | LOG_WARNING(Service_VI, "(STUBBED) called"); | 1064 | LOG_WARNING(Service_VI, "(STUBBED) called"); |
| 1065 | 1065 | ||
| 1066 | DisplayInfo display_info; | 1066 | DisplayInfo display_info; |
| 1067 | display_info.width *= static_cast<u64>(Settings::values.resolution_factor); | 1067 | display_info.width *= static_cast<u64>(Settings::values.resolution_factor.GetValue()); |
| 1068 | display_info.height *= static_cast<u64>(Settings::values.resolution_factor); | 1068 | display_info.height *= static_cast<u64>(Settings::values.resolution_factor.GetValue()); |
| 1069 | ctx.WriteBuffer(&display_info, sizeof(DisplayInfo)); | 1069 | ctx.WriteBuffer(&display_info, sizeof(DisplayInfo)); |
| 1070 | IPC::ResponseBuilder rb{ctx, 4}; | 1070 | IPC::ResponseBuilder rb{ctx, 4}; |
| 1071 | rb.Push(RESULT_SUCCESS); | 1071 | rb.Push(RESULT_SUCCESS); |
diff --git a/src/core/perf_stats.cpp b/src/core/perf_stats.cpp index 9f3a6b811..29339ead7 100644 --- a/src/core/perf_stats.cpp +++ b/src/core/perf_stats.cpp | |||
| @@ -119,13 +119,14 @@ double PerfStats::GetLastFrameTimeScale() { | |||
| 119 | } | 119 | } |
| 120 | 120 | ||
| 121 | void FrameLimiter::DoFrameLimiting(microseconds current_system_time_us) { | 121 | void FrameLimiter::DoFrameLimiting(microseconds current_system_time_us) { |
| 122 | if (!Settings::values.use_frame_limit || Settings::values.use_multi_core) { | 122 | if (!Settings::values.use_frame_limit.GetValue() || |
| 123 | Settings::values.use_multi_core.GetValue()) { | ||
| 123 | return; | 124 | return; |
| 124 | } | 125 | } |
| 125 | 126 | ||
| 126 | auto now = Clock::now(); | 127 | auto now = Clock::now(); |
| 127 | 128 | ||
| 128 | const double sleep_scale = Settings::values.frame_limit / 100.0; | 129 | const double sleep_scale = Settings::values.frame_limit.GetValue() / 100.0; |
| 129 | 130 | ||
| 130 | // Max lag caused by slow frames. Shouldn't be more than the length of a frame at the current | 131 | // Max lag caused by slow frames. Shouldn't be more than the length of a frame at the current |
| 131 | // speed percent or it will clamp too much and prevent this from properly limiting to that | 132 | // speed percent or it will clamp too much and prevent this from properly limiting to that |
diff --git a/src/core/settings.cpp b/src/core/settings.cpp index 56df5e925..d3886c4ec 100644 --- a/src/core/settings.cpp +++ b/src/core/settings.cpp | |||
| @@ -62,6 +62,7 @@ const std::array<const char*, NumMouseButtons> mapping = {{ | |||
| 62 | } | 62 | } |
| 63 | 63 | ||
| 64 | Values values = {}; | 64 | Values values = {}; |
| 65 | bool configuring_global = true; | ||
| 65 | 66 | ||
| 66 | std::string GetTimeZoneString() { | 67 | std::string GetTimeZoneString() { |
| 67 | static constexpr std::array<const char*, 46> timezones{{ | 68 | static constexpr std::array<const char*, 46> timezones{{ |
| @@ -73,9 +74,9 @@ std::string GetTimeZoneString() { | |||
| 73 | "UCT", "Universal", "UTC", "W-SU", "WET", "Zulu", | 74 | "UCT", "Universal", "UTC", "W-SU", "WET", "Zulu", |
| 74 | }}; | 75 | }}; |
| 75 | 76 | ||
| 76 | ASSERT(Settings::values.time_zone_index < timezones.size()); | 77 | ASSERT(Settings::values.time_zone_index.GetValue() < timezones.size()); |
| 77 | 78 | ||
| 78 | return timezones[Settings::values.time_zone_index]; | 79 | return timezones[Settings::values.time_zone_index.GetValue()]; |
| 79 | } | 80 | } |
| 80 | 81 | ||
| 81 | void Apply() { | 82 | void Apply() { |
| @@ -97,25 +98,25 @@ void LogSetting(const std::string& name, const T& value) { | |||
| 97 | 98 | ||
| 98 | void LogSettings() { | 99 | void LogSettings() { |
| 99 | LOG_INFO(Config, "yuzu Configuration:"); | 100 | LOG_INFO(Config, "yuzu Configuration:"); |
| 100 | LogSetting("System_UseDockedMode", Settings::values.use_docked_mode); | 101 | LogSetting("Controls_UseDockedMode", Settings::values.use_docked_mode); |
| 101 | LogSetting("System_RngSeed", Settings::values.rng_seed.value_or(0)); | 102 | LogSetting("System_RngSeed", Settings::values.rng_seed.GetValue().value_or(0)); |
| 102 | LogSetting("System_CurrentUser", Settings::values.current_user); | 103 | LogSetting("System_CurrentUser", Settings::values.current_user); |
| 103 | LogSetting("System_LanguageIndex", Settings::values.language_index); | 104 | LogSetting("System_LanguageIndex", Settings::values.language_index.GetValue()); |
| 104 | LogSetting("System_RegionIndex", Settings::values.region_index); | 105 | LogSetting("System_RegionIndex", Settings::values.region_index.GetValue()); |
| 105 | LogSetting("System_TimeZoneIndex", Settings::values.time_zone_index); | 106 | LogSetting("System_TimeZoneIndex", Settings::values.time_zone_index.GetValue()); |
| 106 | LogSetting("Core_UseMultiCore", Settings::values.use_multi_core); | 107 | LogSetting("Core_UseMultiCore", Settings::values.use_multi_core.GetValue()); |
| 107 | LogSetting("Renderer_UseResolutionFactor", Settings::values.resolution_factor); | 108 | LogSetting("Renderer_UseResolutionFactor", Settings::values.resolution_factor.GetValue()); |
| 108 | LogSetting("Renderer_UseFrameLimit", Settings::values.use_frame_limit); | 109 | LogSetting("Renderer_UseFrameLimit", Settings::values.use_frame_limit.GetValue()); |
| 109 | LogSetting("Renderer_FrameLimit", Settings::values.frame_limit); | 110 | LogSetting("Renderer_FrameLimit", Settings::values.frame_limit.GetValue()); |
| 110 | LogSetting("Renderer_UseDiskShaderCache", Settings::values.use_disk_shader_cache); | 111 | LogSetting("Renderer_UseDiskShaderCache", Settings::values.use_disk_shader_cache.GetValue()); |
| 111 | LogSetting("Renderer_GPUAccuracyLevel", Settings::values.gpu_accuracy); | 112 | LogSetting("Renderer_GPUAccuracyLevel", Settings::values.gpu_accuracy.GetValue()); |
| 112 | LogSetting("Renderer_UseAsynchronousGpuEmulation", | 113 | LogSetting("Renderer_UseAsynchronousGpuEmulation", |
| 113 | Settings::values.use_asynchronous_gpu_emulation); | 114 | Settings::values.use_asynchronous_gpu_emulation.GetValue()); |
| 114 | LogSetting("Renderer_UseVsync", Settings::values.use_vsync); | 115 | LogSetting("Renderer_UseVsync", Settings::values.use_vsync.GetValue()); |
| 115 | LogSetting("Renderer_UseAssemblyShaders", Settings::values.use_assembly_shaders); | 116 | LogSetting("Renderer_UseAssemblyShaders", Settings::values.use_assembly_shaders.GetValue()); |
| 116 | LogSetting("Renderer_AnisotropicFilteringLevel", Settings::values.max_anisotropy); | 117 | LogSetting("Renderer_AnisotropicFilteringLevel", Settings::values.max_anisotropy.GetValue()); |
| 117 | LogSetting("Audio_OutputEngine", Settings::values.sink_id); | 118 | LogSetting("Audio_OutputEngine", Settings::values.sink_id); |
| 118 | LogSetting("Audio_EnableAudioStretching", Settings::values.enable_audio_stretching); | 119 | LogSetting("Audio_EnableAudioStretching", Settings::values.enable_audio_stretching.GetValue()); |
| 119 | LogSetting("Audio_OutputDevice", Settings::values.audio_device_id); | 120 | LogSetting("Audio_OutputDevice", Settings::values.audio_device_id); |
| 120 | LogSetting("DataStorage_UseVirtualSd", Settings::values.use_virtual_sd); | 121 | LogSetting("DataStorage_UseVirtualSd", Settings::values.use_virtual_sd); |
| 121 | LogSetting("DataStorage_NandDir", FileUtil::GetUserPath(FileUtil::UserPath::NANDDir)); | 122 | LogSetting("DataStorage_NandDir", FileUtil::GetUserPath(FileUtil::UserPath::NANDDir)); |
| @@ -131,15 +132,56 @@ float Volume() { | |||
| 131 | if (values.audio_muted) { | 132 | if (values.audio_muted) { |
| 132 | return 0.0f; | 133 | return 0.0f; |
| 133 | } | 134 | } |
| 134 | return values.volume; | 135 | return values.volume.GetValue(); |
| 135 | } | 136 | } |
| 136 | 137 | ||
| 137 | bool IsGPULevelExtreme() { | 138 | bool IsGPULevelExtreme() { |
| 138 | return values.gpu_accuracy == GPUAccuracy::Extreme; | 139 | return values.gpu_accuracy.GetValue() == GPUAccuracy::Extreme; |
| 139 | } | 140 | } |
| 140 | 141 | ||
| 141 | bool IsGPULevelHigh() { | 142 | bool IsGPULevelHigh() { |
| 142 | return values.gpu_accuracy == GPUAccuracy::Extreme || values.gpu_accuracy == GPUAccuracy::High; | 143 | return values.gpu_accuracy.GetValue() == GPUAccuracy::Extreme || |
| 144 | values.gpu_accuracy.GetValue() == GPUAccuracy::High; | ||
| 145 | } | ||
| 146 | |||
| 147 | void RestoreGlobalState() { | ||
| 148 | // If a game is running, DO NOT restore the global settings state | ||
| 149 | if (Core::System::GetInstance().IsPoweredOn()) { | ||
| 150 | return; | ||
| 151 | } | ||
| 152 | |||
| 153 | // Audio | ||
| 154 | values.enable_audio_stretching.SetGlobal(true); | ||
| 155 | values.volume.SetGlobal(true); | ||
| 156 | |||
| 157 | // Core | ||
| 158 | values.use_multi_core.SetGlobal(true); | ||
| 159 | |||
| 160 | // Renderer | ||
| 161 | values.renderer_backend.SetGlobal(true); | ||
| 162 | values.vulkan_device.SetGlobal(true); | ||
| 163 | values.aspect_ratio.SetGlobal(true); | ||
| 164 | values.max_anisotropy.SetGlobal(true); | ||
| 165 | values.use_frame_limit.SetGlobal(true); | ||
| 166 | values.frame_limit.SetGlobal(true); | ||
| 167 | values.use_disk_shader_cache.SetGlobal(true); | ||
| 168 | values.gpu_accuracy.SetGlobal(true); | ||
| 169 | values.use_asynchronous_gpu_emulation.SetGlobal(true); | ||
| 170 | values.use_vsync.SetGlobal(true); | ||
| 171 | values.use_assembly_shaders.SetGlobal(true); | ||
| 172 | values.use_fast_gpu_time.SetGlobal(true); | ||
| 173 | values.force_30fps_mode.SetGlobal(true); | ||
| 174 | values.bg_red.SetGlobal(true); | ||
| 175 | values.bg_green.SetGlobal(true); | ||
| 176 | values.bg_blue.SetGlobal(true); | ||
| 177 | |||
| 178 | // System | ||
| 179 | values.language_index.SetGlobal(true); | ||
| 180 | values.region_index.SetGlobal(true); | ||
| 181 | values.time_zone_index.SetGlobal(true); | ||
| 182 | values.rng_seed.SetGlobal(true); | ||
| 183 | values.custom_rtc.SetGlobal(true); | ||
| 184 | values.sound_index.SetGlobal(true); | ||
| 143 | } | 185 | } |
| 144 | 186 | ||
| 145 | } // namespace Settings | 187 | } // namespace Settings |
diff --git a/src/core/settings.h b/src/core/settings.h index a598ccbc1..850ca4072 100644 --- a/src/core/settings.h +++ b/src/core/settings.h | |||
| @@ -382,20 +382,85 @@ enum class GPUAccuracy : u32 { | |||
| 382 | Extreme = 2, | 382 | Extreme = 2, |
| 383 | }; | 383 | }; |
| 384 | 384 | ||
| 385 | extern bool configuring_global; | ||
| 386 | |||
| 387 | template <typename Type> | ||
| 388 | class Setting final { | ||
| 389 | public: | ||
| 390 | Setting() = default; | ||
| 391 | explicit Setting(Type val) : global{val} {} | ||
| 392 | ~Setting() = default; | ||
| 393 | void SetGlobal(bool to_global) { | ||
| 394 | use_global = to_global; | ||
| 395 | } | ||
| 396 | bool UsingGlobal() const { | ||
| 397 | return use_global; | ||
| 398 | } | ||
| 399 | Type GetValue(bool need_global = false) const { | ||
| 400 | if (use_global || need_global) { | ||
| 401 | return global; | ||
| 402 | } | ||
| 403 | return local; | ||
| 404 | } | ||
| 405 | void SetValue(const Type& value) { | ||
| 406 | if (use_global) { | ||
| 407 | global = value; | ||
| 408 | } else { | ||
| 409 | local = value; | ||
| 410 | } | ||
| 411 | } | ||
| 412 | |||
| 413 | private: | ||
| 414 | bool use_global = true; | ||
| 415 | Type global{}; | ||
| 416 | Type local{}; | ||
| 417 | }; | ||
| 418 | |||
| 385 | struct Values { | 419 | struct Values { |
| 420 | // Audio | ||
| 421 | std::string audio_device_id; | ||
| 422 | std::string sink_id; | ||
| 423 | bool audio_muted; | ||
| 424 | Setting<bool> enable_audio_stretching; | ||
| 425 | Setting<float> volume; | ||
| 426 | |||
| 427 | // Core | ||
| 428 | Setting<bool> use_multi_core; | ||
| 429 | |||
| 430 | // Renderer | ||
| 431 | Setting<RendererBackend> renderer_backend; | ||
| 432 | bool renderer_debug; | ||
| 433 | Setting<int> vulkan_device; | ||
| 434 | |||
| 435 | Setting<u16> resolution_factor = Setting(static_cast<u16>(1)); | ||
| 436 | Setting<int> aspect_ratio; | ||
| 437 | Setting<int> max_anisotropy; | ||
| 438 | Setting<bool> use_frame_limit; | ||
| 439 | Setting<u16> frame_limit; | ||
| 440 | Setting<bool> use_disk_shader_cache; | ||
| 441 | Setting<GPUAccuracy> gpu_accuracy; | ||
| 442 | Setting<bool> use_asynchronous_gpu_emulation; | ||
| 443 | Setting<bool> use_vsync; | ||
| 444 | Setting<bool> use_assembly_shaders; | ||
| 445 | Setting<bool> force_30fps_mode; | ||
| 446 | Setting<bool> use_fast_gpu_time; | ||
| 447 | |||
| 448 | Setting<float> bg_red; | ||
| 449 | Setting<float> bg_green; | ||
| 450 | Setting<float> bg_blue; | ||
| 451 | |||
| 386 | // System | 452 | // System |
| 387 | bool use_docked_mode; | 453 | Setting<std::optional<u32>> rng_seed; |
| 388 | std::optional<u32> rng_seed; | ||
| 389 | // Measured in seconds since epoch | 454 | // Measured in seconds since epoch |
| 390 | std::optional<std::chrono::seconds> custom_rtc; | 455 | Setting<std::optional<std::chrono::seconds>> custom_rtc; |
| 391 | // Set on game boot, reset on stop. Seconds difference between current time and `custom_rtc` | 456 | // Set on game boot, reset on stop. Seconds difference between current time and `custom_rtc` |
| 392 | std::chrono::seconds custom_rtc_differential; | 457 | std::chrono::seconds custom_rtc_differential; |
| 393 | 458 | ||
| 394 | s32 current_user; | 459 | s32 current_user; |
| 395 | s32 language_index; | 460 | Setting<s32> language_index; |
| 396 | s32 region_index; | 461 | Setting<s32> region_index; |
| 397 | s32 time_zone_index; | 462 | Setting<s32> time_zone_index; |
| 398 | s32 sound_index; | 463 | Setting<s32> sound_index; |
| 399 | 464 | ||
| 400 | // Controls | 465 | // Controls |
| 401 | std::array<PlayerInput, 10> players; | 466 | std::array<PlayerInput, 10> players; |
| @@ -419,8 +484,7 @@ struct Values { | |||
| 419 | u16 udp_input_port; | 484 | u16 udp_input_port; |
| 420 | u8 udp_pad_index; | 485 | u8 udp_pad_index; |
| 421 | 486 | ||
| 422 | // Core | 487 | bool use_docked_mode; |
| 423 | bool use_multi_core; | ||
| 424 | 488 | ||
| 425 | // Data Storage | 489 | // Data Storage |
| 426 | bool use_virtual_sd; | 490 | bool use_virtual_sd; |
| @@ -432,39 +496,6 @@ struct Values { | |||
| 432 | NANDUserSize nand_user_size; | 496 | NANDUserSize nand_user_size; |
| 433 | SDMCSize sdmc_size; | 497 | SDMCSize sdmc_size; |
| 434 | 498 | ||
| 435 | // Renderer | ||
| 436 | RendererBackend renderer_backend; | ||
| 437 | bool renderer_debug; | ||
| 438 | int vulkan_device; | ||
| 439 | |||
| 440 | u16 resolution_factor{1}; | ||
| 441 | int aspect_ratio; | ||
| 442 | int max_anisotropy; | ||
| 443 | bool use_frame_limit; | ||
| 444 | u16 frame_limit; | ||
| 445 | bool use_disk_shader_cache; | ||
| 446 | GPUAccuracy gpu_accuracy; | ||
| 447 | bool use_asynchronous_gpu_emulation; | ||
| 448 | bool use_vsync; | ||
| 449 | bool use_assembly_shaders; | ||
| 450 | bool force_30fps_mode; | ||
| 451 | bool use_fast_gpu_time; | ||
| 452 | |||
| 453 | float bg_red; | ||
| 454 | float bg_green; | ||
| 455 | float bg_blue; | ||
| 456 | |||
| 457 | std::string log_filter; | ||
| 458 | |||
| 459 | bool use_dev_keys; | ||
| 460 | |||
| 461 | // Audio | ||
| 462 | bool audio_muted; | ||
| 463 | std::string sink_id; | ||
| 464 | bool enable_audio_stretching; | ||
| 465 | std::string audio_device_id; | ||
| 466 | float volume; | ||
| 467 | |||
| 468 | // Debugging | 499 | // Debugging |
| 469 | bool record_frame_times; | 500 | bool record_frame_times; |
| 470 | bool use_gdbstub; | 501 | bool use_gdbstub; |
| @@ -477,7 +508,11 @@ struct Values { | |||
| 477 | bool disable_cpu_opt; | 508 | bool disable_cpu_opt; |
| 478 | bool disable_macro_jit; | 509 | bool disable_macro_jit; |
| 479 | 510 | ||
| 480 | // BCAT | 511 | // Misceallaneous |
| 512 | std::string log_filter; | ||
| 513 | bool use_dev_keys; | ||
| 514 | |||
| 515 | // Services | ||
| 481 | std::string bcat_backend; | 516 | std::string bcat_backend; |
| 482 | bool bcat_boxcat_local; | 517 | bool bcat_boxcat_local; |
| 483 | 518 | ||
| @@ -501,4 +536,7 @@ std::string GetTimeZoneString(); | |||
| 501 | void Apply(); | 536 | void Apply(); |
| 502 | void LogSettings(); | 537 | void LogSettings(); |
| 503 | 538 | ||
| 539 | // Restore the global state of all applicable settings in the Values struct | ||
| 540 | void RestoreGlobalState(); | ||
| 541 | |||
| 504 | } // namespace Settings | 542 | } // namespace Settings |
diff --git a/src/core/telemetry_session.cpp b/src/core/telemetry_session.cpp index c781b3cfc..78915e6db 100644 --- a/src/core/telemetry_session.cpp +++ b/src/core/telemetry_session.cpp | |||
| @@ -189,19 +189,24 @@ void TelemetrySession::AddInitialInfo(Loader::AppLoader& app_loader) { | |||
| 189 | // Log user configuration information | 189 | // Log user configuration information |
| 190 | constexpr auto field_type = Telemetry::FieldType::UserConfig; | 190 | constexpr auto field_type = Telemetry::FieldType::UserConfig; |
| 191 | AddField(field_type, "Audio_SinkId", Settings::values.sink_id); | 191 | AddField(field_type, "Audio_SinkId", Settings::values.sink_id); |
| 192 | AddField(field_type, "Audio_EnableAudioStretching", Settings::values.enable_audio_stretching); | 192 | AddField(field_type, "Audio_EnableAudioStretching", |
| 193 | AddField(field_type, "Core_UseMultiCore", Settings::values.use_multi_core); | 193 | Settings::values.enable_audio_stretching.GetValue()); |
| 194 | AddField(field_type, "Renderer_Backend", TranslateRenderer(Settings::values.renderer_backend)); | 194 | AddField(field_type, "Core_UseMultiCore", Settings::values.use_multi_core.GetValue()); |
| 195 | AddField(field_type, "Renderer_ResolutionFactor", Settings::values.resolution_factor); | 195 | AddField(field_type, "Renderer_Backend", |
| 196 | AddField(field_type, "Renderer_UseFrameLimit", Settings::values.use_frame_limit); | 196 | TranslateRenderer(Settings::values.renderer_backend.GetValue())); |
| 197 | AddField(field_type, "Renderer_FrameLimit", Settings::values.frame_limit); | 197 | AddField(field_type, "Renderer_ResolutionFactor", |
| 198 | AddField(field_type, "Renderer_UseDiskShaderCache", Settings::values.use_disk_shader_cache); | 198 | Settings::values.resolution_factor.GetValue()); |
| 199 | AddField(field_type, "Renderer_UseFrameLimit", Settings::values.use_frame_limit.GetValue()); | ||
| 200 | AddField(field_type, "Renderer_FrameLimit", Settings::values.frame_limit.GetValue()); | ||
| 201 | AddField(field_type, "Renderer_UseDiskShaderCache", | ||
| 202 | Settings::values.use_disk_shader_cache.GetValue()); | ||
| 199 | AddField(field_type, "Renderer_GPUAccuracyLevel", | 203 | AddField(field_type, "Renderer_GPUAccuracyLevel", |
| 200 | TranslateGPUAccuracyLevel(Settings::values.gpu_accuracy)); | 204 | TranslateGPUAccuracyLevel(Settings::values.gpu_accuracy.GetValue())); |
| 201 | AddField(field_type, "Renderer_UseAsynchronousGpuEmulation", | 205 | AddField(field_type, "Renderer_UseAsynchronousGpuEmulation", |
| 202 | Settings::values.use_asynchronous_gpu_emulation); | 206 | Settings::values.use_asynchronous_gpu_emulation.GetValue()); |
| 203 | AddField(field_type, "Renderer_UseVsync", Settings::values.use_vsync); | 207 | AddField(field_type, "Renderer_UseVsync", Settings::values.use_vsync.GetValue()); |
| 204 | AddField(field_type, "Renderer_UseAssemblyShaders", Settings::values.use_assembly_shaders); | 208 | AddField(field_type, "Renderer_UseAssemblyShaders", |
| 209 | Settings::values.use_assembly_shaders.GetValue()); | ||
| 205 | AddField(field_type, "System_UseDockedMode", Settings::values.use_docked_mode); | 210 | AddField(field_type, "System_UseDockedMode", Settings::values.use_docked_mode); |
| 206 | } | 211 | } |
| 207 | 212 | ||
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index c6479af9f..dd7ce8c99 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h | |||
| @@ -96,7 +96,8 @@ public: | |||
| 96 | } | 96 | } |
| 97 | if (is_written) { | 97 | if (is_written) { |
| 98 | map->MarkAsModified(true, GetModifiedTicks()); | 98 | map->MarkAsModified(true, GetModifiedTicks()); |
| 99 | if (Settings::IsGPULevelHigh() && Settings::values.use_asynchronous_gpu_emulation) { | 99 | if (Settings::IsGPULevelHigh() && |
| 100 | Settings::values.use_asynchronous_gpu_emulation.GetValue()) { | ||
| 100 | MarkForAsyncFlush(map); | 101 | MarkForAsyncFlush(map); |
| 101 | } | 102 | } |
| 102 | if (!map->is_written) { | 103 | if (!map->is_written) { |
| @@ -369,7 +370,8 @@ private: | |||
| 369 | } | 370 | } |
| 370 | if (modified_inheritance) { | 371 | if (modified_inheritance) { |
| 371 | map->MarkAsModified(true, GetModifiedTicks()); | 372 | map->MarkAsModified(true, GetModifiedTicks()); |
| 372 | if (Settings::IsGPULevelHigh() && Settings::values.use_asynchronous_gpu_emulation) { | 373 | if (Settings::IsGPULevelHigh() && |
| 374 | Settings::values.use_asynchronous_gpu_emulation.GetValue()) { | ||
| 373 | MarkForAsyncFlush(map); | 375 | MarkForAsyncFlush(map); |
| 374 | } | 376 | } |
| 375 | } | 377 | } |
diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp index 482e49711..758bfe148 100644 --- a/src/video_core/gpu.cpp +++ b/src/video_core/gpu.cpp | |||
| @@ -157,7 +157,7 @@ u64 GPU::GetTicks() const { | |||
| 157 | constexpr u64 gpu_ticks_den = 625; | 157 | constexpr u64 gpu_ticks_den = 625; |
| 158 | 158 | ||
| 159 | u64 nanoseconds = system.CoreTiming().GetGlobalTimeNs().count(); | 159 | u64 nanoseconds = system.CoreTiming().GetGlobalTimeNs().count(); |
| 160 | if (Settings::values.use_fast_gpu_time) { | 160 | if (Settings::values.use_fast_gpu_time.GetValue()) { |
| 161 | nanoseconds /= 256; | 161 | nanoseconds /= 256; |
| 162 | } | 162 | } |
| 163 | const u64 nanoseconds_num = nanoseconds / gpu_ticks_den; | 163 | const u64 nanoseconds_num = nanoseconds / gpu_ticks_den; |
diff --git a/src/video_core/query_cache.h b/src/video_core/query_cache.h index e12dab899..0d3a88765 100644 --- a/src/video_core/query_cache.h +++ b/src/video_core/query_cache.h | |||
| @@ -132,7 +132,7 @@ public: | |||
| 132 | } | 132 | } |
| 133 | 133 | ||
| 134 | query->BindCounter(Stream(type).Current(), timestamp); | 134 | query->BindCounter(Stream(type).Current(), timestamp); |
| 135 | if (Settings::values.use_asynchronous_gpu_emulation) { | 135 | if (Settings::values.use_asynchronous_gpu_emulation.GetValue()) { |
| 136 | AsyncFlushQuery(cpu_addr); | 136 | AsyncFlushQuery(cpu_addr); |
| 137 | } | 137 | } |
| 138 | } | 138 | } |
diff --git a/src/video_core/renderer_base.cpp b/src/video_core/renderer_base.cpp index 919d1f2d4..dfb06e87e 100644 --- a/src/video_core/renderer_base.cpp +++ b/src/video_core/renderer_base.cpp | |||
| @@ -18,7 +18,7 @@ RendererBase::~RendererBase() = default; | |||
| 18 | void RendererBase::RefreshBaseSettings() { | 18 | void RendererBase::RefreshBaseSettings() { |
| 19 | UpdateCurrentFramebufferLayout(); | 19 | UpdateCurrentFramebufferLayout(); |
| 20 | 20 | ||
| 21 | renderer_settings.use_framelimiter = Settings::values.use_frame_limit; | 21 | renderer_settings.use_framelimiter = Settings::values.use_frame_limit.GetValue(); |
| 22 | renderer_settings.set_background_color = true; | 22 | renderer_settings.set_background_color = true; |
| 23 | } | 23 | } |
| 24 | 24 | ||
diff --git a/src/video_core/renderer_opengl/gl_device.cpp b/src/video_core/renderer_opengl/gl_device.cpp index 208fc6167..c1f20f0ab 100644 --- a/src/video_core/renderer_opengl/gl_device.cpp +++ b/src/video_core/renderer_opengl/gl_device.cpp | |||
| @@ -229,15 +229,15 @@ Device::Device() | |||
| 229 | // uniform buffers as "push constants" | 229 | // uniform buffers as "push constants" |
| 230 | has_fast_buffer_sub_data = is_nvidia && !disable_fast_buffer_sub_data; | 230 | has_fast_buffer_sub_data = is_nvidia && !disable_fast_buffer_sub_data; |
| 231 | 231 | ||
| 232 | use_assembly_shaders = Settings::values.use_assembly_shaders && GLAD_GL_NV_gpu_program5 && | 232 | use_assembly_shaders = Settings::values.use_assembly_shaders.GetValue() && |
| 233 | GLAD_GL_NV_compute_program5 && GLAD_GL_NV_transform_feedback && | 233 | GLAD_GL_NV_gpu_program5 && GLAD_GL_NV_compute_program5 && |
| 234 | GLAD_GL_NV_transform_feedback2; | 234 | GLAD_GL_NV_transform_feedback && GLAD_GL_NV_transform_feedback2; |
| 235 | 235 | ||
| 236 | LOG_INFO(Render_OpenGL, "Renderer_VariableAOFFI: {}", has_variable_aoffi); | 236 | LOG_INFO(Render_OpenGL, "Renderer_VariableAOFFI: {}", has_variable_aoffi); |
| 237 | LOG_INFO(Render_OpenGL, "Renderer_ComponentIndexingBug: {}", has_component_indexing_bug); | 237 | LOG_INFO(Render_OpenGL, "Renderer_ComponentIndexingBug: {}", has_component_indexing_bug); |
| 238 | LOG_INFO(Render_OpenGL, "Renderer_PreciseBug: {}", has_precise_bug); | 238 | LOG_INFO(Render_OpenGL, "Renderer_PreciseBug: {}", has_precise_bug); |
| 239 | 239 | ||
| 240 | if (Settings::values.use_assembly_shaders && !use_assembly_shaders) { | 240 | if (Settings::values.use_assembly_shaders.GetValue() && !use_assembly_shaders) { |
| 241 | LOG_ERROR(Render_OpenGL, "Assembly shaders enabled but not supported"); | 241 | LOG_ERROR(Render_OpenGL, "Assembly shaders enabled but not supported"); |
| 242 | } | 242 | } |
| 243 | } | 243 | } |
diff --git a/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp b/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp index 653c3f2f9..2dcc2b0eb 100644 --- a/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp | |||
| @@ -213,7 +213,7 @@ ShaderDiskCacheOpenGL::~ShaderDiskCacheOpenGL() = default; | |||
| 213 | std::optional<std::vector<ShaderDiskCacheEntry>> ShaderDiskCacheOpenGL::LoadTransferable() { | 213 | std::optional<std::vector<ShaderDiskCacheEntry>> ShaderDiskCacheOpenGL::LoadTransferable() { |
| 214 | // Skip games without title id | 214 | // Skip games without title id |
| 215 | const bool has_title_id = system.CurrentProcess()->GetTitleID() != 0; | 215 | const bool has_title_id = system.CurrentProcess()->GetTitleID() != 0; |
| 216 | if (!Settings::values.use_disk_shader_cache || !has_title_id) { | 216 | if (!Settings::values.use_disk_shader_cache.GetValue() || !has_title_id) { |
| 217 | return {}; | 217 | return {}; |
| 218 | } | 218 | } |
| 219 | 219 | ||
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index c40adb6e7..e66cdc083 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp | |||
| @@ -455,8 +455,8 @@ void RendererOpenGL::LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color | |||
| 455 | void RendererOpenGL::InitOpenGLObjects() { | 455 | void RendererOpenGL::InitOpenGLObjects() { |
| 456 | frame_mailbox = std::make_unique<FrameMailbox>(); | 456 | frame_mailbox = std::make_unique<FrameMailbox>(); |
| 457 | 457 | ||
| 458 | glClearColor(Settings::values.bg_red, Settings::values.bg_green, Settings::values.bg_blue, | 458 | glClearColor(Settings::values.bg_red.GetValue(), Settings::values.bg_green.GetValue(), |
| 459 | 0.0f); | 459 | Settings::values.bg_blue.GetValue(), 0.0f); |
| 460 | 460 | ||
| 461 | // Create shader programs | 461 | // Create shader programs |
| 462 | OGLShader vertex_shader; | 462 | OGLShader vertex_shader; |
| @@ -561,8 +561,8 @@ void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture, | |||
| 561 | void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) { | 561 | void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) { |
| 562 | if (renderer_settings.set_background_color) { | 562 | if (renderer_settings.set_background_color) { |
| 563 | // Update background color before drawing | 563 | // Update background color before drawing |
| 564 | glClearColor(Settings::values.bg_red, Settings::values.bg_green, Settings::values.bg_blue, | 564 | glClearColor(Settings::values.bg_red.GetValue(), Settings::values.bg_green.GetValue(), |
| 565 | 0.0f); | 565 | Settings::values.bg_blue.GetValue(), 0.0f); |
| 566 | } | 566 | } |
| 567 | 567 | ||
| 568 | // Set projection matrix | 568 | // Set projection matrix |
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index 2d9b18ed9..2258479f5 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp | |||
| @@ -409,7 +409,7 @@ bool RendererVulkan::PickDevices() { | |||
| 409 | return false; | 409 | return false; |
| 410 | } | 410 | } |
| 411 | 411 | ||
| 412 | const s32 device_index = Settings::values.vulkan_device; | 412 | const s32 device_index = Settings::values.vulkan_device.GetValue(); |
| 413 | if (device_index < 0 || device_index >= static_cast<s32>(devices->size())) { | 413 | if (device_index < 0 || device_index >= static_cast<s32>(devices->size())) { |
| 414 | LOG_ERROR(Render_Vulkan, "Invalid device index {}!", device_index); | 414 | LOG_ERROR(Render_Vulkan, "Invalid device index {}!", device_index); |
| 415 | return false; | 415 | return false; |
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 6207d8dfe..cdcddb225 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h | |||
| @@ -249,7 +249,7 @@ public: | |||
| 249 | auto& surface = render_targets[index].target; | 249 | auto& surface = render_targets[index].target; |
| 250 | surface->MarkAsRenderTarget(false, NO_RT); | 250 | surface->MarkAsRenderTarget(false, NO_RT); |
| 251 | const auto& cr_params = surface->GetSurfaceParams(); | 251 | const auto& cr_params = surface->GetSurfaceParams(); |
| 252 | if (!cr_params.is_tiled && Settings::values.use_asynchronous_gpu_emulation) { | 252 | if (!cr_params.is_tiled && Settings::values.use_asynchronous_gpu_emulation.GetValue()) { |
| 253 | AsyncFlushSurface(surface); | 253 | AsyncFlushSurface(surface); |
| 254 | } | 254 | } |
| 255 | } | 255 | } |
diff --git a/src/video_core/textures/texture.cpp b/src/video_core/textures/texture.cpp index d1939d744..4171e3ef2 100644 --- a/src/video_core/textures/texture.cpp +++ b/src/video_core/textures/texture.cpp | |||
| @@ -48,7 +48,7 @@ constexpr std::array<float, 256> SRGB_CONVERSION_LUT = { | |||
| 48 | }; | 48 | }; |
| 49 | 49 | ||
| 50 | unsigned SettingsMinimumAnisotropy() noexcept { | 50 | unsigned SettingsMinimumAnisotropy() noexcept { |
| 51 | switch (static_cast<Anisotropy>(Settings::values.max_anisotropy)) { | 51 | switch (static_cast<Anisotropy>(Settings::values.max_anisotropy.GetValue())) { |
| 52 | default: | 52 | default: |
| 53 | case Anisotropy::Default: | 53 | case Anisotropy::Default: |
| 54 | return 1U; | 54 | return 1U; |
diff --git a/src/video_core/video_core.cpp b/src/video_core/video_core.cpp index f60bdc60a..45f360bdd 100644 --- a/src/video_core/video_core.cpp +++ b/src/video_core/video_core.cpp | |||
| @@ -19,7 +19,7 @@ namespace { | |||
| 19 | std::unique_ptr<VideoCore::RendererBase> CreateRenderer(Core::Frontend::EmuWindow& emu_window, | 19 | std::unique_ptr<VideoCore::RendererBase> CreateRenderer(Core::Frontend::EmuWindow& emu_window, |
| 20 | Core::System& system, | 20 | Core::System& system, |
| 21 | Core::Frontend::GraphicsContext& context) { | 21 | Core::Frontend::GraphicsContext& context) { |
| 22 | switch (Settings::values.renderer_backend) { | 22 | switch (Settings::values.renderer_backend.GetValue()) { |
| 23 | case Settings::RendererBackend::OpenGL: | 23 | case Settings::RendererBackend::OpenGL: |
| 24 | return std::make_unique<OpenGL::RendererOpenGL>(emu_window, system, context); | 24 | return std::make_unique<OpenGL::RendererOpenGL>(emu_window, system, context); |
| 25 | #ifdef HAS_VULKAN | 25 | #ifdef HAS_VULKAN |
| @@ -42,7 +42,7 @@ std::unique_ptr<Tegra::GPU> CreateGPU(Core::Frontend::EmuWindow& emu_window, Cor | |||
| 42 | return nullptr; | 42 | return nullptr; |
| 43 | } | 43 | } |
| 44 | 44 | ||
| 45 | if (Settings::values.use_asynchronous_gpu_emulation) { | 45 | if (Settings::values.use_asynchronous_gpu_emulation.GetValue()) { |
| 46 | return std::make_unique<VideoCommon::GPUAsynch>(system, std::move(renderer), | 46 | return std::make_unique<VideoCommon::GPUAsynch>(system, std::move(renderer), |
| 47 | std::move(context)); | 47 | std::move(context)); |
| 48 | } | 48 | } |
| @@ -51,8 +51,8 @@ std::unique_ptr<Tegra::GPU> CreateGPU(Core::Frontend::EmuWindow& emu_window, Cor | |||
| 51 | 51 | ||
| 52 | u16 GetResolutionScaleFactor(const RendererBase& renderer) { | 52 | u16 GetResolutionScaleFactor(const RendererBase& renderer) { |
| 53 | return static_cast<u16>( | 53 | return static_cast<u16>( |
| 54 | Settings::values.resolution_factor != 0 | 54 | Settings::values.resolution_factor.GetValue() != 0 |
| 55 | ? Settings::values.resolution_factor | 55 | ? Settings::values.resolution_factor.GetValue() |
| 56 | : renderer.GetRenderWindow().GetFramebufferLayout().GetScalingRatio()); | 56 | : renderer.GetRenderWindow().GetFramebufferLayout().GetScalingRatio()); |
| 57 | } | 57 | } |
| 58 | 58 | ||
diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index 75c27e39e..742b72856 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt | |||
| @@ -24,6 +24,8 @@ add_executable(yuzu | |||
| 24 | compatibility_list.h | 24 | compatibility_list.h |
| 25 | configuration/config.cpp | 25 | configuration/config.cpp |
| 26 | configuration/config.h | 26 | configuration/config.h |
| 27 | configuration/configuration_shared.cpp | ||
| 28 | configuration/configuration_shared.h | ||
| 27 | configuration/configure.ui | 29 | configuration/configure.ui |
| 28 | configuration/configure_audio.cpp | 30 | configuration/configure_audio.cpp |
| 29 | configuration/configure_audio.h | 31 | configuration/configure_audio.h |
| @@ -60,9 +62,12 @@ add_executable(yuzu | |||
| 60 | configuration/configure_mouse_advanced.cpp | 62 | configuration/configure_mouse_advanced.cpp |
| 61 | configuration/configure_mouse_advanced.h | 63 | configuration/configure_mouse_advanced.h |
| 62 | configuration/configure_mouse_advanced.ui | 64 | configuration/configure_mouse_advanced.ui |
| 63 | configuration/configure_per_general.cpp | 65 | configuration/configure_per_game.cpp |
| 64 | configuration/configure_per_general.h | 66 | configuration/configure_per_game.h |
| 65 | configuration/configure_per_general.ui | 67 | configuration/configure_per_game.ui |
| 68 | configuration/configure_per_game_addons.cpp | ||
| 69 | configuration/configure_per_game_addons.h | ||
| 70 | configuration/configure_per_game_addons.ui | ||
| 66 | configuration/configure_profile_manager.cpp | 71 | configuration/configure_profile_manager.cpp |
| 67 | configuration/configure_profile_manager.h | 72 | configuration/configure_profile_manager.h |
| 68 | configuration/configure_profile_manager.ui | 73 | configuration/configure_profile_manager.ui |
diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp index 4bfce48a4..5738787ac 100644 --- a/src/yuzu/bootmanager.cpp +++ b/src/yuzu/bootmanager.cpp | |||
| @@ -145,7 +145,7 @@ public: | |||
| 145 | 145 | ||
| 146 | // disable vsync for any shared contexts | 146 | // disable vsync for any shared contexts |
| 147 | auto format = share_context->format(); | 147 | auto format = share_context->format(); |
| 148 | format.setSwapInterval(main_surface ? Settings::values.use_vsync : 0); | 148 | format.setSwapInterval(main_surface ? Settings::values.use_vsync.GetValue() : 0); |
| 149 | 149 | ||
| 150 | context = std::make_unique<QOpenGLContext>(); | 150 | context = std::make_unique<QOpenGLContext>(); |
| 151 | context->setShareContext(share_context); | 151 | context->setShareContext(share_context); |
| @@ -495,7 +495,7 @@ void GRenderWindow::resizeEvent(QResizeEvent* event) { | |||
| 495 | 495 | ||
| 496 | std::unique_ptr<Core::Frontend::GraphicsContext> GRenderWindow::CreateSharedContext() const { | 496 | std::unique_ptr<Core::Frontend::GraphicsContext> GRenderWindow::CreateSharedContext() const { |
| 497 | #ifdef HAS_OPENGL | 497 | #ifdef HAS_OPENGL |
| 498 | if (Settings::values.renderer_backend == Settings::RendererBackend::OpenGL) { | 498 | if (Settings::values.renderer_backend.GetValue() == Settings::RendererBackend::OpenGL) { |
| 499 | auto c = static_cast<OpenGLSharedContext*>(main_context.get()); | 499 | auto c = static_cast<OpenGLSharedContext*>(main_context.get()); |
| 500 | // Bind the shared contexts to the main surface in case the backend wants to take over | 500 | // Bind the shared contexts to the main surface in case the backend wants to take over |
| 501 | // presentation | 501 | // presentation |
| @@ -511,7 +511,7 @@ bool GRenderWindow::InitRenderTarget() { | |||
| 511 | 511 | ||
| 512 | first_frame = false; | 512 | first_frame = false; |
| 513 | 513 | ||
| 514 | switch (Settings::values.renderer_backend) { | 514 | switch (Settings::values.renderer_backend.GetValue()) { |
| 515 | case Settings::RendererBackend::OpenGL: | 515 | case Settings::RendererBackend::OpenGL: |
| 516 | if (!InitializeOpenGL()) { | 516 | if (!InitializeOpenGL()) { |
| 517 | return false; | 517 | return false; |
| @@ -538,7 +538,7 @@ bool GRenderWindow::InitRenderTarget() { | |||
| 538 | OnFramebufferSizeChanged(); | 538 | OnFramebufferSizeChanged(); |
| 539 | BackupGeometry(); | 539 | BackupGeometry(); |
| 540 | 540 | ||
| 541 | if (Settings::values.renderer_backend == Settings::RendererBackend::OpenGL) { | 541 | if (Settings::values.renderer_backend.GetValue() == Settings::RendererBackend::OpenGL) { |
| 542 | if (!LoadOpenGL()) { | 542 | if (!LoadOpenGL()) { |
| 543 | return false; | 543 | return false; |
| 544 | } | 544 | } |
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index 5e0d0e7af..1b2b1b2bb 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp | |||
| @@ -13,17 +13,20 @@ | |||
| 13 | #include "input_common/udp/client.h" | 13 | #include "input_common/udp/client.h" |
| 14 | #include "yuzu/configuration/config.h" | 14 | #include "yuzu/configuration/config.h" |
| 15 | 15 | ||
| 16 | Config::Config() { | 16 | Config::Config(const std::string& config_file, bool is_global) { |
| 17 | // TODO: Don't hardcode the path; let the frontend decide where to put the config files. | 17 | // TODO: Don't hardcode the path; let the frontend decide where to put the config files. |
| 18 | qt_config_loc = FileUtil::GetUserPath(FileUtil::UserPath::ConfigDir) + "qt-config.ini"; | 18 | qt_config_loc = FileUtil::GetUserPath(FileUtil::UserPath::ConfigDir) + config_file; |
| 19 | FileUtil::CreateFullPath(qt_config_loc); | 19 | FileUtil::CreateFullPath(qt_config_loc); |
| 20 | qt_config = | 20 | qt_config = |
| 21 | std::make_unique<QSettings>(QString::fromStdString(qt_config_loc), QSettings::IniFormat); | 21 | std::make_unique<QSettings>(QString::fromStdString(qt_config_loc), QSettings::IniFormat); |
| 22 | global = is_global; | ||
| 22 | Reload(); | 23 | Reload(); |
| 23 | } | 24 | } |
| 24 | 25 | ||
| 25 | Config::~Config() { | 26 | Config::~Config() { |
| 26 | Save(); | 27 | if (global) { |
| 28 | Save(); | ||
| 29 | } | ||
| 27 | } | 30 | } |
| 28 | 31 | ||
| 29 | const std::array<int, Settings::NativeButton::NumButtons> Config::default_buttons = { | 32 | const std::array<int, Settings::NativeButton::NumButtons> Config::default_buttons = { |
| @@ -402,16 +405,19 @@ void Config::ApplyDefaultProfileIfInputInvalid() { | |||
| 402 | void Config::ReadAudioValues() { | 405 | void Config::ReadAudioValues() { |
| 403 | qt_config->beginGroup(QStringLiteral("Audio")); | 406 | qt_config->beginGroup(QStringLiteral("Audio")); |
| 404 | 407 | ||
| 405 | Settings::values.sink_id = ReadSetting(QStringLiteral("output_engine"), QStringLiteral("auto")) | 408 | if (global) { |
| 406 | .toString() | 409 | Settings::values.sink_id = |
| 407 | .toStdString(); | 410 | ReadSetting(QStringLiteral("output_engine"), QStringLiteral("auto")) |
| 408 | Settings::values.enable_audio_stretching = | 411 | .toString() |
| 409 | ReadSetting(QStringLiteral("enable_audio_stretching"), true).toBool(); | 412 | .toStdString(); |
| 410 | Settings::values.audio_device_id = | 413 | Settings::values.audio_device_id = |
| 411 | ReadSetting(QStringLiteral("output_device"), QStringLiteral("auto")) | 414 | ReadSetting(QStringLiteral("output_device"), QStringLiteral("auto")) |
| 412 | .toString() | 415 | .toString() |
| 413 | .toStdString(); | 416 | .toStdString(); |
| 414 | Settings::values.volume = ReadSetting(QStringLiteral("volume"), 1).toFloat(); | 417 | } |
| 418 | ReadSettingGlobal(Settings::values.enable_audio_stretching, | ||
| 419 | QStringLiteral("enable_audio_stretching"), true); | ||
| 420 | ReadSettingGlobal(Settings::values.volume, QStringLiteral("volume"), 1); | ||
| 415 | 421 | ||
| 416 | qt_config->endGroup(); | 422 | qt_config->endGroup(); |
| 417 | } | 423 | } |
| @@ -440,6 +446,8 @@ void Config::ReadControlValues() { | |||
| 440 | .toInt()); | 446 | .toInt()); |
| 441 | Settings::values.udp_pad_index = | 447 | Settings::values.udp_pad_index = |
| 442 | static_cast<u8>(ReadSetting(QStringLiteral("udp_pad_index"), 0).toUInt()); | 448 | static_cast<u8>(ReadSetting(QStringLiteral("udp_pad_index"), 0).toUInt()); |
| 449 | Settings::values.use_docked_mode = | ||
| 450 | ReadSetting(QStringLiteral("use_docked_mode"), false).toBool(); | ||
| 443 | 451 | ||
| 444 | qt_config->endGroup(); | 452 | qt_config->endGroup(); |
| 445 | } | 453 | } |
| @@ -447,7 +455,7 @@ void Config::ReadControlValues() { | |||
| 447 | void Config::ReadCoreValues() { | 455 | void Config::ReadCoreValues() { |
| 448 | qt_config->beginGroup(QStringLiteral("Core")); | 456 | qt_config->beginGroup(QStringLiteral("Core")); |
| 449 | 457 | ||
| 450 | Settings::values.use_multi_core = ReadSetting(QStringLiteral("use_multi_core"), false).toBool(); | 458 | ReadSettingGlobal(Settings::values.use_multi_core, QStringLiteral("use_multi_core"), false); |
| 451 | 459 | ||
| 452 | qt_config->endGroup(); | 460 | qt_config->endGroup(); |
| 453 | } | 461 | } |
| @@ -628,32 +636,28 @@ void Config::ReadPathValues() { | |||
| 628 | void Config::ReadRendererValues() { | 636 | void Config::ReadRendererValues() { |
| 629 | qt_config->beginGroup(QStringLiteral("Renderer")); | 637 | qt_config->beginGroup(QStringLiteral("Renderer")); |
| 630 | 638 | ||
| 631 | Settings::values.renderer_backend = | 639 | ReadSettingGlobal(Settings::values.renderer_backend, QStringLiteral("backend"), 0); |
| 632 | static_cast<Settings::RendererBackend>(ReadSetting(QStringLiteral("backend"), 0).toInt()); | 640 | ReadSettingGlobal(Settings::values.renderer_debug, QStringLiteral("debug"), false); |
| 633 | Settings::values.renderer_debug = ReadSetting(QStringLiteral("debug"), false).toBool(); | 641 | ReadSettingGlobal(Settings::values.vulkan_device, QStringLiteral("vulkan_device"), 0); |
| 634 | Settings::values.vulkan_device = ReadSetting(QStringLiteral("vulkan_device"), 0).toInt(); | 642 | ReadSettingGlobal(Settings::values.aspect_ratio, QStringLiteral("aspect_ratio"), 0); |
| 635 | Settings::values.aspect_ratio = ReadSetting(QStringLiteral("aspect_ratio"), 0).toInt(); | 643 | ReadSettingGlobal(Settings::values.max_anisotropy, QStringLiteral("max_anisotropy"), 0); |
| 636 | Settings::values.max_anisotropy = ReadSetting(QStringLiteral("max_anisotropy"), 0).toInt(); | 644 | ReadSettingGlobal(Settings::values.use_frame_limit, QStringLiteral("use_frame_limit"), true); |
| 637 | Settings::values.use_frame_limit = | 645 | ReadSettingGlobal(Settings::values.frame_limit, QStringLiteral("frame_limit"), 100); |
| 638 | ReadSetting(QStringLiteral("use_frame_limit"), true).toBool(); | 646 | ReadSettingGlobal(Settings::values.use_disk_shader_cache, |
| 639 | Settings::values.frame_limit = ReadSetting(QStringLiteral("frame_limit"), 100).toUInt(); | 647 | QStringLiteral("use_disk_shader_cache"), true); |
| 640 | Settings::values.use_disk_shader_cache = | 648 | ReadSettingGlobal(Settings::values.gpu_accuracy, QStringLiteral("gpu_accuracy"), 0); |
| 641 | ReadSetting(QStringLiteral("use_disk_shader_cache"), true).toBool(); | 649 | ReadSettingGlobal(Settings::values.use_asynchronous_gpu_emulation, |
| 642 | const int gpu_accuracy_level = ReadSetting(QStringLiteral("gpu_accuracy"), 0).toInt(); | 650 | QStringLiteral("use_asynchronous_gpu_emulation"), false); |
| 643 | Settings::values.gpu_accuracy = static_cast<Settings::GPUAccuracy>(gpu_accuracy_level); | 651 | ReadSettingGlobal(Settings::values.use_vsync, QStringLiteral("use_vsync"), true); |
| 644 | Settings::values.use_asynchronous_gpu_emulation = | 652 | ReadSettingGlobal(Settings::values.use_assembly_shaders, QStringLiteral("use_assembly_shaders"), |
| 645 | ReadSetting(QStringLiteral("use_asynchronous_gpu_emulation"), false).toBool(); | 653 | false); |
| 646 | Settings::values.use_vsync = ReadSetting(QStringLiteral("use_vsync"), true).toBool(); | 654 | ReadSettingGlobal(Settings::values.use_fast_gpu_time, QStringLiteral("use_fast_gpu_time"), |
| 647 | Settings::values.use_assembly_shaders = | 655 | true); |
| 648 | ReadSetting(QStringLiteral("use_assembly_shaders"), false).toBool(); | 656 | ReadSettingGlobal(Settings::values.force_30fps_mode, QStringLiteral("force_30fps_mode"), false); |
| 649 | Settings::values.use_fast_gpu_time = | 657 | |
| 650 | ReadSetting(QStringLiteral("use_fast_gpu_time"), true).toBool(); | 658 | ReadSettingGlobal(Settings::values.bg_red, QStringLiteral("bg_red"), 0.0); |
| 651 | Settings::values.force_30fps_mode = | 659 | ReadSettingGlobal(Settings::values.bg_green, QStringLiteral("bg_green"), 0.0); |
| 652 | ReadSetting(QStringLiteral("force_30fps_mode"), false).toBool(); | 660 | ReadSettingGlobal(Settings::values.bg_blue, QStringLiteral("bg_blue"), 0.0); |
| 653 | |||
| 654 | Settings::values.bg_red = ReadSetting(QStringLiteral("bg_red"), 0.0).toFloat(); | ||
| 655 | Settings::values.bg_green = ReadSetting(QStringLiteral("bg_green"), 0.0).toFloat(); | ||
| 656 | Settings::values.bg_blue = ReadSetting(QStringLiteral("bg_blue"), 0.0).toFloat(); | ||
| 657 | 661 | ||
| 658 | qt_config->endGroup(); | 662 | qt_config->endGroup(); |
| 659 | } | 663 | } |
| @@ -682,35 +686,45 @@ void Config::ReadShortcutValues() { | |||
| 682 | void Config::ReadSystemValues() { | 686 | void Config::ReadSystemValues() { |
| 683 | qt_config->beginGroup(QStringLiteral("System")); | 687 | qt_config->beginGroup(QStringLiteral("System")); |
| 684 | 688 | ||
| 685 | Settings::values.use_docked_mode = | 689 | ReadSettingGlobal(Settings::values.current_user, QStringLiteral("current_user"), 0); |
| 686 | ReadSetting(QStringLiteral("use_docked_mode"), false).toBool(); | 690 | Settings::values.current_user = |
| 687 | 691 | std::clamp<int>(Settings::values.current_user, 0, Service::Account::MAX_USERS - 1); | |
| 688 | Settings::values.current_user = std::clamp<int>( | ||
| 689 | ReadSetting(QStringLiteral("current_user"), 0).toInt(), 0, Service::Account::MAX_USERS - 1); | ||
| 690 | 692 | ||
| 691 | Settings::values.language_index = ReadSetting(QStringLiteral("language_index"), 1).toInt(); | 693 | ReadSettingGlobal(Settings::values.language_index, QStringLiteral("language_index"), 1); |
| 692 | 694 | ||
| 693 | Settings::values.region_index = ReadSetting(QStringLiteral("region_index"), 1).toInt(); | 695 | ReadSettingGlobal(Settings::values.region_index, QStringLiteral("region_index"), 1); |
| 694 | 696 | ||
| 695 | Settings::values.time_zone_index = ReadSetting(QStringLiteral("time_zone_index"), 0).toInt(); | 697 | ReadSettingGlobal(Settings::values.time_zone_index, QStringLiteral("time_zone_index"), 0); |
| 696 | 698 | ||
| 697 | const auto rng_seed_enabled = ReadSetting(QStringLiteral("rng_seed_enabled"), false).toBool(); | 699 | bool rng_seed_enabled; |
| 698 | if (rng_seed_enabled) { | 700 | ReadSettingGlobal(rng_seed_enabled, QStringLiteral("rng_seed_enabled"), false); |
| 699 | Settings::values.rng_seed = ReadSetting(QStringLiteral("rng_seed"), 0).toULongLong(); | 701 | bool rng_seed_global = |
| 700 | } else { | 702 | global || qt_config->value(QStringLiteral("rng_seed/use_global"), true).toBool(); |
| 701 | Settings::values.rng_seed = std::nullopt; | 703 | Settings::values.rng_seed.SetGlobal(rng_seed_global); |
| 704 | if (global || !rng_seed_global) { | ||
| 705 | if (rng_seed_enabled) { | ||
| 706 | Settings::values.rng_seed.SetValue( | ||
| 707 | ReadSetting(QStringLiteral("rng_seed"), 0).toULongLong()); | ||
| 708 | } else { | ||
| 709 | Settings::values.rng_seed.SetValue(std::nullopt); | ||
| 710 | } | ||
| 702 | } | 711 | } |
| 703 | 712 | ||
| 704 | const auto custom_rtc_enabled = | 713 | bool custom_rtc_enabled; |
| 705 | ReadSetting(QStringLiteral("custom_rtc_enabled"), false).toBool(); | 714 | ReadSettingGlobal(custom_rtc_enabled, QStringLiteral("custom_rtc_enabled"), false); |
| 706 | if (custom_rtc_enabled) { | 715 | bool custom_rtc_global = |
| 707 | Settings::values.custom_rtc = | 716 | global || qt_config->value(QStringLiteral("custom_rtc/use_global"), true).toBool(); |
| 708 | std::chrono::seconds(ReadSetting(QStringLiteral("custom_rtc"), 0).toULongLong()); | 717 | Settings::values.custom_rtc.SetGlobal(custom_rtc_global); |
| 709 | } else { | 718 | if (global || !custom_rtc_global) { |
| 710 | Settings::values.custom_rtc = std::nullopt; | 719 | if (custom_rtc_enabled) { |
| 720 | Settings::values.custom_rtc.SetValue( | ||
| 721 | std::chrono::seconds(ReadSetting(QStringLiteral("custom_rtc"), 0).toULongLong())); | ||
| 722 | } else { | ||
| 723 | Settings::values.custom_rtc.SetValue(std::nullopt); | ||
| 724 | } | ||
| 711 | } | 725 | } |
| 712 | 726 | ||
| 713 | Settings::values.sound_index = ReadSetting(QStringLiteral("sound_index"), 1).toInt(); | 727 | ReadSettingGlobal(Settings::values.sound_index, QStringLiteral("sound_index"), 1); |
| 714 | 728 | ||
| 715 | qt_config->endGroup(); | 729 | qt_config->endGroup(); |
| 716 | } | 730 | } |
| @@ -804,18 +818,20 @@ void Config::ReadWebServiceValues() { | |||
| 804 | } | 818 | } |
| 805 | 819 | ||
| 806 | void Config::ReadValues() { | 820 | void Config::ReadValues() { |
| 807 | ReadControlValues(); | 821 | if (global) { |
| 822 | ReadControlValues(); | ||
| 823 | ReadDataStorageValues(); | ||
| 824 | ReadDebuggingValues(); | ||
| 825 | ReadDisabledAddOnValues(); | ||
| 826 | ReadServiceValues(); | ||
| 827 | ReadUIValues(); | ||
| 828 | ReadWebServiceValues(); | ||
| 829 | ReadMiscellaneousValues(); | ||
| 830 | } | ||
| 808 | ReadCoreValues(); | 831 | ReadCoreValues(); |
| 809 | ReadRendererValues(); | 832 | ReadRendererValues(); |
| 810 | ReadAudioValues(); | 833 | ReadAudioValues(); |
| 811 | ReadDataStorageValues(); | ||
| 812 | ReadSystemValues(); | 834 | ReadSystemValues(); |
| 813 | ReadMiscellaneousValues(); | ||
| 814 | ReadDebuggingValues(); | ||
| 815 | ReadWebServiceValues(); | ||
| 816 | ReadServiceValues(); | ||
| 817 | ReadDisabledAddOnValues(); | ||
| 818 | ReadUIValues(); | ||
| 819 | } | 835 | } |
| 820 | 836 | ||
| 821 | void Config::SavePlayerValues() { | 837 | void Config::SavePlayerValues() { |
| @@ -902,30 +918,35 @@ void Config::SaveTouchscreenValues() { | |||
| 902 | } | 918 | } |
| 903 | 919 | ||
| 904 | void Config::SaveValues() { | 920 | void Config::SaveValues() { |
| 905 | SaveControlValues(); | 921 | if (global) { |
| 922 | SaveControlValues(); | ||
| 923 | SaveDataStorageValues(); | ||
| 924 | SaveDebuggingValues(); | ||
| 925 | SaveDisabledAddOnValues(); | ||
| 926 | SaveServiceValues(); | ||
| 927 | SaveUIValues(); | ||
| 928 | SaveWebServiceValues(); | ||
| 929 | SaveMiscellaneousValues(); | ||
| 930 | } | ||
| 906 | SaveCoreValues(); | 931 | SaveCoreValues(); |
| 907 | SaveRendererValues(); | 932 | SaveRendererValues(); |
| 908 | SaveAudioValues(); | 933 | SaveAudioValues(); |
| 909 | SaveDataStorageValues(); | ||
| 910 | SaveSystemValues(); | 934 | SaveSystemValues(); |
| 911 | SaveMiscellaneousValues(); | ||
| 912 | SaveDebuggingValues(); | ||
| 913 | SaveWebServiceValues(); | ||
| 914 | SaveServiceValues(); | ||
| 915 | SaveDisabledAddOnValues(); | ||
| 916 | SaveUIValues(); | ||
| 917 | } | 935 | } |
| 918 | 936 | ||
| 919 | void Config::SaveAudioValues() { | 937 | void Config::SaveAudioValues() { |
| 920 | qt_config->beginGroup(QStringLiteral("Audio")); | 938 | qt_config->beginGroup(QStringLiteral("Audio")); |
| 921 | 939 | ||
| 922 | WriteSetting(QStringLiteral("output_engine"), QString::fromStdString(Settings::values.sink_id), | 940 | if (global) { |
| 923 | QStringLiteral("auto")); | 941 | WriteSetting(QStringLiteral("output_engine"), |
| 924 | WriteSetting(QStringLiteral("enable_audio_stretching"), | 942 | QString::fromStdString(Settings::values.sink_id), QStringLiteral("auto")); |
| 925 | Settings::values.enable_audio_stretching, true); | 943 | WriteSetting(QStringLiteral("output_device"), |
| 926 | WriteSetting(QStringLiteral("output_device"), | 944 | QString::fromStdString(Settings::values.audio_device_id), |
| 927 | QString::fromStdString(Settings::values.audio_device_id), QStringLiteral("auto")); | 945 | QStringLiteral("auto")); |
| 928 | WriteSetting(QStringLiteral("volume"), Settings::values.volume, 1.0f); | 946 | } |
| 947 | WriteSettingGlobal(QStringLiteral("enable_audio_stretching"), | ||
| 948 | Settings::values.enable_audio_stretching, true); | ||
| 949 | WriteSettingGlobal(QStringLiteral("volume"), Settings::values.volume, 1.0f); | ||
| 929 | 950 | ||
| 930 | qt_config->endGroup(); | 951 | qt_config->endGroup(); |
| 931 | } | 952 | } |
| @@ -948,6 +969,7 @@ void Config::SaveControlValues() { | |||
| 948 | WriteSetting(QStringLiteral("udp_input_port"), Settings::values.udp_input_port, | 969 | WriteSetting(QStringLiteral("udp_input_port"), Settings::values.udp_input_port, |
| 949 | InputCommon::CemuhookUDP::DEFAULT_PORT); | 970 | InputCommon::CemuhookUDP::DEFAULT_PORT); |
| 950 | WriteSetting(QStringLiteral("udp_pad_index"), Settings::values.udp_pad_index, 0); | 971 | WriteSetting(QStringLiteral("udp_pad_index"), Settings::values.udp_pad_index, 0); |
| 972 | WriteSetting(QStringLiteral("use_docked_mode"), Settings::values.use_docked_mode, false); | ||
| 951 | 973 | ||
| 952 | qt_config->endGroup(); | 974 | qt_config->endGroup(); |
| 953 | } | 975 | } |
| @@ -955,7 +977,7 @@ void Config::SaveControlValues() { | |||
| 955 | void Config::SaveCoreValues() { | 977 | void Config::SaveCoreValues() { |
| 956 | qt_config->beginGroup(QStringLiteral("Core")); | 978 | qt_config->beginGroup(QStringLiteral("Core")); |
| 957 | 979 | ||
| 958 | WriteSetting(QStringLiteral("use_multi_core"), Settings::values.use_multi_core, false); | 980 | WriteSettingGlobal(QStringLiteral("use_multi_core"), Settings::values.use_multi_core, false); |
| 959 | 981 | ||
| 960 | qt_config->endGroup(); | 982 | qt_config->endGroup(); |
| 961 | } | 983 | } |
| @@ -1078,29 +1100,34 @@ void Config::SavePathValues() { | |||
| 1078 | void Config::SaveRendererValues() { | 1100 | void Config::SaveRendererValues() { |
| 1079 | qt_config->beginGroup(QStringLiteral("Renderer")); | 1101 | qt_config->beginGroup(QStringLiteral("Renderer")); |
| 1080 | 1102 | ||
| 1081 | WriteSetting(QStringLiteral("backend"), static_cast<int>(Settings::values.renderer_backend), 0); | 1103 | WriteSettingGlobal(QStringLiteral("backend"), |
| 1104 | static_cast<int>(Settings::values.renderer_backend.GetValue(global)), | ||
| 1105 | Settings::values.renderer_backend.UsingGlobal(), 0); | ||
| 1082 | WriteSetting(QStringLiteral("debug"), Settings::values.renderer_debug, false); | 1106 | WriteSetting(QStringLiteral("debug"), Settings::values.renderer_debug, false); |
| 1083 | WriteSetting(QStringLiteral("vulkan_device"), Settings::values.vulkan_device, 0); | 1107 | WriteSettingGlobal(QStringLiteral("vulkan_device"), Settings::values.vulkan_device, 0); |
| 1084 | WriteSetting(QStringLiteral("aspect_ratio"), Settings::values.aspect_ratio, 0); | 1108 | WriteSettingGlobal(QStringLiteral("aspect_ratio"), Settings::values.aspect_ratio, 0); |
| 1085 | WriteSetting(QStringLiteral("max_anisotropy"), Settings::values.max_anisotropy, 0); | 1109 | WriteSettingGlobal(QStringLiteral("max_anisotropy"), Settings::values.max_anisotropy, 0); |
| 1086 | WriteSetting(QStringLiteral("use_frame_limit"), Settings::values.use_frame_limit, true); | 1110 | WriteSettingGlobal(QStringLiteral("use_frame_limit"), Settings::values.use_frame_limit, true); |
| 1087 | WriteSetting(QStringLiteral("frame_limit"), Settings::values.frame_limit, 100); | 1111 | WriteSettingGlobal(QStringLiteral("frame_limit"), Settings::values.frame_limit, 100); |
| 1088 | WriteSetting(QStringLiteral("use_disk_shader_cache"), Settings::values.use_disk_shader_cache, | 1112 | WriteSettingGlobal(QStringLiteral("use_disk_shader_cache"), |
| 1089 | true); | 1113 | Settings::values.use_disk_shader_cache, true); |
| 1090 | WriteSetting(QStringLiteral("gpu_accuracy"), static_cast<int>(Settings::values.gpu_accuracy), | 1114 | WriteSettingGlobal(QStringLiteral("gpu_accuracy"), |
| 1091 | 0); | 1115 | static_cast<int>(Settings::values.gpu_accuracy.GetValue(global)), |
| 1092 | WriteSetting(QStringLiteral("use_asynchronous_gpu_emulation"), | 1116 | Settings::values.gpu_accuracy.UsingGlobal(), 0); |
| 1093 | Settings::values.use_asynchronous_gpu_emulation, false); | 1117 | WriteSettingGlobal(QStringLiteral("use_asynchronous_gpu_emulation"), |
| 1094 | WriteSetting(QStringLiteral("use_vsync"), Settings::values.use_vsync, true); | 1118 | Settings::values.use_asynchronous_gpu_emulation, false); |
| 1095 | WriteSetting(QStringLiteral("use_assembly_shaders"), Settings::values.use_assembly_shaders, | 1119 | WriteSettingGlobal(QStringLiteral("use_vsync"), Settings::values.use_vsync, true); |
| 1096 | false); | 1120 | WriteSettingGlobal(QStringLiteral("use_assembly_shaders"), |
| 1097 | WriteSetting(QStringLiteral("use_fast_gpu_time"), Settings::values.use_fast_gpu_time, true); | 1121 | Settings::values.use_assembly_shaders, false); |
| 1098 | WriteSetting(QStringLiteral("force_30fps_mode"), Settings::values.force_30fps_mode, false); | 1122 | WriteSettingGlobal(QStringLiteral("use_fast_gpu_time"), Settings::values.use_fast_gpu_time, |
| 1123 | true); | ||
| 1124 | WriteSettingGlobal(QStringLiteral("force_30fps_mode"), Settings::values.force_30fps_mode, | ||
| 1125 | false); | ||
| 1099 | 1126 | ||
| 1100 | // Cast to double because Qt's written float values are not human-readable | 1127 | // Cast to double because Qt's written float values are not human-readable |
| 1101 | WriteSetting(QStringLiteral("bg_red"), static_cast<double>(Settings::values.bg_red), 0.0); | 1128 | WriteSettingGlobal(QStringLiteral("bg_red"), Settings::values.bg_red, 0.0); |
| 1102 | WriteSetting(QStringLiteral("bg_green"), static_cast<double>(Settings::values.bg_green), 0.0); | 1129 | WriteSettingGlobal(QStringLiteral("bg_green"), Settings::values.bg_green, 0.0); |
| 1103 | WriteSetting(QStringLiteral("bg_blue"), static_cast<double>(Settings::values.bg_blue), 0.0); | 1130 | WriteSettingGlobal(QStringLiteral("bg_blue"), Settings::values.bg_blue, 0.0); |
| 1104 | 1131 | ||
| 1105 | qt_config->endGroup(); | 1132 | qt_config->endGroup(); |
| 1106 | } | 1133 | } |
| @@ -1128,23 +1155,28 @@ void Config::SaveShortcutValues() { | |||
| 1128 | void Config::SaveSystemValues() { | 1155 | void Config::SaveSystemValues() { |
| 1129 | qt_config->beginGroup(QStringLiteral("System")); | 1156 | qt_config->beginGroup(QStringLiteral("System")); |
| 1130 | 1157 | ||
| 1131 | WriteSetting(QStringLiteral("use_docked_mode"), Settings::values.use_docked_mode, false); | ||
| 1132 | WriteSetting(QStringLiteral("current_user"), Settings::values.current_user, 0); | 1158 | WriteSetting(QStringLiteral("current_user"), Settings::values.current_user, 0); |
| 1133 | WriteSetting(QStringLiteral("language_index"), Settings::values.language_index, 1); | 1159 | WriteSettingGlobal(QStringLiteral("language_index"), Settings::values.language_index, 1); |
| 1134 | WriteSetting(QStringLiteral("region_index"), Settings::values.region_index, 1); | 1160 | WriteSettingGlobal(QStringLiteral("region_index"), Settings::values.region_index, 1); |
| 1135 | WriteSetting(QStringLiteral("time_zone_index"), Settings::values.time_zone_index, 0); | 1161 | WriteSettingGlobal(QStringLiteral("time_zone_index"), Settings::values.time_zone_index, 0); |
| 1136 | 1162 | ||
| 1137 | WriteSetting(QStringLiteral("rng_seed_enabled"), Settings::values.rng_seed.has_value(), false); | 1163 | WriteSettingGlobal(QStringLiteral("rng_seed_enabled"), |
| 1138 | WriteSetting(QStringLiteral("rng_seed"), Settings::values.rng_seed.value_or(0), 0); | 1164 | Settings::values.rng_seed.GetValue(global).has_value(), |
| 1139 | 1165 | Settings::values.rng_seed.UsingGlobal(), false); | |
| 1140 | WriteSetting(QStringLiteral("custom_rtc_enabled"), Settings::values.custom_rtc.has_value(), | 1166 | WriteSettingGlobal(QStringLiteral("rng_seed"), |
| 1141 | false); | 1167 | Settings::values.rng_seed.GetValue(global).value_or(0), |
| 1142 | WriteSetting(QStringLiteral("custom_rtc"), | 1168 | Settings::values.rng_seed.UsingGlobal(), 0); |
| 1143 | QVariant::fromValue<long long>( | 1169 | |
| 1144 | Settings::values.custom_rtc.value_or(std::chrono::seconds{}).count()), | 1170 | WriteSettingGlobal(QStringLiteral("custom_rtc_enabled"), |
| 1145 | 0); | 1171 | Settings::values.custom_rtc.GetValue(global).has_value(), |
| 1146 | 1172 | Settings::values.custom_rtc.UsingGlobal(), false); | |
| 1147 | WriteSetting(QStringLiteral("sound_index"), Settings::values.sound_index, 1); | 1173 | WriteSettingGlobal( |
| 1174 | QStringLiteral("custom_rtc"), | ||
| 1175 | QVariant::fromValue<long long>( | ||
| 1176 | Settings::values.custom_rtc.GetValue(global).value_or(std::chrono::seconds{}).count()), | ||
| 1177 | Settings::values.custom_rtc.UsingGlobal(), 0); | ||
| 1178 | |||
| 1179 | WriteSettingGlobal(QStringLiteral("sound_index"), Settings::values.sound_index, 1); | ||
| 1148 | 1180 | ||
| 1149 | qt_config->endGroup(); | 1181 | qt_config->endGroup(); |
| 1150 | } | 1182 | } |
| @@ -1236,6 +1268,34 @@ QVariant Config::ReadSetting(const QString& name, const QVariant& default_value) | |||
| 1236 | return result; | 1268 | return result; |
| 1237 | } | 1269 | } |
| 1238 | 1270 | ||
| 1271 | template <typename Type> | ||
| 1272 | void Config::ReadSettingGlobal(Settings::Setting<Type>& setting, const QString& name) { | ||
| 1273 | const bool use_global = qt_config->value(name + QStringLiteral("/use_global"), true).toBool(); | ||
| 1274 | setting.SetGlobal(use_global); | ||
| 1275 | if (global || !use_global) { | ||
| 1276 | setting.SetValue(ReadSetting(name).value<Type>()); | ||
| 1277 | } | ||
| 1278 | } | ||
| 1279 | |||
| 1280 | template <typename Type> | ||
| 1281 | void Config::ReadSettingGlobal(Settings::Setting<Type>& setting, const QString& name, | ||
| 1282 | const QVariant& default_value) { | ||
| 1283 | const bool use_global = qt_config->value(name + QStringLiteral("/use_global"), true).toBool(); | ||
| 1284 | setting.SetGlobal(use_global); | ||
| 1285 | if (global || !use_global) { | ||
| 1286 | setting.SetValue(ReadSetting(name, default_value).value<Type>()); | ||
| 1287 | } | ||
| 1288 | } | ||
| 1289 | |||
| 1290 | template <typename Type> | ||
| 1291 | void Config::ReadSettingGlobal(Type& setting, const QString& name, | ||
| 1292 | const QVariant& default_value) const { | ||
| 1293 | const bool use_global = qt_config->value(name + QStringLiteral("/use_global"), true).toBool(); | ||
| 1294 | if (global || !use_global) { | ||
| 1295 | setting = ReadSetting(name, default_value).value<Type>(); | ||
| 1296 | } | ||
| 1297 | } | ||
| 1298 | |||
| 1239 | void Config::WriteSetting(const QString& name, const QVariant& value) { | 1299 | void Config::WriteSetting(const QString& name, const QVariant& value) { |
| 1240 | qt_config->setValue(name, value); | 1300 | qt_config->setValue(name, value); |
| 1241 | } | 1301 | } |
| @@ -1246,6 +1306,40 @@ void Config::WriteSetting(const QString& name, const QVariant& value, | |||
| 1246 | qt_config->setValue(name, value); | 1306 | qt_config->setValue(name, value); |
| 1247 | } | 1307 | } |
| 1248 | 1308 | ||
| 1309 | template <typename Type> | ||
| 1310 | void Config::WriteSettingGlobal(const QString& name, const Settings::Setting<Type>& setting) { | ||
| 1311 | if (!global) { | ||
| 1312 | qt_config->setValue(name + QStringLiteral("/use_global"), setting.UsingGlobal()); | ||
| 1313 | } | ||
| 1314 | if (global || !setting.UsingGlobal()) { | ||
| 1315 | qt_config->setValue(name, setting.GetValue(global)); | ||
| 1316 | } | ||
| 1317 | } | ||
| 1318 | |||
| 1319 | template <typename Type> | ||
| 1320 | void Config::WriteSettingGlobal(const QString& name, const Settings::Setting<Type>& setting, | ||
| 1321 | const QVariant& default_value) { | ||
| 1322 | if (!global) { | ||
| 1323 | qt_config->setValue(name + QStringLiteral("/use_global"), setting.UsingGlobal()); | ||
| 1324 | } | ||
| 1325 | if (global || !setting.UsingGlobal()) { | ||
| 1326 | qt_config->setValue(name + QStringLiteral("/default"), | ||
| 1327 | setting.GetValue(global) == default_value.value<Type>()); | ||
| 1328 | qt_config->setValue(name, setting.GetValue(global)); | ||
| 1329 | } | ||
| 1330 | } | ||
| 1331 | |||
| 1332 | void Config::WriteSettingGlobal(const QString& name, const QVariant& value, bool use_global, | ||
| 1333 | const QVariant& default_value) { | ||
| 1334 | if (!global) { | ||
| 1335 | qt_config->setValue(name + QStringLiteral("/use_global"), use_global); | ||
| 1336 | } | ||
| 1337 | if (global || !use_global) { | ||
| 1338 | qt_config->setValue(name + QStringLiteral("/default"), value == default_value); | ||
| 1339 | qt_config->setValue(name, value); | ||
| 1340 | } | ||
| 1341 | } | ||
| 1342 | |||
| 1249 | void Config::Reload() { | 1343 | void Config::Reload() { |
| 1250 | ReadValues(); | 1344 | ReadValues(); |
| 1251 | // To apply default value changes | 1345 | // To apply default value changes |
diff --git a/src/yuzu/configuration/config.h b/src/yuzu/configuration/config.h index 09316382c..681f0bca5 100644 --- a/src/yuzu/configuration/config.h +++ b/src/yuzu/configuration/config.h | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include <array> | 7 | #include <array> |
| 8 | #include <memory> | 8 | #include <memory> |
| 9 | #include <string> | 9 | #include <string> |
| 10 | #include <QMetaType> | ||
| 10 | #include <QVariant> | 11 | #include <QVariant> |
| 11 | #include "core/settings.h" | 12 | #include "core/settings.h" |
| 12 | #include "yuzu/uisettings.h" | 13 | #include "yuzu/uisettings.h" |
| @@ -15,7 +16,7 @@ class QSettings; | |||
| 15 | 16 | ||
| 16 | class Config { | 17 | class Config { |
| 17 | public: | 18 | public: |
| 18 | Config(); | 19 | explicit Config(const std::string& config_loc = "qt-config.ini", bool is_global = true); |
| 19 | ~Config(); | 20 | ~Config(); |
| 20 | 21 | ||
| 21 | void Reload(); | 22 | void Reload(); |
| @@ -82,9 +83,33 @@ private: | |||
| 82 | 83 | ||
| 83 | QVariant ReadSetting(const QString& name) const; | 84 | QVariant ReadSetting(const QString& name) const; |
| 84 | QVariant ReadSetting(const QString& name, const QVariant& default_value) const; | 85 | QVariant ReadSetting(const QString& name, const QVariant& default_value) const; |
| 86 | // Templated ReadSettingGlobal functions will also look for the use_global setting and set | ||
| 87 | // both the value and the global state properly | ||
| 88 | template <typename Type> | ||
| 89 | void ReadSettingGlobal(Settings::Setting<Type>& setting, const QString& name); | ||
| 90 | template <typename Type> | ||
| 91 | void ReadSettingGlobal(Settings::Setting<Type>& setting, const QString& name, | ||
| 92 | const QVariant& default_value); | ||
| 93 | template <typename Type> | ||
| 94 | void ReadSettingGlobal(Type& setting, const QString& name, const QVariant& default_value) const; | ||
| 95 | // Templated WriteSettingGlobal functions will also write the global state if needed and will | ||
| 96 | // skip writing the actual setting if it defers to the global value | ||
| 85 | void WriteSetting(const QString& name, const QVariant& value); | 97 | void WriteSetting(const QString& name, const QVariant& value); |
| 86 | void WriteSetting(const QString& name, const QVariant& value, const QVariant& default_value); | 98 | void WriteSetting(const QString& name, const QVariant& value, const QVariant& default_value); |
| 99 | template <typename Type> | ||
| 100 | void WriteSettingGlobal(const QString& name, const Settings::Setting<Type>& setting); | ||
| 101 | template <typename Type> | ||
| 102 | void WriteSettingGlobal(const QString& name, const Settings::Setting<Type>& setting, | ||
| 103 | const QVariant& default_value); | ||
| 104 | void WriteSettingGlobal(const QString& name, const QVariant& value, bool use_global, | ||
| 105 | const QVariant& default_value); | ||
| 87 | 106 | ||
| 88 | std::unique_ptr<QSettings> qt_config; | 107 | std::unique_ptr<QSettings> qt_config; |
| 89 | std::string qt_config_loc; | 108 | std::string qt_config_loc; |
| 109 | |||
| 110 | bool global; | ||
| 90 | }; | 111 | }; |
| 112 | |||
| 113 | // These metatype declarations cannot be in core/settings.h because core is devoid of QT | ||
| 114 | Q_DECLARE_METATYPE(Settings::RendererBackend); | ||
| 115 | Q_DECLARE_METATYPE(Settings::GPUAccuracy); | ||
diff --git a/src/yuzu/configuration/configuration_shared.cpp b/src/yuzu/configuration/configuration_shared.cpp new file mode 100644 index 000000000..bb47c3933 --- /dev/null +++ b/src/yuzu/configuration/configuration_shared.cpp | |||
| @@ -0,0 +1,76 @@ | |||
| 1 | // Copyright 2016 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <QCheckBox> | ||
| 6 | #include <QComboBox> | ||
| 7 | #include "core/settings.h" | ||
| 8 | #include "yuzu/configuration/configuration_shared.h" | ||
| 9 | #include "yuzu/configuration/configure_per_game.h" | ||
| 10 | |||
| 11 | void ConfigurationShared::ApplyPerGameSetting(Settings::Setting<bool>* setting, | ||
| 12 | const QCheckBox* checkbox) { | ||
| 13 | if (checkbox->checkState() == Qt::PartiallyChecked) { | ||
| 14 | setting->SetGlobal(true); | ||
| 15 | } else { | ||
| 16 | setting->SetGlobal(false); | ||
| 17 | setting->SetValue(checkbox->checkState() == Qt::Checked); | ||
| 18 | } | ||
| 19 | } | ||
| 20 | |||
| 21 | void ConfigurationShared::ApplyPerGameSetting(Settings::Setting<int>* setting, | ||
| 22 | const QComboBox* combobox) { | ||
| 23 | if (combobox->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) { | ||
| 24 | setting->SetGlobal(true); | ||
| 25 | } else { | ||
| 26 | setting->SetGlobal(false); | ||
| 27 | setting->SetValue(combobox->currentIndex() - ConfigurationShared::USE_GLOBAL_OFFSET); | ||
| 28 | } | ||
| 29 | } | ||
| 30 | |||
| 31 | void ConfigurationShared::ApplyPerGameSetting(Settings::Setting<Settings::RendererBackend>* setting, | ||
| 32 | const QComboBox* combobox) { | ||
| 33 | if (combobox->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) { | ||
| 34 | setting->SetGlobal(true); | ||
| 35 | } else { | ||
| 36 | setting->SetGlobal(false); | ||
| 37 | setting->SetValue(static_cast<Settings::RendererBackend>( | ||
| 38 | combobox->currentIndex() - ConfigurationShared::USE_GLOBAL_OFFSET)); | ||
| 39 | } | ||
| 40 | } | ||
| 41 | |||
| 42 | void ConfigurationShared::SetPerGameSetting(QCheckBox* checkbox, | ||
| 43 | const Settings::Setting<bool>* setting) { | ||
| 44 | if (setting->UsingGlobal()) { | ||
| 45 | checkbox->setCheckState(Qt::PartiallyChecked); | ||
| 46 | } else { | ||
| 47 | checkbox->setCheckState(setting->GetValue() ? Qt::Checked : Qt::Unchecked); | ||
| 48 | } | ||
| 49 | } | ||
| 50 | |||
| 51 | void ConfigurationShared::SetPerGameSetting(QComboBox* combobox, | ||
| 52 | const Settings::Setting<int>* setting) { | ||
| 53 | combobox->setCurrentIndex(setting->UsingGlobal() | ||
| 54 | ? ConfigurationShared::USE_GLOBAL_INDEX | ||
| 55 | : setting->GetValue() + ConfigurationShared::USE_GLOBAL_OFFSET); | ||
| 56 | } | ||
| 57 | |||
| 58 | void ConfigurationShared::SetPerGameSetting( | ||
| 59 | QComboBox* combobox, const Settings::Setting<Settings::RendererBackend>* setting) { | ||
| 60 | combobox->setCurrentIndex(setting->UsingGlobal() ? ConfigurationShared::USE_GLOBAL_INDEX | ||
| 61 | : static_cast<int>(setting->GetValue()) + | ||
| 62 | ConfigurationShared::USE_GLOBAL_OFFSET); | ||
| 63 | } | ||
| 64 | |||
| 65 | void ConfigurationShared::SetPerGameSetting( | ||
| 66 | QComboBox* combobox, const Settings::Setting<Settings::GPUAccuracy>* setting) { | ||
| 67 | combobox->setCurrentIndex(setting->UsingGlobal() ? ConfigurationShared::USE_GLOBAL_INDEX | ||
| 68 | : static_cast<int>(setting->GetValue()) + | ||
| 69 | ConfigurationShared::USE_GLOBAL_OFFSET); | ||
| 70 | } | ||
| 71 | |||
| 72 | void ConfigurationShared::InsertGlobalItem(QComboBox* combobox) { | ||
| 73 | const QString use_global_text = ConfigurePerGame::tr("Use global configuration"); | ||
| 74 | combobox->insertItem(ConfigurationShared::USE_GLOBAL_INDEX, use_global_text); | ||
| 75 | combobox->insertSeparator(ConfigurationShared::USE_GLOBAL_SEPARATOR_INDEX); | ||
| 76 | } | ||
diff --git a/src/yuzu/configuration/configuration_shared.h b/src/yuzu/configuration/configuration_shared.h new file mode 100644 index 000000000..b11b1b950 --- /dev/null +++ b/src/yuzu/configuration/configuration_shared.h | |||
| @@ -0,0 +1,36 @@ | |||
| 1 | // Copyright 2016 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <QCheckBox> | ||
| 8 | #include <QComboBox> | ||
| 9 | #include <QString> | ||
| 10 | #include "core/settings.h" | ||
| 11 | |||
| 12 | namespace ConfigurationShared { | ||
| 13 | |||
| 14 | constexpr int USE_GLOBAL_INDEX = 0; | ||
| 15 | constexpr int USE_GLOBAL_SEPARATOR_INDEX = 1; | ||
| 16 | constexpr int USE_GLOBAL_OFFSET = 2; | ||
| 17 | |||
| 18 | // Global-aware apply and set functions | ||
| 19 | |||
| 20 | void ApplyPerGameSetting(Settings::Setting<bool>* setting, const QCheckBox* checkbox); | ||
| 21 | void ApplyPerGameSetting(Settings::Setting<int>* setting, const QComboBox* combobox); | ||
| 22 | void ApplyPerGameSetting(Settings::Setting<Settings::RendererBackend>* setting, | ||
| 23 | const QComboBox* combobox); | ||
| 24 | void ApplyPerGameSetting(Settings::Setting<Settings::GPUAccuracy>* setting, | ||
| 25 | const QComboBox* combobox); | ||
| 26 | |||
| 27 | void SetPerGameSetting(QCheckBox* checkbox, const Settings::Setting<bool>* setting); | ||
| 28 | void SetPerGameSetting(QComboBox* combobox, const Settings::Setting<int>* setting); | ||
| 29 | void SetPerGameSetting(QComboBox* combobox, | ||
| 30 | const Settings::Setting<Settings::RendererBackend>* setting); | ||
| 31 | void SetPerGameSetting(QComboBox* combobox, | ||
| 32 | const Settings::Setting<Settings::GPUAccuracy>* setting); | ||
| 33 | |||
| 34 | void InsertGlobalItem(QComboBox* combobox); | ||
| 35 | |||
| 36 | } // namespace ConfigurationShared | ||
diff --git a/src/yuzu/configuration/configure_audio.cpp b/src/yuzu/configuration/configure_audio.cpp index f370c690f..cc021beec 100644 --- a/src/yuzu/configuration/configure_audio.cpp +++ b/src/yuzu/configuration/configure_audio.cpp | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | #include "core/core.h" | 11 | #include "core/core.h" |
| 12 | #include "core/settings.h" | 12 | #include "core/settings.h" |
| 13 | #include "ui_configure_audio.h" | 13 | #include "ui_configure_audio.h" |
| 14 | #include "yuzu/configuration/configuration_shared.h" | ||
| 14 | #include "yuzu/configuration/configure_audio.h" | 15 | #include "yuzu/configuration/configure_audio.h" |
| 15 | 16 | ||
| 16 | ConfigureAudio::ConfigureAudio(QWidget* parent) | 17 | ConfigureAudio::ConfigureAudio(QWidget* parent) |
| @@ -24,6 +25,11 @@ ConfigureAudio::ConfigureAudio(QWidget* parent) | |||
| 24 | connect(ui->output_sink_combo_box, qOverload<int>(&QComboBox::currentIndexChanged), this, | 25 | connect(ui->output_sink_combo_box, qOverload<int>(&QComboBox::currentIndexChanged), this, |
| 25 | &ConfigureAudio::UpdateAudioDevices); | 26 | &ConfigureAudio::UpdateAudioDevices); |
| 26 | 27 | ||
| 28 | ui->volume_label->setVisible(Settings::configuring_global); | ||
| 29 | ui->volume_combo_box->setVisible(!Settings::configuring_global); | ||
| 30 | |||
| 31 | SetupPerGameUI(); | ||
| 32 | |||
| 27 | SetConfiguration(); | 33 | SetConfiguration(); |
| 28 | 34 | ||
| 29 | const bool is_powered_on = Core::System::GetInstance().IsPoweredOn(); | 35 | const bool is_powered_on = Core::System::GetInstance().IsPoweredOn(); |
| @@ -41,8 +47,22 @@ void ConfigureAudio::SetConfiguration() { | |||
| 41 | 47 | ||
| 42 | SetAudioDeviceFromDeviceID(); | 48 | SetAudioDeviceFromDeviceID(); |
| 43 | 49 | ||
| 44 | ui->toggle_audio_stretching->setChecked(Settings::values.enable_audio_stretching); | 50 | ui->volume_slider->setValue(Settings::values.volume.GetValue() * ui->volume_slider->maximum()); |
| 45 | ui->volume_slider->setValue(Settings::values.volume * ui->volume_slider->maximum()); | 51 | |
| 52 | if (Settings::configuring_global) { | ||
| 53 | ui->toggle_audio_stretching->setChecked( | ||
| 54 | Settings::values.enable_audio_stretching.GetValue()); | ||
| 55 | } else { | ||
| 56 | ConfigurationShared::SetPerGameSetting(ui->toggle_audio_stretching, | ||
| 57 | &Settings::values.enable_audio_stretching); | ||
| 58 | if (Settings::values.volume.UsingGlobal()) { | ||
| 59 | ui->volume_combo_box->setCurrentIndex(0); | ||
| 60 | ui->volume_slider->setEnabled(false); | ||
| 61 | } else { | ||
| 62 | ui->volume_combo_box->setCurrentIndex(1); | ||
| 63 | ui->volume_slider->setEnabled(true); | ||
| 64 | } | ||
| 65 | } | ||
| 46 | SetVolumeIndicatorText(ui->volume_slider->sliderPosition()); | 66 | SetVolumeIndicatorText(ui->volume_slider->sliderPosition()); |
| 47 | } | 67 | } |
| 48 | 68 | ||
| @@ -80,15 +100,36 @@ void ConfigureAudio::SetVolumeIndicatorText(int percentage) { | |||
| 80 | } | 100 | } |
| 81 | 101 | ||
| 82 | void ConfigureAudio::ApplyConfiguration() { | 102 | void ConfigureAudio::ApplyConfiguration() { |
| 83 | Settings::values.sink_id = | 103 | if (Settings::configuring_global) { |
| 84 | ui->output_sink_combo_box->itemText(ui->output_sink_combo_box->currentIndex()) | 104 | Settings::values.sink_id = |
| 85 | .toStdString(); | 105 | ui->output_sink_combo_box->itemText(ui->output_sink_combo_box->currentIndex()) |
| 86 | Settings::values.enable_audio_stretching = ui->toggle_audio_stretching->isChecked(); | 106 | .toStdString(); |
| 87 | Settings::values.audio_device_id = | 107 | Settings::values.audio_device_id = |
| 88 | ui->audio_device_combo_box->itemText(ui->audio_device_combo_box->currentIndex()) | 108 | ui->audio_device_combo_box->itemText(ui->audio_device_combo_box->currentIndex()) |
| 89 | .toStdString(); | 109 | .toStdString(); |
| 90 | Settings::values.volume = | 110 | |
| 91 | static_cast<float>(ui->volume_slider->sliderPosition()) / ui->volume_slider->maximum(); | 111 | // Guard if during game and set to game-specific value |
| 112 | if (Settings::values.enable_audio_stretching.UsingGlobal()) { | ||
| 113 | Settings::values.enable_audio_stretching.SetValue( | ||
| 114 | ui->toggle_audio_stretching->isChecked()); | ||
| 115 | } | ||
| 116 | if (Settings::values.volume.UsingGlobal()) { | ||
| 117 | Settings::values.volume.SetValue( | ||
| 118 | static_cast<float>(ui->volume_slider->sliderPosition()) / | ||
| 119 | ui->volume_slider->maximum()); | ||
| 120 | } | ||
| 121 | } else { | ||
| 122 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.enable_audio_stretching, | ||
| 123 | ui->toggle_audio_stretching); | ||
| 124 | if (ui->volume_combo_box->currentIndex() == 0) { | ||
| 125 | Settings::values.volume.SetGlobal(true); | ||
| 126 | } else { | ||
| 127 | Settings::values.volume.SetGlobal(false); | ||
| 128 | Settings::values.volume.SetValue( | ||
| 129 | static_cast<float>(ui->volume_slider->sliderPosition()) / | ||
| 130 | ui->volume_slider->maximum()); | ||
| 131 | } | ||
| 132 | } | ||
| 92 | } | 133 | } |
| 93 | 134 | ||
| 94 | void ConfigureAudio::changeEvent(QEvent* event) { | 135 | void ConfigureAudio::changeEvent(QEvent* event) { |
| @@ -122,3 +163,22 @@ void ConfigureAudio::RetranslateUI() { | |||
| 122 | ui->retranslateUi(this); | 163 | ui->retranslateUi(this); |
| 123 | SetVolumeIndicatorText(ui->volume_slider->sliderPosition()); | 164 | SetVolumeIndicatorText(ui->volume_slider->sliderPosition()); |
| 124 | } | 165 | } |
| 166 | |||
| 167 | void ConfigureAudio::SetupPerGameUI() { | ||
| 168 | if (Settings::configuring_global) { | ||
| 169 | ui->volume_slider->setEnabled(Settings::values.volume.UsingGlobal()); | ||
| 170 | ui->toggle_audio_stretching->setEnabled( | ||
| 171 | Settings::values.enable_audio_stretching.UsingGlobal()); | ||
| 172 | |||
| 173 | return; | ||
| 174 | } | ||
| 175 | |||
| 176 | ui->toggle_audio_stretching->setTristate(true); | ||
| 177 | connect(ui->volume_combo_box, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), | ||
| 178 | this, [this](int index) { ui->volume_slider->setEnabled(index == 1); }); | ||
| 179 | |||
| 180 | ui->output_sink_combo_box->setVisible(false); | ||
| 181 | ui->output_sink_label->setVisible(false); | ||
| 182 | ui->audio_device_combo_box->setVisible(false); | ||
| 183 | ui->audio_device_label->setVisible(false); | ||
| 184 | } | ||
diff --git a/src/yuzu/configuration/configure_audio.h b/src/yuzu/configuration/configure_audio.h index ea83bd72d..d84f4a682 100644 --- a/src/yuzu/configuration/configure_audio.h +++ b/src/yuzu/configuration/configure_audio.h | |||
| @@ -34,5 +34,7 @@ private: | |||
| 34 | void SetAudioDeviceFromDeviceID(); | 34 | void SetAudioDeviceFromDeviceID(); |
| 35 | void SetVolumeIndicatorText(int percentage); | 35 | void SetVolumeIndicatorText(int percentage); |
| 36 | 36 | ||
| 37 | void SetupPerGameUI(); | ||
| 38 | |||
| 37 | std::unique_ptr<Ui::ConfigureAudio> ui; | 39 | std::unique_ptr<Ui::ConfigureAudio> ui; |
| 38 | }; | 40 | }; |
diff --git a/src/yuzu/configuration/configure_audio.ui b/src/yuzu/configuration/configure_audio.ui index a098b9acc..862ccb988 100644 --- a/src/yuzu/configuration/configure_audio.ui +++ b/src/yuzu/configuration/configure_audio.ui | |||
| @@ -6,8 +6,8 @@ | |||
| 6 | <rect> | 6 | <rect> |
| 7 | <x>0</x> | 7 | <x>0</x> |
| 8 | <y>0</y> | 8 | <y>0</y> |
| 9 | <width>188</width> | 9 | <width>367</width> |
| 10 | <height>246</height> | 10 | <height>368</height> |
| 11 | </rect> | 11 | </rect> |
| 12 | </property> | 12 | </property> |
| 13 | <layout class="QVBoxLayout"> | 13 | <layout class="QVBoxLayout"> |
| @@ -18,9 +18,9 @@ | |||
| 18 | </property> | 18 | </property> |
| 19 | <layout class="QVBoxLayout"> | 19 | <layout class="QVBoxLayout"> |
| 20 | <item> | 20 | <item> |
| 21 | <layout class="QHBoxLayout"> | 21 | <layout class="QHBoxLayout" name="_3"> |
| 22 | <item> | 22 | <item> |
| 23 | <widget class="QLabel" name="label_1"> | 23 | <widget class="QLabel" name="output_sink_label"> |
| 24 | <property name="text"> | 24 | <property name="text"> |
| 25 | <string>Output Engine:</string> | 25 | <string>Output Engine:</string> |
| 26 | </property> | 26 | </property> |
| @@ -31,20 +31,20 @@ | |||
| 31 | </item> | 31 | </item> |
| 32 | </layout> | 32 | </layout> |
| 33 | </item> | 33 | </item> |
| 34 | <item> | ||
| 35 | <widget class="QCheckBox" name="toggle_audio_stretching"> | ||
| 36 | <property name="toolTip"> | ||
| 37 | <string>This post-processing effect adjusts audio speed to match emulation speed and helps prevent audio stutter. This however increases audio latency.</string> | ||
| 38 | </property> | ||
| 39 | <property name="text"> | ||
| 40 | <string>Enable audio stretching</string> | ||
| 41 | </property> | ||
| 42 | </widget> | ||
| 43 | </item> | ||
| 44 | <item> | 34 | <item> |
| 45 | <layout class="QHBoxLayout"> | 35 | <widget class="QCheckBox" name="toggle_audio_stretching"> |
| 36 | <property name="toolTip"> | ||
| 37 | <string>This post-processing effect adjusts audio speed to match emulation speed and helps prevent audio stutter. This however increases audio latency.</string> | ||
| 38 | </property> | ||
| 39 | <property name="text"> | ||
| 40 | <string>Enable audio stretching</string> | ||
| 41 | </property> | ||
| 42 | </widget> | ||
| 43 | </item> | ||
| 44 | <item> | ||
| 45 | <layout class="QHBoxLayout" name="_2"> | ||
| 46 | <item> | 46 | <item> |
| 47 | <widget class="QLabel" name="label_2"> | 47 | <widget class="QLabel" name="audio_device_label"> |
| 48 | <property name="text"> | 48 | <property name="text"> |
| 49 | <string>Audio Device:</string> | 49 | <string>Audio Device:</string> |
| 50 | </property> | 50 | </property> |
| @@ -61,7 +61,21 @@ | |||
| 61 | <number>0</number> | 61 | <number>0</number> |
| 62 | </property> | 62 | </property> |
| 63 | <item> | 63 | <item> |
| 64 | <widget class="QLabel" name="label_3"> | 64 | <widget class="QComboBox" name="volume_combo_box"> |
| 65 | <item> | ||
| 66 | <property name="text"> | ||
| 67 | <string>Use global volume</string> | ||
| 68 | </property> | ||
| 69 | </item> | ||
| 70 | <item> | ||
| 71 | <property name="text"> | ||
| 72 | <string>Set volume:</string> | ||
| 73 | </property> | ||
| 74 | </item> | ||
| 75 | </widget> | ||
| 76 | </item> | ||
| 77 | <item> | ||
| 78 | <widget class="QLabel" name="volume_label"> | ||
| 65 | <property name="text"> | 79 | <property name="text"> |
| 66 | <string>Volume:</string> | 80 | <string>Volume:</string> |
| 67 | </property> | 81 | </property> |
| @@ -74,7 +88,7 @@ | |||
| 74 | </property> | 88 | </property> |
| 75 | <property name="sizeHint" stdset="0"> | 89 | <property name="sizeHint" stdset="0"> |
| 76 | <size> | 90 | <size> |
| 77 | <width>40</width> | 91 | <width>30</width> |
| 78 | <height>20</height> | 92 | <height>20</height> |
| 79 | </size> | 93 | </size> |
| 80 | </property> | 94 | </property> |
diff --git a/src/yuzu/configuration/configure_dialog.cpp b/src/yuzu/configuration/configure_dialog.cpp index df4473b46..5918e9972 100644 --- a/src/yuzu/configuration/configure_dialog.cpp +++ b/src/yuzu/configuration/configure_dialog.cpp | |||
| @@ -14,6 +14,8 @@ | |||
| 14 | 14 | ||
| 15 | ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry) | 15 | ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry) |
| 16 | : QDialog(parent), ui(new Ui::ConfigureDialog), registry(registry) { | 16 | : QDialog(parent), ui(new Ui::ConfigureDialog), registry(registry) { |
| 17 | Settings::configuring_global = true; | ||
| 18 | |||
| 17 | ui->setupUi(this); | 19 | ui->setupUi(this); |
| 18 | ui->hotkeysTab->Populate(registry); | 20 | ui->hotkeysTab->Populate(registry); |
| 19 | setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); | 21 | setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); |
diff --git a/src/yuzu/configuration/configure_general.cpp b/src/yuzu/configuration/configure_general.cpp index 74b2ad537..1fb62d1cf 100644 --- a/src/yuzu/configuration/configure_general.cpp +++ b/src/yuzu/configuration/configure_general.cpp | |||
| @@ -7,17 +7,21 @@ | |||
| 7 | #include "core/core.h" | 7 | #include "core/core.h" |
| 8 | #include "core/settings.h" | 8 | #include "core/settings.h" |
| 9 | #include "ui_configure_general.h" | 9 | #include "ui_configure_general.h" |
| 10 | #include "yuzu/configuration/configuration_shared.h" | ||
| 10 | #include "yuzu/configuration/configure_general.h" | 11 | #include "yuzu/configuration/configure_general.h" |
| 11 | #include "yuzu/uisettings.h" | 12 | #include "yuzu/uisettings.h" |
| 12 | 13 | ||
| 13 | ConfigureGeneral::ConfigureGeneral(QWidget* parent) | 14 | ConfigureGeneral::ConfigureGeneral(QWidget* parent) |
| 14 | : QWidget(parent), ui(new Ui::ConfigureGeneral) { | 15 | : QWidget(parent), ui(new Ui::ConfigureGeneral) { |
| 15 | |||
| 16 | ui->setupUi(this); | 16 | ui->setupUi(this); |
| 17 | 17 | ||
| 18 | SetupPerGameUI(); | ||
| 19 | |||
| 18 | SetConfiguration(); | 20 | SetConfiguration(); |
| 19 | 21 | ||
| 20 | connect(ui->toggle_frame_limit, &QCheckBox::toggled, ui->frame_limit, &QSpinBox::setEnabled); | 22 | connect(ui->toggle_frame_limit, &QCheckBox::stateChanged, ui->frame_limit, [this]() { |
| 23 | ui->frame_limit->setEnabled(ui->toggle_frame_limit->checkState() == Qt::Checked); | ||
| 24 | }); | ||
| 21 | } | 25 | } |
| 22 | 26 | ||
| 23 | ConfigureGeneral::~ConfigureGeneral() = default; | 27 | ConfigureGeneral::~ConfigureGeneral() = default; |
| @@ -26,27 +30,56 @@ void ConfigureGeneral::SetConfiguration() { | |||
| 26 | const bool runtime_lock = !Core::System::GetInstance().IsPoweredOn(); | 30 | const bool runtime_lock = !Core::System::GetInstance().IsPoweredOn(); |
| 27 | 31 | ||
| 28 | ui->use_multi_core->setEnabled(runtime_lock); | 32 | ui->use_multi_core->setEnabled(runtime_lock); |
| 29 | ui->use_multi_core->setChecked(Settings::values.use_multi_core); | 33 | ui->use_multi_core->setChecked(Settings::values.use_multi_core.GetValue()); |
| 30 | 34 | ||
| 31 | ui->toggle_check_exit->setChecked(UISettings::values.confirm_before_closing); | 35 | ui->toggle_check_exit->setChecked(UISettings::values.confirm_before_closing); |
| 32 | ui->toggle_user_on_boot->setChecked(UISettings::values.select_user_on_boot); | 36 | ui->toggle_user_on_boot->setChecked(UISettings::values.select_user_on_boot); |
| 33 | ui->toggle_background_pause->setChecked(UISettings::values.pause_when_in_background); | 37 | ui->toggle_background_pause->setChecked(UISettings::values.pause_when_in_background); |
| 34 | ui->toggle_hide_mouse->setChecked(UISettings::values.hide_mouse); | 38 | ui->toggle_hide_mouse->setChecked(UISettings::values.hide_mouse); |
| 35 | 39 | ||
| 36 | ui->toggle_frame_limit->setChecked(Settings::values.use_frame_limit); | 40 | ui->toggle_frame_limit->setChecked(Settings::values.use_frame_limit.GetValue()); |
| 37 | ui->frame_limit->setEnabled(ui->toggle_frame_limit->isChecked()); | 41 | ui->frame_limit->setValue(Settings::values.frame_limit.GetValue()); |
| 38 | ui->frame_limit->setValue(Settings::values.frame_limit); | 42 | |
| 43 | if (!Settings::configuring_global) { | ||
| 44 | if (Settings::values.use_multi_core.UsingGlobal()) { | ||
| 45 | ui->use_multi_core->setCheckState(Qt::PartiallyChecked); | ||
| 46 | } | ||
| 47 | if (Settings::values.use_frame_limit.UsingGlobal()) { | ||
| 48 | ui->toggle_frame_limit->setCheckState(Qt::PartiallyChecked); | ||
| 49 | } | ||
| 50 | } | ||
| 51 | |||
| 52 | ui->frame_limit->setEnabled(ui->toggle_frame_limit->checkState() == Qt::Checked && | ||
| 53 | ui->toggle_frame_limit->isEnabled()); | ||
| 39 | } | 54 | } |
| 40 | 55 | ||
| 41 | void ConfigureGeneral::ApplyConfiguration() { | 56 | void ConfigureGeneral::ApplyConfiguration() { |
| 42 | UISettings::values.confirm_before_closing = ui->toggle_check_exit->isChecked(); | 57 | if (Settings::configuring_global) { |
| 43 | UISettings::values.select_user_on_boot = ui->toggle_user_on_boot->isChecked(); | 58 | UISettings::values.confirm_before_closing = ui->toggle_check_exit->isChecked(); |
| 44 | UISettings::values.pause_when_in_background = ui->toggle_background_pause->isChecked(); | 59 | UISettings::values.select_user_on_boot = ui->toggle_user_on_boot->isChecked(); |
| 45 | UISettings::values.hide_mouse = ui->toggle_hide_mouse->isChecked(); | 60 | UISettings::values.pause_when_in_background = ui->toggle_background_pause->isChecked(); |
| 46 | 61 | UISettings::values.hide_mouse = ui->toggle_hide_mouse->isChecked(); | |
| 47 | Settings::values.use_frame_limit = ui->toggle_frame_limit->isChecked(); | 62 | |
| 48 | Settings::values.frame_limit = ui->frame_limit->value(); | 63 | // Guard if during game and set to game-specific value |
| 49 | Settings::values.use_multi_core = ui->use_multi_core->isChecked(); | 64 | if (Settings::values.use_frame_limit.UsingGlobal()) { |
| 65 | Settings::values.use_frame_limit.SetValue(ui->toggle_frame_limit->checkState() == | ||
| 66 | Qt::Checked); | ||
| 67 | Settings::values.frame_limit.SetValue(ui->frame_limit->value()); | ||
| 68 | Settings::values.use_multi_core.SetValue(ui->use_multi_core->isChecked()); | ||
| 69 | } | ||
| 70 | } else { | ||
| 71 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_multi_core, | ||
| 72 | ui->use_multi_core); | ||
| 73 | |||
| 74 | bool global_frame_limit = ui->toggle_frame_limit->checkState() == Qt::PartiallyChecked; | ||
| 75 | Settings::values.use_frame_limit.SetGlobal(global_frame_limit); | ||
| 76 | Settings::values.frame_limit.SetGlobal(global_frame_limit); | ||
| 77 | if (!global_frame_limit) { | ||
| 78 | Settings::values.use_frame_limit.SetValue(ui->toggle_frame_limit->checkState() == | ||
| 79 | Qt::Checked); | ||
| 80 | Settings::values.frame_limit.SetValue(ui->frame_limit->value()); | ||
| 81 | } | ||
| 82 | } | ||
| 50 | } | 83 | } |
| 51 | 84 | ||
| 52 | void ConfigureGeneral::changeEvent(QEvent* event) { | 85 | void ConfigureGeneral::changeEvent(QEvent* event) { |
| @@ -60,3 +93,20 @@ void ConfigureGeneral::changeEvent(QEvent* event) { | |||
| 60 | void ConfigureGeneral::RetranslateUI() { | 93 | void ConfigureGeneral::RetranslateUI() { |
| 61 | ui->retranslateUi(this); | 94 | ui->retranslateUi(this); |
| 62 | } | 95 | } |
| 96 | |||
| 97 | void ConfigureGeneral::SetupPerGameUI() { | ||
| 98 | if (Settings::configuring_global) { | ||
| 99 | ui->toggle_frame_limit->setEnabled(Settings::values.use_frame_limit.UsingGlobal()); | ||
| 100 | ui->frame_limit->setEnabled(Settings::values.frame_limit.UsingGlobal()); | ||
| 101 | |||
| 102 | return; | ||
| 103 | } | ||
| 104 | |||
| 105 | ui->toggle_check_exit->setVisible(false); | ||
| 106 | ui->toggle_user_on_boot->setVisible(false); | ||
| 107 | ui->toggle_background_pause->setVisible(false); | ||
| 108 | ui->toggle_hide_mouse->setVisible(false); | ||
| 109 | |||
| 110 | ui->toggle_frame_limit->setTristate(true); | ||
| 111 | ui->use_multi_core->setTristate(true); | ||
| 112 | } | ||
diff --git a/src/yuzu/configuration/configure_general.h b/src/yuzu/configuration/configure_general.h index ef05ce065..9c785c22e 100644 --- a/src/yuzu/configuration/configure_general.h +++ b/src/yuzu/configuration/configure_general.h | |||
| @@ -28,5 +28,7 @@ private: | |||
| 28 | 28 | ||
| 29 | void SetConfiguration(); | 29 | void SetConfiguration(); |
| 30 | 30 | ||
| 31 | void SetupPerGameUI(); | ||
| 32 | |||
| 31 | std::unique_ptr<Ui::ConfigureGeneral> ui; | 33 | std::unique_ptr<Ui::ConfigureGeneral> ui; |
| 32 | }; | 34 | }; |
diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp index 431f51d73..cb4706bd6 100644 --- a/src/yuzu/configuration/configure_graphics.cpp +++ b/src/yuzu/configuration/configure_graphics.cpp | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #include "core/core.h" | 13 | #include "core/core.h" |
| 14 | #include "core/settings.h" | 14 | #include "core/settings.h" |
| 15 | #include "ui_configure_graphics.h" | 15 | #include "ui_configure_graphics.h" |
| 16 | #include "yuzu/configuration/configuration_shared.h" | ||
| 16 | #include "yuzu/configuration/configure_graphics.h" | 17 | #include "yuzu/configuration/configure_graphics.h" |
| 17 | 18 | ||
| 18 | #ifdef HAS_VULKAN | 19 | #ifdef HAS_VULKAN |
| @@ -21,11 +22,13 @@ | |||
| 21 | 22 | ||
| 22 | ConfigureGraphics::ConfigureGraphics(QWidget* parent) | 23 | ConfigureGraphics::ConfigureGraphics(QWidget* parent) |
| 23 | : QWidget(parent), ui(new Ui::ConfigureGraphics) { | 24 | : QWidget(parent), ui(new Ui::ConfigureGraphics) { |
| 24 | vulkan_device = Settings::values.vulkan_device; | 25 | vulkan_device = Settings::values.vulkan_device.GetValue(); |
| 25 | RetrieveVulkanDevices(); | 26 | RetrieveVulkanDevices(); |
| 26 | 27 | ||
| 27 | ui->setupUi(this); | 28 | ui->setupUi(this); |
| 28 | 29 | ||
| 30 | SetupPerGameUI(); | ||
| 31 | |||
| 29 | SetConfiguration(); | 32 | SetConfiguration(); |
| 30 | 33 | ||
| 31 | connect(ui->api, qOverload<int>(&QComboBox::currentIndexChanged), this, | 34 | connect(ui->api, qOverload<int>(&QComboBox::currentIndexChanged), this, |
| @@ -40,6 +43,9 @@ ConfigureGraphics::ConfigureGraphics(QWidget* parent) | |||
| 40 | } | 43 | } |
| 41 | UpdateBackgroundColorButton(new_bg_color); | 44 | UpdateBackgroundColorButton(new_bg_color); |
| 42 | }); | 45 | }); |
| 46 | |||
| 47 | ui->bg_label->setVisible(Settings::configuring_global); | ||
| 48 | ui->bg_combobox->setVisible(!Settings::configuring_global); | ||
| 43 | } | 49 | } |
| 44 | 50 | ||
| 45 | void ConfigureGraphics::UpdateDeviceSelection(int device) { | 51 | void ConfigureGraphics::UpdateDeviceSelection(int device) { |
| @@ -57,27 +63,95 @@ void ConfigureGraphics::SetConfiguration() { | |||
| 57 | const bool runtime_lock = !Core::System::GetInstance().IsPoweredOn(); | 63 | const bool runtime_lock = !Core::System::GetInstance().IsPoweredOn(); |
| 58 | 64 | ||
| 59 | ui->api->setEnabled(runtime_lock); | 65 | ui->api->setEnabled(runtime_lock); |
| 60 | ui->api->setCurrentIndex(static_cast<int>(Settings::values.renderer_backend)); | ||
| 61 | ui->aspect_ratio_combobox->setCurrentIndex(Settings::values.aspect_ratio); | ||
| 62 | ui->use_disk_shader_cache->setEnabled(runtime_lock); | ||
| 63 | ui->use_disk_shader_cache->setChecked(Settings::values.use_disk_shader_cache); | ||
| 64 | ui->use_asynchronous_gpu_emulation->setEnabled(runtime_lock); | 66 | ui->use_asynchronous_gpu_emulation->setEnabled(runtime_lock); |
| 65 | ui->use_asynchronous_gpu_emulation->setChecked(Settings::values.use_asynchronous_gpu_emulation); | 67 | ui->use_disk_shader_cache->setEnabled(runtime_lock); |
| 66 | UpdateBackgroundColorButton(QColor::fromRgbF(Settings::values.bg_red, Settings::values.bg_green, | 68 | |
| 67 | Settings::values.bg_blue)); | 69 | if (Settings::configuring_global) { |
| 70 | ui->api->setCurrentIndex(static_cast<int>(Settings::values.renderer_backend.GetValue())); | ||
| 71 | ui->aspect_ratio_combobox->setCurrentIndex(Settings::values.aspect_ratio.GetValue()); | ||
| 72 | ui->use_disk_shader_cache->setChecked(Settings::values.use_disk_shader_cache.GetValue()); | ||
| 73 | ui->use_asynchronous_gpu_emulation->setChecked( | ||
| 74 | Settings::values.use_asynchronous_gpu_emulation.GetValue()); | ||
| 75 | } else { | ||
| 76 | ConfigurationShared::SetPerGameSetting(ui->use_disk_shader_cache, | ||
| 77 | &Settings::values.use_disk_shader_cache); | ||
| 78 | ConfigurationShared::SetPerGameSetting(ui->use_asynchronous_gpu_emulation, | ||
| 79 | &Settings::values.use_asynchronous_gpu_emulation); | ||
| 80 | |||
| 81 | ConfigurationShared::SetPerGameSetting(ui->api, &Settings::values.renderer_backend); | ||
| 82 | ConfigurationShared::SetPerGameSetting(ui->aspect_ratio_combobox, | ||
| 83 | &Settings::values.aspect_ratio); | ||
| 84 | |||
| 85 | ui->bg_combobox->setCurrentIndex(Settings::values.bg_red.UsingGlobal() ? 0 : 1); | ||
| 86 | ui->bg_button->setEnabled(!Settings::values.bg_red.UsingGlobal()); | ||
| 87 | } | ||
| 88 | |||
| 89 | UpdateBackgroundColorButton(QColor::fromRgbF(Settings::values.bg_red.GetValue(), | ||
| 90 | Settings::values.bg_green.GetValue(), | ||
| 91 | Settings::values.bg_blue.GetValue())); | ||
| 68 | UpdateDeviceComboBox(); | 92 | UpdateDeviceComboBox(); |
| 69 | } | 93 | } |
| 70 | 94 | ||
| 71 | void ConfigureGraphics::ApplyConfiguration() { | 95 | void ConfigureGraphics::ApplyConfiguration() { |
| 72 | Settings::values.renderer_backend = GetCurrentGraphicsBackend(); | 96 | if (Settings::configuring_global) { |
| 73 | Settings::values.vulkan_device = vulkan_device; | 97 | // Guard if during game and set to game-specific value |
| 74 | Settings::values.aspect_ratio = ui->aspect_ratio_combobox->currentIndex(); | 98 | if (Settings::values.renderer_backend.UsingGlobal()) { |
| 75 | Settings::values.use_disk_shader_cache = ui->use_disk_shader_cache->isChecked(); | 99 | Settings::values.renderer_backend.SetValue(GetCurrentGraphicsBackend()); |
| 76 | Settings::values.use_asynchronous_gpu_emulation = | 100 | } |
| 77 | ui->use_asynchronous_gpu_emulation->isChecked(); | 101 | if (Settings::values.vulkan_device.UsingGlobal()) { |
| 78 | Settings::values.bg_red = static_cast<float>(bg_color.redF()); | 102 | Settings::values.vulkan_device.SetValue(vulkan_device); |
| 79 | Settings::values.bg_green = static_cast<float>(bg_color.greenF()); | 103 | } |
| 80 | Settings::values.bg_blue = static_cast<float>(bg_color.blueF()); | 104 | if (Settings::values.aspect_ratio.UsingGlobal()) { |
| 105 | Settings::values.aspect_ratio.SetValue(ui->aspect_ratio_combobox->currentIndex()); | ||
| 106 | } | ||
| 107 | if (Settings::values.use_disk_shader_cache.UsingGlobal()) { | ||
| 108 | Settings::values.use_disk_shader_cache.SetValue(ui->use_disk_shader_cache->isChecked()); | ||
| 109 | } | ||
| 110 | if (Settings::values.use_asynchronous_gpu_emulation.UsingGlobal()) { | ||
| 111 | Settings::values.use_asynchronous_gpu_emulation.SetValue( | ||
| 112 | ui->use_asynchronous_gpu_emulation->isChecked()); | ||
| 113 | } | ||
| 114 | if (Settings::values.bg_red.UsingGlobal()) { | ||
| 115 | Settings::values.bg_red.SetValue(static_cast<float>(bg_color.redF())); | ||
| 116 | Settings::values.bg_green.SetValue(static_cast<float>(bg_color.greenF())); | ||
| 117 | Settings::values.bg_blue.SetValue(static_cast<float>(bg_color.blueF())); | ||
| 118 | } | ||
| 119 | } else { | ||
| 120 | if (ui->api->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) { | ||
| 121 | Settings::values.renderer_backend.SetGlobal(true); | ||
| 122 | Settings::values.vulkan_device.SetGlobal(true); | ||
| 123 | } else { | ||
| 124 | Settings::values.renderer_backend.SetGlobal(false); | ||
| 125 | Settings::values.renderer_backend.SetValue(GetCurrentGraphicsBackend()); | ||
| 126 | if (GetCurrentGraphicsBackend() == Settings::RendererBackend::Vulkan) { | ||
| 127 | Settings::values.vulkan_device.SetGlobal(false); | ||
| 128 | Settings::values.vulkan_device.SetValue(vulkan_device); | ||
| 129 | } else { | ||
| 130 | Settings::values.vulkan_device.SetGlobal(true); | ||
| 131 | } | ||
| 132 | } | ||
| 133 | |||
| 134 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.aspect_ratio, | ||
| 135 | ui->aspect_ratio_combobox); | ||
| 136 | |||
| 137 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_disk_shader_cache, | ||
| 138 | ui->use_disk_shader_cache); | ||
| 139 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_asynchronous_gpu_emulation, | ||
| 140 | ui->use_asynchronous_gpu_emulation); | ||
| 141 | |||
| 142 | if (ui->bg_combobox->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) { | ||
| 143 | Settings::values.bg_red.SetGlobal(true); | ||
| 144 | Settings::values.bg_green.SetGlobal(true); | ||
| 145 | Settings::values.bg_blue.SetGlobal(true); | ||
| 146 | } else { | ||
| 147 | Settings::values.bg_red.SetGlobal(false); | ||
| 148 | Settings::values.bg_green.SetGlobal(false); | ||
| 149 | Settings::values.bg_blue.SetGlobal(false); | ||
| 150 | Settings::values.bg_red.SetValue(static_cast<float>(bg_color.redF())); | ||
| 151 | Settings::values.bg_green.SetValue(static_cast<float>(bg_color.greenF())); | ||
| 152 | Settings::values.bg_blue.SetValue(static_cast<float>(bg_color.blueF())); | ||
| 153 | } | ||
| 154 | } | ||
| 81 | } | 155 | } |
| 82 | 156 | ||
| 83 | void ConfigureGraphics::changeEvent(QEvent* event) { | 157 | void ConfigureGraphics::changeEvent(QEvent* event) { |
| @@ -106,6 +180,11 @@ void ConfigureGraphics::UpdateDeviceComboBox() { | |||
| 106 | ui->device->clear(); | 180 | ui->device->clear(); |
| 107 | 181 | ||
| 108 | bool enabled = false; | 182 | bool enabled = false; |
| 183 | |||
| 184 | if (!Settings::configuring_global && | ||
| 185 | ui->api->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) { | ||
| 186 | vulkan_device = Settings::values.vulkan_device.GetValue(); | ||
| 187 | } | ||
| 109 | switch (GetCurrentGraphicsBackend()) { | 188 | switch (GetCurrentGraphicsBackend()) { |
| 110 | case Settings::RendererBackend::OpenGL: | 189 | case Settings::RendererBackend::OpenGL: |
| 111 | ui->device->addItem(tr("OpenGL Graphics Device")); | 190 | ui->device->addItem(tr("OpenGL Graphics Device")); |
| @@ -119,6 +198,9 @@ void ConfigureGraphics::UpdateDeviceComboBox() { | |||
| 119 | enabled = !vulkan_devices.empty(); | 198 | enabled = !vulkan_devices.empty(); |
| 120 | break; | 199 | break; |
| 121 | } | 200 | } |
| 201 | // If in per-game config and use global is selected, don't enable. | ||
| 202 | enabled &= !(!Settings::configuring_global && | ||
| 203 | ui->api->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX); | ||
| 122 | ui->device->setEnabled(enabled && !Core::System::GetInstance().IsPoweredOn()); | 204 | ui->device->setEnabled(enabled && !Core::System::GetInstance().IsPoweredOn()); |
| 123 | } | 205 | } |
| 124 | 206 | ||
| @@ -132,5 +214,37 @@ void ConfigureGraphics::RetrieveVulkanDevices() { | |||
| 132 | } | 214 | } |
| 133 | 215 | ||
| 134 | Settings::RendererBackend ConfigureGraphics::GetCurrentGraphicsBackend() const { | 216 | Settings::RendererBackend ConfigureGraphics::GetCurrentGraphicsBackend() const { |
| 135 | return static_cast<Settings::RendererBackend>(ui->api->currentIndex()); | 217 | if (Settings::configuring_global) { |
| 218 | return static_cast<Settings::RendererBackend>(ui->api->currentIndex()); | ||
| 219 | } | ||
| 220 | |||
| 221 | if (ui->api->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) { | ||
| 222 | Settings::values.renderer_backend.SetGlobal(true); | ||
| 223 | return Settings::values.renderer_backend.GetValue(); | ||
| 224 | } | ||
| 225 | Settings::values.renderer_backend.SetGlobal(false); | ||
| 226 | return static_cast<Settings::RendererBackend>(ui->api->currentIndex() - | ||
| 227 | ConfigurationShared::USE_GLOBAL_OFFSET); | ||
| 228 | } | ||
| 229 | |||
| 230 | void ConfigureGraphics::SetupPerGameUI() { | ||
| 231 | if (Settings::configuring_global) { | ||
| 232 | ui->api->setEnabled(Settings::values.renderer_backend.UsingGlobal()); | ||
| 233 | ui->device->setEnabled(Settings::values.renderer_backend.UsingGlobal()); | ||
| 234 | ui->aspect_ratio_combobox->setEnabled(Settings::values.aspect_ratio.UsingGlobal()); | ||
| 235 | ui->use_asynchronous_gpu_emulation->setEnabled( | ||
| 236 | Settings::values.use_asynchronous_gpu_emulation.UsingGlobal()); | ||
| 237 | ui->use_disk_shader_cache->setEnabled(Settings::values.use_disk_shader_cache.UsingGlobal()); | ||
| 238 | ui->bg_button->setEnabled(Settings::values.bg_red.UsingGlobal()); | ||
| 239 | |||
| 240 | return; | ||
| 241 | } | ||
| 242 | |||
| 243 | connect(ui->bg_combobox, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), this, | ||
| 244 | [this](int index) { ui->bg_button->setEnabled(index == 1); }); | ||
| 245 | |||
| 246 | ui->use_disk_shader_cache->setTristate(true); | ||
| 247 | ui->use_asynchronous_gpu_emulation->setTristate(true); | ||
| 248 | ConfigurationShared::InsertGlobalItem(ui->aspect_ratio_combobox); | ||
| 249 | ConfigurationShared::InsertGlobalItem(ui->api); | ||
| 136 | } | 250 | } |
diff --git a/src/yuzu/configuration/configure_graphics.h b/src/yuzu/configuration/configure_graphics.h index 7e0596d9c..24f01c739 100644 --- a/src/yuzu/configuration/configure_graphics.h +++ b/src/yuzu/configuration/configure_graphics.h | |||
| @@ -35,6 +35,8 @@ private: | |||
| 35 | 35 | ||
| 36 | void RetrieveVulkanDevices(); | 36 | void RetrieveVulkanDevices(); |
| 37 | 37 | ||
| 38 | void SetupPerGameUI(); | ||
| 39 | |||
| 38 | Settings::RendererBackend GetCurrentGraphicsBackend() const; | 40 | Settings::RendererBackend GetCurrentGraphicsBackend() const; |
| 39 | 41 | ||
| 40 | std::unique_ptr<Ui::ConfigureGraphics> ui; | 42 | std::unique_ptr<Ui::ConfigureGraphics> ui; |
diff --git a/src/yuzu/configuration/configure_graphics.ui b/src/yuzu/configuration/configure_graphics.ui index 6e75447a5..62418fc14 100644 --- a/src/yuzu/configuration/configure_graphics.ui +++ b/src/yuzu/configuration/configure_graphics.ui | |||
| @@ -122,6 +122,29 @@ | |||
| 122 | <item> | 122 | <item> |
| 123 | <layout class="QHBoxLayout" name="horizontalLayout_3"> | 123 | <layout class="QHBoxLayout" name="horizontalLayout_3"> |
| 124 | <item> | 124 | <item> |
| 125 | <widget class="QComboBox" name="bg_combobox"> | ||
| 126 | <property name="currentText"> | ||
| 127 | <string>Use global background color</string> | ||
| 128 | </property> | ||
| 129 | <property name="currentIndex"> | ||
| 130 | <number>0</number> | ||
| 131 | </property> | ||
| 132 | <property name="maxVisibleItems"> | ||
| 133 | <number>10</number> | ||
| 134 | </property> | ||
| 135 | <item> | ||
| 136 | <property name="text"> | ||
| 137 | <string>Use global background color</string> | ||
| 138 | </property> | ||
| 139 | </item> | ||
| 140 | <item> | ||
| 141 | <property name="text"> | ||
| 142 | <string>Set background color:</string> | ||
| 143 | </property> | ||
| 144 | </item> | ||
| 145 | </widget> | ||
| 146 | </item> | ||
| 147 | <item> | ||
| 125 | <widget class="QLabel" name="bg_label"> | 148 | <widget class="QLabel" name="bg_label"> |
| 126 | <property name="text"> | 149 | <property name="text"> |
| 127 | <string>Background Color:</string> | 150 | <string>Background Color:</string> |
| @@ -129,6 +152,19 @@ | |||
| 129 | </widget> | 152 | </widget> |
| 130 | </item> | 153 | </item> |
| 131 | <item> | 154 | <item> |
| 155 | <spacer name="horizontalSpacer"> | ||
| 156 | <property name="orientation"> | ||
| 157 | <enum>Qt::Horizontal</enum> | ||
| 158 | </property> | ||
| 159 | <property name="sizeHint" stdset="0"> | ||
| 160 | <size> | ||
| 161 | <width>40</width> | ||
| 162 | <height>20</height> | ||
| 163 | </size> | ||
| 164 | </property> | ||
| 165 | </spacer> | ||
| 166 | </item> | ||
| 167 | <item> | ||
| 132 | <widget class="QPushButton" name="bg_button"> | 168 | <widget class="QPushButton" name="bg_button"> |
| 133 | <property name="maximumSize"> | 169 | <property name="maximumSize"> |
| 134 | <size> | 170 | <size> |
diff --git a/src/yuzu/configuration/configure_graphics_advanced.cpp b/src/yuzu/configuration/configure_graphics_advanced.cpp index be5006ad3..7c0fa7ec5 100644 --- a/src/yuzu/configuration/configure_graphics_advanced.cpp +++ b/src/yuzu/configuration/configure_graphics_advanced.cpp | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | #include "core/core.h" | 5 | #include "core/core.h" |
| 6 | #include "core/settings.h" | 6 | #include "core/settings.h" |
| 7 | #include "ui_configure_graphics_advanced.h" | 7 | #include "ui_configure_graphics_advanced.h" |
| 8 | #include "yuzu/configuration/configuration_shared.h" | ||
| 8 | #include "yuzu/configuration/configure_graphics_advanced.h" | 9 | #include "yuzu/configuration/configure_graphics_advanced.h" |
| 9 | 10 | ||
| 10 | ConfigureGraphicsAdvanced::ConfigureGraphicsAdvanced(QWidget* parent) | 11 | ConfigureGraphicsAdvanced::ConfigureGraphicsAdvanced(QWidget* parent) |
| @@ -12,6 +13,8 @@ ConfigureGraphicsAdvanced::ConfigureGraphicsAdvanced(QWidget* parent) | |||
| 12 | 13 | ||
| 13 | ui->setupUi(this); | 14 | ui->setupUi(this); |
| 14 | 15 | ||
| 16 | SetupPerGameUI(); | ||
| 17 | |||
| 15 | SetConfiguration(); | 18 | SetConfiguration(); |
| 16 | } | 19 | } |
| 17 | 20 | ||
| @@ -19,26 +22,81 @@ ConfigureGraphicsAdvanced::~ConfigureGraphicsAdvanced() = default; | |||
| 19 | 22 | ||
| 20 | void ConfigureGraphicsAdvanced::SetConfiguration() { | 23 | void ConfigureGraphicsAdvanced::SetConfiguration() { |
| 21 | const bool runtime_lock = !Core::System::GetInstance().IsPoweredOn(); | 24 | const bool runtime_lock = !Core::System::GetInstance().IsPoweredOn(); |
| 22 | ui->gpu_accuracy->setCurrentIndex(static_cast<int>(Settings::values.gpu_accuracy)); | ||
| 23 | ui->use_vsync->setEnabled(runtime_lock); | 25 | ui->use_vsync->setEnabled(runtime_lock); |
| 24 | ui->use_vsync->setChecked(Settings::values.use_vsync); | ||
| 25 | ui->use_assembly_shaders->setEnabled(runtime_lock); | 26 | ui->use_assembly_shaders->setEnabled(runtime_lock); |
| 26 | ui->use_assembly_shaders->setChecked(Settings::values.use_assembly_shaders); | ||
| 27 | ui->use_fast_gpu_time->setChecked(Settings::values.use_fast_gpu_time); | ||
| 28 | ui->force_30fps_mode->setEnabled(runtime_lock); | 27 | ui->force_30fps_mode->setEnabled(runtime_lock); |
| 29 | ui->force_30fps_mode->setChecked(Settings::values.force_30fps_mode); | ||
| 30 | ui->anisotropic_filtering_combobox->setEnabled(runtime_lock); | 28 | ui->anisotropic_filtering_combobox->setEnabled(runtime_lock); |
| 31 | ui->anisotropic_filtering_combobox->setCurrentIndex(Settings::values.max_anisotropy); | 29 | |
| 30 | if (Settings::configuring_global) { | ||
| 31 | ui->gpu_accuracy->setCurrentIndex( | ||
| 32 | static_cast<int>(Settings::values.gpu_accuracy.GetValue())); | ||
| 33 | ui->use_vsync->setChecked(Settings::values.use_vsync.GetValue()); | ||
| 34 | ui->use_assembly_shaders->setChecked(Settings::values.use_assembly_shaders.GetValue()); | ||
| 35 | ui->use_fast_gpu_time->setChecked(Settings::values.use_fast_gpu_time.GetValue()); | ||
| 36 | ui->force_30fps_mode->setChecked(Settings::values.force_30fps_mode.GetValue()); | ||
| 37 | ui->anisotropic_filtering_combobox->setCurrentIndex( | ||
| 38 | Settings::values.max_anisotropy.GetValue()); | ||
| 39 | } else { | ||
| 40 | ConfigurationShared::SetPerGameSetting(ui->gpu_accuracy, &Settings::values.gpu_accuracy); | ||
| 41 | ConfigurationShared::SetPerGameSetting(ui->use_vsync, &Settings::values.use_vsync); | ||
| 42 | ConfigurationShared::SetPerGameSetting(ui->use_assembly_shaders, | ||
| 43 | &Settings::values.use_assembly_shaders); | ||
| 44 | ConfigurationShared::SetPerGameSetting(ui->use_fast_gpu_time, | ||
| 45 | &Settings::values.use_fast_gpu_time); | ||
| 46 | ConfigurationShared::SetPerGameSetting(ui->force_30fps_mode, | ||
| 47 | &Settings::values.force_30fps_mode); | ||
| 48 | ConfigurationShared::SetPerGameSetting(ui->anisotropic_filtering_combobox, | ||
| 49 | &Settings::values.max_anisotropy); | ||
| 50 | } | ||
| 32 | } | 51 | } |
| 33 | 52 | ||
| 34 | void ConfigureGraphicsAdvanced::ApplyConfiguration() { | 53 | void ConfigureGraphicsAdvanced::ApplyConfiguration() { |
| 35 | auto gpu_accuracy = static_cast<Settings::GPUAccuracy>(ui->gpu_accuracy->currentIndex()); | 54 | // Subtract 2 if configuring per-game (separator and "use global configuration" take 2 slots) |
| 36 | Settings::values.gpu_accuracy = gpu_accuracy; | 55 | const auto gpu_accuracy = static_cast<Settings::GPUAccuracy>( |
| 37 | Settings::values.use_vsync = ui->use_vsync->isChecked(); | 56 | ui->gpu_accuracy->currentIndex() - |
| 38 | Settings::values.use_assembly_shaders = ui->use_assembly_shaders->isChecked(); | 57 | ((Settings::configuring_global) ? 0 : ConfigurationShared::USE_GLOBAL_OFFSET)); |
| 39 | Settings::values.use_fast_gpu_time = ui->use_fast_gpu_time->isChecked(); | 58 | |
| 40 | Settings::values.force_30fps_mode = ui->force_30fps_mode->isChecked(); | 59 | if (Settings::configuring_global) { |
| 41 | Settings::values.max_anisotropy = ui->anisotropic_filtering_combobox->currentIndex(); | 60 | // Must guard in case of a during-game configuration when set to be game-specific. |
| 61 | if (Settings::values.gpu_accuracy.UsingGlobal()) { | ||
| 62 | Settings::values.gpu_accuracy.SetValue(gpu_accuracy); | ||
| 63 | } | ||
| 64 | if (Settings::values.use_vsync.UsingGlobal()) { | ||
| 65 | Settings::values.use_vsync.SetValue(ui->use_vsync->isChecked()); | ||
| 66 | } | ||
| 67 | if (Settings::values.use_assembly_shaders.UsingGlobal()) { | ||
| 68 | Settings::values.use_assembly_shaders.SetValue(ui->use_assembly_shaders->isChecked()); | ||
| 69 | } | ||
| 70 | if (Settings::values.use_fast_gpu_time.UsingGlobal()) { | ||
| 71 | Settings::values.use_fast_gpu_time.SetValue(ui->use_fast_gpu_time->isChecked()); | ||
| 72 | } | ||
| 73 | if (Settings::values.force_30fps_mode.UsingGlobal()) { | ||
| 74 | Settings::values.force_30fps_mode.SetValue(ui->force_30fps_mode->isChecked()); | ||
| 75 | } | ||
| 76 | if (Settings::values.max_anisotropy.UsingGlobal()) { | ||
| 77 | Settings::values.max_anisotropy.SetValue( | ||
| 78 | ui->anisotropic_filtering_combobox->currentIndex()); | ||
| 79 | } | ||
| 80 | } else { | ||
| 81 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.max_anisotropy, | ||
| 82 | ui->anisotropic_filtering_combobox); | ||
| 83 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_vsync, ui->use_vsync); | ||
| 84 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_assembly_shaders, | ||
| 85 | ui->use_assembly_shaders); | ||
| 86 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_fast_gpu_time, | ||
| 87 | ui->use_fast_gpu_time); | ||
| 88 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.force_30fps_mode, | ||
| 89 | ui->force_30fps_mode); | ||
| 90 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.max_anisotropy, | ||
| 91 | ui->anisotropic_filtering_combobox); | ||
| 92 | |||
| 93 | if (ui->gpu_accuracy->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) { | ||
| 94 | Settings::values.gpu_accuracy.SetGlobal(true); | ||
| 95 | } else { | ||
| 96 | Settings::values.gpu_accuracy.SetGlobal(false); | ||
| 97 | Settings::values.gpu_accuracy.SetValue(gpu_accuracy); | ||
| 98 | } | ||
| 99 | } | ||
| 42 | } | 100 | } |
| 43 | 101 | ||
| 44 | void ConfigureGraphicsAdvanced::changeEvent(QEvent* event) { | 102 | void ConfigureGraphicsAdvanced::changeEvent(QEvent* event) { |
| @@ -52,3 +110,25 @@ void ConfigureGraphicsAdvanced::changeEvent(QEvent* event) { | |||
| 52 | void ConfigureGraphicsAdvanced::RetranslateUI() { | 110 | void ConfigureGraphicsAdvanced::RetranslateUI() { |
| 53 | ui->retranslateUi(this); | 111 | ui->retranslateUi(this); |
| 54 | } | 112 | } |
| 113 | |||
| 114 | void ConfigureGraphicsAdvanced::SetupPerGameUI() { | ||
| 115 | // Disable if not global (only happens during game) | ||
| 116 | if (Settings::configuring_global) { | ||
| 117 | ui->gpu_accuracy->setEnabled(Settings::values.gpu_accuracy.UsingGlobal()); | ||
| 118 | ui->use_vsync->setEnabled(Settings::values.use_vsync.UsingGlobal()); | ||
| 119 | ui->use_assembly_shaders->setEnabled(Settings::values.use_assembly_shaders.UsingGlobal()); | ||
| 120 | ui->use_fast_gpu_time->setEnabled(Settings::values.use_fast_gpu_time.UsingGlobal()); | ||
| 121 | ui->force_30fps_mode->setEnabled(Settings::values.force_30fps_mode.UsingGlobal()); | ||
| 122 | ui->anisotropic_filtering_combobox->setEnabled( | ||
| 123 | Settings::values.max_anisotropy.UsingGlobal()); | ||
| 124 | |||
| 125 | return; | ||
| 126 | } | ||
| 127 | |||
| 128 | ConfigurationShared::InsertGlobalItem(ui->gpu_accuracy); | ||
| 129 | ui->use_vsync->setTristate(true); | ||
| 130 | ui->use_assembly_shaders->setTristate(true); | ||
| 131 | ui->use_fast_gpu_time->setTristate(true); | ||
| 132 | ui->force_30fps_mode->setTristate(true); | ||
| 133 | ConfigurationShared::InsertGlobalItem(ui->anisotropic_filtering_combobox); | ||
| 134 | } | ||
diff --git a/src/yuzu/configuration/configure_graphics_advanced.h b/src/yuzu/configuration/configure_graphics_advanced.h index bbc9d4355..c043588ff 100644 --- a/src/yuzu/configuration/configure_graphics_advanced.h +++ b/src/yuzu/configuration/configure_graphics_advanced.h | |||
| @@ -26,5 +26,7 @@ private: | |||
| 26 | 26 | ||
| 27 | void SetConfiguration(); | 27 | void SetConfiguration(); |
| 28 | 28 | ||
| 29 | void SetupPerGameUI(); | ||
| 30 | |||
| 29 | std::unique_ptr<Ui::ConfigureGraphicsAdvanced> ui; | 31 | std::unique_ptr<Ui::ConfigureGraphicsAdvanced> ui; |
| 30 | }; | 32 | }; |
diff --git a/src/yuzu/configuration/configure_per_game.cpp b/src/yuzu/configuration/configure_per_game.cpp new file mode 100644 index 000000000..1e49f0787 --- /dev/null +++ b/src/yuzu/configuration/configure_per_game.cpp | |||
| @@ -0,0 +1,140 @@ | |||
| 1 | // Copyright 2020 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <algorithm> | ||
| 6 | #include <memory> | ||
| 7 | #include <utility> | ||
| 8 | |||
| 9 | #include <QCheckBox> | ||
| 10 | #include <QHeaderView> | ||
| 11 | #include <QMenu> | ||
| 12 | #include <QStandardItemModel> | ||
| 13 | #include <QString> | ||
| 14 | #include <QTimer> | ||
| 15 | #include <QTreeView> | ||
| 16 | |||
| 17 | #include "common/common_paths.h" | ||
| 18 | #include "common/file_util.h" | ||
| 19 | #include "core/file_sys/control_metadata.h" | ||
| 20 | #include "core/file_sys/patch_manager.h" | ||
| 21 | #include "core/file_sys/xts_archive.h" | ||
| 22 | #include "core/loader/loader.h" | ||
| 23 | #include "ui_configure_per_game.h" | ||
| 24 | #include "yuzu/configuration/config.h" | ||
| 25 | #include "yuzu/configuration/configure_input.h" | ||
| 26 | #include "yuzu/configuration/configure_per_game.h" | ||
| 27 | #include "yuzu/uisettings.h" | ||
| 28 | #include "yuzu/util/util.h" | ||
| 29 | |||
| 30 | ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id) | ||
| 31 | : QDialog(parent), ui(std::make_unique<Ui::ConfigurePerGame>()), title_id(title_id) { | ||
| 32 | game_config = std::make_unique<Config>(fmt::format("{:016X}.ini", title_id), false); | ||
| 33 | |||
| 34 | Settings::configuring_global = false; | ||
| 35 | |||
| 36 | ui->setupUi(this); | ||
| 37 | setFocusPolicy(Qt::ClickFocus); | ||
| 38 | setWindowTitle(tr("Properties")); | ||
| 39 | |||
| 40 | ui->addonsTab->SetTitleId(title_id); | ||
| 41 | |||
| 42 | scene = new QGraphicsScene; | ||
| 43 | ui->icon_view->setScene(scene); | ||
| 44 | |||
| 45 | LoadConfiguration(); | ||
| 46 | } | ||
| 47 | |||
| 48 | ConfigurePerGame::~ConfigurePerGame() = default; | ||
| 49 | |||
| 50 | void ConfigurePerGame::ApplyConfiguration() { | ||
| 51 | ui->addonsTab->ApplyConfiguration(); | ||
| 52 | ui->generalTab->ApplyConfiguration(); | ||
| 53 | ui->systemTab->ApplyConfiguration(); | ||
| 54 | ui->graphicsTab->ApplyConfiguration(); | ||
| 55 | ui->graphicsAdvancedTab->ApplyConfiguration(); | ||
| 56 | ui->audioTab->ApplyConfiguration(); | ||
| 57 | |||
| 58 | Settings::Apply(); | ||
| 59 | Settings::LogSettings(); | ||
| 60 | |||
| 61 | game_config->Save(); | ||
| 62 | } | ||
| 63 | |||
| 64 | void ConfigurePerGame::changeEvent(QEvent* event) { | ||
| 65 | if (event->type() == QEvent::LanguageChange) { | ||
| 66 | RetranslateUI(); | ||
| 67 | } | ||
| 68 | |||
| 69 | QDialog::changeEvent(event); | ||
| 70 | } | ||
| 71 | |||
| 72 | void ConfigurePerGame::RetranslateUI() { | ||
| 73 | ui->retranslateUi(this); | ||
| 74 | } | ||
| 75 | |||
| 76 | void ConfigurePerGame::LoadFromFile(FileSys::VirtualFile file) { | ||
| 77 | this->file = std::move(file); | ||
| 78 | LoadConfiguration(); | ||
| 79 | } | ||
| 80 | |||
| 81 | void ConfigurePerGame::LoadConfiguration() { | ||
| 82 | if (file == nullptr) { | ||
| 83 | return; | ||
| 84 | } | ||
| 85 | |||
| 86 | ui->addonsTab->LoadFromFile(file); | ||
| 87 | |||
| 88 | ui->display_title_id->setText( | ||
| 89 | QStringLiteral("%1").arg(title_id, 16, 16, QLatin1Char{'0'}).toUpper()); | ||
| 90 | |||
| 91 | FileSys::PatchManager pm{title_id}; | ||
| 92 | const auto control = pm.GetControlMetadata(); | ||
| 93 | const auto loader = Loader::GetLoader(file); | ||
| 94 | |||
| 95 | if (control.first != nullptr) { | ||
| 96 | ui->display_version->setText(QString::fromStdString(control.first->GetVersionString())); | ||
| 97 | ui->display_name->setText(QString::fromStdString(control.first->GetApplicationName())); | ||
| 98 | ui->display_developer->setText(QString::fromStdString(control.first->GetDeveloperName())); | ||
| 99 | } else { | ||
| 100 | std::string title; | ||
| 101 | if (loader->ReadTitle(title) == Loader::ResultStatus::Success) | ||
| 102 | ui->display_name->setText(QString::fromStdString(title)); | ||
| 103 | |||
| 104 | FileSys::NACP nacp; | ||
| 105 | if (loader->ReadControlData(nacp) == Loader::ResultStatus::Success) | ||
| 106 | ui->display_developer->setText(QString::fromStdString(nacp.GetDeveloperName())); | ||
| 107 | |||
| 108 | ui->display_version->setText(QStringLiteral("1.0.0")); | ||
| 109 | } | ||
| 110 | |||
| 111 | if (control.second != nullptr) { | ||
| 112 | scene->clear(); | ||
| 113 | |||
| 114 | QPixmap map; | ||
| 115 | const auto bytes = control.second->ReadAllBytes(); | ||
| 116 | map.loadFromData(bytes.data(), static_cast<u32>(bytes.size())); | ||
| 117 | |||
| 118 | scene->addPixmap(map.scaled(ui->icon_view->width(), ui->icon_view->height(), | ||
| 119 | Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); | ||
| 120 | } else { | ||
| 121 | std::vector<u8> bytes; | ||
| 122 | if (loader->ReadIcon(bytes) == Loader::ResultStatus::Success) { | ||
| 123 | scene->clear(); | ||
| 124 | |||
| 125 | QPixmap map; | ||
| 126 | map.loadFromData(bytes.data(), static_cast<u32>(bytes.size())); | ||
| 127 | |||
| 128 | scene->addPixmap(map.scaled(ui->icon_view->width(), ui->icon_view->height(), | ||
| 129 | Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); | ||
| 130 | } | ||
| 131 | } | ||
| 132 | |||
| 133 | ui->display_filename->setText(QString::fromStdString(file->GetName())); | ||
| 134 | |||
| 135 | ui->display_format->setText( | ||
| 136 | QString::fromStdString(Loader::GetFileTypeString(loader->GetFileType()))); | ||
| 137 | |||
| 138 | const auto valueText = ReadableByteSize(file->GetSize()); | ||
| 139 | ui->display_size->setText(valueText); | ||
| 140 | } | ||
diff --git a/src/yuzu/configuration/configure_per_game.h b/src/yuzu/configuration/configure_per_game.h new file mode 100644 index 000000000..5f9a08cef --- /dev/null +++ b/src/yuzu/configuration/configure_per_game.h | |||
| @@ -0,0 +1,51 @@ | |||
| 1 | // Copyright 2020 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <memory> | ||
| 8 | #include <vector> | ||
| 9 | |||
| 10 | #include <QDialog> | ||
| 11 | #include <QList> | ||
| 12 | |||
| 13 | #include "core/file_sys/vfs_types.h" | ||
| 14 | #include "yuzu/configuration/config.h" | ||
| 15 | |||
| 16 | class QGraphicsScene; | ||
| 17 | class QStandardItem; | ||
| 18 | class QStandardItemModel; | ||
| 19 | class QTreeView; | ||
| 20 | class QVBoxLayout; | ||
| 21 | |||
| 22 | namespace Ui { | ||
| 23 | class ConfigurePerGame; | ||
| 24 | } | ||
| 25 | |||
| 26 | class ConfigurePerGame : public QDialog { | ||
| 27 | Q_OBJECT | ||
| 28 | |||
| 29 | public: | ||
| 30 | explicit ConfigurePerGame(QWidget* parent, u64 title_id); | ||
| 31 | ~ConfigurePerGame() override; | ||
| 32 | |||
| 33 | /// Save all button configurations to settings file | ||
| 34 | void ApplyConfiguration(); | ||
| 35 | |||
| 36 | void LoadFromFile(FileSys::VirtualFile file); | ||
| 37 | |||
| 38 | private: | ||
| 39 | void changeEvent(QEvent* event) override; | ||
| 40 | void RetranslateUI(); | ||
| 41 | |||
| 42 | void LoadConfiguration(); | ||
| 43 | |||
| 44 | std::unique_ptr<Ui::ConfigurePerGame> ui; | ||
| 45 | FileSys::VirtualFile file; | ||
| 46 | u64 title_id; | ||
| 47 | |||
| 48 | QGraphicsScene* scene; | ||
| 49 | |||
| 50 | std::unique_ptr<Config> game_config; | ||
| 51 | }; | ||
diff --git a/src/yuzu/configuration/configure_per_game.ui b/src/yuzu/configuration/configure_per_game.ui new file mode 100644 index 000000000..d2057c4ab --- /dev/null +++ b/src/yuzu/configuration/configure_per_game.ui | |||
| @@ -0,0 +1,350 @@ | |||
| 1 | <?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | <ui version="4.0"> | ||
| 3 | <class>ConfigurePerGame</class> | ||
| 4 | <widget class="QDialog" name="ConfigurePerGame"> | ||
| 5 | <property name="geometry"> | ||
| 6 | <rect> | ||
| 7 | <x>0</x> | ||
| 8 | <y>0</y> | ||
| 9 | <width>800</width> | ||
| 10 | <height>600</height> | ||
| 11 | </rect> | ||
| 12 | </property> | ||
| 13 | <property name="windowTitle"> | ||
| 14 | <string>Dialog</string> | ||
| 15 | </property> | ||
| 16 | <layout class="QVBoxLayout" name="verticalLayout_3"> | ||
| 17 | <item> | ||
| 18 | <layout class="QHBoxLayout" name="horizontalLayout"> | ||
| 19 | <item> | ||
| 20 | <widget class="QGroupBox" name="groupBox"> | ||
| 21 | <property name="sizePolicy"> | ||
| 22 | <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> | ||
| 23 | <horstretch>0</horstretch> | ||
| 24 | <verstretch>0</verstretch> | ||
| 25 | </sizepolicy> | ||
| 26 | </property> | ||
| 27 | <property name="title"> | ||
| 28 | <string>Info</string> | ||
| 29 | </property> | ||
| 30 | <layout class="QVBoxLayout" name="verticalLayout"> | ||
| 31 | <item alignment="Qt::AlignHCenter"> | ||
| 32 | <widget class="QGraphicsView" name="icon_view"> | ||
| 33 | <property name="sizePolicy"> | ||
| 34 | <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> | ||
| 35 | <horstretch>0</horstretch> | ||
| 36 | <verstretch>0</verstretch> | ||
| 37 | </sizepolicy> | ||
| 38 | </property> | ||
| 39 | <property name="minimumSize"> | ||
| 40 | <size> | ||
| 41 | <width>256</width> | ||
| 42 | <height>256</height> | ||
| 43 | </size> | ||
| 44 | </property> | ||
| 45 | <property name="maximumSize"> | ||
| 46 | <size> | ||
| 47 | <width>256</width> | ||
| 48 | <height>256</height> | ||
| 49 | </size> | ||
| 50 | </property> | ||
| 51 | <property name="verticalScrollBarPolicy"> | ||
| 52 | <enum>Qt::ScrollBarAlwaysOff</enum> | ||
| 53 | </property> | ||
| 54 | <property name="horizontalScrollBarPolicy"> | ||
| 55 | <enum>Qt::ScrollBarAlwaysOff</enum> | ||
| 56 | </property> | ||
| 57 | <property name="interactive"> | ||
| 58 | <bool>false</bool> | ||
| 59 | </property> | ||
| 60 | </widget> | ||
| 61 | </item> | ||
| 62 | <item> | ||
| 63 | <layout class="QGridLayout" name="gridLayout_2"> | ||
| 64 | <item row="6" column="1"> | ||
| 65 | <widget class="QLineEdit" name="display_size"> | ||
| 66 | <property name="enabled"> | ||
| 67 | <bool>true</bool> | ||
| 68 | </property> | ||
| 69 | <property name="readOnly"> | ||
| 70 | <bool>true</bool> | ||
| 71 | </property> | ||
| 72 | </widget> | ||
| 73 | </item> | ||
| 74 | <item row="3" column="1"> | ||
| 75 | <widget class="QLineEdit" name="display_version"> | ||
| 76 | <property name="enabled"> | ||
| 77 | <bool>true</bool> | ||
| 78 | </property> | ||
| 79 | <property name="readOnly"> | ||
| 80 | <bool>true</bool> | ||
| 81 | </property> | ||
| 82 | </widget> | ||
| 83 | </item> | ||
| 84 | <item row="1" column="0"> | ||
| 85 | <widget class="QLabel" name="label"> | ||
| 86 | <property name="text"> | ||
| 87 | <string>Name</string> | ||
| 88 | </property> | ||
| 89 | </widget> | ||
| 90 | </item> | ||
| 91 | <item row="4" column="0"> | ||
| 92 | <widget class="QLabel" name="label_4"> | ||
| 93 | <property name="text"> | ||
| 94 | <string>Title ID</string> | ||
| 95 | </property> | ||
| 96 | </widget> | ||
| 97 | </item> | ||
| 98 | <item row="4" column="1"> | ||
| 99 | <widget class="QLineEdit" name="display_title_id"> | ||
| 100 | <property name="enabled"> | ||
| 101 | <bool>true</bool> | ||
| 102 | </property> | ||
| 103 | <property name="readOnly"> | ||
| 104 | <bool>true</bool> | ||
| 105 | </property> | ||
| 106 | </widget> | ||
| 107 | </item> | ||
| 108 | <item row="7" column="1"> | ||
| 109 | <widget class="QLineEdit" name="display_filename"> | ||
| 110 | <property name="enabled"> | ||
| 111 | <bool>true</bool> | ||
| 112 | </property> | ||
| 113 | <property name="readOnly"> | ||
| 114 | <bool>true</bool> | ||
| 115 | </property> | ||
| 116 | </widget> | ||
| 117 | </item> | ||
| 118 | <item row="5" column="1"> | ||
| 119 | <widget class="QLineEdit" name="display_format"> | ||
| 120 | <property name="enabled"> | ||
| 121 | <bool>true</bool> | ||
| 122 | </property> | ||
| 123 | <property name="readOnly"> | ||
| 124 | <bool>true</bool> | ||
| 125 | </property> | ||
| 126 | </widget> | ||
| 127 | </item> | ||
| 128 | <item row="7" column="0"> | ||
| 129 | <widget class="QLabel" name="label_7"> | ||
| 130 | <property name="text"> | ||
| 131 | <string>Filename</string> | ||
| 132 | </property> | ||
| 133 | </widget> | ||
| 134 | </item> | ||
| 135 | <item row="1" column="1"> | ||
| 136 | <widget class="QLineEdit" name="display_name"> | ||
| 137 | <property name="enabled"> | ||
| 138 | <bool>true</bool> | ||
| 139 | </property> | ||
| 140 | <property name="readOnly"> | ||
| 141 | <bool>true</bool> | ||
| 142 | </property> | ||
| 143 | </widget> | ||
| 144 | </item> | ||
| 145 | <item row="2" column="1"> | ||
| 146 | <widget class="QLineEdit" name="display_developer"> | ||
| 147 | <property name="enabled"> | ||
| 148 | <bool>true</bool> | ||
| 149 | </property> | ||
| 150 | <property name="readOnly"> | ||
| 151 | <bool>true</bool> | ||
| 152 | </property> | ||
| 153 | </widget> | ||
| 154 | </item> | ||
| 155 | <item row="5" column="0"> | ||
| 156 | <widget class="QLabel" name="label_5"> | ||
| 157 | <property name="text"> | ||
| 158 | <string>Format</string> | ||
| 159 | </property> | ||
| 160 | </widget> | ||
| 161 | </item> | ||
| 162 | <item row="3" column="0"> | ||
| 163 | <widget class="QLabel" name="label_3"> | ||
| 164 | <property name="text"> | ||
| 165 | <string>Version</string> | ||
| 166 | </property> | ||
| 167 | </widget> | ||
| 168 | </item> | ||
| 169 | <item row="6" column="0"> | ||
| 170 | <widget class="QLabel" name="label_6"> | ||
| 171 | <property name="text"> | ||
| 172 | <string>Size</string> | ||
| 173 | </property> | ||
| 174 | </widget> | ||
| 175 | </item> | ||
| 176 | <item row="2" column="0"> | ||
| 177 | <widget class="QLabel" name="label_2"> | ||
| 178 | <property name="text"> | ||
| 179 | <string>Developer</string> | ||
| 180 | </property> | ||
| 181 | </widget> | ||
| 182 | </item> | ||
| 183 | </layout> | ||
| 184 | </item> | ||
| 185 | <item> | ||
| 186 | <spacer name="verticalSpacer"> | ||
| 187 | <property name="orientation"> | ||
| 188 | <enum>Qt::Vertical</enum> | ||
| 189 | </property> | ||
| 190 | <property name="sizeHint" stdset="0"> | ||
| 191 | <size> | ||
| 192 | <width>20</width> | ||
| 193 | <height>40</height> | ||
| 194 | </size> | ||
| 195 | </property> | ||
| 196 | </spacer> | ||
| 197 | </item> | ||
| 198 | </layout> | ||
| 199 | </widget> | ||
| 200 | </item> | ||
| 201 | <item> | ||
| 202 | <layout class="QVBoxLayout" name="VerticalLayout"> | ||
| 203 | <item> | ||
| 204 | <layout class="QVBoxLayout" name="verticalLayout_2"/> | ||
| 205 | </item> | ||
| 206 | <item> | ||
| 207 | <widget class="QTabWidget" name="tabWidget"> | ||
| 208 | <property name="enabled"> | ||
| 209 | <bool>true</bool> | ||
| 210 | </property> | ||
| 211 | <property name="currentIndex"> | ||
| 212 | <number>0</number> | ||
| 213 | </property> | ||
| 214 | <property name="usesScrollButtons"> | ||
| 215 | <bool>true</bool> | ||
| 216 | </property> | ||
| 217 | <property name="documentMode"> | ||
| 218 | <bool>false</bool> | ||
| 219 | </property> | ||
| 220 | <property name="tabsClosable"> | ||
| 221 | <bool>false</bool> | ||
| 222 | </property> | ||
| 223 | <widget class="ConfigurePerGameAddons" name="addonsTab"> | ||
| 224 | <attribute name="title"> | ||
| 225 | <string>Add-Ons</string> | ||
| 226 | </attribute> | ||
| 227 | </widget> | ||
| 228 | <widget class="ConfigureGeneral" name="generalTab"> | ||
| 229 | <attribute name="title"> | ||
| 230 | <string>General</string> | ||
| 231 | </attribute> | ||
| 232 | </widget> | ||
| 233 | <widget class="ConfigureSystem" name="systemTab"> | ||
| 234 | <attribute name="title"> | ||
| 235 | <string>System</string> | ||
| 236 | </attribute> | ||
| 237 | </widget> | ||
| 238 | <widget class="ConfigureGraphics" name="graphicsTab"> | ||
| 239 | <attribute name="title"> | ||
| 240 | <string>Graphics</string> | ||
| 241 | </attribute> | ||
| 242 | </widget> | ||
| 243 | <widget class="ConfigureGraphicsAdvanced" name="graphicsAdvancedTab"> | ||
| 244 | <attribute name="title"> | ||
| 245 | <string>Adv. Graphics</string> | ||
| 246 | </attribute> | ||
| 247 | </widget> | ||
| 248 | <widget class="ConfigureAudio" name="audioTab"> | ||
| 249 | <attribute name="title"> | ||
| 250 | <string>Audio</string> | ||
| 251 | </attribute> | ||
| 252 | </widget> | ||
| 253 | </widget> | ||
| 254 | </item> | ||
| 255 | </layout> | ||
| 256 | </item> | ||
| 257 | </layout> | ||
| 258 | </item> | ||
| 259 | <item> | ||
| 260 | <widget class="QDialogButtonBox" name="buttonBox"> | ||
| 261 | <property name="sizePolicy"> | ||
| 262 | <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> | ||
| 263 | <horstretch>0</horstretch> | ||
| 264 | <verstretch>0</verstretch> | ||
| 265 | </sizepolicy> | ||
| 266 | </property> | ||
| 267 | <property name="orientation"> | ||
| 268 | <enum>Qt::Horizontal</enum> | ||
| 269 | </property> | ||
| 270 | <property name="standardButtons"> | ||
| 271 | <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> | ||
| 272 | </property> | ||
| 273 | </widget> | ||
| 274 | </item> | ||
| 275 | </layout> | ||
| 276 | </widget> | ||
| 277 | <customwidgets> | ||
| 278 | <customwidget> | ||
| 279 | <class>ConfigureGeneral</class> | ||
| 280 | <extends>QWidget</extends> | ||
| 281 | <header>configuration/configure_general.h</header> | ||
| 282 | <container>1</container> | ||
| 283 | </customwidget> | ||
| 284 | <customwidget> | ||
| 285 | <class>ConfigureSystem</class> | ||
| 286 | <extends>QWidget</extends> | ||
| 287 | <header>configuration/configure_system.h</header> | ||
| 288 | <container>1</container> | ||
| 289 | </customwidget> | ||
| 290 | <customwidget> | ||
| 291 | <class>ConfigureAudio</class> | ||
| 292 | <extends>QWidget</extends> | ||
| 293 | <header>configuration/configure_audio.h</header> | ||
| 294 | <container>1</container> | ||
| 295 | </customwidget> | ||
| 296 | <customwidget> | ||
| 297 | <class>ConfigureGraphics</class> | ||
| 298 | <extends>QWidget</extends> | ||
| 299 | <header>configuration/configure_graphics.h</header> | ||
| 300 | <container>1</container> | ||
| 301 | </customwidget> | ||
| 302 | <customwidget> | ||
| 303 | <class>ConfigureGraphicsAdvanced</class> | ||
| 304 | <extends>QWidget</extends> | ||
| 305 | <header>configuration/configure_graphics_advanced.h</header> | ||
| 306 | <container>1</container> | ||
| 307 | </customwidget> | ||
| 308 | <customwidget> | ||
| 309 | <class>ConfigurePerGameAddons</class> | ||
| 310 | <extends>QWidget</extends> | ||
| 311 | <header>configuration/configure_per_game_addons.h</header> | ||
| 312 | <container>1</container> | ||
| 313 | </customwidget> | ||
| 314 | </customwidgets> | ||
| 315 | <resources/> | ||
| 316 | <connections> | ||
| 317 | <connection> | ||
| 318 | <sender>buttonBox</sender> | ||
| 319 | <signal>accepted()</signal> | ||
| 320 | <receiver>ConfigurePerGame</receiver> | ||
| 321 | <slot>accept()</slot> | ||
| 322 | <hints> | ||
| 323 | <hint type="sourcelabel"> | ||
| 324 | <x>248</x> | ||
| 325 | <y>254</y> | ||
| 326 | </hint> | ||
| 327 | <hint type="destinationlabel"> | ||
| 328 | <x>157</x> | ||
| 329 | <y>274</y> | ||
| 330 | </hint> | ||
| 331 | </hints> | ||
| 332 | </connection> | ||
| 333 | <connection> | ||
| 334 | <sender>buttonBox</sender> | ||
| 335 | <signal>rejected()</signal> | ||
| 336 | <receiver>ConfigurePerGame</receiver> | ||
| 337 | <slot>reject()</slot> | ||
| 338 | <hints> | ||
| 339 | <hint type="sourcelabel"> | ||
| 340 | <x>316</x> | ||
| 341 | <y>260</y> | ||
| 342 | </hint> | ||
| 343 | <hint type="destinationlabel"> | ||
| 344 | <x>286</x> | ||
| 345 | <y>274</y> | ||
| 346 | </hint> | ||
| 347 | </hints> | ||
| 348 | </connection> | ||
| 349 | </connections> | ||
| 350 | </ui> | ||
diff --git a/src/yuzu/configuration/configure_per_general.cpp b/src/yuzu/configuration/configure_per_game_addons.cpp index d7f259f12..478d5d3a1 100644 --- a/src/yuzu/configuration/configure_per_general.cpp +++ b/src/yuzu/configuration/configure_per_game_addons.cpp | |||
| @@ -15,23 +15,20 @@ | |||
| 15 | 15 | ||
| 16 | #include "common/common_paths.h" | 16 | #include "common/common_paths.h" |
| 17 | #include "common/file_util.h" | 17 | #include "common/file_util.h" |
| 18 | #include "core/file_sys/control_metadata.h" | 18 | #include "core/core.h" |
| 19 | #include "core/file_sys/patch_manager.h" | 19 | #include "core/file_sys/patch_manager.h" |
| 20 | #include "core/file_sys/xts_archive.h" | 20 | #include "core/file_sys/xts_archive.h" |
| 21 | #include "core/loader/loader.h" | 21 | #include "core/loader/loader.h" |
| 22 | #include "ui_configure_per_general.h" | 22 | #include "ui_configure_per_game_addons.h" |
| 23 | #include "yuzu/configuration/config.h" | 23 | #include "yuzu/configuration/config.h" |
| 24 | #include "yuzu/configuration/configure_input.h" | 24 | #include "yuzu/configuration/configure_input.h" |
| 25 | #include "yuzu/configuration/configure_per_general.h" | 25 | #include "yuzu/configuration/configure_per_game_addons.h" |
| 26 | #include "yuzu/uisettings.h" | 26 | #include "yuzu/uisettings.h" |
| 27 | #include "yuzu/util/util.h" | 27 | #include "yuzu/util/util.h" |
| 28 | 28 | ||
| 29 | ConfigurePerGameGeneral::ConfigurePerGameGeneral(QWidget* parent, u64 title_id) | 29 | ConfigurePerGameAddons::ConfigurePerGameAddons(QWidget* parent) |
| 30 | : QDialog(parent), ui(std::make_unique<Ui::ConfigurePerGameGeneral>()), title_id(title_id) { | 30 | : QWidget(parent), ui(new Ui::ConfigurePerGameAddons) { |
| 31 | |||
| 32 | ui->setupUi(this); | 31 | ui->setupUi(this); |
| 33 | setFocusPolicy(Qt::ClickFocus); | ||
| 34 | setWindowTitle(tr("Properties")); | ||
| 35 | 32 | ||
| 36 | layout = new QVBoxLayout; | 33 | layout = new QVBoxLayout; |
| 37 | tree_view = new QTreeView; | 34 | tree_view = new QTreeView; |
| @@ -52,7 +49,7 @@ ConfigurePerGameGeneral::ConfigurePerGameGeneral(QWidget* parent, u64 title_id) | |||
| 52 | item_model->setHeaderData(1, Qt::Horizontal, tr("Version")); | 49 | item_model->setHeaderData(1, Qt::Horizontal, tr("Version")); |
| 53 | 50 | ||
| 54 | // We must register all custom types with the Qt Automoc system so that we are able to use it | 51 | // We must register all custom types with the Qt Automoc system so that we are able to use it |
| 55 | // with signals/slots. In this case, QList falls under the umbrells of custom types. | 52 | // with signals/slots. In this case, QList falls under the umbrella of custom types. |
| 56 | qRegisterMetaType<QList<QStandardItem*>>("QList<QStandardItem*>"); | 53 | qRegisterMetaType<QList<QStandardItem*>>("QList<QStandardItem*>"); |
| 57 | 54 | ||
| 58 | layout->setContentsMargins(0, 0, 0, 0); | 55 | layout->setContentsMargins(0, 0, 0, 0); |
| @@ -61,18 +58,15 @@ ConfigurePerGameGeneral::ConfigurePerGameGeneral(QWidget* parent, u64 title_id) | |||
| 61 | 58 | ||
| 62 | ui->scrollArea->setLayout(layout); | 59 | ui->scrollArea->setLayout(layout); |
| 63 | 60 | ||
| 64 | scene = new QGraphicsScene; | 61 | ui->scrollArea->setEnabled(!Core::System::GetInstance().IsPoweredOn()); |
| 65 | ui->icon_view->setScene(scene); | ||
| 66 | 62 | ||
| 67 | connect(item_model, &QStandardItemModel::itemChanged, | 63 | connect(item_model, &QStandardItemModel::itemChanged, |
| 68 | [] { UISettings::values.is_game_list_reload_pending.exchange(true); }); | 64 | [] { UISettings::values.is_game_list_reload_pending.exchange(true); }); |
| 69 | |||
| 70 | LoadConfiguration(); | ||
| 71 | } | 65 | } |
| 72 | 66 | ||
| 73 | ConfigurePerGameGeneral::~ConfigurePerGameGeneral() = default; | 67 | ConfigurePerGameAddons::~ConfigurePerGameAddons() = default; |
| 74 | 68 | ||
| 75 | void ConfigurePerGameGeneral::ApplyConfiguration() { | 69 | void ConfigurePerGameAddons::ApplyConfiguration() { |
| 76 | std::vector<std::string> disabled_addons; | 70 | std::vector<std::string> disabled_addons; |
| 77 | 71 | ||
| 78 | for (const auto& item : list_items) { | 72 | for (const auto& item : list_items) { |
| @@ -92,72 +86,35 @@ void ConfigurePerGameGeneral::ApplyConfiguration() { | |||
| 92 | Settings::values.disabled_addons[title_id] = disabled_addons; | 86 | Settings::values.disabled_addons[title_id] = disabled_addons; |
| 93 | } | 87 | } |
| 94 | 88 | ||
| 95 | void ConfigurePerGameGeneral::changeEvent(QEvent* event) { | 89 | void ConfigurePerGameAddons::LoadFromFile(FileSys::VirtualFile file) { |
| 90 | this->file = std::move(file); | ||
| 91 | LoadConfiguration(); | ||
| 92 | } | ||
| 93 | |||
| 94 | void ConfigurePerGameAddons::SetTitleId(u64 id) { | ||
| 95 | this->title_id = id; | ||
| 96 | } | ||
| 97 | |||
| 98 | void ConfigurePerGameAddons::changeEvent(QEvent* event) { | ||
| 96 | if (event->type() == QEvent::LanguageChange) { | 99 | if (event->type() == QEvent::LanguageChange) { |
| 97 | RetranslateUI(); | 100 | RetranslateUI(); |
| 98 | } | 101 | } |
| 99 | 102 | ||
| 100 | QDialog::changeEvent(event); | 103 | QWidget::changeEvent(event); |
| 101 | } | 104 | } |
| 102 | 105 | ||
| 103 | void ConfigurePerGameGeneral::RetranslateUI() { | 106 | void ConfigurePerGameAddons::RetranslateUI() { |
| 104 | ui->retranslateUi(this); | 107 | ui->retranslateUi(this); |
| 105 | } | 108 | } |
| 106 | 109 | ||
| 107 | void ConfigurePerGameGeneral::LoadFromFile(FileSys::VirtualFile file) { | 110 | void ConfigurePerGameAddons::LoadConfiguration() { |
| 108 | this->file = std::move(file); | ||
| 109 | LoadConfiguration(); | ||
| 110 | } | ||
| 111 | |||
| 112 | void ConfigurePerGameGeneral::LoadConfiguration() { | ||
| 113 | if (file == nullptr) { | 111 | if (file == nullptr) { |
| 114 | return; | 112 | return; |
| 115 | } | 113 | } |
| 116 | 114 | ||
| 117 | ui->display_title_id->setText(QString::fromStdString(fmt::format("{:016X}", title_id))); | ||
| 118 | |||
| 119 | FileSys::PatchManager pm{title_id}; | 115 | FileSys::PatchManager pm{title_id}; |
| 120 | const auto control = pm.GetControlMetadata(); | ||
| 121 | const auto loader = Loader::GetLoader(file); | 116 | const auto loader = Loader::GetLoader(file); |
| 122 | 117 | ||
| 123 | if (control.first != nullptr) { | ||
| 124 | ui->display_version->setText(QString::fromStdString(control.first->GetVersionString())); | ||
| 125 | ui->display_name->setText(QString::fromStdString(control.first->GetApplicationName())); | ||
| 126 | ui->display_developer->setText(QString::fromStdString(control.first->GetDeveloperName())); | ||
| 127 | } else { | ||
| 128 | std::string title; | ||
| 129 | if (loader->ReadTitle(title) == Loader::ResultStatus::Success) | ||
| 130 | ui->display_name->setText(QString::fromStdString(title)); | ||
| 131 | |||
| 132 | FileSys::NACP nacp; | ||
| 133 | if (loader->ReadControlData(nacp) == Loader::ResultStatus::Success) | ||
| 134 | ui->display_developer->setText(QString::fromStdString(nacp.GetDeveloperName())); | ||
| 135 | |||
| 136 | ui->display_version->setText(QStringLiteral("1.0.0")); | ||
| 137 | } | ||
| 138 | |||
| 139 | if (control.second != nullptr) { | ||
| 140 | scene->clear(); | ||
| 141 | |||
| 142 | QPixmap map; | ||
| 143 | const auto bytes = control.second->ReadAllBytes(); | ||
| 144 | map.loadFromData(bytes.data(), static_cast<u32>(bytes.size())); | ||
| 145 | |||
| 146 | scene->addPixmap(map.scaled(ui->icon_view->width(), ui->icon_view->height(), | ||
| 147 | Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); | ||
| 148 | } else { | ||
| 149 | std::vector<u8> bytes; | ||
| 150 | if (loader->ReadIcon(bytes) == Loader::ResultStatus::Success) { | ||
| 151 | scene->clear(); | ||
| 152 | |||
| 153 | QPixmap map; | ||
| 154 | map.loadFromData(bytes.data(), static_cast<u32>(bytes.size())); | ||
| 155 | |||
| 156 | scene->addPixmap(map.scaled(ui->icon_view->width(), ui->icon_view->height(), | ||
| 157 | Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); | ||
| 158 | } | ||
| 159 | } | ||
| 160 | |||
| 161 | FileSys::VirtualFile update_raw; | 118 | FileSys::VirtualFile update_raw; |
| 162 | loader->ReadUpdateRaw(update_raw); | 119 | loader->ReadUpdateRaw(update_raw); |
| 163 | 120 | ||
| @@ -182,12 +139,4 @@ void ConfigurePerGameGeneral::LoadConfiguration() { | |||
| 182 | } | 139 | } |
| 183 | 140 | ||
| 184 | tree_view->setColumnWidth(0, 5 * tree_view->width() / 16); | 141 | tree_view->setColumnWidth(0, 5 * tree_view->width() / 16); |
| 185 | |||
| 186 | ui->display_filename->setText(QString::fromStdString(file->GetName())); | ||
| 187 | |||
| 188 | ui->display_format->setText( | ||
| 189 | QString::fromStdString(Loader::GetFileTypeString(loader->GetFileType()))); | ||
| 190 | |||
| 191 | const auto valueText = ReadableByteSize(file->GetSize()); | ||
| 192 | ui->display_size->setText(valueText); | ||
| 193 | } | 142 | } |
diff --git a/src/yuzu/configuration/configure_per_general.h b/src/yuzu/configuration/configure_per_game_addons.h index a3b2cdeff..a00ec3539 100644 --- a/src/yuzu/configuration/configure_per_general.h +++ b/src/yuzu/configuration/configure_per_game_addons.h | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | // Copyright 2016 Citra Emulator Project | 1 | // Copyright 2016 Citra Emulator Project |
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| @@ -7,7 +7,6 @@ | |||
| 7 | #include <memory> | 7 | #include <memory> |
| 8 | #include <vector> | 8 | #include <vector> |
| 9 | 9 | ||
| 10 | #include <QDialog> | ||
| 11 | #include <QList> | 10 | #include <QList> |
| 12 | 11 | ||
| 13 | #include "core/file_sys/vfs_types.h" | 12 | #include "core/file_sys/vfs_types.h" |
| @@ -19,35 +18,36 @@ class QTreeView; | |||
| 19 | class QVBoxLayout; | 18 | class QVBoxLayout; |
| 20 | 19 | ||
| 21 | namespace Ui { | 20 | namespace Ui { |
| 22 | class ConfigurePerGameGeneral; | 21 | class ConfigurePerGameAddons; |
| 23 | } | 22 | } |
| 24 | 23 | ||
| 25 | class ConfigurePerGameGeneral : public QDialog { | 24 | class ConfigurePerGameAddons : public QWidget { |
| 26 | Q_OBJECT | 25 | Q_OBJECT |
| 27 | 26 | ||
| 28 | public: | 27 | public: |
| 29 | explicit ConfigurePerGameGeneral(QWidget* parent, u64 title_id); | 28 | explicit ConfigurePerGameAddons(QWidget* parent = nullptr); |
| 30 | ~ConfigurePerGameGeneral() override; | 29 | ~ConfigurePerGameAddons() override; |
| 31 | 30 | ||
| 32 | /// Save all button configurations to settings file | 31 | /// Save all button configurations to settings file |
| 33 | void ApplyConfiguration(); | 32 | void ApplyConfiguration(); |
| 34 | 33 | ||
| 35 | void LoadFromFile(FileSys::VirtualFile file); | 34 | void LoadFromFile(FileSys::VirtualFile file); |
| 36 | 35 | ||
| 36 | void SetTitleId(u64 id); | ||
| 37 | |||
| 37 | private: | 38 | private: |
| 38 | void changeEvent(QEvent* event) override; | 39 | void changeEvent(QEvent* event) override; |
| 39 | void RetranslateUI(); | 40 | void RetranslateUI(); |
| 40 | 41 | ||
| 41 | void LoadConfiguration(); | 42 | void LoadConfiguration(); |
| 42 | 43 | ||
| 43 | std::unique_ptr<Ui::ConfigurePerGameGeneral> ui; | 44 | std::unique_ptr<Ui::ConfigurePerGameAddons> ui; |
| 44 | FileSys::VirtualFile file; | 45 | FileSys::VirtualFile file; |
| 45 | u64 title_id; | 46 | u64 title_id; |
| 46 | 47 | ||
| 47 | QVBoxLayout* layout; | 48 | QVBoxLayout* layout; |
| 48 | QTreeView* tree_view; | 49 | QTreeView* tree_view; |
| 49 | QStandardItemModel* item_model; | 50 | QStandardItemModel* item_model; |
| 50 | QGraphicsScene* scene; | ||
| 51 | 51 | ||
| 52 | std::vector<QList<QStandardItem*>> list_items; | 52 | std::vector<QList<QStandardItem*>> list_items; |
| 53 | }; | 53 | }; |
diff --git a/src/yuzu/configuration/configure_per_game_addons.ui b/src/yuzu/configuration/configure_per_game_addons.ui new file mode 100644 index 000000000..aefdebfcd --- /dev/null +++ b/src/yuzu/configuration/configure_per_game_addons.ui | |||
| @@ -0,0 +1,38 @@ | |||
| 1 | <?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | <ui version="4.0"> | ||
| 3 | <class>ConfigurePerGameAddons</class> | ||
| 4 | <widget class="QWidget" name="ConfigurePerGameAddons"> | ||
| 5 | <property name="geometry"> | ||
| 6 | <rect> | ||
| 7 | <x>0</x> | ||
| 8 | <y>0</y> | ||
| 9 | <width>400</width> | ||
| 10 | <height>300</height> | ||
| 11 | </rect> | ||
| 12 | </property> | ||
| 13 | <property name="windowTitle"> | ||
| 14 | <string>Form</string> | ||
| 15 | </property> | ||
| 16 | <layout class="QGridLayout" name="gridLayout"> | ||
| 17 | <item row="0" column="0"> | ||
| 18 | <widget class="QScrollArea" name="scrollArea"> | ||
| 19 | <property name="widgetResizable"> | ||
| 20 | <bool>true</bool> | ||
| 21 | </property> | ||
| 22 | <widget class="QWidget" name="scrollAreaWidgetContents"> | ||
| 23 | <property name="geometry"> | ||
| 24 | <rect> | ||
| 25 | <x>0</x> | ||
| 26 | <y>0</y> | ||
| 27 | <width>380</width> | ||
| 28 | <height>280</height> | ||
| 29 | </rect> | ||
| 30 | </property> | ||
| 31 | </widget> | ||
| 32 | </widget> | ||
| 33 | </item> | ||
| 34 | </layout> | ||
| 35 | </widget> | ||
| 36 | <resources/> | ||
| 37 | <connections/> | ||
| 38 | </ui> | ||
diff --git a/src/yuzu/configuration/configure_per_general.ui b/src/yuzu/configuration/configure_per_general.ui deleted file mode 100644 index 8fdd96fa4..000000000 --- a/src/yuzu/configuration/configure_per_general.ui +++ /dev/null | |||
| @@ -1,276 +0,0 @@ | |||
| 1 | <?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | <ui version="4.0"> | ||
| 3 | <class>ConfigurePerGameGeneral</class> | ||
| 4 | <widget class="QDialog" name="ConfigurePerGameGeneral"> | ||
| 5 | <property name="geometry"> | ||
| 6 | <rect> | ||
| 7 | <x>0</x> | ||
| 8 | <y>0</y> | ||
| 9 | <width>400</width> | ||
| 10 | <height>520</height> | ||
| 11 | </rect> | ||
| 12 | </property> | ||
| 13 | <property name="windowTitle"> | ||
| 14 | <string>ConfigurePerGameGeneral</string> | ||
| 15 | </property> | ||
| 16 | <layout class="QHBoxLayout" name="HorizontalLayout"> | ||
| 17 | <item> | ||
| 18 | <layout class="QVBoxLayout" name="VerticalLayout"> | ||
| 19 | <item> | ||
| 20 | <widget class="QGroupBox" name="GeneralGroupBox"> | ||
| 21 | <property name="title"> | ||
| 22 | <string>Info</string> | ||
| 23 | </property> | ||
| 24 | <layout class="QHBoxLayout" name="GeneralHorizontalLayout"> | ||
| 25 | <item> | ||
| 26 | <layout class="QGridLayout" name="gridLayout_2"> | ||
| 27 | <item row="6" column="1" colspan="2"> | ||
| 28 | <widget class="QLineEdit" name="display_filename"> | ||
| 29 | <property name="enabled"> | ||
| 30 | <bool>true</bool> | ||
| 31 | </property> | ||
| 32 | <property name="readOnly"> | ||
| 33 | <bool>true</bool> | ||
| 34 | </property> | ||
| 35 | </widget> | ||
| 36 | </item> | ||
| 37 | <item row="0" column="1"> | ||
| 38 | <widget class="QLineEdit" name="display_name"> | ||
| 39 | <property name="enabled"> | ||
| 40 | <bool>true</bool> | ||
| 41 | </property> | ||
| 42 | <property name="readOnly"> | ||
| 43 | <bool>true</bool> | ||
| 44 | </property> | ||
| 45 | </widget> | ||
| 46 | </item> | ||
| 47 | <item row="1" column="0"> | ||
| 48 | <widget class="QLabel" name="label_2"> | ||
| 49 | <property name="text"> | ||
| 50 | <string>Developer</string> | ||
| 51 | </property> | ||
| 52 | </widget> | ||
| 53 | </item> | ||
| 54 | <item row="5" column="1" colspan="2"> | ||
| 55 | <widget class="QLineEdit" name="display_size"> | ||
| 56 | <property name="enabled"> | ||
| 57 | <bool>true</bool> | ||
| 58 | </property> | ||
| 59 | <property name="readOnly"> | ||
| 60 | <bool>true</bool> | ||
| 61 | </property> | ||
| 62 | </widget> | ||
| 63 | </item> | ||
| 64 | <item row="0" column="0"> | ||
| 65 | <widget class="QLabel" name="label"> | ||
| 66 | <property name="text"> | ||
| 67 | <string>Name</string> | ||
| 68 | </property> | ||
| 69 | </widget> | ||
| 70 | </item> | ||
| 71 | <item row="6" column="0"> | ||
| 72 | <widget class="QLabel" name="label_7"> | ||
| 73 | <property name="text"> | ||
| 74 | <string>Filename</string> | ||
| 75 | </property> | ||
| 76 | </widget> | ||
| 77 | </item> | ||
| 78 | <item row="2" column="0"> | ||
| 79 | <widget class="QLabel" name="label_3"> | ||
| 80 | <property name="text"> | ||
| 81 | <string>Version</string> | ||
| 82 | </property> | ||
| 83 | </widget> | ||
| 84 | </item> | ||
| 85 | <item row="4" column="0"> | ||
| 86 | <widget class="QLabel" name="label_5"> | ||
| 87 | <property name="text"> | ||
| 88 | <string>Format</string> | ||
| 89 | </property> | ||
| 90 | </widget> | ||
| 91 | </item> | ||
| 92 | <item row="2" column="1"> | ||
| 93 | <widget class="QLineEdit" name="display_version"> | ||
| 94 | <property name="enabled"> | ||
| 95 | <bool>true</bool> | ||
| 96 | </property> | ||
| 97 | <property name="readOnly"> | ||
| 98 | <bool>true</bool> | ||
| 99 | </property> | ||
| 100 | </widget> | ||
| 101 | </item> | ||
| 102 | <item row="4" column="1"> | ||
| 103 | <widget class="QLineEdit" name="display_format"> | ||
| 104 | <property name="enabled"> | ||
| 105 | <bool>true</bool> | ||
| 106 | </property> | ||
| 107 | <property name="readOnly"> | ||
| 108 | <bool>true</bool> | ||
| 109 | </property> | ||
| 110 | </widget> | ||
| 111 | </item> | ||
| 112 | <item row="5" column="0"> | ||
| 113 | <widget class="QLabel" name="label_6"> | ||
| 114 | <property name="text"> | ||
| 115 | <string>Size</string> | ||
| 116 | </property> | ||
| 117 | </widget> | ||
| 118 | </item> | ||
| 119 | <item row="1" column="1"> | ||
| 120 | <widget class="QLineEdit" name="display_developer"> | ||
| 121 | <property name="enabled"> | ||
| 122 | <bool>true</bool> | ||
| 123 | </property> | ||
| 124 | <property name="readOnly"> | ||
| 125 | <bool>true</bool> | ||
| 126 | </property> | ||
| 127 | </widget> | ||
| 128 | </item> | ||
| 129 | <item row="3" column="0"> | ||
| 130 | <widget class="QLabel" name="label_4"> | ||
| 131 | <property name="text"> | ||
| 132 | <string>Title ID</string> | ||
| 133 | </property> | ||
| 134 | </widget> | ||
| 135 | </item> | ||
| 136 | <item row="3" column="1"> | ||
| 137 | <widget class="QLineEdit" name="display_title_id"> | ||
| 138 | <property name="enabled"> | ||
| 139 | <bool>true</bool> | ||
| 140 | </property> | ||
| 141 | <property name="readOnly"> | ||
| 142 | <bool>true</bool> | ||
| 143 | </property> | ||
| 144 | </widget> | ||
| 145 | </item> | ||
| 146 | <item row="0" column="2" rowspan="5"> | ||
| 147 | <widget class="QGraphicsView" name="icon_view"> | ||
| 148 | <property name="sizePolicy"> | ||
| 149 | <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> | ||
| 150 | <horstretch>0</horstretch> | ||
| 151 | <verstretch>0</verstretch> | ||
| 152 | </sizepolicy> | ||
| 153 | </property> | ||
| 154 | <property name="minimumSize"> | ||
| 155 | <size> | ||
| 156 | <width>128</width> | ||
| 157 | <height>128</height> | ||
| 158 | </size> | ||
| 159 | </property> | ||
| 160 | <property name="maximumSize"> | ||
| 161 | <size> | ||
| 162 | <width>128</width> | ||
| 163 | <height>128</height> | ||
| 164 | </size> | ||
| 165 | </property> | ||
| 166 | <property name="verticalScrollBarPolicy"> | ||
| 167 | <enum>Qt::ScrollBarAlwaysOff</enum> | ||
| 168 | </property> | ||
| 169 | <property name="horizontalScrollBarPolicy"> | ||
| 170 | <enum>Qt::ScrollBarAlwaysOff</enum> | ||
| 171 | </property> | ||
| 172 | <property name="sizeAdjustPolicy"> | ||
| 173 | <enum>QAbstractScrollArea::AdjustToContents</enum> | ||
| 174 | </property> | ||
| 175 | <property name="interactive"> | ||
| 176 | <bool>false</bool> | ||
| 177 | </property> | ||
| 178 | </widget> | ||
| 179 | </item> | ||
| 180 | </layout> | ||
| 181 | </item> | ||
| 182 | </layout> | ||
| 183 | </widget> | ||
| 184 | </item> | ||
| 185 | <item> | ||
| 186 | <widget class="QGroupBox" name="PerformanceGroupBox"> | ||
| 187 | <property name="title"> | ||
| 188 | <string>Add-Ons</string> | ||
| 189 | </property> | ||
| 190 | <layout class="QHBoxLayout" name="PerformanceHorizontalLayout"> | ||
| 191 | <item> | ||
| 192 | <widget class="QScrollArea" name="scrollArea"> | ||
| 193 | <property name="widgetResizable"> | ||
| 194 | <bool>true</bool> | ||
| 195 | </property> | ||
| 196 | <widget class="QWidget" name="scrollAreaWidgetContents"> | ||
| 197 | <property name="geometry"> | ||
| 198 | <rect> | ||
| 199 | <x>0</x> | ||
| 200 | <y>0</y> | ||
| 201 | <width>350</width> | ||
| 202 | <height>169</height> | ||
| 203 | </rect> | ||
| 204 | </property> | ||
| 205 | </widget> | ||
| 206 | </widget> | ||
| 207 | </item> | ||
| 208 | <item> | ||
| 209 | <layout class="QVBoxLayout" name="PerformanceVerticalLayout"/> | ||
| 210 | </item> | ||
| 211 | </layout> | ||
| 212 | </widget> | ||
| 213 | </item> | ||
| 214 | <item> | ||
| 215 | <spacer name="verticalSpacer"> | ||
| 216 | <property name="orientation"> | ||
| 217 | <enum>Qt::Vertical</enum> | ||
| 218 | </property> | ||
| 219 | <property name="sizeType"> | ||
| 220 | <enum>QSizePolicy::Fixed</enum> | ||
| 221 | </property> | ||
| 222 | <property name="sizeHint" stdset="0"> | ||
| 223 | <size> | ||
| 224 | <width>20</width> | ||
| 225 | <height>40</height> | ||
| 226 | </size> | ||
| 227 | </property> | ||
| 228 | </spacer> | ||
| 229 | </item> | ||
| 230 | <item> | ||
| 231 | <widget class="QDialogButtonBox" name="buttonBox"> | ||
| 232 | <property name="standardButtons"> | ||
| 233 | <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> | ||
| 234 | </property> | ||
| 235 | </widget> | ||
| 236 | </item> | ||
| 237 | </layout> | ||
| 238 | </item> | ||
| 239 | </layout> | ||
| 240 | </widget> | ||
| 241 | <resources/> | ||
| 242 | <connections> | ||
| 243 | <connection> | ||
| 244 | <sender>buttonBox</sender> | ||
| 245 | <signal>accepted()</signal> | ||
| 246 | <receiver>ConfigurePerGameGeneral</receiver> | ||
| 247 | <slot>accept()</slot> | ||
| 248 | <hints> | ||
| 249 | <hint type="sourcelabel"> | ||
| 250 | <x>269</x> | ||
| 251 | <y>567</y> | ||
| 252 | </hint> | ||
| 253 | <hint type="destinationlabel"> | ||
| 254 | <x>269</x> | ||
| 255 | <y>294</y> | ||
| 256 | </hint> | ||
| 257 | </hints> | ||
| 258 | </connection> | ||
| 259 | <connection> | ||
| 260 | <sender>buttonBox</sender> | ||
| 261 | <signal>rejected()</signal> | ||
| 262 | <receiver>ConfigurePerGameGeneral</receiver> | ||
| 263 | <slot>reject()</slot> | ||
| 264 | <hints> | ||
| 265 | <hint type="sourcelabel"> | ||
| 266 | <x>269</x> | ||
| 267 | <y>567</y> | ||
| 268 | </hint> | ||
| 269 | <hint type="destinationlabel"> | ||
| 270 | <x>269</x> | ||
| 271 | <y>294</y> | ||
| 272 | </hint> | ||
| 273 | </hints> | ||
| 274 | </connection> | ||
| 275 | </connections> | ||
| 276 | </ui> | ||
diff --git a/src/yuzu/configuration/configure_system.cpp b/src/yuzu/configuration/configure_system.cpp index 10315e7a6..68e02738b 100644 --- a/src/yuzu/configuration/configure_system.cpp +++ b/src/yuzu/configuration/configure_system.cpp | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | #include "core/core.h" | 14 | #include "core/core.h" |
| 15 | #include "core/settings.h" | 15 | #include "core/settings.h" |
| 16 | #include "ui_configure_system.h" | 16 | #include "ui_configure_system.h" |
| 17 | #include "yuzu/configuration/configuration_shared.h" | ||
| 17 | #include "yuzu/configuration/configure_system.h" | 18 | #include "yuzu/configuration/configure_system.h" |
| 18 | 19 | ||
| 19 | ConfigureSystem::ConfigureSystem(QWidget* parent) : QWidget(parent), ui(new Ui::ConfigureSystem) { | 20 | ConfigureSystem::ConfigureSystem(QWidget* parent) : QWidget(parent), ui(new Ui::ConfigureSystem) { |
| @@ -21,20 +22,25 @@ ConfigureSystem::ConfigureSystem(QWidget* parent) : QWidget(parent), ui(new Ui:: | |||
| 21 | connect(ui->button_regenerate_console_id, &QPushButton::clicked, this, | 22 | connect(ui->button_regenerate_console_id, &QPushButton::clicked, this, |
| 22 | &ConfigureSystem::RefreshConsoleID); | 23 | &ConfigureSystem::RefreshConsoleID); |
| 23 | 24 | ||
| 24 | connect(ui->rng_seed_checkbox, &QCheckBox::stateChanged, this, [this](bool checked) { | 25 | connect(ui->rng_seed_checkbox, &QCheckBox::stateChanged, this, [this](int state) { |
| 25 | ui->rng_seed_edit->setEnabled(checked); | 26 | ui->rng_seed_edit->setEnabled(state == Qt::Checked); |
| 26 | if (!checked) { | 27 | if (state != Qt::Checked) { |
| 27 | ui->rng_seed_edit->setText(QStringLiteral("00000000")); | 28 | ui->rng_seed_edit->setText(QStringLiteral("00000000")); |
| 28 | } | 29 | } |
| 29 | }); | 30 | }); |
| 30 | 31 | ||
| 31 | connect(ui->custom_rtc_checkbox, &QCheckBox::stateChanged, this, [this](bool checked) { | 32 | connect(ui->custom_rtc_checkbox, &QCheckBox::stateChanged, this, [this](int state) { |
| 32 | ui->custom_rtc_edit->setEnabled(checked); | 33 | ui->custom_rtc_edit->setEnabled(state == Qt::Checked); |
| 33 | if (!checked) { | 34 | if (state != Qt::Checked) { |
| 34 | ui->custom_rtc_edit->setDateTime(QDateTime::currentDateTime()); | 35 | ui->custom_rtc_edit->setDateTime(QDateTime::currentDateTime()); |
| 35 | } | 36 | } |
| 36 | }); | 37 | }); |
| 37 | 38 | ||
| 39 | ui->label_console_id->setVisible(Settings::configuring_global); | ||
| 40 | ui->button_regenerate_console_id->setVisible(Settings::configuring_global); | ||
| 41 | |||
| 42 | SetupPerGameUI(); | ||
| 43 | |||
| 38 | SetConfiguration(); | 44 | SetConfiguration(); |
| 39 | } | 45 | } |
| 40 | 46 | ||
| @@ -54,26 +60,58 @@ void ConfigureSystem::RetranslateUI() { | |||
| 54 | 60 | ||
| 55 | void ConfigureSystem::SetConfiguration() { | 61 | void ConfigureSystem::SetConfiguration() { |
| 56 | enabled = !Core::System::GetInstance().IsPoweredOn(); | 62 | enabled = !Core::System::GetInstance().IsPoweredOn(); |
| 63 | const auto rng_seed = | ||
| 64 | QStringLiteral("%1") | ||
| 65 | .arg(Settings::values.rng_seed.GetValue().value_or(0), 8, 16, QLatin1Char{'0'}) | ||
| 66 | .toUpper(); | ||
| 67 | const auto rtc_time = Settings::values.custom_rtc.GetValue().value_or( | ||
| 68 | std::chrono::seconds(QDateTime::currentSecsSinceEpoch())); | ||
| 57 | 69 | ||
| 58 | ui->combo_language->setCurrentIndex(Settings::values.language_index); | 70 | if (Settings::configuring_global) { |
| 59 | ui->combo_region->setCurrentIndex(Settings::values.region_index); | 71 | ui->combo_language->setCurrentIndex(Settings::values.language_index.GetValue()); |
| 60 | ui->combo_time_zone->setCurrentIndex(Settings::values.time_zone_index); | 72 | ui->combo_region->setCurrentIndex(Settings::values.region_index.GetValue()); |
| 61 | ui->combo_sound->setCurrentIndex(Settings::values.sound_index); | 73 | ui->combo_time_zone->setCurrentIndex(Settings::values.time_zone_index.GetValue()); |
| 62 | 74 | ui->combo_sound->setCurrentIndex(Settings::values.sound_index.GetValue()); | |
| 63 | ui->rng_seed_checkbox->setChecked(Settings::values.rng_seed.has_value()); | 75 | |
| 64 | ui->rng_seed_edit->setEnabled(Settings::values.rng_seed.has_value()); | 76 | ui->rng_seed_checkbox->setChecked(Settings::values.rng_seed.GetValue().has_value()); |
| 65 | 77 | ui->rng_seed_edit->setEnabled(Settings::values.rng_seed.GetValue().has_value() && | |
| 66 | const auto rng_seed = QStringLiteral("%1") | 78 | Settings::values.rng_seed.UsingGlobal()); |
| 67 | .arg(Settings::values.rng_seed.value_or(0), 8, 16, QLatin1Char{'0'}) | 79 | ui->rng_seed_edit->setText(rng_seed); |
| 68 | .toUpper(); | 80 | |
| 69 | ui->rng_seed_edit->setText(rng_seed); | 81 | ui->custom_rtc_checkbox->setChecked(Settings::values.custom_rtc.GetValue().has_value()); |
| 70 | 82 | ui->custom_rtc_edit->setEnabled(Settings::values.custom_rtc.GetValue().has_value() && | |
| 71 | ui->custom_rtc_checkbox->setChecked(Settings::values.custom_rtc.has_value()); | 83 | Settings::values.rng_seed.UsingGlobal()); |
| 72 | ui->custom_rtc_edit->setEnabled(Settings::values.custom_rtc.has_value()); | 84 | ui->custom_rtc_edit->setDateTime(QDateTime::fromSecsSinceEpoch(rtc_time.count())); |
| 85 | } else { | ||
| 86 | ConfigurationShared::SetPerGameSetting(ui->combo_language, | ||
| 87 | &Settings::values.language_index); | ||
| 88 | ConfigurationShared::SetPerGameSetting(ui->combo_region, &Settings::values.region_index); | ||
| 89 | ConfigurationShared::SetPerGameSetting(ui->combo_time_zone, | ||
| 90 | &Settings::values.time_zone_index); | ||
| 91 | ConfigurationShared::SetPerGameSetting(ui->combo_sound, &Settings::values.sound_index); | ||
| 92 | |||
| 93 | if (Settings::values.rng_seed.UsingGlobal()) { | ||
| 94 | ui->rng_seed_checkbox->setCheckState(Qt::PartiallyChecked); | ||
| 95 | } else { | ||
| 96 | ui->rng_seed_checkbox->setCheckState( | ||
| 97 | Settings::values.rng_seed.GetValue().has_value() ? Qt::Checked : Qt::Unchecked); | ||
| 98 | ui->rng_seed_edit->setEnabled(Settings::values.rng_seed.GetValue().has_value()); | ||
| 99 | if (Settings::values.rng_seed.GetValue().has_value()) { | ||
| 100 | ui->rng_seed_edit->setText(rng_seed); | ||
| 101 | } | ||
| 102 | } | ||
| 73 | 103 | ||
| 74 | const auto rtc_time = Settings::values.custom_rtc.value_or( | 104 | if (Settings::values.custom_rtc.UsingGlobal()) { |
| 75 | std::chrono::seconds(QDateTime::currentSecsSinceEpoch())); | 105 | ui->custom_rtc_checkbox->setCheckState(Qt::PartiallyChecked); |
| 76 | ui->custom_rtc_edit->setDateTime(QDateTime::fromSecsSinceEpoch(rtc_time.count())); | 106 | } else { |
| 107 | ui->custom_rtc_checkbox->setCheckState( | ||
| 108 | Settings::values.custom_rtc.GetValue().has_value() ? Qt::Checked : Qt::Unchecked); | ||
| 109 | ui->custom_rtc_edit->setEnabled(Settings::values.custom_rtc.GetValue().has_value()); | ||
| 110 | if (Settings::values.custom_rtc.GetValue().has_value()) { | ||
| 111 | ui->custom_rtc_edit->setDateTime(QDateTime::fromSecsSinceEpoch(rtc_time.count())); | ||
| 112 | } | ||
| 113 | } | ||
| 114 | } | ||
| 77 | } | 115 | } |
| 78 | 116 | ||
| 79 | void ConfigureSystem::ReadSystemSettings() {} | 117 | void ConfigureSystem::ReadSystemSettings() {} |
| @@ -83,22 +121,78 @@ void ConfigureSystem::ApplyConfiguration() { | |||
| 83 | return; | 121 | return; |
| 84 | } | 122 | } |
| 85 | 123 | ||
| 86 | Settings::values.language_index = ui->combo_language->currentIndex(); | 124 | if (Settings::configuring_global) { |
| 87 | Settings::values.region_index = ui->combo_region->currentIndex(); | 125 | // Guard if during game and set to game-specific value |
| 88 | Settings::values.time_zone_index = ui->combo_time_zone->currentIndex(); | 126 | if (Settings::values.language_index.UsingGlobal()) { |
| 89 | Settings::values.sound_index = ui->combo_sound->currentIndex(); | 127 | Settings::values.language_index.SetValue(ui->combo_language->currentIndex()); |
| 128 | } | ||
| 129 | if (Settings::values.region_index.UsingGlobal()) { | ||
| 130 | Settings::values.region_index.SetValue(ui->combo_region->currentIndex()); | ||
| 131 | } | ||
| 132 | if (Settings::values.time_zone_index.UsingGlobal()) { | ||
| 133 | Settings::values.time_zone_index.SetValue(ui->combo_time_zone->currentIndex()); | ||
| 134 | } | ||
| 135 | if (Settings::values.sound_index.UsingGlobal()) { | ||
| 136 | Settings::values.sound_index.SetValue(ui->combo_sound->currentIndex()); | ||
| 137 | } | ||
| 138 | |||
| 139 | if (Settings::values.rng_seed.UsingGlobal()) { | ||
| 140 | if (ui->rng_seed_checkbox->isChecked()) { | ||
| 141 | Settings::values.rng_seed.SetValue( | ||
| 142 | ui->rng_seed_edit->text().toULongLong(nullptr, 16)); | ||
| 143 | } else { | ||
| 144 | Settings::values.rng_seed.SetValue(std::nullopt); | ||
| 145 | } | ||
| 146 | } | ||
| 90 | 147 | ||
| 91 | if (ui->rng_seed_checkbox->isChecked()) { | 148 | if (Settings::values.custom_rtc.UsingGlobal()) { |
| 92 | Settings::values.rng_seed = ui->rng_seed_edit->text().toULongLong(nullptr, 16); | 149 | if (ui->custom_rtc_checkbox->isChecked()) { |
| 150 | Settings::values.custom_rtc.SetValue( | ||
| 151 | std::chrono::seconds(ui->custom_rtc_edit->dateTime().toSecsSinceEpoch())); | ||
| 152 | } else { | ||
| 153 | Settings::values.custom_rtc.SetValue(std::nullopt); | ||
| 154 | } | ||
| 155 | } | ||
| 93 | } else { | 156 | } else { |
| 94 | Settings::values.rng_seed = std::nullopt; | 157 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.language_index, |
| 95 | } | 158 | ui->combo_language); |
| 159 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.region_index, ui->combo_region); | ||
| 160 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.time_zone_index, | ||
| 161 | ui->combo_time_zone); | ||
| 162 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.sound_index, ui->combo_sound); | ||
| 163 | |||
| 164 | switch (ui->rng_seed_checkbox->checkState()) { | ||
| 165 | case Qt::Checked: | ||
| 166 | Settings::values.rng_seed.SetGlobal(false); | ||
| 167 | Settings::values.rng_seed.SetValue(ui->rng_seed_edit->text().toULongLong(nullptr, 16)); | ||
| 168 | break; | ||
| 169 | case Qt::Unchecked: | ||
| 170 | Settings::values.rng_seed.SetGlobal(false); | ||
| 171 | Settings::values.rng_seed.SetValue(std::nullopt); | ||
| 172 | break; | ||
| 173 | case Qt::PartiallyChecked: | ||
| 174 | Settings::values.rng_seed.SetGlobal(false); | ||
| 175 | Settings::values.rng_seed.SetValue(std::nullopt); | ||
| 176 | Settings::values.rng_seed.SetGlobal(true); | ||
| 177 | break; | ||
| 178 | } | ||
| 96 | 179 | ||
| 97 | if (ui->custom_rtc_checkbox->isChecked()) { | 180 | switch (ui->custom_rtc_checkbox->checkState()) { |
| 98 | Settings::values.custom_rtc = | 181 | case Qt::Checked: |
| 99 | std::chrono::seconds(ui->custom_rtc_edit->dateTime().toSecsSinceEpoch()); | 182 | Settings::values.custom_rtc.SetGlobal(false); |
| 100 | } else { | 183 | Settings::values.custom_rtc.SetValue( |
| 101 | Settings::values.custom_rtc = std::nullopt; | 184 | std::chrono::seconds(ui->custom_rtc_edit->dateTime().toSecsSinceEpoch())); |
| 185 | break; | ||
| 186 | case Qt::Unchecked: | ||
| 187 | Settings::values.custom_rtc.SetGlobal(false); | ||
| 188 | Settings::values.custom_rtc.SetValue(std::nullopt); | ||
| 189 | break; | ||
| 190 | case Qt::PartiallyChecked: | ||
| 191 | Settings::values.custom_rtc.SetGlobal(false); | ||
| 192 | Settings::values.custom_rtc.SetValue(std::nullopt); | ||
| 193 | Settings::values.custom_rtc.SetGlobal(true); | ||
| 194 | break; | ||
| 195 | } | ||
| 102 | } | 196 | } |
| 103 | 197 | ||
| 104 | Settings::Apply(); | 198 | Settings::Apply(); |
| @@ -120,3 +214,25 @@ void ConfigureSystem::RefreshConsoleID() { | |||
| 120 | ui->label_console_id->setText( | 214 | ui->label_console_id->setText( |
| 121 | tr("Console ID: 0x%1").arg(QString::number(console_id, 16).toUpper())); | 215 | tr("Console ID: 0x%1").arg(QString::number(console_id, 16).toUpper())); |
| 122 | } | 216 | } |
| 217 | |||
| 218 | void ConfigureSystem::SetupPerGameUI() { | ||
| 219 | if (Settings::configuring_global) { | ||
| 220 | ui->combo_language->setEnabled(Settings::values.language_index.UsingGlobal()); | ||
| 221 | ui->combo_region->setEnabled(Settings::values.region_index.UsingGlobal()); | ||
| 222 | ui->combo_time_zone->setEnabled(Settings::values.time_zone_index.UsingGlobal()); | ||
| 223 | ui->combo_sound->setEnabled(Settings::values.sound_index.UsingGlobal()); | ||
| 224 | ui->rng_seed_checkbox->setEnabled(Settings::values.rng_seed.UsingGlobal()); | ||
| 225 | ui->rng_seed_edit->setEnabled(Settings::values.rng_seed.UsingGlobal()); | ||
| 226 | ui->custom_rtc_checkbox->setEnabled(Settings::values.custom_rtc.UsingGlobal()); | ||
| 227 | ui->custom_rtc_edit->setEnabled(Settings::values.custom_rtc.UsingGlobal()); | ||
| 228 | |||
| 229 | return; | ||
| 230 | } | ||
| 231 | |||
| 232 | ConfigurationShared::InsertGlobalItem(ui->combo_language); | ||
| 233 | ConfigurationShared::InsertGlobalItem(ui->combo_region); | ||
| 234 | ConfigurationShared::InsertGlobalItem(ui->combo_time_zone); | ||
| 235 | ConfigurationShared::InsertGlobalItem(ui->combo_sound); | ||
| 236 | ui->rng_seed_checkbox->setTristate(true); | ||
| 237 | ui->custom_rtc_checkbox->setTristate(true); | ||
| 238 | } | ||
diff --git a/src/yuzu/configuration/configure_system.h b/src/yuzu/configuration/configure_system.h index 26d42d5c5..f317ef8b5 100644 --- a/src/yuzu/configuration/configure_system.h +++ b/src/yuzu/configuration/configure_system.h | |||
| @@ -32,6 +32,8 @@ private: | |||
| 32 | 32 | ||
| 33 | void RefreshConsoleID(); | 33 | void RefreshConsoleID(); |
| 34 | 34 | ||
| 35 | void SetupPerGameUI(); | ||
| 36 | |||
| 35 | std::unique_ptr<Ui::ConfigureSystem> ui; | 37 | std::unique_ptr<Ui::ConfigureSystem> ui; |
| 36 | bool enabled = false; | 38 | bool enabled = false; |
| 37 | 39 | ||
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 9844e4764..4d501a8f9 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp | |||
| @@ -16,7 +16,7 @@ | |||
| 16 | #include "applets/software_keyboard.h" | 16 | #include "applets/software_keyboard.h" |
| 17 | #include "applets/web_browser.h" | 17 | #include "applets/web_browser.h" |
| 18 | #include "configuration/configure_input.h" | 18 | #include "configuration/configure_input.h" |
| 19 | #include "configuration/configure_per_general.h" | 19 | #include "configuration/configure_per_game.h" |
| 20 | #include "core/file_sys/vfs.h" | 20 | #include "core/file_sys/vfs.h" |
| 21 | #include "core/file_sys/vfs_real.h" | 21 | #include "core/file_sys/vfs_real.h" |
| 22 | #include "core/frontend/applets/general_frontend.h" | 22 | #include "core/frontend/applets/general_frontend.h" |
| @@ -534,15 +534,15 @@ void GMainWindow::InitializeWidgets() { | |||
| 534 | if (emulation_running) { | 534 | if (emulation_running) { |
| 535 | return; | 535 | return; |
| 536 | } | 536 | } |
| 537 | bool is_async = | 537 | bool is_async = !Settings::values.use_asynchronous_gpu_emulation.GetValue() || |
| 538 | !Settings::values.use_asynchronous_gpu_emulation || Settings::values.use_multi_core; | 538 | Settings::values.use_multi_core.GetValue(); |
| 539 | Settings::values.use_asynchronous_gpu_emulation = is_async; | 539 | Settings::values.use_asynchronous_gpu_emulation.SetValue(is_async); |
| 540 | async_status_button->setChecked(Settings::values.use_asynchronous_gpu_emulation); | 540 | async_status_button->setChecked(Settings::values.use_asynchronous_gpu_emulation.GetValue()); |
| 541 | Settings::Apply(); | 541 | Settings::Apply(); |
| 542 | }); | 542 | }); |
| 543 | async_status_button->setText(tr("ASYNC")); | 543 | async_status_button->setText(tr("ASYNC")); |
| 544 | async_status_button->setCheckable(true); | 544 | async_status_button->setCheckable(true); |
| 545 | async_status_button->setChecked(Settings::values.use_asynchronous_gpu_emulation); | 545 | async_status_button->setChecked(Settings::values.use_asynchronous_gpu_emulation.GetValue()); |
| 546 | 546 | ||
| 547 | // Setup Multicore button | 547 | // Setup Multicore button |
| 548 | multicore_status_button = new QPushButton(); | 548 | multicore_status_button = new QPushButton(); |
| @@ -552,17 +552,17 @@ void GMainWindow::InitializeWidgets() { | |||
| 552 | if (emulation_running) { | 552 | if (emulation_running) { |
| 553 | return; | 553 | return; |
| 554 | } | 554 | } |
| 555 | Settings::values.use_multi_core = !Settings::values.use_multi_core; | 555 | Settings::values.use_multi_core.SetValue(!Settings::values.use_multi_core.GetValue()); |
| 556 | bool is_async = | 556 | bool is_async = Settings::values.use_asynchronous_gpu_emulation.GetValue() || |
| 557 | Settings::values.use_asynchronous_gpu_emulation || Settings::values.use_multi_core; | 557 | Settings::values.use_multi_core.GetValue(); |
| 558 | Settings::values.use_asynchronous_gpu_emulation = is_async; | 558 | Settings::values.use_asynchronous_gpu_emulation.SetValue(is_async); |
| 559 | async_status_button->setChecked(Settings::values.use_asynchronous_gpu_emulation); | 559 | async_status_button->setChecked(Settings::values.use_asynchronous_gpu_emulation.GetValue()); |
| 560 | multicore_status_button->setChecked(Settings::values.use_multi_core); | 560 | multicore_status_button->setChecked(Settings::values.use_multi_core.GetValue()); |
| 561 | Settings::Apply(); | 561 | Settings::Apply(); |
| 562 | }); | 562 | }); |
| 563 | multicore_status_button->setText(tr("MULTICORE")); | 563 | multicore_status_button->setText(tr("MULTICORE")); |
| 564 | multicore_status_button->setCheckable(true); | 564 | multicore_status_button->setCheckable(true); |
| 565 | multicore_status_button->setChecked(Settings::values.use_multi_core); | 565 | multicore_status_button->setChecked(Settings::values.use_multi_core.GetValue()); |
| 566 | statusBar()->insertPermanentWidget(0, multicore_status_button); | 566 | statusBar()->insertPermanentWidget(0, multicore_status_button); |
| 567 | statusBar()->insertPermanentWidget(0, async_status_button); | 567 | statusBar()->insertPermanentWidget(0, async_status_button); |
| 568 | 568 | ||
| @@ -581,16 +581,16 @@ void GMainWindow::InitializeWidgets() { | |||
| 581 | renderer_status_button->setCheckable(false); | 581 | renderer_status_button->setCheckable(false); |
| 582 | renderer_status_button->setDisabled(true); | 582 | renderer_status_button->setDisabled(true); |
| 583 | #else | 583 | #else |
| 584 | renderer_status_button->setChecked(Settings::values.renderer_backend == | 584 | renderer_status_button->setChecked(Settings::values.renderer_backend.GetValue() == |
| 585 | Settings::RendererBackend::Vulkan); | 585 | Settings::RendererBackend::Vulkan); |
| 586 | connect(renderer_status_button, &QPushButton::clicked, [=] { | 586 | connect(renderer_status_button, &QPushButton::clicked, [=] { |
| 587 | if (emulation_running) { | 587 | if (emulation_running) { |
| 588 | return; | 588 | return; |
| 589 | } | 589 | } |
| 590 | if (renderer_status_button->isChecked()) { | 590 | if (renderer_status_button->isChecked()) { |
| 591 | Settings::values.renderer_backend = Settings::RendererBackend::Vulkan; | 591 | Settings::values.renderer_backend.SetValue(Settings::RendererBackend::Vulkan); |
| 592 | } else { | 592 | } else { |
| 593 | Settings::values.renderer_backend = Settings::RendererBackend::OpenGL; | 593 | Settings::values.renderer_backend.SetValue(Settings::RendererBackend::OpenGL); |
| 594 | } | 594 | } |
| 595 | 595 | ||
| 596 | Settings::Apply(); | 596 | Settings::Apply(); |
| @@ -727,21 +727,24 @@ void GMainWindow::InitializeHotkeys() { | |||
| 727 | }); | 727 | }); |
| 728 | connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Toggle Speed Limit"), this), | 728 | connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Toggle Speed Limit"), this), |
| 729 | &QShortcut::activated, this, [&] { | 729 | &QShortcut::activated, this, [&] { |
| 730 | Settings::values.use_frame_limit = !Settings::values.use_frame_limit; | 730 | Settings::values.use_frame_limit.SetValue( |
| 731 | !Settings::values.use_frame_limit.GetValue()); | ||
| 731 | UpdateStatusBar(); | 732 | UpdateStatusBar(); |
| 732 | }); | 733 | }); |
| 733 | constexpr u16 SPEED_LIMIT_STEP = 5; | 734 | constexpr u16 SPEED_LIMIT_STEP = 5; |
| 734 | connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Increase Speed Limit"), this), | 735 | connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Increase Speed Limit"), this), |
| 735 | &QShortcut::activated, this, [&] { | 736 | &QShortcut::activated, this, [&] { |
| 736 | if (Settings::values.frame_limit < 9999 - SPEED_LIMIT_STEP) { | 737 | if (Settings::values.frame_limit.GetValue() < 9999 - SPEED_LIMIT_STEP) { |
| 737 | Settings::values.frame_limit += SPEED_LIMIT_STEP; | 738 | Settings::values.frame_limit.SetValue(SPEED_LIMIT_STEP + |
| 739 | Settings::values.frame_limit.GetValue()); | ||
| 738 | UpdateStatusBar(); | 740 | UpdateStatusBar(); |
| 739 | } | 741 | } |
| 740 | }); | 742 | }); |
| 741 | connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Decrease Speed Limit"), this), | 743 | connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Decrease Speed Limit"), this), |
| 742 | &QShortcut::activated, this, [&] { | 744 | &QShortcut::activated, this, [&] { |
| 743 | if (Settings::values.frame_limit > SPEED_LIMIT_STEP) { | 745 | if (Settings::values.frame_limit.GetValue() > SPEED_LIMIT_STEP) { |
| 744 | Settings::values.frame_limit -= SPEED_LIMIT_STEP; | 746 | Settings::values.frame_limit.SetValue(Settings::values.frame_limit.GetValue() - |
| 747 | SPEED_LIMIT_STEP); | ||
| 745 | UpdateStatusBar(); | 748 | UpdateStatusBar(); |
| 746 | } | 749 | } |
| 747 | }); | 750 | }); |
| @@ -1039,6 +1042,17 @@ void GMainWindow::BootGame(const QString& filename) { | |||
| 1039 | LOG_INFO(Frontend, "yuzu starting..."); | 1042 | LOG_INFO(Frontend, "yuzu starting..."); |
| 1040 | StoreRecentFile(filename); // Put the filename on top of the list | 1043 | StoreRecentFile(filename); // Put the filename on top of the list |
| 1041 | 1044 | ||
| 1045 | u64 title_id{0}; | ||
| 1046 | |||
| 1047 | const auto v_file = Core::GetGameFileFromPath(vfs, filename.toUtf8().constData()); | ||
| 1048 | const auto loader = Loader::GetLoader(v_file); | ||
| 1049 | if (!(loader == nullptr || loader->ReadProgramId(title_id) != Loader::ResultStatus::Success)) { | ||
| 1050 | // Load per game settings | ||
| 1051 | Config per_game_config(fmt::format("{:016X}.ini", title_id), false); | ||
| 1052 | } | ||
| 1053 | |||
| 1054 | Settings::LogSettings(); | ||
| 1055 | |||
| 1042 | if (UISettings::values.select_user_on_boot) { | 1056 | if (UISettings::values.select_user_on_boot) { |
| 1043 | SelectAndSetCurrentUser(); | 1057 | SelectAndSetCurrentUser(); |
| 1044 | } | 1058 | } |
| @@ -1063,6 +1077,7 @@ void GMainWindow::BootGame(const QString& filename) { | |||
| 1063 | &LoadingScreen::OnLoadProgress, Qt::QueuedConnection); | 1077 | &LoadingScreen::OnLoadProgress, Qt::QueuedConnection); |
| 1064 | 1078 | ||
| 1065 | // Update the GUI | 1079 | // Update the GUI |
| 1080 | UpdateStatusButtons(); | ||
| 1066 | if (ui.action_Single_Window_Mode->isChecked()) { | 1081 | if (ui.action_Single_Window_Mode->isChecked()) { |
| 1067 | game_list->hide(); | 1082 | game_list->hide(); |
| 1068 | game_list_placeholder->hide(); | 1083 | game_list_placeholder->hide(); |
| @@ -1078,8 +1093,6 @@ void GMainWindow::BootGame(const QString& filename) { | |||
| 1078 | ui.centralwidget->setMouseTracking(true); | 1093 | ui.centralwidget->setMouseTracking(true); |
| 1079 | } | 1094 | } |
| 1080 | 1095 | ||
| 1081 | const u64 title_id = Core::System::GetInstance().CurrentProcess()->GetTitleID(); | ||
| 1082 | |||
| 1083 | std::string title_name; | 1096 | std::string title_name; |
| 1084 | std::string title_version; | 1097 | std::string title_version; |
| 1085 | const auto res = Core::System::GetInstance().GetGameName(title_name); | 1098 | const auto res = Core::System::GetInstance().GetGameName(title_name); |
| @@ -1521,7 +1534,7 @@ void GMainWindow::OnGameListOpenPerGameProperties(const std::string& file) { | |||
| 1521 | return; | 1534 | return; |
| 1522 | } | 1535 | } |
| 1523 | 1536 | ||
| 1524 | ConfigurePerGameGeneral dialog(this, title_id); | 1537 | ConfigurePerGame dialog(this, title_id); |
| 1525 | dialog.LoadFromFile(v_file); | 1538 | dialog.LoadFromFile(v_file); |
| 1526 | auto result = dialog.exec(); | 1539 | auto result = dialog.exec(); |
| 1527 | if (result == QDialog::Accepted) { | 1540 | if (result == QDialog::Accepted) { |
| @@ -1532,7 +1545,14 @@ void GMainWindow::OnGameListOpenPerGameProperties(const std::string& file) { | |||
| 1532 | game_list->PopulateAsync(UISettings::values.game_dirs); | 1545 | game_list->PopulateAsync(UISettings::values.game_dirs); |
| 1533 | } | 1546 | } |
| 1534 | 1547 | ||
| 1535 | config->Save(); | 1548 | // Do not cause the global config to write local settings into the config file |
| 1549 | Settings::RestoreGlobalState(); | ||
| 1550 | |||
| 1551 | if (!Core::System::GetInstance().IsPoweredOn()) { | ||
| 1552 | config->Save(); | ||
| 1553 | } | ||
| 1554 | } else { | ||
| 1555 | Settings::RestoreGlobalState(); | ||
| 1536 | } | 1556 | } |
| 1537 | } | 1557 | } |
| 1538 | 1558 | ||
| @@ -1819,6 +1839,9 @@ void GMainWindow::OnStopGame() { | |||
| 1819 | } | 1839 | } |
| 1820 | 1840 | ||
| 1821 | ShutdownGame(); | 1841 | ShutdownGame(); |
| 1842 | |||
| 1843 | Settings::RestoreGlobalState(); | ||
| 1844 | UpdateStatusButtons(); | ||
| 1822 | } | 1845 | } |
| 1823 | 1846 | ||
| 1824 | void GMainWindow::OnLoadComplete() { | 1847 | void GMainWindow::OnLoadComplete() { |
| @@ -1926,7 +1949,7 @@ void GMainWindow::ToggleWindowMode() { | |||
| 1926 | 1949 | ||
| 1927 | void GMainWindow::ResetWindowSize() { | 1950 | void GMainWindow::ResetWindowSize() { |
| 1928 | const auto aspect_ratio = Layout::EmulationAspectRatio( | 1951 | const auto aspect_ratio = Layout::EmulationAspectRatio( |
| 1929 | static_cast<Layout::AspectRatio>(Settings::values.aspect_ratio), | 1952 | static_cast<Layout::AspectRatio>(Settings::values.aspect_ratio.GetValue()), |
| 1930 | static_cast<float>(Layout::ScreenUndocked::Height) / Layout::ScreenUndocked::Width); | 1953 | static_cast<float>(Layout::ScreenUndocked::Height) / Layout::ScreenUndocked::Width); |
| 1931 | if (!ui.action_Single_Window_Mode->isChecked()) { | 1954 | if (!ui.action_Single_Window_Mode->isChecked()) { |
| 1932 | render_window->resize(Layout::ScreenUndocked::Height / aspect_ratio, | 1955 | render_window->resize(Layout::ScreenUndocked::Height / aspect_ratio, |
| @@ -1974,16 +1997,7 @@ void GMainWindow::OnConfigure() { | |||
| 1974 | ui.centralwidget->setMouseTracking(false); | 1997 | ui.centralwidget->setMouseTracking(false); |
| 1975 | } | 1998 | } |
| 1976 | 1999 | ||
| 1977 | dock_status_button->setChecked(Settings::values.use_docked_mode); | 2000 | UpdateStatusButtons(); |
| 1978 | multicore_status_button->setChecked(Settings::values.use_multi_core); | ||
| 1979 | Settings::values.use_asynchronous_gpu_emulation = | ||
| 1980 | Settings::values.use_asynchronous_gpu_emulation || Settings::values.use_multi_core; | ||
| 1981 | async_status_button->setChecked(Settings::values.use_asynchronous_gpu_emulation); | ||
| 1982 | |||
| 1983 | #ifdef HAS_VULKAN | ||
| 1984 | renderer_status_button->setChecked(Settings::values.renderer_backend == | ||
| 1985 | Settings::RendererBackend::Vulkan); | ||
| 1986 | #endif | ||
| 1987 | } | 2001 | } |
| 1988 | 2002 | ||
| 1989 | void GMainWindow::OnLoadAmiibo() { | 2003 | void GMainWindow::OnLoadAmiibo() { |
| @@ -2097,21 +2111,34 @@ void GMainWindow::UpdateStatusBar() { | |||
| 2097 | 2111 | ||
| 2098 | auto results = Core::System::GetInstance().GetAndResetPerfStats(); | 2112 | auto results = Core::System::GetInstance().GetAndResetPerfStats(); |
| 2099 | 2113 | ||
| 2100 | if (Settings::values.use_frame_limit) { | 2114 | if (Settings::values.use_frame_limit.GetValue()) { |
| 2101 | emu_speed_label->setText(tr("Speed: %1% / %2%") | 2115 | emu_speed_label->setText(tr("Speed: %1% / %2%") |
| 2102 | .arg(results.emulation_speed * 100.0, 0, 'f', 0) | 2116 | .arg(results.emulation_speed * 100.0, 0, 'f', 0) |
| 2103 | .arg(Settings::values.frame_limit)); | 2117 | .arg(Settings::values.frame_limit.GetValue())); |
| 2104 | } else { | 2118 | } else { |
| 2105 | emu_speed_label->setText(tr("Speed: %1%").arg(results.emulation_speed * 100.0, 0, 'f', 0)); | 2119 | emu_speed_label->setText(tr("Speed: %1%").arg(results.emulation_speed * 100.0, 0, 'f', 0)); |
| 2106 | } | 2120 | } |
| 2107 | game_fps_label->setText(tr("Game: %1 FPS").arg(results.game_fps, 0, 'f', 0)); | 2121 | game_fps_label->setText(tr("Game: %1 FPS").arg(results.game_fps, 0, 'f', 0)); |
| 2108 | emu_frametime_label->setText(tr("Frame: %1 ms").arg(results.frametime * 1000.0, 0, 'f', 2)); | 2122 | emu_frametime_label->setText(tr("Frame: %1 ms").arg(results.frametime * 1000.0, 0, 'f', 2)); |
| 2109 | 2123 | ||
| 2110 | emu_speed_label->setVisible(!Settings::values.use_multi_core); | 2124 | emu_speed_label->setVisible(!Settings::values.use_multi_core.GetValue()); |
| 2111 | game_fps_label->setVisible(true); | 2125 | game_fps_label->setVisible(true); |
| 2112 | emu_frametime_label->setVisible(true); | 2126 | emu_frametime_label->setVisible(true); |
| 2113 | } | 2127 | } |
| 2114 | 2128 | ||
| 2129 | void GMainWindow::UpdateStatusButtons() { | ||
| 2130 | dock_status_button->setChecked(Settings::values.use_docked_mode); | ||
| 2131 | multicore_status_button->setChecked(Settings::values.use_multi_core.GetValue()); | ||
| 2132 | Settings::values.use_asynchronous_gpu_emulation.SetValue( | ||
| 2133 | Settings::values.use_asynchronous_gpu_emulation.GetValue() || | ||
| 2134 | Settings::values.use_multi_core.GetValue()); | ||
| 2135 | async_status_button->setChecked(Settings::values.use_asynchronous_gpu_emulation.GetValue()); | ||
| 2136 | #ifdef HAS_VULKAN | ||
| 2137 | renderer_status_button->setChecked(Settings::values.renderer_backend.GetValue() == | ||
| 2138 | Settings::RendererBackend::Vulkan); | ||
| 2139 | #endif | ||
| 2140 | } | ||
| 2141 | |||
| 2115 | void GMainWindow::HideMouseCursor() { | 2142 | void GMainWindow::HideMouseCursor() { |
| 2116 | if (emu_thread == nullptr || UISettings::values.hide_mouse == false) { | 2143 | if (emu_thread == nullptr || UISettings::values.hide_mouse == false) { |
| 2117 | mouse_hide_timer.stop(); | 2144 | mouse_hide_timer.stop(); |
| @@ -2195,6 +2222,9 @@ void GMainWindow::OnCoreError(Core::System::ResultStatus result, std::string det | |||
| 2195 | if (answer == QMessageBox::Yes) { | 2222 | if (answer == QMessageBox::Yes) { |
| 2196 | if (emu_thread) { | 2223 | if (emu_thread) { |
| 2197 | ShutdownGame(); | 2224 | ShutdownGame(); |
| 2225 | |||
| 2226 | Settings::RestoreGlobalState(); | ||
| 2227 | UpdateStatusButtons(); | ||
| 2198 | } | 2228 | } |
| 2199 | } else { | 2229 | } else { |
| 2200 | // Only show the message if the game is still running. | 2230 | // Only show the message if the game is still running. |
| @@ -2357,9 +2387,13 @@ void GMainWindow::closeEvent(QCloseEvent* event) { | |||
| 2357 | hotkey_registry.SaveHotkeys(); | 2387 | hotkey_registry.SaveHotkeys(); |
| 2358 | 2388 | ||
| 2359 | // Shutdown session if the emu thread is active... | 2389 | // Shutdown session if the emu thread is active... |
| 2360 | if (emu_thread != nullptr) | 2390 | if (emu_thread != nullptr) { |
| 2361 | ShutdownGame(); | 2391 | ShutdownGame(); |
| 2362 | 2392 | ||
| 2393 | Settings::RestoreGlobalState(); | ||
| 2394 | UpdateStatusButtons(); | ||
| 2395 | } | ||
| 2396 | |||
| 2363 | render_window->close(); | 2397 | render_window->close(); |
| 2364 | 2398 | ||
| 2365 | QWidget::closeEvent(event); | 2399 | QWidget::closeEvent(event); |
| @@ -2539,8 +2573,6 @@ int main(int argc, char* argv[]) { | |||
| 2539 | QObject::connect(&app, &QGuiApplication::applicationStateChanged, &main_window, | 2573 | QObject::connect(&app, &QGuiApplication::applicationStateChanged, &main_window, |
| 2540 | &GMainWindow::OnAppFocusStateChanged); | 2574 | &GMainWindow::OnAppFocusStateChanged); |
| 2541 | 2575 | ||
| 2542 | Settings::LogSettings(); | ||
| 2543 | |||
| 2544 | int result = app.exec(); | 2576 | int result = app.exec(); |
| 2545 | detached_tasks.WaitForAllTasks(); | 2577 | detached_tasks.WaitForAllTasks(); |
| 2546 | return result; | 2578 | return result; |
diff --git a/src/yuzu/main.h b/src/yuzu/main.h index 66c84e5c0..8e3d39c38 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h | |||
| @@ -221,6 +221,7 @@ private: | |||
| 221 | void UpdateWindowTitle(const std::string& title_name = {}, | 221 | void UpdateWindowTitle(const std::string& title_name = {}, |
| 222 | const std::string& title_version = {}); | 222 | const std::string& title_version = {}); |
| 223 | void UpdateStatusBar(); | 223 | void UpdateStatusBar(); |
| 224 | void UpdateStatusButtons(); | ||
| 224 | void HideMouseCursor(); | 225 | void HideMouseCursor(); |
| 225 | void ShowMouseCursor(); | 226 | void ShowMouseCursor(); |
| 226 | void OpenURL(const QUrl& url); | 227 | void OpenURL(const QUrl& url); |
diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp index 659b9f701..23763144f 100644 --- a/src/yuzu_cmd/config.cpp +++ b/src/yuzu_cmd/config.cpp | |||
| @@ -354,63 +354,72 @@ void Config::ReadValues() { | |||
| 354 | 354 | ||
| 355 | const auto rng_seed_enabled = sdl2_config->GetBoolean("System", "rng_seed_enabled", false); | 355 | const auto rng_seed_enabled = sdl2_config->GetBoolean("System", "rng_seed_enabled", false); |
| 356 | if (rng_seed_enabled) { | 356 | if (rng_seed_enabled) { |
| 357 | Settings::values.rng_seed = sdl2_config->GetInteger("System", "rng_seed", 0); | 357 | Settings::values.rng_seed.SetValue(sdl2_config->GetInteger("System", "rng_seed", 0)); |
| 358 | } else { | 358 | } else { |
| 359 | Settings::values.rng_seed = std::nullopt; | 359 | Settings::values.rng_seed.SetValue(std::nullopt); |
| 360 | } | 360 | } |
| 361 | 361 | ||
| 362 | const auto custom_rtc_enabled = sdl2_config->GetBoolean("System", "custom_rtc_enabled", false); | 362 | const auto custom_rtc_enabled = sdl2_config->GetBoolean("System", "custom_rtc_enabled", false); |
| 363 | if (custom_rtc_enabled) { | 363 | if (custom_rtc_enabled) { |
| 364 | Settings::values.custom_rtc = | 364 | Settings::values.custom_rtc.SetValue( |
| 365 | std::chrono::seconds(sdl2_config->GetInteger("System", "custom_rtc", 0)); | 365 | std::chrono::seconds(sdl2_config->GetInteger("System", "custom_rtc", 0))); |
| 366 | } else { | 366 | } else { |
| 367 | Settings::values.custom_rtc = std::nullopt; | 367 | Settings::values.custom_rtc.SetValue(std::nullopt); |
| 368 | } | 368 | } |
| 369 | 369 | ||
| 370 | Settings::values.language_index = sdl2_config->GetInteger("System", "language_index", 1); | 370 | Settings::values.language_index.SetValue( |
| 371 | Settings::values.time_zone_index = sdl2_config->GetInteger("System", "time_zone_index", 0); | 371 | sdl2_config->GetInteger("System", "language_index", 1)); |
| 372 | Settings::values.time_zone_index.SetValue( | ||
| 373 | sdl2_config->GetInteger("System", "time_zone_index", 0)); | ||
| 372 | 374 | ||
| 373 | // Core | 375 | // Core |
| 374 | Settings::values.use_multi_core = sdl2_config->GetBoolean("Core", "use_multi_core", false); | 376 | Settings::values.use_multi_core.SetValue( |
| 377 | sdl2_config->GetBoolean("Core", "use_multi_core", false)); | ||
| 375 | 378 | ||
| 376 | // Renderer | 379 | // Renderer |
| 377 | const int renderer_backend = sdl2_config->GetInteger( | 380 | const int renderer_backend = sdl2_config->GetInteger( |
| 378 | "Renderer", "backend", static_cast<int>(Settings::RendererBackend::OpenGL)); | 381 | "Renderer", "backend", static_cast<int>(Settings::RendererBackend::OpenGL)); |
| 379 | Settings::values.renderer_backend = static_cast<Settings::RendererBackend>(renderer_backend); | 382 | Settings::values.renderer_backend.SetValue( |
| 383 | static_cast<Settings::RendererBackend>(renderer_backend)); | ||
| 380 | Settings::values.renderer_debug = sdl2_config->GetBoolean("Renderer", "debug", false); | 384 | Settings::values.renderer_debug = sdl2_config->GetBoolean("Renderer", "debug", false); |
| 381 | Settings::values.vulkan_device = sdl2_config->GetInteger("Renderer", "vulkan_device", 0); | 385 | Settings::values.vulkan_device.SetValue( |
| 382 | 386 | sdl2_config->GetInteger("Renderer", "vulkan_device", 0)); | |
| 383 | Settings::values.aspect_ratio = | 387 | |
| 384 | static_cast<int>(sdl2_config->GetInteger("Renderer", "aspect_ratio", 0)); | 388 | Settings::values.aspect_ratio.SetValue( |
| 385 | Settings::values.max_anisotropy = | 389 | static_cast<int>(sdl2_config->GetInteger("Renderer", "aspect_ratio", 0))); |
| 386 | static_cast<int>(sdl2_config->GetInteger("Renderer", "max_anisotropy", 0)); | 390 | Settings::values.max_anisotropy.SetValue( |
| 387 | Settings::values.use_frame_limit = sdl2_config->GetBoolean("Renderer", "use_frame_limit", true); | 391 | static_cast<int>(sdl2_config->GetInteger("Renderer", "max_anisotropy", 0))); |
| 388 | Settings::values.frame_limit = | 392 | Settings::values.use_frame_limit.SetValue( |
| 389 | static_cast<u16>(sdl2_config->GetInteger("Renderer", "frame_limit", 100)); | 393 | sdl2_config->GetBoolean("Renderer", "use_frame_limit", true)); |
| 390 | Settings::values.use_disk_shader_cache = | 394 | Settings::values.frame_limit.SetValue( |
| 391 | sdl2_config->GetBoolean("Renderer", "use_disk_shader_cache", false); | 395 | static_cast<u16>(sdl2_config->GetInteger("Renderer", "frame_limit", 100))); |
| 396 | Settings::values.use_disk_shader_cache.SetValue( | ||
| 397 | sdl2_config->GetBoolean("Renderer", "use_disk_shader_cache", false)); | ||
| 392 | const int gpu_accuracy_level = sdl2_config->GetInteger("Renderer", "gpu_accuracy", 0); | 398 | const int gpu_accuracy_level = sdl2_config->GetInteger("Renderer", "gpu_accuracy", 0); |
| 393 | Settings::values.gpu_accuracy = static_cast<Settings::GPUAccuracy>(gpu_accuracy_level); | 399 | Settings::values.gpu_accuracy.SetValue(static_cast<Settings::GPUAccuracy>(gpu_accuracy_level)); |
| 394 | Settings::values.use_asynchronous_gpu_emulation = | 400 | Settings::values.use_asynchronous_gpu_emulation.SetValue( |
| 395 | sdl2_config->GetBoolean("Renderer", "use_asynchronous_gpu_emulation", false); | 401 | sdl2_config->GetBoolean("Renderer", "use_asynchronous_gpu_emulation", false)); |
| 396 | Settings::values.use_vsync = | 402 | Settings::values.use_vsync.SetValue( |
| 397 | static_cast<u16>(sdl2_config->GetInteger("Renderer", "use_vsync", 1)); | 403 | static_cast<u16>(sdl2_config->GetInteger("Renderer", "use_vsync", 1))); |
| 398 | Settings::values.use_assembly_shaders = | 404 | Settings::values.use_assembly_shaders.SetValue( |
| 399 | sdl2_config->GetBoolean("Renderer", "use_assembly_shaders", false); | 405 | sdl2_config->GetBoolean("Renderer", "use_assembly_shaders", false)); |
| 400 | Settings::values.use_fast_gpu_time = | 406 | Settings::values.use_fast_gpu_time.SetValue( |
| 401 | sdl2_config->GetBoolean("Renderer", "use_fast_gpu_time", true); | 407 | sdl2_config->GetBoolean("Renderer", "use_fast_gpu_time", true)); |
| 402 | 408 | ||
| 403 | Settings::values.bg_red = static_cast<float>(sdl2_config->GetReal("Renderer", "bg_red", 0.0)); | 409 | Settings::values.bg_red.SetValue( |
| 404 | Settings::values.bg_green = | 410 | static_cast<float>(sdl2_config->GetReal("Renderer", "bg_red", 0.0))); |
| 405 | static_cast<float>(sdl2_config->GetReal("Renderer", "bg_green", 0.0)); | 411 | Settings::values.bg_green.SetValue( |
| 406 | Settings::values.bg_blue = static_cast<float>(sdl2_config->GetReal("Renderer", "bg_blue", 0.0)); | 412 | static_cast<float>(sdl2_config->GetReal("Renderer", "bg_green", 0.0))); |
| 413 | Settings::values.bg_blue.SetValue( | ||
| 414 | static_cast<float>(sdl2_config->GetReal("Renderer", "bg_blue", 0.0))); | ||
| 407 | 415 | ||
| 408 | // Audio | 416 | // Audio |
| 409 | Settings::values.sink_id = sdl2_config->Get("Audio", "output_engine", "auto"); | 417 | Settings::values.sink_id = sdl2_config->Get("Audio", "output_engine", "auto"); |
| 410 | Settings::values.enable_audio_stretching = | 418 | Settings::values.enable_audio_stretching.SetValue( |
| 411 | sdl2_config->GetBoolean("Audio", "enable_audio_stretching", true); | 419 | sdl2_config->GetBoolean("Audio", "enable_audio_stretching", true)); |
| 412 | Settings::values.audio_device_id = sdl2_config->Get("Audio", "output_device", "auto"); | 420 | Settings::values.audio_device_id = sdl2_config->Get("Audio", "output_device", "auto"); |
| 413 | Settings::values.volume = static_cast<float>(sdl2_config->GetReal("Audio", "volume", 1)); | 421 | Settings::values.volume.SetValue( |
| 422 | static_cast<float>(sdl2_config->GetReal("Audio", "volume", 1))); | ||
| 414 | 423 | ||
| 415 | // Miscellaneous | 424 | // Miscellaneous |
| 416 | Settings::values.log_filter = sdl2_config->Get("Miscellaneous", "log_filter", "*:Trace"); | 425 | Settings::values.log_filter = sdl2_config->Get("Miscellaneous", "log_filter", "*:Trace"); |
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp index 09cc0a3b5..e78025737 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp | |||
| @@ -165,7 +165,7 @@ std::unique_ptr<Core::Frontend::GraphicsContext> EmuWindow_SDL2_GL::CreateShared | |||
| 165 | 165 | ||
| 166 | void EmuWindow_SDL2_GL::Present() { | 166 | void EmuWindow_SDL2_GL::Present() { |
| 167 | SDL_GL_MakeCurrent(render_window, window_context); | 167 | SDL_GL_MakeCurrent(render_window, window_context); |
| 168 | SDL_GL_SetSwapInterval(Settings::values.use_vsync ? 1 : 0); | 168 | SDL_GL_SetSwapInterval(Settings::values.use_vsync.GetValue() ? 1 : 0); |
| 169 | while (IsOpen()) { | 169 | while (IsOpen()) { |
| 170 | system.Renderer().TryPresent(100); | 170 | system.Renderer().TryPresent(100); |
| 171 | SDL_GL_SwapWindow(render_window); | 171 | SDL_GL_SwapWindow(render_window); |
diff --git a/src/yuzu_cmd/yuzu.cpp b/src/yuzu_cmd/yuzu.cpp index e6c6a839d..512b060a7 100644 --- a/src/yuzu_cmd/yuzu.cpp +++ b/src/yuzu_cmd/yuzu.cpp | |||
| @@ -181,7 +181,7 @@ int main(int argc, char** argv) { | |||
| 181 | Core::System& system{Core::System::GetInstance()}; | 181 | Core::System& system{Core::System::GetInstance()}; |
| 182 | 182 | ||
| 183 | std::unique_ptr<EmuWindow_SDL2> emu_window; | 183 | std::unique_ptr<EmuWindow_SDL2> emu_window; |
| 184 | switch (Settings::values.renderer_backend) { | 184 | switch (Settings::values.renderer_backend.GetValue()) { |
| 185 | case Settings::RendererBackend::OpenGL: | 185 | case Settings::RendererBackend::OpenGL: |
| 186 | emu_window = std::make_unique<EmuWindow_SDL2_GL>(system, fullscreen); | 186 | emu_window = std::make_unique<EmuWindow_SDL2_GL>(system, fullscreen); |
| 187 | break; | 187 | break; |
diff --git a/src/yuzu_tester/config.cpp b/src/yuzu_tester/config.cpp index 1566c2e3f..acb22885e 100644 --- a/src/yuzu_tester/config.cpp +++ b/src/yuzu_tester/config.cpp | |||
| @@ -81,6 +81,9 @@ void Config::ReadValues() { | |||
| 81 | Settings::values.touchscreen.diameter_x = 15; | 81 | Settings::values.touchscreen.diameter_x = 15; |
| 82 | Settings::values.touchscreen.diameter_y = 15; | 82 | Settings::values.touchscreen.diameter_y = 15; |
| 83 | 83 | ||
| 84 | Settings::values.use_docked_mode = | ||
| 85 | sdl2_config->GetBoolean("Controls", "use_docked_mode", false); | ||
| 86 | |||
| 84 | // Data Storage | 87 | // Data Storage |
| 85 | Settings::values.use_virtual_sd = | 88 | Settings::values.use_virtual_sd = |
| 86 | sdl2_config->GetBoolean("Data Storage", "use_virtual_sd", true); | 89 | sdl2_config->GetBoolean("Data Storage", "use_virtual_sd", true); |
| @@ -92,57 +95,59 @@ void Config::ReadValues() { | |||
| 92 | FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir))); | 95 | FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir))); |
| 93 | 96 | ||
| 94 | // System | 97 | // System |
| 95 | Settings::values.use_docked_mode = sdl2_config->GetBoolean("System", "use_docked_mode", false); | ||
| 96 | |||
| 97 | Settings::values.current_user = std::clamp<int>( | 98 | Settings::values.current_user = std::clamp<int>( |
| 98 | sdl2_config->GetInteger("System", "current_user", 0), 0, Service::Account::MAX_USERS - 1); | 99 | sdl2_config->GetInteger("System", "current_user", 0), 0, Service::Account::MAX_USERS - 1); |
| 99 | 100 | ||
| 100 | const auto rng_seed_enabled = sdl2_config->GetBoolean("System", "rng_seed_enabled", false); | 101 | const auto rng_seed_enabled = sdl2_config->GetBoolean("System", "rng_seed_enabled", false); |
| 101 | if (rng_seed_enabled) { | 102 | if (rng_seed_enabled) { |
| 102 | Settings::values.rng_seed = sdl2_config->GetInteger("System", "rng_seed", 0); | 103 | Settings::values.rng_seed.SetValue(sdl2_config->GetInteger("System", "rng_seed", 0)); |
| 103 | } else { | 104 | } else { |
| 104 | Settings::values.rng_seed = std::nullopt; | 105 | Settings::values.rng_seed.SetValue(std::nullopt); |
| 105 | } | 106 | } |
| 106 | 107 | ||
| 107 | const auto custom_rtc_enabled = sdl2_config->GetBoolean("System", "custom_rtc_enabled", false); | 108 | const auto custom_rtc_enabled = sdl2_config->GetBoolean("System", "custom_rtc_enabled", false); |
| 108 | if (custom_rtc_enabled) { | 109 | if (custom_rtc_enabled) { |
| 109 | Settings::values.custom_rtc = | 110 | Settings::values.custom_rtc.SetValue( |
| 110 | std::chrono::seconds(sdl2_config->GetInteger("System", "custom_rtc", 0)); | 111 | std::chrono::seconds(sdl2_config->GetInteger("System", "custom_rtc", 0))); |
| 111 | } else { | 112 | } else { |
| 112 | Settings::values.custom_rtc = std::nullopt; | 113 | Settings::values.custom_rtc.SetValue(std::nullopt); |
| 113 | } | 114 | } |
| 114 | 115 | ||
| 115 | // Core | 116 | // Core |
| 116 | Settings::values.use_multi_core = sdl2_config->GetBoolean("Core", "use_multi_core", false); | 117 | Settings::values.use_multi_core.SetValue( |
| 118 | sdl2_config->GetBoolean("Core", "use_multi_core", false)); | ||
| 117 | 119 | ||
| 118 | // Renderer | 120 | // Renderer |
| 119 | Settings::values.aspect_ratio = | 121 | Settings::values.aspect_ratio.SetValue( |
| 120 | static_cast<int>(sdl2_config->GetInteger("Renderer", "aspect_ratio", 0)); | 122 | static_cast<int>(sdl2_config->GetInteger("Renderer", "aspect_ratio", 0))); |
| 121 | Settings::values.max_anisotropy = | 123 | Settings::values.max_anisotropy.SetValue( |
| 122 | static_cast<int>(sdl2_config->GetInteger("Renderer", "max_anisotropy", 0)); | 124 | static_cast<int>(sdl2_config->GetInteger("Renderer", "max_anisotropy", 0))); |
| 123 | Settings::values.use_frame_limit = false; | 125 | Settings::values.use_frame_limit.SetValue(false); |
| 124 | Settings::values.frame_limit = 100; | 126 | Settings::values.frame_limit.SetValue(100); |
| 125 | Settings::values.use_disk_shader_cache = | 127 | Settings::values.use_disk_shader_cache.SetValue( |
| 126 | sdl2_config->GetBoolean("Renderer", "use_disk_shader_cache", false); | 128 | sdl2_config->GetBoolean("Renderer", "use_disk_shader_cache", false)); |
| 127 | const int gpu_accuracy_level = sdl2_config->GetInteger("Renderer", "gpu_accuracy", 0); | 129 | const int gpu_accuracy_level = sdl2_config->GetInteger("Renderer", "gpu_accuracy", 0); |
| 128 | Settings::values.gpu_accuracy = static_cast<Settings::GPUAccuracy>(gpu_accuracy_level); | 130 | Settings::values.gpu_accuracy.SetValue(static_cast<Settings::GPUAccuracy>(gpu_accuracy_level)); |
| 129 | Settings::values.use_asynchronous_gpu_emulation = | 131 | Settings::values.use_asynchronous_gpu_emulation.SetValue( |
| 130 | sdl2_config->GetBoolean("Renderer", "use_asynchronous_gpu_emulation", false); | 132 | sdl2_config->GetBoolean("Renderer", "use_asynchronous_gpu_emulation", false)); |
| 131 | Settings::values.use_fast_gpu_time = | 133 | Settings::values.use_fast_gpu_time.SetValue( |
| 132 | sdl2_config->GetBoolean("Renderer", "use_fast_gpu_time", true); | 134 | sdl2_config->GetBoolean("Renderer", "use_fast_gpu_time", true)); |
| 133 | 135 | ||
| 134 | Settings::values.bg_red = static_cast<float>(sdl2_config->GetReal("Renderer", "bg_red", 0.0)); | 136 | Settings::values.bg_red.SetValue( |
| 135 | Settings::values.bg_green = | 137 | static_cast<float>(sdl2_config->GetReal("Renderer", "bg_red", 0.0))); |
| 136 | static_cast<float>(sdl2_config->GetReal("Renderer", "bg_green", 0.0)); | 138 | Settings::values.bg_green.SetValue( |
| 137 | Settings::values.bg_blue = static_cast<float>(sdl2_config->GetReal("Renderer", "bg_blue", 0.0)); | 139 | static_cast<float>(sdl2_config->GetReal("Renderer", "bg_green", 0.0))); |
| 140 | Settings::values.bg_blue.SetValue( | ||
| 141 | static_cast<float>(sdl2_config->GetReal("Renderer", "bg_blue", 0.0))); | ||
| 138 | 142 | ||
| 139 | // Audio | 143 | // Audio |
| 140 | Settings::values.sink_id = "null"; | 144 | Settings::values.sink_id = "null"; |
| 141 | Settings::values.enable_audio_stretching = false; | 145 | Settings::values.enable_audio_stretching.SetValue(false); |
| 142 | Settings::values.audio_device_id = "auto"; | 146 | Settings::values.audio_device_id = "auto"; |
| 143 | Settings::values.volume = 0; | 147 | Settings::values.volume.SetValue(0); |
| 144 | 148 | ||
| 145 | Settings::values.language_index = sdl2_config->GetInteger("System", "language_index", 1); | 149 | Settings::values.language_index.SetValue( |
| 150 | sdl2_config->GetInteger("System", "language_index", 1)); | ||
| 146 | 151 | ||
| 147 | // Miscellaneous | 152 | // Miscellaneous |
| 148 | Settings::values.log_filter = sdl2_config->Get("Miscellaneous", "log_filter", "*:Trace"); | 153 | Settings::values.log_filter = sdl2_config->Get("Miscellaneous", "log_filter", "*:Trace"); |