diff options
Diffstat (limited to 'src/common')
-rw-r--r-- | src/common/CMakeLists.txt | 6 | ||||
-rw-r--r-- | src/common/assert.cpp | 14 | ||||
-rw-r--r-- | src/common/assert.h | 14 | ||||
-rw-r--r-- | src/common/common_sizes.h | 43 | ||||
-rw-r--r-- | src/common/logging/backend.cpp | 28 | ||||
-rw-r--r-- | src/common/logging/backend.h | 4 | ||||
-rw-r--r-- | src/common/logging/filter.cpp | 4 | ||||
-rw-r--r-- | src/common/logging/filter.h | 4 | ||||
-rw-r--r-- | src/common/logging/log.h | 35 | ||||
-rw-r--r-- | src/common/logging/text_formatter.cpp | 4 | ||||
-rw-r--r-- | src/common/logging/text_formatter.h | 4 | ||||
-rw-r--r-- | src/common/nvidia_flags.h | 2 | ||||
-rw-r--r-- | src/common/settings.cpp | 143 | ||||
-rw-r--r-- | src/common/settings.h | 261 | ||||
-rw-r--r-- | src/common/settings_input.cpp | 47 | ||||
-rw-r--r-- | src/common/settings_input.h | 373 | ||||
-rw-r--r-- | src/common/threadsafe_queue.h | 10 |
17 files changed, 953 insertions, 43 deletions
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 788516ded..88644eeb6 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -97,6 +97,7 @@ add_custom_command(OUTPUT scm_rev.cpp add_library(common STATIC algorithm.h alignment.h + assert.cpp assert.h atomic_ops.h detached_tasks.cpp @@ -109,6 +110,7 @@ add_library(common STATIC cityhash.h common_funcs.h common_paths.h + common_sizes.h common_types.h concepts.h div_ceil.h @@ -150,6 +152,10 @@ add_library(common STATIC scm_rev.cpp scm_rev.h scope_exit.h + settings.cpp + settings.h + settings_input.cpp + settings_input.h spin_lock.cpp spin_lock.h stream.cpp diff --git a/src/common/assert.cpp b/src/common/assert.cpp new file mode 100644 index 000000000..72f1121aa --- /dev/null +++ b/src/common/assert.cpp @@ -0,0 +1,14 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "common/assert.h" +#include "common/common_funcs.h" + +#include "common/settings.h" + +void assert_handle_failure() { + if (Settings::values.use_debug_asserts) { + Crash(); + } +} diff --git a/src/common/assert.h b/src/common/assert.h index 06d7b5612..b3ba35c0f 100644 --- a/src/common/assert.h +++ b/src/common/assert.h @@ -4,10 +4,13 @@ #pragma once -#include <cstdlib> -#include "common/common_funcs.h" #include "common/logging/log.h" +// Sometimes we want to try to continue even after hitting an assert. +// However touching this file yields a global recompilation as this header is included almost +// everywhere. So let's just move the handling of the failed assert to a single cpp file. +void assert_handle_failure(); + // For asserts we'd like to keep all the junk executed when an assert happens away from the // important code in the function. One way of doing this is to put all the relevant code inside a // lambda and force the compiler to not inline it. Unfortunately, MSVC seems to have no syntax to @@ -17,15 +20,14 @@ // enough for our purposes. template <typename Fn> #if defined(_MSC_VER) -[[msvc::noinline, noreturn]] +[[msvc::noinline]] #elif defined(__GNUC__) -[[gnu::cold, gnu::noinline, noreturn]] +[[gnu::cold, gnu::noinline]] #endif static void assert_noinline_call(const Fn& fn) { fn(); - Crash(); - exit(1); // Keeps GCC's mouth shut about this actually returning + assert_handle_failure(); } #define ASSERT(_a_) \ diff --git a/src/common/common_sizes.h b/src/common/common_sizes.h new file mode 100644 index 000000000..7e9fd968b --- /dev/null +++ b/src/common/common_sizes.h @@ -0,0 +1,43 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include <limits> + +#include "common/common_types.h" + +namespace Common { + +enum : u64 { + Size_1_KB = 0x400ULL, + Size_64_KB = 64ULL * Size_1_KB, + Size_128_KB = 128ULL * Size_1_KB, + Size_1_MB = 0x100000ULL, + Size_2_MB = 2ULL * Size_1_MB, + Size_4_MB = 4ULL * Size_1_MB, + Size_5_MB = 5ULL * Size_1_MB, + Size_14_MB = 14ULL * Size_1_MB, + Size_32_MB = 32ULL * Size_1_MB, + Size_33_MB = 33ULL * Size_1_MB, + Size_128_MB = 128ULL * Size_1_MB, + Size_448_MB = 448ULL * Size_1_MB, + Size_507_MB = 507ULL * Size_1_MB, + Size_562_MB = 562ULL * Size_1_MB, + Size_1554_MB = 1554ULL * Size_1_MB, + Size_2048_MB = 2048ULL * Size_1_MB, + Size_2193_MB = 2193ULL * Size_1_MB, + Size_3285_MB = 3285ULL * Size_1_MB, + Size_4916_MB = 4916ULL * Size_1_MB, + Size_1_GB = 0x40000000ULL, + Size_2_GB = 2ULL * Size_1_GB, + Size_4_GB = 4ULL * Size_1_GB, + Size_6_GB = 6ULL * Size_1_GB, + Size_8_GB = 8ULL * Size_1_GB, + Size_64_GB = 64ULL * Size_1_GB, + Size_512_GB = 512ULL * Size_1_GB, + Size_Invalid = std::numeric_limits<u64>::max(), +}; + +} // namespace Common diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp index 2d4d2e9e7..bc82905c0 100644 --- a/src/common/logging/backend.cpp +++ b/src/common/logging/backend.cpp @@ -21,11 +21,11 @@ #include "common/logging/backend.h" #include "common/logging/log.h" #include "common/logging/text_formatter.h" +#include "common/settings.h" #include "common/string_util.h" #include "common/threadsafe_queue.h" -#include "core/settings.h" -namespace Log { +namespace Common::Log { /** * Static state as a singleton. @@ -37,8 +37,11 @@ public: return backend; } - Impl(Impl const&) = delete; - const Impl& operator=(Impl const&) = delete; + Impl(const Impl&) = delete; + Impl& operator=(const Impl&) = delete; + + Impl(Impl&&) = delete; + Impl& operator=(Impl&&) = delete; void PushEntry(Class log_class, Level log_level, const char* filename, unsigned int line_num, const char* function, std::string message) { @@ -132,7 +135,7 @@ private: std::mutex writing_mutex; std::thread backend_thread; std::vector<std::unique_ptr<Backend>> backends; - Common::MPSCQueue<Log::Entry> message_queue; + MPSCQueue<Entry> message_queue; Filter filter; std::chrono::steady_clock::time_point time_origin{std::chrono::steady_clock::now()}; }; @@ -146,16 +149,16 @@ void ColorConsoleBackend::Write(const Entry& entry) { } FileBackend::FileBackend(const std::string& filename) : bytes_written(0) { - if (Common::FS::Exists(filename + ".old.txt")) { - Common::FS::Delete(filename + ".old.txt"); + if (FS::Exists(filename + ".old.txt")) { + FS::Delete(filename + ".old.txt"); } - if (Common::FS::Exists(filename)) { - Common::FS::Rename(filename, filename + ".old.txt"); + if (FS::Exists(filename)) { + FS::Rename(filename, filename + ".old.txt"); } // _SH_DENYWR allows read only access to the file for other programs. // It is #defined to 0 on other platforms - file = Common::FS::IOFile(filename, "w", _SH_DENYWR); + file = FS::IOFile(filename, "w", _SH_DENYWR); } void FileBackend::Write(const Entry& entry) { @@ -182,7 +185,7 @@ void FileBackend::Write(const Entry& entry) { void DebuggerBackend::Write(const Entry& entry) { #ifdef _WIN32 - ::OutputDebugStringW(Common::UTF8ToUTF16W(FormatLogMessage(entry).append(1, '\n')).c_str()); + ::OutputDebugStringW(UTF8ToUTF16W(FormatLogMessage(entry).append(1, '\n')).c_str()); #endif } @@ -212,6 +215,7 @@ void DebuggerBackend::Write(const Entry& entry) { SUB(Service, ARP) \ SUB(Service, BCAT) \ SUB(Service, BPC) \ + SUB(Service, BGTC) \ SUB(Service, BTDRV) \ SUB(Service, BTM) \ SUB(Service, Capture) \ @@ -341,4 +345,4 @@ void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename, instance.PushEntry(log_class, log_level, filename, line_num, function, fmt::vformat(format, args)); } -} // namespace Log +} // namespace Common::Log diff --git a/src/common/logging/backend.h b/src/common/logging/backend.h index da1c2f185..84a544ea4 100644 --- a/src/common/logging/backend.h +++ b/src/common/logging/backend.h @@ -11,7 +11,7 @@ #include "common/logging/filter.h" #include "common/logging/log.h" -namespace Log { +namespace Common::Log { class Filter; @@ -135,4 +135,4 @@ const char* GetLevelName(Level log_level); * never get the message */ void SetGlobalFilter(const Filter& filter); -} // namespace Log
\ No newline at end of file +} // namespace Common::Log
\ No newline at end of file diff --git a/src/common/logging/filter.cpp b/src/common/logging/filter.cpp index 2eccbcd8d..20a2dd106 100644 --- a/src/common/logging/filter.cpp +++ b/src/common/logging/filter.cpp @@ -7,7 +7,7 @@ #include "common/logging/filter.h" #include "common/string_util.h" -namespace Log { +namespace Common::Log { namespace { template <typename It> Level GetLevelByName(const It begin, const It end) { @@ -103,4 +103,4 @@ bool Filter::IsDebug() const { }); } -} // namespace Log +} // namespace Common::Log diff --git a/src/common/logging/filter.h b/src/common/logging/filter.h index 773df6f2c..f5673a9f6 100644 --- a/src/common/logging/filter.h +++ b/src/common/logging/filter.h @@ -9,7 +9,7 @@ #include <string_view> #include "common/logging/log.h" -namespace Log { +namespace Common::Log { /** * Implements a log message filter which allows different log classes to have different minimum @@ -51,4 +51,4 @@ public: private: std::array<Level, static_cast<std::size_t>(Class::Count)> class_levels; }; -} // namespace Log +} // namespace Common::Log diff --git a/src/common/logging/log.h b/src/common/logging/log.h index 835894918..1f0f8db52 100644 --- a/src/common/logging/log.h +++ b/src/common/logging/log.h @@ -7,7 +7,7 @@ #include <fmt/format.h> #include "common/common_types.h" -namespace Log { +namespace Common::Log { // trims up to and including the last of ../, ..\, src/, src\ in a string constexpr const char* TrimSourcePath(std::string_view source) { @@ -66,6 +66,7 @@ enum class Class : ClassType { Service_ARP, ///< The ARP service Service_Audio, ///< The Audio (Audio control) service Service_BCAT, ///< The BCAT service + Service_BGTC, ///< The BGTC (Background Task Controller) service Service_BPC, ///< The BPC service Service_BTDRV, ///< The Bluetooth driver service Service_BTM, ///< The BTM service @@ -147,28 +148,34 @@ void FmtLogMessage(Class log_class, Level log_level, const char* filename, unsig fmt::make_format_args(args...)); } -} // namespace Log +} // namespace Common::Log #ifdef _DEBUG #define LOG_TRACE(log_class, ...) \ - ::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Trace, \ - ::Log::TrimSourcePath(__FILE__), __LINE__, __func__, __VA_ARGS__) + Common::Log::FmtLogMessage(Common::Log::Class::log_class, Common::Log::Level::Trace, \ + Common::Log::TrimSourcePath(__FILE__), __LINE__, __func__, \ + __VA_ARGS__) #else #define LOG_TRACE(log_class, fmt, ...) (void(0)) #endif #define LOG_DEBUG(log_class, ...) \ - ::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Debug, \ - ::Log::TrimSourcePath(__FILE__), __LINE__, __func__, __VA_ARGS__) + Common::Log::FmtLogMessage(Common::Log::Class::log_class, Common::Log::Level::Debug, \ + Common::Log::TrimSourcePath(__FILE__), __LINE__, __func__, \ + __VA_ARGS__) #define LOG_INFO(log_class, ...) \ - ::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Info, \ - ::Log::TrimSourcePath(__FILE__), __LINE__, __func__, __VA_ARGS__) + Common::Log::FmtLogMessage(Common::Log::Class::log_class, Common::Log::Level::Info, \ + Common::Log::TrimSourcePath(__FILE__), __LINE__, __func__, \ + __VA_ARGS__) #define LOG_WARNING(log_class, ...) \ - ::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Warning, \ - ::Log::TrimSourcePath(__FILE__), __LINE__, __func__, __VA_ARGS__) + Common::Log::FmtLogMessage(Common::Log::Class::log_class, Common::Log::Level::Warning, \ + Common::Log::TrimSourcePath(__FILE__), __LINE__, __func__, \ + __VA_ARGS__) #define LOG_ERROR(log_class, ...) \ - ::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Error, \ - ::Log::TrimSourcePath(__FILE__), __LINE__, __func__, __VA_ARGS__) + Common::Log::FmtLogMessage(Common::Log::Class::log_class, Common::Log::Level::Error, \ + Common::Log::TrimSourcePath(__FILE__), __LINE__, __func__, \ + __VA_ARGS__) #define LOG_CRITICAL(log_class, ...) \ - ::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Critical, \ - ::Log::TrimSourcePath(__FILE__), __LINE__, __func__, __VA_ARGS__) + Common::Log::FmtLogMessage(Common::Log::Class::log_class, Common::Log::Level::Critical, \ + Common::Log::TrimSourcePath(__FILE__), __LINE__, __func__, \ + __VA_ARGS__) diff --git a/src/common/logging/text_formatter.cpp b/src/common/logging/text_formatter.cpp index 6a0605c63..80ee2cca1 100644 --- a/src/common/logging/text_formatter.cpp +++ b/src/common/logging/text_formatter.cpp @@ -16,7 +16,7 @@ #include "common/logging/text_formatter.h" #include "common/string_util.h" -namespace Log { +namespace Common::Log { std::string FormatLogMessage(const Entry& entry) { unsigned int time_seconds = static_cast<unsigned int>(entry.timestamp.count() / 1000000); @@ -108,4 +108,4 @@ void PrintColoredMessage(const Entry& entry) { #undef ESC #endif } -} // namespace Log +} // namespace Common::Log diff --git a/src/common/logging/text_formatter.h b/src/common/logging/text_formatter.h index b6d9e57c8..171e74cfe 100644 --- a/src/common/logging/text_formatter.h +++ b/src/common/logging/text_formatter.h @@ -7,7 +7,7 @@ #include <cstddef> #include <string> -namespace Log { +namespace Common::Log { struct Entry; @@ -17,4 +17,4 @@ std::string FormatLogMessage(const Entry& entry); void PrintMessage(const Entry& entry); /// Prints the same message as `PrintMessage`, but colored according to the severity level. void PrintColoredMessage(const Entry& entry); -} // namespace Log +} // namespace Common::Log diff --git a/src/common/nvidia_flags.h b/src/common/nvidia_flags.h index 75a0233ac..8930efcec 100644 --- a/src/common/nvidia_flags.h +++ b/src/common/nvidia_flags.h @@ -2,6 +2,8 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#pragma once + namespace Common { /// Configure platform specific flags for Nvidia's driver diff --git a/src/common/settings.cpp b/src/common/settings.cpp new file mode 100644 index 000000000..702b6598d --- /dev/null +++ b/src/common/settings.cpp @@ -0,0 +1,143 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include <string_view> + +#include "common/assert.h" +#include "common/file_util.h" +#include "common/logging/log.h" +#include "common/settings.h" + +namespace Settings { + +Values values = {}; +static bool configuring_global = true; + +std::string GetTimeZoneString() { + static constexpr std::array timezones{ + "auto", "default", "CET", "CST6CDT", "Cuba", "EET", "Egypt", "Eire", + "EST", "EST5EDT", "GB", "GB-Eire", "GMT", "GMT+0", "GMT-0", "GMT0", + "Greenwich", "Hongkong", "HST", "Iceland", "Iran", "Israel", "Jamaica", "Japan", + "Kwajalein", "Libya", "MET", "MST", "MST7MDT", "Navajo", "NZ", "NZ-CHAT", + "Poland", "Portugal", "PRC", "PST8PDT", "ROC", "ROK", "Singapore", "Turkey", + "UCT", "Universal", "UTC", "W-SU", "WET", "Zulu", + }; + + const auto time_zone_index = static_cast<std::size_t>(values.time_zone_index.GetValue()); + ASSERT(time_zone_index < timezones.size()); + return timezones[time_zone_index]; +} + +void LogSettings() { + const auto log_setting = [](std::string_view name, const auto& value) { + LOG_INFO(Config, "{}: {}", name, value); + }; + + LOG_INFO(Config, "yuzu Configuration:"); + log_setting("Controls_UseDockedMode", values.use_docked_mode.GetValue()); + log_setting("System_RngSeed", values.rng_seed.GetValue().value_or(0)); + log_setting("System_CurrentUser", values.current_user); + log_setting("System_LanguageIndex", values.language_index.GetValue()); + log_setting("System_RegionIndex", values.region_index.GetValue()); + log_setting("System_TimeZoneIndex", values.time_zone_index.GetValue()); + log_setting("Core_UseMultiCore", values.use_multi_core.GetValue()); + log_setting("CPU_Accuracy", values.cpu_accuracy); + log_setting("Renderer_UseResolutionFactor", values.resolution_factor.GetValue()); + log_setting("Renderer_UseFrameLimit", values.use_frame_limit.GetValue()); + log_setting("Renderer_FrameLimit", values.frame_limit.GetValue()); + log_setting("Renderer_UseDiskShaderCache", values.use_disk_shader_cache.GetValue()); + log_setting("Renderer_GPUAccuracyLevel", values.gpu_accuracy.GetValue()); + log_setting("Renderer_UseAsynchronousGpuEmulation", + values.use_asynchronous_gpu_emulation.GetValue()); + log_setting("Renderer_UseNvdecEmulation", values.use_nvdec_emulation.GetValue()); + log_setting("Renderer_UseVsync", values.use_vsync.GetValue()); + log_setting("Renderer_UseAssemblyShaders", values.use_assembly_shaders.GetValue()); + log_setting("Renderer_UseAsynchronousShaders", values.use_asynchronous_shaders.GetValue()); + log_setting("Renderer_AnisotropicFilteringLevel", values.max_anisotropy.GetValue()); + log_setting("Audio_OutputEngine", values.sink_id); + log_setting("Audio_EnableAudioStretching", values.enable_audio_stretching.GetValue()); + log_setting("Audio_OutputDevice", values.audio_device_id); + log_setting("DataStorage_UseVirtualSd", values.use_virtual_sd); + log_setting("DataStorage_CacheDir", Common::FS::GetUserPath(Common::FS::UserPath::CacheDir)); + log_setting("DataStorage_ConfigDir", Common::FS::GetUserPath(Common::FS::UserPath::ConfigDir)); + log_setting("DataStorage_LoadDir", Common::FS::GetUserPath(Common::FS::UserPath::LoadDir)); + log_setting("DataStorage_NandDir", Common::FS::GetUserPath(Common::FS::UserPath::NANDDir)); + log_setting("DataStorage_SdmcDir", Common::FS::GetUserPath(Common::FS::UserPath::SDMCDir)); + log_setting("Debugging_ProgramArgs", values.program_args); + log_setting("Services_BCATBackend", values.bcat_backend); + log_setting("Services_BCATBoxcatLocal", values.bcat_boxcat_local); +} + +bool IsConfiguringGlobal() { + return configuring_global; +} + +void SetConfiguringGlobal(bool is_global) { + configuring_global = is_global; +} + +bool IsGPULevelExtreme() { + return values.gpu_accuracy.GetValue() == GPUAccuracy::Extreme; +} + +bool IsGPULevelHigh() { + return values.gpu_accuracy.GetValue() == GPUAccuracy::Extreme || + values.gpu_accuracy.GetValue() == GPUAccuracy::High; +} + +float Volume() { + if (values.audio_muted) { + return 0.0f; + } + 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.enable_audio_stretching.SetGlobal(true); + values.volume.SetGlobal(true); + + // Core + values.use_multi_core.SetGlobal(true); + + // Renderer + values.renderer_backend.SetGlobal(true); + values.vulkan_device.SetGlobal(true); + values.aspect_ratio.SetGlobal(true); + values.max_anisotropy.SetGlobal(true); + values.use_frame_limit.SetGlobal(true); + values.frame_limit.SetGlobal(true); + values.use_disk_shader_cache.SetGlobal(true); + values.gpu_accuracy.SetGlobal(true); + values.use_asynchronous_gpu_emulation.SetGlobal(true); + values.use_nvdec_emulation.SetGlobal(true); + values.use_vsync.SetGlobal(true); + values.use_assembly_shaders.SetGlobal(true); + values.use_asynchronous_shaders.SetGlobal(true); + values.use_fast_gpu_time.SetGlobal(true); + values.bg_red.SetGlobal(true); + values.bg_green.SetGlobal(true); + values.bg_blue.SetGlobal(true); + + // System + values.language_index.SetGlobal(true); + values.region_index.SetGlobal(true); + values.time_zone_index.SetGlobal(true); + values.rng_seed.SetGlobal(true); + values.custom_rtc.SetGlobal(true); + values.sound_index.SetGlobal(true); + + // Controls + values.players.SetGlobal(true); + values.use_docked_mode.SetGlobal(true); + values.vibration_enabled.SetGlobal(true); + values.motion_enabled.SetGlobal(true); +} + +} // namespace Settings diff --git a/src/common/settings.h b/src/common/settings.h new file mode 100644 index 000000000..d39b4aa45 --- /dev/null +++ b/src/common/settings.h @@ -0,0 +1,261 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include <array> +#include <atomic> +#include <chrono> +#include <map> +#include <optional> +#include <string> +#include <vector> + +#include "common/common_types.h" +#include "common/settings_input.h" + +namespace Settings { + +enum class RendererBackend : u32 { + OpenGL = 0, + Vulkan = 1, +}; + +enum class GPUAccuracy : u32 { + Normal = 0, + High = 1, + Extreme = 2, +}; + +enum class CPUAccuracy : u32 { + Accurate = 0, + Unsafe = 1, + DebugMode = 2, +}; + +template <typename Type> +class Setting final { +public: + Setting() = default; + explicit Setting(Type val) : global{val} {} + ~Setting() = default; + void SetGlobal(bool to_global) { + use_global = to_global; + } + bool UsingGlobal() const { + return use_global; + } + Type GetValue(bool need_global = false) const { + if (use_global || need_global) { + return global; + } + return local; + } + void SetValue(const Type& value) { + if (use_global) { + global = value; + } else { + local = value; + } + } + +private: + bool use_global = true; + Type global{}; + Type local{}; +}; + +/** + * The InputSetting class allows for getting a reference to either the global or local 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 local (per-game) + * setting and allows for easily accessing and modifying both settings. + */ +template <typename Type> +class InputSetting final { +public: + InputSetting() = default; + explicit InputSetting(Type val) : global{val} {} + ~InputSetting() = default; + void SetGlobal(bool to_global) { + use_global = to_global; + } + bool UsingGlobal() const { + return use_global; + } + Type& GetValue(bool need_global = false) { + if (use_global || need_global) { + return global; + } + return local; + } + +private: + bool use_global = true; + Type global{}; + Type local{}; +}; + +struct TouchFromButtonMap { + std::string name; + std::vector<std::string> buttons; +}; + +struct Values { + // Audio + std::string audio_device_id; + std::string sink_id; + bool audio_muted; + Setting<bool> enable_audio_stretching; + Setting<float> volume; + + // Core + Setting<bool> use_multi_core; + + // Cpu + CPUAccuracy cpu_accuracy; + + bool cpuopt_page_tables; + bool cpuopt_block_linking; + bool cpuopt_return_stack_buffer; + bool cpuopt_fast_dispatcher; + bool cpuopt_context_elimination; + bool cpuopt_const_prop; + bool cpuopt_misc_ir; + bool cpuopt_reduce_misalign_checks; + + bool cpuopt_unsafe_unfuse_fma; + bool cpuopt_unsafe_reduce_fp_error; + bool cpuopt_unsafe_inaccurate_nan; + + // Renderer + Setting<RendererBackend> renderer_backend; + bool renderer_debug; + Setting<int> vulkan_device; + + Setting<u16> resolution_factor{1}; + Setting<int> fullscreen_mode; + Setting<int> aspect_ratio; + Setting<int> max_anisotropy; + Setting<bool> use_frame_limit; + Setting<u16> frame_limit; + Setting<bool> use_disk_shader_cache; + Setting<GPUAccuracy> gpu_accuracy; + Setting<bool> use_asynchronous_gpu_emulation; + Setting<bool> use_nvdec_emulation; + Setting<bool> use_vsync; + Setting<bool> use_assembly_shaders; + Setting<bool> use_asynchronous_shaders; + Setting<bool> use_fast_gpu_time; + + Setting<float> bg_red; + Setting<float> bg_green; + Setting<float> bg_blue; + + // System + Setting<std::optional<u32>> rng_seed; + // Measured in seconds since epoch + Setting<std::optional<std::chrono::seconds>> custom_rtc; + // Set on game boot, reset on stop. Seconds difference between current time and `custom_rtc` + std::chrono::seconds custom_rtc_differential; + + s32 current_user; + Setting<s32> language_index; + Setting<s32> region_index; + Setting<s32> time_zone_index; + Setting<s32> sound_index; + + // Controls + InputSetting<std::array<PlayerInput, 10>> players; + + Setting<bool> use_docked_mode; + + Setting<bool> vibration_enabled; + Setting<bool> enable_accurate_vibrations; + + Setting<bool> motion_enabled; + std::string motion_device; + std::string udp_input_servers; + + bool mouse_panning; + float mouse_panning_sensitivity; + bool mouse_enabled; + std::string mouse_device; + MouseButtonsRaw mouse_buttons; + + bool emulate_analog_keyboard; + bool keyboard_enabled; + KeyboardKeysRaw keyboard_keys; + KeyboardModsRaw keyboard_mods; + + bool debug_pad_enabled; + ButtonsRaw debug_pad_buttons; + AnalogsRaw debug_pad_analogs; + + TouchscreenInput touchscreen; + + bool use_touch_from_button; + std::string touch_device; + int touch_from_button_map_index; + std::vector<TouchFromButtonMap> touch_from_button_maps; + + std::atomic_bool is_device_reload_pending{true}; + + // Data Storage + bool use_virtual_sd; + bool gamecard_inserted; + bool gamecard_current_game; + std::string gamecard_path; + + // Debugging + bool record_frame_times; + bool use_gdbstub; + u16 gdbstub_port; + std::string program_args; + bool dump_exefs; + bool dump_nso; + bool reporting_services; + bool quest_flag; + bool disable_macro_jit; + bool extended_logging; + bool use_debug_asserts; + bool use_auto_stub; + + // Miscellaneous + std::string log_filter; + bool use_dev_keys; + + // Services + std::string bcat_backend; + bool bcat_boxcat_local; + + // WebService + bool enable_telemetry; + std::string web_api_url; + std::string yuzu_username; + std::string yuzu_token; + + // Add-Ons + std::map<u64, std::vector<std::string>> disabled_addons; +}; + +extern Values values; + +bool IsConfiguringGlobal(); +void SetConfiguringGlobal(bool is_global); + +bool IsGPULevelExtreme(); +bool IsGPULevelHigh(); + +float Volume(); + +std::string GetTimeZoneString(); + +void LogSettings(); + +// Restore the global state of all applicable settings in the Values struct +void RestoreGlobalState(bool is_powered_on); + +} // namespace Settings diff --git a/src/common/settings_input.cpp b/src/common/settings_input.cpp new file mode 100644 index 000000000..bea2b837b --- /dev/null +++ b/src/common/settings_input.cpp @@ -0,0 +1,47 @@ +// Copyright 2020 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "common/settings_input.h" + +namespace Settings { +namespace NativeButton { +const std::array<const char*, NumButtons> mapping = {{ + "button_a", "button_b", "button_x", "button_y", "button_lstick", + "button_rstick", "button_l", "button_r", "button_zl", "button_zr", + "button_plus", "button_minus", "button_dleft", "button_dup", "button_dright", + "button_ddown", "button_sl", "button_sr", "button_home", "button_screenshot", +}}; +} + +namespace NativeAnalog { +const std::array<const char*, NumAnalogs> mapping = {{ + "lstick", + "rstick", +}}; +} + +namespace NativeVibration { +const std::array<const char*, NumVibrations> mapping = {{ + "left_vibration_device", + "right_vibration_device", +}}; +} + +namespace NativeMotion { +const std::array<const char*, NumMotions> mapping = {{ + "motionleft", + "motionright", +}}; +} + +namespace NativeMouseButton { +const std::array<const char*, NumMouseButtons> mapping = {{ + "left", + "right", + "middle", + "forward", + "back", +}}; +} +} // namespace Settings diff --git a/src/common/settings_input.h b/src/common/settings_input.h new file mode 100644 index 000000000..609600582 --- /dev/null +++ b/src/common/settings_input.h @@ -0,0 +1,373 @@ +// Copyright 2020 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include <array> +#include <string> + +#include "common/common_types.h" + +namespace Settings { +namespace NativeButton { +enum Values : int { + A, + B, + X, + Y, + LStick, + RStick, + L, + R, + ZL, + ZR, + Plus, + Minus, + + DLeft, + DUp, + DRight, + DDown, + + SL, + SR, + + Home, + Screenshot, + + NumButtons, +}; + +constexpr int BUTTON_HID_BEGIN = A; +constexpr int BUTTON_NS_BEGIN = Home; + +constexpr int BUTTON_HID_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_NS = BUTTON_NS_END - BUTTON_NS_BEGIN; + +extern const std::array<const char*, NumButtons> mapping; + +} // namespace NativeButton + +namespace NativeAnalog { +enum Values : int { + LStick, + RStick, + + NumAnalogs, +}; + +constexpr int STICK_HID_BEGIN = LStick; +constexpr int STICK_HID_END = NumAnalogs; +constexpr int NUM_STICKS_HID = NumAnalogs; + +extern const std::array<const char*, NumAnalogs> mapping; +} // namespace NativeAnalog + +namespace NativeVibration { +enum Values : int { + LeftVibrationDevice, + RightVibrationDevice, + + NumVibrations, +}; + +constexpr int VIBRATION_HID_BEGIN = LeftVibrationDevice; +constexpr int VIBRATION_HID_END = NumVibrations; +constexpr int NUM_VIBRATIONS_HID = NumVibrations; + +extern const std::array<const char*, NumVibrations> mapping; +}; // namespace NativeVibration + +namespace NativeMotion { +enum Values : int { + MotionLeft, + MotionRight, + + NumMotions, +}; + +constexpr int MOTION_HID_BEGIN = MotionLeft; +constexpr int MOTION_HID_END = NumMotions; +constexpr int NUM_MOTIONS_HID = NumMotions; + +extern const std::array<const char*, NumMotions> mapping; +} // namespace NativeMotion + +namespace NativeMouseButton { +enum Values { + Left, + Right, + Middle, + Forward, + Back, + + NumMouseButtons, +}; + +constexpr int MOUSE_HID_BEGIN = Left; +constexpr int MOUSE_HID_END = NumMouseButtons; +constexpr int NUM_MOUSE_HID = NumMouseButtons; + +extern const std::array<const char*, NumMouseButtons> mapping; +} // namespace NativeMouseButton + +namespace NativeKeyboard { +enum Keys { + None, + Error, + + A = 4, + B, + C, + D, + E, + F, + G, + H, + I, + J, + K, + L, + M, + N, + O, + P, + Q, + R, + S, + T, + U, + V, + W, + X, + Y, + Z, + N1, + N2, + N3, + N4, + N5, + N6, + N7, + N8, + N9, + N0, + Enter, + Escape, + Backspace, + Tab, + Space, + Minus, + Equal, + LeftBrace, + RightBrace, + Backslash, + Tilde, + Semicolon, + Apostrophe, + Grave, + Comma, + Dot, + Slash, + CapsLockKey, + + F1, + F2, + F3, + F4, + F5, + F6, + F7, + F8, + F9, + F10, + F11, + F12, + + SystemRequest, + ScrollLockKey, + Pause, + Insert, + Home, + PageUp, + Delete, + End, + PageDown, + Right, + Left, + Down, + Up, + + NumLockKey, + KPSlash, + KPAsterisk, + KPMinus, + KPPlus, + KPEnter, + KP1, + KP2, + KP3, + KP4, + KP5, + KP6, + KP7, + KP8, + KP9, + KP0, + KPDot, + + Key102, + Compose, + Power, + KPEqual, + + F13, + F14, + F15, + F16, + F17, + F18, + F19, + F20, + F21, + F22, + F23, + F24, + + Open, + Help, + Properties, + Front, + Stop, + Repeat, + Undo, + Cut, + Copy, + Paste, + Find, + Mute, + VolumeUp, + VolumeDown, + CapsLockActive, + NumLockActive, + ScrollLockActive, + KPComma, + + KPLeftParenthesis, + KPRightParenthesis, + + LeftControlKey = 0xE0, + LeftShiftKey, + LeftAltKey, + LeftMetaKey, + RightControlKey, + RightShiftKey, + RightAltKey, + RightMetaKey, + + MediaPlayPause, + MediaStopCD, + MediaPrevious, + MediaNext, + MediaEject, + MediaVolumeUp, + MediaVolumeDown, + MediaMute, + MediaWebsite, + MediaBack, + MediaForward, + MediaStop, + MediaFind, + MediaScrollUp, + MediaScrollDown, + MediaEdit, + MediaSleep, + MediaCoffee, + MediaRefresh, + MediaCalculator, + + NumKeyboardKeys, +}; + +static_assert(NumKeyboardKeys == 0xFC, "Incorrect number of keyboard keys."); + +enum Modifiers { + LeftControl, + LeftShift, + LeftAlt, + LeftMeta, + RightControl, + RightShift, + RightAlt, + RightMeta, + CapsLock, + ScrollLock, + NumLock, + + NumKeyboardMods, +}; + +constexpr int KEYBOARD_KEYS_HID_BEGIN = None; +constexpr int KEYBOARD_KEYS_HID_END = NumKeyboardKeys; +constexpr int NUM_KEYBOARD_KEYS_HID = NumKeyboardKeys; + +constexpr int KEYBOARD_MODS_HID_BEGIN = LeftControl; +constexpr int KEYBOARD_MODS_HID_END = NumKeyboardMods; +constexpr int NUM_KEYBOARD_MODS_HID = NumKeyboardMods; + +} // namespace NativeKeyboard + +using AnalogsRaw = std::array<std::string, NativeAnalog::NumAnalogs>; +using ButtonsRaw = std::array<std::string, NativeButton::NumButtons>; +using MotionsRaw = std::array<std::string, NativeMotion::NumMotions>; +using VibrationsRaw = std::array<std::string, NativeVibration::NumVibrations>; + +using MouseButtonsRaw = std::array<std::string, NativeMouseButton::NumMouseButtons>; +using KeyboardKeysRaw = std::array<std::string, NativeKeyboard::NumKeyboardKeys>; +using KeyboardModsRaw = std::array<std::string, NativeKeyboard::NumKeyboardMods>; + +constexpr u32 JOYCON_BODY_NEON_RED = 0xFF3C28; +constexpr u32 JOYCON_BUTTONS_NEON_RED = 0x1E0A0A; +constexpr u32 JOYCON_BODY_NEON_BLUE = 0x0AB9E6; +constexpr u32 JOYCON_BUTTONS_NEON_BLUE = 0x001E1E; + +enum class ControllerType { + ProController, + DualJoyconDetached, + LeftJoycon, + RightJoycon, + Handheld, + GameCube, +}; + +struct PlayerInput { + bool connected; + ControllerType controller_type; + ButtonsRaw buttons; + AnalogsRaw analogs; + VibrationsRaw vibrations; + MotionsRaw motions; + + bool vibration_enabled; + int vibration_strength; + + u32 body_color_left; + u32 body_color_right; + u32 button_color_left; + u32 button_color_right; +}; + +struct TouchscreenInput { + bool enabled; + std::string device; + + u32 finger; + u32 diameter_x; + u32 diameter_y; + u32 rotation_angle; +}; +} // namespace Settings diff --git a/src/common/threadsafe_queue.h b/src/common/threadsafe_queue.h index a4647314a..ad04df8ca 100644 --- a/src/common/threadsafe_queue.h +++ b/src/common/threadsafe_queue.h @@ -83,11 +83,15 @@ public: return true; } - T PopWait() { + void Wait() { if (Empty()) { std::unique_lock lock{cv_mutex}; cv.wait(lock, [this]() { return !Empty(); }); } + } + + T PopWait() { + Wait(); T t; Pop(t); return t; @@ -156,6 +160,10 @@ public: return spsc_queue.Pop(t); } + void Wait() { + spsc_queue.Wait(); + } + T PopWait() { return spsc_queue.PopWait(); } |