mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40: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 { | ||||
|     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_SingleScreen = 1; | ||||
|     public static final int LayoutOption_LargeScreen = 2; | ||||
|  |  | |||
|  | @ -11,10 +11,10 @@ | |||
| #include "common/file_util.h" | ||||
| #include "common/logging/log.h" | ||||
| #include "common/param_package.h" | ||||
| #include "common/settings.h" | ||||
| #include "core/core.h" | ||||
| #include "core/hle/service/cfg/cfg.h" | ||||
| #include "core/hle/service/service.h" | ||||
| #include "core/settings.h" | ||||
| #include "input_common/main.h" | ||||
| #include "input_common/udp/client.h" | ||||
| #include "jni/camera/ndk_camera.h" | ||||
|  | @ -139,9 +139,9 @@ void Config::ReadValues() { | |||
|     Settings::values.factor_3d = | ||||
|         static_cast<u8>(sdl2_config->GetInteger("Renderer", "factor_3d", 0)); | ||||
|     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)"; | ||||
|     else if (Settings::values.render_3d == Settings::StereoRenderOption::Interlaced) | ||||
|     else if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Interlaced) | ||||
|         default_shader = "horizontal (builtin)"; | ||||
|     Settings::values.pp_shader_name = | ||||
|         sdl2_config->GetString("Renderer", "pp_shader_name", default_shader); | ||||
|  | @ -186,9 +186,9 @@ void Config::ReadValues() { | |||
|         sdl2_config->GetBoolean("Utility", "preload_textures", false); | ||||
| 
 | ||||
|     // Audio
 | ||||
|     Settings::values.enable_dsp_lle = sdl2_config->GetBoolean("Audio", "enable_dsp_lle", false); | ||||
|     Settings::values.enable_dsp_lle_multithread = | ||||
|         sdl2_config->GetBoolean("Audio", "enable_dsp_lle_multithread", false); | ||||
|     Settings::values.audio_emulation = | ||||
|         static_cast<Settings::AudioEmulation>(sdl2_config->GetInteger( | ||||
|             "Audio", "audio_emulation", static_cast<int>(Settings::AudioEmulation::HLE))); | ||||
|     Settings::values.sink_id = sdl2_config->GetString("Audio", "output_engine", "auto"); | ||||
|     Settings::values.enable_audio_stretching = | ||||
|         sdl2_config->GetBoolean("Audio", "enable_audio_stretching", true); | ||||
|  |  | |||
|  | @ -11,7 +11,7 @@ | |||
| #include <glad/glad.h> | ||||
| 
 | ||||
| #include "common/logging/log.h" | ||||
| #include "core/settings.h" | ||||
| #include "common/settings.h" | ||||
| #include "input_common/main.h" | ||||
| #include "jni/emu_window/emu_window.h" | ||||
| #include "jni/id_cache.h" | ||||
|  |  | |||
|  | @ -2,7 +2,7 @@ | |||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include "core/settings.h" | ||||
| #include "common/settings.h" | ||||
| 
 | ||||
| namespace GameSettings { | ||||
| 
 | ||||
|  |  | |||
|  | @ -6,7 +6,7 @@ | |||
| #include "common/logging/backend.h" | ||||
| #include "common/logging/filter.h" | ||||
| #include "common/logging/log.h" | ||||
| #include "core/settings.h" | ||||
| #include "common/settings.h" | ||||
| #include "jni/applets/mii_selector.h" | ||||
| #include "jni/applets/swkbd.h" | ||||
| #include "jni/camera/still_image_camera.h" | ||||
|  | @ -156,7 +156,7 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved) { | |||
| 
 | ||||
|     // Initialize Logger
 | ||||
|     Log::Filter log_filter; | ||||
|     log_filter.ParseFilterString(Settings::values.log_filter); | ||||
|     log_filter.ParseFilterString(Settings::values.log_filter.GetValue()); | ||||
|     Log::SetGlobalFilter(log_filter); | ||||
|     Log::AddBackend(std::make_unique<Log::LogcatBackend>()); | ||||
|     FileUtil::CreateFullPath(FileUtil::GetUserPath(FileUtil::UserPath::LogDir)); | ||||
|  |  | |||
|  | @ -17,6 +17,7 @@ | |||
| #include "common/microprofile.h" | ||||
| #include "common/scm_rev.h" | ||||
| #include "common/scope_exit.h" | ||||
| #include "common/settings.h" | ||||
| #include "common/string_util.h" | ||||
| #include "core/core.h" | ||||
| #include "core/frontend/applets/default_applets.h" | ||||
|  | @ -26,7 +27,6 @@ | |||
| #include "core/hle/service/am/am.h" | ||||
| #include "core/hle/service/nfc/nfc.h" | ||||
| #include "core/savestate.h" | ||||
| #include "core/settings.h" | ||||
| #include "jni/android_common/android_common.h" | ||||
| #include "jni/applets/mii_selector.h" | ||||
| #include "jni/applets/swkbd.h" | ||||
|  | @ -238,7 +238,7 @@ static Core::System::ResultStatus RunCitra(const std::string& filepath) { | |||
|             } | ||||
|         } else { | ||||
|             // 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; }); | ||||
|             Settings::values.volume = 0; | ||||
| 
 | ||||
|  |  | |||
|  | @ -7,17 +7,18 @@ | |||
| #include "audio_core/sink.h" | ||||
| #include "audio_core/sink_details.h" | ||||
| #include "common/assert.h" | ||||
| #include "common/settings.h" | ||||
| #include "core/core.h" | ||||
| #include "core/dumping/backend.h" | ||||
| #include "core/settings.h" | ||||
| 
 | ||||
| namespace AudioCore { | ||||
| 
 | ||||
| DspInterface::DspInterface() = default; | ||||
| DspInterface::~DspInterface() = default; | ||||
| 
 | ||||
| void DspInterface::SetSink(const std::string& sink_id, const std::string& audio_device) { | ||||
|     sink = CreateSinkFromID(Settings::values.sink_id, Settings::values.audio_device_id); | ||||
| void DspInterface::SetSink(std::string_view sink_id, std::string_view audio_device) { | ||||
|     sink = CreateSinkFromID(Settings::values.sink_id.GetValue(), | ||||
|                             Settings::values.audio_device_id.GetValue()); | ||||
|     sink->SetCallback( | ||||
|         [this](s16* buffer, std::size_t num_frames) { OutputCallback(buffer, num_frames); }); | ||||
|     time_stretcher.SetOutputSampleRate(sink->GetNativeSampleRate()); | ||||
|  |  | |||
|  | @ -94,7 +94,7 @@ public: | |||
|     virtual void UnloadComponent() = 0; | ||||
| 
 | ||||
|     /// 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
 | ||||
|     Sink& GetSink(); | ||||
|     /// Enable/Disable audio stretching.
 | ||||
|  |  | |||
|  | @ -22,6 +22,7 @@ | |||
| #include "common/logging/log.h" | ||||
| #include "common/scm_rev.h" | ||||
| #include "common/scope_exit.h" | ||||
| #include "common/settings.h" | ||||
| #include "common/string_util.h" | ||||
| #include "core/core.h" | ||||
| #include "core/dumping/backend.h" | ||||
|  | @ -34,7 +35,6 @@ | |||
| #include "core/hle/service/cfg/cfg.h" | ||||
| #include "core/loader/loader.h" | ||||
| #include "core/movie.h" | ||||
| #include "core/settings.h" | ||||
| #include "input_common/main.h" | ||||
| #include "network/network.h" | ||||
| #include "video_core/renderer_base.h" | ||||
|  | @ -174,7 +174,7 @@ static void OnStatusMessageReceived(const Network::StatusMessageEntry& msg) { | |||
| 
 | ||||
| static void InitializeLogging() { | ||||
|     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::AddBackend(std::make_unique<Log::ColorConsoleBackend>()); | ||||
|  | @ -192,8 +192,8 @@ int main(int argc, char** argv) { | |||
|     Common::DetachedTasks detached_tasks; | ||||
|     Config config; | ||||
|     int option_index = 0; | ||||
|     bool use_gdbstub = Settings::values.use_gdbstub; | ||||
|     u32 gdb_port = static_cast<u32>(Settings::values.gdbstub_port); | ||||
|     bool use_gdbstub = Settings::values.use_gdbstub.GetValue(); | ||||
|     u32 gdb_port = static_cast<u32>(Settings::values.gdbstub_port.GetValue()); | ||||
|     std::string movie_record; | ||||
|     std::string movie_record_author; | ||||
|     std::string movie_play; | ||||
|  | @ -363,7 +363,7 @@ int main(int argc, char** argv) { | |||
|     EmuWindow_SDL2::InitializeSDL2(); | ||||
| 
 | ||||
|     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}; | ||||
|     const auto secondary_window = | ||||
|         use_secondary_window ? std::make_unique<EmuWindow_SDL2>(false, true) : nullptr; | ||||
|  |  | |||
|  | @ -13,9 +13,9 @@ | |||
| #include "common/file_util.h" | ||||
| #include "common/logging/log.h" | ||||
| #include "common/param_package.h" | ||||
| #include "common/settings.h" | ||||
| #include "core/frontend/mic.h" | ||||
| #include "core/hle/service/service.h" | ||||
| #include "core/settings.h" | ||||
| #include "input_common/main.h" | ||||
| #include "input_common/udp/client.h" | ||||
| #include "network/network_settings.h" | ||||
|  | @ -128,10 +128,6 @@ void Config::ReadValues() { | |||
|         sdl2_config->GetBoolean("Renderer", "use_disk_shader_cache", true); | ||||
|     Settings::values.frame_limit = | ||||
|         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 = | ||||
|         static_cast<u16>(sdl2_config->GetInteger("Renderer", "use_vsync_new", 1)); | ||||
|     Settings::values.texture_filter_name = | ||||
|  | @ -144,10 +140,11 @@ void Config::ReadValues() { | |||
|     Settings::values.factor_3d = | ||||
|         static_cast<u8>(sdl2_config->GetInteger("Renderer", "factor_3d", 0)); | ||||
|     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)"; | ||||
|     else if (Settings::values.render_3d == Settings::StereoRenderOption::Interlaced || | ||||
|              Settings::values.render_3d == Settings::StereoRenderOption::ReverseInterlaced) | ||||
|     else if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Interlaced || | ||||
|              Settings::values.render_3d.GetValue() == | ||||
|                  Settings::StereoRenderOption::ReverseInterlaced) | ||||
|         default_shader = "horizontal (builtin)"; | ||||
|     Settings::values.pp_shader_name = | ||||
|         sdl2_config->GetString("Renderer", "pp_shader_name", default_shader); | ||||
|  | @ -188,9 +185,8 @@ void Config::ReadValues() { | |||
|         sdl2_config->GetBoolean("Utility", "preload_textures", false); | ||||
| 
 | ||||
|     // Audio
 | ||||
|     Settings::values.enable_dsp_lle = sdl2_config->GetBoolean("Audio", "enable_dsp_lle", false); | ||||
|     Settings::values.enable_dsp_lle_multithread = | ||||
|         sdl2_config->GetBoolean("Audio", "enable_dsp_lle_multithread", false); | ||||
|     Settings::values.audio_emulation = static_cast<Settings::AudioEmulation>( | ||||
|         sdl2_config->GetInteger("Audio", "audio_emulation", 0)); | ||||
|     Settings::values.sink_id = sdl2_config->GetString("Audio", "output_engine", "auto"); | ||||
|     Settings::values.enable_audio_stretching = | ||||
|         sdl2_config->GetBoolean("Audio", "enable_audio_stretching", true); | ||||
|  |  | |||
|  | @ -12,9 +12,9 @@ | |||
| #include "citra/emu_window/emu_window_sdl2.h" | ||||
| #include "common/logging/log.h" | ||||
| #include "common/scm_rev.h" | ||||
| #include "common/settings.h" | ||||
| #include "core/3ds.h" | ||||
| #include "core/core.h" | ||||
| #include "core/settings.h" | ||||
| #include "input_common/keyboard.h" | ||||
| #include "input_common/main.h" | ||||
| #include "input_common/motion_emu.h" | ||||
|  |  | |||
|  | @ -38,6 +38,8 @@ add_executable(citra-qt | |||
|     configuration/config.cpp | ||||
|     configuration/config.h | ||||
|     configuration/configure.ui | ||||
|     configuration/configuration_shared.cpp | ||||
|     configuration/configuration_shared.h | ||||
|     configuration/configure_audio.cpp | ||||
|     configuration/configure_audio.h | ||||
|     configuration/configure_audio.ui | ||||
|  | @ -67,6 +69,9 @@ add_executable(citra-qt | |||
|     configuration/configure_motion_touch.cpp | ||||
|     configuration/configure_motion_touch.h | ||||
|     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.h | ||||
|     configuration/configure_storage.ui | ||||
|  |  | |||
|  | @ -15,11 +15,11 @@ | |||
| #include "citra_qt/main.h" | ||||
| #include "common/microprofile.h" | ||||
| #include "common/scm_rev.h" | ||||
| #include "common/settings.h" | ||||
| #include "core/3ds.h" | ||||
| #include "core/core.h" | ||||
| #include "core/frontend/scope_acquire_context.h" | ||||
| #include "core/perf_stats.h" | ||||
| #include "core/settings.h" | ||||
| #include "input_common/keyboard.h" | ||||
| #include "input_common/main.h" | ||||
| #include "input_common/motion_emu.h" | ||||
|  |  | |||
|  | @ -17,17 +17,15 @@ | |||
| #include "network/network.h" | ||||
| #include "network/network_settings.h" | ||||
| 
 | ||||
| Config::Config() { | ||||
|     // TODO: Don't hardcode the path; let the frontend decide where to put the config files.
 | ||||
|     qt_config_loc = FileUtil::GetUserPath(FileUtil::UserPath::ConfigDir) + "qt-config.ini"; | ||||
|     FileUtil::CreateFullPath(qt_config_loc); | ||||
|     qt_config = | ||||
|         std::make_unique<QSettings>(QString::fromStdString(qt_config_loc), QSettings::IniFormat); | ||||
|     Reload(); | ||||
| Config::Config(const std::string& config_name, ConfigType config_type) : type{config_type} { | ||||
|     global = config_type == ConfigType::GlobalConfig; | ||||
|     Initialize(config_name); | ||||
| } | ||||
| 
 | ||||
| Config::~Config() { | ||||
|     if (global) { | ||||
|         Save(); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| const std::array<int, Settings::NativeButton::NumButtons> Config::default_buttons = { | ||||
|  | @ -85,46 +83,176 @@ const std::array<UISettings::Shortcut, 24> default_hotkeys{ | |||
|      {QStringLiteral("Toggle Texture Dumping"),   QStringLiteral("Main Window"), {QStringLiteral("Ctrl+D"), Qt::ApplicationShortcut}}}}; | ||||
| // clang-format on
 | ||||
| 
 | ||||
| void Config::Initialize(const std::string& config_name) { | ||||
|     const std::string fs_config_loc = FileUtil::GetUserPath(FileUtil::UserPath::ConfigDir); | ||||
|     const std::string config_file = fmt::format("{}.ini", config_name); | ||||
| 
 | ||||
|     switch (type) { | ||||
|     case ConfigType::GlobalConfig: | ||||
|         qt_config_loc = fmt::format("{}/{}", fs_config_loc, config_file); | ||||
|         break; | ||||
|     case ConfigType::PerGameConfig: | ||||
|         qt_config_loc = fmt::format("{}/custom/{}", fs_config_loc, config_file); | ||||
|         break; | ||||
|     } | ||||
| 
 | ||||
|     FileUtil::CreateFullPath(qt_config_loc); | ||||
|     qt_config = | ||||
|         std::make_unique<QSettings>(QString::fromStdString(qt_config_loc), QSettings::IniFormat); | ||||
|     Reload(); | ||||
| } | ||||
| 
 | ||||
| /* {Read,Write}BasicSetting and WriteGlobalSetting templates must be defined here before their
 | ||||
|  * usages later in this file. This allows explicit definition of some types that don't work | ||||
|  * nicely with the general version. | ||||
|  */ | ||||
| 
 | ||||
| // Explicit std::string definition: Qt can't implicitly convert a std::string to a QVariant, nor
 | ||||
| // can it implicitly convert a QVariant back to a {std::,Q}string
 | ||||
| template <> | ||||
| void Config::ReadBasicSetting(Settings::Setting<std::string>& setting) { | ||||
|     const QString name = QString::fromStdString(setting.GetLabel()); | ||||
|     const auto default_value = QString::fromStdString(setting.GetDefault()); | ||||
|     if (qt_config->value(name + QStringLiteral("/default"), false).toBool()) { | ||||
|         setting.SetValue(default_value.toStdString()); | ||||
|     } else { | ||||
|         setting.SetValue(qt_config->value(name, default_value).toString().toStdString()); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| template <typename Type, bool ranged> | ||||
| void Config::ReadBasicSetting(Settings::Setting<Type, ranged>& setting) { | ||||
|     const QString name = QString::fromStdString(setting.GetLabel()); | ||||
|     const Type default_value = setting.GetDefault(); | ||||
|     if (qt_config->value(name + QStringLiteral("/default"), false).toBool()) { | ||||
|         setting.SetValue(default_value); | ||||
|     } else { | ||||
|         QVariant value{}; | ||||
|         if constexpr (std::is_enum_v<Type>) { | ||||
|             using TypeU = std::underlying_type_t<Type>; | ||||
|             value = qt_config->value(name, static_cast<TypeU>(default_value)); | ||||
|             setting.SetValue(static_cast<Type>(value.value<TypeU>())); | ||||
|         } else { | ||||
|             value = qt_config->value(name, QVariant::fromValue(default_value)); | ||||
|             setting.SetValue(value.value<Type>()); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| template <typename Type, bool ranged> | ||||
| void Config::ReadGlobalSetting(Settings::SwitchableSetting<Type, ranged>& setting) { | ||||
|     QString name = QString::fromStdString(setting.GetLabel()); | ||||
|     const bool use_global = qt_config->value(name + QStringLiteral("/use_global"), true).toBool(); | ||||
|     setting.SetGlobal(use_global); | ||||
|     if (global || !use_global) { | ||||
|         QVariant value{}; | ||||
|         if constexpr (std::is_enum_v<Type>) { | ||||
|             using TypeU = std::underlying_type_t<Type>; | ||||
|             value = QVariant::fromValue<TypeU>(static_cast<TypeU>(setting.GetDefault())); | ||||
|             setting.SetValue(static_cast<Type>(ReadSetting(name, value).value<TypeU>())); | ||||
|         } else { | ||||
|             value = QVariant::fromValue<Type>(setting.GetDefault()); | ||||
|             setting.SetValue(ReadSetting(name, value).value<Type>()); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| template <> | ||||
| void Config::ReadGlobalSetting(Settings::SwitchableSetting<std::string>& setting) { | ||||
|     QString name = QString::fromStdString(setting.GetLabel()); | ||||
|     const bool use_global = qt_config->value(name + QStringLiteral("/use_global"), true).toBool(); | ||||
|     setting.SetGlobal(use_global); | ||||
|     if (global || !use_global) { | ||||
|         const QString default_value = QString::fromStdString(setting.GetDefault()); | ||||
|         setting.SetValue( | ||||
|             ReadSetting(name, QVariant::fromValue(default_value)).toString().toStdString()); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| // Explicit std::string definition: Qt can't implicitly convert a std::string to a QVariant
 | ||||
| template <> | ||||
| void Config::WriteBasicSetting(const Settings::Setting<std::string>& setting) { | ||||
|     const QString name = QString::fromStdString(setting.GetLabel()); | ||||
|     const std::string& value = setting.GetValue(); | ||||
|     qt_config->setValue(name + QStringLiteral("/default"), value == setting.GetDefault()); | ||||
|     qt_config->setValue(name, QString::fromStdString(value)); | ||||
| } | ||||
| 
 | ||||
| template <typename Type, bool ranged> | ||||
| void Config::WriteBasicSetting(const Settings::Setting<Type, ranged>& setting) { | ||||
|     const QString name = QString::fromStdString(setting.GetLabel()); | ||||
|     const Type value = setting.GetValue(); | ||||
|     qt_config->setValue(name + QStringLiteral("/default"), value == setting.GetDefault()); | ||||
|     if constexpr (std::is_enum_v<Type>) { | ||||
|         qt_config->setValue(name, static_cast<std::underlying_type_t<Type>>(value)); | ||||
|     } else { | ||||
|         qt_config->setValue(name, QVariant::fromValue(value)); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| template <typename Type, bool ranged> | ||||
| void Config::WriteGlobalSetting(const Settings::SwitchableSetting<Type, ranged>& setting) { | ||||
|     const QString name = QString::fromStdString(setting.GetLabel()); | ||||
|     const Type& value = setting.GetValue(global); | ||||
|     if (!global) { | ||||
|         qt_config->setValue(name + QStringLiteral("/use_global"), setting.UsingGlobal()); | ||||
|     } | ||||
|     if (global || !setting.UsingGlobal()) { | ||||
|         qt_config->setValue(name + QStringLiteral("/default"), value == setting.GetDefault()); | ||||
|         if constexpr (std::is_enum_v<Type>) { | ||||
|             qt_config->setValue(name, static_cast<std::underlying_type_t<Type>>(value)); | ||||
|         } else { | ||||
|             qt_config->setValue(name, QVariant::fromValue(value)); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| template <> | ||||
| void Config::WriteGlobalSetting(const Settings::SwitchableSetting<std::string>& setting) { | ||||
|     const QString name = QString::fromStdString(setting.GetLabel()); | ||||
|     const std::string& value = setting.GetValue(global); | ||||
|     if (!global) { | ||||
|         qt_config->setValue(name + QStringLiteral("/use_global"), setting.UsingGlobal()); | ||||
|     } | ||||
|     if (global || !setting.UsingGlobal()) { | ||||
|         qt_config->setValue(name + QStringLiteral("/default"), value == setting.GetDefault()); | ||||
|         qt_config->setValue(name, QString::fromStdString(value)); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void Config::ReadValues() { | ||||
|     if (global) { | ||||
|         ReadControlValues(); | ||||
|     ReadCoreValues(); | ||||
|     ReadRendererValues(); | ||||
|     ReadLayoutValues(); | ||||
|     ReadAudioValues(); | ||||
|         ReadCameraValues(); | ||||
|         ReadDataStorageValues(); | ||||
|     ReadSystemValues(); | ||||
|         ReadMiscellaneousValues(); | ||||
|         ReadDebuggingValues(); | ||||
|         ReadWebServiceValues(); | ||||
|         ReadVideoDumpingValues(); | ||||
|     ReadUIValues(); | ||||
|         ReadUtilityValues(); | ||||
|     } | ||||
| 
 | ||||
|     ReadUIValues(); | ||||
|     ReadCoreValues(); | ||||
|     ReadRendererValues(); | ||||
|     ReadLayoutValues(); | ||||
|     ReadAudioValues(); | ||||
|     ReadSystemValues(); | ||||
| } | ||||
| 
 | ||||
| void Config::ReadAudioValues() { | ||||
|     qt_config->beginGroup(QStringLiteral("Audio")); | ||||
| 
 | ||||
|     Settings::values.enable_dsp_lle = ReadSetting(QStringLiteral("enable_dsp_lle"), false).toBool(); | ||||
|     Settings::values.enable_dsp_lle_multithread = | ||||
|         ReadSetting(QStringLiteral("enable_dsp_lle_multithread"), false).toBool(); | ||||
|     Settings::values.sink_id = ReadSetting(QStringLiteral("output_engine"), QStringLiteral("auto")) | ||||
|                                    .toString() | ||||
|                                    .toStdString(); | ||||
|     Settings::values.enable_audio_stretching = | ||||
|         ReadSetting(QStringLiteral("enable_audio_stretching"), true).toBool(); | ||||
|     Settings::values.audio_device_id = | ||||
|         ReadSetting(QStringLiteral("output_device"), QStringLiteral("auto")) | ||||
|             .toString() | ||||
|             .toStdString(); | ||||
|     Settings::values.volume = ReadSetting(QStringLiteral("volume"), 1).toFloat(); | ||||
|     Settings::values.mic_input_type = static_cast<Settings::MicInputType>( | ||||
|         ReadSetting(QStringLiteral("mic_input_type"), 0).toInt()); | ||||
|     Settings::values.mic_input_device = | ||||
|         ReadSetting(QStringLiteral("mic_input_device"), | ||||
|                     QString::fromUtf8(Frontend::Mic::default_device_name)) | ||||
|             .toString() | ||||
|             .toStdString(); | ||||
|     ReadGlobalSetting(Settings::values.audio_emulation); | ||||
|     ReadGlobalSetting(Settings::values.enable_audio_stretching); | ||||
|     ReadGlobalSetting(Settings::values.volume); | ||||
| 
 | ||||
|     if (global) { | ||||
|         ReadBasicSetting(Settings::values.sink_id); | ||||
|         ReadBasicSetting(Settings::values.audio_device_id); | ||||
|         ReadBasicSetting(Settings::values.mic_input_device); | ||||
|         ReadBasicSetting(Settings::values.mic_input_type); | ||||
|     } | ||||
| 
 | ||||
|     qt_config->endGroup(); | ||||
| } | ||||
|  | @ -281,11 +409,9 @@ void Config::ReadControlValues() { | |||
| void Config::ReadUtilityValues() { | ||||
|     qt_config->beginGroup(QStringLiteral("Utility")); | ||||
| 
 | ||||
|     Settings::values.dump_textures = ReadSetting(QStringLiteral("dump_textures"), false).toBool(); | ||||
|     Settings::values.custom_textures = | ||||
|         ReadSetting(QStringLiteral("custom_textures"), false).toBool(); | ||||
|     Settings::values.preload_textures = | ||||
|         ReadSetting(QStringLiteral("preload_textures"), false).toBool(); | ||||
|     ReadBasicSetting(Settings::values.dump_textures); | ||||
|     ReadBasicSetting(Settings::values.custom_textures); | ||||
|     ReadBasicSetting(Settings::values.preload_textures); | ||||
| 
 | ||||
|     qt_config->endGroup(); | ||||
| } | ||||
|  | @ -293,9 +419,11 @@ void Config::ReadUtilityValues() { | |||
| void Config::ReadCoreValues() { | ||||
|     qt_config->beginGroup(QStringLiteral("Core")); | ||||
| 
 | ||||
|     Settings::values.use_cpu_jit = ReadSetting(QStringLiteral("use_cpu_jit"), true).toBool(); | ||||
|     Settings::values.cpu_clock_percentage = | ||||
|         ReadSetting(QStringLiteral("cpu_clock_percentage"), 100).toInt(); | ||||
|     ReadGlobalSetting(Settings::values.cpu_clock_percentage); | ||||
| 
 | ||||
|     if (global) { | ||||
|         ReadBasicSetting(Settings::values.use_cpu_jit); | ||||
|     } | ||||
| 
 | ||||
|     qt_config->endGroup(); | ||||
| } | ||||
|  | @ -303,10 +431,9 @@ void Config::ReadCoreValues() { | |||
| void Config::ReadDataStorageValues() { | ||||
|     qt_config->beginGroup(QStringLiteral("Data Storage")); | ||||
| 
 | ||||
|     Settings::values.use_virtual_sd = ReadSetting(QStringLiteral("use_virtual_sd"), true).toBool(); | ||||
|     ReadBasicSetting(Settings::values.use_virtual_sd); | ||||
|     ReadBasicSetting(Settings::values.use_custom_storage); | ||||
| 
 | ||||
|     Settings::values.use_custom_storage = | ||||
|         ReadSetting(QStringLiteral("use_custom_storage"), false).toBool(); | ||||
|     const std::string nand_dir = | ||||
|         ReadSetting(QStringLiteral("nand_directory"), QStringLiteral("")).toString().toStdString(); | ||||
|     const std::string sdmc_dir = | ||||
|  | @ -326,8 +453,8 @@ void Config::ReadDebuggingValues() { | |||
|     // Intentionally not using the QT default setting as this is intended to be changed in the ini
 | ||||
|     Settings::values.record_frame_times = | ||||
|         qt_config->value(QStringLiteral("record_frame_times"), false).toBool(); | ||||
|     Settings::values.use_gdbstub = ReadSetting(QStringLiteral("use_gdbstub"), false).toBool(); | ||||
|     Settings::values.gdbstub_port = ReadSetting(QStringLiteral("gdbstub_port"), 24689).toInt(); | ||||
|     ReadBasicSetting(Settings::values.use_gdbstub); | ||||
|     ReadBasicSetting(Settings::values.gdbstub_port); | ||||
| 
 | ||||
|     qt_config->beginGroup(QStringLiteral("LLE")); | ||||
|     for (const auto& service_module : Service::service_module_map) { | ||||
|  | @ -335,45 +462,38 @@ void Config::ReadDebuggingValues() { | |||
|         Settings::values.lle_modules.emplace(service_module.name, use_lle); | ||||
|     } | ||||
|     qt_config->endGroup(); | ||||
| 
 | ||||
|     qt_config->endGroup(); | ||||
| } | ||||
| 
 | ||||
| void Config::ReadLayoutValues() { | ||||
|     qt_config->beginGroup(QStringLiteral("Layout")); | ||||
| 
 | ||||
|     Settings::values.render_3d = static_cast<Settings::StereoRenderOption>( | ||||
|         ReadSetting(QStringLiteral("render_3d"), 0).toInt()); | ||||
|     Settings::values.factor_3d = ReadSetting(QStringLiteral("factor_3d"), 0).toInt(); | ||||
|     Settings::values.mono_render_left_eye = | ||||
|         ReadSetting(QStringLiteral("mono_render_left_eye"), true).toBool(); | ||||
|     ReadGlobalSetting(Settings::values.render_3d); | ||||
|     ReadGlobalSetting(Settings::values.factor_3d); | ||||
|     Settings::values.pp_shader_name = | ||||
|         ReadSetting(QStringLiteral("pp_shader_name"), | ||||
|                     (Settings::values.render_3d == Settings::StereoRenderOption::Anaglyph) | ||||
|         ReadSetting(QStringLiteral("pp_shader_name"), (Settings::values.render_3d.GetValue() == | ||||
|                                                        Settings::StereoRenderOption::Anaglyph) | ||||
|                                                           ? QStringLiteral("dubois (builtin)") | ||||
|                                                           : QStringLiteral("none (builtin)")) | ||||
|             .toString() | ||||
|             .toStdString(); | ||||
|     Settings::values.filter_mode = ReadSetting(QStringLiteral("filter_mode"), true).toBool(); | ||||
|     Settings::values.layout_option = | ||||
|         static_cast<Settings::LayoutOption>(ReadSetting(QStringLiteral("layout_option")).toInt()); | ||||
|     Settings::values.swap_screen = ReadSetting(QStringLiteral("swap_screen"), false).toBool(); | ||||
|     Settings::values.upright_screen = ReadSetting(QStringLiteral("upright_screen"), false).toBool(); | ||||
|     Settings::values.custom_layout = ReadSetting(QStringLiteral("custom_layout"), false).toBool(); | ||||
|     Settings::values.custom_top_left = ReadSetting(QStringLiteral("custom_top_left"), 0).toInt(); | ||||
|     Settings::values.custom_top_top = ReadSetting(QStringLiteral("custom_top_top"), 0).toInt(); | ||||
|     Settings::values.custom_top_right = | ||||
|         ReadSetting(QStringLiteral("custom_top_right"), 400).toInt(); | ||||
|     Settings::values.custom_top_bottom = | ||||
|         ReadSetting(QStringLiteral("custom_top_bottom"), 240).toInt(); | ||||
|     Settings::values.custom_bottom_left = | ||||
|         ReadSetting(QStringLiteral("custom_bottom_left"), 40).toInt(); | ||||
|     Settings::values.custom_bottom_top = | ||||
|         ReadSetting(QStringLiteral("custom_bottom_top"), 240).toInt(); | ||||
|     Settings::values.custom_bottom_right = | ||||
|         ReadSetting(QStringLiteral("custom_bottom_right"), 360).toInt(); | ||||
|     Settings::values.custom_bottom_bottom = | ||||
|         ReadSetting(QStringLiteral("custom_bottom_bottom"), 480).toInt(); | ||||
|     ReadGlobalSetting(Settings::values.filter_mode); | ||||
|     ReadGlobalSetting(Settings::values.layout_option); | ||||
|     ReadGlobalSetting(Settings::values.swap_screen); | ||||
|     ReadGlobalSetting(Settings::values.upright_screen); | ||||
| 
 | ||||
|     if (global) { | ||||
|         ReadBasicSetting(Settings::values.mono_render_left_eye); | ||||
|         ReadBasicSetting(Settings::values.custom_layout); | ||||
|         ReadBasicSetting(Settings::values.custom_top_left); | ||||
|         ReadBasicSetting(Settings::values.custom_top_top); | ||||
|         ReadBasicSetting(Settings::values.custom_top_right); | ||||
|         ReadBasicSetting(Settings::values.custom_top_bottom); | ||||
|         ReadBasicSetting(Settings::values.custom_bottom_left); | ||||
|         ReadBasicSetting(Settings::values.custom_bottom_top); | ||||
|         ReadBasicSetting(Settings::values.custom_bottom_right); | ||||
|         ReadBasicSetting(Settings::values.custom_bottom_bottom); | ||||
|     } | ||||
| 
 | ||||
|     qt_config->endGroup(); | ||||
| } | ||||
|  | @ -381,10 +501,7 @@ void Config::ReadLayoutValues() { | |||
| void Config::ReadMiscellaneousValues() { | ||||
|     qt_config->beginGroup(QStringLiteral("Miscellaneous")); | ||||
| 
 | ||||
|     Settings::values.log_filter = | ||||
|         ReadSetting(QStringLiteral("log_filter"), QStringLiteral("*:Info")) | ||||
|             .toString() | ||||
|             .toStdString(); | ||||
|     ReadBasicSetting(Settings::values.log_filter); | ||||
| 
 | ||||
|     qt_config->endGroup(); | ||||
| } | ||||
|  | @ -434,13 +551,15 @@ void Config::ReadMultiplayerValues() { | |||
| void Config::ReadPathValues() { | ||||
|     qt_config->beginGroup(QStringLiteral("Paths")); | ||||
| 
 | ||||
|     ReadGlobalSetting(UISettings::values.screenshot_path); | ||||
| 
 | ||||
|     if (global) { | ||||
|         UISettings::values.roms_path = ReadSetting(QStringLiteral("romsPath")).toString(); | ||||
|         UISettings::values.symbols_path = ReadSetting(QStringLiteral("symbolsPath")).toString(); | ||||
|         UISettings::values.movie_record_path = | ||||
|             ReadSetting(QStringLiteral("movieRecordPath")).toString(); | ||||
|         UISettings::values.movie_playback_path = | ||||
|             ReadSetting(QStringLiteral("moviePlaybackPath")).toString(); | ||||
|     UISettings::values.screenshot_path = ReadSetting(QStringLiteral("screenshotPath")).toString(); | ||||
|         UISettings::values.video_dumping_path = | ||||
|             ReadSetting(QStringLiteral("videoDumpingPath")).toString(); | ||||
|         UISettings::values.game_dir_deprecated = | ||||
|  | @ -474,6 +593,7 @@ void Config::ReadPathValues() { | |||
|         } | ||||
|         UISettings::values.recent_files = ReadSetting(QStringLiteral("recentFiles")).toStringList(); | ||||
|         UISettings::values.language = ReadSetting(QStringLiteral("language"), QString{}).toString(); | ||||
|     } | ||||
| 
 | ||||
|     qt_config->endGroup(); | ||||
| } | ||||
|  | @ -481,38 +601,29 @@ void Config::ReadPathValues() { | |||
| void Config::ReadRendererValues() { | ||||
|     qt_config->beginGroup(QStringLiteral("Renderer")); | ||||
| 
 | ||||
|     Settings::values.use_hw_renderer = | ||||
|         ReadSetting(QStringLiteral("use_hw_renderer"), true).toBool(); | ||||
|     Settings::values.use_hw_shader = ReadSetting(QStringLiteral("use_hw_shader"), true).toBool(); | ||||
|     ReadGlobalSetting(Settings::values.use_hw_renderer); | ||||
|     ReadGlobalSetting(Settings::values.use_hw_shader); | ||||
| #ifdef __APPLE__ | ||||
|     // Hardware shader is broken on macos with Intel GPUs thanks to poor drivers.
 | ||||
|     // We still want to provide this option for test/development purposes, but disable it by
 | ||||
|     // default.
 | ||||
|     Settings::values.separable_shader = | ||||
|         ReadSetting(QStringLiteral("separable_shader"), false).toBool(); | ||||
|     ReadGlobalSetting(Settings::values.separable_shader); | ||||
| #endif | ||||
|     Settings::values.shaders_accurate_mul = | ||||
|         ReadSetting(QStringLiteral("shaders_accurate_mul"), true).toBool(); | ||||
|     Settings::values.use_shader_jit = ReadSetting(QStringLiteral("use_shader_jit"), true).toBool(); | ||||
|     Settings::values.use_disk_shader_cache = | ||||
|         ReadSetting(QStringLiteral("use_disk_shader_cache"), true).toBool(); | ||||
|     Settings::values.use_vsync_new = ReadSetting(QStringLiteral("use_vsync_new"), true).toBool(); | ||||
|     Settings::values.resolution_factor = | ||||
|         static_cast<u16>(ReadSetting(QStringLiteral("resolution_factor"), 1).toInt()); | ||||
|     Settings::values.frame_limit = ReadSetting(QStringLiteral("frame_limit"), 100).toInt(); | ||||
|     Settings::values.use_frame_limit_alternate = | ||||
|         ReadSetting(QStringLiteral("use_frame_limit_alternate"), false).toBool(); | ||||
|     Settings::values.frame_limit_alternate = | ||||
|         ReadSetting(QStringLiteral("frame_limit_alternate"), 200).toInt(); | ||||
|     ReadGlobalSetting(Settings::values.shaders_accurate_mul); | ||||
|     ReadGlobalSetting(Settings::values.use_disk_shader_cache); | ||||
|     ReadGlobalSetting(Settings::values.use_vsync_new); | ||||
|     ReadGlobalSetting(Settings::values.resolution_factor); | ||||
|     ReadGlobalSetting(Settings::values.frame_limit); | ||||
| 
 | ||||
|     Settings::values.bg_red = ReadSetting(QStringLiteral("bg_red"), 0.0).toFloat(); | ||||
|     Settings::values.bg_green = ReadSetting(QStringLiteral("bg_green"), 0.0).toFloat(); | ||||
|     Settings::values.bg_blue = ReadSetting(QStringLiteral("bg_blue"), 0.0).toFloat(); | ||||
|     ReadGlobalSetting(Settings::values.bg_red); | ||||
|     ReadGlobalSetting(Settings::values.bg_green); | ||||
|     ReadGlobalSetting(Settings::values.bg_blue); | ||||
| 
 | ||||
|     Settings::values.texture_filter_name = | ||||
|         ReadSetting(QStringLiteral("texture_filter_name"), QStringLiteral("none")) | ||||
|             .toString() | ||||
|             .toStdString(); | ||||
|     ReadGlobalSetting(Settings::values.texture_filter_name); | ||||
| 
 | ||||
|     if (global) { | ||||
|         ReadBasicSetting(Settings::values.use_shader_jit); | ||||
|     } | ||||
| 
 | ||||
|     qt_config->endGroup(); | ||||
| } | ||||
|  | @ -539,16 +650,14 @@ void Config::ReadShortcutValues() { | |||
| void Config::ReadSystemValues() { | ||||
|     qt_config->beginGroup(QStringLiteral("System")); | ||||
| 
 | ||||
|     Settings::values.is_new_3ds = ReadSetting(QStringLiteral("is_new_3ds"), true).toBool(); | ||||
|     Settings::values.region_value = | ||||
|         ReadSetting(QStringLiteral("region_value"), Settings::REGION_VALUE_AUTO_SELECT).toInt(); | ||||
|     Settings::values.init_clock = static_cast<Settings::InitClock>( | ||||
|         ReadSetting(QStringLiteral("init_clock"), static_cast<u32>(Settings::InitClock::SystemTime)) | ||||
|             .toInt()); | ||||
|     Settings::values.init_time = | ||||
|         ReadSetting(QStringLiteral("init_time"), 946681277ULL).toULongLong(); | ||||
|     Settings::values.init_time_offset = | ||||
|         ReadSetting(QStringLiteral("init_time_offset"), 0LL).toLongLong(); | ||||
|     ReadGlobalSetting(Settings::values.is_new_3ds); | ||||
|     ReadGlobalSetting(Settings::values.region_value); | ||||
| 
 | ||||
|     if (global) { | ||||
|         ReadBasicSetting(Settings::values.init_clock); | ||||
|         ReadBasicSetting(Settings::values.init_time); | ||||
|         ReadBasicSetting(Settings::values.init_time_offset); | ||||
|     } | ||||
| 
 | ||||
|     qt_config->endGroup(); | ||||
| } | ||||
|  | @ -599,39 +708,33 @@ void Config::ReadVideoDumpingValues() { | |||
| void Config::ReadUIValues() { | ||||
|     qt_config->beginGroup(QStringLiteral("UI")); | ||||
| 
 | ||||
|     ReadPathValues(); | ||||
| 
 | ||||
|     if (global) { | ||||
|         UISettings::values.theme = | ||||
|             ReadSetting(QStringLiteral("theme"), QString::fromUtf8(UISettings::themes[0].second)) | ||||
|                 .toString(); | ||||
|     UISettings::values.enable_discord_presence = | ||||
|         ReadSetting(QStringLiteral("enable_discord_presence"), true).toBool(); | ||||
|     UISettings::values.screenshot_resolution_factor = | ||||
|         static_cast<u16>(ReadSetting(QStringLiteral("screenshot_resolution_factor"), 0).toUInt()); | ||||
|         ReadBasicSetting(UISettings::values.enable_discord_presence); | ||||
|         ReadBasicSetting(UISettings::values.screenshot_resolution_factor); | ||||
| 
 | ||||
|         ReadUpdaterValues(); | ||||
|         ReadUILayoutValues(); | ||||
|         ReadUIGameListValues(); | ||||
|     ReadPathValues(); | ||||
|         ReadShortcutValues(); | ||||
|         ReadMultiplayerValues(); | ||||
| 
 | ||||
|     UISettings::values.single_window_mode = | ||||
|         ReadSetting(QStringLiteral("singleWindowMode"), true).toBool(); | ||||
|     UISettings::values.fullscreen = ReadSetting(QStringLiteral("fullscreen"), false).toBool(); | ||||
|     UISettings::values.display_titlebar = | ||||
|         ReadSetting(QStringLiteral("displayTitleBars"), true).toBool(); | ||||
|     UISettings::values.show_filter_bar = | ||||
|         ReadSetting(QStringLiteral("showFilterBar"), true).toBool(); | ||||
|     UISettings::values.show_status_bar = | ||||
|         ReadSetting(QStringLiteral("showStatusBar"), true).toBool(); | ||||
|     UISettings::values.confirm_before_closing = | ||||
|         ReadSetting(QStringLiteral("confirmClose"), true).toBool(); | ||||
|     UISettings::values.first_start = ReadSetting(QStringLiteral("firstStart"), true).toBool(); | ||||
|     UISettings::values.callout_flags = ReadSetting(QStringLiteral("calloutFlags"), 0).toUInt(); | ||||
|     UISettings::values.show_console = ReadSetting(QStringLiteral("showConsole"), false).toBool(); | ||||
|     UISettings::values.pause_when_in_background = | ||||
|         ReadSetting(QStringLiteral("pauseWhenInBackground"), false).toBool(); | ||||
|     UISettings::values.hide_mouse = | ||||
|         ReadSetting(QStringLiteral("hideInactiveMouse"), false).toBool(); | ||||
|         ReadBasicSetting(UISettings::values.single_window_mode); | ||||
|         ReadBasicSetting(UISettings::values.fullscreen); | ||||
|         ReadBasicSetting(UISettings::values.display_titlebar); | ||||
|         ReadBasicSetting(UISettings::values.show_filter_bar); | ||||
|         ReadBasicSetting(UISettings::values.show_status_bar); | ||||
|         ReadBasicSetting(UISettings::values.confirm_before_closing); | ||||
|         ReadBasicSetting(UISettings::values.first_start); | ||||
|         ReadBasicSetting(UISettings::values.callout_flags); | ||||
|         ReadBasicSetting(UISettings::values.show_console); | ||||
|         ReadBasicSetting(UISettings::values.pause_when_in_background); | ||||
|         ReadBasicSetting(UISettings::values.hide_mouse); | ||||
|     } | ||||
| 
 | ||||
|     qt_config->endGroup(); | ||||
| } | ||||
|  | @ -639,36 +742,11 @@ void Config::ReadUIValues() { | |||
| void Config::ReadUIGameListValues() { | ||||
|     qt_config->beginGroup(QStringLiteral("GameList")); | ||||
| 
 | ||||
|     auto icon_size = UISettings::GameListIconSize{ | ||||
|         ReadSetting(QStringLiteral("iconSize"), | ||||
|                     static_cast<int>(UISettings::GameListIconSize::LargeIcon)) | ||||
|             .toInt()}; | ||||
|     if (icon_size < UISettings::GameListIconSize::NoIcon || | ||||
|         icon_size > UISettings::GameListIconSize::LargeIcon) { | ||||
|         icon_size = UISettings::GameListIconSize::LargeIcon; | ||||
|     } | ||||
|     UISettings::values.game_list_icon_size = icon_size; | ||||
| 
 | ||||
|     UISettings::GameListText row_1 = UISettings::GameListText{ | ||||
|         ReadSetting(QStringLiteral("row1"), static_cast<int>(UISettings::GameListText::TitleName)) | ||||
|             .toInt()}; | ||||
|     if (row_1 <= UISettings::GameListText::NoText || row_1 >= UISettings::GameListText::ListEnd) { | ||||
|         row_1 = UISettings::GameListText::TitleName; | ||||
|     } | ||||
|     UISettings::values.game_list_row_1 = row_1; | ||||
| 
 | ||||
|     UISettings::GameListText row_2 = UISettings::GameListText{ | ||||
|         ReadSetting(QStringLiteral("row2"), static_cast<int>(UISettings::GameListText::FileName)) | ||||
|             .toInt()}; | ||||
|     if (row_2 < UISettings::GameListText::NoText || row_2 >= UISettings::GameListText::ListEnd) { | ||||
|         row_2 = UISettings::GameListText::FileName; | ||||
|     } | ||||
|     UISettings::values.game_list_row_2 = row_2; | ||||
| 
 | ||||
|     UISettings::values.game_list_hide_no_icon = | ||||
|         ReadSetting(QStringLiteral("hideNoIcon"), false).toBool(); | ||||
|     UISettings::values.game_list_single_line_mode = | ||||
|         ReadSetting(QStringLiteral("singleLineMode"), false).toBool(); | ||||
|     ReadBasicSetting(UISettings::values.game_list_icon_size); | ||||
|     ReadBasicSetting(UISettings::values.game_list_row_1); | ||||
|     ReadBasicSetting(UISettings::values.game_list_row_2); | ||||
|     ReadBasicSetting(UISettings::values.game_list_hide_no_icon); | ||||
|     ReadBasicSetting(UISettings::values.game_list_single_line_mode); | ||||
| 
 | ||||
|     qt_config->endGroup(); | ||||
| } | ||||
|  | @ -684,8 +762,7 @@ void Config::ReadUILayoutValues() { | |||
|         ReadSetting(QStringLiteral("gameListHeaderState")).toByteArray(); | ||||
|     UISettings::values.microprofile_geometry = | ||||
|         ReadSetting(QStringLiteral("microProfileDialogGeometry")).toByteArray(); | ||||
|     UISettings::values.microprofile_visible = | ||||
|         ReadSetting(QStringLiteral("microProfileDialogVisible"), false).toBool(); | ||||
|     ReadBasicSetting(UISettings::values.microprofile_visible); | ||||
| 
 | ||||
|     qt_config->endGroup(); | ||||
| } | ||||
|  | @ -693,10 +770,8 @@ void Config::ReadUILayoutValues() { | |||
| void Config::ReadUpdaterValues() { | ||||
|     qt_config->beginGroup(QStringLiteral("Updater")); | ||||
| 
 | ||||
|     UISettings::values.check_for_update_on_start = | ||||
|         ReadSetting(QStringLiteral("check_for_update_on_start"), true).toBool(); | ||||
|     UISettings::values.update_on_close = | ||||
|         ReadSetting(QStringLiteral("update_on_close"), false).toBool(); | ||||
|     ReadBasicSetting(UISettings::values.check_for_update_on_start); | ||||
|     ReadBasicSetting(UISettings::values.update_on_close); | ||||
| 
 | ||||
|     qt_config->endGroup(); | ||||
| } | ||||
|  | @ -719,40 +794,38 @@ void Config::ReadWebServiceValues() { | |||
| } | ||||
| 
 | ||||
| void Config::SaveValues() { | ||||
|     if (global) { | ||||
|         SaveControlValues(); | ||||
|     SaveCoreValues(); | ||||
|     SaveRendererValues(); | ||||
|     SaveLayoutValues(); | ||||
|     SaveAudioValues(); | ||||
|         SaveCameraValues(); | ||||
|         SaveDataStorageValues(); | ||||
|     SaveSystemValues(); | ||||
|         SaveMiscellaneousValues(); | ||||
|         SaveDebuggingValues(); | ||||
|         SaveWebServiceValues(); | ||||
|         SaveVideoDumpingValues(); | ||||
|     SaveUIValues(); | ||||
|         SaveUtilityValues(); | ||||
|     } | ||||
| 
 | ||||
|     SaveUIValues(); | ||||
|     SaveCoreValues(); | ||||
|     SaveRendererValues(); | ||||
|     SaveLayoutValues(); | ||||
|     SaveAudioValues(); | ||||
|     SaveSystemValues(); | ||||
| } | ||||
| 
 | ||||
| void Config::SaveAudioValues() { | ||||
|     qt_config->beginGroup(QStringLiteral("Audio")); | ||||
| 
 | ||||
|     WriteSetting(QStringLiteral("enable_dsp_lle"), Settings::values.enable_dsp_lle, false); | ||||
|     WriteSetting(QStringLiteral("enable_dsp_lle_multithread"), | ||||
|                  Settings::values.enable_dsp_lle_multithread, false); | ||||
|     WriteSetting(QStringLiteral("output_engine"), QString::fromStdString(Settings::values.sink_id), | ||||
|                  QStringLiteral("auto")); | ||||
|     WriteSetting(QStringLiteral("enable_audio_stretching"), | ||||
|                  Settings::values.enable_audio_stretching, true); | ||||
|     WriteSetting(QStringLiteral("output_device"), | ||||
|                  QString::fromStdString(Settings::values.audio_device_id), QStringLiteral("auto")); | ||||
|     WriteSetting(QStringLiteral("volume"), Settings::values.volume, 1.0f); | ||||
|     WriteSetting(QStringLiteral("mic_input_device"), | ||||
|                  QString::fromStdString(Settings::values.mic_input_device), | ||||
|                  QString::fromUtf8(Frontend::Mic::default_device_name)); | ||||
|     WriteSetting(QStringLiteral("mic_input_type"), | ||||
|                  static_cast<int>(Settings::values.mic_input_type), 0); | ||||
|     WriteGlobalSetting(Settings::values.audio_emulation); | ||||
|     WriteGlobalSetting(Settings::values.enable_audio_stretching); | ||||
|     WriteGlobalSetting(Settings::values.volume); | ||||
| 
 | ||||
|     if (global) { | ||||
|         WriteBasicSetting(Settings::values.sink_id); | ||||
|         WriteBasicSetting(Settings::values.audio_device_id); | ||||
|         WriteBasicSetting(Settings::values.mic_input_device); | ||||
|         WriteBasicSetting(Settings::values.mic_input_type); | ||||
|     } | ||||
| 
 | ||||
|     qt_config->endGroup(); | ||||
| } | ||||
|  | @ -849,9 +922,9 @@ void Config::SaveControlValues() { | |||
| void Config::SaveUtilityValues() { | ||||
|     qt_config->beginGroup(QStringLiteral("Utility")); | ||||
| 
 | ||||
|     WriteSetting(QStringLiteral("dump_textures"), Settings::values.dump_textures, false); | ||||
|     WriteSetting(QStringLiteral("custom_textures"), Settings::values.custom_textures, false); | ||||
|     WriteSetting(QStringLiteral("preload_textures"), Settings::values.preload_textures, false); | ||||
|     WriteBasicSetting(Settings::values.dump_textures); | ||||
|     WriteBasicSetting(Settings::values.custom_textures); | ||||
|     WriteBasicSetting(Settings::values.preload_textures); | ||||
| 
 | ||||
|     qt_config->endGroup(); | ||||
| } | ||||
|  | @ -859,9 +932,11 @@ void Config::SaveUtilityValues() { | |||
| void Config::SaveCoreValues() { | ||||
|     qt_config->beginGroup(QStringLiteral("Core")); | ||||
| 
 | ||||
|     WriteSetting(QStringLiteral("use_cpu_jit"), Settings::values.use_cpu_jit, true); | ||||
|     WriteSetting(QStringLiteral("cpu_clock_percentage"), Settings::values.cpu_clock_percentage, | ||||
|                  100); | ||||
|     WriteGlobalSetting(Settings::values.cpu_clock_percentage); | ||||
| 
 | ||||
|     if (global) { | ||||
|         WriteBasicSetting(Settings::values.use_cpu_jit); | ||||
|     } | ||||
| 
 | ||||
|     qt_config->endGroup(); | ||||
| } | ||||
|  | @ -869,8 +944,8 @@ void Config::SaveCoreValues() { | |||
| void Config::SaveDataStorageValues() { | ||||
|     qt_config->beginGroup(QStringLiteral("Data Storage")); | ||||
| 
 | ||||
|     WriteSetting(QStringLiteral("use_virtual_sd"), Settings::values.use_virtual_sd, true); | ||||
|     WriteSetting(QStringLiteral("use_custom_storage"), Settings::values.use_custom_storage, false); | ||||
|     WriteBasicSetting(Settings::values.use_virtual_sd); | ||||
|     WriteBasicSetting(Settings::values.use_custom_storage); | ||||
|     WriteSetting(QStringLiteral("nand_directory"), | ||||
|                  QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::NANDDir)), | ||||
|                  QStringLiteral("")); | ||||
|  | @ -886,8 +961,8 @@ void Config::SaveDebuggingValues() { | |||
| 
 | ||||
|     // Intentionally not using the QT default setting as this is intended to be changed in the ini
 | ||||
|     qt_config->setValue(QStringLiteral("record_frame_times"), Settings::values.record_frame_times); | ||||
|     WriteSetting(QStringLiteral("use_gdbstub"), Settings::values.use_gdbstub, false); | ||||
|     WriteSetting(QStringLiteral("gdbstub_port"), Settings::values.gdbstub_port, 24689); | ||||
|     WriteBasicSetting(Settings::values.use_gdbstub); | ||||
|     WriteBasicSetting(Settings::values.gdbstub_port); | ||||
| 
 | ||||
|     qt_config->beginGroup(QStringLiteral("LLE")); | ||||
|     for (const auto& service_module : Settings::values.lle_modules) { | ||||
|  | @ -901,29 +976,30 @@ void Config::SaveDebuggingValues() { | |||
| void Config::SaveLayoutValues() { | ||||
|     qt_config->beginGroup(QStringLiteral("Layout")); | ||||
| 
 | ||||
|     WriteSetting(QStringLiteral("render_3d"), static_cast<int>(Settings::values.render_3d), 0); | ||||
|     WriteSetting(QStringLiteral("factor_3d"), Settings::values.factor_3d.load(), 0); | ||||
|     WriteSetting(QStringLiteral("mono_render_left_eye"), Settings::values.mono_render_left_eye, | ||||
|                  false); | ||||
|     WriteGlobalSetting(Settings::values.render_3d); | ||||
|     WriteGlobalSetting(Settings::values.factor_3d); | ||||
|     WriteSetting(QStringLiteral("pp_shader_name"), | ||||
|                  QString::fromStdString(Settings::values.pp_shader_name), | ||||
|                  (Settings::values.render_3d == Settings::StereoRenderOption::Anaglyph) | ||||
|                  QString::fromStdString(Settings::values.pp_shader_name.GetValue()), | ||||
|                  (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Anaglyph) | ||||
|                      ? QStringLiteral("dubois (builtin)") | ||||
|                      : QStringLiteral("none (builtin)")); | ||||
|     WriteSetting(QStringLiteral("filter_mode"), Settings::values.filter_mode, true); | ||||
|     WriteSetting(QStringLiteral("layout_option"), static_cast<int>(Settings::values.layout_option)); | ||||
|     WriteSetting(QStringLiteral("swap_screen"), Settings::values.swap_screen, false); | ||||
|     WriteSetting(QStringLiteral("upright_screen"), Settings::values.upright_screen, false); | ||||
|     WriteSetting(QStringLiteral("custom_layout"), Settings::values.custom_layout, false); | ||||
|     WriteSetting(QStringLiteral("custom_top_left"), Settings::values.custom_top_left, 0); | ||||
|     WriteSetting(QStringLiteral("custom_top_top"), Settings::values.custom_top_top, 0); | ||||
|     WriteSetting(QStringLiteral("custom_top_right"), Settings::values.custom_top_right, 400); | ||||
|     WriteSetting(QStringLiteral("custom_top_bottom"), Settings::values.custom_top_bottom, 240); | ||||
|     WriteSetting(QStringLiteral("custom_bottom_left"), Settings::values.custom_bottom_left, 40); | ||||
|     WriteSetting(QStringLiteral("custom_bottom_top"), Settings::values.custom_bottom_top, 240); | ||||
|     WriteSetting(QStringLiteral("custom_bottom_right"), Settings::values.custom_bottom_right, 360); | ||||
|     WriteSetting(QStringLiteral("custom_bottom_bottom"), Settings::values.custom_bottom_bottom, | ||||
|                  480); | ||||
|     WriteGlobalSetting(Settings::values.filter_mode); | ||||
|     WriteGlobalSetting(Settings::values.layout_option); | ||||
|     WriteGlobalSetting(Settings::values.swap_screen); | ||||
|     WriteGlobalSetting(Settings::values.upright_screen); | ||||
| 
 | ||||
|     if (global) { | ||||
|         WriteBasicSetting(Settings::values.mono_render_left_eye); | ||||
|         WriteBasicSetting(Settings::values.custom_layout); | ||||
|         WriteBasicSetting(Settings::values.custom_top_left); | ||||
|         WriteBasicSetting(Settings::values.custom_top_top); | ||||
|         WriteBasicSetting(Settings::values.custom_top_right); | ||||
|         WriteBasicSetting(Settings::values.custom_top_bottom); | ||||
|         WriteBasicSetting(Settings::values.custom_bottom_left); | ||||
|         WriteBasicSetting(Settings::values.custom_bottom_top); | ||||
|         WriteBasicSetting(Settings::values.custom_bottom_right); | ||||
|         WriteBasicSetting(Settings::values.custom_bottom_bottom); | ||||
|     } | ||||
| 
 | ||||
|     qt_config->endGroup(); | ||||
| } | ||||
|  | @ -931,8 +1007,7 @@ void Config::SaveLayoutValues() { | |||
| void Config::SaveMiscellaneousValues() { | ||||
|     qt_config->beginGroup(QStringLiteral("Miscellaneous")); | ||||
| 
 | ||||
|     WriteSetting(QStringLiteral("log_filter"), QString::fromStdString(Settings::values.log_filter), | ||||
|                  QStringLiteral("*:Info")); | ||||
|     WriteBasicSetting(Settings::values.log_filter); | ||||
| 
 | ||||
|     qt_config->endGroup(); | ||||
| } | ||||
|  | @ -974,11 +1049,12 @@ void Config::SaveMultiplayerValues() { | |||
| void Config::SavePathValues() { | ||||
|     qt_config->beginGroup(QStringLiteral("Paths")); | ||||
| 
 | ||||
|     WriteGlobalSetting(UISettings::values.screenshot_path); | ||||
|     if (global) { | ||||
|         WriteSetting(QStringLiteral("romsPath"), UISettings::values.roms_path); | ||||
|         WriteSetting(QStringLiteral("symbolsPath"), UISettings::values.symbols_path); | ||||
|         WriteSetting(QStringLiteral("movieRecordPath"), UISettings::values.movie_record_path); | ||||
|         WriteSetting(QStringLiteral("moviePlaybackPath"), UISettings::values.movie_playback_path); | ||||
|     WriteSetting(QStringLiteral("screenshotPath"), UISettings::values.screenshot_path); | ||||
|         WriteSetting(QStringLiteral("videoDumpingPath"), UISettings::values.video_dumping_path); | ||||
|         qt_config->beginWriteArray(QStringLiteral("gamedirs")); | ||||
|         for (int i = 0; i < UISettings::values.game_dirs.size(); ++i) { | ||||
|  | @ -991,6 +1067,7 @@ void Config::SavePathValues() { | |||
|         qt_config->endArray(); | ||||
|         WriteSetting(QStringLiteral("recentFiles"), UISettings::values.recent_files); | ||||
|         WriteSetting(QStringLiteral("language"), UISettings::values.language, QString{}); | ||||
|     } | ||||
| 
 | ||||
|     qt_config->endGroup(); | ||||
| } | ||||
|  | @ -998,34 +1075,29 @@ void Config::SavePathValues() { | |||
| void Config::SaveRendererValues() { | ||||
|     qt_config->beginGroup(QStringLiteral("Renderer")); | ||||
| 
 | ||||
|     WriteSetting(QStringLiteral("use_hw_renderer"), Settings::values.use_hw_renderer, true); | ||||
|     WriteSetting(QStringLiteral("use_hw_shader"), Settings::values.use_hw_shader, true); | ||||
|     WriteGlobalSetting(Settings::values.use_hw_renderer); | ||||
|     WriteGlobalSetting(Settings::values.use_hw_shader); | ||||
| #ifdef __APPLE__ | ||||
|     // Hardware shader is broken on macos thanks to poor drivers.
 | ||||
|     // TODO: enable this for none Intel GPUs
 | ||||
|     WriteSetting(QStringLiteral("use_separable_shader"), Settings::values.separable_shader, false); | ||||
|     WriteGlobalSetting(Settings::values.separable_shader); | ||||
| #endif | ||||
|     WriteSetting(QStringLiteral("shaders_accurate_mul"), Settings::values.shaders_accurate_mul, | ||||
|                  true); | ||||
|     WriteSetting(QStringLiteral("use_shader_jit"), Settings::values.use_shader_jit, true); | ||||
|     WriteSetting(QStringLiteral("use_disk_shader_cache"), Settings::values.use_disk_shader_cache, | ||||
|                  true); | ||||
|     WriteSetting(QStringLiteral("use_vsync_new"), Settings::values.use_vsync_new, true); | ||||
|     WriteSetting(QStringLiteral("resolution_factor"), Settings::values.resolution_factor, 1); | ||||
|     WriteSetting(QStringLiteral("frame_limit"), Settings::values.frame_limit, 100); | ||||
|     WriteSetting(QStringLiteral("use_frame_limit_alternate"), | ||||
|                  Settings::values.use_frame_limit_alternate, false); | ||||
|     WriteSetting(QStringLiteral("frame_limit_alternate"), Settings::values.frame_limit_alternate, | ||||
|                  200); | ||||
|     WriteGlobalSetting(Settings::values.shaders_accurate_mul); | ||||
|     WriteGlobalSetting(Settings::values.use_disk_shader_cache); | ||||
|     WriteGlobalSetting(Settings::values.use_vsync_new); | ||||
|     WriteGlobalSetting(Settings::values.resolution_factor); | ||||
|     WriteGlobalSetting(Settings::values.frame_limit); | ||||
| 
 | ||||
|     // Cast to double because Qt's written float values are not human-readable
 | ||||
|     WriteSetting(QStringLiteral("bg_red"), static_cast<double>(Settings::values.bg_red), 0.0); | ||||
|     WriteSetting(QStringLiteral("bg_green"), static_cast<double>(Settings::values.bg_green), 0.0); | ||||
|     WriteSetting(QStringLiteral("bg_blue"), static_cast<double>(Settings::values.bg_blue), 0.0); | ||||
|     WriteGlobalSetting(Settings::values.bg_red); | ||||
|     WriteGlobalSetting(Settings::values.bg_green); | ||||
|     WriteGlobalSetting(Settings::values.bg_blue); | ||||
| 
 | ||||
|     WriteSetting(QStringLiteral("texture_filter_name"), | ||||
|                  QString::fromStdString(Settings::values.texture_filter_name), | ||||
|                  QStringLiteral("none")); | ||||
|     WriteGlobalSetting(Settings::values.texture_filter_name); | ||||
| 
 | ||||
|     if (global) { | ||||
|         WriteSetting(QStringLiteral("use_shader_jit"), Settings::values.use_shader_jit.GetValue(), | ||||
|                      true); | ||||
|     } | ||||
| 
 | ||||
|     qt_config->endGroup(); | ||||
| } | ||||
|  | @ -1052,15 +1124,14 @@ void Config::SaveShortcutValues() { | |||
| void Config::SaveSystemValues() { | ||||
|     qt_config->beginGroup(QStringLiteral("System")); | ||||
| 
 | ||||
|     WriteSetting(QStringLiteral("is_new_3ds"), Settings::values.is_new_3ds, true); | ||||
|     WriteSetting(QStringLiteral("region_value"), Settings::values.region_value, | ||||
|                  Settings::REGION_VALUE_AUTO_SELECT); | ||||
|     WriteSetting(QStringLiteral("init_clock"), static_cast<u32>(Settings::values.init_clock), | ||||
|                  static_cast<u32>(Settings::InitClock::SystemTime)); | ||||
|     WriteSetting(QStringLiteral("init_time"), | ||||
|                  static_cast<unsigned long long>(Settings::values.init_time), 946681277ULL); | ||||
|     WriteSetting(QStringLiteral("init_time_offset"), | ||||
|                  static_cast<long long>(Settings::values.init_time_offset), 0LL); | ||||
|     WriteGlobalSetting(Settings::values.is_new_3ds); | ||||
|     WriteGlobalSetting(Settings::values.region_value); | ||||
| 
 | ||||
|     if (global) { | ||||
|         WriteBasicSetting(Settings::values.init_clock); | ||||
|         WriteBasicSetting(Settings::values.init_time); | ||||
|         WriteBasicSetting(Settings::values.init_time_offset); | ||||
|     } | ||||
| 
 | ||||
|     qt_config->endGroup(); | ||||
| } | ||||
|  | @ -1095,32 +1166,32 @@ void Config::SaveVideoDumpingValues() { | |||
| void Config::SaveUIValues() { | ||||
|     qt_config->beginGroup(QStringLiteral("UI")); | ||||
| 
 | ||||
|     SavePathValues(); | ||||
| 
 | ||||
|     if (global) { | ||||
|         WriteSetting(QStringLiteral("theme"), UISettings::values.theme, | ||||
|                      QString::fromUtf8(UISettings::themes[0].second)); | ||||
|     WriteSetting(QStringLiteral("enable_discord_presence"), | ||||
|                  UISettings::values.enable_discord_presence, true); | ||||
|     WriteSetting(QStringLiteral("screenshot_resolution_factor"), | ||||
|                  UISettings::values.screenshot_resolution_factor, 0); | ||||
|         WriteBasicSetting(UISettings::values.enable_discord_presence); | ||||
|         WriteBasicSetting(UISettings::values.screenshot_resolution_factor); | ||||
| 
 | ||||
|         SaveUpdaterValues(); | ||||
|         SaveUILayoutValues(); | ||||
|         SaveUIGameListValues(); | ||||
|     SavePathValues(); | ||||
|         SaveShortcutValues(); | ||||
|         SaveMultiplayerValues(); | ||||
| 
 | ||||
|     WriteSetting(QStringLiteral("singleWindowMode"), UISettings::values.single_window_mode, true); | ||||
|     WriteSetting(QStringLiteral("fullscreen"), UISettings::values.fullscreen, false); | ||||
|     WriteSetting(QStringLiteral("displayTitleBars"), UISettings::values.display_titlebar, true); | ||||
|     WriteSetting(QStringLiteral("showFilterBar"), UISettings::values.show_filter_bar, true); | ||||
|     WriteSetting(QStringLiteral("showStatusBar"), UISettings::values.show_status_bar, true); | ||||
|     WriteSetting(QStringLiteral("confirmClose"), UISettings::values.confirm_before_closing, true); | ||||
|     WriteSetting(QStringLiteral("firstStart"), UISettings::values.first_start, true); | ||||
|     WriteSetting(QStringLiteral("calloutFlags"), UISettings::values.callout_flags, 0); | ||||
|     WriteSetting(QStringLiteral("showConsole"), UISettings::values.show_console, false); | ||||
|     WriteSetting(QStringLiteral("pauseWhenInBackground"), | ||||
|                  UISettings::values.pause_when_in_background, false); | ||||
|     WriteSetting(QStringLiteral("hideInactiveMouse"), UISettings::values.hide_mouse, false); | ||||
|         WriteBasicSetting(UISettings::values.single_window_mode); | ||||
|         WriteBasicSetting(UISettings::values.fullscreen); | ||||
|         WriteBasicSetting(UISettings::values.display_titlebar); | ||||
|         WriteBasicSetting(UISettings::values.show_filter_bar); | ||||
|         WriteBasicSetting(UISettings::values.show_status_bar); | ||||
|         WriteBasicSetting(UISettings::values.confirm_before_closing); | ||||
|         WriteBasicSetting(UISettings::values.first_start); | ||||
|         WriteBasicSetting(UISettings::values.callout_flags); | ||||
|         WriteBasicSetting(UISettings::values.show_console); | ||||
|         WriteBasicSetting(UISettings::values.pause_when_in_background); | ||||
|         WriteBasicSetting(UISettings::values.hide_mouse); | ||||
|     } | ||||
| 
 | ||||
|     qt_config->endGroup(); | ||||
| } | ||||
|  | @ -1128,13 +1199,11 @@ void Config::SaveUIValues() { | |||
| void Config::SaveUIGameListValues() { | ||||
|     qt_config->beginGroup(QStringLiteral("GameList")); | ||||
| 
 | ||||
|     WriteSetting(QStringLiteral("iconSize"), | ||||
|                  static_cast<int>(UISettings::values.game_list_icon_size), 2); | ||||
|     WriteSetting(QStringLiteral("row1"), static_cast<int>(UISettings::values.game_list_row_1), 2); | ||||
|     WriteSetting(QStringLiteral("row2"), static_cast<int>(UISettings::values.game_list_row_2), 0); | ||||
|     WriteSetting(QStringLiteral("hideNoIcon"), UISettings::values.game_list_hide_no_icon, false); | ||||
|     WriteSetting(QStringLiteral("singleLineMode"), UISettings::values.game_list_single_line_mode, | ||||
|                  false); | ||||
|     WriteBasicSetting(UISettings::values.game_list_icon_size); | ||||
|     WriteBasicSetting(UISettings::values.game_list_row_1); | ||||
|     WriteBasicSetting(UISettings::values.game_list_row_2); | ||||
|     WriteBasicSetting(UISettings::values.game_list_hide_no_icon); | ||||
|     WriteBasicSetting(UISettings::values.game_list_single_line_mode); | ||||
| 
 | ||||
|     qt_config->endGroup(); | ||||
| } | ||||
|  | @ -1148,8 +1217,7 @@ void Config::SaveUILayoutValues() { | |||
|     WriteSetting(QStringLiteral("gameListHeaderState"), UISettings::values.gamelist_header_state); | ||||
|     WriteSetting(QStringLiteral("microProfileDialogGeometry"), | ||||
|                  UISettings::values.microprofile_geometry); | ||||
|     WriteSetting(QStringLiteral("microProfileDialogVisible"), | ||||
|                  UISettings::values.microprofile_visible, false); | ||||
|     WriteBasicSetting(UISettings::values.microprofile_visible); | ||||
| 
 | ||||
|     qt_config->endGroup(); | ||||
| } | ||||
|  | @ -1157,9 +1225,8 @@ void Config::SaveUILayoutValues() { | |||
| void Config::SaveUpdaterValues() { | ||||
|     qt_config->beginGroup(QStringLiteral("Updater")); | ||||
| 
 | ||||
|     WriteSetting(QStringLiteral("check_for_update_on_start"), | ||||
|                  UISettings::values.check_for_update_on_start, true); | ||||
|     WriteSetting(QStringLiteral("update_on_close"), UISettings::values.update_on_close, false); | ||||
|     WriteBasicSetting(UISettings::values.check_for_update_on_start); | ||||
|     WriteBasicSetting(UISettings::values.update_on_close); | ||||
| 
 | ||||
|     qt_config->endGroup(); | ||||
| } | ||||
|  | @ -1193,6 +1260,15 @@ QVariant Config::ReadSetting(const QString& name, const QVariant& default_value) | |||
|     return result; | ||||
| } | ||||
| 
 | ||||
| template <typename Type> | ||||
| void Config::ReadSettingGlobal(Type& setting, const QString& name, | ||||
|                                const QVariant& default_value) const { | ||||
|     const bool use_global = qt_config->value(name + QStringLiteral("/use_global"), true).toBool(); | ||||
|     if (global || !use_global) { | ||||
|         setting = ReadSetting(name, default_value).value<Type>(); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void Config::WriteSetting(const QString& name, const QVariant& value) { | ||||
|     qt_config->setValue(name, value); | ||||
| } | ||||
|  | @ -1203,11 +1279,21 @@ void Config::WriteSetting(const QString& name, const QVariant& value, | |||
|     qt_config->setValue(name, value); | ||||
| } | ||||
| 
 | ||||
| void Config::WriteSetting(const QString& name, const QVariant& value, const QVariant& default_value, | ||||
|                           bool use_global) { | ||||
|     if (!global) { | ||||
|         qt_config->setValue(name + QStringLiteral("/use_global"), use_global); | ||||
|     } | ||||
|     if (global || !use_global) { | ||||
|         qt_config->setValue(name + QStringLiteral("/default"), value == default_value); | ||||
|         qt_config->setValue(name, value); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void Config::Reload() { | ||||
|     ReadValues(); | ||||
|     // To apply default value changes
 | ||||
|     SaveValues(); | ||||
|     Settings::Apply(); | ||||
| } | ||||
| 
 | ||||
| void Config::Save() { | ||||
|  |  | |||
|  | @ -8,13 +8,16 @@ | |||
| #include <memory> | ||||
| #include <string> | ||||
| #include <QVariant> | ||||
| #include "core/settings.h" | ||||
| #include "common/settings.h" | ||||
| 
 | ||||
| class QSettings; | ||||
| 
 | ||||
| class Config { | ||||
| public: | ||||
|     Config(); | ||||
|     enum class ConfigType : u32 { GlobalConfig, PerGameConfig }; | ||||
| 
 | ||||
|     explicit Config(const std::string& config_name = "qt-config", | ||||
|                     ConfigType config_type = ConfigType::GlobalConfig); | ||||
|     ~Config(); | ||||
| 
 | ||||
|     void Reload(); | ||||
|  | @ -24,6 +27,8 @@ public: | |||
|     static const std::array<std::array<int, 5>, Settings::NativeAnalog::NumAnalogs> default_analogs; | ||||
| 
 | ||||
| private: | ||||
|     void Initialize(const std::string& config_name); | ||||
| 
 | ||||
|     void ReadValues(); | ||||
|     void ReadAudioValues(); | ||||
|     void ReadCameraValues(); | ||||
|  | @ -68,11 +73,78 @@ private: | |||
|     void SaveWebServiceValues(); | ||||
|     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& 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, 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::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 | ||||
| #include "audio_core/sink.h" | ||||
| #include "audio_core/sink_details.h" | ||||
| #include "citra_qt/configuration/configuration_shared.h" | ||||
| #include "citra_qt/configuration/configure_audio.h" | ||||
| #include "common/settings.h" | ||||
| #include "core/core.h" | ||||
| #include "core/frontend/mic.h" | ||||
| #include "core/settings.h" | ||||
| #include "ui_configure_audio.h" | ||||
| 
 | ||||
| #if defined(__APPLE__) | ||||
|  | @ -31,25 +32,30 @@ ConfigureAudio::ConfigureAudio(QWidget* parent) | |||
|         ui->output_sink_combo_box->addItem(QString::fromUtf8(id)); | ||||
|     } | ||||
| 
 | ||||
|     ui->emulation_combo_box->addItem(tr("HLE (fast)")); | ||||
|     ui->emulation_combo_box->addItem(tr("LLE (accurate)")); | ||||
|     ui->emulation_combo_box->addItem(tr("LLE multi-core")); | ||||
|     ui->emulation_combo_box->setEnabled(!Core::System::GetInstance().IsPoweredOn()); | ||||
|     const bool is_running = Core::System::GetInstance().IsPoweredOn(); | ||||
|     ui->emulation_combo_box->setEnabled(!is_running); | ||||
| 
 | ||||
|     connect(ui->volume_slider, &QSlider::valueChanged, this, | ||||
|             &ConfigureAudio::SetVolumeIndicatorText); | ||||
| 
 | ||||
|     ui->input_device_combo_box->clear(); | ||||
|     ui->input_device_combo_box->addItem(tr("Default")); | ||||
| 
 | ||||
| #ifdef HAVE_CUBEB | ||||
|     for (const auto& device : AudioCore::ListCubebInputDevices()) { | ||||
|         ui->input_device_combo_box->addItem(QString::fromStdString(device)); | ||||
|     } | ||||
| #endif | ||||
| 
 | ||||
|     connect(ui->input_type_combo_box, qOverload<int>(&QComboBox::currentIndexChanged), this, | ||||
|             &ConfigureAudio::UpdateAudioInputDevices); | ||||
| 
 | ||||
|     ui->volume_label->setVisible(Settings::IsConfiguringGlobal()); | ||||
|     ui->volume_combo_box->setVisible(!Settings::IsConfiguringGlobal()); | ||||
| 
 | ||||
|     SetupPerGameUI(); | ||||
|     SetConfiguration(); | ||||
| 
 | ||||
|     connect(ui->output_sink_combo_box, qOverload<int>(&QComboBox::currentIndexChanged), this, | ||||
|             &ConfigureAudio::UpdateAudioOutputDevices); | ||||
| } | ||||
|  | @ -61,27 +67,35 @@ void ConfigureAudio::SetConfiguration() { | |||
| 
 | ||||
|     // The device list cannot be pre-populated (nor listed) until the output sink is known.
 | ||||
|     UpdateAudioOutputDevices(ui->output_sink_combo_box->currentIndex()); | ||||
| 
 | ||||
|     SetAudioDeviceFromDeviceID(); | ||||
| 
 | ||||
|     ui->toggle_audio_stretching->setChecked(Settings::values.enable_audio_stretching); | ||||
|     ui->volume_slider->setValue( | ||||
|         static_cast<int>(Settings::values.volume * ui->volume_slider->maximum())); | ||||
|     ui->toggle_audio_stretching->setChecked(Settings::values.enable_audio_stretching.GetValue()); | ||||
| 
 | ||||
|     const s32 volume = | ||||
|         static_cast<s32>(Settings::values.volume.GetValue() * ui->volume_slider->maximum()); | ||||
|     ui->volume_slider->setValue(volume); | ||||
|     SetVolumeIndicatorText(ui->volume_slider->sliderPosition()); | ||||
| 
 | ||||
|     int selection; | ||||
|     if (Settings::values.enable_dsp_lle) { | ||||
|         if (Settings::values.enable_dsp_lle_multithread) { | ||||
|             selection = 2; | ||||
|     if (!Settings::IsConfiguringGlobal()) { | ||||
|         if (Settings::values.volume.UsingGlobal()) { | ||||
|             ui->volume_combo_box->setCurrentIndex(0); | ||||
|             ui->volume_slider->setEnabled(false); | ||||
|         } 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 { | ||||
|         selection = 0; | ||||
|     } | ||||
|         s32 selection = static_cast<s32>(Settings::values.audio_emulation.GetValue()); | ||||
|         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); | ||||
| 
 | ||||
|     UpdateAudioInputDevices(index); | ||||
|  | @ -90,7 +104,7 @@ void ConfigureAudio::SetConfiguration() { | |||
| void ConfigureAudio::SetOutputSinkFromSinkID() { | ||||
|     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++) { | ||||
|         if (ui->output_sink_combo_box->itemText(index) == sink_id) { | ||||
|             new_sink_index = index; | ||||
|  | @ -104,7 +118,7 @@ void ConfigureAudio::SetOutputSinkFromSinkID() { | |||
| void ConfigureAudio::SetAudioDeviceFromDeviceID() { | ||||
|     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++) { | ||||
|         if (ui->audio_device_combo_box->itemText(index) == device_id) { | ||||
|             new_device_index = index; | ||||
|  | @ -120,24 +134,31 @@ void ConfigureAudio::SetVolumeIndicatorText(int percentage) { | |||
| } | ||||
| 
 | ||||
| void ConfigureAudio::ApplyConfiguration() { | ||||
|     ConfigurationShared::ApplyPerGameSetting(&Settings::values.enable_audio_stretching, | ||||
|                                              ui->toggle_audio_stretching, audio_stretching); | ||||
|     ConfigurationShared::ApplyPerGameSetting(&Settings::values.audio_emulation, | ||||
|                                              ui->emulation_combo_box); | ||||
|     ConfigurationShared::ApplyPerGameSetting( | ||||
|         &Settings::values.volume, ui->volume_combo_box, [this](s32) { | ||||
|             return static_cast<float>(ui->volume_slider->value()) / ui->volume_slider->maximum(); | ||||
|         }); | ||||
| 
 | ||||
|     if (Settings::IsConfiguringGlobal()) { | ||||
|         Settings::values.sink_id = | ||||
|             ui->output_sink_combo_box->itemText(ui->output_sink_combo_box->currentIndex()) | ||||
|                 .toStdString(); | ||||
|     Settings::values.enable_audio_stretching = ui->toggle_audio_stretching->isChecked(); | ||||
|         Settings::values.audio_device_id = | ||||
|             ui->audio_device_combo_box->itemText(ui->audio_device_combo_box->currentIndex()) | ||||
|                 .toStdString(); | ||||
|     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) { | ||||
|             Settings::values.mic_input_device = Frontend::Mic::default_device_name; | ||||
|         } else { | ||||
|         Settings::values.mic_input_device = ui->input_device_combo_box->currentText().toStdString(); | ||||
|             Settings::values.mic_input_device = | ||||
|                 ui->input_device_combo_box->currentText().toStdString(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | @ -157,12 +178,41 @@ void ConfigureAudio::UpdateAudioInputDevices(int index) { | |||
|         AppleAuthorization::CheckAuthorizationForMicrophone(); | ||||
|     } | ||||
| #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( | ||||
|             QString::fromStdString(Settings::values.mic_input_device)); | ||||
|             QString::fromStdString(Settings::values.mic_input_device.GetValue())); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void ConfigureAudio::RetranslateUI() { | ||||
|     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; | ||||
| } | ||||
| 
 | ||||
| namespace ConfigurationShared { | ||||
| enum class CheckState; | ||||
| } | ||||
| 
 | ||||
| class ConfigureAudio : public QWidget { | ||||
|     Q_OBJECT | ||||
| 
 | ||||
|  | @ -30,5 +34,8 @@ private: | |||
|     void SetAudioDeviceFromDeviceID(); | ||||
|     void SetVolumeIndicatorText(int percentage); | ||||
| 
 | ||||
|     void SetupPerGameUI(); | ||||
| 
 | ||||
|     ConfigurationShared::CheckState audio_stretching; | ||||
|     std::unique_ptr<Ui::ConfigureAudio> ui; | ||||
| }; | ||||
|  |  | |||
|  | @ -6,8 +6,8 @@ | |||
|    <rect> | ||||
|     <x>0</x> | ||||
|     <y>0</y> | ||||
|     <width>329</width> | ||||
|     <height>344</height> | ||||
|     <width>696</width> | ||||
|     <height>527</height> | ||||
|    </rect> | ||||
|   </property> | ||||
|   <layout class="QVBoxLayout"> | ||||
|  | @ -18,7 +18,17 @@ | |||
|      </property> | ||||
|      <layout class="QVBoxLayout"> | ||||
|       <item> | ||||
|       <widget class="QWidget" name="widget_emulation" native="true"> | ||||
|         <layout class="QHBoxLayout" name="horizontalLayout_emulation"> | ||||
|             <property name="leftMargin"> | ||||
|             <number>0</number> | ||||
|             </property> | ||||
|             <property name="topMargin"> | ||||
|             <number>0</number> | ||||
|             </property> | ||||
|             <property name="rightMargin"> | ||||
|             <number>0</number> | ||||
|             </property> | ||||
|             <property name="bottomMargin"> | ||||
|             <number>0</number> | ||||
|             </property> | ||||
|  | @ -30,14 +40,31 @@ | |||
|             </widget> | ||||
|             </item> | ||||
|             <item> | ||||
|          <widget class="QComboBox" name="emulation_combo_box"/> | ||||
|             <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> | ||||
|        <layout class="QHBoxLayout"> | ||||
|        <layout class="QHBoxLayout" name="output_engine_layout"> | ||||
|         <item> | ||||
|          <widget class="QLabel" name="label1"> | ||||
|          <widget class="QLabel" name="output_sink_label"> | ||||
|           <property name="text"> | ||||
|            <string>Output Engine</string> | ||||
|           </property> | ||||
|  | @ -59,9 +86,9 @@ | |||
|        </widget> | ||||
|       </item> | ||||
|       <item> | ||||
|        <layout class="QHBoxLayout"> | ||||
|        <layout class="QHBoxLayout" name="audio_device_layout"> | ||||
|         <item> | ||||
|          <widget class="QLabel" name="label2"> | ||||
|          <widget class="QLabel" name="audio_device_label"> | ||||
|           <property name="text"> | ||||
|            <string>Audio Device</string> | ||||
|           </property> | ||||
|  | @ -73,12 +100,36 @@ | |||
|        </layout> | ||||
|       </item> | ||||
|       <item> | ||||
|        <widget class="QWidget" name="volume_layout" native="true"> | ||||
|         <layout class="QHBoxLayout" name="horizontalLayout_2"> | ||||
|          <property name="leftMargin"> | ||||
|           <number>0</number> | ||||
|          </property> | ||||
|          <property name="topMargin"> | ||||
|           <number>0</number> | ||||
|          </property> | ||||
|          <property name="rightMargin"> | ||||
|           <number>0</number> | ||||
|          </property> | ||||
|          <property name="bottomMargin"> | ||||
|           <number>0</number> | ||||
|          </property> | ||||
|          <item> | ||||
|          <widget class="QLabel" name="label"> | ||||
|           <widget class="QComboBox" name="volume_combo_box"> | ||||
|            <item> | ||||
|             <property name="text"> | ||||
|              <string>Use global volume</string> | ||||
|             </property> | ||||
|            </item> | ||||
|            <item> | ||||
|             <property name="text"> | ||||
|              <string>Set volume:</string> | ||||
|             </property> | ||||
|            </item> | ||||
|           </widget> | ||||
|          </item> | ||||
|          <item> | ||||
|           <widget class="QLabel" name="volume_label"> | ||||
|            <property name="text"> | ||||
|             <string>Volume:</string> | ||||
|            </property> | ||||
|  | @ -91,7 +142,7 @@ | |||
|            </property> | ||||
|            <property name="sizeHint" stdset="0"> | ||||
|             <size> | ||||
|             <width>40</width> | ||||
|              <width>30</width> | ||||
|              <height>20</height> | ||||
|             </size> | ||||
|            </property> | ||||
|  | @ -109,7 +160,7 @@ | |||
|             <number>100</number> | ||||
|            </property> | ||||
|            <property name="pageStep"> | ||||
|            <number>10</number> | ||||
|             <number>5</number> | ||||
|            </property> | ||||
|            <property name="orientation"> | ||||
|             <enum>Qt::Horizontal</enum> | ||||
|  | @ -133,12 +184,13 @@ | |||
|           </widget> | ||||
|          </item> | ||||
|         </layout> | ||||
|        </widget> | ||||
|       </item> | ||||
|      </layout> | ||||
|     </widget> | ||||
|    </item> | ||||
|    <item> | ||||
|     <widget class="QGroupBox" name="groupBox_2"> | ||||
|     <widget class="QGroupBox" name="microphone_layout"> | ||||
|      <property name="title"> | ||||
|       <string>Microphone</string> | ||||
|      </property> | ||||
|  | @ -146,7 +198,7 @@ | |||
|       <item> | ||||
|        <layout class="QHBoxLayout" name="horizontalLayout"> | ||||
|         <item> | ||||
|          <widget class="QLabel" name="label_2"> | ||||
|          <widget class="QLabel" name="input_type_label"> | ||||
|           <property name="text"> | ||||
|            <string>Input Type</string> | ||||
|           </property> | ||||
|  | @ -176,7 +228,7 @@ | |||
|       <item> | ||||
|        <layout class="QHBoxLayout" name="horizontalLayout_3"> | ||||
|         <item> | ||||
|          <widget class="QLabel" name="label_3"> | ||||
|          <widget class="QLabel" name="input_device_label"> | ||||
|           <property name="text"> | ||||
|            <string>Input Device</string> | ||||
|           </property> | ||||
|  |  | |||
|  | @ -9,10 +9,10 @@ | |||
| #include <QMessageBox> | ||||
| #include <QWidget> | ||||
| #include "citra_qt/configuration/configure_camera.h" | ||||
| #include "common/settings.h" | ||||
| #include "core/frontend/camera/factory.h" | ||||
| #include "core/frontend/camera/interface.h" | ||||
| #include "core/hle/service/cam/cam.h" | ||||
| #include "core/settings.h" | ||||
| #include "ui_configure_camera.h" | ||||
| 
 | ||||
| #if defined(__APPLE__) | ||||
|  |  | |||
|  | @ -8,11 +8,9 @@ | |||
| #include "citra_qt/debugger/console.h" | ||||
| #include "citra_qt/uisettings.h" | ||||
| #include "common/file_util.h" | ||||
| #include "common/logging/backend.h" | ||||
| #include "common/logging/filter.h" | ||||
| #include "common/logging/log.h" | ||||
| #include "common/settings.h" | ||||
| #include "core/core.h" | ||||
| #include "core/settings.h" | ||||
| #include "ui_configure_debug.h" | ||||
| 
 | ||||
| ConfigureDebug::ConfigureDebug(QWidget* parent) | ||||
|  | @ -32,13 +30,13 @@ ConfigureDebug::ConfigureDebug(QWidget* parent) | |||
| ConfigureDebug::~ConfigureDebug() = default; | ||||
| 
 | ||||
| void ConfigureDebug::SetConfiguration() { | ||||
|     ui->toggle_gdbstub->setChecked(Settings::values.use_gdbstub); | ||||
|     ui->gdbport_spinbox->setEnabled(Settings::values.use_gdbstub); | ||||
|     ui->gdbport_spinbox->setValue(Settings::values.gdbstub_port); | ||||
|     ui->toggle_gdbstub->setChecked(Settings::values.use_gdbstub.GetValue()); | ||||
|     ui->gdbport_spinbox->setEnabled(Settings::values.use_gdbstub.GetValue()); | ||||
|     ui->gdbport_spinbox->setValue(Settings::values.gdbstub_port.GetValue()); | ||||
|     ui->toggle_console->setEnabled(!Core::System::GetInstance().IsPoweredOn()); | ||||
|     ui->toggle_console->setChecked(UISettings::values.show_console); | ||||
|     ui->log_filter_edit->setText(QString::fromStdString(Settings::values.log_filter)); | ||||
|     ui->toggle_cpu_jit->setChecked(Settings::values.use_cpu_jit); | ||||
|     ui->toggle_console->setChecked(UISettings::values.show_console.GetValue()); | ||||
|     ui->log_filter_edit->setText(QString::fromStdString(Settings::values.log_filter.GetValue())); | ||||
|     ui->toggle_cpu_jit->setChecked(Settings::values.use_cpu_jit.GetValue()); | ||||
| } | ||||
| 
 | ||||
| void ConfigureDebug::ApplyConfiguration() { | ||||
|  | @ -48,7 +46,7 @@ void ConfigureDebug::ApplyConfiguration() { | |||
|     Settings::values.log_filter = ui->log_filter_edit->text().toStdString(); | ||||
|     Debugger::ToggleConsole(); | ||||
|     Log::Filter filter; | ||||
|     filter.ParseFilterString(Settings::values.log_filter); | ||||
|     filter.ParseFilterString(Settings::values.log_filter.GetValue()); | ||||
|     Log::SetGlobalFilter(filter); | ||||
|     Settings::values.use_cpu_jit = ui->toggle_cpu_jit->isChecked(); | ||||
| } | ||||
|  |  | |||
|  | @ -7,11 +7,13 @@ | |||
| #include "citra_qt/configuration/config.h" | ||||
| #include "citra_qt/configuration/configure_dialog.h" | ||||
| #include "citra_qt/hotkeys.h" | ||||
| #include "core/settings.h" | ||||
| #include "common/settings.h" | ||||
| #include "ui_configure.h" | ||||
| 
 | ||||
| ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry, bool enable_web_config) | ||||
|     : QDialog(parent), ui(std::make_unique<Ui::ConfigureDialog>()), registry(registry) { | ||||
|     Settings::SetConfiguringGlobal(true); | ||||
| 
 | ||||
|     ui->setupUi(this); | ||||
|     ui->hotkeysTab->Populate(registry); | ||||
|     ui->webTab->SetWebServiceConfigEnabled(enable_web_config); | ||||
|  |  | |||
|  | @ -4,8 +4,8 @@ | |||
| 
 | ||||
| #include <QColorDialog> | ||||
| #include "citra_qt/configuration/configure_enhancements.h" | ||||
| #include "common/settings.h" | ||||
| #include "core/core.h" | ||||
| #include "core/settings.h" | ||||
| #include "ui_configure_enhancements.h" | ||||
| #include "video_core/renderer_opengl/post_processing_opengl.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->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, | ||||
|             static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, | ||||
|  | @ -50,27 +50,30 @@ ConfigureEnhancements::ConfigureEnhancements(QWidget* parent) | |||
| } | ||||
| 
 | ||||
| void ConfigureEnhancements::SetConfiguration() { | ||||
|     ui->resolution_factor_combobox->setCurrentIndex(Settings::values.resolution_factor); | ||||
|     ui->render_3d_combobox->setCurrentIndex(static_cast<int>(Settings::values.render_3d)); | ||||
|     ui->factor_3d->setValue(Settings::values.factor_3d); | ||||
|     ui->mono_render_left_eye->setChecked(Settings::values.mono_render_left_eye); | ||||
|     updateShaders(Settings::values.render_3d); | ||||
|     ui->toggle_linear_filter->setChecked(Settings::values.filter_mode); | ||||
|     ui->resolution_factor_combobox->setCurrentIndex(Settings::values.resolution_factor.GetValue()); | ||||
|     ui->render_3d_combobox->setCurrentIndex( | ||||
|         static_cast<int>(Settings::values.render_3d.GetValue())); | ||||
|     ui->factor_3d->setValue(Settings::values.factor_3d.GetValue()); | ||||
|     ui->mono_render_left_eye->setChecked(Settings::values.mono_render_left_eye.GetValue()); | ||||
|     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( | ||||
|         QString::fromStdString(Settings::values.texture_filter_name)); | ||||
|         QString::fromStdString(Settings::values.texture_filter_name.GetValue())); | ||||
|     if (tex_filter_idx == -1) { | ||||
|         ui->texture_filter_combobox->setCurrentIndex(0); | ||||
|     } else { | ||||
|         ui->texture_filter_combobox->setCurrentIndex(tex_filter_idx); | ||||
|     } | ||||
|     ui->layout_combobox->setCurrentIndex(static_cast<int>(Settings::values.layout_option)); | ||||
|     ui->swap_screen->setChecked(Settings::values.swap_screen); | ||||
|     ui->upright_screen->setChecked(Settings::values.upright_screen); | ||||
|     ui->toggle_dump_textures->setChecked(Settings::values.dump_textures); | ||||
|     ui->toggle_custom_textures->setChecked(Settings::values.custom_textures); | ||||
|     ui->toggle_preload_textures->setChecked(Settings::values.preload_textures); | ||||
|     bg_color = QColor::fromRgbF(Settings::values.bg_red, Settings::values.bg_green, | ||||
|                                 Settings::values.bg_blue); | ||||
|     ui->layout_combobox->setCurrentIndex( | ||||
|         static_cast<int>(Settings::values.layout_option.GetValue())); | ||||
|     ui->swap_screen->setChecked(Settings::values.swap_screen.GetValue()); | ||||
|     ui->upright_screen->setChecked(Settings::values.upright_screen.GetValue()); | ||||
|     ui->toggle_dump_textures->setChecked(Settings::values.dump_textures.GetValue()); | ||||
|     ui->toggle_custom_textures->setChecked(Settings::values.custom_textures.GetValue()); | ||||
|     ui->toggle_preload_textures->setChecked(Settings::values.preload_textures.GetValue()); | ||||
|     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()); | ||||
|     pixmap.fill(bg_color); | ||||
|     const QIcon color_icon(pixmap); | ||||
|  | @ -93,7 +96,7 @@ void ConfigureEnhancements::updateShaders(Settings::StereoRenderOption stereo_op | |||
|     for (const auto& shader : OpenGL::GetPostProcessingShaderList( | ||||
|              stereo_option == Settings::StereoRenderOption::Anaglyph)) { | ||||
|         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); | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -6,9 +6,10 @@ | |||
| 
 | ||||
| #include <memory> | ||||
| #include <QWidget> | ||||
| #include "common/common_types.h" | ||||
| 
 | ||||
| namespace Settings { | ||||
| enum class StereoRenderOption; | ||||
| enum class StereoRenderOption : u32; | ||||
| } | ||||
| 
 | ||||
| namespace Ui { | ||||
|  |  | |||
|  | @ -6,10 +6,11 @@ | |||
| #include <QFileDialog> | ||||
| #include <QMessageBox> | ||||
| #include <QUrl> | ||||
| #include "citra_qt/configuration/configuration_shared.h" | ||||
| #include "citra_qt/configuration/configure_general.h" | ||||
| #include "citra_qt/uisettings.h" | ||||
| #include "core/core.h" | ||||
| #include "core/settings.h" | ||||
| #include "common/file_util.h" | ||||
| #include "common/settings.h" | ||||
| #include "ui_configure_general.h" | ||||
| 
 | ||||
| // 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.
 | ||||
|     // This scales across DPIs, and is acceptable for uncapitalized strings.
 | ||||
|     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(); | ||||
| 
 | ||||
|     ui->updateBox->setVisible(UISettings::values.updater_found); | ||||
|     connect(ui->button_reset_defaults, &QPushButton::clicked, this, | ||||
|             &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()) { | ||||
|             ui->emulation_speed_display_label->setText(tr("unthrottled")); | ||||
|         } 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] { | ||||
|         const QString dir_path = QFileDialog::getExistingDirectory( | ||||
|             this, tr("Select Screenshot Directory"), ui->screenshot_dir_path->text(), | ||||
|  | @ -73,20 +66,21 @@ ConfigureGeneral::ConfigureGeneral(QWidget* parent) | |||
| ConfigureGeneral::~ConfigureGeneral() = default; | ||||
| 
 | ||||
| void ConfigureGeneral::SetConfiguration() { | ||||
|     ui->toggle_check_exit->setChecked(UISettings::values.confirm_before_closing); | ||||
|     ui->toggle_background_pause->setChecked(UISettings::values.pause_when_in_background); | ||||
|     ui->toggle_hide_mouse->setChecked(UISettings::values.hide_mouse); | ||||
|     if (Settings::IsConfiguringGlobal()) { | ||||
|         ui->toggle_check_exit->setChecked(UISettings::values.confirm_before_closing.GetValue()); | ||||
|         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_auto_update->setChecked(UISettings::values.update_on_close); | ||||
|         ui->toggle_update_check->setChecked( | ||||
|             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
 | ||||
|     ui->region_combobox->setCurrentIndex(Settings::values.region_value + 1); | ||||
| 
 | ||||
|     if (Settings::values.frame_limit == 0) { | ||||
|     if (Settings::values.frame_limit.GetValue() == 0) { | ||||
|         ui->frame_limit->setValue(ui->frame_limit->maximum()); | ||||
|     } 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()) { | ||||
|         ui->emulation_speed_display_label->setText(tr("unthrottled")); | ||||
|  | @ -97,32 +91,48 @@ void ConfigureGeneral::SetConfiguration() { | |||
|                 .rightJustified(tr("unthrottled").size())); | ||||
|     } | ||||
| 
 | ||||
|     ui->toggle_alternate_speed->setChecked(Settings::values.use_frame_limit_alternate); | ||||
| 
 | ||||
|     if (Settings::values.frame_limit_alternate == 0) { | ||||
|         ui->frame_limit_alternate->setValue(ui->frame_limit_alternate->maximum()); | ||||
|     if (!Settings::IsConfiguringGlobal()) { | ||||
|         if (Settings::values.frame_limit.UsingGlobal()) { | ||||
|             ui->emulation_speed_combo->setCurrentIndex(0); | ||||
|             ui->frame_limit->setEnabled(false); | ||||
|         } else { | ||||
|         ui->frame_limit_alternate->setValue( | ||||
|             SettingsToSlider(Settings::values.frame_limit_alternate)); | ||||
|             ui->emulation_speed_combo->setCurrentIndex(1); | ||||
|             ui->frame_limit->setEnabled(true); | ||||
|         } | ||||
|     if (ui->frame_limit_alternate->value() == ui->frame_limit_alternate->maximum()) { | ||||
|         ui->emulation_speed_alternate_display_label->setText(tr("unthrottled")); | ||||
|         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->emulation_speed_alternate_display_label->setText( | ||||
|             QStringLiteral("%1%") | ||||
|                 .arg(SliderToSettings(ui->frame_limit_alternate->value())) | ||||
|                 .rightJustified(tr("unthrottled").size())); | ||||
|             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 { | ||||
|         // The first item is "auto-select" with actual value -1, so plus one here will do the trick
 | ||||
|         ui->region_combobox->setCurrentIndex(Settings::values.region_value.GetValue() + 1); | ||||
|     } | ||||
| 
 | ||||
|     QString screenshot_path = UISettings::values.screenshot_path; | ||||
|     if (screenshot_path.isEmpty()) { | ||||
|         screenshot_path = | ||||
|             QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::UserDir)); | ||||
|         screenshot_path.append(QStringLiteral("screenshots/")); | ||||
|         FileUtil::CreateFullPath(screenshot_path.toStdString()); | ||||
|     UISettings::values.screenshot_path.SetGlobal(ui->screenshot_combo->currentIndex() == | ||||
|                                                  ConfigurationShared::USE_GLOBAL_INDEX); | ||||
|     std::string screenshot_path = UISettings::values.screenshot_path.GetValue(); | ||||
|     if (screenshot_path.empty()) { | ||||
|         screenshot_path = FileUtil::GetUserPath(FileUtil::UserPath::UserDir) + "screenshots/"; | ||||
|         FileUtil::CreateFullPath(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() { | ||||
|  | @ -139,31 +149,57 @@ void ConfigureGeneral::ResetDefaults() { | |||
| } | ||||
| 
 | ||||
| void ConfigureGeneral::ApplyConfiguration() { | ||||
|     ConfigurationShared::ApplyPerGameSetting(&Settings::values.region_value, ui->region_combobox, | ||||
|                                              [](s32 index) { return index - 1; }); | ||||
| 
 | ||||
|     ConfigurationShared::ApplyPerGameSetting( | ||||
|         &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()); | ||||
|         }); | ||||
| 
 | ||||
|     ConfigurationShared::ApplyPerGameSetting( | ||||
|         &UISettings::values.screenshot_path, ui->screenshot_combo, | ||||
|         [this](s32) { return ui->screenshot_dir_path->text().toStdString(); }); | ||||
| 
 | ||||
|     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(); | ||||
| 
 | ||||
|         UISettings::values.check_for_update_on_start = ui->toggle_update_check->isChecked(); | ||||
|         UISettings::values.update_on_close = ui->toggle_auto_update->isChecked(); | ||||
| 
 | ||||
|     UISettings::values.screenshot_path = ui->screenshot_dir_path->text(); | ||||
| 
 | ||||
|     Settings::values.region_value = ui->region_combobox->currentIndex() - 1; | ||||
| 
 | ||||
|     if (ui->frame_limit->value() == ui->frame_limit->maximum()) { | ||||
|         Settings::values.frame_limit = 0; | ||||
|     } 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() { | ||||
|     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 SetConfiguration(); | ||||
| 
 | ||||
|     void SetupPerGameUI(); | ||||
| 
 | ||||
| private: | ||||
|     std::unique_ptr<Ui::ConfigureGeneral> ui; | ||||
| }; | ||||
|  |  | |||
|  | @ -6,8 +6,8 @@ | |||
|    <rect> | ||||
|     <x>0</x> | ||||
|     <y>0</y> | ||||
|     <width>408</width> | ||||
|     <height>436</height> | ||||
|     <width>524</width> | ||||
|     <height>578</height> | ||||
|    </rect> | ||||
|   </property> | ||||
|   <property name="windowTitle"> | ||||
|  | @ -17,7 +17,7 @@ | |||
|    <item> | ||||
|     <layout class="QVBoxLayout" name="verticalLayout"> | ||||
|      <item> | ||||
|       <widget class="QGroupBox" name="groupBox"> | ||||
|       <widget class="QGroupBox" name="general_group"> | ||||
|        <property name="title"> | ||||
|         <string>General</string> | ||||
|        </property> | ||||
|  | @ -70,12 +70,34 @@ | |||
|       </widget> | ||||
|      </item> | ||||
|      <item> | ||||
|       <widget class="QGroupBox" name="groupBox_4"> | ||||
|       <widget class="QGroupBox" name="emulation_group"> | ||||
|        <property name="title"> | ||||
|         <string>Emulation</string> | ||||
|        </property> | ||||
|        <layout class="QGridLayout" name="gridLayout"> | ||||
|         <item row="0" column="2"> | ||||
|        <layout class="QVBoxLayout" name="verticalLayout_2"> | ||||
|         <item> | ||||
|          <widget class="QWidget" name="widget_region" native="true"> | ||||
|           <layout class="QHBoxLayout" name="region_layout"> | ||||
|            <property name="leftMargin"> | ||||
|             <number>0</number> | ||||
|            </property> | ||||
|            <property name="topMargin"> | ||||
|             <number>0</number> | ||||
|            </property> | ||||
|            <property name="rightMargin"> | ||||
|             <number>0</number> | ||||
|            </property> | ||||
|            <property name="bottomMargin"> | ||||
|             <number>0</number> | ||||
|            </property> | ||||
|            <item> | ||||
|             <widget class="QLabel" name="region_label"> | ||||
|              <property name="text"> | ||||
|               <string>Region:</string> | ||||
|              </property> | ||||
|             </widget> | ||||
|            </item> | ||||
|            <item> | ||||
|             <widget class="QComboBox" name="region_combobox"> | ||||
|              <item> | ||||
|               <property name="text"> | ||||
|  | @ -119,21 +141,46 @@ | |||
|              </item> | ||||
|             </widget> | ||||
|            </item> | ||||
|         <item row="1" column="0"> | ||||
|           </layout> | ||||
|          </widget> | ||||
|         </item> | ||||
|         <item> | ||||
|          <widget class="QWidget" name="emulation_speed_layout" native="true"> | ||||
|           <layout class="QHBoxLayout" name="emulation_speed_layout_inner"> | ||||
|            <property name="leftMargin"> | ||||
|             <number>0</number> | ||||
|            </property> | ||||
|            <property name="topMargin"> | ||||
|             <number>0</number> | ||||
|            </property> | ||||
|            <property name="rightMargin"> | ||||
|             <number>0</number> | ||||
|            </property> | ||||
|            <property name="bottomMargin"> | ||||
|             <number>0</number> | ||||
|            </property> | ||||
|            <item> | ||||
|             <widget class="QComboBox" name="emulation_speed_combo"> | ||||
|              <item> | ||||
|               <property name="text"> | ||||
|                <string>Use global emulation speed</string> | ||||
|               </property> | ||||
|              </item> | ||||
|              <item> | ||||
|               <property name="text"> | ||||
|                <string>Set emulation speed:</string> | ||||
|               </property> | ||||
|              </item> | ||||
|             </widget> | ||||
|            </item> | ||||
|            <item> | ||||
|             <widget class="QLabel" name="label_emulation_speed"> | ||||
|              <property name="text"> | ||||
|               <string>Emulation Speed:</string> | ||||
|              </property> | ||||
|             </widget> | ||||
|            </item> | ||||
|         <item row="2" column="0"> | ||||
|          <widget class="QCheckBox" name="toggle_alternate_speed"> | ||||
|           <property name="text"> | ||||
|            <string>Use Alternate Speed:</string> | ||||
|           </property> | ||||
|          </widget> | ||||
|         </item> | ||||
|         <item row="1" column="2"> | ||||
|            <item> | ||||
|             <widget class="QSlider" name="frame_limit"> | ||||
|              <property name="minimum"> | ||||
|               <number>0</number> | ||||
|  | @ -158,7 +205,7 @@ | |||
|              </property> | ||||
|             </widget> | ||||
|            </item> | ||||
|         <item row="1" column="1"> | ||||
|            <item> | ||||
|             <widget class="QLabel" name="emulation_speed_display_label"> | ||||
|              <property name="text"> | ||||
|               <string/> | ||||
|  | @ -168,48 +215,9 @@ | |||
|              </property> | ||||
|             </widget> | ||||
|            </item> | ||||
|         <item row="0" column="0"> | ||||
|          <widget class="QLabel" name="label"> | ||||
|           <property name="text"> | ||||
|            <string>Region:</string> | ||||
|           </property> | ||||
|          </widget> | ||||
|         </item> | ||||
|         <item row="2" column="2"> | ||||
|          <widget class="QSlider" name="frame_limit_alternate"> | ||||
|           <property name="minimum"> | ||||
|            <number>0</number> | ||||
|           </property> | ||||
|           <property name="maximum"> | ||||
|            <number>199</number> | ||||
|           </property> | ||||
|           <property name="singleStep"> | ||||
|            <number>5</number> | ||||
|           </property> | ||||
|           <property name="pageStep"> | ||||
|            <number>15</number> | ||||
|           </property> | ||||
|           <property name="value"> | ||||
|            <number>39</number> | ||||
|           </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> | ||||
|         </item> | ||||
|           </layout> | ||||
|          </widget> | ||||
|         </item> | ||||
|        </layout> | ||||
|       </widget> | ||||
|      </item> | ||||
|  | @ -218,17 +226,48 @@ | |||
|        <property name="title"> | ||||
|         <string>Screenshots</string> | ||||
|        </property> | ||||
|        <layout class="QHBoxLayout" name="horizontalLayout_2"> | ||||
|        <layout class="QGridLayout" name="gridLayout"> | ||||
|         <property name="verticalSpacing"> | ||||
|          <number>0</number> | ||||
|         </property> | ||||
|         <item row="0" column="1"> | ||||
|          <widget class="QWidget" name="widget_screenshot" native="true"> | ||||
|           <layout class="QHBoxLayout" name="screenshot_layout"> | ||||
|            <property name="leftMargin"> | ||||
|             <number>0</number> | ||||
|            </property> | ||||
|            <property name="topMargin"> | ||||
|             <number>0</number> | ||||
|            </property> | ||||
|            <property name="rightMargin"> | ||||
|             <number>0</number> | ||||
|            </property> | ||||
|            <property name="bottomMargin"> | ||||
|             <number>0</number> | ||||
|            </property> | ||||
|            <item> | ||||
|          <widget class="QLabel" name="label_2"> | ||||
|             <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"> | ||||
|          </widget> | ||||
|             <widget class="QLineEdit" name="screenshot_dir_path"/> | ||||
|            </item> | ||||
|            <item> | ||||
|             <widget class="QToolButton" name="change_screenshot_dir"> | ||||
|  | @ -240,6 +279,9 @@ | |||
|           </layout> | ||||
|          </widget> | ||||
|         </item> | ||||
|        </layout> | ||||
|       </widget> | ||||
|      </item> | ||||
|      <item alignment="Qt::AlignRight"> | ||||
|       <widget class="QPushButton" name="button_reset_defaults"> | ||||
|        <property name="text"> | ||||
|  | @ -270,12 +312,6 @@ | |||
|   <tabstop>toggle_hide_mouse</tabstop> | ||||
|   <tabstop>toggle_update_check</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> | ||||
|  </tabstops> | ||||
|  <resources/> | ||||
|  |  | |||
|  | @ -6,22 +6,25 @@ | |||
| #ifdef __APPLE__ | ||||
| #include <QMessageBox> | ||||
| #endif | ||||
| #include "citra_qt/configuration/configuration_shared.h" | ||||
| #include "citra_qt/configuration/configure_graphics.h" | ||||
| #include "common/settings.h" | ||||
| #include "core/core.h" | ||||
| #include "core/settings.h" | ||||
| #include "ui_configure_graphics.h" | ||||
| #include "video_core/renderer_opengl/post_processing_opengl.h" | ||||
| 
 | ||||
| ConfigureGraphics::ConfigureGraphics(QWidget* parent) | ||||
|     : QWidget(parent), ui(std::make_unique<Ui::ConfigureGraphics>()) { | ||||
|     ui->setupUi(this); | ||||
| 
 | ||||
|     SetupPerGameUI(); | ||||
|     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()); | ||||
| 
 | ||||
|     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->toggle_disk_shader_cache->setEnabled(checked && ui->toggle_hw_shader->isChecked()); | ||||
|     }); | ||||
|  | @ -31,7 +34,7 @@ ConfigureGraphics::ConfigureGraphics(QWidget* parent) | |||
|                                              ui->toggle_hw_shader->isChecked()); | ||||
| 
 | ||||
|     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->toggle_disk_shader_cache->setEnabled(checked); | ||||
|     }); | ||||
|  | @ -62,25 +65,67 @@ ConfigureGraphics::ConfigureGraphics(QWidget* parent) | |||
| ConfigureGraphics::~ConfigureGraphics() = default; | ||||
| 
 | ||||
| void ConfigureGraphics::SetConfiguration() { | ||||
|     ui->toggle_hw_renderer->setChecked(Settings::values.use_hw_renderer); | ||||
|     ui->toggle_hw_shader->setChecked(Settings::values.use_hw_shader); | ||||
|     ui->toggle_separable_shader->setChecked(Settings::values.separable_shader); | ||||
|     ui->toggle_accurate_mul->setChecked(Settings::values.shaders_accurate_mul); | ||||
|     ui->toggle_shader_jit->setChecked(Settings::values.use_shader_jit); | ||||
|     ui->toggle_disk_shader_cache->setChecked(Settings::values.use_disk_shader_cache); | ||||
|     ui->toggle_vsync_new->setChecked(Settings::values.use_vsync_new); | ||||
|     ui->toggle_hw_renderer->setChecked(Settings::values.use_hw_renderer.GetValue()); | ||||
|     ui->toggle_hw_shader->setChecked(Settings::values.use_hw_shader.GetValue()); | ||||
|     ui->toggle_separable_shader->setChecked(Settings::values.separable_shader.GetValue()); | ||||
|     ui->toggle_accurate_mul->setChecked(Settings::values.shaders_accurate_mul.GetValue()); | ||||
|     ui->toggle_disk_shader_cache->setChecked(Settings::values.use_disk_shader_cache.GetValue()); | ||||
|     ui->toggle_vsync_new->setChecked(Settings::values.use_vsync_new.GetValue()); | ||||
| 
 | ||||
|     if (Settings::IsConfiguringGlobal()) { | ||||
|         ui->toggle_shader_jit->setChecked(Settings::values.use_shader_jit.GetValue()); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void ConfigureGraphics::ApplyConfiguration() { | ||||
|     Settings::values.use_hw_renderer = ui->toggle_hw_renderer->isChecked(); | ||||
|     Settings::values.use_hw_shader = ui->toggle_hw_shader->isChecked(); | ||||
|     Settings::values.separable_shader = ui->toggle_separable_shader->isChecked(); | ||||
|     Settings::values.shaders_accurate_mul = ui->toggle_accurate_mul->isChecked(); | ||||
|     ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_hw_renderer, | ||||
|                                              ui->toggle_hw_renderer, use_hw_renderer); | ||||
|     ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_hw_shader, ui->toggle_hw_shader, | ||||
|                                              use_hw_shader); | ||||
|     ConfigurationShared::ApplyPerGameSetting(&Settings::values.separable_shader, | ||||
|                                              ui->toggle_separable_shader, separable_shader); | ||||
|     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(); | ||||
|     Settings::values.use_disk_shader_cache = ui->toggle_disk_shader_cache->isChecked(); | ||||
|     Settings::values.use_vsync_new = ui->toggle_vsync_new->isChecked(); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void ConfigureGraphics::RetranslateUI() { | ||||
|     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; | ||||
| } | ||||
| 
 | ||||
| namespace ConfigurationShared { | ||||
| enum class CheckState; | ||||
| } | ||||
| 
 | ||||
| class ConfigureGraphics : public QWidget { | ||||
|     Q_OBJECT | ||||
| 
 | ||||
|  | @ -24,6 +28,14 @@ public: | |||
| 
 | ||||
|     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; | ||||
|     QColor bg_color; | ||||
| }; | ||||
|  |  | |||
|  | @ -7,7 +7,7 @@ | |||
| #include "citra_qt/configuration/configure_hotkeys.h" | ||||
| #include "citra_qt/hotkeys.h" | ||||
| #include "citra_qt/util/sequence_dialog/sequence_dialog.h" | ||||
| #include "core/settings.h" | ||||
| #include "common/settings.h" | ||||
| #include "ui_configure_hotkeys.h" | ||||
| 
 | ||||
| ConfigureHotkeys::ConfigureHotkeys(QWidget* parent) | ||||
|  |  | |||
|  | @ -13,7 +13,7 @@ | |||
| #include <QKeySequence> | ||||
| #include <QWidget> | ||||
| #include "common/param_package.h" | ||||
| #include "core/settings.h" | ||||
| #include "common/settings.h" | ||||
| #include "input_common/main.h" | ||||
| 
 | ||||
| class QKeyEvent; | ||||
|  |  | |||
|  | @ -7,7 +7,7 @@ | |||
| #include <memory> | ||||
| #include <QDialog> | ||||
| #include "common/param_package.h" | ||||
| #include "core/settings.h" | ||||
| #include "common/settings.h" | ||||
| #include "input_common/main.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 <QUrl> | ||||
| #include "citra_qt/configuration/configure_storage.h" | ||||
| #include "common/settings.h" | ||||
| #include "core/core.h" | ||||
| #include "core/settings.h" | ||||
| #include "ui_configure_storage.h" | ||||
| 
 | ||||
| ConfigureStorage::ConfigureStorage(QWidget* parent) | ||||
|  | @ -60,7 +60,7 @@ ConfigureStorage::ConfigureStorage(QWidget* parent) | |||
| ConfigureStorage::~ConfigureStorage() = default; | ||||
| 
 | ||||
| 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)); | ||||
|     ui->nand_dir_path->setText(nand_path); | ||||
|     ui->open_nand_dir->setEnabled(!nand_path.isEmpty()); | ||||
|  | @ -71,8 +71,8 @@ void ConfigureStorage::SetConfiguration() { | |||
|     ui->sdmc_dir_path->setText(sdmc_path); | ||||
|     ui->open_sdmc_dir->setEnabled(!sdmc_path.isEmpty()); | ||||
| 
 | ||||
|     ui->toggle_virtual_sd->setChecked(Settings::values.use_virtual_sd); | ||||
|     ui->toggle_custom_storage->setChecked(Settings::values.use_custom_storage); | ||||
|     ui->toggle_virtual_sd->setChecked(Settings::values.use_virtual_sd.GetValue()); | ||||
|     ui->toggle_custom_storage->setChecked(Settings::values.use_custom_storage.GetValue()); | ||||
| 
 | ||||
|     ui->storage_group->setEnabled(!Core::System::GetInstance().IsPoweredOn()); | ||||
| } | ||||
|  |  | |||
|  | @ -4,12 +4,12 @@ | |||
| 
 | ||||
| #include <cstring> | ||||
| #include <QMessageBox> | ||||
| #include "citra_qt/configuration/configuration_shared.h" | ||||
| #include "citra_qt/configuration/configure_system.h" | ||||
| #include "citra_qt/uisettings.h" | ||||
| #include "common/settings.h" | ||||
| #include "core/core.h" | ||||
| #include "core/hle/service/cfg/cfg.h" | ||||
| #include "core/hle/service/ptm/ptm.h" | ||||
| #include "core/settings.h" | ||||
| #include "ui_configure_system.h" | ||||
| 
 | ||||
| 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%")
 | ||||
|     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_speed_label->setVisible(Settings::IsConfiguringGlobal()); | ||||
|     ui->clock_speed_combo->setVisible(!Settings::IsConfiguringGlobal()); | ||||
| 
 | ||||
|     SetupPerGameUI(); | ||||
|     ConfigureTime(); | ||||
| } | ||||
| 
 | ||||
|  | @ -261,12 +265,12 @@ ConfigureSystem::~ConfigureSystem() = default; | |||
| void ConfigureSystem::SetConfiguration() { | ||||
|     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; | ||||
|     date_time.setTime_t(Settings::values.init_time); | ||||
|     date_time.setTime_t(Settings::values.init_time.GetValue()); | ||||
|     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; | ||||
|     ui->edit_init_time_offset_days->setValue(days_offset); | ||||
| 
 | ||||
|  | @ -287,20 +291,29 @@ void ConfigureSystem::SetConfiguration() { | |||
|         ui->label_disable_info->hide(); | ||||
|     } | ||||
| 
 | ||||
|     ui->slider_clock_speed->setValue(SettingsToSlider(Settings::values.cpu_clock_percentage)); | ||||
|     ui->clock_display_label->setText( | ||||
|         QStringLiteral("%1%").arg(Settings::values.cpu_clock_percentage)); | ||||
|     if (!Settings::IsConfiguringGlobal()) { | ||||
|         if (Settings::values.cpu_clock_percentage.UsingGlobal()) { | ||||
|             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() { | ||||
|     // set username
 | ||||
|     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::fromUtf16(reinterpret_cast<const ushort*>(username.data()))); | ||||
|     ui->edit_username->setText(QString::fromStdU16String(username)); | ||||
| 
 | ||||
|     // set birthday
 | ||||
|     std::tie(birthmonth, birthday) = cfg->GetBirthday(); | ||||
|  | @ -337,32 +350,29 @@ void ConfigureSystem::ApplyConfiguration() { | |||
|         bool modified = false; | ||||
| 
 | ||||
|         // 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( | ||||
|             reinterpret_cast<const char16_t*>(ui->edit_username->text().utf16())); | ||||
|         std::u16string new_username = ui->edit_username->text().toStdU16String(); | ||||
|         if (new_username != username) { | ||||
|             cfg->SetUsername(new_username); | ||||
|             modified = true; | ||||
|         } | ||||
| 
 | ||||
|         // apply birthday
 | ||||
|         int new_birthmonth = ui->combo_birthmonth->currentIndex() + 1; | ||||
|         int new_birthday = ui->combo_birthday->currentIndex() + 1; | ||||
|         s32 new_birthmonth = ui->combo_birthmonth->currentIndex() + 1; | ||||
|         s32 new_birthday = ui->combo_birthday->currentIndex() + 1; | ||||
|         if (birthmonth != new_birthmonth || birthday != new_birthday) { | ||||
|             cfg->SetBirthday(new_birthmonth, new_birthday); | ||||
|             modified = true; | ||||
|         } | ||||
| 
 | ||||
|         // apply language
 | ||||
|         int new_language = ui->combo_language->currentIndex(); | ||||
|         s32 new_language = ui->combo_language->currentIndex(); | ||||
|         if (language_index != new_language) { | ||||
|             cfg->SetSystemLanguage(static_cast<Service::CFG::SystemLanguage>(new_language)); | ||||
|             modified = true; | ||||
|         } | ||||
| 
 | ||||
|         // apply sound
 | ||||
|         int new_sound = ui->combo_sound->currentIndex(); | ||||
|         s32 new_sound = ui->combo_sound->currentIndex(); | ||||
|         if (sound_index != new_sound) { | ||||
|             cfg->SetSoundOutputMode(static_cast<Service::CFG::SoundOutputMode>(new_sound)); | ||||
|             modified = true; | ||||
|  | @ -386,6 +396,9 @@ void ConfigureSystem::ApplyConfiguration() { | |||
|             cfg->UpdateConfigNANDSavegame(); | ||||
|         } | ||||
| 
 | ||||
|         ConfigurationShared::ApplyPerGameSetting(&Settings::values.is_new_3ds, ui->toggle_new_3ds, | ||||
|                                                  is_new_3ds); | ||||
| 
 | ||||
|         Settings::values.init_clock = | ||||
|             static_cast<Settings::InitClock>(ui->combo_init_clock->currentIndex()); | ||||
|         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.is_new_3ds = ui->toggle_new_3ds->isChecked(); | ||||
|     } | ||||
| 
 | ||||
|     Settings::values.cpu_clock_percentage = SliderToSettings(ui->slider_clock_speed->value()); | ||||
|     Settings::Apply(); | ||||
|     ConfigurationShared::ApplyPerGameSetting( | ||||
|         &Settings::values.cpu_clock_percentage, ui->clock_speed_combo, | ||||
|         [this](s32) { return SliderToSettings(ui->slider_clock_speed->value()); }); | ||||
| } | ||||
| 
 | ||||
| void ConfigureSystem::UpdateBirthdayComboBox(int birthmonth_index) { | ||||
|  | @ -410,10 +423,10 @@ void ConfigureSystem::UpdateBirthdayComboBox(int birthmonth_index) { | |||
|         return; | ||||
| 
 | ||||
|     // 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
 | ||||
|     int days = days_in_month[birthmonth_index]; | ||||
|     s32 days = days_in_month[birthmonth_index]; | ||||
| 
 | ||||
|     // if the selected day is out of range,
 | ||||
|     // reset it to 1st
 | ||||
|  | @ -422,7 +435,7 @@ void ConfigureSystem::UpdateBirthdayComboBox(int birthmonth_index) { | |||
| 
 | ||||
|     // update the day combo box
 | ||||
|     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)); | ||||
|     } | ||||
| 
 | ||||
|  | @ -442,15 +455,16 @@ void ConfigureSystem::ConfigureTime() { | |||
| } | ||||
| 
 | ||||
| void ConfigureSystem::UpdateInitTime(int init_clock) { | ||||
|     const bool is_global = Settings::IsConfiguringGlobal(); | ||||
|     const bool is_fixed_time = | ||||
|         static_cast<Settings::InitClock>(init_clock) == Settings::InitClock::FixedTime; | ||||
| 
 | ||||
|     ui->label_init_time->setVisible(is_fixed_time); | ||||
|     ui->edit_init_time->setVisible(is_fixed_time); | ||||
|     ui->label_init_time->setVisible(is_fixed_time && is_global); | ||||
|     ui->edit_init_time->setVisible(is_fixed_time && is_global); | ||||
| 
 | ||||
|     ui->label_init_time_offset->setVisible(!is_fixed_time); | ||||
|     ui->edit_init_time_offset_days->setVisible(!is_fixed_time); | ||||
|     ui->edit_init_time_offset_time->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 && is_global); | ||||
|     ui->edit_init_time_offset_time->setVisible(!is_fixed_time && is_global); | ||||
| } | ||||
| 
 | ||||
| void ConfigureSystem::RefreshConsoleID() { | ||||
|  | @ -475,3 +489,43 @@ void ConfigureSystem::RefreshConsoleID() { | |||
| void ConfigureSystem::RetranslateUI() { | ||||
|     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; | ||||
| } | ||||
| 
 | ||||
| namespace ConfigurationShared { | ||||
| enum class CheckState; | ||||
| } | ||||
| 
 | ||||
| namespace Service { | ||||
| namespace CFG { | ||||
| class Module; | ||||
|  | @ -37,6 +41,9 @@ private: | |||
|     void UpdateInitTime(int init_clock); | ||||
|     void RefreshConsoleID(); | ||||
| 
 | ||||
|     void SetupPerGameUI(); | ||||
| 
 | ||||
|     ConfigurationShared::CheckState is_new_3ds; | ||||
|     std::unique_ptr<Ui::ConfigureSystem> ui; | ||||
|     bool enabled = false; | ||||
| 
 | ||||
|  |  | |||
|  | @ -6,8 +6,8 @@ | |||
|    <rect> | ||||
|     <x>0</x> | ||||
|     <y>0</y> | ||||
|     <width>520</width> | ||||
|     <height>564</height> | ||||
|     <width>525</width> | ||||
|     <height>619</height> | ||||
|    </rect> | ||||
|   </property> | ||||
|   <property name="windowTitle"> | ||||
|  | @ -344,19 +344,39 @@ | |||
|       </widget> | ||||
|      </item> | ||||
|      <item> | ||||
|       <widget class="QGroupBox" name="groupBox"> | ||||
|       <widget class="QGroupBox" name="group_advanced"> | ||||
|        <property name="title"> | ||||
|         <string>Advanced</string> | ||||
|        </property> | ||||
|        <layout class="QGridLayout" name="gridLayout_2"> | ||||
|         <item row="0" column="0"> | ||||
|          <widget class="QLabel" name="label_3"> | ||||
|          <widget class="QWidget" name="clock_speed_widget" native="true"> | ||||
|           <layout class="QHBoxLayout" name="clock_speed_layout"> | ||||
|            <property name="spacing"> | ||||
|             <number>7</number> | ||||
|            </property> | ||||
|            <item> | ||||
|             <widget class="QComboBox" name="clock_speed_combo"> | ||||
|              <item> | ||||
|               <property name="text"> | ||||
|                <string>Use global clock speed</string> | ||||
|               </property> | ||||
|              </item> | ||||
|              <item> | ||||
|               <property name="text"> | ||||
|                <string>Set clock speed:</string> | ||||
|               </property> | ||||
|              </item> | ||||
|             </widget> | ||||
|            </item> | ||||
|            <item> | ||||
|             <widget class="QLabel" name="clock_speed_label"> | ||||
|              <property name="text"> | ||||
|               <string>CPU Clock Speed</string> | ||||
|              </property> | ||||
|             </widget> | ||||
|            </item> | ||||
|         <item row="0" column="2"> | ||||
|            <item> | ||||
|             <widget class="QSlider" name="slider_clock_speed"> | ||||
|              <property name="toolTip"> | ||||
|               <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> | ||||
|  | @ -384,7 +404,7 @@ | |||
|              </property> | ||||
|             </widget> | ||||
|            </item> | ||||
|         <item row="0" column="1"> | ||||
|            <item> | ||||
|             <widget class="QLabel" name="clock_display_label"> | ||||
|              <property name="text"> | ||||
|               <string/> | ||||
|  | @ -397,6 +417,9 @@ | |||
|           </layout> | ||||
|          </widget> | ||||
|         </item> | ||||
|        </layout> | ||||
|       </widget> | ||||
|      </item> | ||||
|      <item> | ||||
|       <layout class="QHBoxLayout" name="horizontalLayout_2"/> | ||||
|      </item> | ||||
|  | @ -449,7 +472,6 @@ | |||
|   <tabstop>edit_init_time</tabstop> | ||||
|   <tabstop>spinBox_play_coins</tabstop> | ||||
|   <tabstop>button_regenerate_console_id</tabstop> | ||||
|   <tabstop>slider_clock_speed</tabstop> | ||||
|  </tabstops> | ||||
|  <resources/> | ||||
|  <connections/> | ||||
|  |  | |||
|  | @ -9,7 +9,7 @@ | |||
| #include <optional> | ||||
| #include <vector> | ||||
| #include <QDialog> | ||||
| #include "core/settings.h" | ||||
| #include "common/settings.h" | ||||
| 
 | ||||
| class QItemSelection; | ||||
| class QModelIndex; | ||||
|  |  | |||
|  | @ -46,12 +46,14 @@ void ConfigureUi::SetConfiguration() { | |||
|     ui->language_combobox->setCurrentIndex( | ||||
|         ui->language_combobox->findData(UISettings::values.language)); | ||||
|     ui->icon_size_combobox->setCurrentIndex( | ||||
|         static_cast<int>(UISettings::values.game_list_icon_size)); | ||||
|     ui->row_1_text_combobox->setCurrentIndex(static_cast<int>(UISettings::values.game_list_row_1)); | ||||
|     ui->row_2_text_combobox->setCurrentIndex(static_cast<int>(UISettings::values.game_list_row_2) + | ||||
|                                              1); | ||||
|     ui->toggle_hide_no_icon->setChecked(UISettings::values.game_list_hide_no_icon); | ||||
|     ui->toggle_single_line_mode->setChecked(UISettings::values.game_list_single_line_mode); | ||||
|         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.GetValue())); | ||||
|     ui->row_2_text_combobox->setCurrentIndex( | ||||
|         static_cast<int>(UISettings::values.game_list_row_2.GetValue()) + 1); | ||||
|     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() { | ||||
|  |  | |||
|  | @ -87,7 +87,7 @@ void ConfigureWeb::SetConfiguration() { | |||
|         tr("Telemetry ID: 0x%1").arg(QString::number(Core::GetTelemetryId(), 16).toUpper())); | ||||
|     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() { | ||||
|  |  | |||
|  | @ -15,10 +15,10 @@ | |||
| namespace Debugger { | ||||
| void ToggleConsole() { | ||||
|     static bool console_shown = false; | ||||
|     if (console_shown == UISettings::values.show_console) { | ||||
|     if (console_shown == UISettings::values.show_console.GetValue()) { | ||||
|         return; | ||||
|     } else { | ||||
|         console_shown = UISettings::values.show_console; | ||||
|         console_shown = UISettings::values.show_console.GetValue(); | ||||
|     } | ||||
| 
 | ||||
| #ifdef _WIN32 | ||||
|  |  | |||
|  | @ -7,7 +7,7 @@ | |||
| #include <QLayout> | ||||
| #include <QScrollArea> | ||||
| #include "citra_qt/debugger/lle_service_modules.h" | ||||
| #include "core/settings.h" | ||||
| #include "common/settings.h" | ||||
| 
 | ||||
| LLEServiceModulesWidget::LLEServiceModulesWidget(QWidget* parent) | ||||
|     : QDockWidget(tr("Toggle LLE Service Modules"), parent) { | ||||
|  |  | |||
|  | @ -7,13 +7,13 @@ | |||
| #include "citra_qt/uisettings.h" | ||||
| #include "citra_qt/util/util.h" | ||||
| #include "common/assert.h" | ||||
| #include "common/settings.h" | ||||
| #include "core/hle/kernel/event.h" | ||||
| #include "core/hle/kernel/mutex.h" | ||||
| #include "core/hle/kernel/semaphore.h" | ||||
| #include "core/hle/kernel/thread.h" | ||||
| #include "core/hle/kernel/timer.h" | ||||
| #include "core/hle/kernel/wait_object.h" | ||||
| #include "core/settings.h" | ||||
| 
 | ||||
| namespace { | ||||
| 
 | ||||
|  |  | |||
|  | @ -7,7 +7,7 @@ | |||
| #include "citra_qt/dumping/dumping_dialog.h" | ||||
| #include "citra_qt/dumping/options_dialog.h" | ||||
| #include "citra_qt/uisettings.h" | ||||
| #include "core/settings.h" | ||||
| #include "common/settings.h" | ||||
| #include "ui_dumping_dialog.h" | ||||
| 
 | ||||
| DumpingDialog::DumpingDialog(QWidget* parent) | ||||
|  |  | |||
|  | @ -3,6 +3,7 @@ | |||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include <QApplication> | ||||
| #include <QDir> | ||||
| #include <QFileInfo> | ||||
| #include <QFileSystemWatcher> | ||||
| #include <QHBoxLayout> | ||||
|  | @ -28,9 +29,11 @@ | |||
| #include "citra_qt/main.h" | ||||
| #include "citra_qt/uisettings.h" | ||||
| #include "common/logging/log.h" | ||||
| #include "common/settings.h" | ||||
| #include "core/file_sys/archive_extsavedata.h" | ||||
| #include "core/file_sys/archive_source_sd_savedata.h" | ||||
| #include "core/hle/service/fs/archive.h" | ||||
| #include "qcursor.h" | ||||
| 
 | ||||
| GameListSearchField::KeyReleaseEater::KeyReleaseEater(GameList* gamelist, QObject* parent) | ||||
|     : QObject(parent), gamelist{gamelist} {} | ||||
|  | @ -462,9 +465,20 @@ void GameList::PopupContextMenu(const QPoint& menu_location) { | |||
|     default: | ||||
|         break; | ||||
|     } | ||||
| 
 | ||||
|     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, | ||||
|                             u64 extdata_id) { | ||||
|     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 = | ||||
|         context_menu.addAction(tr("Open Custom Texture 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* 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 = | ||||
|         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); | ||||
|     open_save_location->setVisible( | ||||
|     open_save_location->setEnabled( | ||||
|         is_application && FileUtil::Exists(FileSys::ArchiveSource_SDSaveData::GetSaveDataPathFor( | ||||
|                               sdmc_dir, program_id))); | ||||
| 
 | ||||
|     if (extdata_id) { | ||||
|         open_extdata_location->setVisible( | ||||
|         open_extdata_location->setEnabled( | ||||
|             is_application && | ||||
|             FileUtil::Exists(FileSys::GetExtDataPathFromId(sdmc_dir, extdata_id))); | ||||
|     } else { | ||||
|  | @ -495,18 +522,20 @@ void GameList::AddGamePopup(QMenu& context_menu, const QString& path, u64 progra | |||
|     } | ||||
| 
 | ||||
|     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)); | ||||
|     open_update_location->setVisible( | ||||
|     open_update_location->setEnabled( | ||||
|         is_application && FileUtil::Exists(Service::AM::GetTitlePath(Service::FS::MediaType::SDMC, | ||||
|                                                                      program_id + 0xe00000000) + | ||||
|                                            "content/")); | ||||
|     auto it = FindMatchingCompatibilityEntry(compatibility_list, program_id); | ||||
| 
 | ||||
|     open_texture_dump_location->setVisible(is_application); | ||||
|     open_texture_load_location->setVisible(is_application); | ||||
|     open_mods_location->setVisible(is_application); | ||||
|     dump_romfs->setVisible(is_application); | ||||
|     open_texture_dump_location->setEnabled(is_application); | ||||
|     open_texture_load_location->setEnabled(is_application); | ||||
|     open_mods_location->setEnabled(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()); | ||||
| 
 | ||||
|  | @ -543,11 +572,32 @@ void GameList::AddGamePopup(QMenu& context_menu, const QString& path, u64 progra | |||
|             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, | ||||
|             [this, path, program_id] { emit DumpRomFSRequested(path, program_id); }); | ||||
|     connect(navigate_to_gamedb_entry, &QAction::triggered, this, [this, program_id]() { | ||||
|         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) { | ||||
|  |  | |||
|  | @ -37,6 +37,8 @@ enum class GameListOpenTarget { | |||
|     TEXTURE_DUMP = 4, | ||||
|     TEXTURE_LOAD = 5, | ||||
|     MODS = 6, | ||||
|     DLC_DATA = 7, | ||||
|     SHADER_CACHE = 8 | ||||
| }; | ||||
| 
 | ||||
| class GameList : public QWidget { | ||||
|  | @ -82,6 +84,7 @@ signals: | |||
|     void OpenFolderRequested(u64 program_id, GameListOpenTarget target); | ||||
|     void NavigateToGamedbEntryRequested(u64 program_id, | ||||
|                                         const CompatibilityList& compatibility_list); | ||||
|     void OpenPerGameGeneralRequested(const QString file); | ||||
|     void DumpRomFSRequested(QString game_path, u64 program_id); | ||||
|     void OpenDirectory(const QString& directory); | ||||
|     void AddDirectory(); | ||||
|  |  | |||
|  | @ -160,17 +160,19 @@ public: | |||
|         setData(qulonglong(program_id), ProgramIdRole); | ||||
|         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
 | ||||
|             setData(QPixmap(), Qt::DecorationRole); | ||||
|         } | ||||
| 
 | ||||
|         bool large = | ||||
|             UISettings::values.game_list_icon_size == UISettings::GameListIconSize::LargeIcon; | ||||
|         bool large = UISettings::values.game_list_icon_size.GetValue() == | ||||
|                      UISettings::GameListIconSize::LargeIcon; | ||||
| 
 | ||||
|         if (!Loader::IsValidSMDH(smdh_data)) { | ||||
|             // 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); | ||||
|             return; | ||||
|         } | ||||
|  | @ -179,7 +181,8 @@ public: | |||
|         memcpy(&smdh, smdh_data.data(), sizeof(Loader::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); | ||||
|         } | ||||
| 
 | ||||
|  | @ -211,16 +214,17 @@ public: | |||
|                  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) | ||||
|                 return row1.toLower(); | ||||
| 
 | ||||
|             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 (!row1.isEmpty()) { | ||||
|                     row2 = UISettings::values.game_list_single_line_mode | ||||
|                     row2 = UISettings::values.game_list_single_line_mode.GetValue() | ||||
|                                ? QStringLiteral("     ") | ||||
|                                : QStringLiteral("\n     "); | ||||
|                 } | ||||
|  | @ -355,7 +359,7 @@ public: | |||
|         UISettings::GameDir* game_dir = &directory; | ||||
|         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) { | ||||
|         case GameListItemType::InstalledDir: | ||||
|             setData(QIcon::fromTheme(QStringLiteral("sd_card")).pixmap(icon_size), | ||||
|  | @ -398,7 +402,7 @@ public: | |||
|     explicit GameListAddDir() { | ||||
|         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(QObject::tr("Add New Game Directory"), Qt::DisplayRole); | ||||
|     } | ||||
|  |  | |||
|  | @ -3,6 +3,7 @@ | |||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include <clocale> | ||||
| #include <filesystem> | ||||
| #include <fstream> | ||||
| #include <memory> | ||||
| #include <thread> | ||||
|  | @ -34,6 +35,7 @@ | |||
| #include "citra_qt/compatibility_list.h" | ||||
| #include "citra_qt/configuration/config.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/graphics/graphics.h" | ||||
| #include "citra_qt/debugger/graphics/graphics_breakpoints.h" | ||||
|  | @ -70,9 +72,11 @@ | |||
| #include "common/microprofile.h" | ||||
| #include "common/scm_rev.h" | ||||
| #include "common/scope_exit.h" | ||||
| #include "common/string_util.h" | ||||
| #ifdef ARCHITECTURE_x86_64 | ||||
| #include "common/x64/cpu_detect.h" | ||||
| #endif | ||||
| #include "common/settings.h" | ||||
| #include "core/core.h" | ||||
| #include "core/dumping/backend.h" | ||||
| #include "core/file_sys/archive_extsavedata.h" | ||||
|  | @ -85,7 +89,6 @@ | |||
| #include "core/loader/loader.h" | ||||
| #include "core/movie.h" | ||||
| #include "core/savestate.h" | ||||
| #include "core/settings.h" | ||||
| #include "game_list_p.h" | ||||
| #include "input_common/main.h" | ||||
| #include "network/network_settings.h" | ||||
|  | @ -124,11 +127,13 @@ enum class CalloutFlag : uint32_t { | |||
| }; | ||||
| 
 | ||||
| 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; | ||||
|     } | ||||
| 
 | ||||
|     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 = | ||||
|         tr("<a href='https://citra-emu.org/entry/telemetry-and-why-thats-a-good-thing/'>Anonymous " | ||||
|            "data is collected</a> to help improve Citra. " | ||||
|  | @ -143,7 +148,7 @@ const int GMainWindow::max_recent_files_item; | |||
| 
 | ||||
| static void InitializeLogging() { | ||||
|     Log::Filter log_filter; | ||||
|     log_filter.ParseFilterString(Settings::values.log_filter); | ||||
|     log_filter.ParseFilterString(Settings::values.log_filter.GetValue()); | ||||
|     Log::SetGlobalFilter(log_filter); | ||||
| 
 | ||||
|     const std::string& log_dir = FileUtil::GetUserPath(FileUtil::UserPath::LogDir); | ||||
|  | @ -175,7 +180,7 @@ GMainWindow::GMainWindow() | |||
|     default_theme_paths = QIcon::themeSearchPaths(); | ||||
|     UpdateUITheme(); | ||||
| 
 | ||||
|     SetDiscordEnabled(UISettings::values.enable_discord_presence); | ||||
|     SetDiscordEnabled(UISettings::values.enable_discord_presence.GetValue()); | ||||
|     discord_rpc->Update(); | ||||
| 
 | ||||
|     Network::Init(); | ||||
|  | @ -556,8 +561,7 @@ void GMainWindow::InitializeHotkeys() { | |||
|             }); | ||||
|     connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Toggle Alternate Speed"), this), | ||||
|             &QShortcut::activated, this, [&] { | ||||
|                 Settings::values.use_frame_limit_alternate = | ||||
|                     !Settings::values.use_frame_limit_alternate; | ||||
|                 Settings::values.frame_limit.SetGlobal(!Settings::values.frame_limit.UsingGlobal()); | ||||
|                 UpdateStatusBar(); | ||||
|             }); | ||||
|     connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Toggle Texture Dumping"), this), | ||||
|  | @ -568,43 +572,26 @@ void GMainWindow::InitializeHotkeys() { | |||
|     static constexpr u16 SPEED_LIMIT_STEP = 5; | ||||
|     connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Increase Speed Limit"), this), | ||||
|             &QShortcut::activated, this, [&] { | ||||
|                 if (Settings::values.use_frame_limit_alternate) { | ||||
|                     if (Settings::values.frame_limit_alternate == 0) { | ||||
|                 if (Settings::values.frame_limit.GetValue() == 0) { | ||||
|                     return; | ||||
|                 } | ||||
|                     if (Settings::values.frame_limit_alternate < 995 - SPEED_LIMIT_STEP) { | ||||
|                         Settings::values.frame_limit_alternate += SPEED_LIMIT_STEP; | ||||
|                     } else { | ||||
|                         Settings::values.frame_limit_alternate = 0; | ||||
|                     } | ||||
|                 } else { | ||||
|                     if (Settings::values.frame_limit == 0) { | ||||
|                         return; | ||||
|                     } | ||||
|                     if (Settings::values.frame_limit < 995 - SPEED_LIMIT_STEP) { | ||||
|                         Settings::values.frame_limit += SPEED_LIMIT_STEP; | ||||
|                 if (Settings::values.frame_limit.GetValue() < 995 - SPEED_LIMIT_STEP) { | ||||
|                     Settings::values.frame_limit.SetValue(Settings::values.frame_limit.GetValue() + | ||||
|                                                           SPEED_LIMIT_STEP); | ||||
|                 } else { | ||||
|                     Settings::values.frame_limit = 0; | ||||
|                 } | ||||
|                 } | ||||
|                 UpdateStatusBar(); | ||||
|             }); | ||||
|     connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Decrease Speed Limit"), this), | ||||
|             &QShortcut::activated, this, [&] { | ||||
|                 if (Settings::values.use_frame_limit_alternate) { | ||||
|                     if (Settings::values.frame_limit_alternate == 0) { | ||||
|                         Settings::values.frame_limit_alternate = 995; | ||||
|                     } else if (Settings::values.frame_limit_alternate > SPEED_LIMIT_STEP) { | ||||
|                         Settings::values.frame_limit_alternate -= SPEED_LIMIT_STEP; | ||||
|                     } | ||||
|                 } else { | ||||
|                     if (Settings::values.frame_limit == 0) { | ||||
|                 if (Settings::values.frame_limit.GetValue() == 0) { | ||||
|                     Settings::values.frame_limit = 995; | ||||
|                     } else if (Settings::values.frame_limit > SPEED_LIMIT_STEP) { | ||||
|                         Settings::values.frame_limit -= SPEED_LIMIT_STEP; | ||||
|                 } else if (Settings::values.frame_limit.GetValue() > SPEED_LIMIT_STEP) { | ||||
|                     Settings::values.frame_limit.SetValue(Settings::values.frame_limit.GetValue() - | ||||
|                                                           SPEED_LIMIT_STEP); | ||||
|                     UpdateStatusBar(); | ||||
|                 } | ||||
|                 } | ||||
|                 UpdateStatusBar(); | ||||
|             }); | ||||
|     connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Toggle Frame Advancing"), this), | ||||
|  | @ -663,25 +650,26 @@ void GMainWindow::RestoreUIState() { | |||
|     render_window->restoreGeometry(UISettings::values.renderwindow_geometry); | ||||
| #if MICROPROFILE_ENABLED | ||||
|     microProfileDialog->restoreGeometry(UISettings::values.microprofile_geometry); | ||||
|     microProfileDialog->setVisible(UISettings::values.microprofile_visible); | ||||
|     microProfileDialog->setVisible(UISettings::values.microprofile_visible.GetValue()); | ||||
| #endif | ||||
|     ui->action_Cheats->setEnabled(false); | ||||
| 
 | ||||
|     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(); | ||||
| 
 | ||||
|     ui->action_Fullscreen->setChecked(UISettings::values.fullscreen); | ||||
|     ui->action_Fullscreen->setChecked(UISettings::values.fullscreen.GetValue()); | ||||
|     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()); | ||||
| 
 | ||||
|     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()); | ||||
| 
 | ||||
|     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()); | ||||
| } | ||||
| 
 | ||||
|  | @ -717,6 +705,9 @@ void GMainWindow::ConnectWidgetEvents() { | |||
|     connect(game_list, &GameList::PopulatingCompleted, this, | ||||
|             [this] { multiplayer_state->UpdateGameList(game_list->GetModel()); }); | ||||
| 
 | ||||
|     connect(game_list, &GameList::OpenPerGameGeneralRequested, this, | ||||
|             &GMainWindow::OnGameListOpenPerGameProperties); | ||||
| 
 | ||||
|     connect(this, &GMainWindow::EmulationStarting, render_window, | ||||
|             &GRenderWindow::OnEmulationStarting); | ||||
|     connect(this, &GMainWindow::EmulationStopping, render_window, | ||||
|  | @ -752,6 +743,8 @@ void GMainWindow::ConnectMenuEvents() { | |||
|     connect(ui->action_Report_Compatibility, &QAction::triggered, this, | ||||
|             &GMainWindow::OnMenuReportCompatibility); | ||||
|     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); | ||||
| 
 | ||||
|     // View
 | ||||
|  | @ -1086,6 +1079,22 @@ void GMainWindow::BootGame(const QString& filename) { | |||
|         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
 | ||||
|     UpdateUISettings(); | ||||
|     game_list->SaveInterfaceLayout(); | ||||
|  | @ -1239,6 +1248,7 @@ void GMainWindow::ShutdownGame() { | |||
|     ui->action_Stop->setEnabled(false); | ||||
|     ui->action_Restart->setEnabled(false); | ||||
|     ui->action_Cheats->setEnabled(false); | ||||
|     ui->action_Configure_Current_Game->setEnabled(false); | ||||
|     ui->action_Load_Amiibo->setEnabled(false); | ||||
|     ui->action_Remove_Amiibo->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/"; | ||||
|         break; | ||||
|     } | ||||
|     case GameListOpenTarget::UPDATE_DATA: | ||||
|     case GameListOpenTarget::UPDATE_DATA: { | ||||
|         open_target = "Update Data"; | ||||
|         path = Service::AM::GetTitlePath(Service::FS::MediaType::SDMC, data_id + 0xe00000000) + | ||||
|                "content/"; | ||||
|         break; | ||||
|     case GameListOpenTarget::TEXTURE_DUMP: | ||||
|     } | ||||
|     case GameListOpenTarget::TEXTURE_DUMP: { | ||||
|         open_target = "Dumped Textures"; | ||||
|         path = fmt::format("{}textures/{:016X}/", | ||||
|                            FileUtil::GetUserPath(FileUtil::UserPath::DumpDir), data_id); | ||||
|         break; | ||||
|     case GameListOpenTarget::TEXTURE_LOAD: | ||||
|     } | ||||
|     case GameListOpenTarget::TEXTURE_LOAD: { | ||||
|         open_target = "Custom Textures"; | ||||
|         path = fmt::format("{}textures/{:016X}/", | ||||
|                            FileUtil::GetUserPath(FileUtil::UserPath::LoadDir), data_id); | ||||
|         break; | ||||
|     case GameListOpenTarget::MODS: | ||||
|     } | ||||
|     case GameListOpenTarget::MODS: { | ||||
|         open_target = "Mods"; | ||||
|         path = fmt::format("{}mods/{:016X}/", FileUtil::GetUserPath(FileUtil::UserPath::LoadDir), | ||||
|                            data_id); | ||||
|         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: | ||||
|         LOG_ERROR(Frontend, "Unexpected target {}", static_cast<int>(target)); | ||||
|         return; | ||||
|  | @ -1529,6 +1555,19 @@ void GMainWindow::OnGameListShowList(bool 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() { | ||||
|     const QString extensions = QStringLiteral("*.").append( | ||||
|         GameList::supported_file_extensions.join(QStringLiteral(" *."))); | ||||
|  | @ -1654,6 +1693,7 @@ void GMainWindow::OnStartGame() { | |||
|     ui->action_Stop->setEnabled(true); | ||||
|     ui->action_Restart->setEnabled(true); | ||||
|     ui->action_Cheats->setEnabled(true); | ||||
|     ui->action_Configure_Current_Game->setEnabled(true); | ||||
|     ui->action_Load_Amiibo->setEnabled(true); | ||||
|     ui->action_Report_Compatibility->setEnabled(true); | ||||
|     ui->action_Capture_Screenshot->setEnabled(true); | ||||
|  | @ -1676,6 +1716,7 @@ void GMainWindow::OnPauseGame() { | |||
| 
 | ||||
| void GMainWindow::OnStopGame() { | ||||
|     ShutdownGame(); | ||||
|     Settings::RestoreGlobalState(false); | ||||
| } | ||||
| 
 | ||||
| void GMainWindow::OnLoadComplete() { | ||||
|  | @ -1769,7 +1810,7 @@ void GMainWindow::UpdateSecondaryWindowVisibility() { | |||
|     if (!emulation_running) { | ||||
|         return; | ||||
|     } | ||||
|     if (Settings::values.layout_option == Settings::LayoutOption::SeparateWindows) { | ||||
|     if (Settings::values.layout_option.GetValue() == Settings::LayoutOption::SeparateWindows) { | ||||
|         secondary_window->RestoreGeometry(); | ||||
|         secondary_window->show(); | ||||
|     } else { | ||||
|  | @ -1800,7 +1841,7 @@ void GMainWindow::ChangeScreenLayout() { | |||
| 
 | ||||
| void GMainWindow::ToggleScreenLayout() { | ||||
|     const Settings::LayoutOption new_layout = []() { | ||||
|         switch (Settings::values.layout_option) { | ||||
|         switch (Settings::values.layout_option.GetValue()) { | ||||
|         case Settings::LayoutOption::Default: | ||||
|             return Settings::LayoutOption::SingleScreen; | ||||
|         case Settings::LayoutOption::SingleScreen: | ||||
|  | @ -1812,7 +1853,8 @@ void GMainWindow::ToggleScreenLayout() { | |||
|         case Settings::LayoutOption::SeparateWindows: | ||||
|             return Settings::LayoutOption::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; | ||||
|         } | ||||
|     }(); | ||||
|  | @ -1864,6 +1906,7 @@ void GMainWindow::OnLoadState() { | |||
| } | ||||
| 
 | ||||
| void GMainWindow::OnConfigure() { | ||||
|     Settings::SetConfiguringGlobal(true); | ||||
|     ConfigureDialog configureDialog(this, hotkey_registry, | ||||
|                                     !multiplayer_state->IsHostingPublicRoom()); | ||||
|     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 auto old_input_profiles = Settings::values.input_profiles; | ||||
|     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(); | ||||
|     if (result == QDialog::Accepted) { | ||||
|         configureDialog.ApplyConfiguration(); | ||||
|         InitializeHotkeys(); | ||||
|         if (UISettings::values.theme != old_theme) | ||||
|             UpdateUITheme(); | ||||
|         if (UISettings::values.enable_discord_presence != old_discord_presence) | ||||
|             SetDiscordEnabled(UISettings::values.enable_discord_presence); | ||||
|         if (UISettings::values.enable_discord_presence.GetValue() != old_discord_presence) | ||||
|             SetDiscordEnabled(UISettings::values.enable_discord_presence.GetValue()); | ||||
|         if (!multiplayer_state->IsHostingPublicRoom()) | ||||
|             multiplayer_state->UpdateCredentials(); | ||||
|         emit UpdateThemedIcons(); | ||||
|  | @ -2057,24 +2100,26 @@ void GMainWindow::OnSaveMovie() { | |||
| 
 | ||||
| void GMainWindow::OnCaptureScreenshot() { | ||||
|     OnPauseGame(); | ||||
|     QString path = UISettings::values.screenshot_path; | ||||
|     if (!FileUtil::IsDirectory(path.toStdString())) { | ||||
|         if (!FileUtil::CreateFullPath(path.toStdString())) { | ||||
|     std::string path = UISettings::values.screenshot_path.GetValue(); | ||||
|     if (!FileUtil::IsDirectory(path)) { | ||||
|         if (!FileUtil::CreateFullPath(path)) { | ||||
|             QMessageBox::information(this, tr("Invalid Screenshot Directory"), | ||||
|                                      tr("Cannot create specified screenshot directory. Screenshot " | ||||
|                                         "path is set back to its default value.")); | ||||
|             path = QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::UserDir)); | ||||
|             path.append(QStringLiteral("screenshots/")); | ||||
|             path = FileUtil::GetUserPath(FileUtil::UserPath::UserDir); | ||||
|             path.append("screenshots/"); | ||||
|             UISettings::values.screenshot_path = path; | ||||
|         }; | ||||
|     } | ||||
|     const QString filename = game_title.remove(QRegularExpression(QStringLiteral("[\\/:?\"<>|]"))); | ||||
|     const QString timestamp = | ||||
|         QDateTime::currentDateTime().toString(QStringLiteral("dd.MM.yy_hh.mm.ss.z")); | ||||
|     path.append(QStringLiteral("/%1_%2.png").arg(filename, timestamp)); | ||||
|     const std::string filename = | ||||
|         game_title.remove(QRegularExpression(QStringLiteral("[\\/:?\"<>|]"))).toStdString(); | ||||
|     const std::string 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; | ||||
|     screenshot_window->CaptureScreenshot(UISettings::values.screenshot_resolution_factor, path); | ||||
|     screenshot_window->CaptureScreenshot(UISettings::values.screenshot_resolution_factor.GetValue(), | ||||
|                                          QString::fromStdString(path)); | ||||
|     OnStartGame(); | ||||
| } | ||||
| 
 | ||||
|  | @ -2166,22 +2211,12 @@ void GMainWindow::UpdateStatusBar() { | |||
| 
 | ||||
|     auto results = Core::System::GetInstance().GetAndResetPerfStats(); | ||||
| 
 | ||||
|     if (Settings::values.use_frame_limit_alternate) { | ||||
|         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) { | ||||
|     if (Settings::values.frame_limit.GetValue() == 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)); | ||||
|                                      .arg(Settings::values.frame_limit.GetValue())); | ||||
|     } | ||||
|     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)); | ||||
|  | @ -2192,7 +2227,7 @@ void GMainWindow::UpdateStatusBar() { | |||
| } | ||||
| 
 | ||||
| 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(); | ||||
|         ShowMouseCursor(); | ||||
|         return; | ||||
|  | @ -2455,6 +2490,35 @@ void GMainWindow::OnLanguageChanged(const QString& locale) { | |||
|         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() { | ||||
|     OnPauseGame(); | ||||
|     QMessageBox::information(this, tr("Playback Completed"), tr("Movie playback completed.")); | ||||
|  | @ -2489,18 +2553,19 @@ void GMainWindow::UpdateUISettings() { | |||
| } | ||||
| 
 | ||||
| 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); | ||||
|     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); | ||||
|     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); | ||||
|     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); | ||||
|     ui->action_Screen_Layout_Separate_Windows->setChecked(Settings::values.layout_option == | ||||
|                                                           Settings::LayoutOption::SeparateWindows); | ||||
|     ui->action_Screen_Layout_Swap_Screens->setChecked(Settings::values.swap_screen); | ||||
|     ui->action_Screen_Layout_Upright_Screens->setChecked(Settings::values.upright_screen); | ||||
|     ui->action_Screen_Layout_Separate_Windows->setChecked( | ||||
|         Settings::values.layout_option.GetValue() == Settings::LayoutOption::SeparateWindows); | ||||
|     ui->action_Screen_Layout_Swap_Screens->setChecked(Settings::values.swap_screen.GetValue()); | ||||
|     ui->action_Screen_Layout_Upright_Screens->setChecked( | ||||
|         Settings::values.upright_screen.GetValue()); | ||||
| } | ||||
| 
 | ||||
| void GMainWindow::RetranslateStatusBar() { | ||||
|  | @ -2573,11 +2638,13 @@ int main(int argc, char* argv[]) { | |||
| 
 | ||||
|     // Register frontend applets
 | ||||
|     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
 | ||||
|     Core::System::GetInstance().RegisterImageInterface(std::make_shared<QtImageInterface>()); | ||||
|     system.RegisterImageInterface(std::make_shared<QtImageInterface>()); | ||||
| 
 | ||||
|     main_window.show(); | ||||
| 
 | ||||
|  |  | |||
|  | @ -183,6 +183,8 @@ private slots: | |||
|     void OnGameListOpenDirectory(const QString& directory); | ||||
|     void OnGameListAddDirectory(); | ||||
|     void OnGameListShowList(bool show); | ||||
|     void OnGameListOpenPerGameProperties(const QString& file); | ||||
|     void OnConfigurePerGame(); | ||||
|     void OnMenuLoadFile(); | ||||
|     void OnMenuInstallCIA(); | ||||
|     void OnUpdateProgress(std::size_t written, std::size_t total); | ||||
|  | @ -238,6 +240,7 @@ private: | |||
|     void InstallCIA(QStringList filepaths); | ||||
|     void HideMouseCursor(); | ||||
|     void ShowMouseCursor(); | ||||
|     void OpenPerGameConfiguration(u64 title_id, const QString& file_name); | ||||
| 
 | ||||
|     std::unique_ptr<Ui::MainWindow> ui; | ||||
| 
 | ||||
|  |  | |||
|  | @ -45,7 +45,7 @@ | |||
|      <x>0</x> | ||||
|      <y>0</y> | ||||
|      <width>1081</width> | ||||
|      <height>21</height> | ||||
|      <height>25</height> | ||||
|     </rect> | ||||
|    </property> | ||||
|    <widget class="QMenu" name="menu_File"> | ||||
|  | @ -104,6 +104,7 @@ | |||
|     <addaction name="action_Report_Compatibility"/> | ||||
|     <addaction name="separator"/> | ||||
|     <addaction name="action_Configure"/> | ||||
|     <addaction name="action_Configure_Current_Game"/> | ||||
|     <addaction name="action_Cheats"/> | ||||
|    </widget> | ||||
|    <widget class="QMenu" name="menu_View"> | ||||
|  | @ -541,6 +542,14 @@ | |||
|     <string>Open Citra Folder</string> | ||||
|    </property> | ||||
|   </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> | ||||
|  <resources/> | ||||
|  <connections/> | ||||
|  |  | |||
|  | @ -13,7 +13,7 @@ | |||
| #include <QString> | ||||
| #include <QStringList> | ||||
| #include <QVector> | ||||
| #include "common/common_types.h" | ||||
| #include "common/settings.h" | ||||
| 
 | ||||
| namespace UISettings { | ||||
| 
 | ||||
|  | @ -40,13 +40,13 @@ struct GameDir { | |||
|     } | ||||
| }; | ||||
| 
 | ||||
| enum class GameListIconSize { | ||||
| enum class GameListIconSize : u32 { | ||||
|     NoIcon,    ///< Do not display icons
 | ||||
|     SmallIcon, ///< Display a small (24x24) icon
 | ||||
|     LargeIcon, ///< Display a large (48x48) icon
 | ||||
| }; | ||||
| 
 | ||||
| enum class GameListText { | ||||
| enum class GameListText : s32 { | ||||
|     NoText = -1,   ///< No text
 | ||||
|     FileName,      ///< Display the file name of the entry
 | ||||
|     FullPath,      ///< Display the full path of the entry
 | ||||
|  | @ -65,40 +65,41 @@ struct Values { | |||
|     QByteArray gamelist_header_state; | ||||
| 
 | ||||
|     QByteArray microprofile_geometry; | ||||
|     bool microprofile_visible; | ||||
|     Settings::Setting<bool> microprofile_visible{false, "microProfileDialogVisible"}; | ||||
| 
 | ||||
|     bool single_window_mode; | ||||
|     bool fullscreen; | ||||
|     bool display_titlebar; | ||||
|     bool show_filter_bar; | ||||
|     bool show_status_bar; | ||||
|     Settings::Setting<bool> single_window_mode{true, "singleWindowMode"}; | ||||
|     Settings::Setting<bool> fullscreen{false, "fullscreen"}; | ||||
|     Settings::Setting<bool> display_titlebar{true, "displayTitleBars"}; | ||||
|     Settings::Setting<bool> show_filter_bar{true, "showFilterBar"}; | ||||
|     Settings::Setting<bool> show_status_bar{true, "showStatusBar"}; | ||||
| 
 | ||||
|     bool confirm_before_closing; | ||||
|     bool first_start; | ||||
|     bool pause_when_in_background; | ||||
|     bool hide_mouse; | ||||
|     Settings::Setting<bool> confirm_before_closing{true, "confirmClose"}; | ||||
|     Settings::Setting<bool> first_start{true, "firstStart"}; | ||||
|     Settings::Setting<bool> pause_when_in_background{false, "pauseWhenInBackground"}; | ||||
|     Settings::Setting<bool> hide_mouse{false, "hideInactiveMouse"}; | ||||
| 
 | ||||
|     bool updater_found; | ||||
|     bool update_on_close; | ||||
|     bool check_for_update_on_start; | ||||
|     Settings::Setting<bool> update_on_close{false, "update_on_close"}; | ||||
|     Settings::Setting<bool> check_for_update_on_start{true, "check_for_update_on_start"}; | ||||
| 
 | ||||
|     // Discord RPC
 | ||||
|     bool enable_discord_presence; | ||||
|     Settings::Setting<bool> enable_discord_presence{true, "enable_discord_presence"}; | ||||
| 
 | ||||
|     // Game List
 | ||||
|     GameListIconSize game_list_icon_size; | ||||
|     GameListText game_list_row_1; | ||||
|     GameListText game_list_row_2; | ||||
|     bool game_list_hide_no_icon; | ||||
|     bool game_list_single_line_mode; | ||||
|     Settings::Setting<GameListIconSize> game_list_icon_size{GameListIconSize::LargeIcon, | ||||
|                                                             "iconSize"}; | ||||
|     Settings::Setting<GameListText> game_list_row_1{GameListText::TitleName, "row1"}; | ||||
|     Settings::Setting<GameListText> game_list_row_2{GameListText::FileName, "row2"}; | ||||
|     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 symbols_path; | ||||
|     QString movie_record_path; | ||||
|     QString movie_playback_path; | ||||
|     QString screenshot_path; | ||||
|     QString video_dumping_path; | ||||
|     QString game_dir_deprecated; | ||||
|     bool game_dir_deprecated_deepscan; | ||||
|  | @ -111,7 +112,7 @@ struct Values { | |||
|     // Shortcut name <Shortcut, context>
 | ||||
|     std::vector<Shortcut> shortcuts; | ||||
| 
 | ||||
|     uint32_t callout_flags; | ||||
|     Settings::Setting<u32> callout_flags{0, "calloutFlags"}; | ||||
| 
 | ||||
|     // multiplayer settings
 | ||||
|     QString nickname; | ||||
|  | @ -127,7 +128,7 @@ struct Values { | |||
|     std::pair<std::vector<std::string>, std::vector<std::string>> ban_list; | ||||
| 
 | ||||
|     // logging
 | ||||
|     bool show_console; | ||||
|     Settings::Setting<bool> show_console{false, "showConsole"}; | ||||
| }; | ||||
| 
 | ||||
| extern Values values; | ||||
|  |  | |||
|  | @ -99,6 +99,8 @@ add_library(common STATIC | |||
|     scm_rev.cpp | ||||
|     scm_rev.h | ||||
|     scope_exit.h | ||||
|     settings.cpp | ||||
|     settings.h | ||||
|     serialization/atomic.h | ||||
|     serialization/boost_discrete_interval.hpp | ||||
|     serialization/boost_flat_set.h | ||||
|  |  | |||
|  | @ -5,6 +5,7 @@ | |||
| #include <string_view> | ||||
| #include <utility> | ||||
| #include "audio_core/dsp_interface.h" | ||||
| #include "common/settings.h" | ||||
| #include "core/core.h" | ||||
| #include "core/gdbstub/gdbstub.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_user.h" | ||||
| #include "core/hle/service/mic_u.h" | ||||
| #include "core/settings.h" | ||||
| #include "video_core/renderer_base.h" | ||||
| #include "video_core/video_core.h" | ||||
| 
 | ||||
| namespace Settings { | ||||
| 
 | ||||
| Values values = {}; | ||||
| static bool configuring_global = true; | ||||
| 
 | ||||
| void Apply() { | ||||
|     GDBStub::SetServerPort(values.gdbstub_port); | ||||
|     GDBStub::ToggleServer(values.use_gdbstub); | ||||
|     GDBStub::SetServerPort(values.gdbstub_port.GetValue()); | ||||
|     GDBStub::ToggleServer(values.use_gdbstub.GetValue()); | ||||
| 
 | ||||
|     VideoCore::g_hw_renderer_enabled = values.use_hw_renderer; | ||||
|     VideoCore::g_shader_jit_enabled = values.use_shader_jit; | ||||
|     VideoCore::g_hw_shader_enabled = values.use_hw_shader; | ||||
|     VideoCore::g_separable_shader_enabled = values.separable_shader; | ||||
|     VideoCore::g_hw_shader_accurate_mul = values.shaders_accurate_mul; | ||||
|     VideoCore::g_use_disk_shader_cache = values.use_disk_shader_cache; | ||||
|     VideoCore::g_hw_renderer_enabled = values.use_hw_renderer.GetValue(); | ||||
|     VideoCore::g_shader_jit_enabled = values.use_shader_jit.GetValue(); | ||||
|     VideoCore::g_hw_shader_enabled = values.use_hw_shader.GetValue(); | ||||
|     VideoCore::g_separable_shader_enabled = values.separable_shader.GetValue(); | ||||
|     VideoCore::g_hw_shader_accurate_mul = values.shaders_accurate_mul.GetValue(); | ||||
|     VideoCore::g_use_disk_shader_cache = values.use_disk_shader_cache.GetValue(); | ||||
| 
 | ||||
| #ifndef ANDROID | ||||
|     if (VideoCore::g_renderer) { | ||||
|  | @ -45,9 +46,9 @@ void Apply() { | |||
| 
 | ||||
|     auto& system = Core::System::GetInstance(); | ||||
|     if (system.IsPoweredOn()) { | ||||
|         system.CoreTiming().UpdateClockSpeed(values.cpu_clock_percentage); | ||||
|         Core::DSP().SetSink(values.sink_id, values.audio_device_id); | ||||
|         Core::DSP().EnableStretching(values.enable_audio_stretching); | ||||
|         system.CoreTiming().UpdateClockSpeed(values.cpu_clock_percentage.GetValue()); | ||||
|         Core::DSP().SetSink(values.sink_id.GetValue(), values.audio_device_id.GetValue()); | ||||
|         Core::DSP().EnableStretching(values.enable_audio_stretching.GetValue()); | ||||
| 
 | ||||
|         auto hid = Service::HID::GetModule(system); | ||||
|         if (hid) { | ||||
|  | @ -76,39 +77,47 @@ void LogSettings() { | |||
|         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_setting("Core_UseCpuJit", values.use_cpu_jit); | ||||
|     log_setting("Core_CPUClockPercentage", values.cpu_clock_percentage); | ||||
|     log_setting("Renderer_UseGLES", values.use_gles); | ||||
|     log_setting("Renderer_UseHwRenderer", values.use_hw_renderer); | ||||
|     log_setting("Renderer_UseHwShader", values.use_hw_shader); | ||||
|     log_setting("Renderer_SeparableShader", values.separable_shader); | ||||
|     log_setting("Renderer_ShadersAccurateMul", values.shaders_accurate_mul); | ||||
|     log_setting("Renderer_UseShaderJit", values.use_shader_jit); | ||||
|     log_setting("Renderer_UseResolutionFactor", values.resolution_factor); | ||||
|     log_setting("Renderer_FrameLimit", values.frame_limit); | ||||
|     log_setting("Renderer_UseFrameLimitAlternate", values.use_frame_limit_alternate); | ||||
|     log_setting("Renderer_FrameLimitAlternate", values.frame_limit_alternate); | ||||
|     log_setting("Renderer_VSyncNew", values.use_vsync_new); | ||||
|     log_setting("Renderer_PostProcessingShader", values.pp_shader_name); | ||||
|     log_setting("Renderer_FilterMode", values.filter_mode); | ||||
|     log_setting("Renderer_TextureFilterName", values.texture_filter_name); | ||||
|     log_setting("Stereoscopy_Render3d", values.render_3d); | ||||
|     log_setting("Stereoscopy_Factor3d", values.factor_3d); | ||||
|     log_setting("Stereoscopy_MonoRenderLeftEye", values.mono_render_left_eye); | ||||
|     log_setting("Layout_LayoutOption", values.layout_option); | ||||
|     log_setting("Layout_SwapScreen", values.swap_screen); | ||||
|     log_setting("Layout_UprightScreen", values.upright_screen); | ||||
|     log_setting("Utility_DumpTextures", values.dump_textures); | ||||
|     log_setting("Utility_CustomTextures", values.custom_textures); | ||||
|     log_setting("Utility_UseDiskShaderCache", values.use_disk_shader_cache); | ||||
|     log_setting("Audio_EnableDspLle", values.enable_dsp_lle); | ||||
|     log_setting("Audio_EnableDspLleMultithread", values.enable_dsp_lle_multithread); | ||||
|     log_setting("Audio_OutputEngine", values.sink_id); | ||||
|     log_setting("Audio_EnableAudioStretching", values.enable_audio_stretching); | ||||
|     log_setting("Audio_OutputDevice", values.audio_device_id); | ||||
|     log_setting("Audio_InputDeviceType", values.mic_input_type); | ||||
|     log_setting("Audio_InputDevice", values.mic_input_device); | ||||
|     log_setting("Core_UseCpuJit", values.use_cpu_jit.GetValue()); | ||||
|     log_setting("Core_CPUClockPercentage", values.cpu_clock_percentage.GetValue()); | ||||
|     log_setting("Renderer_UseGLES", values.use_gles.GetValue()); | ||||
|     log_setting("Renderer_UseHwRenderer", values.use_hw_renderer.GetValue()); | ||||
|     log_setting("Renderer_UseHwShader", values.use_hw_shader.GetValue()); | ||||
|     log_setting("Renderer_SeparableShader", values.separable_shader.GetValue()); | ||||
|     log_setting("Renderer_ShadersAccurateMul", values.shaders_accurate_mul.GetValue()); | ||||
|     log_setting("Renderer_UseShaderJit", values.use_shader_jit.GetValue()); | ||||
|     log_setting("Renderer_UseResolutionFactor", values.resolution_factor.GetValue()); | ||||
|     log_setting("Renderer_FrameLimit", values.frame_limit.GetValue()); | ||||
|     log_setting("Renderer_VSyncNew", values.use_vsync_new.GetValue()); | ||||
|     log_setting("Renderer_PostProcessingShader", values.pp_shader_name.GetValue()); | ||||
|     log_setting("Renderer_FilterMode", values.filter_mode.GetValue()); | ||||
|     log_setting("Renderer_TextureFilterName", values.texture_filter_name.GetValue()); | ||||
|     log_setting("Stereoscopy_Render3d", values.render_3d.GetValue()); | ||||
|     log_setting("Stereoscopy_Factor3d", values.factor_3d.GetValue()); | ||||
|     log_setting("Stereoscopy_MonoRenderLeftEye", values.mono_render_left_eye.GetValue()); | ||||
|     log_setting("Layout_LayoutOption", values.layout_option.GetValue()); | ||||
|     log_setting("Layout_SwapScreen", values.swap_screen.GetValue()); | ||||
|     log_setting("Layout_UprightScreen", values.upright_screen.GetValue()); | ||||
|     log_setting("Utility_DumpTextures", values.dump_textures.GetValue()); | ||||
|     log_setting("Utility_CustomTextures", values.custom_textures.GetValue()); | ||||
|     log_setting("Utility_UseDiskShaderCache", values.use_disk_shader_cache.GetValue()); | ||||
|     log_setting("Audio_Emulation", to_string(values.audio_emulation.GetValue())); | ||||
|     log_setting("Audio_OutputEngine", values.sink_id.GetValue()); | ||||
|     log_setting("Audio_EnableAudioStretching", values.enable_audio_stretching.GetValue()); | ||||
|     log_setting("Audio_OutputDevice", values.audio_device_id.GetValue()); | ||||
|     log_setting("Audio_InputDeviceType", values.mic_input_type.GetValue()); | ||||
|     log_setting("Audio_InputDevice", values.mic_input_device.GetValue()); | ||||
|     using namespace Service::CAM; | ||||
|     log_setting("Camera_OuterRightName", values.camera_name[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_OuterLeftConfig", values.camera_config[OuterLeftCamera]); | ||||
|     log_setting("Camera_OuterLeftFlip", values.camera_flip[OuterLeftCamera]); | ||||
|     log_setting("DataStorage_UseVirtualSd", values.use_virtual_sd); | ||||
|     log_setting("DataStorage_UseCustomStorage", values.use_custom_storage); | ||||
|     log_setting("DataStorage_UseVirtualSd", values.use_virtual_sd.GetValue()); | ||||
|     log_setting("DataStorage_UseCustomStorage", values.use_custom_storage.GetValue()); | ||||
|     if (values.use_custom_storage) { | ||||
|         log_setting("DataStorage_SdmcDir", FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir)); | ||||
|         log_setting("DataStorage_NandDir", FileUtil::GetUserPath(FileUtil::UserPath::NANDDir)); | ||||
|     } | ||||
|     log_setting("System_IsNew3ds", values.is_new_3ds); | ||||
|     log_setting("System_RegionValue", values.region_value); | ||||
|     log_setting("Debugging_UseGdbstub", values.use_gdbstub); | ||||
|     log_setting("Debugging_GdbstubPort", values.gdbstub_port); | ||||
|     log_setting("System_IsNew3ds", values.is_new_3ds.GetValue()); | ||||
|     log_setting("System_RegionValue", values.region_value.GetValue()); | ||||
|     log_setting("Debugging_UseGdbstub", values.use_gdbstub.GetValue()); | ||||
|     log_setting("Debugging_GdbstubPort", values.gdbstub_port.GetValue()); | ||||
| } | ||||
| 
 | ||||
| bool IsConfiguringGlobal() { | ||||
|     return configuring_global; | ||||
| } | ||||
| 
 | ||||
| void SetConfiguringGlobal(bool is_global) { | ||||
|     configuring_global = is_global; | ||||
| } | ||||
| 
 | ||||
| float Volume() { | ||||
|     if (values.audio_muted) { | ||||
|         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) { | ||||
							
								
								
									
										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 | ||||
|     savestate.cpp | ||||
|     savestate.h | ||||
|     settings.cpp | ||||
|     settings.h | ||||
|     telemetry_session.cpp | ||||
|     telemetry_session.h | ||||
|     tracer/citrace.h | ||||
|  |  | |||
|  | @ -4,9 +4,9 @@ | |||
| #if defined(ARCHITECTURE_x86_64) || defined(ARCHITECTURE_arm64) | ||||
| #include "core/arm/dynarmic/arm_exclusive_monitor.h" | ||||
| #endif | ||||
| #include "common/settings.h" | ||||
| #include "core/arm/exclusive_monitor.h" | ||||
| #include "core/memory.h" | ||||
| #include "core/settings.h" | ||||
| 
 | ||||
| namespace Core { | ||||
| 
 | ||||
|  |  | |||
|  | @ -6,6 +6,8 @@ | |||
| 
 | ||||
| #include <atomic> | ||||
| #include <memory> | ||||
| #include <vector> | ||||
| #include "common/common_types.h" | ||||
| #include "core/cheats/cheat_base.h" | ||||
| 
 | ||||
| namespace Cheats { | ||||
|  |  | |||
|  | @ -25,6 +25,7 @@ | |||
| #ifdef ENABLE_FFMPEG_VIDEO_DUMPER | ||||
| #include "core/dumping/ffmpeg_backend.h" | ||||
| #endif | ||||
| #include "common/settings.h" | ||||
| #include "core/custom_tex_cache.h" | ||||
| #include "core/gdbstub/gdbstub.h" | ||||
| #include "core/global.h" | ||||
|  | @ -45,7 +46,6 @@ | |||
| #include "core/loader/loader.h" | ||||
| #include "core/movie.h" | ||||
| #include "core/rpc/rpc_server.h" | ||||
| #include "core/settings.h" | ||||
| #include "network/network.h" | ||||
| #include "video_core/renderer_base.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>(); | ||||
| 
 | ||||
|     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>( | ||||
|         *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->SetRunningCPU(cpu_cores[0].get()); | ||||
| 
 | ||||
|     if (Settings::values.enable_dsp_lle) { | ||||
|         dsp_core = std::make_unique<AudioCore::DspLle>(*memory, | ||||
|                                                        Settings::values.enable_dsp_lle_multithread); | ||||
|     } else { | ||||
|     const auto audio_emulation = Settings::values.audio_emulation.GetValue(); | ||||
|     if (audio_emulation == Settings::AudioEmulation::HLE) { | ||||
|         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); | ||||
| 
 | ||||
|     dsp_core->SetSink(Settings::values.sink_id, Settings::values.audio_device_id); | ||||
|     dsp_core->EnableStretching(Settings::values.enable_audio_stretching); | ||||
|     dsp_core->SetSink(Settings::values.sink_id.GetValue(), | ||||
|                       Settings::values.audio_device_id.GetValue()); | ||||
|     dsp_core->EnableStretching(Settings::values.enable_audio_stretching.GetValue()); | ||||
| 
 | ||||
|     telemetry_session = std::make_unique<Core::TelemetrySession>(); | ||||
| 
 | ||||
|  |  | |||
|  | @ -7,10 +7,10 @@ | |||
| #include "common/file_util.h" | ||||
| #include "common/logging/log.h" | ||||
| #include "common/param_package.h" | ||||
| #include "common/settings.h" | ||||
| #include "common/string_util.h" | ||||
| #include "core/dumping/ffmpeg_backend.h" | ||||
| #include "core/hw/gpu.h" | ||||
| #include "core/settings.h" | ||||
| #include "video_core/renderer_base.h" | ||||
| #include "video_core/video_core.h" | ||||
| 
 | ||||
|  |  | |||
|  | @ -7,11 +7,11 @@ | |||
| #include "common/archives.h" | ||||
| #include "common/file_util.h" | ||||
| #include "common/logging/log.h" | ||||
| #include "common/settings.h" | ||||
| #include "core/file_sys/archive_sdmc.h" | ||||
| #include "core/file_sys/disk_archive.h" | ||||
| #include "core/file_sys/errors.h" | ||||
| #include "core/file_sys/path_parser.h" | ||||
| #include "core/settings.h" | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // FileSys namespace
 | ||||
|  |  | |||
|  | @ -5,11 +5,11 @@ | |||
| #include <memory> | ||||
| #include "common/archives.h" | ||||
| #include "common/file_util.h" | ||||
| #include "common/settings.h" | ||||
| #include "core/file_sys/archive_sdmcwriteonly.h" | ||||
| #include "core/file_sys/directory_backend.h" | ||||
| #include "core/file_sys/errors.h" | ||||
| #include "core/file_sys/file_backend.h" | ||||
| #include "core/settings.h" | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // FileSys namespace
 | ||||
|  |  | |||
|  | @ -4,9 +4,10 @@ | |||
| 
 | ||||
| #include <cmath> | ||||
| #include <mutex> | ||||
| #include "common/settings.h" | ||||
| #include "core/3ds.h" | ||||
| #include "core/frontend/emu_window.h" | ||||
| #include "core/frontend/input.h" | ||||
| #include "core/settings.h" | ||||
| 
 | ||||
| namespace Frontend { | ||||
| /// 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, | ||||
|                                 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 && | ||||
|                 framebuffer_y < layout.bottom_screen.bottom && | ||||
|                 ((framebuffer_x >= layout.bottom_screen.left / 2 && | ||||
|                   framebuffer_x < layout.bottom_screen.right / 2) || | ||||
|                  (framebuffer_x >= (layout.bottom_screen.left / 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 && | ||||
|                 framebuffer_y < layout.bottom_screen.bottom && | ||||
|                 ((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 { | ||||
|     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; | ||||
|         else if (Settings::values.render_3d == Settings::StereoRenderOption::CardboardVR) | ||||
|         else if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::CardboardVR) | ||||
|             new_x -= | ||||
|                 (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::min(new_x, framebuffer_layout.bottom_screen.right / 2 - 1); | ||||
|     } else { | ||||
|  | @ -122,14 +123,14 @@ bool EmuWindow::TouchPressed(unsigned framebuffer_x, unsigned framebuffer_y) { | |||
|         return false; | ||||
| 
 | ||||
|     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; | ||||
|         else if (Settings::values.render_3d == Settings::StereoRenderOption::CardboardVR) | ||||
|         else if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::CardboardVR) | ||||
|             framebuffer_x -= | ||||
|                 (framebuffer_layout.width / 2) - (framebuffer_layout.cardboard.user_x_shift * 2); | ||||
|     } | ||||
|     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 = | ||||
|             static_cast<float>(framebuffer_x - framebuffer_layout.bottom_screen.left / 2) / | ||||
|             (framebuffer_layout.bottom_screen.right / 2 - | ||||
|  | @ -173,55 +174,59 @@ void EmuWindow::UpdateCurrentFramebufferLayout(unsigned width, unsigned height, | |||
|                                                bool is_portrait_mode) { | ||||
|     Layout::FramebufferLayout layout; | ||||
|     const auto layout_option = Settings::values.layout_option; | ||||
|     const auto min_size = | ||||
|         Layout::GetMinimumSizeFromLayout(layout_option, Settings::values.upright_screen); | ||||
|     const auto min_size = Layout::GetMinimumSizeFromLayout( | ||||
|         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); | ||||
|     } else { | ||||
|         width = std::max(width, min_size.first); | ||||
|         height = std::max(height, min_size.second); | ||||
| 
 | ||||
|         // If in portrait mode, only the MobilePortrait option really makes sense
 | ||||
|         const Settings::LayoutOption layout_option = is_portrait_mode | ||||
|                                                          ? Settings::LayoutOption::MobilePortrait | ||||
|                                                          : Settings::values.layout_option; | ||||
|         const Settings::LayoutOption layout_option = | ||||
|             is_portrait_mode ? Settings::LayoutOption::MobilePortrait | ||||
|                              : Settings::values.layout_option.GetValue(); | ||||
| 
 | ||||
|         switch (layout_option) { | ||||
|         case Settings::LayoutOption::SingleScreen: | ||||
|             layout = Layout::SingleFrameLayout(width, height, Settings::values.swap_screen, | ||||
|                                                Settings::values.upright_screen); | ||||
|             layout = | ||||
|                 Layout::SingleFrameLayout(width, height, Settings::values.swap_screen.GetValue(), | ||||
|                                           Settings::values.upright_screen.GetValue()); | ||||
|             break; | ||||
|         case Settings::LayoutOption::LargeScreen: | ||||
|             layout = Layout::LargeFrameLayout(width, height, Settings::values.swap_screen, | ||||
|                                               Settings::values.upright_screen); | ||||
|             layout = | ||||
|                 Layout::LargeFrameLayout(width, height, Settings::values.swap_screen.GetValue(), | ||||
|                                          Settings::values.upright_screen.GetValue()); | ||||
|             break; | ||||
|         case Settings::LayoutOption::SideScreen: | ||||
|             layout = Layout::SideFrameLayout(width, height, Settings::values.swap_screen, | ||||
|                                              Settings::values.upright_screen); | ||||
|             layout = Layout::SideFrameLayout(width, height, Settings::values.swap_screen.GetValue(), | ||||
|                                              Settings::values.upright_screen.GetValue()); | ||||
|             break; | ||||
| #ifndef ANDROID | ||||
|         case Settings::LayoutOption::SeparateWindows: | ||||
|             layout = Layout::SeparateWindowsLayout(width, height, is_secondary, | ||||
|                                                    Settings::values.upright_screen); | ||||
|                                                    Settings::values.upright_screen.GetValue()); | ||||
|             break; | ||||
| #endif | ||||
|         case Settings::LayoutOption::MobilePortrait: | ||||
|             layout = Layout::MobilePortraitFrameLayout(width, height, Settings::values.swap_screen); | ||||
|             layout = Layout::MobilePortraitFrameLayout(width, height, | ||||
|                                                        Settings::values.swap_screen.GetValue()); | ||||
|             break; | ||||
|         case Settings::LayoutOption::MobileLandscape: | ||||
|             layout = Layout::MobileLandscapeFrameLayout(width, height, Settings::values.swap_screen, | ||||
|                                                         2.25f, false); | ||||
|             layout = Layout::MobileLandscapeFrameLayout( | ||||
|                 width, height, Settings::values.swap_screen.GetValue(), 2.25f, false); | ||||
|             break; | ||||
|         case Settings::LayoutOption::Default: | ||||
|         default: | ||||
|             layout = Layout::DefaultFrameLayout(width, height, Settings::values.swap_screen, | ||||
|                                                 Settings::values.upright_screen); | ||||
|             layout = | ||||
|                 Layout::DefaultFrameLayout(width, height, Settings::values.swap_screen.GetValue(), | ||||
|                                            Settings::values.upright_screen.GetValue()); | ||||
|             break; | ||||
|         } | ||||
|         UpdateMinimumWindowSize(min_size); | ||||
|     } | ||||
|     if (Settings::values.render_3d == Settings::StereoRenderOption::CardboardVR) { | ||||
|     if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::CardboardVR) { | ||||
|         layout = Layout::GetCardboardSettings(layout); | ||||
|     } | ||||
|     NotifyFramebufferLayoutChanged(layout); | ||||
|  |  | |||
|  | @ -5,9 +5,9 @@ | |||
| #include <cmath> | ||||
| 
 | ||||
| #include "common/assert.h" | ||||
| #include "common/settings.h" | ||||
| #include "core/3ds.h" | ||||
| #include "core/frontend/framebuffer_layout.h" | ||||
| #include "core/settings.h" | ||||
| 
 | ||||
| namespace Layout { | ||||
| 
 | ||||
|  | @ -355,12 +355,14 @@ FramebufferLayout CustomFrameLayout(u32 width, u32 height) { | |||
| 
 | ||||
|     FramebufferLayout res{width, height, true, true, {}, {}, !Settings::values.upright_screen}; | ||||
| 
 | ||||
|     Common::Rectangle<u32> top_screen{ | ||||
|         Settings::values.custom_top_left, Settings::values.custom_top_top, | ||||
|         Settings::values.custom_top_right, Settings::values.custom_top_bottom}; | ||||
|     Common::Rectangle<u32> bot_screen{ | ||||
|         Settings::values.custom_bottom_left, Settings::values.custom_bottom_top, | ||||
|         Settings::values.custom_bottom_right, Settings::values.custom_bottom_bottom}; | ||||
|     Common::Rectangle<u32> top_screen{Settings::values.custom_top_left.GetValue(), | ||||
|                                       Settings::values.custom_top_top.GetValue(), | ||||
|                                       Settings::values.custom_top_right.GetValue(), | ||||
|                                       Settings::values.custom_top_bottom.GetValue()}; | ||||
|     Common::Rectangle<u32> bot_screen{Settings::values.custom_bottom_left.GetValue(), | ||||
|                                       Settings::values.custom_bottom_top.GetValue(), | ||||
|                                       Settings::values.custom_bottom_right.GetValue(), | ||||
|                                       Settings::values.custom_bottom_bottom.GetValue()}; | ||||
| 
 | ||||
|     res.top_screen = top_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 layout; | ||||
|     if (Settings::values.custom_layout == true) { | ||||
|         layout = CustomFrameLayout( | ||||
|             std::max(Settings::values.custom_top_right, Settings::values.custom_bottom_right), | ||||
|             std::max(Settings::values.custom_top_bottom, Settings::values.custom_bottom_bottom)); | ||||
|     if (Settings::values.custom_layout.GetValue() == true) { | ||||
|         layout = CustomFrameLayout(std::max(Settings::values.custom_top_right.GetValue(), | ||||
|                                             Settings::values.custom_bottom_right.GetValue()), | ||||
|                                    std::max(Settings::values.custom_top_bottom.GetValue(), | ||||
|                                             Settings::values.custom_bottom_bottom.GetValue())); | ||||
|     } else { | ||||
|         int width, height; | ||||
|         switch (Settings::values.layout_option) { | ||||
|         switch (Settings::values.layout_option.GetValue()) { | ||||
|         case Settings::LayoutOption::SingleScreen: | ||||
| #ifndef ANDROID | ||||
|         case Settings::LayoutOption::SeparateWindows: | ||||
| #endif | ||||
|         { | ||||
|             const bool swap_screens = is_secondary || Settings::values.swap_screen; | ||||
|             if (Settings::values.upright_screen) { | ||||
|             const bool swap_screens = is_secondary || Settings::values.swap_screen.GetValue(); | ||||
|             if (Settings::values.upright_screen.GetValue()) { | ||||
|                 if (swap_screens) { | ||||
|                     width = Core::kScreenBottomHeight * res_scale; | ||||
|                     height = Core::kScreenBottomWidth * res_scale; | ||||
|  | @ -399,13 +402,13 @@ FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale, bool is_secondar | |||
|                     height = Core::kScreenTopHeight * res_scale; | ||||
|                 } | ||||
|             } | ||||
|             layout = | ||||
|                 SingleFrameLayout(width, height, swap_screens, Settings::values.upright_screen); | ||||
|             layout = SingleFrameLayout(width, height, swap_screens, | ||||
|                                        Settings::values.upright_screen.GetValue()); | ||||
|             break; | ||||
|         } | ||||
|         case Settings::LayoutOption::LargeScreen: | ||||
|             if (Settings::values.upright_screen) { | ||||
|                 if (Settings::values.swap_screen) { | ||||
|             if (Settings::values.upright_screen.GetValue()) { | ||||
|                 if (Settings::values.swap_screen.GetValue()) { | ||||
|                     width = Core::kScreenBottomHeight * res_scale; | ||||
|                     height = (Core::kScreenBottomWidth + Core::kScreenTopWidth / 4) * res_scale; | ||||
|                 } else { | ||||
|  | @ -413,7 +416,7 @@ FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale, bool is_secondar | |||
|                     height = (Core::kScreenTopWidth + Core::kScreenBottomWidth / 4) * res_scale; | ||||
|                 } | ||||
|             } else { | ||||
|                 if (Settings::values.swap_screen) { | ||||
|                 if (Settings::values.swap_screen.GetValue()) { | ||||
|                     width = (Core::kScreenBottomWidth + Core::kScreenTopWidth / 4) * res_scale; | ||||
|                     height = Core::kScreenBottomHeight * res_scale; | ||||
|                 } else { | ||||
|  | @ -421,51 +424,52 @@ FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale, bool is_secondar | |||
|                     height = Core::kScreenTopHeight * res_scale; | ||||
|                 } | ||||
|             } | ||||
|             layout = LargeFrameLayout(width, height, Settings::values.swap_screen, | ||||
|                                       Settings::values.upright_screen); | ||||
|             layout = LargeFrameLayout(width, height, Settings::values.swap_screen.GetValue(), | ||||
|                                       Settings::values.upright_screen.GetValue()); | ||||
|             break; | ||||
|         case Settings::LayoutOption::SideScreen: | ||||
|             if (Settings::values.upright_screen) { | ||||
|             if (Settings::values.upright_screen.GetValue()) { | ||||
|                 width = Core::kScreenTopHeight * res_scale; | ||||
|                 height = (Core::kScreenTopWidth + Core::kScreenBottomWidth) * res_scale; | ||||
|             } else { | ||||
|                 width = (Core::kScreenTopWidth + Core::kScreenBottomWidth) * res_scale; | ||||
|                 height = Core::kScreenTopHeight * res_scale; | ||||
|             } | ||||
|             layout = SideFrameLayout(width, height, Settings::values.swap_screen, | ||||
|                                      Settings::values.upright_screen); | ||||
|             layout = SideFrameLayout(width, height, Settings::values.swap_screen.GetValue(), | ||||
|                                      Settings::values.upright_screen.GetValue()); | ||||
|             break; | ||||
|         case Settings::LayoutOption::MobilePortrait: | ||||
|             width = Core::kScreenTopWidth * 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; | ||||
|         case Settings::LayoutOption::MobileLandscape: | ||||
|             if (Settings::values.swap_screen) { | ||||
|             if (Settings::values.swap_screen.GetValue()) { | ||||
|                 width = (Core::kScreenBottomWidth + Core::kScreenTopWidth / 2.25f) * res_scale; | ||||
|                 height = Core::kScreenBottomHeight * res_scale; | ||||
|             } else { | ||||
|                 width = (Core::kScreenTopWidth + Core::kScreenBottomWidth / 2.25f) * res_scale; | ||||
|                 height = Core::kScreenTopHeight * res_scale; | ||||
|             } | ||||
|             layout = MobileLandscapeFrameLayout(width, height, Settings::values.swap_screen, 2.25f, | ||||
|                                                 false); | ||||
|             layout = MobileLandscapeFrameLayout( | ||||
|                 width, height, Settings::values.swap_screen.GetValue(), 2.25f, false); | ||||
|             break; | ||||
|         case Settings::LayoutOption::Default: | ||||
|         default: | ||||
|             if (Settings::values.upright_screen) { | ||||
|             if (Settings::values.upright_screen.GetValue()) { | ||||
|                 width = (Core::kScreenTopHeight + Core::kScreenBottomHeight) * res_scale; | ||||
|                 height = Core::kScreenTopWidth * res_scale; | ||||
|             } else { | ||||
|                 width = Core::kScreenTopWidth * res_scale; | ||||
|                 height = (Core::kScreenTopHeight + Core::kScreenBottomHeight) * res_scale; | ||||
|             } | ||||
|             layout = DefaultFrameLayout(width, height, Settings::values.swap_screen, | ||||
|                                         Settings::values.upright_screen); | ||||
|             layout = DefaultFrameLayout(width, height, Settings::values.swap_screen.GetValue(), | ||||
|                                         Settings::values.upright_screen.GetValue()); | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|     if (Settings::values.render_3d == Settings::StereoRenderOption::CardboardVR) { | ||||
|     if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::CardboardVR) { | ||||
|         layout = Layout::GetCardboardSettings(layout); | ||||
|     } | ||||
|     return layout; | ||||
|  | @ -478,17 +482,17 @@ FramebufferLayout GetCardboardSettings(FramebufferLayout layout) { | |||
|     float bottom_screen_left = 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_height = layout.top_screen.GetHeight() / 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; | ||||
|     bool is_swapped = Settings::values.swap_screen; | ||||
|     bool is_portrait = layout.height > layout.width; | ||||
|     const bool is_swapped = Settings::values.swap_screen.GetValue(); | ||||
|     const bool is_portrait = layout.height > layout.width; | ||||
| 
 | ||||
|     float cardboardScreenWidth; | ||||
|     float cardboardScreenHeight; | ||||
|     switch (Settings::values.layout_option) { | ||||
|     switch (Settings::values.layout_option.GetValue()) { | ||||
|     case Settings::LayoutOption::MobileLandscape: | ||||
|     case Settings::LayoutOption::SideScreen: | ||||
|         // If orientation is portrait, only use MobilePortrait
 | ||||
|  | @ -524,9 +528,11 @@ FramebufferLayout GetCardboardSettings(FramebufferLayout layout) { | |||
|         break; | ||||
|     } | ||||
|     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 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
 | ||||
|     newLayout.top_screen.left = top_screen_left + cardboardMaxXShift; | ||||
|  |  | |||
|  | @ -5,7 +5,7 @@ | |||
| #pragma once | ||||
| 
 | ||||
| #include "common/math_util.h" | ||||
| #include "core/settings.h" | ||||
| #include "common/settings.h" | ||||
| 
 | ||||
| namespace Layout { | ||||
| 
 | ||||
|  |  | |||
|  | @ -11,6 +11,7 @@ | |||
| #include "common/assert.h" | ||||
| #include "common/common_types.h" | ||||
| #include "common/logging/log.h" | ||||
| #include "common/settings.h" | ||||
| #include "core/core.h" | ||||
| #include "core/hle/kernel/config_mem.h" | ||||
| #include "core/hle/kernel/memory.h" | ||||
|  | @ -19,7 +20,6 @@ | |||
| #include "core/hle/kernel/vm_manager.h" | ||||
| #include "core/hle/result.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) { | ||||
|     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; | ||||
|     if (is_new_3ds) { | ||||
|         if (n3ds_mode == MemoryMode::Mode6 || n3ds_mode == MemoryMode::Mode6_2) { | ||||
|  |  | |||
|  | @ -6,12 +6,12 @@ | |||
| #include <cstring> | ||||
| #include "common/archives.h" | ||||
| #include "common/assert.h" | ||||
| #include "common/settings.h" | ||||
| #include "core/core.h" | ||||
| #include "core/core_timing.h" | ||||
| #include "core/hle/kernel/shared_page.h" | ||||
| #include "core/hle/service/ptm/ptm.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); | ||||
|     } | ||||
| 
 | ||||
|     switch (Settings::values.init_clock) { | ||||
|     switch (Settings::values.init_clock.GetValue()) { | ||||
|     case Settings::InitClock::SystemTime: { | ||||
|         auto now = std::chrono::system_clock::now(); | ||||
|         // 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); | ||||
| 
 | ||||
|         // 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_in_seconds = days_offset * 86400; // h/m/s truncated
 | ||||
|         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()); | ||||
|     } | ||||
|     case Settings::InitClock::FixedTime: | ||||
|         return std::chrono::seconds(Settings::values.init_time); | ||||
|         return std::chrono::seconds(Settings::values.init_time.GetValue()); | ||||
|     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)); | ||||
|     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); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -8,6 +8,7 @@ | |||
| #include "common/common_paths.h" | ||||
| #include "common/file_util.h" | ||||
| #include "common/logging/log.h" | ||||
| #include "common/settings.h" | ||||
| #include "core/core.h" | ||||
| #include "core/file_sys/archive_ncch.h" | ||||
| #include "core/file_sys/file_backend.h" | ||||
|  | @ -28,7 +29,6 @@ | |||
| #include "core/hle/service/service.h" | ||||
| #include "core/hw/aes/ccm.h" | ||||
| #include "core/hw/aes/key.h" | ||||
| #include "core/settings.h" | ||||
| 
 | ||||
| SERVICE_CONSTRUCT_IMPL(Service::APT::Module) | ||||
| 
 | ||||
|  |  | |||
|  | @ -6,6 +6,7 @@ | |||
| #include "common/archives.h" | ||||
| #include "common/bit_set.h" | ||||
| #include "common/logging/log.h" | ||||
| #include "common/settings.h" | ||||
| #include "core/core.h" | ||||
| #include "core/core_timing.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_u.h" | ||||
| #include "core/memory.h" | ||||
| #include "core/settings.h" | ||||
| 
 | ||||
| SERVICE_CONSTRUCT_IMPL(Service::CAM::Module) | ||||
| 
 | ||||
|  |  | |||
|  | @ -12,6 +12,7 @@ | |||
| #include "common/archives.h" | ||||
| #include "common/file_util.h" | ||||
| #include "common/logging/log.h" | ||||
| #include "common/settings.h" | ||||
| #include "common/string_util.h" | ||||
| #include "common/swap.h" | ||||
| #include "core/core.h" | ||||
|  | @ -25,7 +26,6 @@ | |||
| #include "core/hle/service/cfg/cfg_nor.h" | ||||
| #include "core/hle/service/cfg/cfg_s.h" | ||||
| #include "core/hle/service/cfg/cfg_u.h" | ||||
| #include "core/settings.h" | ||||
| 
 | ||||
| SERIALIZE_EXPORT_IMPL(Service::CFG::Module) | ||||
| 
 | ||||
|  | @ -189,10 +189,10 @@ void Module::Interface::GetCountryCodeID(Kernel::HLERequestContext& ctx) { | |||
| } | ||||
| 
 | ||||
| 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 Settings::values.region_value; | ||||
|     return Settings::values.region_value.GetValue(); | ||||
| } | ||||
| 
 | ||||
| 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; | ||||
|     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) { | ||||
|             LOG_WARNING(Service_CFG, "System language {} does not fit the region. Adjusted to {}", | ||||
|                         current_language, adjusted_language); | ||||
|  |  | |||
|  | @ -9,6 +9,7 @@ | |||
| #include "common/file_util.h" | ||||
| #include "common/logging/log.h" | ||||
| #include "common/scope_exit.h" | ||||
| #include "common/settings.h" | ||||
| #include "common/string_util.h" | ||||
| #include "core/core.h" | ||||
| #include "core/file_sys/errors.h" | ||||
|  | @ -25,7 +26,6 @@ | |||
| #include "core/hle/service/am/am.h" | ||||
| #include "core/hle/service/fs/archive.h" | ||||
| #include "core/hle/service/fs/fs_user.h" | ||||
| #include "core/settings.h" | ||||
| 
 | ||||
| SERVICE_CONSTRUCT_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::RequestBuilder rb = rp.MakeBuilder(2, 0); | ||||
|     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) { | ||||
|  | @ -358,7 +358,7 @@ void FS_USER::IsSdmcWriteable(Kernel::HLERequestContext& ctx) { | |||
|     IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); | ||||
|     rb.Push(RESULT_SUCCESS); | ||||
|     // 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)"); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -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
 | ||||
|     // and possibly moved to its own Core::Timing event.
 | ||||
|     mem->pad.sliderstate_3d = (Settings::values.factor_3d / 100.0f); | ||||
|     system.Kernel().GetSharedPageHandler().Set3DSlider(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.GetValue() / | ||||
|                                                        100.0f); | ||||
| 
 | ||||
|     // Reschedule recurrent 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) { | ||||
|     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); | ||||
|     rb.Push(RESULT_SUCCESS); | ||||
|  |  | |||
|  | @ -13,10 +13,10 @@ | |||
| #include "common/bit_field.h" | ||||
| #include "common/common_funcs.h" | ||||
| #include "common/common_types.h" | ||||
| #include "common/settings.h" | ||||
| #include "core/core_timing.h" | ||||
| #include "core/frontend/input.h" | ||||
| #include "core/hle/service/service.h" | ||||
| #include "core/settings.h" | ||||
| 
 | ||||
| namespace Core { | ||||
| class System; | ||||
|  |  | |||
|  | @ -3,12 +3,12 @@ | |||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include "common/alignment.h" | ||||
| #include "common/settings.h" | ||||
| #include "common/string_util.h" | ||||
| #include "core/core.h" | ||||
| #include "core/core_timing.h" | ||||
| #include "core/hle/service/ir/extra_hid.h" | ||||
| #include "core/movie.h" | ||||
| #include "core/settings.h" | ||||
| 
 | ||||
| namespace Service::IR { | ||||
| 
 | ||||
|  |  | |||
|  | @ -5,6 +5,7 @@ | |||
| #include <boost/serialization/base_object.hpp> | ||||
| #include <boost/serialization/shared_ptr.hpp> | ||||
| #include "common/archives.h" | ||||
| #include "common/settings.h" | ||||
| #include "core/core.h" | ||||
| #include "core/core_timing.h" | ||||
| #include "core/hle/ipc_helpers.h" | ||||
|  | @ -13,7 +14,6 @@ | |||
| #include "core/hle/service/hid/hid.h" | ||||
| #include "core/hle/service/ir/ir_rst.h" | ||||
| #include "core/movie.h" | ||||
| #include "core/settings.h" | ||||
| 
 | ||||
| SERIALIZE_EXPORT_IMPL(Service::IR::IR_RST) | ||||
| SERVICE_CONSTRUCT_IMPL(Service::IR::IR_RST) | ||||
|  |  | |||
|  | @ -5,6 +5,7 @@ | |||
| #include <boost/serialization/weak_ptr.hpp> | ||||
| #include "common/archives.h" | ||||
| #include "common/logging/log.h" | ||||
| #include "common/settings.h" | ||||
| #include "core/core.h" | ||||
| #include "core/frontend/mic.h" | ||||
| #include "core/hle/ipc.h" | ||||
|  | @ -14,7 +15,6 @@ | |||
| #include "core/hle/kernel/kernel.h" | ||||
| #include "core/hle/kernel/shared_memory.h" | ||||
| #include "core/hle/service/mic_u.h" | ||||
| #include "core/settings.h" | ||||
| 
 | ||||
| SERVICE_CONSTRUCT_IMPL(Service::MIC::MIC_U) | ||||
| SERIALIZE_EXPORT_IMPL(Service::MIC::MIC_U) | ||||
|  | @ -350,12 +350,12 @@ struct MIC_U::Impl { | |||
| 
 | ||||
|     void CreateMic() { | ||||
|         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: | ||||
|             new_mic = std::make_unique<Frontend::Mic::NullMic>(); | ||||
|             break; | ||||
|         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; | ||||
|         case Settings::MicInputType::Static: | ||||
|             new_mic = std::make_unique<Frontend::Mic::StaticMic>(); | ||||
|  |  | |||
|  | @ -7,6 +7,7 @@ | |||
| #include "common/common_paths.h" | ||||
| #include "common/file_util.h" | ||||
| #include "common/logging/log.h" | ||||
| #include "common/settings.h" | ||||
| #include "core/core.h" | ||||
| #include "core/file_sys/archive_extsavedata.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_sysm.h" | ||||
| #include "core/hle/service/ptm/ptm_u.h" | ||||
| #include "core/settings.h" | ||||
| 
 | ||||
| SERIALIZE_EXPORT_IMPL(Service::PTM::Module) | ||||
| 
 | ||||
|  | @ -118,7 +118,7 @@ void Module::Interface::GetSoftwareClosedFlag(Kernel::HLERequestContext& ctx) { | |||
| } | ||||
| 
 | ||||
| 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(is_new_3ds); | ||||
|  |  | |||
|  | @ -12,6 +12,7 @@ | |||
| #include "common/atomic_ops.h" | ||||
| #include "common/common_types.h" | ||||
| #include "common/logging/log.h" | ||||
| #include "common/settings.h" | ||||
| #include "common/swap.h" | ||||
| #include "core/arm/arm_interface.h" | ||||
| #include "core/core.h" | ||||
|  | @ -20,7 +21,6 @@ | |||
| #include "core/hle/kernel/process.h" | ||||
| #include "core/hle/lock.h" | ||||
| #include "core/memory.h" | ||||
| #include "core/settings.h" | ||||
| #include "video_core/renderer_base.h" | ||||
| #include "video_core/video_core.h" | ||||
| 
 | ||||
|  | @ -289,7 +289,7 @@ private: | |||
|     friend class boost::serialization::access; | ||||
|     template <class Archive> | ||||
|     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& boost::serialization::make_binary_object(vram.get(), Memory::VRAM_SIZE); | ||||
|         ar& boost::serialization::make_binary_object( | ||||
|  |  | |||
|  | @ -601,8 +601,8 @@ void Movie::PrepareForPlayback(const std::string& movie_file) { | |||
| } | ||||
| 
 | ||||
| void Movie::PrepareForRecording() { | ||||
|     if (Settings::values.init_clock == Settings::InitClock::SystemTime) { | ||||
|         long long init_time_offset = Settings::values.init_time_offset; | ||||
|     if (Settings::values.init_clock.GetValue() == Settings::InitClock::SystemTime) { | ||||
|         long long init_time_offset = Settings::values.init_time_offset.GetValue(); | ||||
|         long long days_offset = init_time_offset / 86400; | ||||
|         unsigned long long seconds_offset = | ||||
|             std::abs(init_time_offset) - std::abs(days_offset * 86400); | ||||
|  | @ -610,7 +610,7 @@ void Movie::PrepareForRecording() { | |||
|         init_time = | ||||
|             Common::Timer::GetTimeSinceJan1970().count() + seconds_offset + (days_offset * 86400); | ||||
|     } else { | ||||
|         init_time = Settings::values.init_time; | ||||
|         init_time = Settings::values.init_time.GetValue(); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -12,9 +12,9 @@ | |||
| #include <fmt/chrono.h> | ||||
| #include <fmt/format.h> | ||||
| #include "common/file_util.h" | ||||
| #include "common/settings.h" | ||||
| #include "core/hw/gpu.h" | ||||
| #include "core/perf_stats.h" | ||||
| #include "core/settings.h" | ||||
| 
 | ||||
| using namespace std::chrono_literals; | ||||
| 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(); | ||||
|     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_alternate == 0) { | ||||
|             return; | ||||
|         } | ||||
|         sleep_scale = Settings::values.frame_limit_alternate / 100.0; | ||||
|     } else if (Settings::values.frame_limit == 0) { | ||||
|     if (Settings::values.frame_limit.GetValue() == 0) { | ||||
|         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/logging/log.h" | ||||
| #include "common/scm_rev.h" | ||||
| #include "common/settings.h" | ||||
| #include "core/core.h" | ||||
| #include "core/settings.h" | ||||
| #include "core/telemetry_session.h" | ||||
| #include "network/network_settings.h" | ||||
| 
 | ||||
|  | @ -124,35 +124,37 @@ void TelemetrySession::AddInitialInfo(Loader::AppLoader& app_loader) { | |||
|     Telemetry::AppendOSInfo(field_collection); | ||||
| 
 | ||||
|     // 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", | ||||
|              Settings::values.enable_audio_stretching); | ||||
|     AddField(Telemetry::FieldType::UserConfig, "Core_UseCpuJit", Settings::values.use_cpu_jit); | ||||
|              Settings::values.enable_audio_stretching.GetValue()); | ||||
|     AddField(Telemetry::FieldType::UserConfig, "Core_UseCpuJit", | ||||
|              Settings::values.use_cpu_jit.GetValue()); | ||||
|     AddField(Telemetry::FieldType::UserConfig, "Renderer_ResolutionFactor", | ||||
|              Settings::values.resolution_factor); | ||||
|     AddField(Telemetry::FieldType::UserConfig, "Renderer_FrameLimit", Settings::values.frame_limit); | ||||
|     AddField(Telemetry::FieldType::UserConfig, "Renderer_UseFrameLimitAlternate", | ||||
|              Settings::values.use_frame_limit_alternate); | ||||
|     AddField(Telemetry::FieldType::UserConfig, "Renderer_FrameLimitAlternate", | ||||
|              Settings::values.frame_limit_alternate); | ||||
|              Settings::values.resolution_factor.GetValue()); | ||||
|     AddField(Telemetry::FieldType::UserConfig, "Renderer_FrameLimit", | ||||
|              Settings::values.frame_limit.GetValue()); | ||||
|     AddField(Telemetry::FieldType::UserConfig, "Renderer_UseHwRenderer", | ||||
|              Settings::values.use_hw_renderer); | ||||
|              Settings::values.use_hw_renderer.GetValue()); | ||||
|     AddField(Telemetry::FieldType::UserConfig, "Renderer_UseHwShader", | ||||
|              Settings::values.use_hw_shader); | ||||
|              Settings::values.use_hw_shader.GetValue()); | ||||
|     AddField(Telemetry::FieldType::UserConfig, "Renderer_ShadersAccurateMul", | ||||
|              Settings::values.shaders_accurate_mul); | ||||
|              Settings::values.shaders_accurate_mul.GetValue()); | ||||
|     AddField(Telemetry::FieldType::UserConfig, "Renderer_UseShaderJit", | ||||
|              Settings::values.use_shader_jit); | ||||
|     AddField(Telemetry::FieldType::UserConfig, "Renderer_UseVsync", Settings::values.use_vsync_new); | ||||
|     AddField(Telemetry::FieldType::UserConfig, "Renderer_FilterMode", Settings::values.filter_mode); | ||||
|              Settings::values.use_shader_jit.GetValue()); | ||||
|     AddField(Telemetry::FieldType::UserConfig, "Renderer_UseVsync", | ||||
|              Settings::values.use_vsync_new.GetValue()); | ||||
|     AddField(Telemetry::FieldType::UserConfig, "Renderer_FilterMode", | ||||
|              Settings::values.filter_mode.GetValue()); | ||||
|     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", | ||||
|              Settings::values.factor_3d.load()); | ||||
|              Settings::values.factor_3d.GetValue()); | ||||
|     AddField(Telemetry::FieldType::UserConfig, "Renderer_MonoRenderLeftEye", | ||||
|              Settings::values.mono_render_left_eye); | ||||
|     AddField(Telemetry::FieldType::UserConfig, "System_IsNew3ds", Settings::values.is_new_3ds); | ||||
|     AddField(Telemetry::FieldType::UserConfig, "System_RegionValue", Settings::values.region_value); | ||||
|              Settings::values.mono_render_left_eye.GetValue()); | ||||
|     AddField(Telemetry::FieldType::UserConfig, "System_IsNew3ds", | ||||
|              Settings::values.is_new_3ds.GetValue()); | ||||
|     AddField(Telemetry::FieldType::UserConfig, "System_RegionValue", | ||||
|              Settings::values.region_value.GetValue()); | ||||
| } | ||||
| 
 | ||||
| bool TelemetrySession::SubmitTestcase() { | ||||
|  |  | |||
|  | @ -5,8 +5,8 @@ | |||
| #pragma once | ||||
| 
 | ||||
| #include <memory> | ||||
| #include "common/settings.h" | ||||
| #include "core/frontend/input.h" | ||||
| #include "core/settings.h" | ||||
| #include "input_common/gcadapter/gc_adapter.h" | ||||
| #include "input_common/main.h" | ||||
| 
 | ||||
|  |  | |||
|  | @ -7,8 +7,8 @@ | |||
| #include <atomic> | ||||
| #include <memory> | ||||
| #include <thread> | ||||
| #include "common/settings.h" | ||||
| #include "common/threadsafe_queue.h" | ||||
| #include "core/settings.h" | ||||
| #include "input_common/sdl/sdl.h" | ||||
| 
 | ||||
| union SDL_Event; | ||||
|  |  | |||
|  | @ -2,8 +2,8 @@ | |||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include "common/settings.h" | ||||
| #include "core/3ds.h" | ||||
| #include "core/settings.h" | ||||
| #include "input_common/touch_from_button.h" | ||||
| 
 | ||||
| namespace InputCommon { | ||||
|  |  | |||
|  | @ -6,8 +6,8 @@ | |||
| #include <optional> | ||||
| #include <tuple> | ||||
| #include "common/param_package.h" | ||||
| #include "common/settings.h" | ||||
| #include "core/frontend/input.h" | ||||
| #include "core/settings.h" | ||||
| #include "input_common/udp/client.h" | ||||
| #include "input_common/udp/udp.h" | ||||
| 
 | ||||
|  |  | |||
|  | @ -241,8 +241,8 @@ static Surface FindMatch(const SurfaceCache& surface_cache, const SurfaceParams& | |||
| 
 | ||||
| RasterizerCacheOpenGL::RasterizerCacheOpenGL() { | ||||
|     resolution_scale_factor = VideoCore::GetResolutionScaleFactor(); | ||||
|     texture_filterer = std::make_unique<TextureFilterer>(Settings::values.texture_filter_name, | ||||
|                                                          resolution_scale_factor); | ||||
|     texture_filterer = std::make_unique<TextureFilterer>( | ||||
|         Settings::values.texture_filter_name.GetValue(), resolution_scale_factor); | ||||
|     format_reinterpreter = std::make_unique<FormatReinterpreterOpenGL>(); | ||||
|     texture_downloader_es = std::make_unique<TextureDownloaderES>(false); | ||||
| } | ||||
|  | @ -592,7 +592,7 @@ SurfaceSurfaceRect_Tuple RasterizerCacheOpenGL::GetFramebufferSurfaces( | |||
|         resolution_scale_factor != VideoCore::GetResolutionScaleFactor(); | ||||
|     const bool texture_filter_changed = | ||||
|         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()); | ||||
| 
 | ||||
|     if (resolution_scale_changed || texture_filter_changed) { | ||||
|  |  | |||
|  | @ -11,10 +11,10 @@ | |||
| #include "common/file_util.h" | ||||
| #include "common/logging/log.h" | ||||
| #include "common/scm_rev.h" | ||||
| #include "common/settings.h" | ||||
| #include "common/zstd_compression.h" | ||||
| #include "core/core.h" | ||||
| #include "core/hle/kernel/process.h" | ||||
| #include "core/settings.h" | ||||
| #include "video_core/renderer_opengl/gl_shader_disk_cache.h" | ||||
| 
 | ||||
| namespace OpenGL { | ||||
|  |  | |||
|  | @ -5,6 +5,7 @@ | |||
| #include <queue> | ||||
| #include "common/logging/log.h" | ||||
| #include "common/microprofile.h" | ||||
| #include "common/settings.h" | ||||
| #include "core/core.h" | ||||
| #include "core/dumping/backend.h" | ||||
| #include "core/frontend/emu_window.h" | ||||
|  | @ -12,7 +13,6 @@ | |||
| #include "core/hw/hw.h" | ||||
| #include "core/hw/lcd.h" | ||||
| #include "core/memory.h" | ||||
| #include "core/settings.h" | ||||
| #include "core/tracer/recorder.h" | ||||
| #include "video_core/debug_utils/debug_utils.h" | ||||
| #include "video_core/rasterizer_interface.h" | ||||
|  | @ -381,7 +381,7 @@ void RendererOpenGL::SwapBuffers() { | |||
|     RenderToMailbox(main_layout, render_window.mailbox, false); | ||||
| 
 | ||||
| #ifndef ANDROID | ||||
|     if (Settings::values.layout_option == Settings::LayoutOption::SeparateWindows) { | ||||
|     if (Settings::values.layout_option.GetValue() == Settings::LayoutOption::SeparateWindows) { | ||||
|         ASSERT(secondary_window); | ||||
|         const auto& secondary_layout = secondary_window->GetFramebufferLayout(); | ||||
|         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. | ||||
|  */ | ||||
| void RendererOpenGL::InitOpenGLObjects() { | ||||
|     glClearColor(Settings::values.bg_red, Settings::values.bg_green, Settings::values.bg_blue, | ||||
|                  0.0f); | ||||
|     glClearColor(Settings::values.bg_red.GetValue(), Settings::values.bg_green.GetValue(), | ||||
|                  Settings::values.bg_blue.GetValue(), 0.0f); | ||||
| 
 | ||||
|     filter_sampler.Create(); | ||||
|     ReloadSampler(); | ||||
|  | @ -685,12 +685,13 @@ void RendererOpenGL::ReloadShader() { | |||
|     if (GLES) { | ||||
|         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; | ||||
|         } else { | ||||
|             std::string shader_text = | ||||
|                 OpenGL::GetPostProcessingShaderCode(true, Settings::values.pp_shader_name); | ||||
|             std::string shader_text = OpenGL::GetPostProcessingShaderCode( | ||||
|                 true, Settings::values.pp_shader_name.GetValue()); | ||||
|             if (shader_text.empty()) { | ||||
|                 // Should probably provide some information that the shader couldn't load
 | ||||
|                 shader_data += fragment_shader_anaglyph; | ||||
|  | @ -698,13 +699,14 @@ void RendererOpenGL::ReloadShader() { | |||
|                 shader_data += shader_text; | ||||
|             } | ||||
|         } | ||||
|     } else if (Settings::values.render_3d == Settings::StereoRenderOption::Interlaced || | ||||
|                Settings::values.render_3d == Settings::StereoRenderOption::ReverseInterlaced) { | ||||
|         if (Settings::values.pp_shader_name == "horizontal (builtin)") { | ||||
|     } else if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Interlaced || | ||||
|                Settings::values.render_3d.GetValue() == | ||||
|                    Settings::StereoRenderOption::ReverseInterlaced) { | ||||
|         if (Settings::values.pp_shader_name.GetValue() == "horizontal (builtin)") { | ||||
|             shader_data += fragment_shader_interlaced; | ||||
|         } else { | ||||
|             std::string shader_text = | ||||
|                 OpenGL::GetPostProcessingShaderCode(false, Settings::values.pp_shader_name); | ||||
|             std::string shader_text = OpenGL::GetPostProcessingShaderCode( | ||||
|                 false, Settings::values.pp_shader_name.GetValue()); | ||||
|             if (shader_text.empty()) { | ||||
|                 // Should probably provide some information that the shader couldn't load
 | ||||
|                 shader_data += fragment_shader_interlaced; | ||||
|  | @ -713,11 +715,11 @@ void RendererOpenGL::ReloadShader() { | |||
|             } | ||||
|         } | ||||
|     } else { | ||||
|         if (Settings::values.pp_shader_name == "none (builtin)") { | ||||
|         if (Settings::values.pp_shader_name.GetValue() == "none (builtin)") { | ||||
|             shader_data += fragment_shader; | ||||
|         } else { | ||||
|             std::string shader_text = | ||||
|                 OpenGL::GetPostProcessingShaderCode(false, Settings::values.pp_shader_name); | ||||
|             std::string shader_text = OpenGL::GetPostProcessingShaderCode( | ||||
|                 false, Settings::values.pp_shader_name.GetValue()); | ||||
|             if (shader_text.empty()) { | ||||
|                 // Should probably provide some information that the shader couldn't load
 | ||||
|                 shader_data += fragment_shader; | ||||
|  | @ -731,16 +733,17 @@ void RendererOpenGL::ReloadShader() { | |||
|     state.Apply(); | ||||
|     uniform_modelview_matrix = glGetUniformLocation(shader.handle, "modelview_matrix"); | ||||
|     uniform_color_texture = glGetUniformLocation(shader.handle, "color_texture"); | ||||
|     if (Settings::values.render_3d == Settings::StereoRenderOption::Anaglyph || | ||||
|         Settings::values.render_3d == Settings::StereoRenderOption::Interlaced || | ||||
|         Settings::values.render_3d == Settings::StereoRenderOption::ReverseInterlaced) { | ||||
|     if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Anaglyph || | ||||
|         Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Interlaced || | ||||
|         Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::ReverseInterlaced) { | ||||
|         uniform_color_texture_r = glGetUniformLocation(shader.handle, "color_texture_r"); | ||||
|     } | ||||
|     if (Settings::values.render_3d == Settings::StereoRenderOption::Interlaced || | ||||
|         Settings::values.render_3d == Settings::StereoRenderOption::ReverseInterlaced) { | ||||
|     if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Interlaced || | ||||
|         Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::ReverseInterlaced) { | ||||
|         GLuint uniform_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); | ||||
|         else | ||||
|             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) { | ||||
|     if (VideoCore::g_renderer_bg_color_update_requested.exchange(false)) { | ||||
|         // Update background color before drawing
 | ||||
|         glClearColor(Settings::values.bg_red, Settings::values.bg_green, Settings::values.bg_blue, | ||||
|                      0.0f); | ||||
|         glClearColor(Settings::values.bg_red.GetValue(), Settings::values.bg_green.GetValue(), | ||||
|                      Settings::values.bg_blue.GetValue(), 0.0f); | ||||
|     } | ||||
| 
 | ||||
|     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); | ||||
| 
 | ||||
|     const bool stereo_single_screen = | ||||
|         Settings::values.render_3d == Settings::StereoRenderOption::Anaglyph || | ||||
|         Settings::values.render_3d == Settings::StereoRenderOption::Interlaced || | ||||
|         Settings::values.render_3d == Settings::StereoRenderOption::ReverseInterlaced; | ||||
|         Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Anaglyph || | ||||
|         Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Interlaced || | ||||
|         Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::ReverseInterlaced; | ||||
| 
 | ||||
|     // Bind a second texture for the right eye if in Anaglyph mode
 | ||||
|     if (stereo_single_screen) { | ||||
|  | @ -1001,12 +1004,13 @@ void RendererOpenGL::DrawScreens(const Layout::FramebufferLayout& layout, bool f | |||
|     glUniform1i(uniform_layer, 0); | ||||
|     if (layout.top_screen_enabled) { | ||||
|         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; | ||||
|                 DrawSingleScreenRotated(screen_infos[eye], (float)top_screen.left, | ||||
|                                         (float)top_screen.top, (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) { | ||||
|                 DrawSingleScreenRotated(screen_infos[0], (float)top_screen.left / 2, | ||||
|                                         (float)top_screen.top, (float)top_screen.GetWidth() / 2, | ||||
|                                         (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.top, (float)top_screen.GetWidth() / 2, | ||||
|                                         (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, | ||||
|                                         layout.top_screen.top, layout.top_screen.GetWidth(), | ||||
|                                         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()); | ||||
|             } | ||||
|         } else { | ||||
|             if (Settings::values.render_3d == Settings::StereoRenderOption::Off) { | ||||
|                 int eye = Settings::values.mono_render_left_eye ? 0 : 1; | ||||
|             if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Off) { | ||||
|                 int eye = Settings::values.mono_render_left_eye.GetValue() ? 0 : 1; | ||||
|                 DrawSingleScreen(screen_infos[eye], (float)top_screen.left, (float)top_screen.top, | ||||
|                                  (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, | ||||
|                                  (float)top_screen.GetWidth() / 2, (float)top_screen.GetHeight()); | ||||
|                 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.top, (float)top_screen.GetWidth() / 2, | ||||
|                                  (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, | ||||
|                                  layout.top_screen.GetWidth(), layout.top_screen.GetHeight()); | ||||
|                 glUniform1i(uniform_layer, 1); | ||||
|  | @ -1061,11 +1068,12 @@ void RendererOpenGL::DrawScreens(const Layout::FramebufferLayout& layout, bool f | |||
|     glUniform1i(uniform_layer, 0); | ||||
|     if (layout.bottom_screen_enabled) { | ||||
|         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, | ||||
|                                         (float)bottom_screen.top, (float)bottom_screen.GetWidth(), | ||||
|                                         (float)bottom_screen.GetHeight()); | ||||
|             } else if (Settings::values.render_3d == Settings::StereoRenderOption::SideBySide) { | ||||
|             } else if (Settings::values.render_3d.GetValue() == | ||||
|                        Settings::StereoRenderOption::SideBySide) { | ||||
|                 DrawSingleScreenRotated( | ||||
|                     screen_infos[2], (float)bottom_screen.left / 2, (float)bottom_screen.top, | ||||
|                     (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), | ||||
|                     (float)bottom_screen.top, (float)bottom_screen.GetWidth() / 2, | ||||
|                     (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, | ||||
|                                         layout.bottom_screen.top, layout.bottom_screen.GetWidth(), | ||||
|                                         layout.bottom_screen.GetHeight()); | ||||
|  | @ -1091,11 +1100,12 @@ void RendererOpenGL::DrawScreens(const Layout::FramebufferLayout& layout, bool f | |||
|                                               (float)bottom_screen.GetHeight()); | ||||
|             } | ||||
|         } 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, | ||||
|                                  (float)bottom_screen.top, (float)bottom_screen.GetWidth(), | ||||
|                                  (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, | ||||
|                                  (float)bottom_screen.top, (float)bottom_screen.GetWidth() / 2, | ||||
|                                  (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.top, (float)bottom_screen.GetWidth() / 2, | ||||
|                                  (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, | ||||
|                                  layout.bottom_screen.top, layout.bottom_screen.GetWidth(), | ||||
|                                  layout.bottom_screen.GetHeight()); | ||||
|  |  | |||
|  | @ -5,7 +5,7 @@ | |||
| #include <memory> | ||||
| #include "common/archives.h" | ||||
| #include "common/logging/log.h" | ||||
| #include "core/settings.h" | ||||
| #include "common/settings.h" | ||||
| #include "video_core/pica.h" | ||||
| #include "video_core/pica_state.h" | ||||
| #include "video_core/renderer_base.h" | ||||
|  | @ -44,7 +44,7 @@ ResultStatus Init(Frontend::EmuWindow& emu_window, Frontend::EmuWindow* secondar | |||
|     g_memory = &memory; | ||||
|     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); | ||||
|     ResultStatus result = g_renderer->Init(); | ||||
|  | @ -82,8 +82,8 @@ void RequestScreenshot(void* data, std::function<void()> callback, | |||
| 
 | ||||
| u16 GetResolutionScaleFactor() { | ||||
|     if (g_hw_renderer_enabled) { | ||||
|         return Settings::values.resolution_factor | ||||
|                    ? Settings::values.resolution_factor | ||||
|         return Settings::values.resolution_factor.GetValue() | ||||
|                    ? Settings::values.resolution_factor.GetValue() | ||||
|                    : g_renderer->GetRenderWindow().GetFramebufferLayout().GetScalingRatio(); | ||||
|     } else { | ||||
|         // Software renderer always render at native resolution
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue