diff options
Diffstat (limited to 'src/common')
-rw-r--r-- | src/common/CMakeLists.txt | 11 | ||||
-rw-r--r-- | src/common/alignment.h | 37 | ||||
-rw-r--r-- | src/common/bounded_threadsafe_queue.h | 4 | ||||
-rw-r--r-- | src/common/fs/fs.cpp | 15 | ||||
-rw-r--r-- | src/common/fs/path_util.cpp | 6 | ||||
-rw-r--r-- | src/common/logging/filter.cpp | 2 | ||||
-rw-r--r-- | src/common/logging/types.h | 2 | ||||
-rw-r--r-- | src/common/lz4_compression.cpp | 6 | ||||
-rw-r--r-- | src/common/lz4_compression.h | 2 | ||||
-rw-r--r-- | src/common/polyfill_thread.h | 20 | ||||
-rw-r--r-- | src/common/settings.cpp | 17 | ||||
-rw-r--r-- | src/common/settings.h | 13 | ||||
-rw-r--r-- | src/common/settings_common.cpp | 3 | ||||
-rw-r--r-- | src/common/settings_common.h | 13 | ||||
-rw-r--r-- | src/common/settings_enums.h | 18 | ||||
-rw-r--r-- | src/common/settings_setting.h | 43 | ||||
-rw-r--r-- | src/common/swap.h | 5 |
17 files changed, 163 insertions, 54 deletions
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index bf97d9ba2..416203c59 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -26,12 +26,11 @@ add_library(common STATIC assert.h atomic_helpers.h atomic_ops.h - detached_tasks.cpp - detached_tasks.h bit_cast.h bit_field.h bit_set.h bit_util.h + bounded_threadsafe_queue.h cityhash.cpp cityhash.h common_funcs.h @@ -41,6 +40,8 @@ add_library(common STATIC container_hash.h demangle.cpp demangle.h + detached_tasks.cpp + detached_tasks.h div_ceil.h dynamic_library.cpp dynamic_library.h @@ -151,6 +152,10 @@ add_library(common STATIC zstd_compression.h ) +if (YUZU_ENABLE_PORTABLE) + add_compile_definitions(YUZU_ENABLE_PORTABLE) +endif() + if (WIN32) target_sources(common PRIVATE windows/timer_resolution.cpp @@ -191,8 +196,6 @@ if (MSVC) _SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING ) target_compile_options(common PRIVATE - /W4 - /we4242 # 'identifier': conversion from 'type1' to 'type2', possible loss of data /we4254 # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data /we4800 # Implicit conversion from 'type' to bool. Possible information loss diff --git a/src/common/alignment.h b/src/common/alignment.h index fa715d497..fc5c26898 100644 --- a/src/common/alignment.h +++ b/src/common/alignment.h @@ -3,6 +3,7 @@ #pragma once +#include <bit> #include <cstddef> #include <new> #include <type_traits> @@ -10,8 +11,10 @@ namespace Common { template <typename T> - requires std::is_unsigned_v<T> -[[nodiscard]] constexpr T AlignUp(T value, size_t size) { + requires std::is_integral_v<T> +[[nodiscard]] constexpr T AlignUp(T value_, size_t size) { + using U = typename std::make_unsigned_t<T>; + auto value{static_cast<U>(value_)}; auto mod{static_cast<T>(value % size)}; value -= mod; return static_cast<T>(mod == T{0} ? value : value + size); @@ -24,8 +27,10 @@ template <typename T> } template <typename T> - requires std::is_unsigned_v<T> -[[nodiscard]] constexpr T AlignDown(T value, size_t size) { + requires std::is_integral_v<T> +[[nodiscard]] constexpr T AlignDown(T value_, size_t size) { + using U = typename std::make_unsigned_t<T>; + const auto value{static_cast<U>(value_)}; return static_cast<T>(value - value % size); } @@ -55,6 +60,30 @@ template <typename T, typename U> return (x + (y - 1)) / y; } +template <typename T> + requires std::is_integral_v<T> +[[nodiscard]] constexpr T LeastSignificantOneBit(T x) { + return x & ~(x - 1); +} + +template <typename T> + requires std::is_integral_v<T> +[[nodiscard]] constexpr T ResetLeastSignificantOneBit(T x) { + return x & (x - 1); +} + +template <typename T> + requires std::is_integral_v<T> +[[nodiscard]] constexpr bool IsPowerOfTwo(T x) { + return x > 0 && ResetLeastSignificantOneBit(x) == 0; +} + +template <typename T> + requires std::is_integral_v<T> +[[nodiscard]] constexpr T FloorPowerOfTwo(T x) { + return T{1} << (sizeof(T) * 8 - std::countl_zero(x) - 1); +} + template <typename T, size_t Align = 16> class AlignmentAllocator { public: diff --git a/src/common/bounded_threadsafe_queue.h b/src/common/bounded_threadsafe_queue.h index bd87aa09b..b36fc1de9 100644 --- a/src/common/bounded_threadsafe_queue.h +++ b/src/common/bounded_threadsafe_queue.h @@ -45,13 +45,13 @@ public: } T PopWait() { - T t; + T t{}; Pop<PopMode::Wait>(t); return t; } T PopWait(std::stop_token stop_token) { - T t; + T t{}; Pop<PopMode::WaitWithStopToken>(t, stop_token); return t; } diff --git a/src/common/fs/fs.cpp b/src/common/fs/fs.cpp index 36e67c145..174aed49b 100644 --- a/src/common/fs/fs.cpp +++ b/src/common/fs/fs.cpp @@ -528,38 +528,41 @@ void IterateDirEntriesRecursively(const std::filesystem::path& path, // Generic Filesystem Operations bool Exists(const fs::path& path) { + std::error_code ec; #ifdef ANDROID if (Android::IsContentUri(path)) { return Android::Exists(path); } else { - return fs::exists(path); + return fs::exists(path, ec); } #else - return fs::exists(path); + return fs::exists(path, ec); #endif } bool IsFile(const fs::path& path) { + std::error_code ec; #ifdef ANDROID if (Android::IsContentUri(path)) { return !Android::IsDirectory(path); } else { - return fs::is_regular_file(path); + return fs::is_regular_file(path, ec); } #else - return fs::is_regular_file(path); + return fs::is_regular_file(path, ec); #endif } bool IsDir(const fs::path& path) { + std::error_code ec; #ifdef ANDROID if (Android::IsContentUri(path)) { return Android::IsDirectory(path); } else { - return fs::is_directory(path); + return fs::is_directory(path, ec); } #else - return fs::is_directory(path); + return fs::is_directory(path, ec); #endif } diff --git a/src/common/fs/path_util.cpp b/src/common/fs/path_util.cpp index d71cfacc6..dce219fcf 100644 --- a/src/common/fs/path_util.cpp +++ b/src/common/fs/path_util.cpp @@ -88,8 +88,9 @@ public: fs::path yuzu_path_config; #ifdef _WIN32 +#ifdef YUZU_ENABLE_PORTABLE yuzu_path = GetExeDirectory() / PORTABLE_DIR; - +#endif if (!IsDir(yuzu_path)) { yuzu_path = GetAppDataRoamingDirectory() / YUZU_DIR; } @@ -101,8 +102,9 @@ public: yuzu_path_cache = yuzu_path / CACHE_DIR; yuzu_path_config = yuzu_path / CONFIG_DIR; #else +#ifdef YUZU_ENABLE_PORTABLE yuzu_path = GetCurrentDir() / PORTABLE_DIR; - +#endif if (Exists(yuzu_path) && IsDir(yuzu_path)) { yuzu_path_cache = yuzu_path / CACHE_DIR; yuzu_path_config = yuzu_path / CONFIG_DIR; diff --git a/src/common/logging/filter.cpp b/src/common/logging/filter.cpp index c95909561..4e3a614a4 100644 --- a/src/common/logging/filter.cpp +++ b/src/common/logging/filter.cpp @@ -112,7 +112,7 @@ bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) { SUB(Service, NCM) \ SUB(Service, NFC) \ SUB(Service, NFP) \ - SUB(Service, NGCT) \ + SUB(Service, NGC) \ SUB(Service, NIFM) \ SUB(Service, NIM) \ SUB(Service, NOTIF) \ diff --git a/src/common/logging/types.h b/src/common/logging/types.h index 8356e3183..08af50ee0 100644 --- a/src/common/logging/types.h +++ b/src/common/logging/types.h @@ -80,7 +80,7 @@ enum class Class : u8 { Service_NCM, ///< The NCM service Service_NFC, ///< The NFC (Near-field communication) service Service_NFP, ///< The NFP service - Service_NGCT, ///< The NGCT (No Good Content for Terra) service + Service_NGC, ///< The NGC (No Good Content) service Service_NIFM, ///< The NIFM (Network interface) service Service_NIM, ///< The NIM service Service_NOTIF, ///< The NOTIF (Notification) service diff --git a/src/common/lz4_compression.cpp b/src/common/lz4_compression.cpp index ffb32fecf..d85ab1742 100644 --- a/src/common/lz4_compression.cpp +++ b/src/common/lz4_compression.cpp @@ -71,4 +71,10 @@ std::vector<u8> DecompressDataLZ4(std::span<const u8> compressed, std::size_t un return uncompressed; } +int DecompressDataLZ4(void* dst, size_t dst_size, const void* src, size_t src_size) { + // This is just a thin wrapper around LZ4. + return LZ4_decompress_safe(reinterpret_cast<const char*>(src), reinterpret_cast<char*>(dst), + static_cast<int>(src_size), static_cast<int>(dst_size)); +} + } // namespace Common::Compression diff --git a/src/common/lz4_compression.h b/src/common/lz4_compression.h index 7fd53a960..3ae17c2bb 100644 --- a/src/common/lz4_compression.h +++ b/src/common/lz4_compression.h @@ -56,4 +56,6 @@ namespace Common::Compression { [[nodiscard]] std::vector<u8> DecompressDataLZ4(std::span<const u8> compressed, std::size_t uncompressed_size); +[[nodiscard]] int DecompressDataLZ4(void* dst, size_t dst_size, const void* src, size_t src_size); + } // namespace Common::Compression diff --git a/src/common/polyfill_thread.h b/src/common/polyfill_thread.h index b5ef055db..41cbb9ed5 100644 --- a/src/common/polyfill_thread.h +++ b/src/common/polyfill_thread.h @@ -19,8 +19,8 @@ namespace Common { template <typename Condvar, typename Lock, typename Pred> -void CondvarWait(Condvar& cv, Lock& lock, std::stop_token token, Pred&& pred) { - cv.wait(lock, token, std::move(pred)); +void CondvarWait(Condvar& cv, std::unique_lock<Lock>& lk, std::stop_token token, Pred&& pred) { + cv.wait(lk, token, std::move(pred)); } template <typename Rep, typename Period> @@ -332,13 +332,17 @@ private: namespace Common { template <typename Condvar, typename Lock, typename Pred> -void CondvarWait(Condvar& cv, Lock& lock, std::stop_token token, Pred pred) { +void CondvarWait(Condvar& cv, std::unique_lock<Lock>& lk, std::stop_token token, Pred pred) { if (token.stop_requested()) { return; } - std::stop_callback callback(token, [&] { cv.notify_all(); }); - cv.wait(lock, [&] { return pred() || token.stop_requested(); }); + std::stop_callback callback(token, [&] { + { std::scoped_lock lk2{*lk.mutex()}; } + cv.notify_all(); + }); + + cv.wait(lk, [&] { return pred() || token.stop_requested(); }); } template <typename Rep, typename Period> @@ -353,8 +357,10 @@ bool StoppableTimedWait(std::stop_token token, const std::chrono::duration<Rep, std::stop_callback cb(token, [&] { // Wake up the waiting thread. - std::unique_lock lk{m}; - stop_requested = true; + { + std::scoped_lock lk{m}; + stop_requested = true; + } cv.notify_one(); }); diff --git a/src/common/settings.cpp b/src/common/settings.cpp index 15fd2e222..4ecaf550b 100644 --- a/src/common/settings.cpp +++ b/src/common/settings.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include <version> +#include "common/settings_enums.h" #if __cpp_lib_chrono >= 201907L #include <chrono> #include <exception> @@ -145,6 +146,10 @@ bool IsFastmemEnabled() { return true; } +bool IsDockedMode() { + return values.use_docked_mode.GetValue() == Settings::ConsoleMode::Docked; +} + float Volume() { if (values.audio_muted) { return 0.0f; @@ -154,6 +159,8 @@ float Volume() { const char* TranslateCategory(Category category) { switch (category) { + case Category::Android: + return "Android"; case Category::Audio: return "Audio"; case Category::Core: @@ -207,9 +214,7 @@ const char* TranslateCategory(Category category) { return "Miscellaneous"; } -void UpdateRescalingInfo() { - const auto setup = values.resolution_setup.GetValue(); - auto& info = values.resolution_info; +void TranslateResolutionInfo(ResolutionSetup setup, ResolutionScalingInfo& info) { info.downscale = false; switch (setup) { case ResolutionSetup::Res1_2X: @@ -269,6 +274,12 @@ void UpdateRescalingInfo() { info.active = info.up_scale != 1 || info.down_shift != 0; } +void UpdateRescalingInfo() { + const auto setup = values.resolution_setup.GetValue(); + auto& info = values.resolution_info; + TranslateResolutionInfo(setup, info); +} + void RestoreGlobalState(bool is_powered_on) { // If a game is running, DO NOT restore the global settings state if (is_powered_on) { diff --git a/src/common/settings.h b/src/common/settings.h index b0bc6519a..82ec9077e 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -348,6 +348,8 @@ struct Values { Category::RendererDebug}; Setting<bool> disable_shader_loop_safety_checks{ linkage, false, "disable_shader_loop_safety_checks", Category::RendererDebug}; + Setting<bool> enable_renderdoc_hotkey{linkage, false, "renderdoc_hotkey", + Category::RendererDebug}; // System SwitchableSetting<Language, true> language_index{linkage, @@ -379,7 +381,13 @@ struct Values { Setting<s32> current_user{linkage, 0, "current_user", Category::System}; - SwitchableSetting<bool> use_docked_mode{linkage, true, "use_docked_mode", Category::System}; + SwitchableSetting<ConsoleMode> use_docked_mode{linkage, + ConsoleMode::Docked, + "use_docked_mode", + Category::System, + Specialization::Radio, + true, + true}; // Controls InputSetting<std::array<PlayerInput, 10>> players; @@ -519,12 +527,15 @@ bool IsGPULevelHigh(); bool IsFastmemEnabled(); +bool IsDockedMode(); + float Volume(); std::string GetTimeZoneString(TimeZone time_zone); void LogSettings(); +void TranslateResolutionInfo(ResolutionSetup setup, ResolutionScalingInfo& info); void UpdateRescalingInfo(); // Restore the global state of all applicable settings in the Values struct diff --git a/src/common/settings_common.cpp b/src/common/settings_common.cpp index dedf5ef90..5960b78aa 100644 --- a/src/common/settings_common.cpp +++ b/src/common/settings_common.cpp @@ -1,7 +1,9 @@ // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include <functional> #include <string> +#include <vector> #include "common/settings_common.h" namespace Settings { @@ -12,6 +14,7 @@ BasicSetting::BasicSetting(Linkage& linkage, const std::string& name, enum Categ : label{name}, category{category_}, id{linkage.count}, save{save_}, runtime_modifiable{runtime_modifiable_}, specialization{specialization_}, other_setting{other_setting_} { + linkage.by_key.insert({name, this}); linkage.by_category[category].push_back(this); linkage.count++; } diff --git a/src/common/settings_common.h b/src/common/settings_common.h index 2efb329b0..1800ab10d 100644 --- a/src/common/settings_common.h +++ b/src/common/settings_common.h @@ -12,6 +12,7 @@ namespace Settings { enum class Category : u32 { + Android, Audio, Core, Cpu, @@ -56,6 +57,7 @@ enum Specialization : u8 { Scalar = 5, // Values are continuous Countable = 6, // Can be stepped through Paired = 7, // Another setting is associated with this setting + Radio = 8, // Setting should be presented in a radio group Percentage = (1 << SpecializationAttributeOffset), // Should be represented as a percentage }; @@ -67,6 +69,7 @@ public: explicit Linkage(u32 initial_count = 0); ~Linkage(); std::map<Category, std::vector<BasicSetting*>> by_category{}; + std::map<std::string, Settings::BasicSetting*> by_key{}; std::vector<std::function<void()>> restore_functions{}; u32 count; }; @@ -222,6 +225,16 @@ public: */ [[nodiscard]] virtual constexpr u32 EnumIndex() const = 0; + /** + * @returns True if the underlying type is a floating point storage + */ + [[nodiscard]] virtual constexpr bool IsFloatingPoint() const = 0; + + /** + * @returns True if the underlying type is an integer storage + */ + [[nodiscard]] virtual constexpr bool IsIntegral() const = 0; + /* * Switchable settings */ diff --git a/src/common/settings_enums.h b/src/common/settings_enums.h index a1a29ebf6..815cafe15 100644 --- a/src/common/settings_enums.h +++ b/src/common/settings_enums.h @@ -12,8 +12,8 @@ namespace Settings { template <typename T> struct EnumMetadata { - static constexpr std::vector<std::pair<std::string, T>> Canonicalizations(); - static constexpr u32 Index(); + static std::vector<std::pair<std::string, T>> Canonicalizations(); + static u32 Index(); }; #define PAIR_45(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_46(N, __VA_ARGS__)) @@ -66,11 +66,11 @@ struct EnumMetadata { #define ENUM(NAME, ...) \ enum class NAME : u32 { __VA_ARGS__ }; \ template <> \ - constexpr std::vector<std::pair<std::string, NAME>> EnumMetadata<NAME>::Canonicalizations() { \ + inline std::vector<std::pair<std::string, NAME>> EnumMetadata<NAME>::Canonicalizations() { \ return {PAIR(NAME, __VA_ARGS__)}; \ } \ template <> \ - constexpr u32 EnumMetadata<NAME>::Index() { \ + inline u32 EnumMetadata<NAME>::Index() { \ return __COUNTER__; \ } @@ -85,7 +85,7 @@ enum class AudioEngine : u32 { }; template <> -constexpr std::vector<std::pair<std::string, AudioEngine>> +inline std::vector<std::pair<std::string, AudioEngine>> EnumMetadata<AudioEngine>::Canonicalizations() { return { {"auto", AudioEngine::Auto}, @@ -96,7 +96,7 @@ EnumMetadata<AudioEngine>::Canonicalizations() { } template <> -constexpr u32 EnumMetadata<AudioEngine>::Index() { +inline u32 EnumMetadata<AudioEngine>::Index() { // This is just a sufficiently large number that is more than the number of other enums declared // here return 100; @@ -146,8 +146,10 @@ ENUM(AntiAliasing, None, Fxaa, Smaa, MaxEnum); ENUM(AspectRatio, R16_9, R4_3, R21_9, R16_10, Stretch); +ENUM(ConsoleMode, Handheld, Docked); + template <typename Type> -constexpr std::string CanonicalizeEnum(Type id) { +inline std::string CanonicalizeEnum(Type id) { const auto group = EnumMetadata<Type>::Canonicalizations(); for (auto& [name, value] : group) { if (value == id) { @@ -158,7 +160,7 @@ constexpr std::string CanonicalizeEnum(Type id) { } template <typename Type> -constexpr Type ToEnum(const std::string& canonicalization) { +inline Type ToEnum(const std::string& canonicalization) { const auto group = EnumMetadata<Type>::Canonicalizations(); for (auto& [name, value] : group) { if (name == canonicalization) { diff --git a/src/common/settings_setting.h b/src/common/settings_setting.h index a8beb06e9..7be6f26f7 100644 --- a/src/common/settings_setting.h +++ b/src/common/settings_setting.h @@ -10,6 +10,7 @@ #include <string> #include <typeindex> #include <typeinfo> +#include <fmt/core.h> #include "common/common_types.h" #include "common/settings_common.h" #include "common/settings_enums.h" @@ -115,8 +116,12 @@ protected: } else if constexpr (std::is_same_v<Type, AudioEngine>) { // Compatibility with old AudioEngine setting being a string return CanonicalizeEnum(value_); + } else if constexpr (std::is_floating_point_v<Type>) { + return fmt::format("{:f}", value_); + } else if constexpr (std::is_enum_v<Type>) { + return std::to_string(static_cast<u32>(value_)); } else { - return std::to_string(static_cast<u64>(value_)); + return std::to_string(value_); } } @@ -180,17 +185,19 @@ public: this->SetValue(static_cast<u32>(std::stoul(input))); } else if constexpr (std::is_same_v<Type, bool>) { this->SetValue(input == "true"); - } else if constexpr (std::is_same_v<Type, AudioEngine>) { - this->SetValue(ToEnum<Type>(input)); + } else if constexpr (std::is_same_v<Type, float>) { + this->SetValue(std::stof(input)); } else { this->SetValue(static_cast<Type>(std::stoll(input))); } } catch (std::invalid_argument&) { this->SetValue(this->GetDefault()); + } catch (std::out_of_range&) { + this->SetValue(this->GetDefault()); } } - [[nodiscard]] std::string constexpr Canonicalize() const override final { + [[nodiscard]] std::string Canonicalize() const override final { if constexpr (std::is_enum_v<Type>) { return CanonicalizeEnum(this->GetValue()); } else { @@ -215,11 +222,27 @@ public: } } + [[nodiscard]] constexpr bool IsFloatingPoint() const final { + return std::is_floating_point_v<Type>; + } + + [[nodiscard]] constexpr bool IsIntegral() const final { + return std::is_integral_v<Type>; + } + [[nodiscard]] std::string MinVal() const override final { - return this->ToString(minimum); + if constexpr (std::is_arithmetic_v<Type> && !ranged) { + return this->ToString(std::numeric_limits<Type>::min()); + } else { + return this->ToString(minimum); + } } [[nodiscard]] std::string MaxVal() const override final { - return this->ToString(maximum); + if constexpr (std::is_arithmetic_v<Type> && !ranged) { + return this->ToString(std::numeric_limits<Type>::max()); + } else { + return this->ToString(maximum); + } } [[nodiscard]] constexpr bool Ranged() const override { @@ -256,11 +279,11 @@ public: * @param runtime_modifiable_ Suggests whether this is modifiable while a guest is loaded * @param other_setting_ A second Setting to associate to this one in metadata */ + template <typename T = BasicSetting> explicit SwitchableSetting(Linkage& linkage, const Type& default_val, const std::string& name, Category category_, u32 specialization_ = Specialization::Default, bool save_ = true, bool runtime_modifiable_ = false, - BasicSetting* other_setting_ = nullptr) - requires(!ranged) + typename std::enable_if<!ranged, T*>::type other_setting_ = nullptr) : Setting<Type, false>{ linkage, default_val, name, category_, specialization_, save_, runtime_modifiable_, other_setting_} { @@ -282,12 +305,12 @@ public: * @param runtime_modifiable_ Suggests whether this is modifiable while a guest is loaded * @param other_setting_ A second Setting to associate to this one in metadata */ + template <typename T = BasicSetting> explicit SwitchableSetting(Linkage& linkage, const Type& default_val, const Type& min_val, const Type& max_val, const std::string& name, Category category_, u32 specialization_ = Specialization::Default, bool save_ = true, bool runtime_modifiable_ = false, - BasicSetting* other_setting_ = nullptr) - requires(ranged) + typename std::enable_if<ranged, T*>::type other_setting_ = nullptr) : Setting<Type, true>{linkage, default_val, min_val, max_val, name, category_, specialization_, save_, runtime_modifiable_, diff --git a/src/common/swap.h b/src/common/swap.h index 085baaf9a..fde343e45 100644 --- a/src/common/swap.h +++ b/src/common/swap.h @@ -460,11 +460,6 @@ S operator&(const S& i, const swap_struct_t<T, F> v) { return i & v.swap(); } -template <typename S, typename T, typename F> -S operator&(const swap_struct_t<T, F> v, const S& i) { - return static_cast<S>(v.swap() & i); -} - // Comparison template <typename S, typename T, typename F> bool operator<(const S& p, const swap_struct_t<T, F> v) { |