mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-30 21:30:04 +00:00 
			
		
		
		
	Add per game configuration options (#6187)
* common: Move settings to common from core. - Removes a dependency on core and input_common from common. * code: Wrap settings values * Port from yuzu to allow per game settings * citra_qt: Initial per-game settings dialog * citra_qt: Use new API for read/save of config values * citra_qt: Per game audio settings * citra_qt: Per game graphics settings * citra_qt: Per game system settings * citra_qt: Per game general settings * citra_qt: Document and run clang format * citra_qt: Make icon smaller and centered * citra_qt: Remove version number * Not sure how to extract that, can always add it back later * citra_qt: Wrap UISettings * citra_qt: Fix unthottled fps setting * citra_qt: Remove margin in emulation tab * citra_qt: Implement some suggestions * Bring back speed switch hotkey * Allow configuration when game is running * Rename/adjust UI stuff * citra_qt: Fix build with separate windows * citra_qt: Address feedback * citra_qt: Log per-game settings before launching games * citra_qt: Add shader cache options * Also fix android build * citra_qt: Add DLC menu option * citra_qt: Run clang-format * citra_qt: Adjust for time offset * citra_qt: Implement suggestions * Run clang-format Co-authored-by: bunnei <bunneidev@gmail.com>
This commit is contained in:
		
							parent
							
								
									f261daf2fa
								
							
						
					
					
						commit
						48ee112ceb
					
				
					 92 changed files with 3171 additions and 1546 deletions
				
			
		|  | @ -8,7 +8,7 @@ import org.citra.citra_emu.CitraApplication; | ||||||
| public class EmulationMenuSettings { | public class EmulationMenuSettings { | ||||||
|     private static SharedPreferences mPreferences = PreferenceManager.getDefaultSharedPreferences(CitraApplication.getAppContext()); |     private static SharedPreferences mPreferences = PreferenceManager.getDefaultSharedPreferences(CitraApplication.getAppContext()); | ||||||
| 
 | 
 | ||||||
|     // These must match what is defined in src/core/settings.h |     // These must match what is defined in src/common/settings.h | ||||||
|     public static final int LayoutOption_Default = 0; |     public static final int LayoutOption_Default = 0; | ||||||
|     public static final int LayoutOption_SingleScreen = 1; |     public static final int LayoutOption_SingleScreen = 1; | ||||||
|     public static final int LayoutOption_LargeScreen = 2; |     public static final int LayoutOption_LargeScreen = 2; | ||||||
|  |  | ||||||
|  | @ -11,10 +11,10 @@ | ||||||
| #include "common/file_util.h" | #include "common/file_util.h" | ||||||
| #include "common/logging/log.h" | #include "common/logging/log.h" | ||||||
| #include "common/param_package.h" | #include "common/param_package.h" | ||||||
|  | #include "common/settings.h" | ||||||
| #include "core/core.h" | #include "core/core.h" | ||||||
| #include "core/hle/service/cfg/cfg.h" | #include "core/hle/service/cfg/cfg.h" | ||||||
| #include "core/hle/service/service.h" | #include "core/hle/service/service.h" | ||||||
| #include "core/settings.h" |  | ||||||
| #include "input_common/main.h" | #include "input_common/main.h" | ||||||
| #include "input_common/udp/client.h" | #include "input_common/udp/client.h" | ||||||
| #include "jni/camera/ndk_camera.h" | #include "jni/camera/ndk_camera.h" | ||||||
|  | @ -139,9 +139,9 @@ void Config::ReadValues() { | ||||||
|     Settings::values.factor_3d = |     Settings::values.factor_3d = | ||||||
|         static_cast<u8>(sdl2_config->GetInteger("Renderer", "factor_3d", 0)); |         static_cast<u8>(sdl2_config->GetInteger("Renderer", "factor_3d", 0)); | ||||||
|     std::string default_shader = "none (builtin)"; |     std::string default_shader = "none (builtin)"; | ||||||
|     if (Settings::values.render_3d == Settings::StereoRenderOption::Anaglyph) |     if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Anaglyph) | ||||||
|         default_shader = "dubois (builtin)"; |         default_shader = "dubois (builtin)"; | ||||||
|     else if (Settings::values.render_3d == Settings::StereoRenderOption::Interlaced) |     else if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Interlaced) | ||||||
|         default_shader = "horizontal (builtin)"; |         default_shader = "horizontal (builtin)"; | ||||||
|     Settings::values.pp_shader_name = |     Settings::values.pp_shader_name = | ||||||
|         sdl2_config->GetString("Renderer", "pp_shader_name", default_shader); |         sdl2_config->GetString("Renderer", "pp_shader_name", default_shader); | ||||||
|  | @ -186,9 +186,9 @@ void Config::ReadValues() { | ||||||
|         sdl2_config->GetBoolean("Utility", "preload_textures", false); |         sdl2_config->GetBoolean("Utility", "preload_textures", false); | ||||||
| 
 | 
 | ||||||
|     // Audio
 |     // Audio
 | ||||||
|     Settings::values.enable_dsp_lle = sdl2_config->GetBoolean("Audio", "enable_dsp_lle", false); |     Settings::values.audio_emulation = | ||||||
|     Settings::values.enable_dsp_lle_multithread = |         static_cast<Settings::AudioEmulation>(sdl2_config->GetInteger( | ||||||
|         sdl2_config->GetBoolean("Audio", "enable_dsp_lle_multithread", false); |             "Audio", "audio_emulation", static_cast<int>(Settings::AudioEmulation::HLE))); | ||||||
|     Settings::values.sink_id = sdl2_config->GetString("Audio", "output_engine", "auto"); |     Settings::values.sink_id = sdl2_config->GetString("Audio", "output_engine", "auto"); | ||||||
|     Settings::values.enable_audio_stretching = |     Settings::values.enable_audio_stretching = | ||||||
|         sdl2_config->GetBoolean("Audio", "enable_audio_stretching", true); |         sdl2_config->GetBoolean("Audio", "enable_audio_stretching", true); | ||||||
|  |  | ||||||
|  | @ -11,7 +11,7 @@ | ||||||
| #include <glad/glad.h> | #include <glad/glad.h> | ||||||
| 
 | 
 | ||||||
| #include "common/logging/log.h" | #include "common/logging/log.h" | ||||||
| #include "core/settings.h" | #include "common/settings.h" | ||||||
| #include "input_common/main.h" | #include "input_common/main.h" | ||||||
| #include "jni/emu_window/emu_window.h" | #include "jni/emu_window/emu_window.h" | ||||||
| #include "jni/id_cache.h" | #include "jni/id_cache.h" | ||||||
|  |  | ||||||
|  | @ -2,7 +2,7 @@ | ||||||
| // Licensed under GPLv2 or any later version
 | // Licensed under GPLv2 or any later version
 | ||||||
| // Refer to the license.txt file included.
 | // Refer to the license.txt file included.
 | ||||||
| 
 | 
 | ||||||
| #include "core/settings.h" | #include "common/settings.h" | ||||||
| 
 | 
 | ||||||
| namespace GameSettings { | namespace GameSettings { | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -6,7 +6,7 @@ | ||||||
| #include "common/logging/backend.h" | #include "common/logging/backend.h" | ||||||
| #include "common/logging/filter.h" | #include "common/logging/filter.h" | ||||||
| #include "common/logging/log.h" | #include "common/logging/log.h" | ||||||
| #include "core/settings.h" | #include "common/settings.h" | ||||||
| #include "jni/applets/mii_selector.h" | #include "jni/applets/mii_selector.h" | ||||||
| #include "jni/applets/swkbd.h" | #include "jni/applets/swkbd.h" | ||||||
| #include "jni/camera/still_image_camera.h" | #include "jni/camera/still_image_camera.h" | ||||||
|  | @ -156,7 +156,7 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved) { | ||||||
| 
 | 
 | ||||||
|     // Initialize Logger
 |     // Initialize Logger
 | ||||||
|     Log::Filter log_filter; |     Log::Filter log_filter; | ||||||
|     log_filter.ParseFilterString(Settings::values.log_filter); |     log_filter.ParseFilterString(Settings::values.log_filter.GetValue()); | ||||||
|     Log::SetGlobalFilter(log_filter); |     Log::SetGlobalFilter(log_filter); | ||||||
|     Log::AddBackend(std::make_unique<Log::LogcatBackend>()); |     Log::AddBackend(std::make_unique<Log::LogcatBackend>()); | ||||||
|     FileUtil::CreateFullPath(FileUtil::GetUserPath(FileUtil::UserPath::LogDir)); |     FileUtil::CreateFullPath(FileUtil::GetUserPath(FileUtil::UserPath::LogDir)); | ||||||
|  |  | ||||||
|  | @ -17,6 +17,7 @@ | ||||||
| #include "common/microprofile.h" | #include "common/microprofile.h" | ||||||
| #include "common/scm_rev.h" | #include "common/scm_rev.h" | ||||||
| #include "common/scope_exit.h" | #include "common/scope_exit.h" | ||||||
|  | #include "common/settings.h" | ||||||
| #include "common/string_util.h" | #include "common/string_util.h" | ||||||
| #include "core/core.h" | #include "core/core.h" | ||||||
| #include "core/frontend/applets/default_applets.h" | #include "core/frontend/applets/default_applets.h" | ||||||
|  | @ -26,7 +27,6 @@ | ||||||
| #include "core/hle/service/am/am.h" | #include "core/hle/service/am/am.h" | ||||||
| #include "core/hle/service/nfc/nfc.h" | #include "core/hle/service/nfc/nfc.h" | ||||||
| #include "core/savestate.h" | #include "core/savestate.h" | ||||||
| #include "core/settings.h" |  | ||||||
| #include "jni/android_common/android_common.h" | #include "jni/android_common/android_common.h" | ||||||
| #include "jni/applets/mii_selector.h" | #include "jni/applets/mii_selector.h" | ||||||
| #include "jni/applets/swkbd.h" | #include "jni/applets/swkbd.h" | ||||||
|  | @ -238,7 +238,7 @@ static Core::System::ResultStatus RunCitra(const std::string& filepath) { | ||||||
|             } |             } | ||||||
|         } else { |         } else { | ||||||
|             // Ensure no audio bleeds out while game is paused
 |             // Ensure no audio bleeds out while game is paused
 | ||||||
|             const float volume = Settings::values.volume; |             const float volume = Settings::values.volume.GetValue(); | ||||||
|             SCOPE_EXIT({ Settings::values.volume = volume; }); |             SCOPE_EXIT({ Settings::values.volume = volume; }); | ||||||
|             Settings::values.volume = 0; |             Settings::values.volume = 0; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -7,17 +7,18 @@ | ||||||
| #include "audio_core/sink.h" | #include "audio_core/sink.h" | ||||||
| #include "audio_core/sink_details.h" | #include "audio_core/sink_details.h" | ||||||
| #include "common/assert.h" | #include "common/assert.h" | ||||||
|  | #include "common/settings.h" | ||||||
| #include "core/core.h" | #include "core/core.h" | ||||||
| #include "core/dumping/backend.h" | #include "core/dumping/backend.h" | ||||||
| #include "core/settings.h" |  | ||||||
| 
 | 
 | ||||||
| namespace AudioCore { | namespace AudioCore { | ||||||
| 
 | 
 | ||||||
| DspInterface::DspInterface() = default; | DspInterface::DspInterface() = default; | ||||||
| DspInterface::~DspInterface() = default; | DspInterface::~DspInterface() = default; | ||||||
| 
 | 
 | ||||||
| void DspInterface::SetSink(const std::string& sink_id, const std::string& audio_device) { | void DspInterface::SetSink(std::string_view sink_id, std::string_view audio_device) { | ||||||
|     sink = CreateSinkFromID(Settings::values.sink_id, Settings::values.audio_device_id); |     sink = CreateSinkFromID(Settings::values.sink_id.GetValue(), | ||||||
|  |                             Settings::values.audio_device_id.GetValue()); | ||||||
|     sink->SetCallback( |     sink->SetCallback( | ||||||
|         [this](s16* buffer, std::size_t num_frames) { OutputCallback(buffer, num_frames); }); |         [this](s16* buffer, std::size_t num_frames) { OutputCallback(buffer, num_frames); }); | ||||||
|     time_stretcher.SetOutputSampleRate(sink->GetNativeSampleRate()); |     time_stretcher.SetOutputSampleRate(sink->GetNativeSampleRate()); | ||||||
|  |  | ||||||
|  | @ -94,7 +94,7 @@ public: | ||||||
|     virtual void UnloadComponent() = 0; |     virtual void UnloadComponent() = 0; | ||||||
| 
 | 
 | ||||||
|     /// Select the sink to use based on sink id.
 |     /// Select the sink to use based on sink id.
 | ||||||
|     void SetSink(const std::string& sink_id, const std::string& audio_device); |     void SetSink(std::string_view sink_id, std::string_view audio_device); | ||||||
|     /// Get the current sink
 |     /// Get the current sink
 | ||||||
|     Sink& GetSink(); |     Sink& GetSink(); | ||||||
|     /// Enable/Disable audio stretching.
 |     /// Enable/Disable audio stretching.
 | ||||||
|  |  | ||||||
|  | @ -22,6 +22,7 @@ | ||||||
| #include "common/logging/log.h" | #include "common/logging/log.h" | ||||||
| #include "common/scm_rev.h" | #include "common/scm_rev.h" | ||||||
| #include "common/scope_exit.h" | #include "common/scope_exit.h" | ||||||
|  | #include "common/settings.h" | ||||||
| #include "common/string_util.h" | #include "common/string_util.h" | ||||||
| #include "core/core.h" | #include "core/core.h" | ||||||
| #include "core/dumping/backend.h" | #include "core/dumping/backend.h" | ||||||
|  | @ -34,7 +35,6 @@ | ||||||
| #include "core/hle/service/cfg/cfg.h" | #include "core/hle/service/cfg/cfg.h" | ||||||
| #include "core/loader/loader.h" | #include "core/loader/loader.h" | ||||||
| #include "core/movie.h" | #include "core/movie.h" | ||||||
| #include "core/settings.h" |  | ||||||
| #include "input_common/main.h" | #include "input_common/main.h" | ||||||
| #include "network/network.h" | #include "network/network.h" | ||||||
| #include "video_core/renderer_base.h" | #include "video_core/renderer_base.h" | ||||||
|  | @ -174,7 +174,7 @@ static void OnStatusMessageReceived(const Network::StatusMessageEntry& msg) { | ||||||
| 
 | 
 | ||||||
| static void InitializeLogging() { | static void InitializeLogging() { | ||||||
|     Log::Filter log_filter(Log::Level::Debug); |     Log::Filter log_filter(Log::Level::Debug); | ||||||
|     log_filter.ParseFilterString(Settings::values.log_filter); |     log_filter.ParseFilterString(Settings::values.log_filter.GetValue()); | ||||||
|     Log::SetGlobalFilter(log_filter); |     Log::SetGlobalFilter(log_filter); | ||||||
| 
 | 
 | ||||||
|     Log::AddBackend(std::make_unique<Log::ColorConsoleBackend>()); |     Log::AddBackend(std::make_unique<Log::ColorConsoleBackend>()); | ||||||
|  | @ -192,8 +192,8 @@ int main(int argc, char** argv) { | ||||||
|     Common::DetachedTasks detached_tasks; |     Common::DetachedTasks detached_tasks; | ||||||
|     Config config; |     Config config; | ||||||
|     int option_index = 0; |     int option_index = 0; | ||||||
|     bool use_gdbstub = Settings::values.use_gdbstub; |     bool use_gdbstub = Settings::values.use_gdbstub.GetValue(); | ||||||
|     u32 gdb_port = static_cast<u32>(Settings::values.gdbstub_port); |     u32 gdb_port = static_cast<u32>(Settings::values.gdbstub_port.GetValue()); | ||||||
|     std::string movie_record; |     std::string movie_record; | ||||||
|     std::string movie_record_author; |     std::string movie_record_author; | ||||||
|     std::string movie_play; |     std::string movie_play; | ||||||
|  | @ -363,7 +363,7 @@ int main(int argc, char** argv) { | ||||||
|     EmuWindow_SDL2::InitializeSDL2(); |     EmuWindow_SDL2::InitializeSDL2(); | ||||||
| 
 | 
 | ||||||
|     const auto emu_window{std::make_unique<EmuWindow_SDL2>(fullscreen, false)}; |     const auto emu_window{std::make_unique<EmuWindow_SDL2>(fullscreen, false)}; | ||||||
|     const bool use_secondary_window{Settings::values.layout_option == |     const bool use_secondary_window{Settings::values.layout_option.GetValue() == | ||||||
|                                     Settings::LayoutOption::SeparateWindows}; |                                     Settings::LayoutOption::SeparateWindows}; | ||||||
|     const auto secondary_window = |     const auto secondary_window = | ||||||
|         use_secondary_window ? std::make_unique<EmuWindow_SDL2>(false, true) : nullptr; |         use_secondary_window ? std::make_unique<EmuWindow_SDL2>(false, true) : nullptr; | ||||||
|  |  | ||||||
|  | @ -13,9 +13,9 @@ | ||||||
| #include "common/file_util.h" | #include "common/file_util.h" | ||||||
| #include "common/logging/log.h" | #include "common/logging/log.h" | ||||||
| #include "common/param_package.h" | #include "common/param_package.h" | ||||||
|  | #include "common/settings.h" | ||||||
| #include "core/frontend/mic.h" | #include "core/frontend/mic.h" | ||||||
| #include "core/hle/service/service.h" | #include "core/hle/service/service.h" | ||||||
| #include "core/settings.h" |  | ||||||
| #include "input_common/main.h" | #include "input_common/main.h" | ||||||
| #include "input_common/udp/client.h" | #include "input_common/udp/client.h" | ||||||
| #include "network/network_settings.h" | #include "network/network_settings.h" | ||||||
|  | @ -128,10 +128,6 @@ void Config::ReadValues() { | ||||||
|         sdl2_config->GetBoolean("Renderer", "use_disk_shader_cache", true); |         sdl2_config->GetBoolean("Renderer", "use_disk_shader_cache", true); | ||||||
|     Settings::values.frame_limit = |     Settings::values.frame_limit = | ||||||
|         static_cast<u16>(sdl2_config->GetInteger("Renderer", "frame_limit", 100)); |         static_cast<u16>(sdl2_config->GetInteger("Renderer", "frame_limit", 100)); | ||||||
|     Settings::values.use_frame_limit_alternate = |  | ||||||
|         sdl2_config->GetBoolean("Renderer", "use_frame_limit_alternate", false); |  | ||||||
|     Settings::values.frame_limit_alternate = |  | ||||||
|         static_cast<u16>(sdl2_config->GetInteger("Renderer", "frame_limit_alternate", 200)); |  | ||||||
|     Settings::values.use_vsync_new = |     Settings::values.use_vsync_new = | ||||||
|         static_cast<u16>(sdl2_config->GetInteger("Renderer", "use_vsync_new", 1)); |         static_cast<u16>(sdl2_config->GetInteger("Renderer", "use_vsync_new", 1)); | ||||||
|     Settings::values.texture_filter_name = |     Settings::values.texture_filter_name = | ||||||
|  | @ -144,10 +140,11 @@ void Config::ReadValues() { | ||||||
|     Settings::values.factor_3d = |     Settings::values.factor_3d = | ||||||
|         static_cast<u8>(sdl2_config->GetInteger("Renderer", "factor_3d", 0)); |         static_cast<u8>(sdl2_config->GetInteger("Renderer", "factor_3d", 0)); | ||||||
|     std::string default_shader = "none (builtin)"; |     std::string default_shader = "none (builtin)"; | ||||||
|     if (Settings::values.render_3d == Settings::StereoRenderOption::Anaglyph) |     if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Anaglyph) | ||||||
|         default_shader = "dubois (builtin)"; |         default_shader = "dubois (builtin)"; | ||||||
|     else if (Settings::values.render_3d == Settings::StereoRenderOption::Interlaced || |     else if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Interlaced || | ||||||
|              Settings::values.render_3d == Settings::StereoRenderOption::ReverseInterlaced) |              Settings::values.render_3d.GetValue() == | ||||||
|  |                  Settings::StereoRenderOption::ReverseInterlaced) | ||||||
|         default_shader = "horizontal (builtin)"; |         default_shader = "horizontal (builtin)"; | ||||||
|     Settings::values.pp_shader_name = |     Settings::values.pp_shader_name = | ||||||
|         sdl2_config->GetString("Renderer", "pp_shader_name", default_shader); |         sdl2_config->GetString("Renderer", "pp_shader_name", default_shader); | ||||||
|  | @ -188,9 +185,8 @@ void Config::ReadValues() { | ||||||
|         sdl2_config->GetBoolean("Utility", "preload_textures", false); |         sdl2_config->GetBoolean("Utility", "preload_textures", false); | ||||||
| 
 | 
 | ||||||
|     // Audio
 |     // Audio
 | ||||||
|     Settings::values.enable_dsp_lle = sdl2_config->GetBoolean("Audio", "enable_dsp_lle", false); |     Settings::values.audio_emulation = static_cast<Settings::AudioEmulation>( | ||||||
|     Settings::values.enable_dsp_lle_multithread = |         sdl2_config->GetInteger("Audio", "audio_emulation", 0)); | ||||||
|         sdl2_config->GetBoolean("Audio", "enable_dsp_lle_multithread", false); |  | ||||||
|     Settings::values.sink_id = sdl2_config->GetString("Audio", "output_engine", "auto"); |     Settings::values.sink_id = sdl2_config->GetString("Audio", "output_engine", "auto"); | ||||||
|     Settings::values.enable_audio_stretching = |     Settings::values.enable_audio_stretching = | ||||||
|         sdl2_config->GetBoolean("Audio", "enable_audio_stretching", true); |         sdl2_config->GetBoolean("Audio", "enable_audio_stretching", true); | ||||||
|  |  | ||||||
|  | @ -12,9 +12,9 @@ | ||||||
| #include "citra/emu_window/emu_window_sdl2.h" | #include "citra/emu_window/emu_window_sdl2.h" | ||||||
| #include "common/logging/log.h" | #include "common/logging/log.h" | ||||||
| #include "common/scm_rev.h" | #include "common/scm_rev.h" | ||||||
|  | #include "common/settings.h" | ||||||
| #include "core/3ds.h" | #include "core/3ds.h" | ||||||
| #include "core/core.h" | #include "core/core.h" | ||||||
| #include "core/settings.h" |  | ||||||
| #include "input_common/keyboard.h" | #include "input_common/keyboard.h" | ||||||
| #include "input_common/main.h" | #include "input_common/main.h" | ||||||
| #include "input_common/motion_emu.h" | #include "input_common/motion_emu.h" | ||||||
|  |  | ||||||
|  | @ -38,6 +38,8 @@ add_executable(citra-qt | ||||||
|     configuration/config.cpp |     configuration/config.cpp | ||||||
|     configuration/config.h |     configuration/config.h | ||||||
|     configuration/configure.ui |     configuration/configure.ui | ||||||
|  |     configuration/configuration_shared.cpp | ||||||
|  |     configuration/configuration_shared.h | ||||||
|     configuration/configure_audio.cpp |     configuration/configure_audio.cpp | ||||||
|     configuration/configure_audio.h |     configuration/configure_audio.h | ||||||
|     configuration/configure_audio.ui |     configuration/configure_audio.ui | ||||||
|  | @ -67,6 +69,9 @@ add_executable(citra-qt | ||||||
|     configuration/configure_motion_touch.cpp |     configuration/configure_motion_touch.cpp | ||||||
|     configuration/configure_motion_touch.h |     configuration/configure_motion_touch.h | ||||||
|     configuration/configure_motion_touch.ui |     configuration/configure_motion_touch.ui | ||||||
|  |     configuration/configure_per_game.cpp | ||||||
|  |     configuration/configure_per_game.h | ||||||
|  |     configuration/configure_per_game.ui | ||||||
|     configuration/configure_storage.cpp |     configuration/configure_storage.cpp | ||||||
|     configuration/configure_storage.h |     configuration/configure_storage.h | ||||||
|     configuration/configure_storage.ui |     configuration/configure_storage.ui | ||||||
|  |  | ||||||
|  | @ -15,11 +15,11 @@ | ||||||
| #include "citra_qt/main.h" | #include "citra_qt/main.h" | ||||||
| #include "common/microprofile.h" | #include "common/microprofile.h" | ||||||
| #include "common/scm_rev.h" | #include "common/scm_rev.h" | ||||||
|  | #include "common/settings.h" | ||||||
| #include "core/3ds.h" | #include "core/3ds.h" | ||||||
| #include "core/core.h" | #include "core/core.h" | ||||||
| #include "core/frontend/scope_acquire_context.h" | #include "core/frontend/scope_acquire_context.h" | ||||||
| #include "core/perf_stats.h" | #include "core/perf_stats.h" | ||||||
| #include "core/settings.h" |  | ||||||
| #include "input_common/keyboard.h" | #include "input_common/keyboard.h" | ||||||
| #include "input_common/main.h" | #include "input_common/main.h" | ||||||
| #include "input_common/motion_emu.h" | #include "input_common/motion_emu.h" | ||||||
|  |  | ||||||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -8,13 +8,16 @@ | ||||||
| #include <memory> | #include <memory> | ||||||
| #include <string> | #include <string> | ||||||
| #include <QVariant> | #include <QVariant> | ||||||
| #include "core/settings.h" | #include "common/settings.h" | ||||||
| 
 | 
 | ||||||
| class QSettings; | class QSettings; | ||||||
| 
 | 
 | ||||||
| class Config { | class Config { | ||||||
| public: | public: | ||||||
|     Config(); |     enum class ConfigType : u32 { GlobalConfig, PerGameConfig }; | ||||||
|  | 
 | ||||||
|  |     explicit Config(const std::string& config_name = "qt-config", | ||||||
|  |                     ConfigType config_type = ConfigType::GlobalConfig); | ||||||
|     ~Config(); |     ~Config(); | ||||||
| 
 | 
 | ||||||
|     void Reload(); |     void Reload(); | ||||||
|  | @ -24,6 +27,8 @@ public: | ||||||
|     static const std::array<std::array<int, 5>, Settings::NativeAnalog::NumAnalogs> default_analogs; |     static const std::array<std::array<int, 5>, Settings::NativeAnalog::NumAnalogs> default_analogs; | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|  |     void Initialize(const std::string& config_name); | ||||||
|  | 
 | ||||||
|     void ReadValues(); |     void ReadValues(); | ||||||
|     void ReadAudioValues(); |     void ReadAudioValues(); | ||||||
|     void ReadCameraValues(); |     void ReadCameraValues(); | ||||||
|  | @ -68,11 +73,78 @@ private: | ||||||
|     void SaveWebServiceValues(); |     void SaveWebServiceValues(); | ||||||
|     void SaveVideoDumpingValues(); |     void SaveVideoDumpingValues(); | ||||||
| 
 | 
 | ||||||
|  |     /**
 | ||||||
|  |      * Reads a setting from the qt_config. | ||||||
|  |      * | ||||||
|  |      * @param name The setting's identifier | ||||||
|  |      * @param default_value The value to use when the setting is not already present in the config | ||||||
|  |      */ | ||||||
|     QVariant ReadSetting(const QString& name) const; |     QVariant ReadSetting(const QString& name) const; | ||||||
|     QVariant ReadSetting(const QString& name, const QVariant& default_value) const; |     QVariant ReadSetting(const QString& name, const QVariant& default_value) const; | ||||||
|  | 
 | ||||||
|  |     /**
 | ||||||
|  |      * Only reads a setting from the qt_config if the current config is a global config, or if the | ||||||
|  |      * current config is a custom config and the setting is overriding the global setting. Otherwise | ||||||
|  |      * it does nothing. | ||||||
|  |      * | ||||||
|  |      * @param setting The variable to be modified | ||||||
|  |      * @param name The setting's identifier | ||||||
|  |      * @param default_value The value to use when the setting is not already present in the config | ||||||
|  |      */ | ||||||
|  |     template <typename Type> | ||||||
|  |     void ReadSettingGlobal(Type& setting, const QString& name, const QVariant& default_value) const; | ||||||
|  | 
 | ||||||
|  |     /**
 | ||||||
|  |      * Writes a setting to the qt_config. | ||||||
|  |      * | ||||||
|  |      * @param name The setting's idetentifier | ||||||
|  |      * @param value Value of the setting | ||||||
|  |      * @param default_value Default of the setting if not present in qt_config | ||||||
|  |      * @param use_global Specifies if the custom or global config should be in use, for custom | ||||||
|  |      * configs | ||||||
|  |      */ | ||||||
|     void WriteSetting(const QString& name, const QVariant& value); |     void WriteSetting(const QString& name, const QVariant& value); | ||||||
|     void WriteSetting(const QString& name, const QVariant& value, const QVariant& default_value); |     void WriteSetting(const QString& name, const QVariant& value, const QVariant& default_value); | ||||||
|  |     void WriteSetting(const QString& name, const QVariant& value, const QVariant& default_value, | ||||||
|  |                       bool use_global); | ||||||
| 
 | 
 | ||||||
|  |     /**
 | ||||||
|  |      * Reads a value from the qt_config and applies it to the setting, using its label and default | ||||||
|  |      * value. If the config is a custom config, this will also read the global state of the setting | ||||||
|  |      * and apply that information to it. | ||||||
|  |      * | ||||||
|  |      * @param The setting | ||||||
|  |      */ | ||||||
|  |     template <typename Type, bool ranged> | ||||||
|  |     void ReadGlobalSetting(Settings::SwitchableSetting<Type, ranged>& setting); | ||||||
|  | 
 | ||||||
|  |     /**
 | ||||||
|  |      * Sets a value to the qt_config using the setting's label and default value. If the config is a | ||||||
|  |      * custom config, it will apply the global state, and the custom value if needed. | ||||||
|  |      * | ||||||
|  |      * @param The setting | ||||||
|  |      */ | ||||||
|  |     template <typename Type, bool ranged> | ||||||
|  |     void WriteGlobalSetting(const Settings::SwitchableSetting<Type, ranged>& setting); | ||||||
|  | 
 | ||||||
|  |     /**
 | ||||||
|  |      * Reads a value from the qt_config using the setting's label and default value and applies the | ||||||
|  |      * value to the setting. | ||||||
|  |      * | ||||||
|  |      * @param The setting | ||||||
|  |      */ | ||||||
|  |     template <typename Type, bool ranged> | ||||||
|  |     void ReadBasicSetting(Settings::Setting<Type, ranged>& setting); | ||||||
|  | 
 | ||||||
|  |     /** Sets a value from the setting in the qt_config using the setting's label and default value.
 | ||||||
|  |      * | ||||||
|  |      * @param The setting | ||||||
|  |      */ | ||||||
|  |     template <typename Type, bool ranged> | ||||||
|  |     void WriteBasicSetting(const Settings::Setting<Type, ranged>& setting); | ||||||
|  | 
 | ||||||
|  |     ConfigType type; | ||||||
|     std::unique_ptr<QSettings> qt_config; |     std::unique_ptr<QSettings> qt_config; | ||||||
|     std::string qt_config_loc; |     std::string qt_config_loc; | ||||||
|  |     bool global; | ||||||
| }; | }; | ||||||
|  |  | ||||||
							
								
								
									
										95
									
								
								src/citra_qt/configuration/configuration_shared.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								src/citra_qt/configuration/configuration_shared.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,95 @@ | ||||||
|  | // Copyright 2020 yuzu Emulator Project
 | ||||||
|  | // Licensed under GPLv2 or any later version
 | ||||||
|  | // Refer to the license.txt file included.
 | ||||||
|  | 
 | ||||||
|  | #include <QCheckBox> | ||||||
|  | #include <QObject> | ||||||
|  | #include <QString> | ||||||
|  | #include "citra_qt/configuration/configuration_shared.h" | ||||||
|  | #include "citra_qt/configuration/configure_per_game.h" | ||||||
|  | #include "common/settings.h" | ||||||
|  | 
 | ||||||
|  | void ConfigurationShared::ApplyPerGameSetting(Settings::SwitchableSetting<bool>* setting, | ||||||
|  |                                               const QCheckBox* checkbox, | ||||||
|  |                                               const CheckState& tracker) { | ||||||
|  |     if (Settings::IsConfiguringGlobal() && setting->UsingGlobal()) { | ||||||
|  |         setting->SetValue(checkbox->checkState()); | ||||||
|  |     } else if (!Settings::IsConfiguringGlobal()) { | ||||||
|  |         if (tracker == CheckState::Global) { | ||||||
|  |             setting->SetGlobal(true); | ||||||
|  |         } else { | ||||||
|  |             setting->SetGlobal(false); | ||||||
|  |             setting->SetValue(checkbox->checkState()); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void ConfigurationShared::SetPerGameSetting(QCheckBox* checkbox, | ||||||
|  |                                             const Settings::SwitchableSetting<bool>* setting) { | ||||||
|  |     if (setting->UsingGlobal()) { | ||||||
|  |         checkbox->setCheckState(Qt::PartiallyChecked); | ||||||
|  |     } else { | ||||||
|  |         checkbox->setCheckState(setting->GetValue() ? Qt::Checked : Qt::Unchecked); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void ConfigurationShared::SetHighlight(QWidget* widget, bool highlighted) { | ||||||
|  |     if (highlighted) { | ||||||
|  |         widget->setStyleSheet(QStringLiteral("QWidget#%1 { background-color:rgba(0,203,255,0.5) }") | ||||||
|  |                                   .arg(widget->objectName())); | ||||||
|  |     } else { | ||||||
|  |         widget->setStyleSheet(QStringLiteral("QWidget#%1 { background-color:rgba(0,0,0,0) }") | ||||||
|  |                                   .arg(widget->objectName())); | ||||||
|  |     } | ||||||
|  |     widget->show(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void ConfigurationShared::SetColoredTristate(QCheckBox* checkbox, | ||||||
|  |                                              const Settings::SwitchableSetting<bool>& setting, | ||||||
|  |                                              CheckState& tracker) { | ||||||
|  |     if (setting.UsingGlobal()) { | ||||||
|  |         tracker = CheckState::Global; | ||||||
|  |     } else { | ||||||
|  |         tracker = (setting.GetValue() == setting.GetValue(true)) ? CheckState::On : CheckState::Off; | ||||||
|  |     } | ||||||
|  |     SetHighlight(checkbox, tracker != CheckState::Global); | ||||||
|  |     QObject::connect(checkbox, &QCheckBox::clicked, checkbox, [checkbox, setting, &tracker] { | ||||||
|  |         tracker = static_cast<CheckState>((static_cast<int>(tracker) + 1) % | ||||||
|  |                                           static_cast<int>(CheckState::Count)); | ||||||
|  |         if (tracker == CheckState::Global) { | ||||||
|  |             checkbox->setChecked(setting.GetValue(true)); | ||||||
|  |         } | ||||||
|  |         SetHighlight(checkbox, tracker != CheckState::Global); | ||||||
|  |     }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void ConfigurationShared::SetColoredTristate(QCheckBox* checkbox, bool global, bool state, | ||||||
|  |                                              bool global_state, CheckState& tracker) { | ||||||
|  |     if (global) { | ||||||
|  |         tracker = CheckState::Global; | ||||||
|  |     } else { | ||||||
|  |         tracker = (state == global_state) ? CheckState::On : CheckState::Off; | ||||||
|  |     } | ||||||
|  |     SetHighlight(checkbox, tracker != CheckState::Global); | ||||||
|  |     QObject::connect(checkbox, &QCheckBox::clicked, checkbox, [checkbox, global_state, &tracker] { | ||||||
|  |         tracker = static_cast<CheckState>((static_cast<int>(tracker) + 1) % | ||||||
|  |                                           static_cast<int>(CheckState::Count)); | ||||||
|  |         if (tracker == CheckState::Global) { | ||||||
|  |             checkbox->setChecked(global_state); | ||||||
|  |         } | ||||||
|  |         SetHighlight(checkbox, tracker != CheckState::Global); | ||||||
|  |     }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void ConfigurationShared::SetColoredComboBox(QComboBox* combobox, QWidget* target, int global) { | ||||||
|  |     InsertGlobalItem(combobox, global); | ||||||
|  |     QObject::connect(combobox, qOverload<int>(&QComboBox::activated), target, | ||||||
|  |                      [target](int index) { SetHighlight(target, index != 0); }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void ConfigurationShared::InsertGlobalItem(QComboBox* combobox, int global_index) { | ||||||
|  |     const QString use_global_text = | ||||||
|  |         ConfigurePerGame::tr("Use global configuration (%1)").arg(combobox->itemText(global_index)); | ||||||
|  |     combobox->insertItem(ConfigurationShared::USE_GLOBAL_INDEX, use_global_text); | ||||||
|  |     combobox->insertSeparator(ConfigurationShared::USE_GLOBAL_SEPARATOR_INDEX); | ||||||
|  | } | ||||||
							
								
								
									
										98
									
								
								src/citra_qt/configuration/configuration_shared.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								src/citra_qt/configuration/configuration_shared.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,98 @@ | ||||||
|  | // Copyright 2020 yuzu Emulator Project
 | ||||||
|  | // Licensed under GPLv2 or any later version
 | ||||||
|  | // Refer to the license.txt file included.
 | ||||||
|  | 
 | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <QCheckBox> | ||||||
|  | #include <QComboBox> | ||||||
|  | #include "common/settings.h" | ||||||
|  | 
 | ||||||
|  | namespace ConfigurationShared { | ||||||
|  | 
 | ||||||
|  | constexpr int USE_GLOBAL_INDEX = | ||||||
|  |     0; ///< The index of the "Use global configuration" option in checkboxes
 | ||||||
|  | constexpr int USE_GLOBAL_SEPARATOR_INDEX = 1; | ||||||
|  | constexpr int USE_GLOBAL_OFFSET = 2; | ||||||
|  | 
 | ||||||
|  | /// CheckBoxes require a tracker for their state since we emulate a tristate CheckBox
 | ||||||
|  | enum class CheckState { | ||||||
|  |     Off,    ///< Checkbox overrides to off/false
 | ||||||
|  |     On,     ///< Checkbox overrides to on/true
 | ||||||
|  |     Global, ///< Checkbox defers to the global state
 | ||||||
|  |     Count,  ///< Simply the number of states, not a valid checkbox state
 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * @brief ApplyPerGameSetting given a setting and a Qt UI element, properly applies a Setting | ||||||
|  |  * taking into account the global/per-game check state. This is used for configuring checkboxes | ||||||
|  |  * @param setting | ||||||
|  |  * @param checkbox | ||||||
|  |  * @param tracker | ||||||
|  |  */ | ||||||
|  | void ApplyPerGameSetting(Settings::SwitchableSetting<bool>* setting, const QCheckBox* checkbox, | ||||||
|  |                          const CheckState& tracker); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * @brief ApplyPerGameSetting given a setting and a Qt UI element, properly applies a Setting | ||||||
|  |  * taking into account the global/per-game check state. This is used for both combo boxes | ||||||
|  |  * as well as any other widget that is accompanied by a combo box in per-game settings. | ||||||
|  |  * @param setting The setting class that stores the desired option | ||||||
|  |  * @param combobox The Qt combo box that stores the value/per-game status | ||||||
|  |  * @param transform A function that accepts the combo box index and transforms it to the | ||||||
|  |  * desired settings value. When used with sliders/edit the user can ignore the input value | ||||||
|  |  * and set a custom value this making this function useful for these widgets as well | ||||||
|  |  */ | ||||||
|  | template <typename Type, bool ranged> | ||||||
|  | void ApplyPerGameSetting(Settings::SwitchableSetting<Type, ranged>* setting, | ||||||
|  |                          const QComboBox* combobox, auto transform) { | ||||||
|  |     if (Settings::IsConfiguringGlobal() && setting->UsingGlobal()) { | ||||||
|  |         setting->SetValue(static_cast<Type>(transform(combobox->currentIndex()))); | ||||||
|  |     } else if (!Settings::IsConfiguringGlobal()) { | ||||||
|  |         if (combobox->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) { | ||||||
|  |             setting->SetGlobal(true); | ||||||
|  |         } else { | ||||||
|  |             setting->SetGlobal(false); | ||||||
|  |             setting->SetValue(static_cast<Type>( | ||||||
|  |                 transform(combobox->currentIndex() - ConfigurationShared::USE_GLOBAL_OFFSET))); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /// Simpler version of ApplyPerGameSetting without a transform parameter
 | ||||||
|  | template <typename Type, bool ranged> | ||||||
|  | void ApplyPerGameSetting(Settings::SwitchableSetting<Type, ranged>* setting, | ||||||
|  |                          const QComboBox* combobox) { | ||||||
|  |     const auto transform = [](s32 index) { return index; }; | ||||||
|  |     return ApplyPerGameSetting(setting, combobox, transform); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /// Sets a Qt UI element given a Settings::Setting
 | ||||||
|  | void SetPerGameSetting(QCheckBox* checkbox, const Settings::SwitchableSetting<bool>* setting); | ||||||
|  | 
 | ||||||
|  | template <typename Type, bool ranged> | ||||||
|  | void SetPerGameSetting(QComboBox* combobox, | ||||||
|  |                        const Settings::SwitchableSetting<Type, ranged>* setting) { | ||||||
|  |     combobox->setCurrentIndex(setting->UsingGlobal() ? ConfigurationShared::USE_GLOBAL_INDEX | ||||||
|  |                                                      : static_cast<int>(setting->GetValue()) + | ||||||
|  |                                                            ConfigurationShared::USE_GLOBAL_OFFSET); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /// Given a Qt widget sets the background color to indicate whether the setting
 | ||||||
|  | /// is per-game overriden (highlighted) or global (non-highlighted)
 | ||||||
|  | void SetHighlight(QWidget* widget, bool highlighted); | ||||||
|  | 
 | ||||||
|  | /// Sets up a QCheckBox like a tristate one, given a Setting
 | ||||||
|  | void SetColoredTristate(QCheckBox* checkbox, const Settings::SwitchableSetting<bool>& setting, | ||||||
|  |                         CheckState& tracker); | ||||||
|  | void SetColoredTristate(QCheckBox* checkbox, bool global, bool state, bool global_state, | ||||||
|  |                         CheckState& tracker); | ||||||
|  | 
 | ||||||
|  | /// Sets up coloring of a QWidget `target` based on the state of a QComboBox, and calls
 | ||||||
|  | /// InsertGlobalItem
 | ||||||
|  | void SetColoredComboBox(QComboBox* combobox, QWidget* target, int global); | ||||||
|  | 
 | ||||||
|  | /// Adds the "Use Global Configuration" selection and separator to the beginning of a QComboBox
 | ||||||
|  | void InsertGlobalItem(QComboBox* combobox, int global_index); | ||||||
|  | 
 | ||||||
|  | } // namespace ConfigurationShared
 | ||||||
|  | @ -9,10 +9,11 @@ | ||||||
| #endif | #endif | ||||||
| #include "audio_core/sink.h" | #include "audio_core/sink.h" | ||||||
| #include "audio_core/sink_details.h" | #include "audio_core/sink_details.h" | ||||||
|  | #include "citra_qt/configuration/configuration_shared.h" | ||||||
| #include "citra_qt/configuration/configure_audio.h" | #include "citra_qt/configuration/configure_audio.h" | ||||||
|  | #include "common/settings.h" | ||||||
| #include "core/core.h" | #include "core/core.h" | ||||||
| #include "core/frontend/mic.h" | #include "core/frontend/mic.h" | ||||||
| #include "core/settings.h" |  | ||||||
| #include "ui_configure_audio.h" | #include "ui_configure_audio.h" | ||||||
| 
 | 
 | ||||||
| #if defined(__APPLE__) | #if defined(__APPLE__) | ||||||
|  | @ -31,25 +32,30 @@ ConfigureAudio::ConfigureAudio(QWidget* parent) | ||||||
|         ui->output_sink_combo_box->addItem(QString::fromUtf8(id)); |         ui->output_sink_combo_box->addItem(QString::fromUtf8(id)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     ui->emulation_combo_box->addItem(tr("HLE (fast)")); |     const bool is_running = Core::System::GetInstance().IsPoweredOn(); | ||||||
|     ui->emulation_combo_box->addItem(tr("LLE (accurate)")); |     ui->emulation_combo_box->setEnabled(!is_running); | ||||||
|     ui->emulation_combo_box->addItem(tr("LLE multi-core")); |  | ||||||
|     ui->emulation_combo_box->setEnabled(!Core::System::GetInstance().IsPoweredOn()); |  | ||||||
| 
 | 
 | ||||||
|     connect(ui->volume_slider, &QSlider::valueChanged, this, |     connect(ui->volume_slider, &QSlider::valueChanged, this, | ||||||
|             &ConfigureAudio::SetVolumeIndicatorText); |             &ConfigureAudio::SetVolumeIndicatorText); | ||||||
| 
 | 
 | ||||||
|     ui->input_device_combo_box->clear(); |     ui->input_device_combo_box->clear(); | ||||||
|     ui->input_device_combo_box->addItem(tr("Default")); |     ui->input_device_combo_box->addItem(tr("Default")); | ||||||
|  | 
 | ||||||
| #ifdef HAVE_CUBEB | #ifdef HAVE_CUBEB | ||||||
|     for (const auto& device : AudioCore::ListCubebInputDevices()) { |     for (const auto& device : AudioCore::ListCubebInputDevices()) { | ||||||
|         ui->input_device_combo_box->addItem(QString::fromStdString(device)); |         ui->input_device_combo_box->addItem(QString::fromStdString(device)); | ||||||
|     } |     } | ||||||
| #endif | #endif | ||||||
|  | 
 | ||||||
|     connect(ui->input_type_combo_box, qOverload<int>(&QComboBox::currentIndexChanged), this, |     connect(ui->input_type_combo_box, qOverload<int>(&QComboBox::currentIndexChanged), this, | ||||||
|             &ConfigureAudio::UpdateAudioInputDevices); |             &ConfigureAudio::UpdateAudioInputDevices); | ||||||
| 
 | 
 | ||||||
|  |     ui->volume_label->setVisible(Settings::IsConfiguringGlobal()); | ||||||
|  |     ui->volume_combo_box->setVisible(!Settings::IsConfiguringGlobal()); | ||||||
|  | 
 | ||||||
|  |     SetupPerGameUI(); | ||||||
|     SetConfiguration(); |     SetConfiguration(); | ||||||
|  | 
 | ||||||
|     connect(ui->output_sink_combo_box, qOverload<int>(&QComboBox::currentIndexChanged), this, |     connect(ui->output_sink_combo_box, qOverload<int>(&QComboBox::currentIndexChanged), this, | ||||||
|             &ConfigureAudio::UpdateAudioOutputDevices); |             &ConfigureAudio::UpdateAudioOutputDevices); | ||||||
| } | } | ||||||
|  | @ -61,27 +67,35 @@ void ConfigureAudio::SetConfiguration() { | ||||||
| 
 | 
 | ||||||
|     // The device list cannot be pre-populated (nor listed) until the output sink is known.
 |     // The device list cannot be pre-populated (nor listed) until the output sink is known.
 | ||||||
|     UpdateAudioOutputDevices(ui->output_sink_combo_box->currentIndex()); |     UpdateAudioOutputDevices(ui->output_sink_combo_box->currentIndex()); | ||||||
| 
 |  | ||||||
|     SetAudioDeviceFromDeviceID(); |     SetAudioDeviceFromDeviceID(); | ||||||
| 
 | 
 | ||||||
|     ui->toggle_audio_stretching->setChecked(Settings::values.enable_audio_stretching); |     ui->toggle_audio_stretching->setChecked(Settings::values.enable_audio_stretching.GetValue()); | ||||||
|     ui->volume_slider->setValue( | 
 | ||||||
|         static_cast<int>(Settings::values.volume * ui->volume_slider->maximum())); |     const s32 volume = | ||||||
|  |         static_cast<s32>(Settings::values.volume.GetValue() * ui->volume_slider->maximum()); | ||||||
|  |     ui->volume_slider->setValue(volume); | ||||||
|     SetVolumeIndicatorText(ui->volume_slider->sliderPosition()); |     SetVolumeIndicatorText(ui->volume_slider->sliderPosition()); | ||||||
| 
 | 
 | ||||||
|     int selection; |     if (!Settings::IsConfiguringGlobal()) { | ||||||
|     if (Settings::values.enable_dsp_lle) { |         if (Settings::values.volume.UsingGlobal()) { | ||||||
|         if (Settings::values.enable_dsp_lle_multithread) { |             ui->volume_combo_box->setCurrentIndex(0); | ||||||
|             selection = 2; |             ui->volume_slider->setEnabled(false); | ||||||
|         } else { |         } else { | ||||||
|             selection = 1; |             ui->volume_combo_box->setCurrentIndex(1); | ||||||
|  |             ui->volume_slider->setEnabled(true); | ||||||
|         } |         } | ||||||
|  |         ConfigurationShared::SetHighlight(ui->volume_layout, | ||||||
|  |                                           !Settings::values.volume.UsingGlobal()); | ||||||
|  |         ConfigurationShared::SetHighlight(ui->widget_emulation, | ||||||
|  |                                           !Settings::values.audio_emulation.UsingGlobal()); | ||||||
|  |         ConfigurationShared::SetPerGameSetting(ui->emulation_combo_box, | ||||||
|  |                                                &Settings::values.audio_emulation); | ||||||
|     } else { |     } else { | ||||||
|         selection = 0; |         s32 selection = static_cast<s32>(Settings::values.audio_emulation.GetValue()); | ||||||
|  |         ui->emulation_combo_box->setCurrentIndex(selection); | ||||||
|     } |     } | ||||||
|     ui->emulation_combo_box->setCurrentIndex(selection); |  | ||||||
| 
 | 
 | ||||||
|     int index = static_cast<int>(Settings::values.mic_input_type); |     s32 index = static_cast<s32>(Settings::values.mic_input_type.GetValue()); | ||||||
|     ui->input_type_combo_box->setCurrentIndex(index); |     ui->input_type_combo_box->setCurrentIndex(index); | ||||||
| 
 | 
 | ||||||
|     UpdateAudioInputDevices(index); |     UpdateAudioInputDevices(index); | ||||||
|  | @ -90,7 +104,7 @@ void ConfigureAudio::SetConfiguration() { | ||||||
| void ConfigureAudio::SetOutputSinkFromSinkID() { | void ConfigureAudio::SetOutputSinkFromSinkID() { | ||||||
|     int new_sink_index = 0; |     int new_sink_index = 0; | ||||||
| 
 | 
 | ||||||
|     const QString sink_id = QString::fromStdString(Settings::values.sink_id); |     const QString sink_id = QString::fromStdString(Settings::values.sink_id.GetValue()); | ||||||
|     for (int index = 0; index < ui->output_sink_combo_box->count(); index++) { |     for (int index = 0; index < ui->output_sink_combo_box->count(); index++) { | ||||||
|         if (ui->output_sink_combo_box->itemText(index) == sink_id) { |         if (ui->output_sink_combo_box->itemText(index) == sink_id) { | ||||||
|             new_sink_index = index; |             new_sink_index = index; | ||||||
|  | @ -104,7 +118,7 @@ void ConfigureAudio::SetOutputSinkFromSinkID() { | ||||||
| void ConfigureAudio::SetAudioDeviceFromDeviceID() { | void ConfigureAudio::SetAudioDeviceFromDeviceID() { | ||||||
|     int new_device_index = -1; |     int new_device_index = -1; | ||||||
| 
 | 
 | ||||||
|     const QString device_id = QString::fromStdString(Settings::values.audio_device_id); |     const QString device_id = QString::fromStdString(Settings::values.audio_device_id.GetValue()); | ||||||
|     for (int index = 0; index < ui->audio_device_combo_box->count(); index++) { |     for (int index = 0; index < ui->audio_device_combo_box->count(); index++) { | ||||||
|         if (ui->audio_device_combo_box->itemText(index) == device_id) { |         if (ui->audio_device_combo_box->itemText(index) == device_id) { | ||||||
|             new_device_index = index; |             new_device_index = index; | ||||||
|  | @ -120,24 +134,31 @@ void ConfigureAudio::SetVolumeIndicatorText(int percentage) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ConfigureAudio::ApplyConfiguration() { | void ConfigureAudio::ApplyConfiguration() { | ||||||
|     Settings::values.sink_id = |     ConfigurationShared::ApplyPerGameSetting(&Settings::values.enable_audio_stretching, | ||||||
|         ui->output_sink_combo_box->itemText(ui->output_sink_combo_box->currentIndex()) |                                              ui->toggle_audio_stretching, audio_stretching); | ||||||
|             .toStdString(); |     ConfigurationShared::ApplyPerGameSetting(&Settings::values.audio_emulation, | ||||||
|     Settings::values.enable_audio_stretching = ui->toggle_audio_stretching->isChecked(); |                                              ui->emulation_combo_box); | ||||||
|     Settings::values.audio_device_id = |     ConfigurationShared::ApplyPerGameSetting( | ||||||
|         ui->audio_device_combo_box->itemText(ui->audio_device_combo_box->currentIndex()) |         &Settings::values.volume, ui->volume_combo_box, [this](s32) { | ||||||
|             .toStdString(); |             return static_cast<float>(ui->volume_slider->value()) / ui->volume_slider->maximum(); | ||||||
|     Settings::values.volume = |         }); | ||||||
|         static_cast<float>(ui->volume_slider->sliderPosition()) / ui->volume_slider->maximum(); |  | ||||||
|     Settings::values.enable_dsp_lle = ui->emulation_combo_box->currentIndex() != 0; |  | ||||||
|     Settings::values.enable_dsp_lle_multithread = ui->emulation_combo_box->currentIndex() == 2; |  | ||||||
|     Settings::values.mic_input_type = |  | ||||||
|         static_cast<Settings::MicInputType>(ui->input_type_combo_box->currentIndex()); |  | ||||||
| 
 | 
 | ||||||
|     if (ui->input_device_combo_box->currentIndex() == DEFAULT_INPUT_DEVICE_INDEX) { |     if (Settings::IsConfiguringGlobal()) { | ||||||
|         Settings::values.mic_input_device = Frontend::Mic::default_device_name; |         Settings::values.sink_id = | ||||||
|     } else { |             ui->output_sink_combo_box->itemText(ui->output_sink_combo_box->currentIndex()) | ||||||
|         Settings::values.mic_input_device = ui->input_device_combo_box->currentText().toStdString(); |                 .toStdString(); | ||||||
|  |         Settings::values.audio_device_id = | ||||||
|  |             ui->audio_device_combo_box->itemText(ui->audio_device_combo_box->currentIndex()) | ||||||
|  |                 .toStdString(); | ||||||
|  |         Settings::values.mic_input_type = | ||||||
|  |             static_cast<Settings::MicInputType>(ui->input_type_combo_box->currentIndex()); | ||||||
|  | 
 | ||||||
|  |         if (ui->input_device_combo_box->currentIndex() == DEFAULT_INPUT_DEVICE_INDEX) { | ||||||
|  |             Settings::values.mic_input_device = Frontend::Mic::default_device_name; | ||||||
|  |         } else { | ||||||
|  |             Settings::values.mic_input_device = | ||||||
|  |                 ui->input_device_combo_box->currentText().toStdString(); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -157,12 +178,41 @@ void ConfigureAudio::UpdateAudioInputDevices(int index) { | ||||||
|         AppleAuthorization::CheckAuthorizationForMicrophone(); |         AppleAuthorization::CheckAuthorizationForMicrophone(); | ||||||
|     } |     } | ||||||
| #endif | #endif | ||||||
|     if (Settings::values.mic_input_device != Frontend::Mic::default_device_name) { |     if (Settings::values.mic_input_device.GetValue() != Frontend::Mic::default_device_name) { | ||||||
|         ui->input_device_combo_box->setCurrentText( |         ui->input_device_combo_box->setCurrentText( | ||||||
|             QString::fromStdString(Settings::values.mic_input_device)); |             QString::fromStdString(Settings::values.mic_input_device.GetValue())); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ConfigureAudio::RetranslateUI() { | void ConfigureAudio::RetranslateUI() { | ||||||
|     ui->retranslateUi(this); |     ui->retranslateUi(this); | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | void ConfigureAudio::SetupPerGameUI() { | ||||||
|  |     if (Settings::IsConfiguringGlobal()) { | ||||||
|  |         ui->volume_slider->setEnabled(Settings::values.volume.UsingGlobal()); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     ui->output_sink_combo_box->setVisible(false); | ||||||
|  |     ui->output_sink_label->setVisible(false); | ||||||
|  |     ui->audio_device_combo_box->setVisible(false); | ||||||
|  |     ui->audio_device_label->setVisible(false); | ||||||
|  |     ui->input_type_label->setVisible(false); | ||||||
|  |     ui->input_type_combo_box->setVisible(false); | ||||||
|  |     ui->input_device_label->setVisible(false); | ||||||
|  |     ui->input_device_combo_box->setVisible(false); | ||||||
|  |     ui->microphone_layout->setVisible(false); | ||||||
|  | 
 | ||||||
|  |     connect(ui->volume_combo_box, qOverload<int>(&QComboBox::activated), this, [this](int index) { | ||||||
|  |         ui->volume_slider->setEnabled(index == 1); | ||||||
|  |         ConfigurationShared::SetHighlight(ui->volume_layout, index == 1); | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     ConfigurationShared::SetColoredComboBox( | ||||||
|  |         ui->emulation_combo_box, ui->widget_emulation, | ||||||
|  |         static_cast<u32>(Settings::values.audio_emulation.GetValue(true))); | ||||||
|  | 
 | ||||||
|  |     ConfigurationShared::SetColoredTristate( | ||||||
|  |         ui->toggle_audio_stretching, Settings::values.enable_audio_stretching, audio_stretching); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -11,6 +11,10 @@ namespace Ui { | ||||||
| class ConfigureAudio; | class ConfigureAudio; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | namespace ConfigurationShared { | ||||||
|  | enum class CheckState; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| class ConfigureAudio : public QWidget { | class ConfigureAudio : public QWidget { | ||||||
|     Q_OBJECT |     Q_OBJECT | ||||||
| 
 | 
 | ||||||
|  | @ -30,5 +34,8 @@ private: | ||||||
|     void SetAudioDeviceFromDeviceID(); |     void SetAudioDeviceFromDeviceID(); | ||||||
|     void SetVolumeIndicatorText(int percentage); |     void SetVolumeIndicatorText(int percentage); | ||||||
| 
 | 
 | ||||||
|  |     void SetupPerGameUI(); | ||||||
|  | 
 | ||||||
|  |     ConfigurationShared::CheckState audio_stretching; | ||||||
|     std::unique_ptr<Ui::ConfigureAudio> ui; |     std::unique_ptr<Ui::ConfigureAudio> ui; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | @ -6,8 +6,8 @@ | ||||||
|    <rect> |    <rect> | ||||||
|     <x>0</x> |     <x>0</x> | ||||||
|     <y>0</y> |     <y>0</y> | ||||||
|     <width>329</width> |     <width>696</width> | ||||||
|     <height>344</height> |     <height>527</height> | ||||||
|    </rect> |    </rect> | ||||||
|   </property> |   </property> | ||||||
|   <layout class="QVBoxLayout"> |   <layout class="QVBoxLayout"> | ||||||
|  | @ -18,26 +18,53 @@ | ||||||
|      </property> |      </property> | ||||||
|      <layout class="QVBoxLayout"> |      <layout class="QVBoxLayout"> | ||||||
|       <item> |       <item> | ||||||
|        <layout class="QHBoxLayout" name="horizontalLayout_emulation"> |       <widget class="QWidget" name="widget_emulation" native="true"> | ||||||
|         <property name="bottomMargin"> |         <layout class="QHBoxLayout" name="horizontalLayout_emulation"> | ||||||
|          <number>0</number> |             <property name="leftMargin"> | ||||||
|         </property> |             <number>0</number> | ||||||
|         <item> |             </property> | ||||||
|          <widget class="QLabel" name="label_emulation"> |             <property name="topMargin"> | ||||||
|           <property name="text"> |             <number>0</number> | ||||||
|            <string>Emulation:</string> |             </property> | ||||||
|           </property> |             <property name="rightMargin"> | ||||||
|          </widget> |             <number>0</number> | ||||||
|         </item> |             </property> | ||||||
|         <item> |             <property name="bottomMargin"> | ||||||
|          <widget class="QComboBox" name="emulation_combo_box"/> |             <number>0</number> | ||||||
|         </item> |             </property> | ||||||
|        </layout> |             <item> | ||||||
|  |             <widget class="QLabel" name="label_emulation"> | ||||||
|  |             <property name="text"> | ||||||
|  |             <string>Emulation:</string> | ||||||
|  |             </property> | ||||||
|  |             </widget> | ||||||
|  |             </item> | ||||||
|  |             <item> | ||||||
|  |             <widget class="QComboBox" name="emulation_combo_box"> | ||||||
|  |             <item> | ||||||
|  |             <property name="text"> | ||||||
|  |                 <string>HLE (fast)</string> | ||||||
|  |             </property> | ||||||
|  |             </item> | ||||||
|  |             <item> | ||||||
|  |             <property name="text"> | ||||||
|  |                 <string>LLE (accurate)</string> | ||||||
|  |             </property> | ||||||
|  |             </item> | ||||||
|  |             <item> | ||||||
|  |             <property name="text"> | ||||||
|  |                 <string>LLE multi-core</string> | ||||||
|  |             </property> | ||||||
|  |             </item> | ||||||
|  |             </widget> | ||||||
|  |             </item> | ||||||
|  |         </layout> | ||||||
|  |        </widget> | ||||||
|       </item> |       </item> | ||||||
|       <item> |       <item> | ||||||
|        <layout class="QHBoxLayout"> |        <layout class="QHBoxLayout" name="output_engine_layout"> | ||||||
|         <item> |         <item> | ||||||
|          <widget class="QLabel" name="label1"> |          <widget class="QLabel" name="output_sink_label"> | ||||||
|           <property name="text"> |           <property name="text"> | ||||||
|            <string>Output Engine</string> |            <string>Output Engine</string> | ||||||
|           </property> |           </property> | ||||||
|  | @ -59,9 +86,9 @@ | ||||||
|        </widget> |        </widget> | ||||||
|       </item> |       </item> | ||||||
|       <item> |       <item> | ||||||
|        <layout class="QHBoxLayout"> |        <layout class="QHBoxLayout" name="audio_device_layout"> | ||||||
|         <item> |         <item> | ||||||
|          <widget class="QLabel" name="label2"> |          <widget class="QLabel" name="audio_device_label"> | ||||||
|           <property name="text"> |           <property name="text"> | ||||||
|            <string>Audio Device</string> |            <string>Audio Device</string> | ||||||
|           </property> |           </property> | ||||||
|  | @ -73,72 +100,97 @@ | ||||||
|        </layout> |        </layout> | ||||||
|       </item> |       </item> | ||||||
|       <item> |       <item> | ||||||
|        <layout class="QHBoxLayout" name="horizontalLayout_2"> |        <widget class="QWidget" name="volume_layout" native="true"> | ||||||
|         <property name="topMargin"> |         <layout class="QHBoxLayout" name="horizontalLayout_2"> | ||||||
|          <number>0</number> |          <property name="leftMargin"> | ||||||
|         </property> |           <number>0</number> | ||||||
|         <item> |          </property> | ||||||
|          <widget class="QLabel" name="label"> |          <property name="topMargin"> | ||||||
|           <property name="text"> |           <number>0</number> | ||||||
|            <string>Volume:</string> |          </property> | ||||||
|           </property> |          <property name="rightMargin"> | ||||||
|          </widget> |           <number>0</number> | ||||||
|         </item> |          </property> | ||||||
|         <item> |          <property name="bottomMargin"> | ||||||
|          <spacer name="horizontalSpacer"> |           <number>0</number> | ||||||
|           <property name="orientation"> |          </property> | ||||||
|            <enum>Qt::Horizontal</enum> |          <item> | ||||||
|           </property> |           <widget class="QComboBox" name="volume_combo_box"> | ||||||
|           <property name="sizeHint" stdset="0"> |            <item> | ||||||
|            <size> |             <property name="text"> | ||||||
|             <width>40</width> |              <string>Use global volume</string> | ||||||
|             <height>20</height> |             </property> | ||||||
|            </size> |            </item> | ||||||
|           </property> |            <item> | ||||||
|          </spacer> |             <property name="text"> | ||||||
|         </item> |              <string>Set volume:</string> | ||||||
|         <item> |             </property> | ||||||
|          <widget class="QSlider" name="volume_slider"> |            </item> | ||||||
|           <property name="sizePolicy"> |           </widget> | ||||||
|            <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> |          </item> | ||||||
|             <horstretch>0</horstretch> |          <item> | ||||||
|             <verstretch>0</verstretch> |           <widget class="QLabel" name="volume_label"> | ||||||
|            </sizepolicy> |            <property name="text"> | ||||||
|           </property> |             <string>Volume:</string> | ||||||
|           <property name="maximum"> |            </property> | ||||||
|            <number>100</number> |           </widget> | ||||||
|           </property> |          </item> | ||||||
|           <property name="pageStep"> |          <item> | ||||||
|            <number>10</number> |           <spacer name="horizontalSpacer"> | ||||||
|           </property> |            <property name="orientation"> | ||||||
|           <property name="orientation"> |             <enum>Qt::Horizontal</enum> | ||||||
|            <enum>Qt::Horizontal</enum> |            </property> | ||||||
|           </property> |            <property name="sizeHint" stdset="0"> | ||||||
|          </widget> |             <size> | ||||||
|         </item> |              <width>30</width> | ||||||
|         <item> |              <height>20</height> | ||||||
|          <widget class="QLabel" name="volume_indicator"> |             </size> | ||||||
|           <property name="minimumSize"> |            </property> | ||||||
|            <size> |           </spacer> | ||||||
|             <width>32</width> |          </item> | ||||||
|             <height>0</height> |          <item> | ||||||
|            </size> |           <widget class="QSlider" name="volume_slider"> | ||||||
|           </property> |            <property name="sizePolicy"> | ||||||
|           <property name="text"> |             <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> | ||||||
|            <string>0 %</string> |              <horstretch>0</horstretch> | ||||||
|           </property> |              <verstretch>0</verstretch> | ||||||
|           <property name="alignment"> |             </sizepolicy> | ||||||
|            <set>Qt::AlignCenter</set> |            </property> | ||||||
|           </property> |            <property name="maximum"> | ||||||
|          </widget> |             <number>100</number> | ||||||
|         </item> |            </property> | ||||||
|        </layout> |            <property name="pageStep"> | ||||||
|  |             <number>5</number> | ||||||
|  |            </property> | ||||||
|  |            <property name="orientation"> | ||||||
|  |             <enum>Qt::Horizontal</enum> | ||||||
|  |            </property> | ||||||
|  |           </widget> | ||||||
|  |          </item> | ||||||
|  |          <item> | ||||||
|  |           <widget class="QLabel" name="volume_indicator"> | ||||||
|  |            <property name="minimumSize"> | ||||||
|  |             <size> | ||||||
|  |              <width>32</width> | ||||||
|  |              <height>0</height> | ||||||
|  |             </size> | ||||||
|  |            </property> | ||||||
|  |            <property name="text"> | ||||||
|  |             <string>0 %</string> | ||||||
|  |            </property> | ||||||
|  |            <property name="alignment"> | ||||||
|  |             <set>Qt::AlignCenter</set> | ||||||
|  |            </property> | ||||||
|  |           </widget> | ||||||
|  |          </item> | ||||||
|  |         </layout> | ||||||
|  |        </widget> | ||||||
|       </item> |       </item> | ||||||
|      </layout> |      </layout> | ||||||
|     </widget> |     </widget> | ||||||
|    </item> |    </item> | ||||||
|    <item> |    <item> | ||||||
|     <widget class="QGroupBox" name="groupBox_2"> |     <widget class="QGroupBox" name="microphone_layout"> | ||||||
|      <property name="title"> |      <property name="title"> | ||||||
|       <string>Microphone</string> |       <string>Microphone</string> | ||||||
|      </property> |      </property> | ||||||
|  | @ -146,7 +198,7 @@ | ||||||
|       <item> |       <item> | ||||||
|        <layout class="QHBoxLayout" name="horizontalLayout"> |        <layout class="QHBoxLayout" name="horizontalLayout"> | ||||||
|         <item> |         <item> | ||||||
|          <widget class="QLabel" name="label_2"> |          <widget class="QLabel" name="input_type_label"> | ||||||
|           <property name="text"> |           <property name="text"> | ||||||
|            <string>Input Type</string> |            <string>Input Type</string> | ||||||
|           </property> |           </property> | ||||||
|  | @ -176,7 +228,7 @@ | ||||||
|       <item> |       <item> | ||||||
|        <layout class="QHBoxLayout" name="horizontalLayout_3"> |        <layout class="QHBoxLayout" name="horizontalLayout_3"> | ||||||
|         <item> |         <item> | ||||||
|          <widget class="QLabel" name="label_3"> |          <widget class="QLabel" name="input_device_label"> | ||||||
|           <property name="text"> |           <property name="text"> | ||||||
|            <string>Input Device</string> |            <string>Input Device</string> | ||||||
|           </property> |           </property> | ||||||
|  |  | ||||||
|  | @ -9,10 +9,10 @@ | ||||||
| #include <QMessageBox> | #include <QMessageBox> | ||||||
| #include <QWidget> | #include <QWidget> | ||||||
| #include "citra_qt/configuration/configure_camera.h" | #include "citra_qt/configuration/configure_camera.h" | ||||||
|  | #include "common/settings.h" | ||||||
| #include "core/frontend/camera/factory.h" | #include "core/frontend/camera/factory.h" | ||||||
| #include "core/frontend/camera/interface.h" | #include "core/frontend/camera/interface.h" | ||||||
| #include "core/hle/service/cam/cam.h" | #include "core/hle/service/cam/cam.h" | ||||||
| #include "core/settings.h" |  | ||||||
| #include "ui_configure_camera.h" | #include "ui_configure_camera.h" | ||||||
| 
 | 
 | ||||||
| #if defined(__APPLE__) | #if defined(__APPLE__) | ||||||
|  |  | ||||||
|  | @ -8,11 +8,9 @@ | ||||||
| #include "citra_qt/debugger/console.h" | #include "citra_qt/debugger/console.h" | ||||||
| #include "citra_qt/uisettings.h" | #include "citra_qt/uisettings.h" | ||||||
| #include "common/file_util.h" | #include "common/file_util.h" | ||||||
| #include "common/logging/backend.h" |  | ||||||
| #include "common/logging/filter.h" |  | ||||||
| #include "common/logging/log.h" | #include "common/logging/log.h" | ||||||
|  | #include "common/settings.h" | ||||||
| #include "core/core.h" | #include "core/core.h" | ||||||
| #include "core/settings.h" |  | ||||||
| #include "ui_configure_debug.h" | #include "ui_configure_debug.h" | ||||||
| 
 | 
 | ||||||
| ConfigureDebug::ConfigureDebug(QWidget* parent) | ConfigureDebug::ConfigureDebug(QWidget* parent) | ||||||
|  | @ -32,13 +30,13 @@ ConfigureDebug::ConfigureDebug(QWidget* parent) | ||||||
| ConfigureDebug::~ConfigureDebug() = default; | ConfigureDebug::~ConfigureDebug() = default; | ||||||
| 
 | 
 | ||||||
| void ConfigureDebug::SetConfiguration() { | void ConfigureDebug::SetConfiguration() { | ||||||
|     ui->toggle_gdbstub->setChecked(Settings::values.use_gdbstub); |     ui->toggle_gdbstub->setChecked(Settings::values.use_gdbstub.GetValue()); | ||||||
|     ui->gdbport_spinbox->setEnabled(Settings::values.use_gdbstub); |     ui->gdbport_spinbox->setEnabled(Settings::values.use_gdbstub.GetValue()); | ||||||
|     ui->gdbport_spinbox->setValue(Settings::values.gdbstub_port); |     ui->gdbport_spinbox->setValue(Settings::values.gdbstub_port.GetValue()); | ||||||
|     ui->toggle_console->setEnabled(!Core::System::GetInstance().IsPoweredOn()); |     ui->toggle_console->setEnabled(!Core::System::GetInstance().IsPoweredOn()); | ||||||
|     ui->toggle_console->setChecked(UISettings::values.show_console); |     ui->toggle_console->setChecked(UISettings::values.show_console.GetValue()); | ||||||
|     ui->log_filter_edit->setText(QString::fromStdString(Settings::values.log_filter)); |     ui->log_filter_edit->setText(QString::fromStdString(Settings::values.log_filter.GetValue())); | ||||||
|     ui->toggle_cpu_jit->setChecked(Settings::values.use_cpu_jit); |     ui->toggle_cpu_jit->setChecked(Settings::values.use_cpu_jit.GetValue()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ConfigureDebug::ApplyConfiguration() { | void ConfigureDebug::ApplyConfiguration() { | ||||||
|  | @ -48,7 +46,7 @@ void ConfigureDebug::ApplyConfiguration() { | ||||||
|     Settings::values.log_filter = ui->log_filter_edit->text().toStdString(); |     Settings::values.log_filter = ui->log_filter_edit->text().toStdString(); | ||||||
|     Debugger::ToggleConsole(); |     Debugger::ToggleConsole(); | ||||||
|     Log::Filter filter; |     Log::Filter filter; | ||||||
|     filter.ParseFilterString(Settings::values.log_filter); |     filter.ParseFilterString(Settings::values.log_filter.GetValue()); | ||||||
|     Log::SetGlobalFilter(filter); |     Log::SetGlobalFilter(filter); | ||||||
|     Settings::values.use_cpu_jit = ui->toggle_cpu_jit->isChecked(); |     Settings::values.use_cpu_jit = ui->toggle_cpu_jit->isChecked(); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -7,11 +7,13 @@ | ||||||
| #include "citra_qt/configuration/config.h" | #include "citra_qt/configuration/config.h" | ||||||
| #include "citra_qt/configuration/configure_dialog.h" | #include "citra_qt/configuration/configure_dialog.h" | ||||||
| #include "citra_qt/hotkeys.h" | #include "citra_qt/hotkeys.h" | ||||||
| #include "core/settings.h" | #include "common/settings.h" | ||||||
| #include "ui_configure.h" | #include "ui_configure.h" | ||||||
| 
 | 
 | ||||||
| ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry, bool enable_web_config) | ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry, bool enable_web_config) | ||||||
|     : QDialog(parent), ui(std::make_unique<Ui::ConfigureDialog>()), registry(registry) { |     : QDialog(parent), ui(std::make_unique<Ui::ConfigureDialog>()), registry(registry) { | ||||||
|  |     Settings::SetConfiguringGlobal(true); | ||||||
|  | 
 | ||||||
|     ui->setupUi(this); |     ui->setupUi(this); | ||||||
|     ui->hotkeysTab->Populate(registry); |     ui->hotkeysTab->Populate(registry); | ||||||
|     ui->webTab->SetWebServiceConfigEnabled(enable_web_config); |     ui->webTab->SetWebServiceConfigEnabled(enable_web_config); | ||||||
|  |  | ||||||
|  | @ -4,8 +4,8 @@ | ||||||
| 
 | 
 | ||||||
| #include <QColorDialog> | #include <QColorDialog> | ||||||
| #include "citra_qt/configuration/configure_enhancements.h" | #include "citra_qt/configuration/configure_enhancements.h" | ||||||
|  | #include "common/settings.h" | ||||||
| #include "core/core.h" | #include "core/core.h" | ||||||
| #include "core/settings.h" |  | ||||||
| #include "ui_configure_enhancements.h" | #include "ui_configure_enhancements.h" | ||||||
| #include "video_core/renderer_opengl/post_processing_opengl.h" | #include "video_core/renderer_opengl/post_processing_opengl.h" | ||||||
| #include "video_core/renderer_opengl/texture_filters/texture_filterer.h" | #include "video_core/renderer_opengl/texture_filters/texture_filterer.h" | ||||||
|  | @ -21,7 +21,7 @@ ConfigureEnhancements::ConfigureEnhancements(QWidget* parent) | ||||||
| 
 | 
 | ||||||
|     ui->layoutBox->setEnabled(!Settings::values.custom_layout); |     ui->layoutBox->setEnabled(!Settings::values.custom_layout); | ||||||
| 
 | 
 | ||||||
|     ui->resolution_factor_combobox->setEnabled(Settings::values.use_hw_renderer); |     ui->resolution_factor_combobox->setEnabled(Settings::values.use_hw_renderer.GetValue()); | ||||||
| 
 | 
 | ||||||
|     connect(ui->render_3d_combobox, |     connect(ui->render_3d_combobox, | ||||||
|             static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, |             static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, | ||||||
|  | @ -50,27 +50,30 @@ ConfigureEnhancements::ConfigureEnhancements(QWidget* parent) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ConfigureEnhancements::SetConfiguration() { | void ConfigureEnhancements::SetConfiguration() { | ||||||
|     ui->resolution_factor_combobox->setCurrentIndex(Settings::values.resolution_factor); |     ui->resolution_factor_combobox->setCurrentIndex(Settings::values.resolution_factor.GetValue()); | ||||||
|     ui->render_3d_combobox->setCurrentIndex(static_cast<int>(Settings::values.render_3d)); |     ui->render_3d_combobox->setCurrentIndex( | ||||||
|     ui->factor_3d->setValue(Settings::values.factor_3d); |         static_cast<int>(Settings::values.render_3d.GetValue())); | ||||||
|     ui->mono_render_left_eye->setChecked(Settings::values.mono_render_left_eye); |     ui->factor_3d->setValue(Settings::values.factor_3d.GetValue()); | ||||||
|     updateShaders(Settings::values.render_3d); |     ui->mono_render_left_eye->setChecked(Settings::values.mono_render_left_eye.GetValue()); | ||||||
|     ui->toggle_linear_filter->setChecked(Settings::values.filter_mode); |     updateShaders(Settings::values.render_3d.GetValue()); | ||||||
|  |     ui->toggle_linear_filter->setChecked(Settings::values.filter_mode.GetValue()); | ||||||
|     int tex_filter_idx = ui->texture_filter_combobox->findText( |     int tex_filter_idx = ui->texture_filter_combobox->findText( | ||||||
|         QString::fromStdString(Settings::values.texture_filter_name)); |         QString::fromStdString(Settings::values.texture_filter_name.GetValue())); | ||||||
|     if (tex_filter_idx == -1) { |     if (tex_filter_idx == -1) { | ||||||
|         ui->texture_filter_combobox->setCurrentIndex(0); |         ui->texture_filter_combobox->setCurrentIndex(0); | ||||||
|     } else { |     } else { | ||||||
|         ui->texture_filter_combobox->setCurrentIndex(tex_filter_idx); |         ui->texture_filter_combobox->setCurrentIndex(tex_filter_idx); | ||||||
|     } |     } | ||||||
|     ui->layout_combobox->setCurrentIndex(static_cast<int>(Settings::values.layout_option)); |     ui->layout_combobox->setCurrentIndex( | ||||||
|     ui->swap_screen->setChecked(Settings::values.swap_screen); |         static_cast<int>(Settings::values.layout_option.GetValue())); | ||||||
|     ui->upright_screen->setChecked(Settings::values.upright_screen); |     ui->swap_screen->setChecked(Settings::values.swap_screen.GetValue()); | ||||||
|     ui->toggle_dump_textures->setChecked(Settings::values.dump_textures); |     ui->upright_screen->setChecked(Settings::values.upright_screen.GetValue()); | ||||||
|     ui->toggle_custom_textures->setChecked(Settings::values.custom_textures); |     ui->toggle_dump_textures->setChecked(Settings::values.dump_textures.GetValue()); | ||||||
|     ui->toggle_preload_textures->setChecked(Settings::values.preload_textures); |     ui->toggle_custom_textures->setChecked(Settings::values.custom_textures.GetValue()); | ||||||
|     bg_color = QColor::fromRgbF(Settings::values.bg_red, Settings::values.bg_green, |     ui->toggle_preload_textures->setChecked(Settings::values.preload_textures.GetValue()); | ||||||
|                                 Settings::values.bg_blue); |     bg_color = | ||||||
|  |         QColor::fromRgbF(Settings::values.bg_red.GetValue(), Settings::values.bg_green.GetValue(), | ||||||
|  |                          Settings::values.bg_blue.GetValue()); | ||||||
|     QPixmap pixmap(ui->bg_button->size()); |     QPixmap pixmap(ui->bg_button->size()); | ||||||
|     pixmap.fill(bg_color); |     pixmap.fill(bg_color); | ||||||
|     const QIcon color_icon(pixmap); |     const QIcon color_icon(pixmap); | ||||||
|  | @ -93,7 +96,7 @@ void ConfigureEnhancements::updateShaders(Settings::StereoRenderOption stereo_op | ||||||
|     for (const auto& shader : OpenGL::GetPostProcessingShaderList( |     for (const auto& shader : OpenGL::GetPostProcessingShaderList( | ||||||
|              stereo_option == Settings::StereoRenderOption::Anaglyph)) { |              stereo_option == Settings::StereoRenderOption::Anaglyph)) { | ||||||
|         ui->shader_combobox->addItem(QString::fromStdString(shader)); |         ui->shader_combobox->addItem(QString::fromStdString(shader)); | ||||||
|         if (Settings::values.pp_shader_name == shader) |         if (Settings::values.pp_shader_name.GetValue() == shader) | ||||||
|             ui->shader_combobox->setCurrentIndex(ui->shader_combobox->count() - 1); |             ui->shader_combobox->setCurrentIndex(ui->shader_combobox->count() - 1); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -6,9 +6,10 @@ | ||||||
| 
 | 
 | ||||||
| #include <memory> | #include <memory> | ||||||
| #include <QWidget> | #include <QWidget> | ||||||
|  | #include "common/common_types.h" | ||||||
| 
 | 
 | ||||||
| namespace Settings { | namespace Settings { | ||||||
| enum class StereoRenderOption; | enum class StereoRenderOption : u32; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| namespace Ui { | namespace Ui { | ||||||
|  |  | ||||||
|  | @ -6,10 +6,11 @@ | ||||||
| #include <QFileDialog> | #include <QFileDialog> | ||||||
| #include <QMessageBox> | #include <QMessageBox> | ||||||
| #include <QUrl> | #include <QUrl> | ||||||
|  | #include "citra_qt/configuration/configuration_shared.h" | ||||||
| #include "citra_qt/configuration/configure_general.h" | #include "citra_qt/configuration/configure_general.h" | ||||||
| #include "citra_qt/uisettings.h" | #include "citra_qt/uisettings.h" | ||||||
| #include "core/core.h" | #include "common/file_util.h" | ||||||
| #include "core/settings.h" | #include "common/settings.h" | ||||||
| #include "ui_configure_general.h" | #include "ui_configure_general.h" | ||||||
| 
 | 
 | ||||||
| // The QSlider doesn't have an easy way to set a custom step amount,
 | // The QSlider doesn't have an easy way to set a custom step amount,
 | ||||||
|  | @ -31,14 +32,17 @@ ConfigureGeneral::ConfigureGeneral(QWidget* parent) | ||||||
|     // Set a minimum width for the label to prevent the slider from changing size.
 |     // Set a minimum width for the label to prevent the slider from changing size.
 | ||||||
|     // This scales across DPIs, and is acceptable for uncapitalized strings.
 |     // This scales across DPIs, and is acceptable for uncapitalized strings.
 | ||||||
|     ui->emulation_speed_display_label->setMinimumWidth(tr("unthrottled").size() * 6); |     ui->emulation_speed_display_label->setMinimumWidth(tr("unthrottled").size() * 6); | ||||||
|  |     ui->emulation_speed_combo->setVisible(!Settings::IsConfiguringGlobal()); | ||||||
|  |     ui->screenshot_combo->setVisible(!Settings::IsConfiguringGlobal()); | ||||||
| 
 | 
 | ||||||
|  |     SetupPerGameUI(); | ||||||
|     SetConfiguration(); |     SetConfiguration(); | ||||||
| 
 | 
 | ||||||
|     ui->updateBox->setVisible(UISettings::values.updater_found); |     ui->updateBox->setVisible(UISettings::values.updater_found); | ||||||
|     connect(ui->button_reset_defaults, &QPushButton::clicked, this, |     connect(ui->button_reset_defaults, &QPushButton::clicked, this, | ||||||
|             &ConfigureGeneral::ResetDefaults); |             &ConfigureGeneral::ResetDefaults); | ||||||
| 
 | 
 | ||||||
|     connect(ui->frame_limit, &QSlider::valueChanged, [&](int value) { |     connect(ui->frame_limit, &QSlider::valueChanged, this, [&](int value) { | ||||||
|         if (value == ui->frame_limit->maximum()) { |         if (value == ui->frame_limit->maximum()) { | ||||||
|             ui->emulation_speed_display_label->setText(tr("unthrottled")); |             ui->emulation_speed_display_label->setText(tr("unthrottled")); | ||||||
|         } else { |         } else { | ||||||
|  | @ -49,17 +53,6 @@ ConfigureGeneral::ConfigureGeneral(QWidget* parent) | ||||||
|         } |         } | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     connect(ui->frame_limit_alternate, &QSlider::valueChanged, [&](int value) { |  | ||||||
|         if (value == ui->frame_limit_alternate->maximum()) { |  | ||||||
|             ui->emulation_speed_alternate_display_label->setText(tr("unthrottled")); |  | ||||||
|         } else { |  | ||||||
|             ui->emulation_speed_alternate_display_label->setText( |  | ||||||
|                 QStringLiteral("%1%") |  | ||||||
|                     .arg(SliderToSettings(value)) |  | ||||||
|                     .rightJustified(tr("unthrottled").size())); |  | ||||||
|         } |  | ||||||
|     }); |  | ||||||
| 
 |  | ||||||
|     connect(ui->change_screenshot_dir, &QToolButton::clicked, this, [this] { |     connect(ui->change_screenshot_dir, &QToolButton::clicked, this, [this] { | ||||||
|         const QString dir_path = QFileDialog::getExistingDirectory( |         const QString dir_path = QFileDialog::getExistingDirectory( | ||||||
|             this, tr("Select Screenshot Directory"), ui->screenshot_dir_path->text(), |             this, tr("Select Screenshot Directory"), ui->screenshot_dir_path->text(), | ||||||
|  | @ -73,20 +66,21 @@ ConfigureGeneral::ConfigureGeneral(QWidget* parent) | ||||||
| ConfigureGeneral::~ConfigureGeneral() = default; | ConfigureGeneral::~ConfigureGeneral() = default; | ||||||
| 
 | 
 | ||||||
| void ConfigureGeneral::SetConfiguration() { | void ConfigureGeneral::SetConfiguration() { | ||||||
|     ui->toggle_check_exit->setChecked(UISettings::values.confirm_before_closing); |     if (Settings::IsConfiguringGlobal()) { | ||||||
|     ui->toggle_background_pause->setChecked(UISettings::values.pause_when_in_background); |         ui->toggle_check_exit->setChecked(UISettings::values.confirm_before_closing.GetValue()); | ||||||
|     ui->toggle_hide_mouse->setChecked(UISettings::values.hide_mouse); |         ui->toggle_background_pause->setChecked( | ||||||
|  |             UISettings::values.pause_when_in_background.GetValue()); | ||||||
|  |         ui->toggle_hide_mouse->setChecked(UISettings::values.hide_mouse.GetValue()); | ||||||
| 
 | 
 | ||||||
|     ui->toggle_update_check->setChecked(UISettings::values.check_for_update_on_start); |         ui->toggle_update_check->setChecked( | ||||||
|     ui->toggle_auto_update->setChecked(UISettings::values.update_on_close); |             UISettings::values.check_for_update_on_start.GetValue()); | ||||||
|  |         ui->toggle_auto_update->setChecked(UISettings::values.update_on_close.GetValue()); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     // The first item is "auto-select" with actual value -1, so plus one here will do the trick
 |     if (Settings::values.frame_limit.GetValue() == 0) { | ||||||
|     ui->region_combobox->setCurrentIndex(Settings::values.region_value + 1); |  | ||||||
| 
 |  | ||||||
|     if (Settings::values.frame_limit == 0) { |  | ||||||
|         ui->frame_limit->setValue(ui->frame_limit->maximum()); |         ui->frame_limit->setValue(ui->frame_limit->maximum()); | ||||||
|     } else { |     } else { | ||||||
|         ui->frame_limit->setValue(SettingsToSlider(Settings::values.frame_limit)); |         ui->frame_limit->setValue(SettingsToSlider(Settings::values.frame_limit.GetValue())); | ||||||
|     } |     } | ||||||
|     if (ui->frame_limit->value() == ui->frame_limit->maximum()) { |     if (ui->frame_limit->value() == ui->frame_limit->maximum()) { | ||||||
|         ui->emulation_speed_display_label->setText(tr("unthrottled")); |         ui->emulation_speed_display_label->setText(tr("unthrottled")); | ||||||
|  | @ -97,32 +91,48 @@ void ConfigureGeneral::SetConfiguration() { | ||||||
|                 .rightJustified(tr("unthrottled").size())); |                 .rightJustified(tr("unthrottled").size())); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     ui->toggle_alternate_speed->setChecked(Settings::values.use_frame_limit_alternate); |     if (!Settings::IsConfiguringGlobal()) { | ||||||
| 
 |         if (Settings::values.frame_limit.UsingGlobal()) { | ||||||
|     if (Settings::values.frame_limit_alternate == 0) { |             ui->emulation_speed_combo->setCurrentIndex(0); | ||||||
|         ui->frame_limit_alternate->setValue(ui->frame_limit_alternate->maximum()); |             ui->frame_limit->setEnabled(false); | ||||||
|  |         } else { | ||||||
|  |             ui->emulation_speed_combo->setCurrentIndex(1); | ||||||
|  |             ui->frame_limit->setEnabled(true); | ||||||
|  |         } | ||||||
|  |         if (UISettings::values.screenshot_path.UsingGlobal()) { | ||||||
|  |             ui->screenshot_combo->setCurrentIndex(0); | ||||||
|  |             ui->screenshot_dir_path->setEnabled(false); | ||||||
|  |             ui->change_screenshot_dir->setEnabled(false); | ||||||
|  |         } else { | ||||||
|  |             ui->screenshot_combo->setCurrentIndex(1); | ||||||
|  |             ui->screenshot_dir_path->setEnabled(true); | ||||||
|  |             ui->change_screenshot_dir->setEnabled(true); | ||||||
|  |         } | ||||||
|  |         ConfigurationShared::SetHighlight(ui->widget_screenshot, | ||||||
|  |                                           !UISettings::values.screenshot_path.UsingGlobal()); | ||||||
|  |         ConfigurationShared::SetHighlight(ui->emulation_speed_layout, | ||||||
|  |                                           !Settings::values.frame_limit.UsingGlobal()); | ||||||
|  |         ConfigurationShared::SetHighlight(ui->widget_region, | ||||||
|  |                                           !Settings::values.region_value.UsingGlobal()); | ||||||
|  |         const bool is_region_global = Settings::values.region_value.UsingGlobal(); | ||||||
|  |         ui->region_combobox->setCurrentIndex( | ||||||
|  |             is_region_global ? ConfigurationShared::USE_GLOBAL_INDEX | ||||||
|  |                              : static_cast<int>(Settings::values.region_value.GetValue()) + | ||||||
|  |                                    ConfigurationShared::USE_GLOBAL_OFFSET + 1); | ||||||
|     } else { |     } else { | ||||||
|         ui->frame_limit_alternate->setValue( |         // The first item is "auto-select" with actual value -1, so plus one here will do the trick
 | ||||||
|             SettingsToSlider(Settings::values.frame_limit_alternate)); |         ui->region_combobox->setCurrentIndex(Settings::values.region_value.GetValue() + 1); | ||||||
|     } |  | ||||||
|     if (ui->frame_limit_alternate->value() == ui->frame_limit_alternate->maximum()) { |  | ||||||
|         ui->emulation_speed_alternate_display_label->setText(tr("unthrottled")); |  | ||||||
|     } else { |  | ||||||
|         ui->emulation_speed_alternate_display_label->setText( |  | ||||||
|             QStringLiteral("%1%") |  | ||||||
|                 .arg(SliderToSettings(ui->frame_limit_alternate->value())) |  | ||||||
|                 .rightJustified(tr("unthrottled").size())); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     QString screenshot_path = UISettings::values.screenshot_path; |     UISettings::values.screenshot_path.SetGlobal(ui->screenshot_combo->currentIndex() == | ||||||
|     if (screenshot_path.isEmpty()) { |                                                  ConfigurationShared::USE_GLOBAL_INDEX); | ||||||
|         screenshot_path = |     std::string screenshot_path = UISettings::values.screenshot_path.GetValue(); | ||||||
|             QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::UserDir)); |     if (screenshot_path.empty()) { | ||||||
|         screenshot_path.append(QStringLiteral("screenshots/")); |         screenshot_path = FileUtil::GetUserPath(FileUtil::UserPath::UserDir) + "screenshots/"; | ||||||
|         FileUtil::CreateFullPath(screenshot_path.toStdString()); |         FileUtil::CreateFullPath(screenshot_path); | ||||||
|         UISettings::values.screenshot_path = screenshot_path; |         UISettings::values.screenshot_path = screenshot_path; | ||||||
|     } |     } | ||||||
|     ui->screenshot_dir_path->setText(screenshot_path); |     ui->screenshot_dir_path->setText(QString::fromStdString(screenshot_path)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ConfigureGeneral::ResetDefaults() { | void ConfigureGeneral::ResetDefaults() { | ||||||
|  | @ -139,31 +149,57 @@ void ConfigureGeneral::ResetDefaults() { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ConfigureGeneral::ApplyConfiguration() { | void ConfigureGeneral::ApplyConfiguration() { | ||||||
|     UISettings::values.confirm_before_closing = ui->toggle_check_exit->isChecked(); |     ConfigurationShared::ApplyPerGameSetting(&Settings::values.region_value, ui->region_combobox, | ||||||
|     UISettings::values.pause_when_in_background = ui->toggle_background_pause->isChecked(); |                                              [](s32 index) { return index - 1; }); | ||||||
|     UISettings::values.hide_mouse = ui->toggle_hide_mouse->isChecked(); |  | ||||||
| 
 | 
 | ||||||
|     UISettings::values.check_for_update_on_start = ui->toggle_update_check->isChecked(); |     ConfigurationShared::ApplyPerGameSetting( | ||||||
|     UISettings::values.update_on_close = ui->toggle_auto_update->isChecked(); |         &Settings::values.frame_limit, ui->emulation_speed_combo, [this](s32) { | ||||||
|  |             const bool is_maximum = ui->frame_limit->value() == ui->frame_limit->maximum(); | ||||||
|  |             return is_maximum ? 0 : SliderToSettings(ui->frame_limit->value()); | ||||||
|  |         }); | ||||||
| 
 | 
 | ||||||
|     UISettings::values.screenshot_path = ui->screenshot_dir_path->text(); |     ConfigurationShared::ApplyPerGameSetting( | ||||||
|  |         &UISettings::values.screenshot_path, ui->screenshot_combo, | ||||||
|  |         [this](s32) { return ui->screenshot_dir_path->text().toStdString(); }); | ||||||
| 
 | 
 | ||||||
|     Settings::values.region_value = ui->region_combobox->currentIndex() - 1; |     if (Settings::IsConfiguringGlobal()) { | ||||||
|  |         UISettings::values.confirm_before_closing = ui->toggle_check_exit->isChecked(); | ||||||
|  |         UISettings::values.pause_when_in_background = ui->toggle_background_pause->isChecked(); | ||||||
|  |         UISettings::values.hide_mouse = ui->toggle_hide_mouse->isChecked(); | ||||||
| 
 | 
 | ||||||
|     if (ui->frame_limit->value() == ui->frame_limit->maximum()) { |         UISettings::values.check_for_update_on_start = ui->toggle_update_check->isChecked(); | ||||||
|         Settings::values.frame_limit = 0; |         UISettings::values.update_on_close = ui->toggle_auto_update->isChecked(); | ||||||
|     } else { |  | ||||||
|         Settings::values.frame_limit = SliderToSettings(ui->frame_limit->value()); |  | ||||||
|     } |  | ||||||
|     Settings::values.use_frame_limit_alternate = ui->toggle_alternate_speed->isChecked(); |  | ||||||
|     if (ui->frame_limit_alternate->value() == ui->frame_limit_alternate->maximum()) { |  | ||||||
|         Settings::values.frame_limit_alternate = 0; |  | ||||||
|     } else { |  | ||||||
|         Settings::values.frame_limit_alternate = |  | ||||||
|             SliderToSettings(ui->frame_limit_alternate->value()); |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ConfigureGeneral::RetranslateUI() { | void ConfigureGeneral::RetranslateUI() { | ||||||
|     ui->retranslateUi(this); |     ui->retranslateUi(this); | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | void ConfigureGeneral::SetupPerGameUI() { | ||||||
|  |     if (Settings::IsConfiguringGlobal()) { | ||||||
|  |         ui->region_combobox->setEnabled(Settings::values.region_value.UsingGlobal()); | ||||||
|  |         ui->frame_limit->setEnabled(Settings::values.frame_limit.UsingGlobal()); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     connect(ui->emulation_speed_combo, qOverload<int>(&QComboBox::activated), this, | ||||||
|  |             [this](int index) { | ||||||
|  |                 ui->frame_limit->setEnabled(index == 1); | ||||||
|  |                 ConfigurationShared::SetHighlight(ui->emulation_speed_layout, index == 1); | ||||||
|  |             }); | ||||||
|  | 
 | ||||||
|  |     connect(ui->screenshot_combo, qOverload<int>(&QComboBox::activated), this, [this](int index) { | ||||||
|  |         ui->screenshot_dir_path->setEnabled(index == 1); | ||||||
|  |         ui->change_screenshot_dir->setEnabled(index == 1); | ||||||
|  |         ConfigurationShared::SetHighlight(ui->widget_screenshot, index == 1); | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     ui->general_group->setVisible(false); | ||||||
|  |     ui->updateBox->setVisible(false); | ||||||
|  |     ui->button_reset_defaults->setVisible(false); | ||||||
|  | 
 | ||||||
|  |     ConfigurationShared::SetColoredComboBox( | ||||||
|  |         ui->region_combobox, ui->widget_region, | ||||||
|  |         static_cast<u32>(Settings::values.region_value.GetValue(true) + 1)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -25,6 +25,8 @@ public: | ||||||
|     void RetranslateUI(); |     void RetranslateUI(); | ||||||
|     void SetConfiguration(); |     void SetConfiguration(); | ||||||
| 
 | 
 | ||||||
|  |     void SetupPerGameUI(); | ||||||
|  | 
 | ||||||
| private: | private: | ||||||
|     std::unique_ptr<Ui::ConfigureGeneral> ui; |     std::unique_ptr<Ui::ConfigureGeneral> ui; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | @ -6,8 +6,8 @@ | ||||||
|    <rect> |    <rect> | ||||||
|     <x>0</x> |     <x>0</x> | ||||||
|     <y>0</y> |     <y>0</y> | ||||||
|     <width>408</width> |     <width>524</width> | ||||||
|     <height>436</height> |     <height>578</height> | ||||||
|    </rect> |    </rect> | ||||||
|   </property> |   </property> | ||||||
|   <property name="windowTitle"> |   <property name="windowTitle"> | ||||||
|  | @ -17,7 +17,7 @@ | ||||||
|    <item> |    <item> | ||||||
|     <layout class="QVBoxLayout" name="verticalLayout"> |     <layout class="QVBoxLayout" name="verticalLayout"> | ||||||
|      <item> |      <item> | ||||||
|       <widget class="QGroupBox" name="groupBox"> |       <widget class="QGroupBox" name="general_group"> | ||||||
|        <property name="title"> |        <property name="title"> | ||||||
|         <string>General</string> |         <string>General</string> | ||||||
|        </property> |        </property> | ||||||
|  | @ -70,144 +70,152 @@ | ||||||
|       </widget> |       </widget> | ||||||
|      </item> |      </item> | ||||||
|      <item> |      <item> | ||||||
|       <widget class="QGroupBox" name="groupBox_4"> |       <widget class="QGroupBox" name="emulation_group"> | ||||||
|        <property name="title"> |        <property name="title"> | ||||||
|         <string>Emulation</string> |         <string>Emulation</string> | ||||||
|        </property> |        </property> | ||||||
|        <layout class="QGridLayout" name="gridLayout"> |        <layout class="QVBoxLayout" name="verticalLayout_2"> | ||||||
|         <item row="0" column="2"> |         <item> | ||||||
|          <widget class="QComboBox" name="region_combobox"> |          <widget class="QWidget" name="widget_region" native="true"> | ||||||
|           <item> |           <layout class="QHBoxLayout" name="region_layout"> | ||||||
|            <property name="text"> |            <property name="leftMargin"> | ||||||
|             <string>Auto-select</string> |             <number>0</number> | ||||||
|            </property> |            </property> | ||||||
|           </item> |            <property name="topMargin"> | ||||||
|           <item> |             <number>0</number> | ||||||
|            <property name="text"> |  | ||||||
|             <string notr="true">JPN</string> |  | ||||||
|            </property> |            </property> | ||||||
|           </item> |            <property name="rightMargin"> | ||||||
|           <item> |             <number>0</number> | ||||||
|            <property name="text"> |  | ||||||
|             <string notr="true">USA</string> |  | ||||||
|            </property> |            </property> | ||||||
|           </item> |            <property name="bottomMargin"> | ||||||
|           <item> |             <number>0</number> | ||||||
|            <property name="text"> |  | ||||||
|             <string notr="true">EUR</string> |  | ||||||
|            </property> |            </property> | ||||||
|           </item> |            <item> | ||||||
|           <item> |             <widget class="QLabel" name="region_label"> | ||||||
|            <property name="text"> |              <property name="text"> | ||||||
|             <string notr="true">AUS</string> |               <string>Region:</string> | ||||||
|            </property> |              </property> | ||||||
|           </item> |             </widget> | ||||||
|           <item> |            </item> | ||||||
|            <property name="text"> |            <item> | ||||||
|             <string notr="true">CHN</string> |             <widget class="QComboBox" name="region_combobox"> | ||||||
|            </property> |              <item> | ||||||
|           </item> |               <property name="text"> | ||||||
|           <item> |                <string>Auto-select</string> | ||||||
|            <property name="text"> |               </property> | ||||||
|             <string notr="true">KOR</string> |              </item> | ||||||
|            </property> |              <item> | ||||||
|           </item> |               <property name="text"> | ||||||
|           <item> |                <string notr="true">JPN</string> | ||||||
|            <property name="text"> |               </property> | ||||||
|             <string notr="true">TWN</string> |              </item> | ||||||
|            </property> |              <item> | ||||||
|           </item> |               <property name="text"> | ||||||
|  |                <string notr="true">USA</string> | ||||||
|  |               </property> | ||||||
|  |              </item> | ||||||
|  |              <item> | ||||||
|  |               <property name="text"> | ||||||
|  |                <string notr="true">EUR</string> | ||||||
|  |               </property> | ||||||
|  |              </item> | ||||||
|  |              <item> | ||||||
|  |               <property name="text"> | ||||||
|  |                <string notr="true">AUS</string> | ||||||
|  |               </property> | ||||||
|  |              </item> | ||||||
|  |              <item> | ||||||
|  |               <property name="text"> | ||||||
|  |                <string notr="true">CHN</string> | ||||||
|  |               </property> | ||||||
|  |              </item> | ||||||
|  |              <item> | ||||||
|  |               <property name="text"> | ||||||
|  |                <string notr="true">KOR</string> | ||||||
|  |               </property> | ||||||
|  |              </item> | ||||||
|  |              <item> | ||||||
|  |               <property name="text"> | ||||||
|  |                <string notr="true">TWN</string> | ||||||
|  |               </property> | ||||||
|  |              </item> | ||||||
|  |             </widget> | ||||||
|  |            </item> | ||||||
|  |           </layout> | ||||||
|          </widget> |          </widget> | ||||||
|         </item> |         </item> | ||||||
|         <item row="1" column="0"> |         <item> | ||||||
|          <widget class="QLabel" name="label_emulation_speed"> |          <widget class="QWidget" name="emulation_speed_layout" native="true"> | ||||||
|           <property name="text"> |           <layout class="QHBoxLayout" name="emulation_speed_layout_inner"> | ||||||
|            <string>Emulation Speed:</string> |            <property name="leftMargin"> | ||||||
|           </property> |             <number>0</number> | ||||||
|          </widget> |            </property> | ||||||
|         </item> |            <property name="topMargin"> | ||||||
|         <item row="2" column="0"> |             <number>0</number> | ||||||
|          <widget class="QCheckBox" name="toggle_alternate_speed"> |            </property> | ||||||
|           <property name="text"> |            <property name="rightMargin"> | ||||||
|            <string>Use Alternate Speed:</string> |             <number>0</number> | ||||||
|           </property> |            </property> | ||||||
|          </widget> |            <property name="bottomMargin"> | ||||||
|         </item> |             <number>0</number> | ||||||
|         <item row="1" column="2"> |            </property> | ||||||
|          <widget class="QSlider" name="frame_limit"> |            <item> | ||||||
|           <property name="minimum"> |             <widget class="QComboBox" name="emulation_speed_combo"> | ||||||
|            <number>0</number> |              <item> | ||||||
|           </property> |               <property name="text"> | ||||||
|           <property name="maximum"> |                <string>Use global emulation speed</string> | ||||||
|            <number>199</number> |               </property> | ||||||
|           </property> |              </item> | ||||||
|           <property name="singleStep"> |              <item> | ||||||
|            <number>5</number> |               <property name="text"> | ||||||
|           </property> |                <string>Set emulation speed:</string> | ||||||
|           <property name="pageStep"> |               </property> | ||||||
|            <number>15</number> |              </item> | ||||||
|           </property> |             </widget> | ||||||
|           <property name="value"> |            </item> | ||||||
|            <number>19</number> |            <item> | ||||||
|           </property> |             <widget class="QLabel" name="label_emulation_speed"> | ||||||
|           <property name="orientation"> |              <property name="text"> | ||||||
|            <enum>Qt::Horizontal</enum> |               <string>Emulation Speed:</string> | ||||||
|           </property> |              </property> | ||||||
|           <property name="tickPosition"> |             </widget> | ||||||
|            <enum>QSlider::TicksBelow</enum> |            </item> | ||||||
|           </property> |            <item> | ||||||
|          </widget> |             <widget class="QSlider" name="frame_limit"> | ||||||
|         </item> |              <property name="minimum"> | ||||||
|         <item row="1" column="1"> |               <number>0</number> | ||||||
|          <widget class="QLabel" name="emulation_speed_display_label"> |              </property> | ||||||
|           <property name="text"> |              <property name="maximum"> | ||||||
|            <string/> |               <number>199</number> | ||||||
|           </property> |              </property> | ||||||
|           <property name="alignment"> |              <property name="singleStep"> | ||||||
|            <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> |               <number>5</number> | ||||||
|           </property> |              </property> | ||||||
|          </widget> |              <property name="pageStep"> | ||||||
|         </item> |               <number>15</number> | ||||||
|         <item row="0" column="0"> |              </property> | ||||||
|          <widget class="QLabel" name="label"> |              <property name="value"> | ||||||
|           <property name="text"> |               <number>19</number> | ||||||
|            <string>Region:</string> |              </property> | ||||||
|           </property> |              <property name="orientation"> | ||||||
|          </widget> |               <enum>Qt::Horizontal</enum> | ||||||
|         </item> |              </property> | ||||||
|         <item row="2" column="2"> |              <property name="tickPosition"> | ||||||
|          <widget class="QSlider" name="frame_limit_alternate"> |               <enum>QSlider::TicksBelow</enum> | ||||||
|           <property name="minimum"> |              </property> | ||||||
|            <number>0</number> |             </widget> | ||||||
|           </property> |            </item> | ||||||
|           <property name="maximum"> |            <item> | ||||||
|            <number>199</number> |             <widget class="QLabel" name="emulation_speed_display_label"> | ||||||
|           </property> |              <property name="text"> | ||||||
|           <property name="singleStep"> |               <string/> | ||||||
|            <number>5</number> |              </property> | ||||||
|           </property> |              <property name="alignment"> | ||||||
|           <property name="pageStep"> |               <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> | ||||||
|            <number>15</number> |              </property> | ||||||
|           </property> |             </widget> | ||||||
|           <property name="value"> |            </item> | ||||||
|            <number>39</number> |           </layout> | ||||||
|           </property> |  | ||||||
|           <property name="orientation"> |  | ||||||
|            <enum>Qt::Horizontal</enum> |  | ||||||
|           </property> |  | ||||||
|           <property name="tickPosition"> |  | ||||||
|            <enum>QSlider::TicksBelow</enum> |  | ||||||
|           </property> |  | ||||||
|          </widget> |  | ||||||
|         </item> |  | ||||||
|         <item row="2" column="1"> |  | ||||||
|          <widget class="QLabel" name="emulation_speed_alternate_display_label"> |  | ||||||
|           <property name="text"> |  | ||||||
|            <string/> |  | ||||||
|           </property> |  | ||||||
|           <property name="alignment"> |  | ||||||
|            <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> |  | ||||||
|           </property> |  | ||||||
|          </widget> |          </widget> | ||||||
|         </item> |         </item> | ||||||
|        </layout> |        </layout> | ||||||
|  | @ -218,23 +226,57 @@ | ||||||
|        <property name="title"> |        <property name="title"> | ||||||
|         <string>Screenshots</string> |         <string>Screenshots</string> | ||||||
|        </property> |        </property> | ||||||
|        <layout class="QHBoxLayout" name="horizontalLayout_2"> |        <layout class="QGridLayout" name="gridLayout"> | ||||||
|         <item> |         <property name="verticalSpacing"> | ||||||
|          <widget class="QLabel" name="label_2"> |          <number>0</number> | ||||||
|           <property name="text"> |         </property> | ||||||
|            <string>Save Screenshots To</string> |         <item row="0" column="1"> | ||||||
|           </property> |          <widget class="QWidget" name="widget_screenshot" native="true"> | ||||||
|          </widget> |           <layout class="QHBoxLayout" name="screenshot_layout"> | ||||||
|         </item> |            <property name="leftMargin"> | ||||||
|         <item> |             <number>0</number> | ||||||
|          <widget class="QLineEdit" name="screenshot_dir_path"> |            </property> | ||||||
|          </widget> |            <property name="topMargin"> | ||||||
|         </item> |             <number>0</number> | ||||||
|         <item> |            </property> | ||||||
|          <widget class="QToolButton" name="change_screenshot_dir"> |            <property name="rightMargin"> | ||||||
|           <property name="text"> |             <number>0</number> | ||||||
|            <string>...</string> |            </property> | ||||||
|           </property> |            <property name="bottomMargin"> | ||||||
|  |             <number>0</number> | ||||||
|  |            </property> | ||||||
|  |            <item> | ||||||
|  |             <widget class="QComboBox" name="screenshot_combo"> | ||||||
|  |              <item> | ||||||
|  |               <property name="text"> | ||||||
|  |                <string>Use global screenshot path</string> | ||||||
|  |               </property> | ||||||
|  |              </item> | ||||||
|  |              <item> | ||||||
|  |               <property name="text"> | ||||||
|  |                <string>Set screenshot path:</string> | ||||||
|  |               </property> | ||||||
|  |              </item> | ||||||
|  |             </widget> | ||||||
|  |            </item> | ||||||
|  |            <item> | ||||||
|  |             <widget class="QLabel" name="screenshot_dir_label"> | ||||||
|  |              <property name="text"> | ||||||
|  |               <string>Save Screenshots To</string> | ||||||
|  |              </property> | ||||||
|  |             </widget> | ||||||
|  |            </item> | ||||||
|  |            <item> | ||||||
|  |             <widget class="QLineEdit" name="screenshot_dir_path"/> | ||||||
|  |            </item> | ||||||
|  |            <item> | ||||||
|  |             <widget class="QToolButton" name="change_screenshot_dir"> | ||||||
|  |              <property name="text"> | ||||||
|  |               <string>...</string> | ||||||
|  |              </property> | ||||||
|  |             </widget> | ||||||
|  |            </item> | ||||||
|  |           </layout> | ||||||
|          </widget> |          </widget> | ||||||
|         </item> |         </item> | ||||||
|        </layout> |        </layout> | ||||||
|  | @ -270,12 +312,6 @@ | ||||||
|   <tabstop>toggle_hide_mouse</tabstop> |   <tabstop>toggle_hide_mouse</tabstop> | ||||||
|   <tabstop>toggle_update_check</tabstop> |   <tabstop>toggle_update_check</tabstop> | ||||||
|   <tabstop>toggle_auto_update</tabstop> |   <tabstop>toggle_auto_update</tabstop> | ||||||
|   <tabstop>region_combobox</tabstop> |  | ||||||
|   <tabstop>frame_limit</tabstop> |  | ||||||
|   <tabstop>toggle_alternate_speed</tabstop> |  | ||||||
|   <tabstop>frame_limit_alternate</tabstop> |  | ||||||
|   <tabstop>screenshot_dir_path</tabstop> |  | ||||||
|   <tabstop>change_screenshot_dir</tabstop> |  | ||||||
|   <tabstop>button_reset_defaults</tabstop> |   <tabstop>button_reset_defaults</tabstop> | ||||||
|  </tabstops> |  </tabstops> | ||||||
|  <resources/> |  <resources/> | ||||||
|  |  | ||||||
|  | @ -6,22 +6,25 @@ | ||||||
| #ifdef __APPLE__ | #ifdef __APPLE__ | ||||||
| #include <QMessageBox> | #include <QMessageBox> | ||||||
| #endif | #endif | ||||||
|  | #include "citra_qt/configuration/configuration_shared.h" | ||||||
| #include "citra_qt/configuration/configure_graphics.h" | #include "citra_qt/configuration/configure_graphics.h" | ||||||
|  | #include "common/settings.h" | ||||||
| #include "core/core.h" | #include "core/core.h" | ||||||
| #include "core/settings.h" |  | ||||||
| #include "ui_configure_graphics.h" | #include "ui_configure_graphics.h" | ||||||
| #include "video_core/renderer_opengl/post_processing_opengl.h" |  | ||||||
| 
 | 
 | ||||||
| ConfigureGraphics::ConfigureGraphics(QWidget* parent) | ConfigureGraphics::ConfigureGraphics(QWidget* parent) | ||||||
|     : QWidget(parent), ui(std::make_unique<Ui::ConfigureGraphics>()) { |     : QWidget(parent), ui(std::make_unique<Ui::ConfigureGraphics>()) { | ||||||
|     ui->setupUi(this); |     ui->setupUi(this); | ||||||
|  | 
 | ||||||
|  |     SetupPerGameUI(); | ||||||
|     SetConfiguration(); |     SetConfiguration(); | ||||||
| 
 | 
 | ||||||
|     ui->hw_renderer_group->setEnabled(ui->toggle_hw_renderer->isChecked()); |     ui->hw_renderer_group->setEnabled(ui->hw_renderer_group->isEnabled() && | ||||||
|  |                                       ui->toggle_hw_renderer->isChecked()); | ||||||
|     ui->toggle_vsync_new->setEnabled(!Core::System::GetInstance().IsPoweredOn()); |     ui->toggle_vsync_new->setEnabled(!Core::System::GetInstance().IsPoweredOn()); | ||||||
| 
 | 
 | ||||||
|     connect(ui->toggle_hw_renderer, &QCheckBox::toggled, this, [this] { |     connect(ui->toggle_hw_renderer, &QCheckBox::toggled, this, [this] { | ||||||
|         auto checked = ui->toggle_hw_renderer->isChecked(); |         const bool checked = ui->toggle_hw_renderer->isChecked(); | ||||||
|         ui->hw_renderer_group->setEnabled(checked); |         ui->hw_renderer_group->setEnabled(checked); | ||||||
|         ui->toggle_disk_shader_cache->setEnabled(checked && ui->toggle_hw_shader->isChecked()); |         ui->toggle_disk_shader_cache->setEnabled(checked && ui->toggle_hw_shader->isChecked()); | ||||||
|     }); |     }); | ||||||
|  | @ -31,7 +34,7 @@ ConfigureGraphics::ConfigureGraphics(QWidget* parent) | ||||||
|                                              ui->toggle_hw_shader->isChecked()); |                                              ui->toggle_hw_shader->isChecked()); | ||||||
| 
 | 
 | ||||||
|     connect(ui->toggle_hw_shader, &QCheckBox::toggled, this, [this] { |     connect(ui->toggle_hw_shader, &QCheckBox::toggled, this, [this] { | ||||||
|         auto checked = ui->toggle_hw_shader->isChecked(); |         const bool checked = ui->toggle_hw_shader->isChecked(); | ||||||
|         ui->hw_shader_group->setEnabled(checked); |         ui->hw_shader_group->setEnabled(checked); | ||||||
|         ui->toggle_disk_shader_cache->setEnabled(checked); |         ui->toggle_disk_shader_cache->setEnabled(checked); | ||||||
|     }); |     }); | ||||||
|  | @ -62,25 +65,67 @@ ConfigureGraphics::ConfigureGraphics(QWidget* parent) | ||||||
| ConfigureGraphics::~ConfigureGraphics() = default; | ConfigureGraphics::~ConfigureGraphics() = default; | ||||||
| 
 | 
 | ||||||
| void ConfigureGraphics::SetConfiguration() { | void ConfigureGraphics::SetConfiguration() { | ||||||
|     ui->toggle_hw_renderer->setChecked(Settings::values.use_hw_renderer); |     ui->toggle_hw_renderer->setChecked(Settings::values.use_hw_renderer.GetValue()); | ||||||
|     ui->toggle_hw_shader->setChecked(Settings::values.use_hw_shader); |     ui->toggle_hw_shader->setChecked(Settings::values.use_hw_shader.GetValue()); | ||||||
|     ui->toggle_separable_shader->setChecked(Settings::values.separable_shader); |     ui->toggle_separable_shader->setChecked(Settings::values.separable_shader.GetValue()); | ||||||
|     ui->toggle_accurate_mul->setChecked(Settings::values.shaders_accurate_mul); |     ui->toggle_accurate_mul->setChecked(Settings::values.shaders_accurate_mul.GetValue()); | ||||||
|     ui->toggle_shader_jit->setChecked(Settings::values.use_shader_jit); |     ui->toggle_disk_shader_cache->setChecked(Settings::values.use_disk_shader_cache.GetValue()); | ||||||
|     ui->toggle_disk_shader_cache->setChecked(Settings::values.use_disk_shader_cache); |     ui->toggle_vsync_new->setChecked(Settings::values.use_vsync_new.GetValue()); | ||||||
|     ui->toggle_vsync_new->setChecked(Settings::values.use_vsync_new); | 
 | ||||||
|  |     if (Settings::IsConfiguringGlobal()) { | ||||||
|  |         ui->toggle_shader_jit->setChecked(Settings::values.use_shader_jit.GetValue()); | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ConfigureGraphics::ApplyConfiguration() { | void ConfigureGraphics::ApplyConfiguration() { | ||||||
|     Settings::values.use_hw_renderer = ui->toggle_hw_renderer->isChecked(); |     ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_hw_renderer, | ||||||
|     Settings::values.use_hw_shader = ui->toggle_hw_shader->isChecked(); |                                              ui->toggle_hw_renderer, use_hw_renderer); | ||||||
|     Settings::values.separable_shader = ui->toggle_separable_shader->isChecked(); |     ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_hw_shader, ui->toggle_hw_shader, | ||||||
|     Settings::values.shaders_accurate_mul = ui->toggle_accurate_mul->isChecked(); |                                              use_hw_shader); | ||||||
|     Settings::values.use_shader_jit = ui->toggle_shader_jit->isChecked(); |     ConfigurationShared::ApplyPerGameSetting(&Settings::values.separable_shader, | ||||||
|     Settings::values.use_disk_shader_cache = ui->toggle_disk_shader_cache->isChecked(); |                                              ui->toggle_separable_shader, separable_shader); | ||||||
|     Settings::values.use_vsync_new = ui->toggle_vsync_new->isChecked(); |     ConfigurationShared::ApplyPerGameSetting(&Settings::values.shaders_accurate_mul, | ||||||
|  |                                              ui->toggle_accurate_mul, shaders_accurate_mul); | ||||||
|  |     ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_disk_shader_cache, | ||||||
|  |                                              ui->toggle_disk_shader_cache, use_disk_shader_cache); | ||||||
|  |     ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_vsync_new, ui->toggle_vsync_new, | ||||||
|  |                                              use_vsync_new); | ||||||
|  | 
 | ||||||
|  |     if (Settings::IsConfiguringGlobal()) { | ||||||
|  |         Settings::values.use_shader_jit = ui->toggle_shader_jit->isChecked(); | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ConfigureGraphics::RetranslateUI() { | void ConfigureGraphics::RetranslateUI() { | ||||||
|     ui->retranslateUi(this); |     ui->retranslateUi(this); | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | void ConfigureGraphics::SetupPerGameUI() { | ||||||
|  |     // Block the global settings if a game is currently running that overrides them
 | ||||||
|  |     if (Settings::IsConfiguringGlobal()) { | ||||||
|  |         ui->toggle_hw_renderer->setEnabled(Settings::values.use_hw_renderer.UsingGlobal()); | ||||||
|  |         ui->toggle_hw_shader->setEnabled(Settings::values.use_hw_shader.UsingGlobal()); | ||||||
|  |         ui->toggle_separable_shader->setEnabled(Settings::values.separable_shader.UsingGlobal()); | ||||||
|  |         ui->toggle_accurate_mul->setEnabled(Settings::values.shaders_accurate_mul.UsingGlobal()); | ||||||
|  |         ui->toggle_disk_shader_cache->setEnabled( | ||||||
|  |             Settings::values.use_disk_shader_cache.UsingGlobal()); | ||||||
|  |         ui->toggle_vsync_new->setEnabled(Settings::values.use_vsync_new.UsingGlobal()); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     ui->toggle_shader_jit->setVisible(false); | ||||||
|  | 
 | ||||||
|  |     ConfigurationShared::SetColoredTristate(ui->toggle_hw_renderer, | ||||||
|  |                                             Settings::values.use_hw_renderer, use_hw_renderer); | ||||||
|  |     ConfigurationShared::SetColoredTristate(ui->toggle_hw_shader, Settings::values.use_hw_shader, | ||||||
|  |                                             use_hw_shader); | ||||||
|  |     ConfigurationShared::SetColoredTristate(ui->toggle_separable_shader, | ||||||
|  |                                             Settings::values.separable_shader, separable_shader); | ||||||
|  |     ConfigurationShared::SetColoredTristate( | ||||||
|  |         ui->toggle_accurate_mul, Settings::values.shaders_accurate_mul, shaders_accurate_mul); | ||||||
|  |     ConfigurationShared::SetColoredTristate(ui->toggle_disk_shader_cache, | ||||||
|  |                                             Settings::values.use_disk_shader_cache, | ||||||
|  |                                             use_disk_shader_cache); | ||||||
|  |     ConfigurationShared::SetColoredTristate(ui->toggle_vsync_new, Settings::values.use_vsync_new, | ||||||
|  |                                             use_vsync_new); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -11,6 +11,10 @@ namespace Ui { | ||||||
| class ConfigureGraphics; | class ConfigureGraphics; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | namespace ConfigurationShared { | ||||||
|  | enum class CheckState; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| class ConfigureGraphics : public QWidget { | class ConfigureGraphics : public QWidget { | ||||||
|     Q_OBJECT |     Q_OBJECT | ||||||
| 
 | 
 | ||||||
|  | @ -24,6 +28,14 @@ public: | ||||||
| 
 | 
 | ||||||
|     void UpdateBackgroundColorButton(const QColor& color); |     void UpdateBackgroundColorButton(const QColor& color); | ||||||
| 
 | 
 | ||||||
|  |     void SetupPerGameUI(); | ||||||
|  | 
 | ||||||
|  |     ConfigurationShared::CheckState use_hw_renderer; | ||||||
|  |     ConfigurationShared::CheckState use_hw_shader; | ||||||
|  |     ConfigurationShared::CheckState separable_shader; | ||||||
|  |     ConfigurationShared::CheckState shaders_accurate_mul; | ||||||
|  |     ConfigurationShared::CheckState use_disk_shader_cache; | ||||||
|  |     ConfigurationShared::CheckState use_vsync_new; | ||||||
|     std::unique_ptr<Ui::ConfigureGraphics> ui; |     std::unique_ptr<Ui::ConfigureGraphics> ui; | ||||||
|     QColor bg_color; |     QColor bg_color; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | @ -7,7 +7,7 @@ | ||||||
| #include "citra_qt/configuration/configure_hotkeys.h" | #include "citra_qt/configuration/configure_hotkeys.h" | ||||||
| #include "citra_qt/hotkeys.h" | #include "citra_qt/hotkeys.h" | ||||||
| #include "citra_qt/util/sequence_dialog/sequence_dialog.h" | #include "citra_qt/util/sequence_dialog/sequence_dialog.h" | ||||||
| #include "core/settings.h" | #include "common/settings.h" | ||||||
| #include "ui_configure_hotkeys.h" | #include "ui_configure_hotkeys.h" | ||||||
| 
 | 
 | ||||||
| ConfigureHotkeys::ConfigureHotkeys(QWidget* parent) | ConfigureHotkeys::ConfigureHotkeys(QWidget* parent) | ||||||
|  |  | ||||||
|  | @ -13,7 +13,7 @@ | ||||||
| #include <QKeySequence> | #include <QKeySequence> | ||||||
| #include <QWidget> | #include <QWidget> | ||||||
| #include "common/param_package.h" | #include "common/param_package.h" | ||||||
| #include "core/settings.h" | #include "common/settings.h" | ||||||
| #include "input_common/main.h" | #include "input_common/main.h" | ||||||
| 
 | 
 | ||||||
| class QKeyEvent; | class QKeyEvent; | ||||||
|  |  | ||||||
|  | @ -7,7 +7,7 @@ | ||||||
| #include <memory> | #include <memory> | ||||||
| #include <QDialog> | #include <QDialog> | ||||||
| #include "common/param_package.h" | #include "common/param_package.h" | ||||||
| #include "core/settings.h" | #include "common/settings.h" | ||||||
| #include "input_common/main.h" | #include "input_common/main.h" | ||||||
| #include "input_common/udp/udp.h" | #include "input_common/udp/udp.h" | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										128
									
								
								src/citra_qt/configuration/configure_per_game.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								src/citra_qt/configuration/configure_per_game.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,128 @@ | ||||||
|  | // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
 | ||||||
|  | // SPDX-License-Identifier: GPL-2.0-or-later
 | ||||||
|  | 
 | ||||||
|  | #include <utility> | ||||||
|  | #include <vector> | ||||||
|  | #include <QPushButton> | ||||||
|  | #include <QString> | ||||||
|  | #include <fmt/format.h> | ||||||
|  | #include "citra_qt/configuration/config.h" | ||||||
|  | #include "citra_qt/configuration/configure_audio.h" | ||||||
|  | #include "citra_qt/configuration/configure_general.h" | ||||||
|  | #include "citra_qt/configuration/configure_graphics.h" | ||||||
|  | #include "citra_qt/configuration/configure_per_game.h" | ||||||
|  | #include "citra_qt/configuration/configure_system.h" | ||||||
|  | #include "citra_qt/util/util.h" | ||||||
|  | #include "core/core.h" | ||||||
|  | #include "core/loader/loader.h" | ||||||
|  | #include "core/loader/smdh.h" | ||||||
|  | #include "ui_configure_per_game.h" | ||||||
|  | 
 | ||||||
|  | ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id_, const QString& file_name, | ||||||
|  |                                    Core::System& system_) | ||||||
|  |     : QDialog(parent), ui(std::make_unique<Ui::ConfigurePerGame>()), | ||||||
|  |       filename{file_name.toStdString()}, title_id{title_id_}, system{system_} { | ||||||
|  |     const auto config_file_name = title_id == 0 ? filename : fmt::format("{:016X}", title_id); | ||||||
|  |     game_config = std::make_unique<Config>(config_file_name, Config::ConfigType::PerGameConfig); | ||||||
|  | 
 | ||||||
|  |     audio_tab = std::make_unique<ConfigureAudio>(this); | ||||||
|  |     general_tab = std::make_unique<ConfigureGeneral>(this); | ||||||
|  |     graphics_tab = std::make_unique<ConfigureGraphics>(this); | ||||||
|  |     system_tab = std::make_unique<ConfigureSystem>(this); | ||||||
|  | 
 | ||||||
|  |     ui->setupUi(this); | ||||||
|  | 
 | ||||||
|  |     ui->tabWidget->addTab(general_tab.get(), tr("General")); | ||||||
|  |     ui->tabWidget->addTab(system_tab.get(), tr("System")); | ||||||
|  |     ui->tabWidget->addTab(graphics_tab.get(), tr("Graphics")); | ||||||
|  |     ui->tabWidget->addTab(audio_tab.get(), tr("Audio")); | ||||||
|  | 
 | ||||||
|  |     setFocusPolicy(Qt::ClickFocus); | ||||||
|  |     setWindowTitle(tr("Properties")); | ||||||
|  |     // remove Help question mark button from the title bar
 | ||||||
|  |     setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); | ||||||
|  | 
 | ||||||
|  |     scene = new QGraphicsScene; | ||||||
|  |     ui->icon_view->setScene(scene); | ||||||
|  | 
 | ||||||
|  |     if (system.IsPoweredOn()) { | ||||||
|  |         QPushButton* apply_button = ui->buttonBox->addButton(QDialogButtonBox::Apply); | ||||||
|  |         connect(apply_button, &QAbstractButton::clicked, this, | ||||||
|  |                 &ConfigurePerGame::HandleApplyButtonClicked); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     LoadConfiguration(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ConfigurePerGame::~ConfigurePerGame() = default; | ||||||
|  | 
 | ||||||
|  | void ConfigurePerGame::ApplyConfiguration() { | ||||||
|  |     general_tab->ApplyConfiguration(); | ||||||
|  |     system_tab->ApplyConfiguration(); | ||||||
|  |     graphics_tab->ApplyConfiguration(); | ||||||
|  |     audio_tab->ApplyConfiguration(); | ||||||
|  | 
 | ||||||
|  |     Settings::LogSettings(); | ||||||
|  | 
 | ||||||
|  |     game_config->Save(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void ConfigurePerGame::changeEvent(QEvent* event) { | ||||||
|  |     if (event->type() == QEvent::LanguageChange) { | ||||||
|  |         RetranslateUI(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     QDialog::changeEvent(event); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void ConfigurePerGame::RetranslateUI() { | ||||||
|  |     ui->retranslateUi(this); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void ConfigurePerGame::HandleApplyButtonClicked() { | ||||||
|  |     ApplyConfiguration(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static QPixmap GetQPixmapFromSMDH(std::vector<u8>& smdh_data) { | ||||||
|  |     Loader::SMDH smdh; | ||||||
|  |     memcpy(&smdh, smdh_data.data(), sizeof(Loader::SMDH)); | ||||||
|  | 
 | ||||||
|  |     bool large = true; | ||||||
|  |     std::vector<u16> icon_data = smdh.GetIcon(large); | ||||||
|  |     const uchar* data = reinterpret_cast<const uchar*>(icon_data.data()); | ||||||
|  |     int size = large ? 48 : 24; | ||||||
|  |     QImage icon(data, size, size, QImage::Format::Format_RGB16); | ||||||
|  |     return QPixmap::fromImage(icon); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void ConfigurePerGame::LoadConfiguration() { | ||||||
|  |     if (filename.empty()) { | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     ui->display_title_id->setText( | ||||||
|  |         QStringLiteral("%1").arg(title_id, 16, 16, QLatin1Char{'0'}).toUpper()); | ||||||
|  | 
 | ||||||
|  |     const auto loader = Loader::GetLoader(filename); | ||||||
|  | 
 | ||||||
|  |     std::string title; | ||||||
|  |     if (loader->ReadTitle(title) == Loader::ResultStatus::Success) | ||||||
|  |         ui->display_name->setText(QString::fromStdString(title)); | ||||||
|  | 
 | ||||||
|  |     std::vector<u8> bytes; | ||||||
|  |     if (loader->ReadIcon(bytes) == Loader::ResultStatus::Success) { | ||||||
|  |         scene->clear(); | ||||||
|  | 
 | ||||||
|  |         QPixmap map = GetQPixmapFromSMDH(bytes); | ||||||
|  |         scene->addPixmap(map.scaled(ui->icon_view->width(), ui->icon_view->height(), | ||||||
|  |                                     Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     ui->display_filepath->setText(QString::fromStdString(filename)); | ||||||
|  | 
 | ||||||
|  |     ui->display_format->setText( | ||||||
|  |         QString::fromStdString(Loader::GetFileTypeString(loader->GetFileType()))); | ||||||
|  | 
 | ||||||
|  |     const auto valueText = ReadableByteSize(FileUtil::GetSize(filename)); | ||||||
|  |     ui->display_size->setText(valueText); | ||||||
|  | } | ||||||
							
								
								
									
										66
									
								
								src/citra_qt/configuration/configure_per_game.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								src/citra_qt/configuration/configure_per_game.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,66 @@ | ||||||
|  | // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
 | ||||||
|  | // SPDX-License-Identifier: GPL-2.0-or-later
 | ||||||
|  | 
 | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <memory> | ||||||
|  | #include <string> | ||||||
|  | #include <QDialog> | ||||||
|  | #include <QList> | ||||||
|  | #include "citra_qt/configuration/config.h" | ||||||
|  | 
 | ||||||
|  | namespace Core { | ||||||
|  | class System; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | class ConfigureAudio; | ||||||
|  | class ConfigureGeneral; | ||||||
|  | class ConfigureGraphics; | ||||||
|  | class ConfigureSystem; | ||||||
|  | 
 | ||||||
|  | class QGraphicsScene; | ||||||
|  | class QStandardItem; | ||||||
|  | class QStandardItemModel; | ||||||
|  | class QTreeView; | ||||||
|  | class QVBoxLayout; | ||||||
|  | 
 | ||||||
|  | namespace Ui { | ||||||
|  | class ConfigurePerGame; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | class ConfigurePerGame : public QDialog { | ||||||
|  |     Q_OBJECT | ||||||
|  | 
 | ||||||
|  | public: | ||||||
|  |     // Cannot use std::filesystem::path due to https://bugreports.qt.io/browse/QTBUG-73263
 | ||||||
|  |     explicit ConfigurePerGame(QWidget* parent, u64 title_id_, const QString& file_name, | ||||||
|  |                               Core::System& system_); | ||||||
|  |     ~ConfigurePerGame() override; | ||||||
|  | 
 | ||||||
|  |     /// Loads all button configurations to settings file
 | ||||||
|  |     void LoadConfiguration(); | ||||||
|  | 
 | ||||||
|  |     /// Save all button configurations to settings file
 | ||||||
|  |     void ApplyConfiguration(); | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |     void changeEvent(QEvent* event) override; | ||||||
|  |     void RetranslateUI(); | ||||||
|  | 
 | ||||||
|  |     void HandleApplyButtonClicked(); | ||||||
|  | 
 | ||||||
|  |     std::unique_ptr<Ui::ConfigurePerGame> ui; | ||||||
|  |     std::string filename; | ||||||
|  |     u64 title_id; | ||||||
|  | 
 | ||||||
|  |     QGraphicsScene* scene; | ||||||
|  | 
 | ||||||
|  |     std::unique_ptr<Config> game_config; | ||||||
|  | 
 | ||||||
|  |     Core::System& system; | ||||||
|  | 
 | ||||||
|  |     std::unique_ptr<ConfigureAudio> audio_tab; | ||||||
|  |     std::unique_ptr<ConfigureGeneral> general_tab; | ||||||
|  |     std::unique_ptr<ConfigureGraphics> graphics_tab; | ||||||
|  |     std::unique_ptr<ConfigureSystem> system_tab; | ||||||
|  | }; | ||||||
							
								
								
									
										264
									
								
								src/citra_qt/configuration/configure_per_game.ui
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										264
									
								
								src/citra_qt/configuration/configure_per_game.ui
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,264 @@ | ||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <ui version="4.0"> | ||||||
|  |  <class>ConfigurePerGame</class> | ||||||
|  |  <widget class="QDialog" name="ConfigurePerGame"> | ||||||
|  |   <property name="geometry"> | ||||||
|  |    <rect> | ||||||
|  |     <x>0</x> | ||||||
|  |     <y>0</y> | ||||||
|  |     <width>900</width> | ||||||
|  |     <height>661</height> | ||||||
|  |    </rect> | ||||||
|  |   </property> | ||||||
|  |   <property name="minimumSize"> | ||||||
|  |    <size> | ||||||
|  |     <width>900</width> | ||||||
|  |     <height>0</height> | ||||||
|  |    </size> | ||||||
|  |   </property> | ||||||
|  |   <property name="windowTitle"> | ||||||
|  |    <string>Dialog</string> | ||||||
|  |   </property> | ||||||
|  |   <layout class="QVBoxLayout" name="verticalLayout_3"> | ||||||
|  |    <item> | ||||||
|  |     <layout class="QHBoxLayout" name="horizontalLayout"> | ||||||
|  |      <item> | ||||||
|  |       <widget class="QGroupBox" name="groupBox"> | ||||||
|  |        <property name="sizePolicy"> | ||||||
|  |         <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> | ||||||
|  |          <horstretch>0</horstretch> | ||||||
|  |          <verstretch>0</verstretch> | ||||||
|  |         </sizepolicy> | ||||||
|  |        </property> | ||||||
|  |        <property name="title"> | ||||||
|  |         <string>Info</string> | ||||||
|  |        </property> | ||||||
|  |        <layout class="QVBoxLayout" name="verticalLayout"> | ||||||
|  |         <item> | ||||||
|  |          <layout class="QGridLayout" name="gridLayout"> | ||||||
|  |           <item row="0" column="0"> | ||||||
|  |            <widget class="QGraphicsView" name="icon_view"> | ||||||
|  |             <property name="sizePolicy"> | ||||||
|  |              <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> | ||||||
|  |               <horstretch>0</horstretch> | ||||||
|  |               <verstretch>0</verstretch> | ||||||
|  |              </sizepolicy> | ||||||
|  |             </property> | ||||||
|  |             <property name="minimumSize"> | ||||||
|  |              <size> | ||||||
|  |               <width>128</width> | ||||||
|  |               <height>128</height> | ||||||
|  |              </size> | ||||||
|  |             </property> | ||||||
|  |             <property name="maximumSize"> | ||||||
|  |              <size> | ||||||
|  |               <width>128</width> | ||||||
|  |               <height>128</height> | ||||||
|  |              </size> | ||||||
|  |             </property> | ||||||
|  |             <property name="verticalScrollBarPolicy"> | ||||||
|  |              <enum>Qt::ScrollBarAlwaysOff</enum> | ||||||
|  |             </property> | ||||||
|  |             <property name="horizontalScrollBarPolicy"> | ||||||
|  |              <enum>Qt::ScrollBarAlwaysOff</enum> | ||||||
|  |             </property> | ||||||
|  |             <property name="interactive"> | ||||||
|  |              <bool>false</bool> | ||||||
|  |             </property> | ||||||
|  |            </widget> | ||||||
|  |           </item> | ||||||
|  |          </layout> | ||||||
|  |         </item> | ||||||
|  |         <item> | ||||||
|  |          <layout class="QGridLayout" name="gridLayout_2"> | ||||||
|  |           <item row="4" column="0"> | ||||||
|  |            <widget class="QLabel" name="label_6"> | ||||||
|  |             <property name="text"> | ||||||
|  |              <string>Size</string> | ||||||
|  |             </property> | ||||||
|  |            </widget> | ||||||
|  |           </item> | ||||||
|  |           <item row="5" column="1"> | ||||||
|  |            <widget class="QLineEdit" name="display_filepath"> | ||||||
|  |             <property name="enabled"> | ||||||
|  |              <bool>true</bool> | ||||||
|  |             </property> | ||||||
|  |             <property name="minimumSize"> | ||||||
|  |              <size> | ||||||
|  |               <width>160</width> | ||||||
|  |               <height>0</height> | ||||||
|  |              </size> | ||||||
|  |             </property> | ||||||
|  |             <property name="readOnly"> | ||||||
|  |              <bool>true</bool> | ||||||
|  |             </property> | ||||||
|  |            </widget> | ||||||
|  |           </item> | ||||||
|  |           <item row="3" column="0"> | ||||||
|  |            <widget class="QLabel" name="label_5"> | ||||||
|  |             <property name="text"> | ||||||
|  |              <string>Format</string> | ||||||
|  |             </property> | ||||||
|  |            </widget> | ||||||
|  |           </item> | ||||||
|  |           <item row="1" column="0"> | ||||||
|  |            <widget class="QLabel" name="label"> | ||||||
|  |             <property name="text"> | ||||||
|  |              <string>Name</string> | ||||||
|  |             </property> | ||||||
|  |            </widget> | ||||||
|  |           </item> | ||||||
|  |           <item row="4" column="1"> | ||||||
|  |            <widget class="QLineEdit" name="display_size"> | ||||||
|  |             <property name="enabled"> | ||||||
|  |              <bool>true</bool> | ||||||
|  |             </property> | ||||||
|  |             <property name="readOnly"> | ||||||
|  |              <bool>true</bool> | ||||||
|  |             </property> | ||||||
|  |            </widget> | ||||||
|  |           </item> | ||||||
|  |           <item row="5" column="0"> | ||||||
|  |            <widget class="QLabel" name="label_7"> | ||||||
|  |             <property name="text"> | ||||||
|  |              <string>Filepath</string> | ||||||
|  |             </property> | ||||||
|  |            </widget> | ||||||
|  |           </item> | ||||||
|  |           <item row="2" column="0"> | ||||||
|  |            <widget class="QLabel" name="label_4"> | ||||||
|  |             <property name="text"> | ||||||
|  |              <string>Title ID</string> | ||||||
|  |             </property> | ||||||
|  |            </widget> | ||||||
|  |           </item> | ||||||
|  |           <item row="2" column="1"> | ||||||
|  |            <widget class="QLineEdit" name="display_title_id"> | ||||||
|  |             <property name="enabled"> | ||||||
|  |              <bool>true</bool> | ||||||
|  |             </property> | ||||||
|  |             <property name="readOnly"> | ||||||
|  |              <bool>true</bool> | ||||||
|  |             </property> | ||||||
|  |            </widget> | ||||||
|  |           </item> | ||||||
|  |           <item row="1" column="1"> | ||||||
|  |            <widget class="QLineEdit" name="display_name"> | ||||||
|  |             <property name="enabled"> | ||||||
|  |              <bool>true</bool> | ||||||
|  |             </property> | ||||||
|  |             <property name="readOnly"> | ||||||
|  |              <bool>true</bool> | ||||||
|  |             </property> | ||||||
|  |            </widget> | ||||||
|  |           </item> | ||||||
|  |           <item row="3" column="1"> | ||||||
|  |            <widget class="QLineEdit" name="display_format"> | ||||||
|  |             <property name="enabled"> | ||||||
|  |              <bool>true</bool> | ||||||
|  |             </property> | ||||||
|  |             <property name="readOnly"> | ||||||
|  |              <bool>true</bool> | ||||||
|  |             </property> | ||||||
|  |            </widget> | ||||||
|  |           </item> | ||||||
|  |          </layout> | ||||||
|  |         </item> | ||||||
|  |         <item> | ||||||
|  |          <spacer name="verticalSpacer"> | ||||||
|  |           <property name="orientation"> | ||||||
|  |            <enum>Qt::Vertical</enum> | ||||||
|  |           </property> | ||||||
|  |           <property name="sizeHint" stdset="0"> | ||||||
|  |            <size> | ||||||
|  |             <width>20</width> | ||||||
|  |             <height>40</height> | ||||||
|  |            </size> | ||||||
|  |           </property> | ||||||
|  |          </spacer> | ||||||
|  |         </item> | ||||||
|  |        </layout> | ||||||
|  |       </widget> | ||||||
|  |      </item> | ||||||
|  |      <item> | ||||||
|  |       <layout class="QVBoxLayout" name="VerticalLayout"> | ||||||
|  |        <item> | ||||||
|  |         <layout class="QVBoxLayout" name="verticalLayout_2"/> | ||||||
|  |        </item> | ||||||
|  |        <item> | ||||||
|  |         <widget class="QTabWidget" name="tabWidget"> | ||||||
|  |          <property name="enabled"> | ||||||
|  |           <bool>true</bool> | ||||||
|  |          </property> | ||||||
|  |          <property name="currentIndex"> | ||||||
|  |           <number>-1</number> | ||||||
|  |          </property> | ||||||
|  |          <property name="usesScrollButtons"> | ||||||
|  |           <bool>true</bool> | ||||||
|  |          </property> | ||||||
|  |          <property name="documentMode"> | ||||||
|  |           <bool>false</bool> | ||||||
|  |          </property> | ||||||
|  |          <property name="tabsClosable"> | ||||||
|  |           <bool>false</bool> | ||||||
|  |          </property> | ||||||
|  |         </widget> | ||||||
|  |        </item> | ||||||
|  |       </layout> | ||||||
|  |      </item> | ||||||
|  |     </layout> | ||||||
|  |    </item> | ||||||
|  |    <item> | ||||||
|  |     <widget class="QDialogButtonBox" name="buttonBox"> | ||||||
|  |      <property name="sizePolicy"> | ||||||
|  |       <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> | ||||||
|  |        <horstretch>0</horstretch> | ||||||
|  |        <verstretch>0</verstretch> | ||||||
|  |       </sizepolicy> | ||||||
|  |      </property> | ||||||
|  |      <property name="orientation"> | ||||||
|  |       <enum>Qt::Horizontal</enum> | ||||||
|  |      </property> | ||||||
|  |      <property name="standardButtons"> | ||||||
|  |       <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> | ||||||
|  |      </property> | ||||||
|  |     </widget> | ||||||
|  |    </item> | ||||||
|  |   </layout> | ||||||
|  |  </widget> | ||||||
|  |  <resources/> | ||||||
|  |  <connections> | ||||||
|  |   <connection> | ||||||
|  |    <sender>buttonBox</sender> | ||||||
|  |    <signal>accepted()</signal> | ||||||
|  |    <receiver>ConfigurePerGame</receiver> | ||||||
|  |    <slot>accept()</slot> | ||||||
|  |    <hints> | ||||||
|  |     <hint type="sourcelabel"> | ||||||
|  |      <x>20</x> | ||||||
|  |      <y>20</y> | ||||||
|  |     </hint> | ||||||
|  |     <hint type="destinationlabel"> | ||||||
|  |      <x>20</x> | ||||||
|  |      <y>20</y> | ||||||
|  |     </hint> | ||||||
|  |    </hints> | ||||||
|  |   </connection> | ||||||
|  |   <connection> | ||||||
|  |    <sender>buttonBox</sender> | ||||||
|  |    <signal>rejected()</signal> | ||||||
|  |    <receiver>ConfigurePerGame</receiver> | ||||||
|  |    <slot>reject()</slot> | ||||||
|  |    <hints> | ||||||
|  |     <hint type="sourcelabel"> | ||||||
|  |      <x>20</x> | ||||||
|  |      <y>20</y> | ||||||
|  |     </hint> | ||||||
|  |     <hint type="destinationlabel"> | ||||||
|  |      <x>20</x> | ||||||
|  |      <y>20</y> | ||||||
|  |     </hint> | ||||||
|  |    </hints> | ||||||
|  |   </connection> | ||||||
|  |  </connections> | ||||||
|  | </ui> | ||||||
|  | @ -6,8 +6,8 @@ | ||||||
| #include <QFileDialog> | #include <QFileDialog> | ||||||
| #include <QUrl> | #include <QUrl> | ||||||
| #include "citra_qt/configuration/configure_storage.h" | #include "citra_qt/configuration/configure_storage.h" | ||||||
|  | #include "common/settings.h" | ||||||
| #include "core/core.h" | #include "core/core.h" | ||||||
| #include "core/settings.h" |  | ||||||
| #include "ui_configure_storage.h" | #include "ui_configure_storage.h" | ||||||
| 
 | 
 | ||||||
| ConfigureStorage::ConfigureStorage(QWidget* parent) | ConfigureStorage::ConfigureStorage(QWidget* parent) | ||||||
|  | @ -60,7 +60,7 @@ ConfigureStorage::ConfigureStorage(QWidget* parent) | ||||||
| ConfigureStorage::~ConfigureStorage() = default; | ConfigureStorage::~ConfigureStorage() = default; | ||||||
| 
 | 
 | ||||||
| void ConfigureStorage::SetConfiguration() { | void ConfigureStorage::SetConfiguration() { | ||||||
|     ui->nand_group->setVisible(Settings::values.use_custom_storage); |     ui->nand_group->setVisible(Settings::values.use_custom_storage.GetValue()); | ||||||
|     QString nand_path = QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::NANDDir)); |     QString nand_path = QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::NANDDir)); | ||||||
|     ui->nand_dir_path->setText(nand_path); |     ui->nand_dir_path->setText(nand_path); | ||||||
|     ui->open_nand_dir->setEnabled(!nand_path.isEmpty()); |     ui->open_nand_dir->setEnabled(!nand_path.isEmpty()); | ||||||
|  | @ -71,8 +71,8 @@ void ConfigureStorage::SetConfiguration() { | ||||||
|     ui->sdmc_dir_path->setText(sdmc_path); |     ui->sdmc_dir_path->setText(sdmc_path); | ||||||
|     ui->open_sdmc_dir->setEnabled(!sdmc_path.isEmpty()); |     ui->open_sdmc_dir->setEnabled(!sdmc_path.isEmpty()); | ||||||
| 
 | 
 | ||||||
|     ui->toggle_virtual_sd->setChecked(Settings::values.use_virtual_sd); |     ui->toggle_virtual_sd->setChecked(Settings::values.use_virtual_sd.GetValue()); | ||||||
|     ui->toggle_custom_storage->setChecked(Settings::values.use_custom_storage); |     ui->toggle_custom_storage->setChecked(Settings::values.use_custom_storage.GetValue()); | ||||||
| 
 | 
 | ||||||
|     ui->storage_group->setEnabled(!Core::System::GetInstance().IsPoweredOn()); |     ui->storage_group->setEnabled(!Core::System::GetInstance().IsPoweredOn()); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -4,12 +4,12 @@ | ||||||
| 
 | 
 | ||||||
| #include <cstring> | #include <cstring> | ||||||
| #include <QMessageBox> | #include <QMessageBox> | ||||||
|  | #include "citra_qt/configuration/configuration_shared.h" | ||||||
| #include "citra_qt/configuration/configure_system.h" | #include "citra_qt/configuration/configure_system.h" | ||||||
| #include "citra_qt/uisettings.h" | #include "common/settings.h" | ||||||
| #include "core/core.h" | #include "core/core.h" | ||||||
| #include "core/hle/service/cfg/cfg.h" | #include "core/hle/service/cfg/cfg.h" | ||||||
| #include "core/hle/service/ptm/ptm.h" | #include "core/hle/service/ptm/ptm.h" | ||||||
| #include "core/settings.h" |  | ||||||
| #include "ui_configure_system.h" | #include "ui_configure_system.h" | ||||||
| 
 | 
 | ||||||
| static const std::array<int, 12> days_in_month = {{ | static const std::array<int, 12> days_in_month = {{ | ||||||
|  | @ -249,10 +249,14 @@ ConfigureSystem::ConfigureSystem(QWidget* parent) | ||||||
|     // This scales across DPIs. (This value should be enough for "xxx%")
 |     // This scales across DPIs. (This value should be enough for "xxx%")
 | ||||||
|     ui->clock_display_label->setMinimumWidth(40); |     ui->clock_display_label->setMinimumWidth(40); | ||||||
| 
 | 
 | ||||||
|     connect(ui->slider_clock_speed, &QSlider::valueChanged, [&](int value) { |     connect(ui->slider_clock_speed, &QSlider::valueChanged, this, [&](int value) { | ||||||
|         ui->clock_display_label->setText(QStringLiteral("%1%").arg(SliderToSettings(value))); |         ui->clock_display_label->setText(QStringLiteral("%1%").arg(SliderToSettings(value))); | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|  |     ui->clock_speed_label->setVisible(Settings::IsConfiguringGlobal()); | ||||||
|  |     ui->clock_speed_combo->setVisible(!Settings::IsConfiguringGlobal()); | ||||||
|  | 
 | ||||||
|  |     SetupPerGameUI(); | ||||||
|     ConfigureTime(); |     ConfigureTime(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -261,12 +265,12 @@ ConfigureSystem::~ConfigureSystem() = default; | ||||||
| void ConfigureSystem::SetConfiguration() { | void ConfigureSystem::SetConfiguration() { | ||||||
|     enabled = !Core::System::GetInstance().IsPoweredOn(); |     enabled = !Core::System::GetInstance().IsPoweredOn(); | ||||||
| 
 | 
 | ||||||
|     ui->combo_init_clock->setCurrentIndex(static_cast<u8>(Settings::values.init_clock)); |     ui->combo_init_clock->setCurrentIndex(static_cast<u8>(Settings::values.init_clock.GetValue())); | ||||||
|     QDateTime date_time; |     QDateTime date_time; | ||||||
|     date_time.setTime_t(Settings::values.init_time); |     date_time.setTime_t(Settings::values.init_time.GetValue()); | ||||||
|     ui->edit_init_time->setDateTime(date_time); |     ui->edit_init_time->setDateTime(date_time); | ||||||
| 
 | 
 | ||||||
|     long long init_time_offset = Settings::values.init_time_offset; |     long long init_time_offset = Settings::values.init_time_offset.GetValue(); | ||||||
|     long long days_offset = init_time_offset / 86400; |     long long days_offset = init_time_offset / 86400; | ||||||
|     ui->edit_init_time_offset_days->setValue(days_offset); |     ui->edit_init_time_offset_days->setValue(days_offset); | ||||||
| 
 | 
 | ||||||
|  | @ -287,20 +291,29 @@ void ConfigureSystem::SetConfiguration() { | ||||||
|         ui->label_disable_info->hide(); |         ui->label_disable_info->hide(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     ui->slider_clock_speed->setValue(SettingsToSlider(Settings::values.cpu_clock_percentage)); |     if (!Settings::IsConfiguringGlobal()) { | ||||||
|     ui->clock_display_label->setText( |         if (Settings::values.cpu_clock_percentage.UsingGlobal()) { | ||||||
|         QStringLiteral("%1%").arg(Settings::values.cpu_clock_percentage)); |             ui->clock_speed_combo->setCurrentIndex(0); | ||||||
|  |             ui->slider_clock_speed->setEnabled(false); | ||||||
|  |         } else { | ||||||
|  |             ui->clock_speed_combo->setCurrentIndex(1); | ||||||
|  |             ui->slider_clock_speed->setEnabled(true); | ||||||
|  |         } | ||||||
|  |         ConfigurationShared::SetHighlight(ui->clock_speed_widget, | ||||||
|  |                                           !Settings::values.cpu_clock_percentage.UsingGlobal()); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     ui->toggle_new_3ds->setChecked(Settings::values.is_new_3ds); |     ui->slider_clock_speed->setValue( | ||||||
|  |         SettingsToSlider(Settings::values.cpu_clock_percentage.GetValue())); | ||||||
|  |     ui->clock_display_label->setText( | ||||||
|  |         QStringLiteral("%1%").arg(Settings::values.cpu_clock_percentage.GetValue())); | ||||||
|  |     ui->toggle_new_3ds->setChecked(Settings::values.is_new_3ds.GetValue()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ConfigureSystem::ReadSystemSettings() { | void ConfigureSystem::ReadSystemSettings() { | ||||||
|     // set username
 |     // set username
 | ||||||
|     username = cfg->GetUsername(); |     username = cfg->GetUsername(); | ||||||
|     // TODO(wwylele): Use this when we move to Qt 5.5
 |     ui->edit_username->setText(QString::fromStdU16String(username)); | ||||||
|     // ui->edit_username->setText(QString::fromStdU16String(username));
 |  | ||||||
|     ui->edit_username->setText( |  | ||||||
|         QString::fromUtf16(reinterpret_cast<const ushort*>(username.data()))); |  | ||||||
| 
 | 
 | ||||||
|     // set birthday
 |     // set birthday
 | ||||||
|     std::tie(birthmonth, birthday) = cfg->GetBirthday(); |     std::tie(birthmonth, birthday) = cfg->GetBirthday(); | ||||||
|  | @ -337,32 +350,29 @@ void ConfigureSystem::ApplyConfiguration() { | ||||||
|         bool modified = false; |         bool modified = false; | ||||||
| 
 | 
 | ||||||
|         // apply username
 |         // apply username
 | ||||||
|         // TODO(wwylele): Use this when we move to Qt 5.5
 |         std::u16string new_username = ui->edit_username->text().toStdU16String(); | ||||||
|         // std::u16string new_username = ui->edit_username->text().toStdU16String();
 |  | ||||||
|         std::u16string new_username( |  | ||||||
|             reinterpret_cast<const char16_t*>(ui->edit_username->text().utf16())); |  | ||||||
|         if (new_username != username) { |         if (new_username != username) { | ||||||
|             cfg->SetUsername(new_username); |             cfg->SetUsername(new_username); | ||||||
|             modified = true; |             modified = true; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         // apply birthday
 |         // apply birthday
 | ||||||
|         int new_birthmonth = ui->combo_birthmonth->currentIndex() + 1; |         s32 new_birthmonth = ui->combo_birthmonth->currentIndex() + 1; | ||||||
|         int new_birthday = ui->combo_birthday->currentIndex() + 1; |         s32 new_birthday = ui->combo_birthday->currentIndex() + 1; | ||||||
|         if (birthmonth != new_birthmonth || birthday != new_birthday) { |         if (birthmonth != new_birthmonth || birthday != new_birthday) { | ||||||
|             cfg->SetBirthday(new_birthmonth, new_birthday); |             cfg->SetBirthday(new_birthmonth, new_birthday); | ||||||
|             modified = true; |             modified = true; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         // apply language
 |         // apply language
 | ||||||
|         int new_language = ui->combo_language->currentIndex(); |         s32 new_language = ui->combo_language->currentIndex(); | ||||||
|         if (language_index != new_language) { |         if (language_index != new_language) { | ||||||
|             cfg->SetSystemLanguage(static_cast<Service::CFG::SystemLanguage>(new_language)); |             cfg->SetSystemLanguage(static_cast<Service::CFG::SystemLanguage>(new_language)); | ||||||
|             modified = true; |             modified = true; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         // apply sound
 |         // apply sound
 | ||||||
|         int new_sound = ui->combo_sound->currentIndex(); |         s32 new_sound = ui->combo_sound->currentIndex(); | ||||||
|         if (sound_index != new_sound) { |         if (sound_index != new_sound) { | ||||||
|             cfg->SetSoundOutputMode(static_cast<Service::CFG::SoundOutputMode>(new_sound)); |             cfg->SetSoundOutputMode(static_cast<Service::CFG::SoundOutputMode>(new_sound)); | ||||||
|             modified = true; |             modified = true; | ||||||
|  | @ -386,6 +396,9 @@ void ConfigureSystem::ApplyConfiguration() { | ||||||
|             cfg->UpdateConfigNANDSavegame(); |             cfg->UpdateConfigNANDSavegame(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         ConfigurationShared::ApplyPerGameSetting(&Settings::values.is_new_3ds, ui->toggle_new_3ds, | ||||||
|  |                                                  is_new_3ds); | ||||||
|  | 
 | ||||||
|         Settings::values.init_clock = |         Settings::values.init_clock = | ||||||
|             static_cast<Settings::InitClock>(ui->combo_init_clock->currentIndex()); |             static_cast<Settings::InitClock>(ui->combo_init_clock->currentIndex()); | ||||||
|         Settings::values.init_time = ui->edit_init_time->dateTime().toTime_t(); |         Settings::values.init_time = ui->edit_init_time->dateTime().toTime_t(); | ||||||
|  | @ -398,11 +411,11 @@ void ConfigureSystem::ApplyConfiguration() { | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         Settings::values.init_time_offset = time_offset_days + time_offset_time; |         Settings::values.init_time_offset = time_offset_days + time_offset_time; | ||||||
|         Settings::values.is_new_3ds = ui->toggle_new_3ds->isChecked(); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     Settings::values.cpu_clock_percentage = SliderToSettings(ui->slider_clock_speed->value()); |     ConfigurationShared::ApplyPerGameSetting( | ||||||
|     Settings::Apply(); |         &Settings::values.cpu_clock_percentage, ui->clock_speed_combo, | ||||||
|  |         [this](s32) { return SliderToSettings(ui->slider_clock_speed->value()); }); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ConfigureSystem::UpdateBirthdayComboBox(int birthmonth_index) { | void ConfigureSystem::UpdateBirthdayComboBox(int birthmonth_index) { | ||||||
|  | @ -410,10 +423,10 @@ void ConfigureSystem::UpdateBirthdayComboBox(int birthmonth_index) { | ||||||
|         return; |         return; | ||||||
| 
 | 
 | ||||||
|     // store current day selection
 |     // store current day selection
 | ||||||
|     int birthday_index = ui->combo_birthday->currentIndex(); |     s32 birthday_index = ui->combo_birthday->currentIndex(); | ||||||
| 
 | 
 | ||||||
|     // get number of days in the new selected month
 |     // get number of days in the new selected month
 | ||||||
|     int days = days_in_month[birthmonth_index]; |     s32 days = days_in_month[birthmonth_index]; | ||||||
| 
 | 
 | ||||||
|     // if the selected day is out of range,
 |     // if the selected day is out of range,
 | ||||||
|     // reset it to 1st
 |     // reset it to 1st
 | ||||||
|  | @ -422,7 +435,7 @@ void ConfigureSystem::UpdateBirthdayComboBox(int birthmonth_index) { | ||||||
| 
 | 
 | ||||||
|     // update the day combo box
 |     // update the day combo box
 | ||||||
|     ui->combo_birthday->clear(); |     ui->combo_birthday->clear(); | ||||||
|     for (int i = 1; i <= days; ++i) { |     for (s32 i = 1; i <= days; ++i) { | ||||||
|         ui->combo_birthday->addItem(QString::number(i)); |         ui->combo_birthday->addItem(QString::number(i)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -442,15 +455,16 @@ void ConfigureSystem::ConfigureTime() { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ConfigureSystem::UpdateInitTime(int init_clock) { | void ConfigureSystem::UpdateInitTime(int init_clock) { | ||||||
|  |     const bool is_global = Settings::IsConfiguringGlobal(); | ||||||
|     const bool is_fixed_time = |     const bool is_fixed_time = | ||||||
|         static_cast<Settings::InitClock>(init_clock) == Settings::InitClock::FixedTime; |         static_cast<Settings::InitClock>(init_clock) == Settings::InitClock::FixedTime; | ||||||
| 
 | 
 | ||||||
|     ui->label_init_time->setVisible(is_fixed_time); |     ui->label_init_time->setVisible(is_fixed_time && is_global); | ||||||
|     ui->edit_init_time->setVisible(is_fixed_time); |     ui->edit_init_time->setVisible(is_fixed_time && is_global); | ||||||
| 
 | 
 | ||||||
|     ui->label_init_time_offset->setVisible(!is_fixed_time); |     ui->label_init_time_offset->setVisible(!is_fixed_time && is_global); | ||||||
|     ui->edit_init_time_offset_days->setVisible(!is_fixed_time); |     ui->edit_init_time_offset_days->setVisible(!is_fixed_time && is_global); | ||||||
|     ui->edit_init_time_offset_time->setVisible(!is_fixed_time); |     ui->edit_init_time_offset_time->setVisible(!is_fixed_time && is_global); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ConfigureSystem::RefreshConsoleID() { | void ConfigureSystem::RefreshConsoleID() { | ||||||
|  | @ -475,3 +489,43 @@ void ConfigureSystem::RefreshConsoleID() { | ||||||
| void ConfigureSystem::RetranslateUI() { | void ConfigureSystem::RetranslateUI() { | ||||||
|     ui->retranslateUi(this); |     ui->retranslateUi(this); | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | void ConfigureSystem::SetupPerGameUI() { | ||||||
|  |     // Block the global settings if a game is currently running that overrides them
 | ||||||
|  |     if (Settings::IsConfiguringGlobal()) { | ||||||
|  |         ui->toggle_new_3ds->setEnabled(Settings::values.is_new_3ds.UsingGlobal()); | ||||||
|  |         ui->slider_clock_speed->setEnabled(Settings::values.cpu_clock_percentage.UsingGlobal()); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // Hide most settings for now, we can implement them later
 | ||||||
|  |     ui->label_username->setVisible(false); | ||||||
|  |     ui->label_birthday->setVisible(false); | ||||||
|  |     ui->label_init_clock->setVisible(false); | ||||||
|  |     ui->label_init_time->setVisible(false); | ||||||
|  |     ui->label_console_id->setVisible(false); | ||||||
|  |     ui->label_sound->setVisible(false); | ||||||
|  |     ui->label_language->setVisible(false); | ||||||
|  |     ui->label_country->setVisible(false); | ||||||
|  |     ui->label_play_coins->setVisible(false); | ||||||
|  |     ui->edit_username->setVisible(false); | ||||||
|  |     ui->spinBox_play_coins->setVisible(false); | ||||||
|  |     ui->combo_birthday->setVisible(false); | ||||||
|  |     ui->combo_birthmonth->setVisible(false); | ||||||
|  |     ui->combo_init_clock->setVisible(false); | ||||||
|  |     ui->combo_sound->setVisible(false); | ||||||
|  |     ui->combo_language->setVisible(false); | ||||||
|  |     ui->combo_country->setVisible(false); | ||||||
|  |     ui->label_init_time_offset->setVisible(false); | ||||||
|  |     ui->edit_init_time_offset_days->setVisible(false); | ||||||
|  |     ui->edit_init_time_offset_time->setVisible(false); | ||||||
|  |     ui->button_regenerate_console_id->setVisible(false); | ||||||
|  | 
 | ||||||
|  |     connect(ui->clock_speed_combo, qOverload<int>(&QComboBox::activated), this, [this](int index) { | ||||||
|  |         ui->slider_clock_speed->setEnabled(index == 1); | ||||||
|  |         ConfigurationShared::SetHighlight(ui->clock_speed_widget, index == 1); | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     ConfigurationShared::SetColoredTristate(ui->toggle_new_3ds, Settings::values.is_new_3ds, | ||||||
|  |                                             is_new_3ds); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -12,6 +12,10 @@ namespace Ui { | ||||||
| class ConfigureSystem; | class ConfigureSystem; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | namespace ConfigurationShared { | ||||||
|  | enum class CheckState; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| namespace Service { | namespace Service { | ||||||
| namespace CFG { | namespace CFG { | ||||||
| class Module; | class Module; | ||||||
|  | @ -37,6 +41,9 @@ private: | ||||||
|     void UpdateInitTime(int init_clock); |     void UpdateInitTime(int init_clock); | ||||||
|     void RefreshConsoleID(); |     void RefreshConsoleID(); | ||||||
| 
 | 
 | ||||||
|  |     void SetupPerGameUI(); | ||||||
|  | 
 | ||||||
|  |     ConfigurationShared::CheckState is_new_3ds; | ||||||
|     std::unique_ptr<Ui::ConfigureSystem> ui; |     std::unique_ptr<Ui::ConfigureSystem> ui; | ||||||
|     bool enabled = false; |     bool enabled = false; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -6,8 +6,8 @@ | ||||||
|    <rect> |    <rect> | ||||||
|     <x>0</x> |     <x>0</x> | ||||||
|     <y>0</y> |     <y>0</y> | ||||||
|     <width>520</width> |     <width>525</width> | ||||||
|     <height>564</height> |     <height>619</height> | ||||||
|    </rect> |    </rect> | ||||||
|   </property> |   </property> | ||||||
|   <property name="windowTitle"> |   <property name="windowTitle"> | ||||||
|  | @ -344,54 +344,77 @@ | ||||||
|       </widget> |       </widget> | ||||||
|      </item> |      </item> | ||||||
|      <item> |      <item> | ||||||
|       <widget class="QGroupBox" name="groupBox"> |       <widget class="QGroupBox" name="group_advanced"> | ||||||
|        <property name="title"> |        <property name="title"> | ||||||
|         <string>Advanced</string> |         <string>Advanced</string> | ||||||
|        </property> |        </property> | ||||||
|        <layout class="QGridLayout" name="gridLayout_2"> |        <layout class="QGridLayout" name="gridLayout_2"> | ||||||
|         <item row="0" column="0"> |         <item row="0" column="0"> | ||||||
|          <widget class="QLabel" name="label_3"> |          <widget class="QWidget" name="clock_speed_widget" native="true"> | ||||||
|           <property name="text"> |           <layout class="QHBoxLayout" name="clock_speed_layout"> | ||||||
|            <string>CPU Clock Speed</string> |            <property name="spacing"> | ||||||
|           </property> |             <number>7</number> | ||||||
|          </widget> |            </property> | ||||||
|         </item> |            <item> | ||||||
|         <item row="0" column="2"> |             <widget class="QComboBox" name="clock_speed_combo"> | ||||||
|          <widget class="QSlider" name="slider_clock_speed"> |              <item> | ||||||
|           <property name="toolTip"> |               <property name="text"> | ||||||
|            <string><html><body>Changes the emulated CPU clock frequency.<br>Underclocking can increase performance but may cause the game to freeze.<br>Overclocking may reduce in game lag but also might cause freezes</body></html></string> |                <string>Use global clock speed</string> | ||||||
|           </property> |               </property> | ||||||
|           <property name="minimum"> |              </item> | ||||||
|            <number>0</number> |              <item> | ||||||
|           </property> |               <property name="text"> | ||||||
|           <property name="maximum"> |                <string>Set clock speed:</string> | ||||||
|            <number>79</number> |               </property> | ||||||
|           </property> |              </item> | ||||||
|           <property name="singleStep"> |             </widget> | ||||||
|            <number>5</number> |            </item> | ||||||
|           </property> |            <item> | ||||||
|           <property name="pageStep"> |             <widget class="QLabel" name="clock_speed_label"> | ||||||
|            <number>15</number> |              <property name="text"> | ||||||
|           </property> |               <string>CPU Clock Speed</string> | ||||||
|           <property name="value"> |              </property> | ||||||
|            <number>25</number> |             </widget> | ||||||
|           </property> |            </item> | ||||||
|           <property name="orientation"> |            <item> | ||||||
|            <enum>Qt::Horizontal</enum> |             <widget class="QSlider" name="slider_clock_speed"> | ||||||
|           </property> |              <property name="toolTip"> | ||||||
|           <property name="tickPosition"> |               <string><html><body>Changes the emulated CPU clock frequency.<br>Underclocking can increase performance but may cause the game to freeze.<br>Overclocking may reduce in game lag but also might cause freezes</body></html></string> | ||||||
|            <enum>QSlider::TicksBelow</enum> |              </property> | ||||||
|           </property> |              <property name="minimum"> | ||||||
|          </widget> |               <number>0</number> | ||||||
|         </item> |              </property> | ||||||
|         <item row="0" column="1"> |              <property name="maximum"> | ||||||
|          <widget class="QLabel" name="clock_display_label"> |               <number>79</number> | ||||||
|           <property name="text"> |              </property> | ||||||
|            <string/> |              <property name="singleStep"> | ||||||
|           </property> |               <number>5</number> | ||||||
|           <property name="alignment"> |              </property> | ||||||
|            <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> |              <property name="pageStep"> | ||||||
|           </property> |               <number>15</number> | ||||||
|  |              </property> | ||||||
|  |              <property name="value"> | ||||||
|  |               <number>25</number> | ||||||
|  |              </property> | ||||||
|  |              <property name="orientation"> | ||||||
|  |               <enum>Qt::Horizontal</enum> | ||||||
|  |              </property> | ||||||
|  |              <property name="tickPosition"> | ||||||
|  |               <enum>QSlider::TicksBelow</enum> | ||||||
|  |              </property> | ||||||
|  |             </widget> | ||||||
|  |            </item> | ||||||
|  |            <item> | ||||||
|  |             <widget class="QLabel" name="clock_display_label"> | ||||||
|  |              <property name="text"> | ||||||
|  |               <string/> | ||||||
|  |              </property> | ||||||
|  |              <property name="alignment"> | ||||||
|  |               <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> | ||||||
|  |              </property> | ||||||
|  |             </widget> | ||||||
|  |            </item> | ||||||
|  |           </layout> | ||||||
|          </widget> |          </widget> | ||||||
|         </item> |         </item> | ||||||
|        </layout> |        </layout> | ||||||
|  | @ -449,7 +472,6 @@ | ||||||
|   <tabstop>edit_init_time</tabstop> |   <tabstop>edit_init_time</tabstop> | ||||||
|   <tabstop>spinBox_play_coins</tabstop> |   <tabstop>spinBox_play_coins</tabstop> | ||||||
|   <tabstop>button_regenerate_console_id</tabstop> |   <tabstop>button_regenerate_console_id</tabstop> | ||||||
|   <tabstop>slider_clock_speed</tabstop> |  | ||||||
|  </tabstops> |  </tabstops> | ||||||
|  <resources/> |  <resources/> | ||||||
|  <connections/> |  <connections/> | ||||||
|  |  | ||||||
|  | @ -9,7 +9,7 @@ | ||||||
| #include <optional> | #include <optional> | ||||||
| #include <vector> | #include <vector> | ||||||
| #include <QDialog> | #include <QDialog> | ||||||
| #include "core/settings.h" | #include "common/settings.h" | ||||||
| 
 | 
 | ||||||
| class QItemSelection; | class QItemSelection; | ||||||
| class QModelIndex; | class QModelIndex; | ||||||
|  |  | ||||||
|  | @ -46,12 +46,14 @@ void ConfigureUi::SetConfiguration() { | ||||||
|     ui->language_combobox->setCurrentIndex( |     ui->language_combobox->setCurrentIndex( | ||||||
|         ui->language_combobox->findData(UISettings::values.language)); |         ui->language_combobox->findData(UISettings::values.language)); | ||||||
|     ui->icon_size_combobox->setCurrentIndex( |     ui->icon_size_combobox->setCurrentIndex( | ||||||
|         static_cast<int>(UISettings::values.game_list_icon_size)); |         static_cast<int>(UISettings::values.game_list_icon_size.GetValue())); | ||||||
|     ui->row_1_text_combobox->setCurrentIndex(static_cast<int>(UISettings::values.game_list_row_1)); |     ui->row_1_text_combobox->setCurrentIndex( | ||||||
|     ui->row_2_text_combobox->setCurrentIndex(static_cast<int>(UISettings::values.game_list_row_2) + |         static_cast<int>(UISettings::values.game_list_row_1.GetValue())); | ||||||
|                                              1); |     ui->row_2_text_combobox->setCurrentIndex( | ||||||
|     ui->toggle_hide_no_icon->setChecked(UISettings::values.game_list_hide_no_icon); |         static_cast<int>(UISettings::values.game_list_row_2.GetValue()) + 1); | ||||||
|     ui->toggle_single_line_mode->setChecked(UISettings::values.game_list_single_line_mode); |     ui->toggle_hide_no_icon->setChecked(UISettings::values.game_list_hide_no_icon.GetValue()); | ||||||
|  |     ui->toggle_single_line_mode->setChecked( | ||||||
|  |         UISettings::values.game_list_single_line_mode.GetValue()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ConfigureUi::ApplyConfiguration() { | void ConfigureUi::ApplyConfiguration() { | ||||||
|  |  | ||||||
|  | @ -87,7 +87,7 @@ void ConfigureWeb::SetConfiguration() { | ||||||
|         tr("Telemetry ID: 0x%1").arg(QString::number(Core::GetTelemetryId(), 16).toUpper())); |         tr("Telemetry ID: 0x%1").arg(QString::number(Core::GetTelemetryId(), 16).toUpper())); | ||||||
|     user_verified = true; |     user_verified = true; | ||||||
| 
 | 
 | ||||||
|     ui->toggle_discordrpc->setChecked(UISettings::values.enable_discord_presence); |     ui->toggle_discordrpc->setChecked(UISettings::values.enable_discord_presence.GetValue()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ConfigureWeb::ApplyConfiguration() { | void ConfigureWeb::ApplyConfiguration() { | ||||||
|  |  | ||||||
|  | @ -15,10 +15,10 @@ | ||||||
| namespace Debugger { | namespace Debugger { | ||||||
| void ToggleConsole() { | void ToggleConsole() { | ||||||
|     static bool console_shown = false; |     static bool console_shown = false; | ||||||
|     if (console_shown == UISettings::values.show_console) { |     if (console_shown == UISettings::values.show_console.GetValue()) { | ||||||
|         return; |         return; | ||||||
|     } else { |     } else { | ||||||
|         console_shown = UISettings::values.show_console; |         console_shown = UISettings::values.show_console.GetValue(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| #ifdef _WIN32 | #ifdef _WIN32 | ||||||
|  |  | ||||||
|  | @ -7,7 +7,7 @@ | ||||||
| #include <QLayout> | #include <QLayout> | ||||||
| #include <QScrollArea> | #include <QScrollArea> | ||||||
| #include "citra_qt/debugger/lle_service_modules.h" | #include "citra_qt/debugger/lle_service_modules.h" | ||||||
| #include "core/settings.h" | #include "common/settings.h" | ||||||
| 
 | 
 | ||||||
| LLEServiceModulesWidget::LLEServiceModulesWidget(QWidget* parent) | LLEServiceModulesWidget::LLEServiceModulesWidget(QWidget* parent) | ||||||
|     : QDockWidget(tr("Toggle LLE Service Modules"), parent) { |     : QDockWidget(tr("Toggle LLE Service Modules"), parent) { | ||||||
|  |  | ||||||
|  | @ -7,13 +7,13 @@ | ||||||
| #include "citra_qt/uisettings.h" | #include "citra_qt/uisettings.h" | ||||||
| #include "citra_qt/util/util.h" | #include "citra_qt/util/util.h" | ||||||
| #include "common/assert.h" | #include "common/assert.h" | ||||||
|  | #include "common/settings.h" | ||||||
| #include "core/hle/kernel/event.h" | #include "core/hle/kernel/event.h" | ||||||
| #include "core/hle/kernel/mutex.h" | #include "core/hle/kernel/mutex.h" | ||||||
| #include "core/hle/kernel/semaphore.h" | #include "core/hle/kernel/semaphore.h" | ||||||
| #include "core/hle/kernel/thread.h" | #include "core/hle/kernel/thread.h" | ||||||
| #include "core/hle/kernel/timer.h" | #include "core/hle/kernel/timer.h" | ||||||
| #include "core/hle/kernel/wait_object.h" | #include "core/hle/kernel/wait_object.h" | ||||||
| #include "core/settings.h" |  | ||||||
| 
 | 
 | ||||||
| namespace { | namespace { | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -7,7 +7,7 @@ | ||||||
| #include "citra_qt/dumping/dumping_dialog.h" | #include "citra_qt/dumping/dumping_dialog.h" | ||||||
| #include "citra_qt/dumping/options_dialog.h" | #include "citra_qt/dumping/options_dialog.h" | ||||||
| #include "citra_qt/uisettings.h" | #include "citra_qt/uisettings.h" | ||||||
| #include "core/settings.h" | #include "common/settings.h" | ||||||
| #include "ui_dumping_dialog.h" | #include "ui_dumping_dialog.h" | ||||||
| 
 | 
 | ||||||
| DumpingDialog::DumpingDialog(QWidget* parent) | DumpingDialog::DumpingDialog(QWidget* parent) | ||||||
|  |  | ||||||
|  | @ -3,6 +3,7 @@ | ||||||
| // Refer to the license.txt file included.
 | // Refer to the license.txt file included.
 | ||||||
| 
 | 
 | ||||||
| #include <QApplication> | #include <QApplication> | ||||||
|  | #include <QDir> | ||||||
| #include <QFileInfo> | #include <QFileInfo> | ||||||
| #include <QFileSystemWatcher> | #include <QFileSystemWatcher> | ||||||
| #include <QHBoxLayout> | #include <QHBoxLayout> | ||||||
|  | @ -28,9 +29,11 @@ | ||||||
| #include "citra_qt/main.h" | #include "citra_qt/main.h" | ||||||
| #include "citra_qt/uisettings.h" | #include "citra_qt/uisettings.h" | ||||||
| #include "common/logging/log.h" | #include "common/logging/log.h" | ||||||
|  | #include "common/settings.h" | ||||||
| #include "core/file_sys/archive_extsavedata.h" | #include "core/file_sys/archive_extsavedata.h" | ||||||
| #include "core/file_sys/archive_source_sd_savedata.h" | #include "core/file_sys/archive_source_sd_savedata.h" | ||||||
| #include "core/hle/service/fs/archive.h" | #include "core/hle/service/fs/archive.h" | ||||||
|  | #include "qcursor.h" | ||||||
| 
 | 
 | ||||||
| GameListSearchField::KeyReleaseEater::KeyReleaseEater(GameList* gamelist, QObject* parent) | GameListSearchField::KeyReleaseEater::KeyReleaseEater(GameList* gamelist, QObject* parent) | ||||||
|     : QObject(parent), gamelist{gamelist} {} |     : QObject(parent), gamelist{gamelist} {} | ||||||
|  | @ -462,9 +465,20 @@ void GameList::PopupContextMenu(const QPoint& menu_location) { | ||||||
|     default: |     default: | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|     context_menu.exec(tree_view->viewport()->mapToGlobal(menu_location)); |     context_menu.exec(tree_view->viewport()->mapToGlobal(menu_location)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void ForEachOpenGLCacheFile(u64 program_id, auto func) { | ||||||
|  |     for (const std::string_view cache_type : {"separable", "conventional"}) { | ||||||
|  |         const std::string path = fmt::format("{}opengl/precompiled/{}/{:016X}.bin", | ||||||
|  |                                              FileUtil::GetUserPath(FileUtil::UserPath::ShaderDir), | ||||||
|  |                                              cache_type, program_id); | ||||||
|  |         QFile file{QString::fromStdString(path)}; | ||||||
|  |         func(file); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void GameList::AddGamePopup(QMenu& context_menu, const QString& path, u64 program_id, | void GameList::AddGamePopup(QMenu& context_menu, const QString& path, u64 program_id, | ||||||
|                             u64 extdata_id) { |                             u64 extdata_id) { | ||||||
|     QAction* open_save_location = context_menu.addAction(tr("Open Save Data Location")); |     QAction* open_save_location = context_menu.addAction(tr("Open Save Data Location")); | ||||||
|  | @ -475,19 +489,32 @@ void GameList::AddGamePopup(QMenu& context_menu, const QString& path, u64 progra | ||||||
|     QAction* open_texture_load_location = |     QAction* open_texture_load_location = | ||||||
|         context_menu.addAction(tr("Open Custom Texture Location")); |         context_menu.addAction(tr("Open Custom Texture Location")); | ||||||
|     QAction* open_mods_location = context_menu.addAction(tr("Open Mods Location")); |     QAction* open_mods_location = context_menu.addAction(tr("Open Mods Location")); | ||||||
|  |     QAction* open_dlc_location = context_menu.addAction(tr("Open DLC Data Location")); | ||||||
|  |     QMenu* shader_menu = context_menu.addMenu(tr("Disk Shader Cache")); | ||||||
|     QAction* dump_romfs = context_menu.addAction(tr("Dump RomFS")); |     QAction* dump_romfs = context_menu.addAction(tr("Dump RomFS")); | ||||||
|     QAction* navigate_to_gamedb_entry = context_menu.addAction(tr("Navigate to GameDB entry")); |     QAction* navigate_to_gamedb_entry = context_menu.addAction(tr("Navigate to GameDB entry")); | ||||||
|  |     context_menu.addSeparator(); | ||||||
|  |     QAction* properties = context_menu.addAction(tr("Properties")); | ||||||
|  | 
 | ||||||
|  |     QAction* open_shader_cache_location = shader_menu->addAction(tr("Open Shader Cache Location")); | ||||||
|  |     shader_menu->addSeparator(); | ||||||
|  |     QAction* delete_opengl_disk_shader_cache = | ||||||
|  |         shader_menu->addAction(tr("Delete OpenGL Shader Cache")); | ||||||
| 
 | 
 | ||||||
|     const bool is_application = |     const bool is_application = | ||||||
|         0x0004000000000000 <= program_id && program_id <= 0x00040000FFFFFFFF; |         0x0004000000000000 <= program_id && program_id <= 0x00040000FFFFFFFF; | ||||||
| 
 | 
 | ||||||
|  |     bool opengl_cache_exists = false; | ||||||
|  |     ForEachOpenGLCacheFile( | ||||||
|  |         program_id, [&opengl_cache_exists](QFile& file) { opengl_cache_exists |= file.exists(); }); | ||||||
|  | 
 | ||||||
|     std::string sdmc_dir = FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir); |     std::string sdmc_dir = FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir); | ||||||
|     open_save_location->setVisible( |     open_save_location->setEnabled( | ||||||
|         is_application && FileUtil::Exists(FileSys::ArchiveSource_SDSaveData::GetSaveDataPathFor( |         is_application && FileUtil::Exists(FileSys::ArchiveSource_SDSaveData::GetSaveDataPathFor( | ||||||
|                               sdmc_dir, program_id))); |                               sdmc_dir, program_id))); | ||||||
| 
 | 
 | ||||||
|     if (extdata_id) { |     if (extdata_id) { | ||||||
|         open_extdata_location->setVisible( |         open_extdata_location->setEnabled( | ||||||
|             is_application && |             is_application && | ||||||
|             FileUtil::Exists(FileSys::GetExtDataPathFromId(sdmc_dir, extdata_id))); |             FileUtil::Exists(FileSys::GetExtDataPathFromId(sdmc_dir, extdata_id))); | ||||||
|     } else { |     } else { | ||||||
|  | @ -495,18 +522,20 @@ void GameList::AddGamePopup(QMenu& context_menu, const QString& path, u64 progra | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     auto media_type = Service::AM::GetTitleMediaType(program_id); |     auto media_type = Service::AM::GetTitleMediaType(program_id); | ||||||
|     open_application_location->setVisible(path.toStdString() == |     open_application_location->setEnabled(path.toStdString() == | ||||||
|                                           Service::AM::GetTitleContentPath(media_type, program_id)); |                                           Service::AM::GetTitleContentPath(media_type, program_id)); | ||||||
|     open_update_location->setVisible( |     open_update_location->setEnabled( | ||||||
|         is_application && FileUtil::Exists(Service::AM::GetTitlePath(Service::FS::MediaType::SDMC, |         is_application && FileUtil::Exists(Service::AM::GetTitlePath(Service::FS::MediaType::SDMC, | ||||||
|                                                                      program_id + 0xe00000000) + |                                                                      program_id + 0xe00000000) + | ||||||
|                                            "content/")); |                                            "content/")); | ||||||
|     auto it = FindMatchingCompatibilityEntry(compatibility_list, program_id); |     auto it = FindMatchingCompatibilityEntry(compatibility_list, program_id); | ||||||
| 
 | 
 | ||||||
|     open_texture_dump_location->setVisible(is_application); |     open_texture_dump_location->setEnabled(is_application); | ||||||
|     open_texture_load_location->setVisible(is_application); |     open_texture_load_location->setEnabled(is_application); | ||||||
|     open_mods_location->setVisible(is_application); |     open_mods_location->setEnabled(is_application); | ||||||
|     dump_romfs->setVisible(is_application); |     open_dlc_location->setEnabled(is_application); | ||||||
|  |     dump_romfs->setEnabled(is_application); | ||||||
|  |     delete_opengl_disk_shader_cache->setEnabled(opengl_cache_exists); | ||||||
| 
 | 
 | ||||||
|     navigate_to_gamedb_entry->setVisible(it != compatibility_list.end()); |     navigate_to_gamedb_entry->setVisible(it != compatibility_list.end()); | ||||||
| 
 | 
 | ||||||
|  | @ -543,11 +572,32 @@ void GameList::AddGamePopup(QMenu& context_menu, const QString& path, u64 progra | ||||||
|             emit OpenFolderRequested(program_id, GameListOpenTarget::MODS); |             emit OpenFolderRequested(program_id, GameListOpenTarget::MODS); | ||||||
|         } |         } | ||||||
|     }); |     }); | ||||||
|  |     connect(open_dlc_location, &QAction::triggered, this, [this, program_id] { | ||||||
|  |         const u64 trimmed_id = program_id & 0xFFFFFFF; | ||||||
|  |         const std::string dlc_path = | ||||||
|  |             fmt::format("{}Nintendo 3DS/00000000000000000000000000000000/" | ||||||
|  |                         "00000000000000000000000000000000/title/0004008c/{:08x}/content/", | ||||||
|  |                         FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir), trimmed_id); | ||||||
|  |         fmt::print("DLC path {}\n", dlc_path); | ||||||
|  |         if (FileUtil::CreateFullPath(dlc_path)) { | ||||||
|  |             emit OpenFolderRequested(trimmed_id, GameListOpenTarget::DLC_DATA); | ||||||
|  |         } | ||||||
|  |     }); | ||||||
|     connect(dump_romfs, &QAction::triggered, this, |     connect(dump_romfs, &QAction::triggered, this, | ||||||
|             [this, path, program_id] { emit DumpRomFSRequested(path, program_id); }); |             [this, path, program_id] { emit DumpRomFSRequested(path, program_id); }); | ||||||
|     connect(navigate_to_gamedb_entry, &QAction::triggered, this, [this, program_id]() { |     connect(navigate_to_gamedb_entry, &QAction::triggered, this, [this, program_id]() { | ||||||
|         emit NavigateToGamedbEntryRequested(program_id, compatibility_list); |         emit NavigateToGamedbEntryRequested(program_id, compatibility_list); | ||||||
|     }); |     }); | ||||||
|  |     connect(properties, &QAction::triggered, this, | ||||||
|  |             [this, path]() { emit OpenPerGameGeneralRequested(path); }); | ||||||
|  |     connect(open_shader_cache_location, &QAction::triggered, this, [this, program_id] { | ||||||
|  |         if (FileUtil::CreateFullPath(FileUtil::GetUserPath(FileUtil::UserPath::ShaderDir))) { | ||||||
|  |             emit OpenFolderRequested(program_id, GameListOpenTarget::SHADER_CACHE); | ||||||
|  |         } | ||||||
|  |     }); | ||||||
|  |     connect(delete_opengl_disk_shader_cache, &QAction::triggered, this, [program_id] { | ||||||
|  |         ForEachOpenGLCacheFile(program_id, [](QFile& file) { file.remove(); }); | ||||||
|  |     }); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| void GameList::AddCustomDirPopup(QMenu& context_menu, QModelIndex selected) { | void GameList::AddCustomDirPopup(QMenu& context_menu, QModelIndex selected) { | ||||||
|  |  | ||||||
|  | @ -37,6 +37,8 @@ enum class GameListOpenTarget { | ||||||
|     TEXTURE_DUMP = 4, |     TEXTURE_DUMP = 4, | ||||||
|     TEXTURE_LOAD = 5, |     TEXTURE_LOAD = 5, | ||||||
|     MODS = 6, |     MODS = 6, | ||||||
|  |     DLC_DATA = 7, | ||||||
|  |     SHADER_CACHE = 8 | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| class GameList : public QWidget { | class GameList : public QWidget { | ||||||
|  | @ -82,6 +84,7 @@ signals: | ||||||
|     void OpenFolderRequested(u64 program_id, GameListOpenTarget target); |     void OpenFolderRequested(u64 program_id, GameListOpenTarget target); | ||||||
|     void NavigateToGamedbEntryRequested(u64 program_id, |     void NavigateToGamedbEntryRequested(u64 program_id, | ||||||
|                                         const CompatibilityList& compatibility_list); |                                         const CompatibilityList& compatibility_list); | ||||||
|  |     void OpenPerGameGeneralRequested(const QString file); | ||||||
|     void DumpRomFSRequested(QString game_path, u64 program_id); |     void DumpRomFSRequested(QString game_path, u64 program_id); | ||||||
|     void OpenDirectory(const QString& directory); |     void OpenDirectory(const QString& directory); | ||||||
|     void AddDirectory(); |     void AddDirectory(); | ||||||
|  |  | ||||||
|  | @ -160,17 +160,19 @@ public: | ||||||
|         setData(qulonglong(program_id), ProgramIdRole); |         setData(qulonglong(program_id), ProgramIdRole); | ||||||
|         setData(qulonglong(extdata_id), ExtdataIdRole); |         setData(qulonglong(extdata_id), ExtdataIdRole); | ||||||
| 
 | 
 | ||||||
|         if (UISettings::values.game_list_icon_size == UISettings::GameListIconSize::NoIcon) { |         if (UISettings::values.game_list_icon_size.GetValue() == | ||||||
|  |             UISettings::GameListIconSize::NoIcon) { | ||||||
|             // Do not display icons
 |             // Do not display icons
 | ||||||
|             setData(QPixmap(), Qt::DecorationRole); |             setData(QPixmap(), Qt::DecorationRole); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         bool large = |         bool large = UISettings::values.game_list_icon_size.GetValue() == | ||||||
|             UISettings::values.game_list_icon_size == UISettings::GameListIconSize::LargeIcon; |                      UISettings::GameListIconSize::LargeIcon; | ||||||
| 
 | 
 | ||||||
|         if (!Loader::IsValidSMDH(smdh_data)) { |         if (!Loader::IsValidSMDH(smdh_data)) { | ||||||
|             // SMDH is not valid, set a default icon
 |             // SMDH is not valid, set a default icon
 | ||||||
|             if (UISettings::values.game_list_icon_size != UISettings::GameListIconSize::NoIcon) |             if (UISettings::values.game_list_icon_size.GetValue() != | ||||||
|  |                 UISettings::GameListIconSize::NoIcon) | ||||||
|                 setData(GetDefaultIcon(large), Qt::DecorationRole); |                 setData(GetDefaultIcon(large), Qt::DecorationRole); | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|  | @ -179,7 +181,8 @@ public: | ||||||
|         memcpy(&smdh, smdh_data.data(), sizeof(Loader::SMDH)); |         memcpy(&smdh, smdh_data.data(), sizeof(Loader::SMDH)); | ||||||
| 
 | 
 | ||||||
|         // Get icon from SMDH
 |         // Get icon from SMDH
 | ||||||
|         if (UISettings::values.game_list_icon_size != UISettings::GameListIconSize::NoIcon) { |         if (UISettings::values.game_list_icon_size.GetValue() != | ||||||
|  |             UISettings::GameListIconSize::NoIcon) { | ||||||
|             setData(GetQPixmapFromSMDH(smdh, large), Qt::DecorationRole); |             setData(GetQPixmapFromSMDH(smdh, large), Qt::DecorationRole); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -211,16 +214,17 @@ public: | ||||||
|                  QString::fromStdString(fmt::format("{:016X}", data(ProgramIdRole).toULongLong()))}, |                  QString::fromStdString(fmt::format("{:016X}", data(ProgramIdRole).toULongLong()))}, | ||||||
|             }; |             }; | ||||||
| 
 | 
 | ||||||
|             const QString& row1 = display_texts.at(UISettings::values.game_list_row_1).simplified(); |             const QString& row1 = | ||||||
|  |                 display_texts.at(UISettings::values.game_list_row_1.GetValue()).simplified(); | ||||||
| 
 | 
 | ||||||
|             if (role == SortRole) |             if (role == SortRole) | ||||||
|                 return row1.toLower(); |                 return row1.toLower(); | ||||||
| 
 | 
 | ||||||
|             QString row2; |             QString row2; | ||||||
|             auto row_2_id = UISettings::values.game_list_row_2; |             const auto row_2_id = UISettings::values.game_list_row_2.GetValue(); | ||||||
|             if (row_2_id != UISettings::GameListText::NoText) { |             if (row_2_id != UISettings::GameListText::NoText) { | ||||||
|                 if (!row1.isEmpty()) { |                 if (!row1.isEmpty()) { | ||||||
|                     row2 = UISettings::values.game_list_single_line_mode |                     row2 = UISettings::values.game_list_single_line_mode.GetValue() | ||||||
|                                ? QStringLiteral("     ") |                                ? QStringLiteral("     ") | ||||||
|                                : QStringLiteral("\n     "); |                                : QStringLiteral("\n     "); | ||||||
|                 } |                 } | ||||||
|  | @ -355,7 +359,7 @@ public: | ||||||
|         UISettings::GameDir* game_dir = &directory; |         UISettings::GameDir* game_dir = &directory; | ||||||
|         setData(QVariant(UISettings::values.game_dirs.indexOf(directory)), GameDirRole); |         setData(QVariant(UISettings::values.game_dirs.indexOf(directory)), GameDirRole); | ||||||
| 
 | 
 | ||||||
|         const int icon_size = IconSizes.at(UISettings::values.game_list_icon_size); |         const int icon_size = IconSizes.at(UISettings::values.game_list_icon_size.GetValue()); | ||||||
|         switch (dir_type) { |         switch (dir_type) { | ||||||
|         case GameListItemType::InstalledDir: |         case GameListItemType::InstalledDir: | ||||||
|             setData(QIcon::fromTheme(QStringLiteral("sd_card")).pixmap(icon_size), |             setData(QIcon::fromTheme(QStringLiteral("sd_card")).pixmap(icon_size), | ||||||
|  | @ -398,7 +402,7 @@ public: | ||||||
|     explicit GameListAddDir() { |     explicit GameListAddDir() { | ||||||
|         setData(type(), TypeRole); |         setData(type(), TypeRole); | ||||||
| 
 | 
 | ||||||
|         int icon_size = IconSizes.at(UISettings::values.game_list_icon_size); |         int icon_size = IconSizes.at(UISettings::values.game_list_icon_size.GetValue()); | ||||||
|         setData(QIcon::fromTheme(QStringLiteral("plus")).pixmap(icon_size), Qt::DecorationRole); |         setData(QIcon::fromTheme(QStringLiteral("plus")).pixmap(icon_size), Qt::DecorationRole); | ||||||
|         setData(QObject::tr("Add New Game Directory"), Qt::DisplayRole); |         setData(QObject::tr("Add New Game Directory"), Qt::DisplayRole); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -3,6 +3,7 @@ | ||||||
| // Refer to the license.txt file included.
 | // Refer to the license.txt file included.
 | ||||||
| 
 | 
 | ||||||
| #include <clocale> | #include <clocale> | ||||||
|  | #include <filesystem> | ||||||
| #include <fstream> | #include <fstream> | ||||||
| #include <memory> | #include <memory> | ||||||
| #include <thread> | #include <thread> | ||||||
|  | @ -34,6 +35,7 @@ | ||||||
| #include "citra_qt/compatibility_list.h" | #include "citra_qt/compatibility_list.h" | ||||||
| #include "citra_qt/configuration/config.h" | #include "citra_qt/configuration/config.h" | ||||||
| #include "citra_qt/configuration/configure_dialog.h" | #include "citra_qt/configuration/configure_dialog.h" | ||||||
|  | #include "citra_qt/configuration/configure_per_game.h" | ||||||
| #include "citra_qt/debugger/console.h" | #include "citra_qt/debugger/console.h" | ||||||
| #include "citra_qt/debugger/graphics/graphics.h" | #include "citra_qt/debugger/graphics/graphics.h" | ||||||
| #include "citra_qt/debugger/graphics/graphics_breakpoints.h" | #include "citra_qt/debugger/graphics/graphics_breakpoints.h" | ||||||
|  | @ -70,9 +72,11 @@ | ||||||
| #include "common/microprofile.h" | #include "common/microprofile.h" | ||||||
| #include "common/scm_rev.h" | #include "common/scm_rev.h" | ||||||
| #include "common/scope_exit.h" | #include "common/scope_exit.h" | ||||||
|  | #include "common/string_util.h" | ||||||
| #ifdef ARCHITECTURE_x86_64 | #ifdef ARCHITECTURE_x86_64 | ||||||
| #include "common/x64/cpu_detect.h" | #include "common/x64/cpu_detect.h" | ||||||
| #endif | #endif | ||||||
|  | #include "common/settings.h" | ||||||
| #include "core/core.h" | #include "core/core.h" | ||||||
| #include "core/dumping/backend.h" | #include "core/dumping/backend.h" | ||||||
| #include "core/file_sys/archive_extsavedata.h" | #include "core/file_sys/archive_extsavedata.h" | ||||||
|  | @ -85,7 +89,6 @@ | ||||||
| #include "core/loader/loader.h" | #include "core/loader/loader.h" | ||||||
| #include "core/movie.h" | #include "core/movie.h" | ||||||
| #include "core/savestate.h" | #include "core/savestate.h" | ||||||
| #include "core/settings.h" |  | ||||||
| #include "game_list_p.h" | #include "game_list_p.h" | ||||||
| #include "input_common/main.h" | #include "input_common/main.h" | ||||||
| #include "network/network_settings.h" | #include "network/network_settings.h" | ||||||
|  | @ -124,11 +127,13 @@ enum class CalloutFlag : uint32_t { | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| void GMainWindow::ShowTelemetryCallout() { | void GMainWindow::ShowTelemetryCallout() { | ||||||
|     if (UISettings::values.callout_flags & static_cast<uint32_t>(CalloutFlag::Telemetry)) { |     if (UISettings::values.callout_flags.GetValue() & | ||||||
|  |         static_cast<uint32_t>(CalloutFlag::Telemetry)) { | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     UISettings::values.callout_flags |= static_cast<uint32_t>(CalloutFlag::Telemetry); |     UISettings::values.callout_flags = | ||||||
|  |         UISettings::values.callout_flags.GetValue() | static_cast<uint32_t>(CalloutFlag::Telemetry); | ||||||
|     const QString telemetry_message = |     const QString telemetry_message = | ||||||
|         tr("<a href='https://citra-emu.org/entry/telemetry-and-why-thats-a-good-thing/'>Anonymous " |         tr("<a href='https://citra-emu.org/entry/telemetry-and-why-thats-a-good-thing/'>Anonymous " | ||||||
|            "data is collected</a> to help improve Citra. " |            "data is collected</a> to help improve Citra. " | ||||||
|  | @ -143,7 +148,7 @@ const int GMainWindow::max_recent_files_item; | ||||||
| 
 | 
 | ||||||
| static void InitializeLogging() { | static void InitializeLogging() { | ||||||
|     Log::Filter log_filter; |     Log::Filter log_filter; | ||||||
|     log_filter.ParseFilterString(Settings::values.log_filter); |     log_filter.ParseFilterString(Settings::values.log_filter.GetValue()); | ||||||
|     Log::SetGlobalFilter(log_filter); |     Log::SetGlobalFilter(log_filter); | ||||||
| 
 | 
 | ||||||
|     const std::string& log_dir = FileUtil::GetUserPath(FileUtil::UserPath::LogDir); |     const std::string& log_dir = FileUtil::GetUserPath(FileUtil::UserPath::LogDir); | ||||||
|  | @ -175,7 +180,7 @@ GMainWindow::GMainWindow() | ||||||
|     default_theme_paths = QIcon::themeSearchPaths(); |     default_theme_paths = QIcon::themeSearchPaths(); | ||||||
|     UpdateUITheme(); |     UpdateUITheme(); | ||||||
| 
 | 
 | ||||||
|     SetDiscordEnabled(UISettings::values.enable_discord_presence); |     SetDiscordEnabled(UISettings::values.enable_discord_presence.GetValue()); | ||||||
|     discord_rpc->Update(); |     discord_rpc->Update(); | ||||||
| 
 | 
 | ||||||
|     Network::Init(); |     Network::Init(); | ||||||
|  | @ -556,8 +561,7 @@ void GMainWindow::InitializeHotkeys() { | ||||||
|             }); |             }); | ||||||
|     connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Toggle Alternate Speed"), this), |     connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Toggle Alternate Speed"), this), | ||||||
|             &QShortcut::activated, this, [&] { |             &QShortcut::activated, this, [&] { | ||||||
|                 Settings::values.use_frame_limit_alternate = |                 Settings::values.frame_limit.SetGlobal(!Settings::values.frame_limit.UsingGlobal()); | ||||||
|                     !Settings::values.use_frame_limit_alternate; |  | ||||||
|                 UpdateStatusBar(); |                 UpdateStatusBar(); | ||||||
|             }); |             }); | ||||||
|     connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Toggle Texture Dumping"), this), |     connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Toggle Texture Dumping"), this), | ||||||
|  | @ -568,42 +572,25 @@ void GMainWindow::InitializeHotkeys() { | ||||||
|     static constexpr u16 SPEED_LIMIT_STEP = 5; |     static constexpr u16 SPEED_LIMIT_STEP = 5; | ||||||
|     connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Increase Speed Limit"), this), |     connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Increase Speed Limit"), this), | ||||||
|             &QShortcut::activated, this, [&] { |             &QShortcut::activated, this, [&] { | ||||||
|                 if (Settings::values.use_frame_limit_alternate) { |                 if (Settings::values.frame_limit.GetValue() == 0) { | ||||||
|                     if (Settings::values.frame_limit_alternate == 0) { |                     return; | ||||||
|                         return; |                 } | ||||||
|                     } |                 if (Settings::values.frame_limit.GetValue() < 995 - SPEED_LIMIT_STEP) { | ||||||
|                     if (Settings::values.frame_limit_alternate < 995 - SPEED_LIMIT_STEP) { |                     Settings::values.frame_limit.SetValue(Settings::values.frame_limit.GetValue() + | ||||||
|                         Settings::values.frame_limit_alternate += SPEED_LIMIT_STEP; |                                                           SPEED_LIMIT_STEP); | ||||||
|                     } else { |  | ||||||
|                         Settings::values.frame_limit_alternate = 0; |  | ||||||
|                     } |  | ||||||
|                 } else { |                 } else { | ||||||
|                     if (Settings::values.frame_limit == 0) { |                     Settings::values.frame_limit = 0; | ||||||
|                         return; |  | ||||||
|                     } |  | ||||||
|                     if (Settings::values.frame_limit < 995 - SPEED_LIMIT_STEP) { |  | ||||||
|                         Settings::values.frame_limit += SPEED_LIMIT_STEP; |  | ||||||
|                     } else { |  | ||||||
|                         Settings::values.frame_limit = 0; |  | ||||||
|                     } |  | ||||||
|                 } |                 } | ||||||
|                 UpdateStatusBar(); |                 UpdateStatusBar(); | ||||||
|             }); |             }); | ||||||
|     connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Decrease Speed Limit"), this), |     connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Decrease Speed Limit"), this), | ||||||
|             &QShortcut::activated, this, [&] { |             &QShortcut::activated, this, [&] { | ||||||
|                 if (Settings::values.use_frame_limit_alternate) { |                 if (Settings::values.frame_limit.GetValue() == 0) { | ||||||
|                     if (Settings::values.frame_limit_alternate == 0) { |                     Settings::values.frame_limit = 995; | ||||||
|                         Settings::values.frame_limit_alternate = 995; |                 } else if (Settings::values.frame_limit.GetValue() > SPEED_LIMIT_STEP) { | ||||||
|                     } else if (Settings::values.frame_limit_alternate > SPEED_LIMIT_STEP) { |                     Settings::values.frame_limit.SetValue(Settings::values.frame_limit.GetValue() - | ||||||
|                         Settings::values.frame_limit_alternate -= SPEED_LIMIT_STEP; |                                                           SPEED_LIMIT_STEP); | ||||||
|                     } |                     UpdateStatusBar(); | ||||||
|                 } else { |  | ||||||
|                     if (Settings::values.frame_limit == 0) { |  | ||||||
|                         Settings::values.frame_limit = 995; |  | ||||||
|                     } else if (Settings::values.frame_limit > SPEED_LIMIT_STEP) { |  | ||||||
|                         Settings::values.frame_limit -= SPEED_LIMIT_STEP; |  | ||||||
|                         UpdateStatusBar(); |  | ||||||
|                     } |  | ||||||
|                 } |                 } | ||||||
|                 UpdateStatusBar(); |                 UpdateStatusBar(); | ||||||
|             }); |             }); | ||||||
|  | @ -663,25 +650,26 @@ void GMainWindow::RestoreUIState() { | ||||||
|     render_window->restoreGeometry(UISettings::values.renderwindow_geometry); |     render_window->restoreGeometry(UISettings::values.renderwindow_geometry); | ||||||
| #if MICROPROFILE_ENABLED | #if MICROPROFILE_ENABLED | ||||||
|     microProfileDialog->restoreGeometry(UISettings::values.microprofile_geometry); |     microProfileDialog->restoreGeometry(UISettings::values.microprofile_geometry); | ||||||
|     microProfileDialog->setVisible(UISettings::values.microprofile_visible); |     microProfileDialog->setVisible(UISettings::values.microprofile_visible.GetValue()); | ||||||
| #endif | #endif | ||||||
|     ui->action_Cheats->setEnabled(false); |     ui->action_Cheats->setEnabled(false); | ||||||
| 
 | 
 | ||||||
|     game_list->LoadInterfaceLayout(); |     game_list->LoadInterfaceLayout(); | ||||||
| 
 | 
 | ||||||
|     ui->action_Single_Window_Mode->setChecked(UISettings::values.single_window_mode); |     ui->action_Single_Window_Mode->setChecked(UISettings::values.single_window_mode.GetValue()); | ||||||
|     ToggleWindowMode(); |     ToggleWindowMode(); | ||||||
| 
 | 
 | ||||||
|     ui->action_Fullscreen->setChecked(UISettings::values.fullscreen); |     ui->action_Fullscreen->setChecked(UISettings::values.fullscreen.GetValue()); | ||||||
|     SyncMenuUISettings(); |     SyncMenuUISettings(); | ||||||
| 
 | 
 | ||||||
|     ui->action_Display_Dock_Widget_Headers->setChecked(UISettings::values.display_titlebar); |     ui->action_Display_Dock_Widget_Headers->setChecked( | ||||||
|  |         UISettings::values.display_titlebar.GetValue()); | ||||||
|     OnDisplayTitleBars(ui->action_Display_Dock_Widget_Headers->isChecked()); |     OnDisplayTitleBars(ui->action_Display_Dock_Widget_Headers->isChecked()); | ||||||
| 
 | 
 | ||||||
|     ui->action_Show_Filter_Bar->setChecked(UISettings::values.show_filter_bar); |     ui->action_Show_Filter_Bar->setChecked(UISettings::values.show_filter_bar.GetValue()); | ||||||
|     game_list->SetFilterVisible(ui->action_Show_Filter_Bar->isChecked()); |     game_list->SetFilterVisible(ui->action_Show_Filter_Bar->isChecked()); | ||||||
| 
 | 
 | ||||||
|     ui->action_Show_Status_Bar->setChecked(UISettings::values.show_status_bar); |     ui->action_Show_Status_Bar->setChecked(UISettings::values.show_status_bar.GetValue()); | ||||||
|     statusBar()->setVisible(ui->action_Show_Status_Bar->isChecked()); |     statusBar()->setVisible(ui->action_Show_Status_Bar->isChecked()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -717,6 +705,9 @@ void GMainWindow::ConnectWidgetEvents() { | ||||||
|     connect(game_list, &GameList::PopulatingCompleted, this, |     connect(game_list, &GameList::PopulatingCompleted, this, | ||||||
|             [this] { multiplayer_state->UpdateGameList(game_list->GetModel()); }); |             [this] { multiplayer_state->UpdateGameList(game_list->GetModel()); }); | ||||||
| 
 | 
 | ||||||
|  |     connect(game_list, &GameList::OpenPerGameGeneralRequested, this, | ||||||
|  |             &GMainWindow::OnGameListOpenPerGameProperties); | ||||||
|  | 
 | ||||||
|     connect(this, &GMainWindow::EmulationStarting, render_window, |     connect(this, &GMainWindow::EmulationStarting, render_window, | ||||||
|             &GRenderWindow::OnEmulationStarting); |             &GRenderWindow::OnEmulationStarting); | ||||||
|     connect(this, &GMainWindow::EmulationStopping, render_window, |     connect(this, &GMainWindow::EmulationStopping, render_window, | ||||||
|  | @ -752,6 +743,8 @@ void GMainWindow::ConnectMenuEvents() { | ||||||
|     connect(ui->action_Report_Compatibility, &QAction::triggered, this, |     connect(ui->action_Report_Compatibility, &QAction::triggered, this, | ||||||
|             &GMainWindow::OnMenuReportCompatibility); |             &GMainWindow::OnMenuReportCompatibility); | ||||||
|     connect(ui->action_Configure, &QAction::triggered, this, &GMainWindow::OnConfigure); |     connect(ui->action_Configure, &QAction::triggered, this, &GMainWindow::OnConfigure); | ||||||
|  |     connect(ui->action_Configure_Current_Game, &QAction::triggered, this, | ||||||
|  |             &GMainWindow::OnConfigurePerGame); | ||||||
|     connect(ui->action_Cheats, &QAction::triggered, this, &GMainWindow::OnCheats); |     connect(ui->action_Cheats, &QAction::triggered, this, &GMainWindow::OnCheats); | ||||||
| 
 | 
 | ||||||
|     // View
 |     // View
 | ||||||
|  | @ -1086,6 +1079,22 @@ void GMainWindow::BootGame(const QString& filename) { | ||||||
|         Core::Movie::GetInstance().PrepareForPlayback(movie_playback_path.toStdString()); |         Core::Movie::GetInstance().PrepareForPlayback(movie_playback_path.toStdString()); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     u64 title_id{0}; | ||||||
|  |     const std::string path = filename.toStdString(); | ||||||
|  |     const auto loader = Loader::GetLoader(path); | ||||||
|  | 
 | ||||||
|  |     if (loader != nullptr && loader->ReadProgramId(title_id) == Loader::ResultStatus::Success) { | ||||||
|  |         // Load per game settings
 | ||||||
|  |         const std::string name{FileUtil::GetFilename(filename.toStdString())}; | ||||||
|  |         const std::string config_file_name = | ||||||
|  |             title_id == 0 ? name : fmt::format("{:016X}", title_id); | ||||||
|  |         Config per_game_config(config_file_name, Config::ConfigType::PerGameConfig); | ||||||
|  |         Settings::Apply(); | ||||||
|  | 
 | ||||||
|  |         LOG_INFO(Frontend, "Using per game config file for title id {}", config_file_name); | ||||||
|  |         Settings::LogSettings(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     // Save configurations
 |     // Save configurations
 | ||||||
|     UpdateUISettings(); |     UpdateUISettings(); | ||||||
|     game_list->SaveInterfaceLayout(); |     game_list->SaveInterfaceLayout(); | ||||||
|  | @ -1239,6 +1248,7 @@ void GMainWindow::ShutdownGame() { | ||||||
|     ui->action_Stop->setEnabled(false); |     ui->action_Stop->setEnabled(false); | ||||||
|     ui->action_Restart->setEnabled(false); |     ui->action_Restart->setEnabled(false); | ||||||
|     ui->action_Cheats->setEnabled(false); |     ui->action_Cheats->setEnabled(false); | ||||||
|  |     ui->action_Configure_Current_Game->setEnabled(false); | ||||||
|     ui->action_Load_Amiibo->setEnabled(false); |     ui->action_Load_Amiibo->setEnabled(false); | ||||||
|     ui->action_Remove_Amiibo->setEnabled(false); |     ui->action_Remove_Amiibo->setEnabled(false); | ||||||
|     ui->action_Report_Compatibility->setEnabled(false); |     ui->action_Report_Compatibility->setEnabled(false); | ||||||
|  | @ -1398,26 +1408,42 @@ void GMainWindow::OnGameListOpenFolder(u64 data_id, GameListOpenTarget target) { | ||||||
|         path = Service::AM::GetTitlePath(media_type, data_id) + "content/"; |         path = Service::AM::GetTitlePath(media_type, data_id) + "content/"; | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
|     case GameListOpenTarget::UPDATE_DATA: |     case GameListOpenTarget::UPDATE_DATA: { | ||||||
|         open_target = "Update Data"; |         open_target = "Update Data"; | ||||||
|         path = Service::AM::GetTitlePath(Service::FS::MediaType::SDMC, data_id + 0xe00000000) + |         path = Service::AM::GetTitlePath(Service::FS::MediaType::SDMC, data_id + 0xe00000000) + | ||||||
|                "content/"; |                "content/"; | ||||||
|         break; |         break; | ||||||
|     case GameListOpenTarget::TEXTURE_DUMP: |     } | ||||||
|  |     case GameListOpenTarget::TEXTURE_DUMP: { | ||||||
|         open_target = "Dumped Textures"; |         open_target = "Dumped Textures"; | ||||||
|         path = fmt::format("{}textures/{:016X}/", |         path = fmt::format("{}textures/{:016X}/", | ||||||
|                            FileUtil::GetUserPath(FileUtil::UserPath::DumpDir), data_id); |                            FileUtil::GetUserPath(FileUtil::UserPath::DumpDir), data_id); | ||||||
|         break; |         break; | ||||||
|     case GameListOpenTarget::TEXTURE_LOAD: |     } | ||||||
|  |     case GameListOpenTarget::TEXTURE_LOAD: { | ||||||
|         open_target = "Custom Textures"; |         open_target = "Custom Textures"; | ||||||
|         path = fmt::format("{}textures/{:016X}/", |         path = fmt::format("{}textures/{:016X}/", | ||||||
|                            FileUtil::GetUserPath(FileUtil::UserPath::LoadDir), data_id); |                            FileUtil::GetUserPath(FileUtil::UserPath::LoadDir), data_id); | ||||||
|         break; |         break; | ||||||
|     case GameListOpenTarget::MODS: |     } | ||||||
|  |     case GameListOpenTarget::MODS: { | ||||||
|         open_target = "Mods"; |         open_target = "Mods"; | ||||||
|         path = fmt::format("{}mods/{:016X}/", FileUtil::GetUserPath(FileUtil::UserPath::LoadDir), |         path = fmt::format("{}mods/{:016X}/", FileUtil::GetUserPath(FileUtil::UserPath::LoadDir), | ||||||
|                            data_id); |                            data_id); | ||||||
|         break; |         break; | ||||||
|  |     } | ||||||
|  |     case GameListOpenTarget::DLC_DATA: { | ||||||
|  |         open_target = "DLC Data"; | ||||||
|  |         path = fmt::format("{}Nintendo 3DS/00000000000000000000000000000000/" | ||||||
|  |                            "00000000000000000000000000000000/title/0004008c/{:08x}/content/", | ||||||
|  |                            FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir), data_id); | ||||||
|  |         break; | ||||||
|  |     } | ||||||
|  |     case GameListOpenTarget::SHADER_CACHE: { | ||||||
|  |         open_target = "Shader Cache"; | ||||||
|  |         path = FileUtil::GetUserPath(FileUtil::UserPath::ShaderDir); | ||||||
|  |         break; | ||||||
|  |     } | ||||||
|     default: |     default: | ||||||
|         LOG_ERROR(Frontend, "Unexpected target {}", static_cast<int>(target)); |         LOG_ERROR(Frontend, "Unexpected target {}", static_cast<int>(target)); | ||||||
|         return; |         return; | ||||||
|  | @ -1529,6 +1555,19 @@ void GMainWindow::OnGameListShowList(bool show) { | ||||||
|     game_list_placeholder->setVisible(!show); |     game_list_placeholder->setVisible(!show); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | void GMainWindow::OnGameListOpenPerGameProperties(const QString& file) { | ||||||
|  |     const auto loader = Loader::GetLoader(file.toStdString()); | ||||||
|  | 
 | ||||||
|  |     u64 title_id{}; | ||||||
|  |     if (!loader || loader->ReadProgramId(title_id) != Loader::ResultStatus::Success) { | ||||||
|  |         QMessageBox::information(this, tr("Properties"), | ||||||
|  |                                  tr("The game properties could not be loaded.")); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     OpenPerGameConfiguration(title_id, file); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void GMainWindow::OnMenuLoadFile() { | void GMainWindow::OnMenuLoadFile() { | ||||||
|     const QString extensions = QStringLiteral("*.").append( |     const QString extensions = QStringLiteral("*.").append( | ||||||
|         GameList::supported_file_extensions.join(QStringLiteral(" *."))); |         GameList::supported_file_extensions.join(QStringLiteral(" *."))); | ||||||
|  | @ -1654,6 +1693,7 @@ void GMainWindow::OnStartGame() { | ||||||
|     ui->action_Stop->setEnabled(true); |     ui->action_Stop->setEnabled(true); | ||||||
|     ui->action_Restart->setEnabled(true); |     ui->action_Restart->setEnabled(true); | ||||||
|     ui->action_Cheats->setEnabled(true); |     ui->action_Cheats->setEnabled(true); | ||||||
|  |     ui->action_Configure_Current_Game->setEnabled(true); | ||||||
|     ui->action_Load_Amiibo->setEnabled(true); |     ui->action_Load_Amiibo->setEnabled(true); | ||||||
|     ui->action_Report_Compatibility->setEnabled(true); |     ui->action_Report_Compatibility->setEnabled(true); | ||||||
|     ui->action_Capture_Screenshot->setEnabled(true); |     ui->action_Capture_Screenshot->setEnabled(true); | ||||||
|  | @ -1676,6 +1716,7 @@ void GMainWindow::OnPauseGame() { | ||||||
| 
 | 
 | ||||||
| void GMainWindow::OnStopGame() { | void GMainWindow::OnStopGame() { | ||||||
|     ShutdownGame(); |     ShutdownGame(); | ||||||
|  |     Settings::RestoreGlobalState(false); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void GMainWindow::OnLoadComplete() { | void GMainWindow::OnLoadComplete() { | ||||||
|  | @ -1769,7 +1810,7 @@ void GMainWindow::UpdateSecondaryWindowVisibility() { | ||||||
|     if (!emulation_running) { |     if (!emulation_running) { | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|     if (Settings::values.layout_option == Settings::LayoutOption::SeparateWindows) { |     if (Settings::values.layout_option.GetValue() == Settings::LayoutOption::SeparateWindows) { | ||||||
|         secondary_window->RestoreGeometry(); |         secondary_window->RestoreGeometry(); | ||||||
|         secondary_window->show(); |         secondary_window->show(); | ||||||
|     } else { |     } else { | ||||||
|  | @ -1800,7 +1841,7 @@ void GMainWindow::ChangeScreenLayout() { | ||||||
| 
 | 
 | ||||||
| void GMainWindow::ToggleScreenLayout() { | void GMainWindow::ToggleScreenLayout() { | ||||||
|     const Settings::LayoutOption new_layout = []() { |     const Settings::LayoutOption new_layout = []() { | ||||||
|         switch (Settings::values.layout_option) { |         switch (Settings::values.layout_option.GetValue()) { | ||||||
|         case Settings::LayoutOption::Default: |         case Settings::LayoutOption::Default: | ||||||
|             return Settings::LayoutOption::SingleScreen; |             return Settings::LayoutOption::SingleScreen; | ||||||
|         case Settings::LayoutOption::SingleScreen: |         case Settings::LayoutOption::SingleScreen: | ||||||
|  | @ -1812,7 +1853,8 @@ void GMainWindow::ToggleScreenLayout() { | ||||||
|         case Settings::LayoutOption::SeparateWindows: |         case Settings::LayoutOption::SeparateWindows: | ||||||
|             return Settings::LayoutOption::Default; |             return Settings::LayoutOption::Default; | ||||||
|         default: |         default: | ||||||
|             LOG_ERROR(Frontend, "Unknown layout option {}", Settings::values.layout_option); |             LOG_ERROR(Frontend, "Unknown layout option {}", | ||||||
|  |                       Settings::values.layout_option.GetValue()); | ||||||
|             return Settings::LayoutOption::Default; |             return Settings::LayoutOption::Default; | ||||||
|         } |         } | ||||||
|     }(); |     }(); | ||||||
|  | @ -1864,6 +1906,7 @@ void GMainWindow::OnLoadState() { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void GMainWindow::OnConfigure() { | void GMainWindow::OnConfigure() { | ||||||
|  |     Settings::SetConfiguringGlobal(true); | ||||||
|     ConfigureDialog configureDialog(this, hotkey_registry, |     ConfigureDialog configureDialog(this, hotkey_registry, | ||||||
|                                     !multiplayer_state->IsHostingPublicRoom()); |                                     !multiplayer_state->IsHostingPublicRoom()); | ||||||
|     connect(&configureDialog, &ConfigureDialog::LanguageChanged, this, |     connect(&configureDialog, &ConfigureDialog::LanguageChanged, this, | ||||||
|  | @ -1872,15 +1915,15 @@ void GMainWindow::OnConfigure() { | ||||||
|     const int old_input_profile_index = Settings::values.current_input_profile_index; |     const int old_input_profile_index = Settings::values.current_input_profile_index; | ||||||
|     const auto old_input_profiles = Settings::values.input_profiles; |     const auto old_input_profiles = Settings::values.input_profiles; | ||||||
|     const auto old_touch_from_button_maps = Settings::values.touch_from_button_maps; |     const auto old_touch_from_button_maps = Settings::values.touch_from_button_maps; | ||||||
|     const bool old_discord_presence = UISettings::values.enable_discord_presence; |     const bool old_discord_presence = UISettings::values.enable_discord_presence.GetValue(); | ||||||
|     auto result = configureDialog.exec(); |     auto result = configureDialog.exec(); | ||||||
|     if (result == QDialog::Accepted) { |     if (result == QDialog::Accepted) { | ||||||
|         configureDialog.ApplyConfiguration(); |         configureDialog.ApplyConfiguration(); | ||||||
|         InitializeHotkeys(); |         InitializeHotkeys(); | ||||||
|         if (UISettings::values.theme != old_theme) |         if (UISettings::values.theme != old_theme) | ||||||
|             UpdateUITheme(); |             UpdateUITheme(); | ||||||
|         if (UISettings::values.enable_discord_presence != old_discord_presence) |         if (UISettings::values.enable_discord_presence.GetValue() != old_discord_presence) | ||||||
|             SetDiscordEnabled(UISettings::values.enable_discord_presence); |             SetDiscordEnabled(UISettings::values.enable_discord_presence.GetValue()); | ||||||
|         if (!multiplayer_state->IsHostingPublicRoom()) |         if (!multiplayer_state->IsHostingPublicRoom()) | ||||||
|             multiplayer_state->UpdateCredentials(); |             multiplayer_state->UpdateCredentials(); | ||||||
|         emit UpdateThemedIcons(); |         emit UpdateThemedIcons(); | ||||||
|  | @ -2057,24 +2100,26 @@ void GMainWindow::OnSaveMovie() { | ||||||
| 
 | 
 | ||||||
| void GMainWindow::OnCaptureScreenshot() { | void GMainWindow::OnCaptureScreenshot() { | ||||||
|     OnPauseGame(); |     OnPauseGame(); | ||||||
|     QString path = UISettings::values.screenshot_path; |     std::string path = UISettings::values.screenshot_path.GetValue(); | ||||||
|     if (!FileUtil::IsDirectory(path.toStdString())) { |     if (!FileUtil::IsDirectory(path)) { | ||||||
|         if (!FileUtil::CreateFullPath(path.toStdString())) { |         if (!FileUtil::CreateFullPath(path)) { | ||||||
|             QMessageBox::information(this, tr("Invalid Screenshot Directory"), |             QMessageBox::information(this, tr("Invalid Screenshot Directory"), | ||||||
|                                      tr("Cannot create specified screenshot directory. Screenshot " |                                      tr("Cannot create specified screenshot directory. Screenshot " | ||||||
|                                         "path is set back to its default value.")); |                                         "path is set back to its default value.")); | ||||||
|             path = QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::UserDir)); |             path = FileUtil::GetUserPath(FileUtil::UserPath::UserDir); | ||||||
|             path.append(QStringLiteral("screenshots/")); |             path.append("screenshots/"); | ||||||
|             UISettings::values.screenshot_path = path; |             UISettings::values.screenshot_path = path; | ||||||
|         }; |         }; | ||||||
|     } |     } | ||||||
|     const QString filename = game_title.remove(QRegularExpression(QStringLiteral("[\\/:?\"<>|]"))); |     const std::string filename = | ||||||
|     const QString timestamp = |         game_title.remove(QRegularExpression(QStringLiteral("[\\/:?\"<>|]"))).toStdString(); | ||||||
|         QDateTime::currentDateTime().toString(QStringLiteral("dd.MM.yy_hh.mm.ss.z")); |     const std::string timestamp = | ||||||
|     path.append(QStringLiteral("/%1_%2.png").arg(filename, timestamp)); |         QDateTime::currentDateTime().toString(QStringLiteral("dd.MM.yy_hh.mm.ss.z")).toStdString(); | ||||||
|  |     path.append(fmt::format("/{}_{}.png", filename, timestamp)); | ||||||
| 
 | 
 | ||||||
|     auto* const screenshot_window = secondary_window->HasFocus() ? secondary_window : render_window; |     auto* const screenshot_window = secondary_window->HasFocus() ? secondary_window : render_window; | ||||||
|     screenshot_window->CaptureScreenshot(UISettings::values.screenshot_resolution_factor, path); |     screenshot_window->CaptureScreenshot(UISettings::values.screenshot_resolution_factor.GetValue(), | ||||||
|  |                                          QString::fromStdString(path)); | ||||||
|     OnStartGame(); |     OnStartGame(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -2166,22 +2211,12 @@ void GMainWindow::UpdateStatusBar() { | ||||||
| 
 | 
 | ||||||
|     auto results = Core::System::GetInstance().GetAndResetPerfStats(); |     auto results = Core::System::GetInstance().GetAndResetPerfStats(); | ||||||
| 
 | 
 | ||||||
|     if (Settings::values.use_frame_limit_alternate) { |     if (Settings::values.frame_limit.GetValue() == 0) { | ||||||
|         if (Settings::values.frame_limit_alternate == 0) { |  | ||||||
|             emu_speed_label->setText( |  | ||||||
|                 tr("Speed: %1%").arg(results.emulation_speed * 100.0, 0, 'f', 0)); |  | ||||||
| 
 |  | ||||||
|         } else { |  | ||||||
|             emu_speed_label->setText(tr("Speed: %1% / %2%") |  | ||||||
|                                          .arg(results.emulation_speed * 100.0, 0, 'f', 0) |  | ||||||
|                                          .arg(Settings::values.frame_limit_alternate)); |  | ||||||
|         } |  | ||||||
|     } else if (Settings::values.frame_limit == 0) { |  | ||||||
|         emu_speed_label->setText(tr("Speed: %1%").arg(results.emulation_speed * 100.0, 0, 'f', 0)); |         emu_speed_label->setText(tr("Speed: %1%").arg(results.emulation_speed * 100.0, 0, 'f', 0)); | ||||||
|     } else { |     } else { | ||||||
|         emu_speed_label->setText(tr("Speed: %1% / %2%") |         emu_speed_label->setText(tr("Speed: %1% / %2%") | ||||||
|                                      .arg(results.emulation_speed * 100.0, 0, 'f', 0) |                                      .arg(results.emulation_speed * 100.0, 0, 'f', 0) | ||||||
|                                      .arg(Settings::values.frame_limit)); |                                      .arg(Settings::values.frame_limit.GetValue())); | ||||||
|     } |     } | ||||||
|     game_fps_label->setText(tr("Game: %1 FPS").arg(results.game_fps, 0, 'f', 0)); |     game_fps_label->setText(tr("Game: %1 FPS").arg(results.game_fps, 0, 'f', 0)); | ||||||
|     emu_frametime_label->setText(tr("Frame: %1 ms").arg(results.frametime * 1000.0, 0, 'f', 2)); |     emu_frametime_label->setText(tr("Frame: %1 ms").arg(results.frametime * 1000.0, 0, 'f', 2)); | ||||||
|  | @ -2192,7 +2227,7 @@ void GMainWindow::UpdateStatusBar() { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void GMainWindow::HideMouseCursor() { | void GMainWindow::HideMouseCursor() { | ||||||
|     if (emu_thread == nullptr || UISettings::values.hide_mouse == false) { |     if (emu_thread == nullptr || !UISettings::values.hide_mouse.GetValue()) { | ||||||
|         mouse_hide_timer.stop(); |         mouse_hide_timer.stop(); | ||||||
|         ShowMouseCursor(); |         ShowMouseCursor(); | ||||||
|         return; |         return; | ||||||
|  | @ -2455,6 +2490,35 @@ void GMainWindow::OnLanguageChanged(const QString& locale) { | ||||||
|         ui->action_Start->setText(tr("Continue")); |         ui->action_Start->setText(tr("Continue")); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void GMainWindow::OnConfigurePerGame() { | ||||||
|  |     u64 title_id{}; | ||||||
|  |     Core::System::GetInstance().GetAppLoader().ReadProgramId(title_id); | ||||||
|  |     OpenPerGameConfiguration(title_id, game_path); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void GMainWindow::OpenPerGameConfiguration(u64 title_id, const QString& file_name) { | ||||||
|  |     Core::System& system = Core::System::GetInstance(); | ||||||
|  | 
 | ||||||
|  |     Settings::SetConfiguringGlobal(false); | ||||||
|  |     ConfigurePerGame dialog(this, title_id, file_name, system); | ||||||
|  |     const auto result = dialog.exec(); | ||||||
|  | 
 | ||||||
|  |     if (result != QDialog::Accepted) { | ||||||
|  |         Settings::RestoreGlobalState(system.IsPoweredOn()); | ||||||
|  |         return; | ||||||
|  |     } else if (result == QDialog::Accepted) { | ||||||
|  |         dialog.ApplyConfiguration(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // Do not cause the global config to write local settings into the config file
 | ||||||
|  |     const bool is_powered_on = system.IsPoweredOn(); | ||||||
|  |     Settings::RestoreGlobalState(system.IsPoweredOn()); | ||||||
|  | 
 | ||||||
|  |     if (!is_powered_on) { | ||||||
|  |         config->Save(); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void GMainWindow::OnMoviePlaybackCompleted() { | void GMainWindow::OnMoviePlaybackCompleted() { | ||||||
|     OnPauseGame(); |     OnPauseGame(); | ||||||
|     QMessageBox::information(this, tr("Playback Completed"), tr("Movie playback completed.")); |     QMessageBox::information(this, tr("Playback Completed"), tr("Movie playback completed.")); | ||||||
|  | @ -2489,18 +2553,19 @@ void GMainWindow::UpdateUISettings() { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void GMainWindow::SyncMenuUISettings() { | void GMainWindow::SyncMenuUISettings() { | ||||||
|     ui->action_Screen_Layout_Default->setChecked(Settings::values.layout_option == |     ui->action_Screen_Layout_Default->setChecked(Settings::values.layout_option.GetValue() == | ||||||
|                                                  Settings::LayoutOption::Default); |                                                  Settings::LayoutOption::Default); | ||||||
|     ui->action_Screen_Layout_Single_Screen->setChecked(Settings::values.layout_option == |     ui->action_Screen_Layout_Single_Screen->setChecked(Settings::values.layout_option.GetValue() == | ||||||
|                                                        Settings::LayoutOption::SingleScreen); |                                                        Settings::LayoutOption::SingleScreen); | ||||||
|     ui->action_Screen_Layout_Large_Screen->setChecked(Settings::values.layout_option == |     ui->action_Screen_Layout_Large_Screen->setChecked(Settings::values.layout_option.GetValue() == | ||||||
|                                                       Settings::LayoutOption::LargeScreen); |                                                       Settings::LayoutOption::LargeScreen); | ||||||
|     ui->action_Screen_Layout_Side_by_Side->setChecked(Settings::values.layout_option == |     ui->action_Screen_Layout_Side_by_Side->setChecked(Settings::values.layout_option.GetValue() == | ||||||
|                                                       Settings::LayoutOption::SideScreen); |                                                       Settings::LayoutOption::SideScreen); | ||||||
|     ui->action_Screen_Layout_Separate_Windows->setChecked(Settings::values.layout_option == |     ui->action_Screen_Layout_Separate_Windows->setChecked( | ||||||
|                                                           Settings::LayoutOption::SeparateWindows); |         Settings::values.layout_option.GetValue() == Settings::LayoutOption::SeparateWindows); | ||||||
|     ui->action_Screen_Layout_Swap_Screens->setChecked(Settings::values.swap_screen); |     ui->action_Screen_Layout_Swap_Screens->setChecked(Settings::values.swap_screen.GetValue()); | ||||||
|     ui->action_Screen_Layout_Upright_Screens->setChecked(Settings::values.upright_screen); |     ui->action_Screen_Layout_Upright_Screens->setChecked( | ||||||
|  |         Settings::values.upright_screen.GetValue()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void GMainWindow::RetranslateStatusBar() { | void GMainWindow::RetranslateStatusBar() { | ||||||
|  | @ -2573,11 +2638,13 @@ int main(int argc, char* argv[]) { | ||||||
| 
 | 
 | ||||||
|     // Register frontend applets
 |     // Register frontend applets
 | ||||||
|     Frontend::RegisterDefaultApplets(); |     Frontend::RegisterDefaultApplets(); | ||||||
|     Core::System::GetInstance().RegisterMiiSelector(std::make_shared<QtMiiSelector>(main_window)); | 
 | ||||||
|     Core::System::GetInstance().RegisterSoftwareKeyboard(std::make_shared<QtKeyboard>(main_window)); |     Core::System& system = Core::System::GetInstance(); | ||||||
|  |     system.RegisterMiiSelector(std::make_shared<QtMiiSelector>(main_window)); | ||||||
|  |     system.RegisterSoftwareKeyboard(std::make_shared<QtKeyboard>(main_window)); | ||||||
| 
 | 
 | ||||||
|     // Register Qt image interface
 |     // Register Qt image interface
 | ||||||
|     Core::System::GetInstance().RegisterImageInterface(std::make_shared<QtImageInterface>()); |     system.RegisterImageInterface(std::make_shared<QtImageInterface>()); | ||||||
| 
 | 
 | ||||||
|     main_window.show(); |     main_window.show(); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -183,6 +183,8 @@ private slots: | ||||||
|     void OnGameListOpenDirectory(const QString& directory); |     void OnGameListOpenDirectory(const QString& directory); | ||||||
|     void OnGameListAddDirectory(); |     void OnGameListAddDirectory(); | ||||||
|     void OnGameListShowList(bool show); |     void OnGameListShowList(bool show); | ||||||
|  |     void OnGameListOpenPerGameProperties(const QString& file); | ||||||
|  |     void OnConfigurePerGame(); | ||||||
|     void OnMenuLoadFile(); |     void OnMenuLoadFile(); | ||||||
|     void OnMenuInstallCIA(); |     void OnMenuInstallCIA(); | ||||||
|     void OnUpdateProgress(std::size_t written, std::size_t total); |     void OnUpdateProgress(std::size_t written, std::size_t total); | ||||||
|  | @ -238,6 +240,7 @@ private: | ||||||
|     void InstallCIA(QStringList filepaths); |     void InstallCIA(QStringList filepaths); | ||||||
|     void HideMouseCursor(); |     void HideMouseCursor(); | ||||||
|     void ShowMouseCursor(); |     void ShowMouseCursor(); | ||||||
|  |     void OpenPerGameConfiguration(u64 title_id, const QString& file_name); | ||||||
| 
 | 
 | ||||||
|     std::unique_ptr<Ui::MainWindow> ui; |     std::unique_ptr<Ui::MainWindow> ui; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -45,7 +45,7 @@ | ||||||
|      <x>0</x> |      <x>0</x> | ||||||
|      <y>0</y> |      <y>0</y> | ||||||
|      <width>1081</width> |      <width>1081</width> | ||||||
|      <height>21</height> |      <height>25</height> | ||||||
|     </rect> |     </rect> | ||||||
|    </property> |    </property> | ||||||
|    <widget class="QMenu" name="menu_File"> |    <widget class="QMenu" name="menu_File"> | ||||||
|  | @ -104,6 +104,7 @@ | ||||||
|     <addaction name="action_Report_Compatibility"/> |     <addaction name="action_Report_Compatibility"/> | ||||||
|     <addaction name="separator"/> |     <addaction name="separator"/> | ||||||
|     <addaction name="action_Configure"/> |     <addaction name="action_Configure"/> | ||||||
|  |     <addaction name="action_Configure_Current_Game"/> | ||||||
|     <addaction name="action_Cheats"/> |     <addaction name="action_Cheats"/> | ||||||
|    </widget> |    </widget> | ||||||
|    <widget class="QMenu" name="menu_View"> |    <widget class="QMenu" name="menu_View"> | ||||||
|  | @ -239,20 +240,20 @@ | ||||||
|    </property> |    </property> | ||||||
|   </action> |   </action> | ||||||
|   <action name="action_Save"> |   <action name="action_Save"> | ||||||
|     <property name="enabled"> |    <property name="enabled"> | ||||||
|       <bool>false</bool> |     <bool>false</bool> | ||||||
|     </property> |    </property> | ||||||
|     <property name="text"> |    <property name="text"> | ||||||
|       <string>Save</string> |     <string>Save</string> | ||||||
|     </property> |    </property> | ||||||
|   </action> |   </action> | ||||||
|   <action name="action_Load"> |   <action name="action_Load"> | ||||||
|     <property name="enabled"> |    <property name="enabled"> | ||||||
|       <bool>false</bool> |     <bool>false</bool> | ||||||
|     </property> |    </property> | ||||||
|     <property name="text"> |    <property name="text"> | ||||||
|       <string>Load</string> |     <string>Load</string> | ||||||
|     </property> |    </property> | ||||||
|   </action> |   </action> | ||||||
|   <action name="action_FAQ"> |   <action name="action_FAQ"> | ||||||
|    <property name="text"> |    <property name="text"> | ||||||
|  | @ -541,6 +542,14 @@ | ||||||
|     <string>Open Citra Folder</string> |     <string>Open Citra Folder</string> | ||||||
|    </property> |    </property> | ||||||
|   </action> |   </action> | ||||||
|  |   <action name="action_Configure_Current_Game"> | ||||||
|  |    <property name="enabled"> | ||||||
|  |     <bool>false</bool> | ||||||
|  |    </property> | ||||||
|  |    <property name="text"> | ||||||
|  |     <string>Configure Current Game...</string> | ||||||
|  |    </property> | ||||||
|  |   </action> | ||||||
|  </widget> |  </widget> | ||||||
|  <resources/> |  <resources/> | ||||||
|  <connections/> |  <connections/> | ||||||
|  |  | ||||||
|  | @ -13,7 +13,7 @@ | ||||||
| #include <QString> | #include <QString> | ||||||
| #include <QStringList> | #include <QStringList> | ||||||
| #include <QVector> | #include <QVector> | ||||||
| #include "common/common_types.h" | #include "common/settings.h" | ||||||
| 
 | 
 | ||||||
| namespace UISettings { | namespace UISettings { | ||||||
| 
 | 
 | ||||||
|  | @ -40,13 +40,13 @@ struct GameDir { | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| enum class GameListIconSize { | enum class GameListIconSize : u32 { | ||||||
|     NoIcon,    ///< Do not display icons
 |     NoIcon,    ///< Do not display icons
 | ||||||
|     SmallIcon, ///< Display a small (24x24) icon
 |     SmallIcon, ///< Display a small (24x24) icon
 | ||||||
|     LargeIcon, ///< Display a large (48x48) icon
 |     LargeIcon, ///< Display a large (48x48) icon
 | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| enum class GameListText { | enum class GameListText : s32 { | ||||||
|     NoText = -1,   ///< No text
 |     NoText = -1,   ///< No text
 | ||||||
|     FileName,      ///< Display the file name of the entry
 |     FileName,      ///< Display the file name of the entry
 | ||||||
|     FullPath,      ///< Display the full path of the entry
 |     FullPath,      ///< Display the full path of the entry
 | ||||||
|  | @ -65,40 +65,41 @@ struct Values { | ||||||
|     QByteArray gamelist_header_state; |     QByteArray gamelist_header_state; | ||||||
| 
 | 
 | ||||||
|     QByteArray microprofile_geometry; |     QByteArray microprofile_geometry; | ||||||
|     bool microprofile_visible; |     Settings::Setting<bool> microprofile_visible{false, "microProfileDialogVisible"}; | ||||||
| 
 | 
 | ||||||
|     bool single_window_mode; |     Settings::Setting<bool> single_window_mode{true, "singleWindowMode"}; | ||||||
|     bool fullscreen; |     Settings::Setting<bool> fullscreen{false, "fullscreen"}; | ||||||
|     bool display_titlebar; |     Settings::Setting<bool> display_titlebar{true, "displayTitleBars"}; | ||||||
|     bool show_filter_bar; |     Settings::Setting<bool> show_filter_bar{true, "showFilterBar"}; | ||||||
|     bool show_status_bar; |     Settings::Setting<bool> show_status_bar{true, "showStatusBar"}; | ||||||
| 
 | 
 | ||||||
|     bool confirm_before_closing; |     Settings::Setting<bool> confirm_before_closing{true, "confirmClose"}; | ||||||
|     bool first_start; |     Settings::Setting<bool> first_start{true, "firstStart"}; | ||||||
|     bool pause_when_in_background; |     Settings::Setting<bool> pause_when_in_background{false, "pauseWhenInBackground"}; | ||||||
|     bool hide_mouse; |     Settings::Setting<bool> hide_mouse{false, "hideInactiveMouse"}; | ||||||
| 
 | 
 | ||||||
|     bool updater_found; |     bool updater_found; | ||||||
|     bool update_on_close; |     Settings::Setting<bool> update_on_close{false, "update_on_close"}; | ||||||
|     bool check_for_update_on_start; |     Settings::Setting<bool> check_for_update_on_start{true, "check_for_update_on_start"}; | ||||||
| 
 | 
 | ||||||
|     // Discord RPC
 |     // Discord RPC
 | ||||||
|     bool enable_discord_presence; |     Settings::Setting<bool> enable_discord_presence{true, "enable_discord_presence"}; | ||||||
| 
 | 
 | ||||||
|     // Game List
 |     // Game List
 | ||||||
|     GameListIconSize game_list_icon_size; |     Settings::Setting<GameListIconSize> game_list_icon_size{GameListIconSize::LargeIcon, | ||||||
|     GameListText game_list_row_1; |                                                             "iconSize"}; | ||||||
|     GameListText game_list_row_2; |     Settings::Setting<GameListText> game_list_row_1{GameListText::TitleName, "row1"}; | ||||||
|     bool game_list_hide_no_icon; |     Settings::Setting<GameListText> game_list_row_2{GameListText::FileName, "row2"}; | ||||||
|     bool game_list_single_line_mode; |     Settings::Setting<bool> game_list_hide_no_icon{false, "hideNoIcon"}; | ||||||
|  |     Settings::Setting<bool> game_list_single_line_mode{false, "singleLineMode"}; | ||||||
| 
 | 
 | ||||||
|     u16 screenshot_resolution_factor; |     Settings::Setting<u16> screenshot_resolution_factor{0, "screenshot_resolution_factor"}; | ||||||
|  |     Settings::SwitchableSetting<std::string> screenshot_path{"", "screenshotPath"}; | ||||||
| 
 | 
 | ||||||
|     QString roms_path; |     QString roms_path; | ||||||
|     QString symbols_path; |     QString symbols_path; | ||||||
|     QString movie_record_path; |     QString movie_record_path; | ||||||
|     QString movie_playback_path; |     QString movie_playback_path; | ||||||
|     QString screenshot_path; |  | ||||||
|     QString video_dumping_path; |     QString video_dumping_path; | ||||||
|     QString game_dir_deprecated; |     QString game_dir_deprecated; | ||||||
|     bool game_dir_deprecated_deepscan; |     bool game_dir_deprecated_deepscan; | ||||||
|  | @ -111,7 +112,7 @@ struct Values { | ||||||
|     // Shortcut name <Shortcut, context>
 |     // Shortcut name <Shortcut, context>
 | ||||||
|     std::vector<Shortcut> shortcuts; |     std::vector<Shortcut> shortcuts; | ||||||
| 
 | 
 | ||||||
|     uint32_t callout_flags; |     Settings::Setting<u32> callout_flags{0, "calloutFlags"}; | ||||||
| 
 | 
 | ||||||
|     // multiplayer settings
 |     // multiplayer settings
 | ||||||
|     QString nickname; |     QString nickname; | ||||||
|  | @ -127,7 +128,7 @@ struct Values { | ||||||
|     std::pair<std::vector<std::string>, std::vector<std::string>> ban_list; |     std::pair<std::vector<std::string>, std::vector<std::string>> ban_list; | ||||||
| 
 | 
 | ||||||
|     // logging
 |     // logging
 | ||||||
|     bool show_console; |     Settings::Setting<bool> show_console{false, "showConsole"}; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| extern Values values; | extern Values values; | ||||||
|  |  | ||||||
|  | @ -99,6 +99,8 @@ add_library(common STATIC | ||||||
|     scm_rev.cpp |     scm_rev.cpp | ||||||
|     scm_rev.h |     scm_rev.h | ||||||
|     scope_exit.h |     scope_exit.h | ||||||
|  |     settings.cpp | ||||||
|  |     settings.h | ||||||
|     serialization/atomic.h |     serialization/atomic.h | ||||||
|     serialization/boost_discrete_interval.hpp |     serialization/boost_discrete_interval.hpp | ||||||
|     serialization/boost_flat_set.h |     serialization/boost_flat_set.h | ||||||
|  |  | ||||||
|  | @ -5,6 +5,7 @@ | ||||||
| #include <string_view> | #include <string_view> | ||||||
| #include <utility> | #include <utility> | ||||||
| #include "audio_core/dsp_interface.h" | #include "audio_core/dsp_interface.h" | ||||||
|  | #include "common/settings.h" | ||||||
| #include "core/core.h" | #include "core/core.h" | ||||||
| #include "core/gdbstub/gdbstub.h" | #include "core/gdbstub/gdbstub.h" | ||||||
| #include "core/hle/kernel/shared_page.h" | #include "core/hle/kernel/shared_page.h" | ||||||
|  | @ -13,24 +14,24 @@ | ||||||
| #include "core/hle/service/ir/ir_rst.h" | #include "core/hle/service/ir/ir_rst.h" | ||||||
| #include "core/hle/service/ir/ir_user.h" | #include "core/hle/service/ir/ir_user.h" | ||||||
| #include "core/hle/service/mic_u.h" | #include "core/hle/service/mic_u.h" | ||||||
| #include "core/settings.h" |  | ||||||
| #include "video_core/renderer_base.h" | #include "video_core/renderer_base.h" | ||||||
| #include "video_core/video_core.h" | #include "video_core/video_core.h" | ||||||
| 
 | 
 | ||||||
| namespace Settings { | namespace Settings { | ||||||
| 
 | 
 | ||||||
| Values values = {}; | Values values = {}; | ||||||
|  | static bool configuring_global = true; | ||||||
| 
 | 
 | ||||||
| void Apply() { | void Apply() { | ||||||
|     GDBStub::SetServerPort(values.gdbstub_port); |     GDBStub::SetServerPort(values.gdbstub_port.GetValue()); | ||||||
|     GDBStub::ToggleServer(values.use_gdbstub); |     GDBStub::ToggleServer(values.use_gdbstub.GetValue()); | ||||||
| 
 | 
 | ||||||
|     VideoCore::g_hw_renderer_enabled = values.use_hw_renderer; |     VideoCore::g_hw_renderer_enabled = values.use_hw_renderer.GetValue(); | ||||||
|     VideoCore::g_shader_jit_enabled = values.use_shader_jit; |     VideoCore::g_shader_jit_enabled = values.use_shader_jit.GetValue(); | ||||||
|     VideoCore::g_hw_shader_enabled = values.use_hw_shader; |     VideoCore::g_hw_shader_enabled = values.use_hw_shader.GetValue(); | ||||||
|     VideoCore::g_separable_shader_enabled = values.separable_shader; |     VideoCore::g_separable_shader_enabled = values.separable_shader.GetValue(); | ||||||
|     VideoCore::g_hw_shader_accurate_mul = values.shaders_accurate_mul; |     VideoCore::g_hw_shader_accurate_mul = values.shaders_accurate_mul.GetValue(); | ||||||
|     VideoCore::g_use_disk_shader_cache = values.use_disk_shader_cache; |     VideoCore::g_use_disk_shader_cache = values.use_disk_shader_cache.GetValue(); | ||||||
| 
 | 
 | ||||||
| #ifndef ANDROID | #ifndef ANDROID | ||||||
|     if (VideoCore::g_renderer) { |     if (VideoCore::g_renderer) { | ||||||
|  | @ -45,9 +46,9 @@ void Apply() { | ||||||
| 
 | 
 | ||||||
|     auto& system = Core::System::GetInstance(); |     auto& system = Core::System::GetInstance(); | ||||||
|     if (system.IsPoweredOn()) { |     if (system.IsPoweredOn()) { | ||||||
|         system.CoreTiming().UpdateClockSpeed(values.cpu_clock_percentage); |         system.CoreTiming().UpdateClockSpeed(values.cpu_clock_percentage.GetValue()); | ||||||
|         Core::DSP().SetSink(values.sink_id, values.audio_device_id); |         Core::DSP().SetSink(values.sink_id.GetValue(), values.audio_device_id.GetValue()); | ||||||
|         Core::DSP().EnableStretching(values.enable_audio_stretching); |         Core::DSP().EnableStretching(values.enable_audio_stretching.GetValue()); | ||||||
| 
 | 
 | ||||||
|         auto hid = Service::HID::GetModule(system); |         auto hid = Service::HID::GetModule(system); | ||||||
|         if (hid) { |         if (hid) { | ||||||
|  | @ -76,39 +77,47 @@ void LogSettings() { | ||||||
|         LOG_INFO(Config, "{}: {}", name, value); |         LOG_INFO(Config, "{}: {}", name, value); | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|  |     const auto to_string = [](AudioEmulation emulation) -> std::string_view { | ||||||
|  |         switch (emulation) { | ||||||
|  |         case AudioEmulation::HLE: | ||||||
|  |             return "HLE"; | ||||||
|  |         case AudioEmulation::LLE: | ||||||
|  |             return "LLE"; | ||||||
|  |         case AudioEmulation::LLEMultithreaded: | ||||||
|  |             return "LLE Multithreaded"; | ||||||
|  |         } | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|     LOG_INFO(Config, "Citra Configuration:"); |     LOG_INFO(Config, "Citra Configuration:"); | ||||||
|     log_setting("Core_UseCpuJit", values.use_cpu_jit); |     log_setting("Core_UseCpuJit", values.use_cpu_jit.GetValue()); | ||||||
|     log_setting("Core_CPUClockPercentage", values.cpu_clock_percentage); |     log_setting("Core_CPUClockPercentage", values.cpu_clock_percentage.GetValue()); | ||||||
|     log_setting("Renderer_UseGLES", values.use_gles); |     log_setting("Renderer_UseGLES", values.use_gles.GetValue()); | ||||||
|     log_setting("Renderer_UseHwRenderer", values.use_hw_renderer); |     log_setting("Renderer_UseHwRenderer", values.use_hw_renderer.GetValue()); | ||||||
|     log_setting("Renderer_UseHwShader", values.use_hw_shader); |     log_setting("Renderer_UseHwShader", values.use_hw_shader.GetValue()); | ||||||
|     log_setting("Renderer_SeparableShader", values.separable_shader); |     log_setting("Renderer_SeparableShader", values.separable_shader.GetValue()); | ||||||
|     log_setting("Renderer_ShadersAccurateMul", values.shaders_accurate_mul); |     log_setting("Renderer_ShadersAccurateMul", values.shaders_accurate_mul.GetValue()); | ||||||
|     log_setting("Renderer_UseShaderJit", values.use_shader_jit); |     log_setting("Renderer_UseShaderJit", values.use_shader_jit.GetValue()); | ||||||
|     log_setting("Renderer_UseResolutionFactor", values.resolution_factor); |     log_setting("Renderer_UseResolutionFactor", values.resolution_factor.GetValue()); | ||||||
|     log_setting("Renderer_FrameLimit", values.frame_limit); |     log_setting("Renderer_FrameLimit", values.frame_limit.GetValue()); | ||||||
|     log_setting("Renderer_UseFrameLimitAlternate", values.use_frame_limit_alternate); |     log_setting("Renderer_VSyncNew", values.use_vsync_new.GetValue()); | ||||||
|     log_setting("Renderer_FrameLimitAlternate", values.frame_limit_alternate); |     log_setting("Renderer_PostProcessingShader", values.pp_shader_name.GetValue()); | ||||||
|     log_setting("Renderer_VSyncNew", values.use_vsync_new); |     log_setting("Renderer_FilterMode", values.filter_mode.GetValue()); | ||||||
|     log_setting("Renderer_PostProcessingShader", values.pp_shader_name); |     log_setting("Renderer_TextureFilterName", values.texture_filter_name.GetValue()); | ||||||
|     log_setting("Renderer_FilterMode", values.filter_mode); |     log_setting("Stereoscopy_Render3d", values.render_3d.GetValue()); | ||||||
|     log_setting("Renderer_TextureFilterName", values.texture_filter_name); |     log_setting("Stereoscopy_Factor3d", values.factor_3d.GetValue()); | ||||||
|     log_setting("Stereoscopy_Render3d", values.render_3d); |     log_setting("Stereoscopy_MonoRenderLeftEye", values.mono_render_left_eye.GetValue()); | ||||||
|     log_setting("Stereoscopy_Factor3d", values.factor_3d); |     log_setting("Layout_LayoutOption", values.layout_option.GetValue()); | ||||||
|     log_setting("Stereoscopy_MonoRenderLeftEye", values.mono_render_left_eye); |     log_setting("Layout_SwapScreen", values.swap_screen.GetValue()); | ||||||
|     log_setting("Layout_LayoutOption", values.layout_option); |     log_setting("Layout_UprightScreen", values.upright_screen.GetValue()); | ||||||
|     log_setting("Layout_SwapScreen", values.swap_screen); |     log_setting("Utility_DumpTextures", values.dump_textures.GetValue()); | ||||||
|     log_setting("Layout_UprightScreen", values.upright_screen); |     log_setting("Utility_CustomTextures", values.custom_textures.GetValue()); | ||||||
|     log_setting("Utility_DumpTextures", values.dump_textures); |     log_setting("Utility_UseDiskShaderCache", values.use_disk_shader_cache.GetValue()); | ||||||
|     log_setting("Utility_CustomTextures", values.custom_textures); |     log_setting("Audio_Emulation", to_string(values.audio_emulation.GetValue())); | ||||||
|     log_setting("Utility_UseDiskShaderCache", values.use_disk_shader_cache); |     log_setting("Audio_OutputEngine", values.sink_id.GetValue()); | ||||||
|     log_setting("Audio_EnableDspLle", values.enable_dsp_lle); |     log_setting("Audio_EnableAudioStretching", values.enable_audio_stretching.GetValue()); | ||||||
|     log_setting("Audio_EnableDspLleMultithread", values.enable_dsp_lle_multithread); |     log_setting("Audio_OutputDevice", values.audio_device_id.GetValue()); | ||||||
|     log_setting("Audio_OutputEngine", values.sink_id); |     log_setting("Audio_InputDeviceType", values.mic_input_type.GetValue()); | ||||||
|     log_setting("Audio_EnableAudioStretching", values.enable_audio_stretching); |     log_setting("Audio_InputDevice", values.mic_input_device.GetValue()); | ||||||
|     log_setting("Audio_OutputDevice", values.audio_device_id); |  | ||||||
|     log_setting("Audio_InputDeviceType", values.mic_input_type); |  | ||||||
|     log_setting("Audio_InputDevice", values.mic_input_device); |  | ||||||
|     using namespace Service::CAM; |     using namespace Service::CAM; | ||||||
|     log_setting("Camera_OuterRightName", values.camera_name[OuterRightCamera]); |     log_setting("Camera_OuterRightName", values.camera_name[OuterRightCamera]); | ||||||
|     log_setting("Camera_OuterRightConfig", values.camera_config[OuterRightCamera]); |     log_setting("Camera_OuterRightConfig", values.camera_config[OuterRightCamera]); | ||||||
|  | @ -119,23 +128,68 @@ void LogSettings() { | ||||||
|     log_setting("Camera_OuterLeftName", values.camera_name[OuterLeftCamera]); |     log_setting("Camera_OuterLeftName", values.camera_name[OuterLeftCamera]); | ||||||
|     log_setting("Camera_OuterLeftConfig", values.camera_config[OuterLeftCamera]); |     log_setting("Camera_OuterLeftConfig", values.camera_config[OuterLeftCamera]); | ||||||
|     log_setting("Camera_OuterLeftFlip", values.camera_flip[OuterLeftCamera]); |     log_setting("Camera_OuterLeftFlip", values.camera_flip[OuterLeftCamera]); | ||||||
|     log_setting("DataStorage_UseVirtualSd", values.use_virtual_sd); |     log_setting("DataStorage_UseVirtualSd", values.use_virtual_sd.GetValue()); | ||||||
|     log_setting("DataStorage_UseCustomStorage", values.use_custom_storage); |     log_setting("DataStorage_UseCustomStorage", values.use_custom_storage.GetValue()); | ||||||
|     if (values.use_custom_storage) { |     if (values.use_custom_storage) { | ||||||
|         log_setting("DataStorage_SdmcDir", FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir)); |         log_setting("DataStorage_SdmcDir", FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir)); | ||||||
|         log_setting("DataStorage_NandDir", FileUtil::GetUserPath(FileUtil::UserPath::NANDDir)); |         log_setting("DataStorage_NandDir", FileUtil::GetUserPath(FileUtil::UserPath::NANDDir)); | ||||||
|     } |     } | ||||||
|     log_setting("System_IsNew3ds", values.is_new_3ds); |     log_setting("System_IsNew3ds", values.is_new_3ds.GetValue()); | ||||||
|     log_setting("System_RegionValue", values.region_value); |     log_setting("System_RegionValue", values.region_value.GetValue()); | ||||||
|     log_setting("Debugging_UseGdbstub", values.use_gdbstub); |     log_setting("Debugging_UseGdbstub", values.use_gdbstub.GetValue()); | ||||||
|     log_setting("Debugging_GdbstubPort", values.gdbstub_port); |     log_setting("Debugging_GdbstubPort", values.gdbstub_port.GetValue()); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool IsConfiguringGlobal() { | ||||||
|  |     return configuring_global; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void SetConfiguringGlobal(bool is_global) { | ||||||
|  |     configuring_global = is_global; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| float Volume() { | float Volume() { | ||||||
|     if (values.audio_muted) { |     if (values.audio_muted) { | ||||||
|         return 0.0f; |         return 0.0f; | ||||||
|     } |     } | ||||||
|     return values.volume; |     return values.volume.GetValue(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void RestoreGlobalState(bool is_powered_on) { | ||||||
|  |     // If a game is running, DO NOT restore the global settings state
 | ||||||
|  |     if (is_powered_on) { | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // Audio
 | ||||||
|  |     values.audio_emulation.SetGlobal(true); | ||||||
|  |     values.enable_audio_stretching.SetGlobal(true); | ||||||
|  |     values.volume.SetGlobal(true); | ||||||
|  | 
 | ||||||
|  |     // Core
 | ||||||
|  |     values.cpu_clock_percentage.SetGlobal(true); | ||||||
|  |     values.is_new_3ds.SetGlobal(true); | ||||||
|  | 
 | ||||||
|  |     // Renderer
 | ||||||
|  |     values.use_hw_renderer.SetGlobal(true); | ||||||
|  |     values.use_hw_shader.SetGlobal(true); | ||||||
|  |     values.separable_shader.SetGlobal(true); | ||||||
|  |     values.use_disk_shader_cache.SetGlobal(true); | ||||||
|  |     values.shaders_accurate_mul.SetGlobal(true); | ||||||
|  |     values.use_vsync_new.SetGlobal(true); | ||||||
|  |     values.resolution_factor.SetGlobal(true); | ||||||
|  |     values.frame_limit.SetGlobal(true); | ||||||
|  |     values.texture_filter_name.SetGlobal(true); | ||||||
|  |     values.layout_option.SetGlobal(true); | ||||||
|  |     values.swap_screen.SetGlobal(true); | ||||||
|  |     values.upright_screen.SetGlobal(true); | ||||||
|  |     values.bg_red.SetGlobal(true); | ||||||
|  |     values.bg_green.SetGlobal(true); | ||||||
|  |     values.bg_blue.SetGlobal(true); | ||||||
|  |     values.render_3d.SetGlobal(true); | ||||||
|  |     values.factor_3d.SetGlobal(true); | ||||||
|  |     values.filter_mode.SetGlobal(true); | ||||||
|  |     values.pp_shader_name.SetGlobal(true); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void LoadProfile(int index) { | void LoadProfile(int index) { | ||||||
							
								
								
									
										538
									
								
								src/common/settings.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										538
									
								
								src/common/settings.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,538 @@ | ||||||
|  | // Copyright 2014 Citra Emulator Project
 | ||||||
|  | // Licensed under GPLv2 or any later version
 | ||||||
|  | // Refer to the license.txt file included.
 | ||||||
|  | 
 | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <algorithm> | ||||||
|  | #include <array> | ||||||
|  | #include <atomic> | ||||||
|  | #include <string> | ||||||
|  | #include <unordered_map> | ||||||
|  | #include <vector> | ||||||
|  | #include "common/common_types.h" | ||||||
|  | #include "core/hle/service/cam/cam_params.h" | ||||||
|  | 
 | ||||||
|  | namespace Settings { | ||||||
|  | 
 | ||||||
|  | enum class InitClock : u32 { | ||||||
|  |     SystemTime = 0, | ||||||
|  |     FixedTime = 1, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | enum class LayoutOption : u32 { | ||||||
|  |     Default, | ||||||
|  |     SingleScreen, | ||||||
|  |     LargeScreen, | ||||||
|  |     SideScreen, | ||||||
|  | #ifndef ANDROID | ||||||
|  |     SeparateWindows, | ||||||
|  | #endif | ||||||
|  |     // Similiar to default, but better for mobile devices in portrait mode. Top screen in clamped to
 | ||||||
|  |     // the top of the frame, and the bottom screen is enlarged to match the top screen.
 | ||||||
|  |     MobilePortrait, | ||||||
|  | 
 | ||||||
|  |     // Similiar to LargeScreen, but better for mobile devices in landscape mode. The screens are
 | ||||||
|  |     // clamped to the top of the frame, and the bottom screen is a bit bigger.
 | ||||||
|  |     MobileLandscape, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | enum class MicInputType : u32 { | ||||||
|  |     None = 0, | ||||||
|  |     Real = 1, | ||||||
|  |     Static = 2, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | enum class StereoRenderOption : u32 { | ||||||
|  |     Off = 0, | ||||||
|  |     SideBySide = 1, | ||||||
|  |     Anaglyph = 2, | ||||||
|  |     Interlaced = 3, | ||||||
|  |     ReverseInterlaced = 4, | ||||||
|  |     CardboardVR = 5 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | enum class AudioEmulation : u32 { HLE = 0, LLE = 1, LLEMultithreaded = 2 }; | ||||||
|  | 
 | ||||||
|  | namespace NativeButton { | ||||||
|  | 
 | ||||||
|  | enum Values { | ||||||
|  |     A, | ||||||
|  |     B, | ||||||
|  |     X, | ||||||
|  |     Y, | ||||||
|  |     Up, | ||||||
|  |     Down, | ||||||
|  |     Left, | ||||||
|  |     Right, | ||||||
|  |     L, | ||||||
|  |     R, | ||||||
|  |     Start, | ||||||
|  |     Select, | ||||||
|  |     Debug, | ||||||
|  |     Gpio14, | ||||||
|  | 
 | ||||||
|  |     ZL, | ||||||
|  |     ZR, | ||||||
|  | 
 | ||||||
|  |     Home, | ||||||
|  | 
 | ||||||
|  |     NumButtons, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | constexpr int BUTTON_HID_BEGIN = A; | ||||||
|  | constexpr int BUTTON_IR_BEGIN = ZL; | ||||||
|  | constexpr int BUTTON_NS_BEGIN = Home; | ||||||
|  | 
 | ||||||
|  | constexpr int BUTTON_HID_END = BUTTON_IR_BEGIN; | ||||||
|  | constexpr int BUTTON_IR_END = BUTTON_NS_BEGIN; | ||||||
|  | constexpr int BUTTON_NS_END = NumButtons; | ||||||
|  | 
 | ||||||
|  | constexpr int NUM_BUTTONS_HID = BUTTON_HID_END - BUTTON_HID_BEGIN; | ||||||
|  | constexpr int NUM_BUTTONS_IR = BUTTON_IR_END - BUTTON_IR_BEGIN; | ||||||
|  | constexpr int NUM_BUTTONS_NS = BUTTON_NS_END - BUTTON_NS_BEGIN; | ||||||
|  | 
 | ||||||
|  | static const std::array<const char*, NumButtons> mapping = {{ | ||||||
|  |     "button_a", | ||||||
|  |     "button_b", | ||||||
|  |     "button_x", | ||||||
|  |     "button_y", | ||||||
|  |     "button_up", | ||||||
|  |     "button_down", | ||||||
|  |     "button_left", | ||||||
|  |     "button_right", | ||||||
|  |     "button_l", | ||||||
|  |     "button_r", | ||||||
|  |     "button_start", | ||||||
|  |     "button_select", | ||||||
|  |     "button_debug", | ||||||
|  |     "button_gpio14", | ||||||
|  |     "button_zl", | ||||||
|  |     "button_zr", | ||||||
|  |     "button_home", | ||||||
|  | }}; | ||||||
|  | 
 | ||||||
|  | } // namespace NativeButton
 | ||||||
|  | 
 | ||||||
|  | namespace NativeAnalog { | ||||||
|  | enum Values { | ||||||
|  |     CirclePad, | ||||||
|  |     CStick, | ||||||
|  |     NumAnalogs, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | constexpr std::array<const char*, NumAnalogs> mapping = {{ | ||||||
|  |     "circle_pad", | ||||||
|  |     "c_stick", | ||||||
|  | }}; | ||||||
|  | } // namespace NativeAnalog
 | ||||||
|  | 
 | ||||||
|  | /** The Setting class is a simple resource manager. It defines a label and default value alongside
 | ||||||
|  |  * the actual value of the setting for simpler and less-error prone use with frontend | ||||||
|  |  * configurations. Specifying a default value and label is required. A minimum and maximum range can | ||||||
|  |  * be specified for sanitization. | ||||||
|  |  */ | ||||||
|  | template <typename Type, bool ranged = false> | ||||||
|  | class Setting { | ||||||
|  | protected: | ||||||
|  |     Setting() = default; | ||||||
|  | 
 | ||||||
|  |     /**
 | ||||||
|  |      * Only sets the setting to the given initializer, leaving the other members to their default | ||||||
|  |      * initializers. | ||||||
|  |      * | ||||||
|  |      * @param global_val Initial value of the setting | ||||||
|  |      */ | ||||||
|  |     explicit Setting(const Type& val) : value{val} {} | ||||||
|  | 
 | ||||||
|  | public: | ||||||
|  |     /**
 | ||||||
|  |      * Sets a default value, label, and setting value. | ||||||
|  |      * | ||||||
|  |      * @param default_val Intial value of the setting, and default value of the setting | ||||||
|  |      * @param name Label for the setting | ||||||
|  |      */ | ||||||
|  |     explicit Setting(const Type& default_val, const std::string& name) requires(!ranged) | ||||||
|  |         : value{default_val}, default_value{default_val}, label{name} {} | ||||||
|  |     virtual ~Setting() = default; | ||||||
|  | 
 | ||||||
|  |     /**
 | ||||||
|  |      * Sets a default value, minimum value, maximum value, and label. | ||||||
|  |      * | ||||||
|  |      * @param default_val Intial value of the setting, and default value of the setting | ||||||
|  |      * @param min_val Sets the minimum allowed value of the setting | ||||||
|  |      * @param max_val Sets the maximum allowed value of the setting | ||||||
|  |      * @param name Label for the setting | ||||||
|  |      */ | ||||||
|  |     explicit Setting(const Type& default_val, const Type& min_val, const Type& max_val, | ||||||
|  |                      const std::string& name) requires(ranged) | ||||||
|  |         : value{default_val}, | ||||||
|  |           default_value{default_val}, maximum{max_val}, minimum{min_val}, label{name} {} | ||||||
|  | 
 | ||||||
|  |     /**
 | ||||||
|  |      *  Returns a reference to the setting's value. | ||||||
|  |      * | ||||||
|  |      * @returns A reference to the setting | ||||||
|  |      */ | ||||||
|  |     [[nodiscard]] virtual const Type& GetValue() const { | ||||||
|  |         return value; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /**
 | ||||||
|  |      * Sets the setting to the given value. | ||||||
|  |      * | ||||||
|  |      * @param val The desired value | ||||||
|  |      */ | ||||||
|  |     virtual void SetValue(const Type& val) { | ||||||
|  |         Type temp{ranged ? std::clamp(val, minimum, maximum) : val}; | ||||||
|  |         std::swap(value, temp); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /**
 | ||||||
|  |      * Returns the value that this setting was created with. | ||||||
|  |      * | ||||||
|  |      * @returns A reference to the default value | ||||||
|  |      */ | ||||||
|  |     [[nodiscard]] const Type& GetDefault() const { | ||||||
|  |         return default_value; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /**
 | ||||||
|  |      * Returns the label this setting was created with. | ||||||
|  |      * | ||||||
|  |      * @returns A reference to the label | ||||||
|  |      */ | ||||||
|  |     [[nodiscard]] const std::string& GetLabel() const { | ||||||
|  |         return label; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /**
 | ||||||
|  |      * Assigns a value to the setting. | ||||||
|  |      * | ||||||
|  |      * @param val The desired setting value | ||||||
|  |      * | ||||||
|  |      * @returns A reference to the setting | ||||||
|  |      */ | ||||||
|  |     virtual const Type& operator=(const Type& val) { | ||||||
|  |         Type temp{ranged ? std::clamp(val, minimum, maximum) : val}; | ||||||
|  |         std::swap(value, temp); | ||||||
|  |         return value; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /**
 | ||||||
|  |      * Returns a reference to the setting. | ||||||
|  |      * | ||||||
|  |      * @returns A reference to the setting | ||||||
|  |      */ | ||||||
|  |     explicit virtual operator const Type&() const { | ||||||
|  |         return value; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | protected: | ||||||
|  |     Type value{};               ///< The setting
 | ||||||
|  |     const Type default_value{}; ///< The default value
 | ||||||
|  |     const Type maximum{};       ///< Maximum allowed value of the setting
 | ||||||
|  |     const Type minimum{};       ///< Minimum allowed value of the setting
 | ||||||
|  |     const std::string label{};  ///< The setting's label
 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * The SwitchableSetting class is a slightly more complex version of the Setting class. This adds a | ||||||
|  |  * custom setting to switch to when a guest application specifically requires it. The effect is that | ||||||
|  |  * other components of the emulator can access the setting's intended value without any need for the | ||||||
|  |  * component to ask whether the custom or global setting is needed at the moment. | ||||||
|  |  * | ||||||
|  |  * By default, the global setting is used. | ||||||
|  |  */ | ||||||
|  | template <typename Type, bool ranged = false> | ||||||
|  | class SwitchableSetting : virtual public Setting<Type, ranged> { | ||||||
|  | public: | ||||||
|  |     /**
 | ||||||
|  |      * Sets a default value, label, and setting value. | ||||||
|  |      * | ||||||
|  |      * @param default_val Intial value of the setting, and default value of the setting | ||||||
|  |      * @param name Label for the setting | ||||||
|  |      */ | ||||||
|  |     explicit SwitchableSetting(const Type& default_val, const std::string& name) requires(!ranged) | ||||||
|  |         : Setting<Type>{default_val, name} {} | ||||||
|  |     virtual ~SwitchableSetting() = default; | ||||||
|  | 
 | ||||||
|  |     /**
 | ||||||
|  |      * Sets a default value, minimum value, maximum value, and label. | ||||||
|  |      * | ||||||
|  |      * @param default_val Intial value of the setting, and default value of the setting | ||||||
|  |      * @param min_val Sets the minimum allowed value of the setting | ||||||
|  |      * @param max_val Sets the maximum allowed value of the setting | ||||||
|  |      * @param name Label for the setting | ||||||
|  |      */ | ||||||
|  |     explicit SwitchableSetting(const Type& default_val, const Type& min_val, const Type& max_val, | ||||||
|  |                                const std::string& name) requires(ranged) | ||||||
|  |         : Setting<Type, true>{default_val, min_val, max_val, name} {} | ||||||
|  | 
 | ||||||
|  |     /**
 | ||||||
|  |      * Tells this setting to represent either the global or custom setting when other member | ||||||
|  |      * functions are used. | ||||||
|  |      * | ||||||
|  |      * @param to_global Whether to use the global or custom setting. | ||||||
|  |      */ | ||||||
|  |     void SetGlobal(bool to_global) { | ||||||
|  |         use_global = to_global; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /**
 | ||||||
|  |      * Returns whether this setting is using the global setting or not. | ||||||
|  |      * | ||||||
|  |      * @returns The global state | ||||||
|  |      */ | ||||||
|  |     [[nodiscard]] bool UsingGlobal() const { | ||||||
|  |         return use_global; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /**
 | ||||||
|  |      * Returns either the global or custom setting depending on the values of this setting's global | ||||||
|  |      * state or if the global value was specifically requested. | ||||||
|  |      * | ||||||
|  |      * @param need_global Request global value regardless of setting's state; defaults to false | ||||||
|  |      * | ||||||
|  |      * @returns The required value of the setting | ||||||
|  |      */ | ||||||
|  |     [[nodiscard]] virtual const Type& GetValue() const override { | ||||||
|  |         if (use_global) { | ||||||
|  |             return this->value; | ||||||
|  |         } | ||||||
|  |         return custom; | ||||||
|  |     } | ||||||
|  |     [[nodiscard]] virtual const Type& GetValue(bool need_global) const { | ||||||
|  |         if (use_global || need_global) { | ||||||
|  |             return this->value; | ||||||
|  |         } | ||||||
|  |         return custom; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /**
 | ||||||
|  |      * Sets the current setting value depending on the global state. | ||||||
|  |      * | ||||||
|  |      * @param val The new value | ||||||
|  |      */ | ||||||
|  |     void SetValue(const Type& val) override { | ||||||
|  |         Type temp{ranged ? std::clamp(val, this->minimum, this->maximum) : val}; | ||||||
|  |         if (use_global) { | ||||||
|  |             std::swap(this->value, temp); | ||||||
|  |         } else { | ||||||
|  |             std::swap(custom, temp); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /**
 | ||||||
|  |      * Assigns the current setting value depending on the global state. | ||||||
|  |      * | ||||||
|  |      * @param val The new value | ||||||
|  |      * | ||||||
|  |      * @returns A reference to the current setting value | ||||||
|  |      */ | ||||||
|  |     const Type& operator=(const Type& val) override { | ||||||
|  |         Type temp{ranged ? std::clamp(val, this->minimum, this->maximum) : val}; | ||||||
|  |         if (use_global) { | ||||||
|  |             std::swap(this->value, temp); | ||||||
|  |             return this->value; | ||||||
|  |         } | ||||||
|  |         std::swap(custom, temp); | ||||||
|  |         return custom; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /**
 | ||||||
|  |      * Returns the current setting value depending on the global state. | ||||||
|  |      * | ||||||
|  |      * @returns A reference to the current setting value | ||||||
|  |      */ | ||||||
|  |     virtual explicit operator const Type&() const override { | ||||||
|  |         if (use_global) { | ||||||
|  |             return this->value; | ||||||
|  |         } | ||||||
|  |         return custom; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | protected: | ||||||
|  |     bool use_global{true}; ///< The setting's global state
 | ||||||
|  |     Type custom{};         ///< The custom value of the setting
 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * The InputSetting class allows for getting a reference to either the global or custom members. | ||||||
|  |  * This is required as we cannot easily modify the values of user-defined types within containers | ||||||
|  |  * using the SetValue() member function found in the Setting class. The primary purpose of this | ||||||
|  |  * class is to store an array of 10 PlayerInput structs for both the global and custom setting and | ||||||
|  |  * allows for easily accessing and modifying both settings. | ||||||
|  |  */ | ||||||
|  | template <typename Type> | ||||||
|  | class InputSetting final { | ||||||
|  | public: | ||||||
|  |     InputSetting() = default; | ||||||
|  |     explicit InputSetting(Type val) : Setting<Type>(val) {} | ||||||
|  |     ~InputSetting() = default; | ||||||
|  |     void SetGlobal(bool to_global) { | ||||||
|  |         use_global = to_global; | ||||||
|  |     } | ||||||
|  |     [[nodiscard]] bool UsingGlobal() const { | ||||||
|  |         return use_global; | ||||||
|  |     } | ||||||
|  |     [[nodiscard]] Type& GetValue(bool need_global = false) { | ||||||
|  |         if (use_global || need_global) { | ||||||
|  |             return global; | ||||||
|  |         } | ||||||
|  |         return custom; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |     bool use_global{true}; ///< The setting's global state
 | ||||||
|  |     Type global{};         ///< The setting
 | ||||||
|  |     Type custom{};         ///< The custom setting value
 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct InputProfile { | ||||||
|  |     std::string name; | ||||||
|  |     std::array<std::string, NativeButton::NumButtons> buttons; | ||||||
|  |     std::array<std::string, NativeAnalog::NumAnalogs> analogs; | ||||||
|  |     std::string motion_device; | ||||||
|  |     std::string touch_device; | ||||||
|  |     bool use_touch_from_button; | ||||||
|  |     int touch_from_button_map_index; | ||||||
|  |     std::string udp_input_address; | ||||||
|  |     u16 udp_input_port; | ||||||
|  |     u8 udp_pad_index; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct TouchFromButtonMap { | ||||||
|  |     std::string name; | ||||||
|  |     std::vector<std::string> buttons; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /// A special region value indicating that citra will automatically select a region
 | ||||||
|  | /// value to fit the region lockout info of the game
 | ||||||
|  | static constexpr s32 REGION_VALUE_AUTO_SELECT = -1; | ||||||
|  | 
 | ||||||
|  | struct Values { | ||||||
|  |     // Controls
 | ||||||
|  |     InputProfile current_input_profile;       ///< The current input profile
 | ||||||
|  |     int current_input_profile_index;          ///< The current input profile index
 | ||||||
|  |     std::vector<InputProfile> input_profiles; ///< The list of input profiles
 | ||||||
|  |     std::vector<TouchFromButtonMap> touch_from_button_maps; | ||||||
|  | 
 | ||||||
|  |     // Core
 | ||||||
|  |     Setting<bool> use_cpu_jit{true, "use_cpu_jit"}; | ||||||
|  |     SwitchableSetting<s32, true> cpu_clock_percentage{100, 5, 400, "cpu_clock_percentage"}; | ||||||
|  |     SwitchableSetting<bool> is_new_3ds{true, "is_new_3ds"}; | ||||||
|  | 
 | ||||||
|  |     // Data Storage
 | ||||||
|  |     Setting<bool> use_virtual_sd{true, "use_virtual_sd"}; | ||||||
|  |     Setting<bool> use_custom_storage{false, "use_custom_storage"}; | ||||||
|  | 
 | ||||||
|  |     // System
 | ||||||
|  |     SwitchableSetting<s32> region_value{REGION_VALUE_AUTO_SELECT, "region_value"}; | ||||||
|  |     Setting<InitClock> init_clock{InitClock::SystemTime, "init_clock"}; | ||||||
|  |     Setting<u64> init_time{946681277ULL, "init_time"}; | ||||||
|  |     Setting<s64> init_time_offset{0, "init_time_offset"}; | ||||||
|  | 
 | ||||||
|  |     // Renderer
 | ||||||
|  |     Setting<bool> use_gles{false, "use_gles"}; | ||||||
|  |     SwitchableSetting<bool> use_hw_renderer{true, "use_hw_renderer"}; | ||||||
|  |     SwitchableSetting<bool> use_hw_shader{true, "use_hw_shader"}; | ||||||
|  |     SwitchableSetting<bool> separable_shader{false, "use_separable_shader"}; | ||||||
|  |     SwitchableSetting<bool> use_disk_shader_cache{true, "use_disk_shader_cache"}; | ||||||
|  |     SwitchableSetting<bool> shaders_accurate_mul{true, "shaders_accurate_mul"}; | ||||||
|  |     SwitchableSetting<bool> use_vsync_new{true, "use_vsync_new"}; | ||||||
|  |     Setting<bool> use_shader_jit{true, "use_shader_jit"}; | ||||||
|  |     SwitchableSetting<u16, true> resolution_factor{1, 1, 10, "resolution_factor"}; | ||||||
|  |     SwitchableSetting<u16, true> frame_limit{100, 0, 1000, "frame_limit"}; | ||||||
|  |     SwitchableSetting<std::string> texture_filter_name{"none", "texture_filter_name"}; | ||||||
|  | 
 | ||||||
|  |     SwitchableSetting<LayoutOption> layout_option{LayoutOption::Default, "layout_option"}; | ||||||
|  |     SwitchableSetting<bool> swap_screen{false, "swap_screen"}; | ||||||
|  |     SwitchableSetting<bool> upright_screen{false, "upright_screen"}; | ||||||
|  |     Setting<bool> custom_layout{false, "custom_layout"}; | ||||||
|  |     Setting<u16> custom_top_left{0, "custom_top_left"}; | ||||||
|  |     Setting<u16> custom_top_top{0, "custom_top_top"}; | ||||||
|  |     Setting<u16> custom_top_right{400, "custom_top_right"}; | ||||||
|  |     Setting<u16> custom_top_bottom{240, "custom_top_bottom"}; | ||||||
|  |     Setting<u16> custom_bottom_left{40, "custom_bottom_left"}; | ||||||
|  |     Setting<u16> custom_bottom_top{240, "custom_bottom_top"}; | ||||||
|  |     Setting<u16> custom_bottom_right{360, "custom_bottom_right"}; | ||||||
|  |     Setting<u16> custom_bottom_bottom{480, "custom_bottom_bottom"}; | ||||||
|  | 
 | ||||||
|  |     SwitchableSetting<double> bg_red{0.f, "bg_red"}; | ||||||
|  |     SwitchableSetting<double> bg_green{0.f, "bg_green"}; | ||||||
|  |     SwitchableSetting<double> bg_blue{0.f, "bg_blue"}; | ||||||
|  | 
 | ||||||
|  |     SwitchableSetting<StereoRenderOption> render_3d{StereoRenderOption::Off, "render_3d"}; | ||||||
|  |     SwitchableSetting<u32> factor_3d{0, "factor_3d"}; | ||||||
|  | 
 | ||||||
|  |     Setting<bool> mono_render_left_eye{false, "mono_render_left_eye"}; | ||||||
|  |     Setting<s32> cardboard_screen_size{85, "cardboard_screen_size"}; | ||||||
|  |     Setting<s32> cardboard_x_shift{0, "cardboard_x_shift"}; | ||||||
|  |     Setting<s32> cardboard_y_shift{0, "cardboard_y_shift"}; | ||||||
|  | 
 | ||||||
|  |     SwitchableSetting<bool> filter_mode{true, "filter_mode"}; | ||||||
|  |     SwitchableSetting<std::string> pp_shader_name{"none (builtin)", "pp_shader_name"}; | ||||||
|  | 
 | ||||||
|  |     Setting<bool> dump_textures{false, "dump_textures"}; | ||||||
|  |     Setting<bool> custom_textures{false, "custom_textures"}; | ||||||
|  |     Setting<bool> preload_textures{false, "preload_textures"}; | ||||||
|  | 
 | ||||||
|  |     // Audio
 | ||||||
|  |     bool audio_muted; | ||||||
|  |     SwitchableSetting<AudioEmulation> audio_emulation{AudioEmulation::HLE, "audio_emulation"}; | ||||||
|  |     Setting<std::string> sink_id{"auto", "output_engine"}; | ||||||
|  |     SwitchableSetting<bool> enable_audio_stretching{true, "enable_audio_stretching"}; | ||||||
|  |     Setting<std::string> audio_device_id{"auto", "output_device"}; | ||||||
|  |     SwitchableSetting<float, true> volume{1.f, 0.f, 1.f, "volume"}; | ||||||
|  |     Setting<MicInputType> mic_input_type{MicInputType::None, "mic_input_type"}; | ||||||
|  |     Setting<std::string> mic_input_device{"Default", "mic_input_device"}; | ||||||
|  | 
 | ||||||
|  |     // Camera
 | ||||||
|  |     std::array<std::string, Service::CAM::NumCameras> camera_name; | ||||||
|  |     std::array<std::string, Service::CAM::NumCameras> camera_config; | ||||||
|  |     std::array<int, Service::CAM::NumCameras> camera_flip; | ||||||
|  | 
 | ||||||
|  |     // Debugging
 | ||||||
|  |     bool record_frame_times; | ||||||
|  |     std::unordered_map<std::string, bool> lle_modules; | ||||||
|  |     Setting<bool> use_gdbstub{false, "use_gdbstub"}; | ||||||
|  |     Setting<u16> gdbstub_port{24689, "gdbstub_port"}; | ||||||
|  | 
 | ||||||
|  |     // Miscellaneous
 | ||||||
|  |     Setting<std::string> log_filter{"*:Info", "log_filter"}; | ||||||
|  | 
 | ||||||
|  |     // Video Dumping
 | ||||||
|  |     std::string output_format; | ||||||
|  |     std::string format_options; | ||||||
|  | 
 | ||||||
|  |     std::string video_encoder; | ||||||
|  |     std::string video_encoder_options; | ||||||
|  |     u64 video_bitrate; | ||||||
|  | 
 | ||||||
|  |     std::string audio_encoder; | ||||||
|  |     std::string audio_encoder_options; | ||||||
|  |     u64 audio_bitrate; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | extern Values values; | ||||||
|  | 
 | ||||||
|  | bool IsConfiguringGlobal(); | ||||||
|  | void SetConfiguringGlobal(bool is_global); | ||||||
|  | 
 | ||||||
|  | float Volume(); | ||||||
|  | 
 | ||||||
|  | void Apply(); | ||||||
|  | void LogSettings(); | ||||||
|  | 
 | ||||||
|  | // Restore the global state of all applicable settings in the Values struct
 | ||||||
|  | void RestoreGlobalState(bool is_powered_on); | ||||||
|  | 
 | ||||||
|  | // Input profiles
 | ||||||
|  | void LoadProfile(int index); | ||||||
|  | void SaveProfile(int index); | ||||||
|  | void CreateProfile(std::string name); | ||||||
|  | void DeleteProfile(int index); | ||||||
|  | void RenameCurrentProfile(std::string new_name); | ||||||
|  | 
 | ||||||
|  | } // namespace Settings
 | ||||||
|  | @ -454,8 +454,6 @@ add_library(core STATIC | ||||||
|     rpc/udp_server.h |     rpc/udp_server.h | ||||||
|     savestate.cpp |     savestate.cpp | ||||||
|     savestate.h |     savestate.h | ||||||
|     settings.cpp |  | ||||||
|     settings.h |  | ||||||
|     telemetry_session.cpp |     telemetry_session.cpp | ||||||
|     telemetry_session.h |     telemetry_session.h | ||||||
|     tracer/citrace.h |     tracer/citrace.h | ||||||
|  |  | ||||||
|  | @ -4,9 +4,9 @@ | ||||||
| #if defined(ARCHITECTURE_x86_64) || defined(ARCHITECTURE_arm64) | #if defined(ARCHITECTURE_x86_64) || defined(ARCHITECTURE_arm64) | ||||||
| #include "core/arm/dynarmic/arm_exclusive_monitor.h" | #include "core/arm/dynarmic/arm_exclusive_monitor.h" | ||||||
| #endif | #endif | ||||||
|  | #include "common/settings.h" | ||||||
| #include "core/arm/exclusive_monitor.h" | #include "core/arm/exclusive_monitor.h" | ||||||
| #include "core/memory.h" | #include "core/memory.h" | ||||||
| #include "core/settings.h" |  | ||||||
| 
 | 
 | ||||||
| namespace Core { | namespace Core { | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -6,6 +6,8 @@ | ||||||
| 
 | 
 | ||||||
| #include <atomic> | #include <atomic> | ||||||
| #include <memory> | #include <memory> | ||||||
|  | #include <vector> | ||||||
|  | #include "common/common_types.h" | ||||||
| #include "core/cheats/cheat_base.h" | #include "core/cheats/cheat_base.h" | ||||||
| 
 | 
 | ||||||
| namespace Cheats { | namespace Cheats { | ||||||
|  |  | ||||||
|  | @ -25,6 +25,7 @@ | ||||||
| #ifdef ENABLE_FFMPEG_VIDEO_DUMPER | #ifdef ENABLE_FFMPEG_VIDEO_DUMPER | ||||||
| #include "core/dumping/ffmpeg_backend.h" | #include "core/dumping/ffmpeg_backend.h" | ||||||
| #endif | #endif | ||||||
|  | #include "common/settings.h" | ||||||
| #include "core/custom_tex_cache.h" | #include "core/custom_tex_cache.h" | ||||||
| #include "core/gdbstub/gdbstub.h" | #include "core/gdbstub/gdbstub.h" | ||||||
| #include "core/global.h" | #include "core/global.h" | ||||||
|  | @ -45,7 +46,6 @@ | ||||||
| #include "core/loader/loader.h" | #include "core/loader/loader.h" | ||||||
| #include "core/movie.h" | #include "core/movie.h" | ||||||
| #include "core/rpc/rpc_server.h" | #include "core/rpc/rpc_server.h" | ||||||
| #include "core/settings.h" |  | ||||||
| #include "network/network.h" | #include "network/network.h" | ||||||
| #include "video_core/renderer_base.h" | #include "video_core/renderer_base.h" | ||||||
| #include "video_core/video_core.h" | #include "video_core/video_core.h" | ||||||
|  | @ -365,7 +365,7 @@ System::ResultStatus System::Init(Frontend::EmuWindow& emu_window, | ||||||
| 
 | 
 | ||||||
|     memory = std::make_unique<Memory::MemorySystem>(); |     memory = std::make_unique<Memory::MemorySystem>(); | ||||||
| 
 | 
 | ||||||
|     timing = std::make_unique<Timing>(num_cores, Settings::values.cpu_clock_percentage); |     timing = std::make_unique<Timing>(num_cores, Settings::values.cpu_clock_percentage.GetValue()); | ||||||
| 
 | 
 | ||||||
|     kernel = std::make_unique<Kernel::KernelSystem>( |     kernel = std::make_unique<Kernel::KernelSystem>( | ||||||
|         *memory, *timing, [this] { PrepareReschedule(); }, system_mode, num_cores, n3ds_mode); |         *memory, *timing, [this] { PrepareReschedule(); }, system_mode, num_cores, n3ds_mode); | ||||||
|  | @ -395,17 +395,19 @@ System::ResultStatus System::Init(Frontend::EmuWindow& emu_window, | ||||||
|     kernel->SetCPUs(cpu_cores); |     kernel->SetCPUs(cpu_cores); | ||||||
|     kernel->SetRunningCPU(cpu_cores[0].get()); |     kernel->SetRunningCPU(cpu_cores[0].get()); | ||||||
| 
 | 
 | ||||||
|     if (Settings::values.enable_dsp_lle) { |     const auto audio_emulation = Settings::values.audio_emulation.GetValue(); | ||||||
|         dsp_core = std::make_unique<AudioCore::DspLle>(*memory, |     if (audio_emulation == Settings::AudioEmulation::HLE) { | ||||||
|                                                        Settings::values.enable_dsp_lle_multithread); |  | ||||||
|     } else { |  | ||||||
|         dsp_core = std::make_unique<AudioCore::DspHle>(*memory); |         dsp_core = std::make_unique<AudioCore::DspHle>(*memory); | ||||||
|  |     } else { | ||||||
|  |         const bool multithread = audio_emulation == Settings::AudioEmulation::LLEMultithreaded; | ||||||
|  |         dsp_core = std::make_unique<AudioCore::DspLle>(*memory, multithread); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     memory->SetDSP(*dsp_core); |     memory->SetDSP(*dsp_core); | ||||||
| 
 | 
 | ||||||
|     dsp_core->SetSink(Settings::values.sink_id, Settings::values.audio_device_id); |     dsp_core->SetSink(Settings::values.sink_id.GetValue(), | ||||||
|     dsp_core->EnableStretching(Settings::values.enable_audio_stretching); |                       Settings::values.audio_device_id.GetValue()); | ||||||
|  |     dsp_core->EnableStretching(Settings::values.enable_audio_stretching.GetValue()); | ||||||
| 
 | 
 | ||||||
|     telemetry_session = std::make_unique<Core::TelemetrySession>(); |     telemetry_session = std::make_unique<Core::TelemetrySession>(); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -7,10 +7,10 @@ | ||||||
| #include "common/file_util.h" | #include "common/file_util.h" | ||||||
| #include "common/logging/log.h" | #include "common/logging/log.h" | ||||||
| #include "common/param_package.h" | #include "common/param_package.h" | ||||||
|  | #include "common/settings.h" | ||||||
| #include "common/string_util.h" | #include "common/string_util.h" | ||||||
| #include "core/dumping/ffmpeg_backend.h" | #include "core/dumping/ffmpeg_backend.h" | ||||||
| #include "core/hw/gpu.h" | #include "core/hw/gpu.h" | ||||||
| #include "core/settings.h" |  | ||||||
| #include "video_core/renderer_base.h" | #include "video_core/renderer_base.h" | ||||||
| #include "video_core/video_core.h" | #include "video_core/video_core.h" | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -7,11 +7,11 @@ | ||||||
| #include "common/archives.h" | #include "common/archives.h" | ||||||
| #include "common/file_util.h" | #include "common/file_util.h" | ||||||
| #include "common/logging/log.h" | #include "common/logging/log.h" | ||||||
|  | #include "common/settings.h" | ||||||
| #include "core/file_sys/archive_sdmc.h" | #include "core/file_sys/archive_sdmc.h" | ||||||
| #include "core/file_sys/disk_archive.h" | #include "core/file_sys/disk_archive.h" | ||||||
| #include "core/file_sys/errors.h" | #include "core/file_sys/errors.h" | ||||||
| #include "core/file_sys/path_parser.h" | #include "core/file_sys/path_parser.h" | ||||||
| #include "core/settings.h" |  | ||||||
| 
 | 
 | ||||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||||
| // FileSys namespace
 | // FileSys namespace
 | ||||||
|  |  | ||||||
|  | @ -5,11 +5,11 @@ | ||||||
| #include <memory> | #include <memory> | ||||||
| #include "common/archives.h" | #include "common/archives.h" | ||||||
| #include "common/file_util.h" | #include "common/file_util.h" | ||||||
|  | #include "common/settings.h" | ||||||
| #include "core/file_sys/archive_sdmcwriteonly.h" | #include "core/file_sys/archive_sdmcwriteonly.h" | ||||||
| #include "core/file_sys/directory_backend.h" | #include "core/file_sys/directory_backend.h" | ||||||
| #include "core/file_sys/errors.h" | #include "core/file_sys/errors.h" | ||||||
| #include "core/file_sys/file_backend.h" | #include "core/file_sys/file_backend.h" | ||||||
| #include "core/settings.h" |  | ||||||
| 
 | 
 | ||||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||||
| // FileSys namespace
 | // FileSys namespace
 | ||||||
|  |  | ||||||
|  | @ -4,9 +4,10 @@ | ||||||
| 
 | 
 | ||||||
| #include <cmath> | #include <cmath> | ||||||
| #include <mutex> | #include <mutex> | ||||||
|  | #include "common/settings.h" | ||||||
|  | #include "core/3ds.h" | ||||||
| #include "core/frontend/emu_window.h" | #include "core/frontend/emu_window.h" | ||||||
| #include "core/frontend/input.h" | #include "core/frontend/input.h" | ||||||
| #include "core/settings.h" |  | ||||||
| 
 | 
 | ||||||
| namespace Frontend { | namespace Frontend { | ||||||
| /// We need a global touch state that is shared across the different window instances
 | /// We need a global touch state that is shared across the different window instances
 | ||||||
|  | @ -63,14 +64,14 @@ EmuWindow::~EmuWindow() = default; | ||||||
|  */ |  */ | ||||||
| static bool IsWithinTouchscreen(const Layout::FramebufferLayout& layout, unsigned framebuffer_x, | static bool IsWithinTouchscreen(const Layout::FramebufferLayout& layout, unsigned framebuffer_x, | ||||||
|                                 unsigned framebuffer_y) { |                                 unsigned framebuffer_y) { | ||||||
|     if (Settings::values.render_3d == Settings::StereoRenderOption::SideBySide) { |     if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::SideBySide) { | ||||||
|         return (framebuffer_y >= layout.bottom_screen.top && |         return (framebuffer_y >= layout.bottom_screen.top && | ||||||
|                 framebuffer_y < layout.bottom_screen.bottom && |                 framebuffer_y < layout.bottom_screen.bottom && | ||||||
|                 ((framebuffer_x >= layout.bottom_screen.left / 2 && |                 ((framebuffer_x >= layout.bottom_screen.left / 2 && | ||||||
|                   framebuffer_x < layout.bottom_screen.right / 2) || |                   framebuffer_x < layout.bottom_screen.right / 2) || | ||||||
|                  (framebuffer_x >= (layout.bottom_screen.left / 2) + (layout.width / 2) && |                  (framebuffer_x >= (layout.bottom_screen.left / 2) + (layout.width / 2) && | ||||||
|                   framebuffer_x < (layout.bottom_screen.right / 2) + (layout.width / 2)))); |                   framebuffer_x < (layout.bottom_screen.right / 2) + (layout.width / 2)))); | ||||||
|     } else if (Settings::values.render_3d == Settings::StereoRenderOption::CardboardVR) { |     } else if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::CardboardVR) { | ||||||
|         return (framebuffer_y >= layout.bottom_screen.top && |         return (framebuffer_y >= layout.bottom_screen.top && | ||||||
|                 framebuffer_y < layout.bottom_screen.bottom && |                 framebuffer_y < layout.bottom_screen.bottom && | ||||||
|                 ((framebuffer_x >= layout.bottom_screen.left && |                 ((framebuffer_x >= layout.bottom_screen.left && | ||||||
|  | @ -88,13 +89,13 @@ static bool IsWithinTouchscreen(const Layout::FramebufferLayout& layout, unsigne | ||||||
| 
 | 
 | ||||||
| std::tuple<unsigned, unsigned> EmuWindow::ClipToTouchScreen(unsigned new_x, unsigned new_y) const { | std::tuple<unsigned, unsigned> EmuWindow::ClipToTouchScreen(unsigned new_x, unsigned new_y) const { | ||||||
|     if (new_x >= framebuffer_layout.width / 2) { |     if (new_x >= framebuffer_layout.width / 2) { | ||||||
|         if (Settings::values.render_3d == Settings::StereoRenderOption::SideBySide) |         if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::SideBySide) | ||||||
|             new_x -= framebuffer_layout.width / 2; |             new_x -= framebuffer_layout.width / 2; | ||||||
|         else if (Settings::values.render_3d == Settings::StereoRenderOption::CardboardVR) |         else if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::CardboardVR) | ||||||
|             new_x -= |             new_x -= | ||||||
|                 (framebuffer_layout.width / 2) - (framebuffer_layout.cardboard.user_x_shift * 2); |                 (framebuffer_layout.width / 2) - (framebuffer_layout.cardboard.user_x_shift * 2); | ||||||
|     } |     } | ||||||
|     if (Settings::values.render_3d == Settings::StereoRenderOption::SideBySide) { |     if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::SideBySide) { | ||||||
|         new_x = std::max(new_x, framebuffer_layout.bottom_screen.left / 2); |         new_x = std::max(new_x, framebuffer_layout.bottom_screen.left / 2); | ||||||
|         new_x = std::min(new_x, framebuffer_layout.bottom_screen.right / 2 - 1); |         new_x = std::min(new_x, framebuffer_layout.bottom_screen.right / 2 - 1); | ||||||
|     } else { |     } else { | ||||||
|  | @ -122,14 +123,14 @@ bool EmuWindow::TouchPressed(unsigned framebuffer_x, unsigned framebuffer_y) { | ||||||
|         return false; |         return false; | ||||||
| 
 | 
 | ||||||
|     if (framebuffer_x >= framebuffer_layout.width / 2) { |     if (framebuffer_x >= framebuffer_layout.width / 2) { | ||||||
|         if (Settings::values.render_3d == Settings::StereoRenderOption::SideBySide) |         if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::SideBySide) | ||||||
|             framebuffer_x -= framebuffer_layout.width / 2; |             framebuffer_x -= framebuffer_layout.width / 2; | ||||||
|         else if (Settings::values.render_3d == Settings::StereoRenderOption::CardboardVR) |         else if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::CardboardVR) | ||||||
|             framebuffer_x -= |             framebuffer_x -= | ||||||
|                 (framebuffer_layout.width / 2) - (framebuffer_layout.cardboard.user_x_shift * 2); |                 (framebuffer_layout.width / 2) - (framebuffer_layout.cardboard.user_x_shift * 2); | ||||||
|     } |     } | ||||||
|     std::lock_guard guard(touch_state->mutex); |     std::lock_guard guard(touch_state->mutex); | ||||||
|     if (Settings::values.render_3d == Settings::StereoRenderOption::SideBySide) { |     if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::SideBySide) { | ||||||
|         touch_state->touch_x = |         touch_state->touch_x = | ||||||
|             static_cast<float>(framebuffer_x - framebuffer_layout.bottom_screen.left / 2) / |             static_cast<float>(framebuffer_x - framebuffer_layout.bottom_screen.left / 2) / | ||||||
|             (framebuffer_layout.bottom_screen.right / 2 - |             (framebuffer_layout.bottom_screen.right / 2 - | ||||||
|  | @ -173,55 +174,59 @@ void EmuWindow::UpdateCurrentFramebufferLayout(unsigned width, unsigned height, | ||||||
|                                                bool is_portrait_mode) { |                                                bool is_portrait_mode) { | ||||||
|     Layout::FramebufferLayout layout; |     Layout::FramebufferLayout layout; | ||||||
|     const auto layout_option = Settings::values.layout_option; |     const auto layout_option = Settings::values.layout_option; | ||||||
|     const auto min_size = |     const auto min_size = Layout::GetMinimumSizeFromLayout( | ||||||
|         Layout::GetMinimumSizeFromLayout(layout_option, Settings::values.upright_screen); |         layout_option.GetValue(), Settings::values.upright_screen.GetValue()); | ||||||
| 
 | 
 | ||||||
|     if (Settings::values.custom_layout == true) { |     if (Settings::values.custom_layout.GetValue() == true) { | ||||||
|         layout = Layout::CustomFrameLayout(width, height); |         layout = Layout::CustomFrameLayout(width, height); | ||||||
|     } else { |     } else { | ||||||
|         width = std::max(width, min_size.first); |         width = std::max(width, min_size.first); | ||||||
|         height = std::max(height, min_size.second); |         height = std::max(height, min_size.second); | ||||||
| 
 | 
 | ||||||
|         // If in portrait mode, only the MobilePortrait option really makes sense
 |         // If in portrait mode, only the MobilePortrait option really makes sense
 | ||||||
|         const Settings::LayoutOption layout_option = is_portrait_mode |         const Settings::LayoutOption layout_option = | ||||||
|                                                          ? Settings::LayoutOption::MobilePortrait |             is_portrait_mode ? Settings::LayoutOption::MobilePortrait | ||||||
|                                                          : Settings::values.layout_option; |                              : Settings::values.layout_option.GetValue(); | ||||||
| 
 | 
 | ||||||
|         switch (layout_option) { |         switch (layout_option) { | ||||||
|         case Settings::LayoutOption::SingleScreen: |         case Settings::LayoutOption::SingleScreen: | ||||||
|             layout = Layout::SingleFrameLayout(width, height, Settings::values.swap_screen, |             layout = | ||||||
|                                                Settings::values.upright_screen); |                 Layout::SingleFrameLayout(width, height, Settings::values.swap_screen.GetValue(), | ||||||
|  |                                           Settings::values.upright_screen.GetValue()); | ||||||
|             break; |             break; | ||||||
|         case Settings::LayoutOption::LargeScreen: |         case Settings::LayoutOption::LargeScreen: | ||||||
|             layout = Layout::LargeFrameLayout(width, height, Settings::values.swap_screen, |             layout = | ||||||
|                                               Settings::values.upright_screen); |                 Layout::LargeFrameLayout(width, height, Settings::values.swap_screen.GetValue(), | ||||||
|  |                                          Settings::values.upright_screen.GetValue()); | ||||||
|             break; |             break; | ||||||
|         case Settings::LayoutOption::SideScreen: |         case Settings::LayoutOption::SideScreen: | ||||||
|             layout = Layout::SideFrameLayout(width, height, Settings::values.swap_screen, |             layout = Layout::SideFrameLayout(width, height, Settings::values.swap_screen.GetValue(), | ||||||
|                                              Settings::values.upright_screen); |                                              Settings::values.upright_screen.GetValue()); | ||||||
|             break; |             break; | ||||||
| #ifndef ANDROID | #ifndef ANDROID | ||||||
|         case Settings::LayoutOption::SeparateWindows: |         case Settings::LayoutOption::SeparateWindows: | ||||||
|             layout = Layout::SeparateWindowsLayout(width, height, is_secondary, |             layout = Layout::SeparateWindowsLayout(width, height, is_secondary, | ||||||
|                                                    Settings::values.upright_screen); |                                                    Settings::values.upright_screen.GetValue()); | ||||||
|             break; |             break; | ||||||
| #endif | #endif | ||||||
|         case Settings::LayoutOption::MobilePortrait: |         case Settings::LayoutOption::MobilePortrait: | ||||||
|             layout = Layout::MobilePortraitFrameLayout(width, height, Settings::values.swap_screen); |             layout = Layout::MobilePortraitFrameLayout(width, height, | ||||||
|  |                                                        Settings::values.swap_screen.GetValue()); | ||||||
|             break; |             break; | ||||||
|         case Settings::LayoutOption::MobileLandscape: |         case Settings::LayoutOption::MobileLandscape: | ||||||
|             layout = Layout::MobileLandscapeFrameLayout(width, height, Settings::values.swap_screen, |             layout = Layout::MobileLandscapeFrameLayout( | ||||||
|                                                         2.25f, false); |                 width, height, Settings::values.swap_screen.GetValue(), 2.25f, false); | ||||||
|             break; |             break; | ||||||
|         case Settings::LayoutOption::Default: |         case Settings::LayoutOption::Default: | ||||||
|         default: |         default: | ||||||
|             layout = Layout::DefaultFrameLayout(width, height, Settings::values.swap_screen, |             layout = | ||||||
|                                                 Settings::values.upright_screen); |                 Layout::DefaultFrameLayout(width, height, Settings::values.swap_screen.GetValue(), | ||||||
|  |                                            Settings::values.upright_screen.GetValue()); | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|         UpdateMinimumWindowSize(min_size); |         UpdateMinimumWindowSize(min_size); | ||||||
|     } |     } | ||||||
|     if (Settings::values.render_3d == Settings::StereoRenderOption::CardboardVR) { |     if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::CardboardVR) { | ||||||
|         layout = Layout::GetCardboardSettings(layout); |         layout = Layout::GetCardboardSettings(layout); | ||||||
|     } |     } | ||||||
|     NotifyFramebufferLayoutChanged(layout); |     NotifyFramebufferLayoutChanged(layout); | ||||||
|  |  | ||||||
|  | @ -5,9 +5,9 @@ | ||||||
| #include <cmath> | #include <cmath> | ||||||
| 
 | 
 | ||||||
| #include "common/assert.h" | #include "common/assert.h" | ||||||
|  | #include "common/settings.h" | ||||||
| #include "core/3ds.h" | #include "core/3ds.h" | ||||||
| #include "core/frontend/framebuffer_layout.h" | #include "core/frontend/framebuffer_layout.h" | ||||||
| #include "core/settings.h" |  | ||||||
| 
 | 
 | ||||||
| namespace Layout { | namespace Layout { | ||||||
| 
 | 
 | ||||||
|  | @ -355,12 +355,14 @@ FramebufferLayout CustomFrameLayout(u32 width, u32 height) { | ||||||
| 
 | 
 | ||||||
|     FramebufferLayout res{width, height, true, true, {}, {}, !Settings::values.upright_screen}; |     FramebufferLayout res{width, height, true, true, {}, {}, !Settings::values.upright_screen}; | ||||||
| 
 | 
 | ||||||
|     Common::Rectangle<u32> top_screen{ |     Common::Rectangle<u32> top_screen{Settings::values.custom_top_left.GetValue(), | ||||||
|         Settings::values.custom_top_left, Settings::values.custom_top_top, |                                       Settings::values.custom_top_top.GetValue(), | ||||||
|         Settings::values.custom_top_right, Settings::values.custom_top_bottom}; |                                       Settings::values.custom_top_right.GetValue(), | ||||||
|     Common::Rectangle<u32> bot_screen{ |                                       Settings::values.custom_top_bottom.GetValue()}; | ||||||
|         Settings::values.custom_bottom_left, Settings::values.custom_bottom_top, |     Common::Rectangle<u32> bot_screen{Settings::values.custom_bottom_left.GetValue(), | ||||||
|         Settings::values.custom_bottom_right, Settings::values.custom_bottom_bottom}; |                                       Settings::values.custom_bottom_top.GetValue(), | ||||||
|  |                                       Settings::values.custom_bottom_right.GetValue(), | ||||||
|  |                                       Settings::values.custom_bottom_bottom.GetValue()}; | ||||||
| 
 | 
 | ||||||
|     res.top_screen = top_screen; |     res.top_screen = top_screen; | ||||||
|     res.bottom_screen = bot_screen; |     res.bottom_screen = bot_screen; | ||||||
|  | @ -369,20 +371,21 @@ FramebufferLayout CustomFrameLayout(u32 width, u32 height) { | ||||||
| 
 | 
 | ||||||
| FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale, bool is_secondary) { | FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale, bool is_secondary) { | ||||||
|     FramebufferLayout layout; |     FramebufferLayout layout; | ||||||
|     if (Settings::values.custom_layout == true) { |     if (Settings::values.custom_layout.GetValue() == true) { | ||||||
|         layout = CustomFrameLayout( |         layout = CustomFrameLayout(std::max(Settings::values.custom_top_right.GetValue(), | ||||||
|             std::max(Settings::values.custom_top_right, Settings::values.custom_bottom_right), |                                             Settings::values.custom_bottom_right.GetValue()), | ||||||
|             std::max(Settings::values.custom_top_bottom, Settings::values.custom_bottom_bottom)); |                                    std::max(Settings::values.custom_top_bottom.GetValue(), | ||||||
|  |                                             Settings::values.custom_bottom_bottom.GetValue())); | ||||||
|     } else { |     } else { | ||||||
|         int width, height; |         int width, height; | ||||||
|         switch (Settings::values.layout_option) { |         switch (Settings::values.layout_option.GetValue()) { | ||||||
|         case Settings::LayoutOption::SingleScreen: |         case Settings::LayoutOption::SingleScreen: | ||||||
| #ifndef ANDROID | #ifndef ANDROID | ||||||
|         case Settings::LayoutOption::SeparateWindows: |         case Settings::LayoutOption::SeparateWindows: | ||||||
| #endif | #endif | ||||||
|         { |         { | ||||||
|             const bool swap_screens = is_secondary || Settings::values.swap_screen; |             const bool swap_screens = is_secondary || Settings::values.swap_screen.GetValue(); | ||||||
|             if (Settings::values.upright_screen) { |             if (Settings::values.upright_screen.GetValue()) { | ||||||
|                 if (swap_screens) { |                 if (swap_screens) { | ||||||
|                     width = Core::kScreenBottomHeight * res_scale; |                     width = Core::kScreenBottomHeight * res_scale; | ||||||
|                     height = Core::kScreenBottomWidth * res_scale; |                     height = Core::kScreenBottomWidth * res_scale; | ||||||
|  | @ -399,13 +402,13 @@ FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale, bool is_secondar | ||||||
|                     height = Core::kScreenTopHeight * res_scale; |                     height = Core::kScreenTopHeight * res_scale; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             layout = |             layout = SingleFrameLayout(width, height, swap_screens, | ||||||
|                 SingleFrameLayout(width, height, swap_screens, Settings::values.upright_screen); |                                        Settings::values.upright_screen.GetValue()); | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|         case Settings::LayoutOption::LargeScreen: |         case Settings::LayoutOption::LargeScreen: | ||||||
|             if (Settings::values.upright_screen) { |             if (Settings::values.upright_screen.GetValue()) { | ||||||
|                 if (Settings::values.swap_screen) { |                 if (Settings::values.swap_screen.GetValue()) { | ||||||
|                     width = Core::kScreenBottomHeight * res_scale; |                     width = Core::kScreenBottomHeight * res_scale; | ||||||
|                     height = (Core::kScreenBottomWidth + Core::kScreenTopWidth / 4) * res_scale; |                     height = (Core::kScreenBottomWidth + Core::kScreenTopWidth / 4) * res_scale; | ||||||
|                 } else { |                 } else { | ||||||
|  | @ -413,7 +416,7 @@ FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale, bool is_secondar | ||||||
|                     height = (Core::kScreenTopWidth + Core::kScreenBottomWidth / 4) * res_scale; |                     height = (Core::kScreenTopWidth + Core::kScreenBottomWidth / 4) * res_scale; | ||||||
|                 } |                 } | ||||||
|             } else { |             } else { | ||||||
|                 if (Settings::values.swap_screen) { |                 if (Settings::values.swap_screen.GetValue()) { | ||||||
|                     width = (Core::kScreenBottomWidth + Core::kScreenTopWidth / 4) * res_scale; |                     width = (Core::kScreenBottomWidth + Core::kScreenTopWidth / 4) * res_scale; | ||||||
|                     height = Core::kScreenBottomHeight * res_scale; |                     height = Core::kScreenBottomHeight * res_scale; | ||||||
|                 } else { |                 } else { | ||||||
|  | @ -421,51 +424,52 @@ FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale, bool is_secondar | ||||||
|                     height = Core::kScreenTopHeight * res_scale; |                     height = Core::kScreenTopHeight * res_scale; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             layout = LargeFrameLayout(width, height, Settings::values.swap_screen, |             layout = LargeFrameLayout(width, height, Settings::values.swap_screen.GetValue(), | ||||||
|                                       Settings::values.upright_screen); |                                       Settings::values.upright_screen.GetValue()); | ||||||
|             break; |             break; | ||||||
|         case Settings::LayoutOption::SideScreen: |         case Settings::LayoutOption::SideScreen: | ||||||
|             if (Settings::values.upright_screen) { |             if (Settings::values.upright_screen.GetValue()) { | ||||||
|                 width = Core::kScreenTopHeight * res_scale; |                 width = Core::kScreenTopHeight * res_scale; | ||||||
|                 height = (Core::kScreenTopWidth + Core::kScreenBottomWidth) * res_scale; |                 height = (Core::kScreenTopWidth + Core::kScreenBottomWidth) * res_scale; | ||||||
|             } else { |             } else { | ||||||
|                 width = (Core::kScreenTopWidth + Core::kScreenBottomWidth) * res_scale; |                 width = (Core::kScreenTopWidth + Core::kScreenBottomWidth) * res_scale; | ||||||
|                 height = Core::kScreenTopHeight * res_scale; |                 height = Core::kScreenTopHeight * res_scale; | ||||||
|             } |             } | ||||||
|             layout = SideFrameLayout(width, height, Settings::values.swap_screen, |             layout = SideFrameLayout(width, height, Settings::values.swap_screen.GetValue(), | ||||||
|                                      Settings::values.upright_screen); |                                      Settings::values.upright_screen.GetValue()); | ||||||
|             break; |             break; | ||||||
|         case Settings::LayoutOption::MobilePortrait: |         case Settings::LayoutOption::MobilePortrait: | ||||||
|             width = Core::kScreenTopWidth * res_scale; |             width = Core::kScreenTopWidth * res_scale; | ||||||
|             height = (Core::kScreenTopHeight + Core::kScreenBottomHeight) * res_scale; |             height = (Core::kScreenTopHeight + Core::kScreenBottomHeight) * res_scale; | ||||||
|             layout = MobilePortraitFrameLayout(width, height, Settings::values.swap_screen); |             layout = | ||||||
|  |                 MobilePortraitFrameLayout(width, height, Settings::values.swap_screen.GetValue()); | ||||||
|             break; |             break; | ||||||
|         case Settings::LayoutOption::MobileLandscape: |         case Settings::LayoutOption::MobileLandscape: | ||||||
|             if (Settings::values.swap_screen) { |             if (Settings::values.swap_screen.GetValue()) { | ||||||
|                 width = (Core::kScreenBottomWidth + Core::kScreenTopWidth / 2.25f) * res_scale; |                 width = (Core::kScreenBottomWidth + Core::kScreenTopWidth / 2.25f) * res_scale; | ||||||
|                 height = Core::kScreenBottomHeight * res_scale; |                 height = Core::kScreenBottomHeight * res_scale; | ||||||
|             } else { |             } else { | ||||||
|                 width = (Core::kScreenTopWidth + Core::kScreenBottomWidth / 2.25f) * res_scale; |                 width = (Core::kScreenTopWidth + Core::kScreenBottomWidth / 2.25f) * res_scale; | ||||||
|                 height = Core::kScreenTopHeight * res_scale; |                 height = Core::kScreenTopHeight * res_scale; | ||||||
|             } |             } | ||||||
|             layout = MobileLandscapeFrameLayout(width, height, Settings::values.swap_screen, 2.25f, |             layout = MobileLandscapeFrameLayout( | ||||||
|                                                 false); |                 width, height, Settings::values.swap_screen.GetValue(), 2.25f, false); | ||||||
|             break; |             break; | ||||||
|         case Settings::LayoutOption::Default: |         case Settings::LayoutOption::Default: | ||||||
|         default: |         default: | ||||||
|             if (Settings::values.upright_screen) { |             if (Settings::values.upright_screen.GetValue()) { | ||||||
|                 width = (Core::kScreenTopHeight + Core::kScreenBottomHeight) * res_scale; |                 width = (Core::kScreenTopHeight + Core::kScreenBottomHeight) * res_scale; | ||||||
|                 height = Core::kScreenTopWidth * res_scale; |                 height = Core::kScreenTopWidth * res_scale; | ||||||
|             } else { |             } else { | ||||||
|                 width = Core::kScreenTopWidth * res_scale; |                 width = Core::kScreenTopWidth * res_scale; | ||||||
|                 height = (Core::kScreenTopHeight + Core::kScreenBottomHeight) * res_scale; |                 height = (Core::kScreenTopHeight + Core::kScreenBottomHeight) * res_scale; | ||||||
|             } |             } | ||||||
|             layout = DefaultFrameLayout(width, height, Settings::values.swap_screen, |             layout = DefaultFrameLayout(width, height, Settings::values.swap_screen.GetValue(), | ||||||
|                                         Settings::values.upright_screen); |                                         Settings::values.upright_screen.GetValue()); | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     if (Settings::values.render_3d == Settings::StereoRenderOption::CardboardVR) { |     if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::CardboardVR) { | ||||||
|         layout = Layout::GetCardboardSettings(layout); |         layout = Layout::GetCardboardSettings(layout); | ||||||
|     } |     } | ||||||
|     return layout; |     return layout; | ||||||
|  | @ -478,17 +482,17 @@ FramebufferLayout GetCardboardSettings(FramebufferLayout layout) { | ||||||
|     float bottom_screen_left = 0; |     float bottom_screen_left = 0; | ||||||
|     float bottom_screen_top = 0; |     float bottom_screen_top = 0; | ||||||
| 
 | 
 | ||||||
|     float cardboardScreenScale = Settings::values.cardboard_screen_size / 100.0f; |     float cardboardScreenScale = Settings::values.cardboard_screen_size.GetValue() / 100.0f; | ||||||
|     float top_screen_width = layout.top_screen.GetWidth() / 2.0f * cardboardScreenScale; |     float top_screen_width = layout.top_screen.GetWidth() / 2.0f * cardboardScreenScale; | ||||||
|     float top_screen_height = layout.top_screen.GetHeight() / 2.0f * cardboardScreenScale; |     float top_screen_height = layout.top_screen.GetHeight() / 2.0f * cardboardScreenScale; | ||||||
|     float bottom_screen_width = layout.bottom_screen.GetWidth() / 2.0f * cardboardScreenScale; |     float bottom_screen_width = layout.bottom_screen.GetWidth() / 2.0f * cardboardScreenScale; | ||||||
|     float bottom_screen_height = layout.bottom_screen.GetHeight() / 2.0f * cardboardScreenScale; |     float bottom_screen_height = layout.bottom_screen.GetHeight() / 2.0f * cardboardScreenScale; | ||||||
|     bool is_swapped = Settings::values.swap_screen; |     const bool is_swapped = Settings::values.swap_screen.GetValue(); | ||||||
|     bool is_portrait = layout.height > layout.width; |     const bool is_portrait = layout.height > layout.width; | ||||||
| 
 | 
 | ||||||
|     float cardboardScreenWidth; |     float cardboardScreenWidth; | ||||||
|     float cardboardScreenHeight; |     float cardboardScreenHeight; | ||||||
|     switch (Settings::values.layout_option) { |     switch (Settings::values.layout_option.GetValue()) { | ||||||
|     case Settings::LayoutOption::MobileLandscape: |     case Settings::LayoutOption::MobileLandscape: | ||||||
|     case Settings::LayoutOption::SideScreen: |     case Settings::LayoutOption::SideScreen: | ||||||
|         // If orientation is portrait, only use MobilePortrait
 |         // If orientation is portrait, only use MobilePortrait
 | ||||||
|  | @ -524,9 +528,11 @@ FramebufferLayout GetCardboardSettings(FramebufferLayout layout) { | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
|     float cardboardMaxXShift = (layout.width / 2.0f - cardboardScreenWidth) / 2.0f; |     float cardboardMaxXShift = (layout.width / 2.0f - cardboardScreenWidth) / 2.0f; | ||||||
|     float cardboardUserXShift = (Settings::values.cardboard_x_shift / 100.0f) * cardboardMaxXShift; |     float cardboardUserXShift = | ||||||
|  |         (Settings::values.cardboard_x_shift.GetValue() / 100.0f) * cardboardMaxXShift; | ||||||
|     float cardboardMaxYShift = ((float)layout.height - cardboardScreenHeight) / 2.0f; |     float cardboardMaxYShift = ((float)layout.height - cardboardScreenHeight) / 2.0f; | ||||||
|     float cardboardUserYShift = (Settings::values.cardboard_y_shift / 100.0f) * cardboardMaxYShift; |     float cardboardUserYShift = | ||||||
|  |         (Settings::values.cardboard_y_shift.GetValue() / 100.0f) * cardboardMaxYShift; | ||||||
| 
 | 
 | ||||||
|     // Center the screens and apply user Y shift
 |     // Center the screens and apply user Y shift
 | ||||||
|     newLayout.top_screen.left = top_screen_left + cardboardMaxXShift; |     newLayout.top_screen.left = top_screen_left + cardboardMaxXShift; | ||||||
|  |  | ||||||
|  | @ -5,7 +5,7 @@ | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| #include "common/math_util.h" | #include "common/math_util.h" | ||||||
| #include "core/settings.h" | #include "common/settings.h" | ||||||
| 
 | 
 | ||||||
| namespace Layout { | namespace Layout { | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -11,6 +11,7 @@ | ||||||
| #include "common/assert.h" | #include "common/assert.h" | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| #include "common/logging/log.h" | #include "common/logging/log.h" | ||||||
|  | #include "common/settings.h" | ||||||
| #include "core/core.h" | #include "core/core.h" | ||||||
| #include "core/hle/kernel/config_mem.h" | #include "core/hle/kernel/config_mem.h" | ||||||
| #include "core/hle/kernel/memory.h" | #include "core/hle/kernel/memory.h" | ||||||
|  | @ -19,7 +20,6 @@ | ||||||
| #include "core/hle/kernel/vm_manager.h" | #include "core/hle/kernel/vm_manager.h" | ||||||
| #include "core/hle/result.h" | #include "core/hle/result.h" | ||||||
| #include "core/memory.h" | #include "core/memory.h" | ||||||
| #include "core/settings.h" |  | ||||||
| 
 | 
 | ||||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||||
| 
 | 
 | ||||||
|  | @ -52,7 +52,7 @@ enum N3DSMode : u8 { | ||||||
| void KernelSystem::MemoryInit(u32 mem_type, u8 n3ds_mode) { | void KernelSystem::MemoryInit(u32 mem_type, u8 n3ds_mode) { | ||||||
|     ASSERT(mem_type != 1); |     ASSERT(mem_type != 1); | ||||||
| 
 | 
 | ||||||
|     const bool is_new_3ds = Settings::values.is_new_3ds; |     const bool is_new_3ds = Settings::values.is_new_3ds.GetValue(); | ||||||
|     u32 reported_mem_type = mem_type; |     u32 reported_mem_type = mem_type; | ||||||
|     if (is_new_3ds) { |     if (is_new_3ds) { | ||||||
|         if (n3ds_mode == MemoryMode::Mode6 || n3ds_mode == MemoryMode::Mode6_2) { |         if (n3ds_mode == MemoryMode::Mode6 || n3ds_mode == MemoryMode::Mode6_2) { | ||||||
|  |  | ||||||
|  | @ -6,12 +6,12 @@ | ||||||
| #include <cstring> | #include <cstring> | ||||||
| #include "common/archives.h" | #include "common/archives.h" | ||||||
| #include "common/assert.h" | #include "common/assert.h" | ||||||
|  | #include "common/settings.h" | ||||||
| #include "core/core.h" | #include "core/core.h" | ||||||
| #include "core/core_timing.h" | #include "core/core_timing.h" | ||||||
| #include "core/hle/kernel/shared_page.h" | #include "core/hle/kernel/shared_page.h" | ||||||
| #include "core/hle/service/ptm/ptm.h" | #include "core/hle/service/ptm/ptm.h" | ||||||
| #include "core/movie.h" | #include "core/movie.h" | ||||||
| #include "core/settings.h" |  | ||||||
| 
 | 
 | ||||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||||
| 
 | 
 | ||||||
|  | @ -37,7 +37,7 @@ static std::chrono::seconds GetInitTime() { | ||||||
|         return std::chrono::seconds(override_init_time); |         return std::chrono::seconds(override_init_time); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     switch (Settings::values.init_clock) { |     switch (Settings::values.init_clock.GetValue()) { | ||||||
|     case Settings::InitClock::SystemTime: { |     case Settings::InitClock::SystemTime: { | ||||||
|         auto now = std::chrono::system_clock::now(); |         auto now = std::chrono::system_clock::now(); | ||||||
|         // If the system time is in daylight saving, we give an additional hour to console time
 |         // If the system time is in daylight saving, we give an additional hour to console time
 | ||||||
|  | @ -47,7 +47,7 @@ static std::chrono::seconds GetInitTime() { | ||||||
|             now = now + std::chrono::hours(1); |             now = now + std::chrono::hours(1); | ||||||
| 
 | 
 | ||||||
|         // add the offset
 |         // add the offset
 | ||||||
|         s64 init_time_offset = Settings::values.init_time_offset; |         s64 init_time_offset = Settings::values.init_time_offset.GetValue(); | ||||||
|         long long days_offset = init_time_offset / 86400; |         long long days_offset = init_time_offset / 86400; | ||||||
|         long long days_offset_in_seconds = days_offset * 86400; // h/m/s truncated
 |         long long days_offset_in_seconds = days_offset * 86400; // h/m/s truncated
 | ||||||
|         unsigned long long seconds_offset = |         unsigned long long seconds_offset = | ||||||
|  | @ -58,9 +58,9 @@ static std::chrono::seconds GetInitTime() { | ||||||
|         return std::chrono::duration_cast<std::chrono::seconds>(now.time_since_epoch()); |         return std::chrono::duration_cast<std::chrono::seconds>(now.time_since_epoch()); | ||||||
|     } |     } | ||||||
|     case Settings::InitClock::FixedTime: |     case Settings::InitClock::FixedTime: | ||||||
|         return std::chrono::seconds(Settings::values.init_time); |         return std::chrono::seconds(Settings::values.init_time.GetValue()); | ||||||
|     default: |     default: | ||||||
|         UNREACHABLE_MSG("Invalid InitClock value ({})", Settings::values.init_clock); |         UNREACHABLE_MSG("Invalid InitClock value ({})", Settings::values.init_clock.GetValue()); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -85,7 +85,7 @@ Handler::Handler(Core::Timing& timing) : timing(timing) { | ||||||
|                                              std::bind(&Handler::UpdateTimeCallback, this, _1, _2)); |                                              std::bind(&Handler::UpdateTimeCallback, this, _1, _2)); | ||||||
|     timing.ScheduleEvent(0, update_time_event, 0, 0); |     timing.ScheduleEvent(0, update_time_event, 0, 0); | ||||||
| 
 | 
 | ||||||
|     float slidestate = Settings::values.factor_3d / 100.0f; |     float slidestate = Settings::values.factor_3d.GetValue() / 100.0f; | ||||||
|     shared_page.sliderstate_3d = static_cast<float_le>(slidestate); |     shared_page.sliderstate_3d = static_cast<float_le>(slidestate); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -8,6 +8,7 @@ | ||||||
| #include "common/common_paths.h" | #include "common/common_paths.h" | ||||||
| #include "common/file_util.h" | #include "common/file_util.h" | ||||||
| #include "common/logging/log.h" | #include "common/logging/log.h" | ||||||
|  | #include "common/settings.h" | ||||||
| #include "core/core.h" | #include "core/core.h" | ||||||
| #include "core/file_sys/archive_ncch.h" | #include "core/file_sys/archive_ncch.h" | ||||||
| #include "core/file_sys/file_backend.h" | #include "core/file_sys/file_backend.h" | ||||||
|  | @ -28,7 +29,6 @@ | ||||||
| #include "core/hle/service/service.h" | #include "core/hle/service/service.h" | ||||||
| #include "core/hw/aes/ccm.h" | #include "core/hw/aes/ccm.h" | ||||||
| #include "core/hw/aes/key.h" | #include "core/hw/aes/key.h" | ||||||
| #include "core/settings.h" |  | ||||||
| 
 | 
 | ||||||
| SERVICE_CONSTRUCT_IMPL(Service::APT::Module) | SERVICE_CONSTRUCT_IMPL(Service::APT::Module) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -6,6 +6,7 @@ | ||||||
| #include "common/archives.h" | #include "common/archives.h" | ||||||
| #include "common/bit_set.h" | #include "common/bit_set.h" | ||||||
| #include "common/logging/log.h" | #include "common/logging/log.h" | ||||||
|  | #include "common/settings.h" | ||||||
| #include "core/core.h" | #include "core/core.h" | ||||||
| #include "core/core_timing.h" | #include "core/core_timing.h" | ||||||
| #include "core/frontend/camera/factory.h" | #include "core/frontend/camera/factory.h" | ||||||
|  | @ -19,7 +20,6 @@ | ||||||
| #include "core/hle/service/cam/cam_s.h" | #include "core/hle/service/cam/cam_s.h" | ||||||
| #include "core/hle/service/cam/cam_u.h" | #include "core/hle/service/cam/cam_u.h" | ||||||
| #include "core/memory.h" | #include "core/memory.h" | ||||||
| #include "core/settings.h" |  | ||||||
| 
 | 
 | ||||||
| SERVICE_CONSTRUCT_IMPL(Service::CAM::Module) | SERVICE_CONSTRUCT_IMPL(Service::CAM::Module) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -12,6 +12,7 @@ | ||||||
| #include "common/archives.h" | #include "common/archives.h" | ||||||
| #include "common/file_util.h" | #include "common/file_util.h" | ||||||
| #include "common/logging/log.h" | #include "common/logging/log.h" | ||||||
|  | #include "common/settings.h" | ||||||
| #include "common/string_util.h" | #include "common/string_util.h" | ||||||
| #include "common/swap.h" | #include "common/swap.h" | ||||||
| #include "core/core.h" | #include "core/core.h" | ||||||
|  | @ -25,7 +26,6 @@ | ||||||
| #include "core/hle/service/cfg/cfg_nor.h" | #include "core/hle/service/cfg/cfg_nor.h" | ||||||
| #include "core/hle/service/cfg/cfg_s.h" | #include "core/hle/service/cfg/cfg_s.h" | ||||||
| #include "core/hle/service/cfg/cfg_u.h" | #include "core/hle/service/cfg/cfg_u.h" | ||||||
| #include "core/settings.h" |  | ||||||
| 
 | 
 | ||||||
| SERIALIZE_EXPORT_IMPL(Service::CFG::Module) | SERIALIZE_EXPORT_IMPL(Service::CFG::Module) | ||||||
| 
 | 
 | ||||||
|  | @ -189,10 +189,10 @@ void Module::Interface::GetCountryCodeID(Kernel::HLERequestContext& ctx) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| u32 Module::GetRegionValue() { | u32 Module::GetRegionValue() { | ||||||
|     if (Settings::values.region_value == Settings::REGION_VALUE_AUTO_SELECT) |     if (Settings::values.region_value.GetValue() == Settings::REGION_VALUE_AUTO_SELECT) | ||||||
|         return preferred_region_code; |         return preferred_region_code; | ||||||
| 
 | 
 | ||||||
|     return Settings::values.region_value; |     return Settings::values.region_value.GetValue(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Module::Interface::SecureInfoGetRegion(Kernel::HLERequestContext& ctx, u16 id) { | void Module::Interface::SecureInfoGetRegion(Kernel::HLERequestContext& ctx, u16 id) { | ||||||
|  | @ -654,7 +654,7 @@ void Module::SetPreferredRegionCodes(const std::vector<u32>& region_codes) { | ||||||
|     preferred_region_code = region; |     preferred_region_code = region; | ||||||
|     LOG_INFO(Service_CFG, "Preferred region code set to {}", preferred_region_code); |     LOG_INFO(Service_CFG, "Preferred region code set to {}", preferred_region_code); | ||||||
| 
 | 
 | ||||||
|     if (Settings::values.region_value == Settings::REGION_VALUE_AUTO_SELECT) { |     if (Settings::values.region_value.GetValue() == Settings::REGION_VALUE_AUTO_SELECT) { | ||||||
|         if (current_language != adjusted_language) { |         if (current_language != adjusted_language) { | ||||||
|             LOG_WARNING(Service_CFG, "System language {} does not fit the region. Adjusted to {}", |             LOG_WARNING(Service_CFG, "System language {} does not fit the region. Adjusted to {}", | ||||||
|                         current_language, adjusted_language); |                         current_language, adjusted_language); | ||||||
|  |  | ||||||
|  | @ -9,6 +9,7 @@ | ||||||
| #include "common/file_util.h" | #include "common/file_util.h" | ||||||
| #include "common/logging/log.h" | #include "common/logging/log.h" | ||||||
| #include "common/scope_exit.h" | #include "common/scope_exit.h" | ||||||
|  | #include "common/settings.h" | ||||||
| #include "common/string_util.h" | #include "common/string_util.h" | ||||||
| #include "core/core.h" | #include "core/core.h" | ||||||
| #include "core/file_sys/errors.h" | #include "core/file_sys/errors.h" | ||||||
|  | @ -25,7 +26,6 @@ | ||||||
| #include "core/hle/service/am/am.h" | #include "core/hle/service/am/am.h" | ||||||
| #include "core/hle/service/fs/archive.h" | #include "core/hle/service/fs/archive.h" | ||||||
| #include "core/hle/service/fs/fs_user.h" | #include "core/hle/service/fs/fs_user.h" | ||||||
| #include "core/settings.h" |  | ||||||
| 
 | 
 | ||||||
| SERVICE_CONSTRUCT_IMPL(Service::FS::FS_USER) | SERVICE_CONSTRUCT_IMPL(Service::FS::FS_USER) | ||||||
| SERIALIZE_EXPORT_IMPL(Service::FS::FS_USER) | SERIALIZE_EXPORT_IMPL(Service::FS::FS_USER) | ||||||
|  | @ -350,7 +350,7 @@ void FS_USER::IsSdmcDetected(Kernel::HLERequestContext& ctx) { | ||||||
|     IPC::RequestParser rp(ctx, 0x817, 0, 0); |     IPC::RequestParser rp(ctx, 0x817, 0, 0); | ||||||
|     IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); |     IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); | ||||||
|     rb.Push(RESULT_SUCCESS); |     rb.Push(RESULT_SUCCESS); | ||||||
|     rb.Push(Settings::values.use_virtual_sd); |     rb.Push(Settings::values.use_virtual_sd.GetValue()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void FS_USER::IsSdmcWriteable(Kernel::HLERequestContext& ctx) { | void FS_USER::IsSdmcWriteable(Kernel::HLERequestContext& ctx) { | ||||||
|  | @ -358,7 +358,7 @@ void FS_USER::IsSdmcWriteable(Kernel::HLERequestContext& ctx) { | ||||||
|     IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); |     IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); | ||||||
|     rb.Push(RESULT_SUCCESS); |     rb.Push(RESULT_SUCCESS); | ||||||
|     // If the SD isn't enabled, it can't be writeable...else, stubbed true
 |     // If the SD isn't enabled, it can't be writeable...else, stubbed true
 | ||||||
|     rb.Push(Settings::values.use_virtual_sd); |     rb.Push(Settings::values.use_virtual_sd.GetValue()); | ||||||
|     LOG_DEBUG(Service_FS, " (STUBBED)"); |     LOG_DEBUG(Service_FS, " (STUBBED)"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -218,8 +218,9 @@ void Module::UpdatePadCallback(std::uintptr_t user_data, s64 cycles_late) { | ||||||
| 
 | 
 | ||||||
|     // TODO(xperia64): How the 3D Slider is updated by the HID module needs to be RE'd
 |     // TODO(xperia64): How the 3D Slider is updated by the HID module needs to be RE'd
 | ||||||
|     // and possibly moved to its own Core::Timing event.
 |     // and possibly moved to its own Core::Timing event.
 | ||||||
|     mem->pad.sliderstate_3d = (Settings::values.factor_3d / 100.0f); |     mem->pad.sliderstate_3d = (Settings::values.factor_3d.GetValue() / 100.0f); | ||||||
|     system.Kernel().GetSharedPageHandler().Set3DSlider(Settings::values.factor_3d / 100.0f); |     system.Kernel().GetSharedPageHandler().Set3DSlider(Settings::values.factor_3d.GetValue() / | ||||||
|  |                                                        100.0f); | ||||||
| 
 | 
 | ||||||
|     // Reschedule recurrent event
 |     // Reschedule recurrent event
 | ||||||
|     system.CoreTiming().ScheduleEvent(pad_update_ticks - cycles_late, pad_update_event); |     system.CoreTiming().ScheduleEvent(pad_update_ticks - cycles_late, pad_update_event); | ||||||
|  | @ -406,7 +407,7 @@ void Module::Interface::GetGyroscopeLowCalibrateParam(Kernel::HLERequestContext& | ||||||
| void Module::Interface::GetSoundVolume(Kernel::HLERequestContext& ctx) { | void Module::Interface::GetSoundVolume(Kernel::HLERequestContext& ctx) { | ||||||
|     IPC::RequestParser rp{ctx, 0x17, 0, 0}; |     IPC::RequestParser rp{ctx, 0x17, 0, 0}; | ||||||
| 
 | 
 | ||||||
|     const u8 volume = static_cast<u8>(0x3F * Settings::values.volume); |     const u8 volume = static_cast<u8>(0x3F * Settings::values.volume.GetValue()); | ||||||
| 
 | 
 | ||||||
|     IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); |     IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); | ||||||
|     rb.Push(RESULT_SUCCESS); |     rb.Push(RESULT_SUCCESS); | ||||||
|  |  | ||||||
|  | @ -13,10 +13,10 @@ | ||||||
| #include "common/bit_field.h" | #include "common/bit_field.h" | ||||||
| #include "common/common_funcs.h" | #include "common/common_funcs.h" | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
|  | #include "common/settings.h" | ||||||
| #include "core/core_timing.h" | #include "core/core_timing.h" | ||||||
| #include "core/frontend/input.h" | #include "core/frontend/input.h" | ||||||
| #include "core/hle/service/service.h" | #include "core/hle/service/service.h" | ||||||
| #include "core/settings.h" |  | ||||||
| 
 | 
 | ||||||
| namespace Core { | namespace Core { | ||||||
| class System; | class System; | ||||||
|  |  | ||||||
|  | @ -3,12 +3,12 @@ | ||||||
| // Refer to the license.txt file included.
 | // Refer to the license.txt file included.
 | ||||||
| 
 | 
 | ||||||
| #include "common/alignment.h" | #include "common/alignment.h" | ||||||
|  | #include "common/settings.h" | ||||||
| #include "common/string_util.h" | #include "common/string_util.h" | ||||||
| #include "core/core.h" | #include "core/core.h" | ||||||
| #include "core/core_timing.h" | #include "core/core_timing.h" | ||||||
| #include "core/hle/service/ir/extra_hid.h" | #include "core/hle/service/ir/extra_hid.h" | ||||||
| #include "core/movie.h" | #include "core/movie.h" | ||||||
| #include "core/settings.h" |  | ||||||
| 
 | 
 | ||||||
| namespace Service::IR { | namespace Service::IR { | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -5,6 +5,7 @@ | ||||||
| #include <boost/serialization/base_object.hpp> | #include <boost/serialization/base_object.hpp> | ||||||
| #include <boost/serialization/shared_ptr.hpp> | #include <boost/serialization/shared_ptr.hpp> | ||||||
| #include "common/archives.h" | #include "common/archives.h" | ||||||
|  | #include "common/settings.h" | ||||||
| #include "core/core.h" | #include "core/core.h" | ||||||
| #include "core/core_timing.h" | #include "core/core_timing.h" | ||||||
| #include "core/hle/ipc_helpers.h" | #include "core/hle/ipc_helpers.h" | ||||||
|  | @ -13,7 +14,6 @@ | ||||||
| #include "core/hle/service/hid/hid.h" | #include "core/hle/service/hid/hid.h" | ||||||
| #include "core/hle/service/ir/ir_rst.h" | #include "core/hle/service/ir/ir_rst.h" | ||||||
| #include "core/movie.h" | #include "core/movie.h" | ||||||
| #include "core/settings.h" |  | ||||||
| 
 | 
 | ||||||
| SERIALIZE_EXPORT_IMPL(Service::IR::IR_RST) | SERIALIZE_EXPORT_IMPL(Service::IR::IR_RST) | ||||||
| SERVICE_CONSTRUCT_IMPL(Service::IR::IR_RST) | SERVICE_CONSTRUCT_IMPL(Service::IR::IR_RST) | ||||||
|  |  | ||||||
|  | @ -5,6 +5,7 @@ | ||||||
| #include <boost/serialization/weak_ptr.hpp> | #include <boost/serialization/weak_ptr.hpp> | ||||||
| #include "common/archives.h" | #include "common/archives.h" | ||||||
| #include "common/logging/log.h" | #include "common/logging/log.h" | ||||||
|  | #include "common/settings.h" | ||||||
| #include "core/core.h" | #include "core/core.h" | ||||||
| #include "core/frontend/mic.h" | #include "core/frontend/mic.h" | ||||||
| #include "core/hle/ipc.h" | #include "core/hle/ipc.h" | ||||||
|  | @ -14,7 +15,6 @@ | ||||||
| #include "core/hle/kernel/kernel.h" | #include "core/hle/kernel/kernel.h" | ||||||
| #include "core/hle/kernel/shared_memory.h" | #include "core/hle/kernel/shared_memory.h" | ||||||
| #include "core/hle/service/mic_u.h" | #include "core/hle/service/mic_u.h" | ||||||
| #include "core/settings.h" |  | ||||||
| 
 | 
 | ||||||
| SERVICE_CONSTRUCT_IMPL(Service::MIC::MIC_U) | SERVICE_CONSTRUCT_IMPL(Service::MIC::MIC_U) | ||||||
| SERIALIZE_EXPORT_IMPL(Service::MIC::MIC_U) | SERIALIZE_EXPORT_IMPL(Service::MIC::MIC_U) | ||||||
|  | @ -350,12 +350,12 @@ struct MIC_U::Impl { | ||||||
| 
 | 
 | ||||||
|     void CreateMic() { |     void CreateMic() { | ||||||
|         std::unique_ptr<Frontend::Mic::Interface> new_mic; |         std::unique_ptr<Frontend::Mic::Interface> new_mic; | ||||||
|         switch (Settings::values.mic_input_type) { |         switch (Settings::values.mic_input_type.GetValue()) { | ||||||
|         case Settings::MicInputType::None: |         case Settings::MicInputType::None: | ||||||
|             new_mic = std::make_unique<Frontend::Mic::NullMic>(); |             new_mic = std::make_unique<Frontend::Mic::NullMic>(); | ||||||
|             break; |             break; | ||||||
|         case Settings::MicInputType::Real: |         case Settings::MicInputType::Real: | ||||||
|             new_mic = Frontend::Mic::CreateRealMic(Settings::values.mic_input_device); |             new_mic = Frontend::Mic::CreateRealMic(Settings::values.mic_input_device.GetValue()); | ||||||
|             break; |             break; | ||||||
|         case Settings::MicInputType::Static: |         case Settings::MicInputType::Static: | ||||||
|             new_mic = std::make_unique<Frontend::Mic::StaticMic>(); |             new_mic = std::make_unique<Frontend::Mic::StaticMic>(); | ||||||
|  |  | ||||||
|  | @ -7,6 +7,7 @@ | ||||||
| #include "common/common_paths.h" | #include "common/common_paths.h" | ||||||
| #include "common/file_util.h" | #include "common/file_util.h" | ||||||
| #include "common/logging/log.h" | #include "common/logging/log.h" | ||||||
|  | #include "common/settings.h" | ||||||
| #include "core/core.h" | #include "core/core.h" | ||||||
| #include "core/file_sys/archive_extsavedata.h" | #include "core/file_sys/archive_extsavedata.h" | ||||||
| #include "core/file_sys/errors.h" | #include "core/file_sys/errors.h" | ||||||
|  | @ -17,7 +18,6 @@ | ||||||
| #include "core/hle/service/ptm/ptm_sets.h" | #include "core/hle/service/ptm/ptm_sets.h" | ||||||
| #include "core/hle/service/ptm/ptm_sysm.h" | #include "core/hle/service/ptm/ptm_sysm.h" | ||||||
| #include "core/hle/service/ptm/ptm_u.h" | #include "core/hle/service/ptm/ptm_u.h" | ||||||
| #include "core/settings.h" |  | ||||||
| 
 | 
 | ||||||
| SERIALIZE_EXPORT_IMPL(Service::PTM::Module) | SERIALIZE_EXPORT_IMPL(Service::PTM::Module) | ||||||
| 
 | 
 | ||||||
|  | @ -118,7 +118,7 @@ void Module::Interface::GetSoftwareClosedFlag(Kernel::HLERequestContext& ctx) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void CheckNew3DS(IPC::RequestBuilder& rb) { | void CheckNew3DS(IPC::RequestBuilder& rb) { | ||||||
|     const bool is_new_3ds = Settings::values.is_new_3ds; |     const bool is_new_3ds = Settings::values.is_new_3ds.GetValue(); | ||||||
| 
 | 
 | ||||||
|     rb.Push(RESULT_SUCCESS); |     rb.Push(RESULT_SUCCESS); | ||||||
|     rb.Push(is_new_3ds); |     rb.Push(is_new_3ds); | ||||||
|  |  | ||||||
|  | @ -12,6 +12,7 @@ | ||||||
| #include "common/atomic_ops.h" | #include "common/atomic_ops.h" | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| #include "common/logging/log.h" | #include "common/logging/log.h" | ||||||
|  | #include "common/settings.h" | ||||||
| #include "common/swap.h" | #include "common/swap.h" | ||||||
| #include "core/arm/arm_interface.h" | #include "core/arm/arm_interface.h" | ||||||
| #include "core/core.h" | #include "core/core.h" | ||||||
|  | @ -20,7 +21,6 @@ | ||||||
| #include "core/hle/kernel/process.h" | #include "core/hle/kernel/process.h" | ||||||
| #include "core/hle/lock.h" | #include "core/hle/lock.h" | ||||||
| #include "core/memory.h" | #include "core/memory.h" | ||||||
| #include "core/settings.h" |  | ||||||
| #include "video_core/renderer_base.h" | #include "video_core/renderer_base.h" | ||||||
| #include "video_core/video_core.h" | #include "video_core/video_core.h" | ||||||
| 
 | 
 | ||||||
|  | @ -289,7 +289,7 @@ private: | ||||||
|     friend class boost::serialization::access; |     friend class boost::serialization::access; | ||||||
|     template <class Archive> |     template <class Archive> | ||||||
|     void serialize(Archive& ar, const unsigned int file_version) { |     void serialize(Archive& ar, const unsigned int file_version) { | ||||||
|         bool save_n3ds_ram = Settings::values.is_new_3ds; |         bool save_n3ds_ram = Settings::values.is_new_3ds.GetValue(); | ||||||
|         ar& save_n3ds_ram; |         ar& save_n3ds_ram; | ||||||
|         ar& boost::serialization::make_binary_object(vram.get(), Memory::VRAM_SIZE); |         ar& boost::serialization::make_binary_object(vram.get(), Memory::VRAM_SIZE); | ||||||
|         ar& boost::serialization::make_binary_object( |         ar& boost::serialization::make_binary_object( | ||||||
|  |  | ||||||
|  | @ -601,8 +601,8 @@ void Movie::PrepareForPlayback(const std::string& movie_file) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Movie::PrepareForRecording() { | void Movie::PrepareForRecording() { | ||||||
|     if (Settings::values.init_clock == Settings::InitClock::SystemTime) { |     if (Settings::values.init_clock.GetValue() == Settings::InitClock::SystemTime) { | ||||||
|         long long init_time_offset = Settings::values.init_time_offset; |         long long init_time_offset = Settings::values.init_time_offset.GetValue(); | ||||||
|         long long days_offset = init_time_offset / 86400; |         long long days_offset = init_time_offset / 86400; | ||||||
|         unsigned long long seconds_offset = |         unsigned long long seconds_offset = | ||||||
|             std::abs(init_time_offset) - std::abs(days_offset * 86400); |             std::abs(init_time_offset) - std::abs(days_offset * 86400); | ||||||
|  | @ -610,7 +610,7 @@ void Movie::PrepareForRecording() { | ||||||
|         init_time = |         init_time = | ||||||
|             Common::Timer::GetTimeSinceJan1970().count() + seconds_offset + (days_offset * 86400); |             Common::Timer::GetTimeSinceJan1970().count() + seconds_offset + (days_offset * 86400); | ||||||
|     } else { |     } else { | ||||||
|         init_time = Settings::values.init_time; |         init_time = Settings::values.init_time.GetValue(); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -12,9 +12,9 @@ | ||||||
| #include <fmt/chrono.h> | #include <fmt/chrono.h> | ||||||
| #include <fmt/format.h> | #include <fmt/format.h> | ||||||
| #include "common/file_util.h" | #include "common/file_util.h" | ||||||
|  | #include "common/settings.h" | ||||||
| #include "core/hw/gpu.h" | #include "core/hw/gpu.h" | ||||||
| #include "core/perf_stats.h" | #include "core/perf_stats.h" | ||||||
| #include "core/settings.h" |  | ||||||
| 
 | 
 | ||||||
| using namespace std::chrono_literals; | using namespace std::chrono_literals; | ||||||
| using DoubleSecs = std::chrono::duration<double, std::chrono::seconds::period>; | using DoubleSecs = std::chrono::duration<double, std::chrono::seconds::period>; | ||||||
|  | @ -136,14 +136,9 @@ void FrameLimiter::DoFrameLimiting(microseconds current_system_time_us) { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     auto now = Clock::now(); |     auto now = Clock::now(); | ||||||
|     double sleep_scale = Settings::values.frame_limit / 100.0; |     double sleep_scale = Settings::values.frame_limit.GetValue() / 100.0; | ||||||
| 
 | 
 | ||||||
|     if (Settings::values.use_frame_limit_alternate) { |     if (Settings::values.frame_limit.GetValue() == 0) { | ||||||
|         if (Settings::values.frame_limit_alternate == 0) { |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|         sleep_scale = Settings::values.frame_limit_alternate / 100.0; |  | ||||||
|     } else if (Settings::values.frame_limit == 0) { |  | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,268 +0,0 @@ | ||||||
| // Copyright 2014 Citra Emulator Project
 |  | ||||||
| // Licensed under GPLv2 or any later version
 |  | ||||||
| // Refer to the license.txt file included.
 |  | ||||||
| 
 |  | ||||||
| #pragma once |  | ||||||
| 
 |  | ||||||
| #include <array> |  | ||||||
| #include <atomic> |  | ||||||
| #include <string> |  | ||||||
| #include <unordered_map> |  | ||||||
| #include <vector> |  | ||||||
| #include "common/common_types.h" |  | ||||||
| #include "core/hle/service/cam/cam_params.h" |  | ||||||
| 
 |  | ||||||
| namespace Settings { |  | ||||||
| 
 |  | ||||||
| enum class InitClock { |  | ||||||
|     SystemTime = 0, |  | ||||||
|     FixedTime = 1, |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| enum class LayoutOption { |  | ||||||
|     Default, |  | ||||||
|     SingleScreen, |  | ||||||
|     LargeScreen, |  | ||||||
|     SideScreen, |  | ||||||
| #ifndef ANDROID |  | ||||||
|     SeparateWindows, |  | ||||||
| #endif |  | ||||||
|     // Similiar to default, but better for mobile devices in portrait mode. Top screen in clamped to
 |  | ||||||
|     // the top of the frame, and the bottom screen is enlarged to match the top screen.
 |  | ||||||
|     MobilePortrait, |  | ||||||
| 
 |  | ||||||
|     // Similiar to LargeScreen, but better for mobile devices in landscape mode. The screens are
 |  | ||||||
|     // clamped to the top of the frame, and the bottom screen is a bit bigger.
 |  | ||||||
|     MobileLandscape, |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| enum class MicInputType { |  | ||||||
|     None, |  | ||||||
|     Real, |  | ||||||
|     Static, |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| enum class StereoRenderOption { |  | ||||||
|     Off, |  | ||||||
|     SideBySide, |  | ||||||
|     Anaglyph, |  | ||||||
|     Interlaced, |  | ||||||
|     ReverseInterlaced, |  | ||||||
|     CardboardVR |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| namespace NativeButton { |  | ||||||
| enum Values { |  | ||||||
|     A, |  | ||||||
|     B, |  | ||||||
|     X, |  | ||||||
|     Y, |  | ||||||
|     Up, |  | ||||||
|     Down, |  | ||||||
|     Left, |  | ||||||
|     Right, |  | ||||||
|     L, |  | ||||||
|     R, |  | ||||||
|     Start, |  | ||||||
|     Select, |  | ||||||
|     Debug, |  | ||||||
|     Gpio14, |  | ||||||
| 
 |  | ||||||
|     ZL, |  | ||||||
|     ZR, |  | ||||||
| 
 |  | ||||||
|     Home, |  | ||||||
| 
 |  | ||||||
|     NumButtons, |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| constexpr int BUTTON_HID_BEGIN = A; |  | ||||||
| constexpr int BUTTON_IR_BEGIN = ZL; |  | ||||||
| constexpr int BUTTON_NS_BEGIN = Home; |  | ||||||
| 
 |  | ||||||
| constexpr int BUTTON_HID_END = BUTTON_IR_BEGIN; |  | ||||||
| constexpr int BUTTON_IR_END = BUTTON_NS_BEGIN; |  | ||||||
| constexpr int BUTTON_NS_END = NumButtons; |  | ||||||
| 
 |  | ||||||
| constexpr int NUM_BUTTONS_HID = BUTTON_HID_END - BUTTON_HID_BEGIN; |  | ||||||
| constexpr int NUM_BUTTONS_IR = BUTTON_IR_END - BUTTON_IR_BEGIN; |  | ||||||
| constexpr int NUM_BUTTONS_NS = BUTTON_NS_END - BUTTON_NS_BEGIN; |  | ||||||
| 
 |  | ||||||
| static const std::array<const char*, NumButtons> mapping = {{ |  | ||||||
|     "button_a", |  | ||||||
|     "button_b", |  | ||||||
|     "button_x", |  | ||||||
|     "button_y", |  | ||||||
|     "button_up", |  | ||||||
|     "button_down", |  | ||||||
|     "button_left", |  | ||||||
|     "button_right", |  | ||||||
|     "button_l", |  | ||||||
|     "button_r", |  | ||||||
|     "button_start", |  | ||||||
|     "button_select", |  | ||||||
|     "button_debug", |  | ||||||
|     "button_gpio14", |  | ||||||
|     "button_zl", |  | ||||||
|     "button_zr", |  | ||||||
|     "button_home", |  | ||||||
| }}; |  | ||||||
| } // namespace NativeButton
 |  | ||||||
| 
 |  | ||||||
| namespace NativeAnalog { |  | ||||||
| enum Values { |  | ||||||
|     CirclePad, |  | ||||||
|     CStick, |  | ||||||
| 
 |  | ||||||
|     NumAnalogs, |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| static const std::array<const char*, NumAnalogs> mapping = {{ |  | ||||||
|     "circle_pad", |  | ||||||
|     "c_stick", |  | ||||||
| }}; |  | ||||||
| } // namespace NativeAnalog
 |  | ||||||
| 
 |  | ||||||
| struct InputProfile { |  | ||||||
|     std::string name; |  | ||||||
|     std::array<std::string, NativeButton::NumButtons> buttons; |  | ||||||
|     std::array<std::string, NativeAnalog::NumAnalogs> analogs; |  | ||||||
|     std::string motion_device; |  | ||||||
|     std::string touch_device; |  | ||||||
|     bool use_touch_from_button; |  | ||||||
|     int touch_from_button_map_index; |  | ||||||
|     std::string udp_input_address; |  | ||||||
|     u16 udp_input_port; |  | ||||||
|     u8 udp_pad_index; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct TouchFromButtonMap { |  | ||||||
|     std::string name; |  | ||||||
|     std::vector<std::string> buttons; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct Values { |  | ||||||
|     // CheckNew3DS
 |  | ||||||
|     bool is_new_3ds; |  | ||||||
| 
 |  | ||||||
|     // Controls
 |  | ||||||
|     InputProfile current_input_profile;       ///< The current input profile
 |  | ||||||
|     int current_input_profile_index;          ///< The current input profile index
 |  | ||||||
|     std::vector<InputProfile> input_profiles; ///< The list of input profiles
 |  | ||||||
|     std::vector<TouchFromButtonMap> touch_from_button_maps; |  | ||||||
| 
 |  | ||||||
|     // Core
 |  | ||||||
|     bool use_cpu_jit; |  | ||||||
|     int cpu_clock_percentage; |  | ||||||
| 
 |  | ||||||
|     // Data Storage
 |  | ||||||
|     bool use_virtual_sd; |  | ||||||
|     bool use_custom_storage; |  | ||||||
| 
 |  | ||||||
|     // System
 |  | ||||||
|     int region_value; |  | ||||||
|     InitClock init_clock; |  | ||||||
|     u64 init_time; |  | ||||||
|     s64 init_time_offset; |  | ||||||
| 
 |  | ||||||
|     // Renderer
 |  | ||||||
|     bool use_gles; |  | ||||||
|     bool use_hw_renderer; |  | ||||||
|     bool use_hw_shader; |  | ||||||
|     bool separable_shader; |  | ||||||
|     bool use_disk_shader_cache; |  | ||||||
|     bool shaders_accurate_mul; |  | ||||||
|     bool use_shader_jit; |  | ||||||
|     u16 resolution_factor; |  | ||||||
|     bool use_frame_limit_alternate; |  | ||||||
|     u16 frame_limit; |  | ||||||
|     u16 frame_limit_alternate; |  | ||||||
|     std::string texture_filter_name; |  | ||||||
| 
 |  | ||||||
|     LayoutOption layout_option; |  | ||||||
|     bool swap_screen; |  | ||||||
|     bool upright_screen; |  | ||||||
|     bool custom_layout; |  | ||||||
|     u16 custom_top_left; |  | ||||||
|     u16 custom_top_top; |  | ||||||
|     u16 custom_top_right; |  | ||||||
|     u16 custom_top_bottom; |  | ||||||
|     u16 custom_bottom_left; |  | ||||||
|     u16 custom_bottom_top; |  | ||||||
|     u16 custom_bottom_right; |  | ||||||
|     u16 custom_bottom_bottom; |  | ||||||
| 
 |  | ||||||
|     float bg_red; |  | ||||||
|     float bg_green; |  | ||||||
|     float bg_blue; |  | ||||||
| 
 |  | ||||||
|     StereoRenderOption render_3d; |  | ||||||
|     std::atomic<u8> factor_3d; |  | ||||||
| 
 |  | ||||||
|     bool mono_render_left_eye; |  | ||||||
| 
 |  | ||||||
|     int cardboard_screen_size; |  | ||||||
|     int cardboard_x_shift; |  | ||||||
|     int cardboard_y_shift; |  | ||||||
| 
 |  | ||||||
|     bool filter_mode; |  | ||||||
|     std::string pp_shader_name; |  | ||||||
| 
 |  | ||||||
|     bool dump_textures; |  | ||||||
|     bool custom_textures; |  | ||||||
|     bool preload_textures; |  | ||||||
| 
 |  | ||||||
|     bool use_vsync_new; |  | ||||||
| 
 |  | ||||||
|     // Audio
 |  | ||||||
|     bool audio_muted; |  | ||||||
|     bool enable_dsp_lle; |  | ||||||
|     bool enable_dsp_lle_multithread; |  | ||||||
|     std::string sink_id; |  | ||||||
|     bool enable_audio_stretching; |  | ||||||
|     std::string audio_device_id; |  | ||||||
|     float volume; |  | ||||||
|     MicInputType mic_input_type; |  | ||||||
|     std::string mic_input_device; |  | ||||||
| 
 |  | ||||||
|     // Camera
 |  | ||||||
|     std::array<std::string, Service::CAM::NumCameras> camera_name; |  | ||||||
|     std::array<std::string, Service::CAM::NumCameras> camera_config; |  | ||||||
|     std::array<int, Service::CAM::NumCameras> camera_flip; |  | ||||||
| 
 |  | ||||||
|     // Debugging
 |  | ||||||
|     bool record_frame_times; |  | ||||||
|     bool use_gdbstub; |  | ||||||
|     u16 gdbstub_port; |  | ||||||
|     std::string log_filter; |  | ||||||
|     std::unordered_map<std::string, bool> lle_modules; |  | ||||||
| 
 |  | ||||||
|     // Video Dumping
 |  | ||||||
|     std::string output_format; |  | ||||||
|     std::string format_options; |  | ||||||
| 
 |  | ||||||
|     std::string video_encoder; |  | ||||||
|     std::string video_encoder_options; |  | ||||||
|     u64 video_bitrate; |  | ||||||
| 
 |  | ||||||
|     std::string audio_encoder; |  | ||||||
|     std::string audio_encoder_options; |  | ||||||
|     u64 audio_bitrate; |  | ||||||
| } extern values; |  | ||||||
| 
 |  | ||||||
| float Volume(); |  | ||||||
| 
 |  | ||||||
| // a special value for Values::region_value indicating that citra will automatically select a region
 |  | ||||||
| // value to fit the region lockout info of the game
 |  | ||||||
| static constexpr int REGION_VALUE_AUTO_SELECT = -1; |  | ||||||
| 
 |  | ||||||
| void Apply(); |  | ||||||
| void LogSettings(); |  | ||||||
| 
 |  | ||||||
| // Input profiles
 |  | ||||||
| void LoadProfile(int index); |  | ||||||
| void SaveProfile(int index); |  | ||||||
| void CreateProfile(std::string name); |  | ||||||
| void DeleteProfile(int index); |  | ||||||
| void RenameCurrentProfile(std::string new_name); |  | ||||||
| } // namespace Settings
 |  | ||||||
|  | @ -9,8 +9,8 @@ | ||||||
| #include "common/file_util.h" | #include "common/file_util.h" | ||||||
| #include "common/logging/log.h" | #include "common/logging/log.h" | ||||||
| #include "common/scm_rev.h" | #include "common/scm_rev.h" | ||||||
|  | #include "common/settings.h" | ||||||
| #include "core/core.h" | #include "core/core.h" | ||||||
| #include "core/settings.h" |  | ||||||
| #include "core/telemetry_session.h" | #include "core/telemetry_session.h" | ||||||
| #include "network/network_settings.h" | #include "network/network_settings.h" | ||||||
| 
 | 
 | ||||||
|  | @ -124,35 +124,37 @@ void TelemetrySession::AddInitialInfo(Loader::AppLoader& app_loader) { | ||||||
|     Telemetry::AppendOSInfo(field_collection); |     Telemetry::AppendOSInfo(field_collection); | ||||||
| 
 | 
 | ||||||
|     // Log user configuration information
 |     // Log user configuration information
 | ||||||
|     AddField(Telemetry::FieldType::UserConfig, "Audio_SinkId", Settings::values.sink_id); |     AddField(Telemetry::FieldType::UserConfig, "Audio_SinkId", Settings::values.sink_id.GetValue()); | ||||||
|     AddField(Telemetry::FieldType::UserConfig, "Audio_EnableAudioStretching", |     AddField(Telemetry::FieldType::UserConfig, "Audio_EnableAudioStretching", | ||||||
|              Settings::values.enable_audio_stretching); |              Settings::values.enable_audio_stretching.GetValue()); | ||||||
|     AddField(Telemetry::FieldType::UserConfig, "Core_UseCpuJit", Settings::values.use_cpu_jit); |     AddField(Telemetry::FieldType::UserConfig, "Core_UseCpuJit", | ||||||
|  |              Settings::values.use_cpu_jit.GetValue()); | ||||||
|     AddField(Telemetry::FieldType::UserConfig, "Renderer_ResolutionFactor", |     AddField(Telemetry::FieldType::UserConfig, "Renderer_ResolutionFactor", | ||||||
|              Settings::values.resolution_factor); |              Settings::values.resolution_factor.GetValue()); | ||||||
|     AddField(Telemetry::FieldType::UserConfig, "Renderer_FrameLimit", Settings::values.frame_limit); |     AddField(Telemetry::FieldType::UserConfig, "Renderer_FrameLimit", | ||||||
|     AddField(Telemetry::FieldType::UserConfig, "Renderer_UseFrameLimitAlternate", |              Settings::values.frame_limit.GetValue()); | ||||||
|              Settings::values.use_frame_limit_alternate); |  | ||||||
|     AddField(Telemetry::FieldType::UserConfig, "Renderer_FrameLimitAlternate", |  | ||||||
|              Settings::values.frame_limit_alternate); |  | ||||||
|     AddField(Telemetry::FieldType::UserConfig, "Renderer_UseHwRenderer", |     AddField(Telemetry::FieldType::UserConfig, "Renderer_UseHwRenderer", | ||||||
|              Settings::values.use_hw_renderer); |              Settings::values.use_hw_renderer.GetValue()); | ||||||
|     AddField(Telemetry::FieldType::UserConfig, "Renderer_UseHwShader", |     AddField(Telemetry::FieldType::UserConfig, "Renderer_UseHwShader", | ||||||
|              Settings::values.use_hw_shader); |              Settings::values.use_hw_shader.GetValue()); | ||||||
|     AddField(Telemetry::FieldType::UserConfig, "Renderer_ShadersAccurateMul", |     AddField(Telemetry::FieldType::UserConfig, "Renderer_ShadersAccurateMul", | ||||||
|              Settings::values.shaders_accurate_mul); |              Settings::values.shaders_accurate_mul.GetValue()); | ||||||
|     AddField(Telemetry::FieldType::UserConfig, "Renderer_UseShaderJit", |     AddField(Telemetry::FieldType::UserConfig, "Renderer_UseShaderJit", | ||||||
|              Settings::values.use_shader_jit); |              Settings::values.use_shader_jit.GetValue()); | ||||||
|     AddField(Telemetry::FieldType::UserConfig, "Renderer_UseVsync", Settings::values.use_vsync_new); |     AddField(Telemetry::FieldType::UserConfig, "Renderer_UseVsync", | ||||||
|     AddField(Telemetry::FieldType::UserConfig, "Renderer_FilterMode", Settings::values.filter_mode); |              Settings::values.use_vsync_new.GetValue()); | ||||||
|  |     AddField(Telemetry::FieldType::UserConfig, "Renderer_FilterMode", | ||||||
|  |              Settings::values.filter_mode.GetValue()); | ||||||
|     AddField(Telemetry::FieldType::UserConfig, "Renderer_Render3d", |     AddField(Telemetry::FieldType::UserConfig, "Renderer_Render3d", | ||||||
|              static_cast<int>(Settings::values.render_3d)); |              static_cast<int>(Settings::values.render_3d.GetValue())); | ||||||
|     AddField(Telemetry::FieldType::UserConfig, "Renderer_Factor3d", |     AddField(Telemetry::FieldType::UserConfig, "Renderer_Factor3d", | ||||||
|              Settings::values.factor_3d.load()); |              Settings::values.factor_3d.GetValue()); | ||||||
|     AddField(Telemetry::FieldType::UserConfig, "Renderer_MonoRenderLeftEye", |     AddField(Telemetry::FieldType::UserConfig, "Renderer_MonoRenderLeftEye", | ||||||
|              Settings::values.mono_render_left_eye); |              Settings::values.mono_render_left_eye.GetValue()); | ||||||
|     AddField(Telemetry::FieldType::UserConfig, "System_IsNew3ds", Settings::values.is_new_3ds); |     AddField(Telemetry::FieldType::UserConfig, "System_IsNew3ds", | ||||||
|     AddField(Telemetry::FieldType::UserConfig, "System_RegionValue", Settings::values.region_value); |              Settings::values.is_new_3ds.GetValue()); | ||||||
|  |     AddField(Telemetry::FieldType::UserConfig, "System_RegionValue", | ||||||
|  |              Settings::values.region_value.GetValue()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool TelemetrySession::SubmitTestcase() { | bool TelemetrySession::SubmitTestcase() { | ||||||
|  |  | ||||||
|  | @ -5,8 +5,8 @@ | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| #include <memory> | #include <memory> | ||||||
|  | #include "common/settings.h" | ||||||
| #include "core/frontend/input.h" | #include "core/frontend/input.h" | ||||||
| #include "core/settings.h" |  | ||||||
| #include "input_common/gcadapter/gc_adapter.h" | #include "input_common/gcadapter/gc_adapter.h" | ||||||
| #include "input_common/main.h" | #include "input_common/main.h" | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -7,8 +7,8 @@ | ||||||
| #include <atomic> | #include <atomic> | ||||||
| #include <memory> | #include <memory> | ||||||
| #include <thread> | #include <thread> | ||||||
|  | #include "common/settings.h" | ||||||
| #include "common/threadsafe_queue.h" | #include "common/threadsafe_queue.h" | ||||||
| #include "core/settings.h" |  | ||||||
| #include "input_common/sdl/sdl.h" | #include "input_common/sdl/sdl.h" | ||||||
| 
 | 
 | ||||||
| union SDL_Event; | union SDL_Event; | ||||||
|  |  | ||||||
|  | @ -2,8 +2,8 @@ | ||||||
| // Licensed under GPLv2 or any later version
 | // Licensed under GPLv2 or any later version
 | ||||||
| // Refer to the license.txt file included.
 | // Refer to the license.txt file included.
 | ||||||
| 
 | 
 | ||||||
|  | #include "common/settings.h" | ||||||
| #include "core/3ds.h" | #include "core/3ds.h" | ||||||
| #include "core/settings.h" |  | ||||||
| #include "input_common/touch_from_button.h" | #include "input_common/touch_from_button.h" | ||||||
| 
 | 
 | ||||||
| namespace InputCommon { | namespace InputCommon { | ||||||
|  |  | ||||||
|  | @ -6,8 +6,8 @@ | ||||||
| #include <optional> | #include <optional> | ||||||
| #include <tuple> | #include <tuple> | ||||||
| #include "common/param_package.h" | #include "common/param_package.h" | ||||||
|  | #include "common/settings.h" | ||||||
| #include "core/frontend/input.h" | #include "core/frontend/input.h" | ||||||
| #include "core/settings.h" |  | ||||||
| #include "input_common/udp/client.h" | #include "input_common/udp/client.h" | ||||||
| #include "input_common/udp/udp.h" | #include "input_common/udp/udp.h" | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -241,8 +241,8 @@ static Surface FindMatch(const SurfaceCache& surface_cache, const SurfaceParams& | ||||||
| 
 | 
 | ||||||
| RasterizerCacheOpenGL::RasterizerCacheOpenGL() { | RasterizerCacheOpenGL::RasterizerCacheOpenGL() { | ||||||
|     resolution_scale_factor = VideoCore::GetResolutionScaleFactor(); |     resolution_scale_factor = VideoCore::GetResolutionScaleFactor(); | ||||||
|     texture_filterer = std::make_unique<TextureFilterer>(Settings::values.texture_filter_name, |     texture_filterer = std::make_unique<TextureFilterer>( | ||||||
|                                                          resolution_scale_factor); |         Settings::values.texture_filter_name.GetValue(), resolution_scale_factor); | ||||||
|     format_reinterpreter = std::make_unique<FormatReinterpreterOpenGL>(); |     format_reinterpreter = std::make_unique<FormatReinterpreterOpenGL>(); | ||||||
|     texture_downloader_es = std::make_unique<TextureDownloaderES>(false); |     texture_downloader_es = std::make_unique<TextureDownloaderES>(false); | ||||||
| } | } | ||||||
|  | @ -592,7 +592,7 @@ SurfaceSurfaceRect_Tuple RasterizerCacheOpenGL::GetFramebufferSurfaces( | ||||||
|         resolution_scale_factor != VideoCore::GetResolutionScaleFactor(); |         resolution_scale_factor != VideoCore::GetResolutionScaleFactor(); | ||||||
|     const bool texture_filter_changed = |     const bool texture_filter_changed = | ||||||
|         VideoCore::g_texture_filter_update_requested.exchange(false) && |         VideoCore::g_texture_filter_update_requested.exchange(false) && | ||||||
|         texture_filterer->Reset(Settings::values.texture_filter_name, |         texture_filterer->Reset(Settings::values.texture_filter_name.GetValue(), | ||||||
|                                 VideoCore::GetResolutionScaleFactor()); |                                 VideoCore::GetResolutionScaleFactor()); | ||||||
| 
 | 
 | ||||||
|     if (resolution_scale_changed || texture_filter_changed) { |     if (resolution_scale_changed || texture_filter_changed) { | ||||||
|  |  | ||||||
|  | @ -11,10 +11,10 @@ | ||||||
| #include "common/file_util.h" | #include "common/file_util.h" | ||||||
| #include "common/logging/log.h" | #include "common/logging/log.h" | ||||||
| #include "common/scm_rev.h" | #include "common/scm_rev.h" | ||||||
|  | #include "common/settings.h" | ||||||
| #include "common/zstd_compression.h" | #include "common/zstd_compression.h" | ||||||
| #include "core/core.h" | #include "core/core.h" | ||||||
| #include "core/hle/kernel/process.h" | #include "core/hle/kernel/process.h" | ||||||
| #include "core/settings.h" |  | ||||||
| #include "video_core/renderer_opengl/gl_shader_disk_cache.h" | #include "video_core/renderer_opengl/gl_shader_disk_cache.h" | ||||||
| 
 | 
 | ||||||
| namespace OpenGL { | namespace OpenGL { | ||||||
|  |  | ||||||
|  | @ -5,6 +5,7 @@ | ||||||
| #include <queue> | #include <queue> | ||||||
| #include "common/logging/log.h" | #include "common/logging/log.h" | ||||||
| #include "common/microprofile.h" | #include "common/microprofile.h" | ||||||
|  | #include "common/settings.h" | ||||||
| #include "core/core.h" | #include "core/core.h" | ||||||
| #include "core/dumping/backend.h" | #include "core/dumping/backend.h" | ||||||
| #include "core/frontend/emu_window.h" | #include "core/frontend/emu_window.h" | ||||||
|  | @ -12,7 +13,6 @@ | ||||||
| #include "core/hw/hw.h" | #include "core/hw/hw.h" | ||||||
| #include "core/hw/lcd.h" | #include "core/hw/lcd.h" | ||||||
| #include "core/memory.h" | #include "core/memory.h" | ||||||
| #include "core/settings.h" |  | ||||||
| #include "core/tracer/recorder.h" | #include "core/tracer/recorder.h" | ||||||
| #include "video_core/debug_utils/debug_utils.h" | #include "video_core/debug_utils/debug_utils.h" | ||||||
| #include "video_core/rasterizer_interface.h" | #include "video_core/rasterizer_interface.h" | ||||||
|  | @ -381,7 +381,7 @@ void RendererOpenGL::SwapBuffers() { | ||||||
|     RenderToMailbox(main_layout, render_window.mailbox, false); |     RenderToMailbox(main_layout, render_window.mailbox, false); | ||||||
| 
 | 
 | ||||||
| #ifndef ANDROID | #ifndef ANDROID | ||||||
|     if (Settings::values.layout_option == Settings::LayoutOption::SeparateWindows) { |     if (Settings::values.layout_option.GetValue() == Settings::LayoutOption::SeparateWindows) { | ||||||
|         ASSERT(secondary_window); |         ASSERT(secondary_window); | ||||||
|         const auto& secondary_layout = secondary_window->GetFramebufferLayout(); |         const auto& secondary_layout = secondary_window->GetFramebufferLayout(); | ||||||
|         RenderToMailbox(secondary_layout, secondary_window->mailbox, false); |         RenderToMailbox(secondary_layout, secondary_window->mailbox, false); | ||||||
|  | @ -618,8 +618,8 @@ void RendererOpenGL::LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color | ||||||
|  * Initializes the OpenGL state and creates persistent objects. |  * Initializes the OpenGL state and creates persistent objects. | ||||||
|  */ |  */ | ||||||
| void RendererOpenGL::InitOpenGLObjects() { | void RendererOpenGL::InitOpenGLObjects() { | ||||||
|     glClearColor(Settings::values.bg_red, Settings::values.bg_green, Settings::values.bg_blue, |     glClearColor(Settings::values.bg_red.GetValue(), Settings::values.bg_green.GetValue(), | ||||||
|                  0.0f); |                  Settings::values.bg_blue.GetValue(), 0.0f); | ||||||
| 
 | 
 | ||||||
|     filter_sampler.Create(); |     filter_sampler.Create(); | ||||||
|     ReloadSampler(); |     ReloadSampler(); | ||||||
|  | @ -685,12 +685,13 @@ void RendererOpenGL::ReloadShader() { | ||||||
|     if (GLES) { |     if (GLES) { | ||||||
|         shader_data += fragment_shader_precision_OES; |         shader_data += fragment_shader_precision_OES; | ||||||
|     } |     } | ||||||
|     if (Settings::values.render_3d == Settings::StereoRenderOption::Anaglyph) { | 
 | ||||||
|         if (Settings::values.pp_shader_name == "dubois (builtin)") { |     if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Anaglyph) { | ||||||
|  |         if (Settings::values.pp_shader_name.GetValue() == "dubois (builtin)") { | ||||||
|             shader_data += fragment_shader_anaglyph; |             shader_data += fragment_shader_anaglyph; | ||||||
|         } else { |         } else { | ||||||
|             std::string shader_text = |             std::string shader_text = OpenGL::GetPostProcessingShaderCode( | ||||||
|                 OpenGL::GetPostProcessingShaderCode(true, Settings::values.pp_shader_name); |                 true, Settings::values.pp_shader_name.GetValue()); | ||||||
|             if (shader_text.empty()) { |             if (shader_text.empty()) { | ||||||
|                 // Should probably provide some information that the shader couldn't load
 |                 // Should probably provide some information that the shader couldn't load
 | ||||||
|                 shader_data += fragment_shader_anaglyph; |                 shader_data += fragment_shader_anaglyph; | ||||||
|  | @ -698,13 +699,14 @@ void RendererOpenGL::ReloadShader() { | ||||||
|                 shader_data += shader_text; |                 shader_data += shader_text; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } else if (Settings::values.render_3d == Settings::StereoRenderOption::Interlaced || |     } else if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Interlaced || | ||||||
|                Settings::values.render_3d == Settings::StereoRenderOption::ReverseInterlaced) { |                Settings::values.render_3d.GetValue() == | ||||||
|         if (Settings::values.pp_shader_name == "horizontal (builtin)") { |                    Settings::StereoRenderOption::ReverseInterlaced) { | ||||||
|  |         if (Settings::values.pp_shader_name.GetValue() == "horizontal (builtin)") { | ||||||
|             shader_data += fragment_shader_interlaced; |             shader_data += fragment_shader_interlaced; | ||||||
|         } else { |         } else { | ||||||
|             std::string shader_text = |             std::string shader_text = OpenGL::GetPostProcessingShaderCode( | ||||||
|                 OpenGL::GetPostProcessingShaderCode(false, Settings::values.pp_shader_name); |                 false, Settings::values.pp_shader_name.GetValue()); | ||||||
|             if (shader_text.empty()) { |             if (shader_text.empty()) { | ||||||
|                 // Should probably provide some information that the shader couldn't load
 |                 // Should probably provide some information that the shader couldn't load
 | ||||||
|                 shader_data += fragment_shader_interlaced; |                 shader_data += fragment_shader_interlaced; | ||||||
|  | @ -713,11 +715,11 @@ void RendererOpenGL::ReloadShader() { | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } else { |     } else { | ||||||
|         if (Settings::values.pp_shader_name == "none (builtin)") { |         if (Settings::values.pp_shader_name.GetValue() == "none (builtin)") { | ||||||
|             shader_data += fragment_shader; |             shader_data += fragment_shader; | ||||||
|         } else { |         } else { | ||||||
|             std::string shader_text = |             std::string shader_text = OpenGL::GetPostProcessingShaderCode( | ||||||
|                 OpenGL::GetPostProcessingShaderCode(false, Settings::values.pp_shader_name); |                 false, Settings::values.pp_shader_name.GetValue()); | ||||||
|             if (shader_text.empty()) { |             if (shader_text.empty()) { | ||||||
|                 // Should probably provide some information that the shader couldn't load
 |                 // Should probably provide some information that the shader couldn't load
 | ||||||
|                 shader_data += fragment_shader; |                 shader_data += fragment_shader; | ||||||
|  | @ -731,16 +733,17 @@ void RendererOpenGL::ReloadShader() { | ||||||
|     state.Apply(); |     state.Apply(); | ||||||
|     uniform_modelview_matrix = glGetUniformLocation(shader.handle, "modelview_matrix"); |     uniform_modelview_matrix = glGetUniformLocation(shader.handle, "modelview_matrix"); | ||||||
|     uniform_color_texture = glGetUniformLocation(shader.handle, "color_texture"); |     uniform_color_texture = glGetUniformLocation(shader.handle, "color_texture"); | ||||||
|     if (Settings::values.render_3d == Settings::StereoRenderOption::Anaglyph || |     if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Anaglyph || | ||||||
|         Settings::values.render_3d == Settings::StereoRenderOption::Interlaced || |         Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Interlaced || | ||||||
|         Settings::values.render_3d == Settings::StereoRenderOption::ReverseInterlaced) { |         Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::ReverseInterlaced) { | ||||||
|         uniform_color_texture_r = glGetUniformLocation(shader.handle, "color_texture_r"); |         uniform_color_texture_r = glGetUniformLocation(shader.handle, "color_texture_r"); | ||||||
|     } |     } | ||||||
|     if (Settings::values.render_3d == Settings::StereoRenderOption::Interlaced || |     if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Interlaced || | ||||||
|         Settings::values.render_3d == Settings::StereoRenderOption::ReverseInterlaced) { |         Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::ReverseInterlaced) { | ||||||
|         GLuint uniform_reverse_interlaced = |         GLuint uniform_reverse_interlaced = | ||||||
|             glGetUniformLocation(shader.handle, "reverse_interlaced"); |             glGetUniformLocation(shader.handle, "reverse_interlaced"); | ||||||
|         if (Settings::values.render_3d == Settings::StereoRenderOption::ReverseInterlaced) |         if (Settings::values.render_3d.GetValue() == | ||||||
|  |             Settings::StereoRenderOption::ReverseInterlaced) | ||||||
|             glUniform1i(uniform_reverse_interlaced, 1); |             glUniform1i(uniform_reverse_interlaced, 1); | ||||||
|         else |         else | ||||||
|             glUniform1i(uniform_reverse_interlaced, 0); |             glUniform1i(uniform_reverse_interlaced, 0); | ||||||
|  | @ -958,8 +961,8 @@ void RendererOpenGL::DrawSingleScreenStereo(const ScreenInfo& screen_info_l, | ||||||
| void RendererOpenGL::DrawScreens(const Layout::FramebufferLayout& layout, bool flipped) { | void RendererOpenGL::DrawScreens(const Layout::FramebufferLayout& layout, bool flipped) { | ||||||
|     if (VideoCore::g_renderer_bg_color_update_requested.exchange(false)) { |     if (VideoCore::g_renderer_bg_color_update_requested.exchange(false)) { | ||||||
|         // Update background color before drawing
 |         // Update background color before drawing
 | ||||||
|         glClearColor(Settings::values.bg_red, Settings::values.bg_green, Settings::values.bg_blue, |         glClearColor(Settings::values.bg_red.GetValue(), Settings::values.bg_green.GetValue(), | ||||||
|                      0.0f); |                      Settings::values.bg_blue.GetValue(), 0.0f); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (VideoCore::g_renderer_sampler_update_requested.exchange(false)) { |     if (VideoCore::g_renderer_sampler_update_requested.exchange(false)) { | ||||||
|  | @ -989,9 +992,9 @@ void RendererOpenGL::DrawScreens(const Layout::FramebufferLayout& layout, bool f | ||||||
|     glUniform1i(uniform_color_texture, 0); |     glUniform1i(uniform_color_texture, 0); | ||||||
| 
 | 
 | ||||||
|     const bool stereo_single_screen = |     const bool stereo_single_screen = | ||||||
|         Settings::values.render_3d == Settings::StereoRenderOption::Anaglyph || |         Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Anaglyph || | ||||||
|         Settings::values.render_3d == Settings::StereoRenderOption::Interlaced || |         Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Interlaced || | ||||||
|         Settings::values.render_3d == Settings::StereoRenderOption::ReverseInterlaced; |         Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::ReverseInterlaced; | ||||||
| 
 | 
 | ||||||
|     // Bind a second texture for the right eye if in Anaglyph mode
 |     // Bind a second texture for the right eye if in Anaglyph mode
 | ||||||
|     if (stereo_single_screen) { |     if (stereo_single_screen) { | ||||||
|  | @ -1001,12 +1004,13 @@ void RendererOpenGL::DrawScreens(const Layout::FramebufferLayout& layout, bool f | ||||||
|     glUniform1i(uniform_layer, 0); |     glUniform1i(uniform_layer, 0); | ||||||
|     if (layout.top_screen_enabled) { |     if (layout.top_screen_enabled) { | ||||||
|         if (layout.is_rotated) { |         if (layout.is_rotated) { | ||||||
|             if (Settings::values.render_3d == Settings::StereoRenderOption::Off) { |             if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Off) { | ||||||
|                 int eye = Settings::values.mono_render_left_eye ? 0 : 1; |                 int eye = Settings::values.mono_render_left_eye ? 0 : 1; | ||||||
|                 DrawSingleScreenRotated(screen_infos[eye], (float)top_screen.left, |                 DrawSingleScreenRotated(screen_infos[eye], (float)top_screen.left, | ||||||
|                                         (float)top_screen.top, (float)top_screen.GetWidth(), |                                         (float)top_screen.top, (float)top_screen.GetWidth(), | ||||||
|                                         (float)top_screen.GetHeight()); |                                         (float)top_screen.GetHeight()); | ||||||
|             } else if (Settings::values.render_3d == Settings::StereoRenderOption::SideBySide) { |             } else if (Settings::values.render_3d.GetValue() == | ||||||
|  |                        Settings::StereoRenderOption::SideBySide) { | ||||||
|                 DrawSingleScreenRotated(screen_infos[0], (float)top_screen.left / 2, |                 DrawSingleScreenRotated(screen_infos[0], (float)top_screen.left / 2, | ||||||
|                                         (float)top_screen.top, (float)top_screen.GetWidth() / 2, |                                         (float)top_screen.top, (float)top_screen.GetWidth() / 2, | ||||||
|                                         (float)top_screen.GetHeight()); |                                         (float)top_screen.GetHeight()); | ||||||
|  | @ -1015,7 +1019,8 @@ void RendererOpenGL::DrawScreens(const Layout::FramebufferLayout& layout, bool f | ||||||
|                                         ((float)top_screen.left / 2) + ((float)layout.width / 2), |                                         ((float)top_screen.left / 2) + ((float)layout.width / 2), | ||||||
|                                         (float)top_screen.top, (float)top_screen.GetWidth() / 2, |                                         (float)top_screen.top, (float)top_screen.GetWidth() / 2, | ||||||
|                                         (float)top_screen.GetHeight()); |                                         (float)top_screen.GetHeight()); | ||||||
|             } else if (Settings::values.render_3d == Settings::StereoRenderOption::CardboardVR) { |             } else if (Settings::values.render_3d.GetValue() == | ||||||
|  |                        Settings::StereoRenderOption::CardboardVR) { | ||||||
|                 DrawSingleScreenRotated(screen_infos[0], layout.top_screen.left, |                 DrawSingleScreenRotated(screen_infos[0], layout.top_screen.left, | ||||||
|                                         layout.top_screen.top, layout.top_screen.GetWidth(), |                                         layout.top_screen.top, layout.top_screen.GetWidth(), | ||||||
|                                         layout.top_screen.GetHeight()); |                                         layout.top_screen.GetHeight()); | ||||||
|  | @ -1031,11 +1036,12 @@ void RendererOpenGL::DrawScreens(const Layout::FramebufferLayout& layout, bool f | ||||||
|                     (float)top_screen.GetWidth(), (float)top_screen.GetHeight()); |                     (float)top_screen.GetWidth(), (float)top_screen.GetHeight()); | ||||||
|             } |             } | ||||||
|         } else { |         } else { | ||||||
|             if (Settings::values.render_3d == Settings::StereoRenderOption::Off) { |             if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Off) { | ||||||
|                 int eye = Settings::values.mono_render_left_eye ? 0 : 1; |                 int eye = Settings::values.mono_render_left_eye.GetValue() ? 0 : 1; | ||||||
|                 DrawSingleScreen(screen_infos[eye], (float)top_screen.left, (float)top_screen.top, |                 DrawSingleScreen(screen_infos[eye], (float)top_screen.left, (float)top_screen.top, | ||||||
|                                  (float)top_screen.GetWidth(), (float)top_screen.GetHeight()); |                                  (float)top_screen.GetWidth(), (float)top_screen.GetHeight()); | ||||||
|             } else if (Settings::values.render_3d == Settings::StereoRenderOption::SideBySide) { |             } else if (Settings::values.render_3d.GetValue() == | ||||||
|  |                        Settings::StereoRenderOption::SideBySide) { | ||||||
|                 DrawSingleScreen(screen_infos[0], (float)top_screen.left / 2, (float)top_screen.top, |                 DrawSingleScreen(screen_infos[0], (float)top_screen.left / 2, (float)top_screen.top, | ||||||
|                                  (float)top_screen.GetWidth() / 2, (float)top_screen.GetHeight()); |                                  (float)top_screen.GetWidth() / 2, (float)top_screen.GetHeight()); | ||||||
|                 glUniform1i(uniform_layer, 1); |                 glUniform1i(uniform_layer, 1); | ||||||
|  | @ -1043,7 +1049,8 @@ void RendererOpenGL::DrawScreens(const Layout::FramebufferLayout& layout, bool f | ||||||
|                                  ((float)top_screen.left / 2) + ((float)layout.width / 2), |                                  ((float)top_screen.left / 2) + ((float)layout.width / 2), | ||||||
|                                  (float)top_screen.top, (float)top_screen.GetWidth() / 2, |                                  (float)top_screen.top, (float)top_screen.GetWidth() / 2, | ||||||
|                                  (float)top_screen.GetHeight()); |                                  (float)top_screen.GetHeight()); | ||||||
|             } else if (Settings::values.render_3d == Settings::StereoRenderOption::CardboardVR) { |             } else if (Settings::values.render_3d.GetValue() == | ||||||
|  |                        Settings::StereoRenderOption::CardboardVR) { | ||||||
|                 DrawSingleScreen(screen_infos[0], layout.top_screen.left, layout.top_screen.top, |                 DrawSingleScreen(screen_infos[0], layout.top_screen.left, layout.top_screen.top, | ||||||
|                                  layout.top_screen.GetWidth(), layout.top_screen.GetHeight()); |                                  layout.top_screen.GetWidth(), layout.top_screen.GetHeight()); | ||||||
|                 glUniform1i(uniform_layer, 1); |                 glUniform1i(uniform_layer, 1); | ||||||
|  | @ -1061,11 +1068,12 @@ void RendererOpenGL::DrawScreens(const Layout::FramebufferLayout& layout, bool f | ||||||
|     glUniform1i(uniform_layer, 0); |     glUniform1i(uniform_layer, 0); | ||||||
|     if (layout.bottom_screen_enabled) { |     if (layout.bottom_screen_enabled) { | ||||||
|         if (layout.is_rotated) { |         if (layout.is_rotated) { | ||||||
|             if (Settings::values.render_3d == Settings::StereoRenderOption::Off) { |             if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Off) { | ||||||
|                 DrawSingleScreenRotated(screen_infos[2], (float)bottom_screen.left, |                 DrawSingleScreenRotated(screen_infos[2], (float)bottom_screen.left, | ||||||
|                                         (float)bottom_screen.top, (float)bottom_screen.GetWidth(), |                                         (float)bottom_screen.top, (float)bottom_screen.GetWidth(), | ||||||
|                                         (float)bottom_screen.GetHeight()); |                                         (float)bottom_screen.GetHeight()); | ||||||
|             } else if (Settings::values.render_3d == Settings::StereoRenderOption::SideBySide) { |             } else if (Settings::values.render_3d.GetValue() == | ||||||
|  |                        Settings::StereoRenderOption::SideBySide) { | ||||||
|                 DrawSingleScreenRotated( |                 DrawSingleScreenRotated( | ||||||
|                     screen_infos[2], (float)bottom_screen.left / 2, (float)bottom_screen.top, |                     screen_infos[2], (float)bottom_screen.left / 2, (float)bottom_screen.top, | ||||||
|                     (float)bottom_screen.GetWidth() / 2, (float)bottom_screen.GetHeight()); |                     (float)bottom_screen.GetWidth() / 2, (float)bottom_screen.GetHeight()); | ||||||
|  | @ -1074,7 +1082,8 @@ void RendererOpenGL::DrawScreens(const Layout::FramebufferLayout& layout, bool f | ||||||
|                     screen_infos[2], ((float)bottom_screen.left / 2) + ((float)layout.width / 2), |                     screen_infos[2], ((float)bottom_screen.left / 2) + ((float)layout.width / 2), | ||||||
|                     (float)bottom_screen.top, (float)bottom_screen.GetWidth() / 2, |                     (float)bottom_screen.top, (float)bottom_screen.GetWidth() / 2, | ||||||
|                     (float)bottom_screen.GetHeight()); |                     (float)bottom_screen.GetHeight()); | ||||||
|             } else if (Settings::values.render_3d == Settings::StereoRenderOption::CardboardVR) { |             } else if (Settings::values.render_3d.GetValue() == | ||||||
|  |                        Settings::StereoRenderOption::CardboardVR) { | ||||||
|                 DrawSingleScreenRotated(screen_infos[2], layout.bottom_screen.left, |                 DrawSingleScreenRotated(screen_infos[2], layout.bottom_screen.left, | ||||||
|                                         layout.bottom_screen.top, layout.bottom_screen.GetWidth(), |                                         layout.bottom_screen.top, layout.bottom_screen.GetWidth(), | ||||||
|                                         layout.bottom_screen.GetHeight()); |                                         layout.bottom_screen.GetHeight()); | ||||||
|  | @ -1091,11 +1100,12 @@ void RendererOpenGL::DrawScreens(const Layout::FramebufferLayout& layout, bool f | ||||||
|                                               (float)bottom_screen.GetHeight()); |                                               (float)bottom_screen.GetHeight()); | ||||||
|             } |             } | ||||||
|         } else { |         } else { | ||||||
|             if (Settings::values.render_3d == Settings::StereoRenderOption::Off) { |             if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Off) { | ||||||
|                 DrawSingleScreen(screen_infos[2], (float)bottom_screen.left, |                 DrawSingleScreen(screen_infos[2], (float)bottom_screen.left, | ||||||
|                                  (float)bottom_screen.top, (float)bottom_screen.GetWidth(), |                                  (float)bottom_screen.top, (float)bottom_screen.GetWidth(), | ||||||
|                                  (float)bottom_screen.GetHeight()); |                                  (float)bottom_screen.GetHeight()); | ||||||
|             } else if (Settings::values.render_3d == Settings::StereoRenderOption::SideBySide) { |             } else if (Settings::values.render_3d.GetValue() == | ||||||
|  |                        Settings::StereoRenderOption::SideBySide) { | ||||||
|                 DrawSingleScreen(screen_infos[2], (float)bottom_screen.left / 2, |                 DrawSingleScreen(screen_infos[2], (float)bottom_screen.left / 2, | ||||||
|                                  (float)bottom_screen.top, (float)bottom_screen.GetWidth() / 2, |                                  (float)bottom_screen.top, (float)bottom_screen.GetWidth() / 2, | ||||||
|                                  (float)bottom_screen.GetHeight()); |                                  (float)bottom_screen.GetHeight()); | ||||||
|  | @ -1104,7 +1114,8 @@ void RendererOpenGL::DrawScreens(const Layout::FramebufferLayout& layout, bool f | ||||||
|                                  ((float)bottom_screen.left / 2) + ((float)layout.width / 2), |                                  ((float)bottom_screen.left / 2) + ((float)layout.width / 2), | ||||||
|                                  (float)bottom_screen.top, (float)bottom_screen.GetWidth() / 2, |                                  (float)bottom_screen.top, (float)bottom_screen.GetWidth() / 2, | ||||||
|                                  (float)bottom_screen.GetHeight()); |                                  (float)bottom_screen.GetHeight()); | ||||||
|             } else if (Settings::values.render_3d == Settings::StereoRenderOption::CardboardVR) { |             } else if (Settings::values.render_3d.GetValue() == | ||||||
|  |                        Settings::StereoRenderOption::CardboardVR) { | ||||||
|                 DrawSingleScreen(screen_infos[2], layout.bottom_screen.left, |                 DrawSingleScreen(screen_infos[2], layout.bottom_screen.left, | ||||||
|                                  layout.bottom_screen.top, layout.bottom_screen.GetWidth(), |                                  layout.bottom_screen.top, layout.bottom_screen.GetWidth(), | ||||||
|                                  layout.bottom_screen.GetHeight()); |                                  layout.bottom_screen.GetHeight()); | ||||||
|  |  | ||||||
|  | @ -5,7 +5,7 @@ | ||||||
| #include <memory> | #include <memory> | ||||||
| #include "common/archives.h" | #include "common/archives.h" | ||||||
| #include "common/logging/log.h" | #include "common/logging/log.h" | ||||||
| #include "core/settings.h" | #include "common/settings.h" | ||||||
| #include "video_core/pica.h" | #include "video_core/pica.h" | ||||||
| #include "video_core/pica_state.h" | #include "video_core/pica_state.h" | ||||||
| #include "video_core/renderer_base.h" | #include "video_core/renderer_base.h" | ||||||
|  | @ -44,7 +44,7 @@ ResultStatus Init(Frontend::EmuWindow& emu_window, Frontend::EmuWindow* secondar | ||||||
|     g_memory = &memory; |     g_memory = &memory; | ||||||
|     Pica::Init(); |     Pica::Init(); | ||||||
| 
 | 
 | ||||||
|     OpenGL::GLES = Settings::values.use_gles; |     OpenGL::GLES = Settings::values.use_gles.GetValue(); | ||||||
| 
 | 
 | ||||||
|     g_renderer = std::make_unique<OpenGL::RendererOpenGL>(emu_window, secondary_window); |     g_renderer = std::make_unique<OpenGL::RendererOpenGL>(emu_window, secondary_window); | ||||||
|     ResultStatus result = g_renderer->Init(); |     ResultStatus result = g_renderer->Init(); | ||||||
|  | @ -82,8 +82,8 @@ void RequestScreenshot(void* data, std::function<void()> callback, | ||||||
| 
 | 
 | ||||||
| u16 GetResolutionScaleFactor() { | u16 GetResolutionScaleFactor() { | ||||||
|     if (g_hw_renderer_enabled) { |     if (g_hw_renderer_enabled) { | ||||||
|         return Settings::values.resolution_factor |         return Settings::values.resolution_factor.GetValue() | ||||||
|                    ? Settings::values.resolution_factor |                    ? Settings::values.resolution_factor.GetValue() | ||||||
|                    : g_renderer->GetRenderWindow().GetFramebufferLayout().GetScalingRatio(); |                    : g_renderer->GetRenderWindow().GetFramebufferLayout().GetScalingRatio(); | ||||||
|     } else { |     } else { | ||||||
|         // Software renderer always render at native resolution
 |         // Software renderer always render at native resolution
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue