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 | |||
| 26 | assert.h | 26 | assert.h |
| 27 | atomic_helpers.h | 27 | atomic_helpers.h |
| 28 | atomic_ops.h | 28 | atomic_ops.h |
| 29 | detached_tasks.cpp | ||
| 30 | detached_tasks.h | ||
| 31 | bit_cast.h | 29 | bit_cast.h |
| 32 | bit_field.h | 30 | bit_field.h |
| 33 | bit_set.h | 31 | bit_set.h |
| 34 | bit_util.h | 32 | bit_util.h |
| 33 | bounded_threadsafe_queue.h | ||
| 35 | cityhash.cpp | 34 | cityhash.cpp |
| 36 | cityhash.h | 35 | cityhash.h |
| 37 | common_funcs.h | 36 | common_funcs.h |
| @@ -41,6 +40,8 @@ add_library(common STATIC | |||
| 41 | container_hash.h | 40 | container_hash.h |
| 42 | demangle.cpp | 41 | demangle.cpp |
| 43 | demangle.h | 42 | demangle.h |
| 43 | detached_tasks.cpp | ||
| 44 | detached_tasks.h | ||
| 44 | div_ceil.h | 45 | div_ceil.h |
| 45 | dynamic_library.cpp | 46 | dynamic_library.cpp |
| 46 | dynamic_library.h | 47 | dynamic_library.h |
| @@ -151,6 +152,10 @@ add_library(common STATIC | |||
| 151 | zstd_compression.h | 152 | zstd_compression.h |
| 152 | ) | 153 | ) |
| 153 | 154 | ||
| 155 | if (YUZU_ENABLE_PORTABLE) | ||
| 156 | add_compile_definitions(YUZU_ENABLE_PORTABLE) | ||
| 157 | endif() | ||
| 158 | |||
| 154 | if (WIN32) | 159 | if (WIN32) |
| 155 | target_sources(common PRIVATE | 160 | target_sources(common PRIVATE |
| 156 | windows/timer_resolution.cpp | 161 | windows/timer_resolution.cpp |
| @@ -191,8 +196,6 @@ if (MSVC) | |||
| 191 | _SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING | 196 | _SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING |
| 192 | ) | 197 | ) |
| 193 | target_compile_options(common PRIVATE | 198 | target_compile_options(common PRIVATE |
| 194 | /W4 | ||
| 195 | |||
| 196 | /we4242 # 'identifier': conversion from 'type1' to 'type2', possible loss of data | 199 | /we4242 # 'identifier': conversion from 'type1' to 'type2', possible loss of data |
| 197 | /we4254 # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data | 200 | /we4254 # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data |
| 198 | /we4800 # Implicit conversion from 'type' to bool. Possible information loss | 201 | /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 @@ | |||
| 3 | 3 | ||
| 4 | #pragma once | 4 | #pragma once |
| 5 | 5 | ||
| 6 | #include <bit> | ||
| 6 | #include <cstddef> | 7 | #include <cstddef> |
| 7 | #include <new> | 8 | #include <new> |
| 8 | #include <type_traits> | 9 | #include <type_traits> |
| @@ -10,8 +11,10 @@ | |||
| 10 | namespace Common { | 11 | namespace Common { |
| 11 | 12 | ||
| 12 | template <typename T> | 13 | template <typename T> |
| 13 | requires std::is_unsigned_v<T> | 14 | requires std::is_integral_v<T> |
| 14 | [[nodiscard]] constexpr T AlignUp(T value, size_t size) { | 15 | [[nodiscard]] constexpr T AlignUp(T value_, size_t size) { |
| 16 | using U = typename std::make_unsigned_t<T>; | ||
| 17 | auto value{static_cast<U>(value_)}; | ||
| 15 | auto mod{static_cast<T>(value % size)}; | 18 | auto mod{static_cast<T>(value % size)}; |
| 16 | value -= mod; | 19 | value -= mod; |
| 17 | return static_cast<T>(mod == T{0} ? value : value + size); | 20 | return static_cast<T>(mod == T{0} ? value : value + size); |
| @@ -24,8 +27,10 @@ template <typename T> | |||
| 24 | } | 27 | } |
| 25 | 28 | ||
| 26 | template <typename T> | 29 | template <typename T> |
| 27 | requires std::is_unsigned_v<T> | 30 | requires std::is_integral_v<T> |
| 28 | [[nodiscard]] constexpr T AlignDown(T value, size_t size) { | 31 | [[nodiscard]] constexpr T AlignDown(T value_, size_t size) { |
| 32 | using U = typename std::make_unsigned_t<T>; | ||
| 33 | const auto value{static_cast<U>(value_)}; | ||
| 29 | return static_cast<T>(value - value % size); | 34 | return static_cast<T>(value - value % size); |
| 30 | } | 35 | } |
| 31 | 36 | ||
| @@ -55,6 +60,30 @@ template <typename T, typename U> | |||
| 55 | return (x + (y - 1)) / y; | 60 | return (x + (y - 1)) / y; |
| 56 | } | 61 | } |
| 57 | 62 | ||
| 63 | template <typename T> | ||
| 64 | requires std::is_integral_v<T> | ||
| 65 | [[nodiscard]] constexpr T LeastSignificantOneBit(T x) { | ||
| 66 | return x & ~(x - 1); | ||
| 67 | } | ||
| 68 | |||
| 69 | template <typename T> | ||
| 70 | requires std::is_integral_v<T> | ||
| 71 | [[nodiscard]] constexpr T ResetLeastSignificantOneBit(T x) { | ||
| 72 | return x & (x - 1); | ||
| 73 | } | ||
| 74 | |||
| 75 | template <typename T> | ||
| 76 | requires std::is_integral_v<T> | ||
| 77 | [[nodiscard]] constexpr bool IsPowerOfTwo(T x) { | ||
| 78 | return x > 0 && ResetLeastSignificantOneBit(x) == 0; | ||
| 79 | } | ||
| 80 | |||
| 81 | template <typename T> | ||
| 82 | requires std::is_integral_v<T> | ||
| 83 | [[nodiscard]] constexpr T FloorPowerOfTwo(T x) { | ||
| 84 | return T{1} << (sizeof(T) * 8 - std::countl_zero(x) - 1); | ||
| 85 | } | ||
| 86 | |||
| 58 | template <typename T, size_t Align = 16> | 87 | template <typename T, size_t Align = 16> |
| 59 | class AlignmentAllocator { | 88 | class AlignmentAllocator { |
| 60 | public: | 89 | 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: | |||
| 45 | } | 45 | } |
| 46 | 46 | ||
| 47 | T PopWait() { | 47 | T PopWait() { |
| 48 | T t; | 48 | T t{}; |
| 49 | Pop<PopMode::Wait>(t); | 49 | Pop<PopMode::Wait>(t); |
| 50 | return t; | 50 | return t; |
| 51 | } | 51 | } |
| 52 | 52 | ||
| 53 | T PopWait(std::stop_token stop_token) { | 53 | T PopWait(std::stop_token stop_token) { |
| 54 | T t; | 54 | T t{}; |
| 55 | Pop<PopMode::WaitWithStopToken>(t, stop_token); | 55 | Pop<PopMode::WaitWithStopToken>(t, stop_token); |
| 56 | return t; | 56 | return t; |
| 57 | } | 57 | } |
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, | |||
| 528 | // Generic Filesystem Operations | 528 | // Generic Filesystem Operations |
| 529 | 529 | ||
| 530 | bool Exists(const fs::path& path) { | 530 | bool Exists(const fs::path& path) { |
| 531 | std::error_code ec; | ||
| 531 | #ifdef ANDROID | 532 | #ifdef ANDROID |
| 532 | if (Android::IsContentUri(path)) { | 533 | if (Android::IsContentUri(path)) { |
| 533 | return Android::Exists(path); | 534 | return Android::Exists(path); |
| 534 | } else { | 535 | } else { |
| 535 | return fs::exists(path); | 536 | return fs::exists(path, ec); |
| 536 | } | 537 | } |
| 537 | #else | 538 | #else |
| 538 | return fs::exists(path); | 539 | return fs::exists(path, ec); |
| 539 | #endif | 540 | #endif |
| 540 | } | 541 | } |
| 541 | 542 | ||
| 542 | bool IsFile(const fs::path& path) { | 543 | bool IsFile(const fs::path& path) { |
| 544 | std::error_code ec; | ||
| 543 | #ifdef ANDROID | 545 | #ifdef ANDROID |
| 544 | if (Android::IsContentUri(path)) { | 546 | if (Android::IsContentUri(path)) { |
| 545 | return !Android::IsDirectory(path); | 547 | return !Android::IsDirectory(path); |
| 546 | } else { | 548 | } else { |
| 547 | return fs::is_regular_file(path); | 549 | return fs::is_regular_file(path, ec); |
| 548 | } | 550 | } |
| 549 | #else | 551 | #else |
| 550 | return fs::is_regular_file(path); | 552 | return fs::is_regular_file(path, ec); |
| 551 | #endif | 553 | #endif |
| 552 | } | 554 | } |
| 553 | 555 | ||
| 554 | bool IsDir(const fs::path& path) { | 556 | bool IsDir(const fs::path& path) { |
| 557 | std::error_code ec; | ||
| 555 | #ifdef ANDROID | 558 | #ifdef ANDROID |
| 556 | if (Android::IsContentUri(path)) { | 559 | if (Android::IsContentUri(path)) { |
| 557 | return Android::IsDirectory(path); | 560 | return Android::IsDirectory(path); |
| 558 | } else { | 561 | } else { |
| 559 | return fs::is_directory(path); | 562 | return fs::is_directory(path, ec); |
| 560 | } | 563 | } |
| 561 | #else | 564 | #else |
| 562 | return fs::is_directory(path); | 565 | return fs::is_directory(path, ec); |
| 563 | #endif | 566 | #endif |
| 564 | } | 567 | } |
| 565 | 568 | ||
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: | |||
| 88 | fs::path yuzu_path_config; | 88 | fs::path yuzu_path_config; |
| 89 | 89 | ||
| 90 | #ifdef _WIN32 | 90 | #ifdef _WIN32 |
| 91 | #ifdef YUZU_ENABLE_PORTABLE | ||
| 91 | yuzu_path = GetExeDirectory() / PORTABLE_DIR; | 92 | yuzu_path = GetExeDirectory() / PORTABLE_DIR; |
| 92 | 93 | #endif | |
| 93 | if (!IsDir(yuzu_path)) { | 94 | if (!IsDir(yuzu_path)) { |
| 94 | yuzu_path = GetAppDataRoamingDirectory() / YUZU_DIR; | 95 | yuzu_path = GetAppDataRoamingDirectory() / YUZU_DIR; |
| 95 | } | 96 | } |
| @@ -101,8 +102,9 @@ public: | |||
| 101 | yuzu_path_cache = yuzu_path / CACHE_DIR; | 102 | yuzu_path_cache = yuzu_path / CACHE_DIR; |
| 102 | yuzu_path_config = yuzu_path / CONFIG_DIR; | 103 | yuzu_path_config = yuzu_path / CONFIG_DIR; |
| 103 | #else | 104 | #else |
| 105 | #ifdef YUZU_ENABLE_PORTABLE | ||
| 104 | yuzu_path = GetCurrentDir() / PORTABLE_DIR; | 106 | yuzu_path = GetCurrentDir() / PORTABLE_DIR; |
| 105 | 107 | #endif | |
| 106 | if (Exists(yuzu_path) && IsDir(yuzu_path)) { | 108 | if (Exists(yuzu_path) && IsDir(yuzu_path)) { |
| 107 | yuzu_path_cache = yuzu_path / CACHE_DIR; | 109 | yuzu_path_cache = yuzu_path / CACHE_DIR; |
| 108 | yuzu_path_config = yuzu_path / CONFIG_DIR; | 110 | 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) { | |||
| 112 | SUB(Service, NCM) \ | 112 | SUB(Service, NCM) \ |
| 113 | SUB(Service, NFC) \ | 113 | SUB(Service, NFC) \ |
| 114 | SUB(Service, NFP) \ | 114 | SUB(Service, NFP) \ |
| 115 | SUB(Service, NGCT) \ | 115 | SUB(Service, NGC) \ |
| 116 | SUB(Service, NIFM) \ | 116 | SUB(Service, NIFM) \ |
| 117 | SUB(Service, NIM) \ | 117 | SUB(Service, NIM) \ |
| 118 | SUB(Service, NOTIF) \ | 118 | 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 { | |||
| 80 | Service_NCM, ///< The NCM service | 80 | Service_NCM, ///< The NCM service |
| 81 | Service_NFC, ///< The NFC (Near-field communication) service | 81 | Service_NFC, ///< The NFC (Near-field communication) service |
| 82 | Service_NFP, ///< The NFP service | 82 | Service_NFP, ///< The NFP service |
| 83 | Service_NGCT, ///< The NGCT (No Good Content for Terra) service | 83 | Service_NGC, ///< The NGC (No Good Content) service |
| 84 | Service_NIFM, ///< The NIFM (Network interface) service | 84 | Service_NIFM, ///< The NIFM (Network interface) service |
| 85 | Service_NIM, ///< The NIM service | 85 | Service_NIM, ///< The NIM service |
| 86 | Service_NOTIF, ///< The NOTIF (Notification) service | 86 | 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 | |||
| 71 | return uncompressed; | 71 | return uncompressed; |
| 72 | } | 72 | } |
| 73 | 73 | ||
| 74 | int DecompressDataLZ4(void* dst, size_t dst_size, const void* src, size_t src_size) { | ||
| 75 | // This is just a thin wrapper around LZ4. | ||
| 76 | return LZ4_decompress_safe(reinterpret_cast<const char*>(src), reinterpret_cast<char*>(dst), | ||
| 77 | static_cast<int>(src_size), static_cast<int>(dst_size)); | ||
| 78 | } | ||
| 79 | |||
| 74 | } // namespace Common::Compression | 80 | } // 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 { | |||
| 56 | [[nodiscard]] std::vector<u8> DecompressDataLZ4(std::span<const u8> compressed, | 56 | [[nodiscard]] std::vector<u8> DecompressDataLZ4(std::span<const u8> compressed, |
| 57 | std::size_t uncompressed_size); | 57 | std::size_t uncompressed_size); |
| 58 | 58 | ||
| 59 | [[nodiscard]] int DecompressDataLZ4(void* dst, size_t dst_size, const void* src, size_t src_size); | ||
| 60 | |||
| 59 | } // namespace Common::Compression | 61 | } // 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 @@ | |||
| 19 | namespace Common { | 19 | namespace Common { |
| 20 | 20 | ||
| 21 | template <typename Condvar, typename Lock, typename Pred> | 21 | template <typename Condvar, typename Lock, typename Pred> |
| 22 | void CondvarWait(Condvar& cv, Lock& lock, std::stop_token token, Pred&& pred) { | 22 | void CondvarWait(Condvar& cv, std::unique_lock<Lock>& lk, std::stop_token token, Pred&& pred) { |
| 23 | cv.wait(lock, token, std::move(pred)); | 23 | cv.wait(lk, token, std::move(pred)); |
| 24 | } | 24 | } |
| 25 | 25 | ||
| 26 | template <typename Rep, typename Period> | 26 | template <typename Rep, typename Period> |
| @@ -332,13 +332,17 @@ private: | |||
| 332 | namespace Common { | 332 | namespace Common { |
| 333 | 333 | ||
| 334 | template <typename Condvar, typename Lock, typename Pred> | 334 | template <typename Condvar, typename Lock, typename Pred> |
| 335 | void CondvarWait(Condvar& cv, Lock& lock, std::stop_token token, Pred pred) { | 335 | void CondvarWait(Condvar& cv, std::unique_lock<Lock>& lk, std::stop_token token, Pred pred) { |
| 336 | if (token.stop_requested()) { | 336 | if (token.stop_requested()) { |
| 337 | return; | 337 | return; |
| 338 | } | 338 | } |
| 339 | 339 | ||
| 340 | std::stop_callback callback(token, [&] { cv.notify_all(); }); | 340 | std::stop_callback callback(token, [&] { |
| 341 | cv.wait(lock, [&] { return pred() || token.stop_requested(); }); | 341 | { std::scoped_lock lk2{*lk.mutex()}; } |
| 342 | cv.notify_all(); | ||
| 343 | }); | ||
| 344 | |||
| 345 | cv.wait(lk, [&] { return pred() || token.stop_requested(); }); | ||
| 342 | } | 346 | } |
| 343 | 347 | ||
| 344 | template <typename Rep, typename Period> | 348 | template <typename Rep, typename Period> |
| @@ -353,8 +357,10 @@ bool StoppableTimedWait(std::stop_token token, const std::chrono::duration<Rep, | |||
| 353 | 357 | ||
| 354 | std::stop_callback cb(token, [&] { | 358 | std::stop_callback cb(token, [&] { |
| 355 | // Wake up the waiting thread. | 359 | // Wake up the waiting thread. |
| 356 | std::unique_lock lk{m}; | 360 | { |
| 357 | stop_requested = true; | 361 | std::scoped_lock lk{m}; |
| 362 | stop_requested = true; | ||
| 363 | } | ||
| 358 | cv.notify_one(); | 364 | cv.notify_one(); |
| 359 | }); | 365 | }); |
| 360 | 366 | ||
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 @@ | |||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include <version> | 4 | #include <version> |
| 5 | #include "common/settings_enums.h" | ||
| 5 | #if __cpp_lib_chrono >= 201907L | 6 | #if __cpp_lib_chrono >= 201907L |
| 6 | #include <chrono> | 7 | #include <chrono> |
| 7 | #include <exception> | 8 | #include <exception> |
| @@ -145,6 +146,10 @@ bool IsFastmemEnabled() { | |||
| 145 | return true; | 146 | return true; |
| 146 | } | 147 | } |
| 147 | 148 | ||
| 149 | bool IsDockedMode() { | ||
| 150 | return values.use_docked_mode.GetValue() == Settings::ConsoleMode::Docked; | ||
| 151 | } | ||
| 152 | |||
| 148 | float Volume() { | 153 | float Volume() { |
| 149 | if (values.audio_muted) { | 154 | if (values.audio_muted) { |
| 150 | return 0.0f; | 155 | return 0.0f; |
| @@ -154,6 +159,8 @@ float Volume() { | |||
| 154 | 159 | ||
| 155 | const char* TranslateCategory(Category category) { | 160 | const char* TranslateCategory(Category category) { |
| 156 | switch (category) { | 161 | switch (category) { |
| 162 | case Category::Android: | ||
| 163 | return "Android"; | ||
| 157 | case Category::Audio: | 164 | case Category::Audio: |
| 158 | return "Audio"; | 165 | return "Audio"; |
| 159 | case Category::Core: | 166 | case Category::Core: |
| @@ -207,9 +214,7 @@ const char* TranslateCategory(Category category) { | |||
| 207 | return "Miscellaneous"; | 214 | return "Miscellaneous"; |
| 208 | } | 215 | } |
| 209 | 216 | ||
| 210 | void UpdateRescalingInfo() { | 217 | void TranslateResolutionInfo(ResolutionSetup setup, ResolutionScalingInfo& info) { |
| 211 | const auto setup = values.resolution_setup.GetValue(); | ||
| 212 | auto& info = values.resolution_info; | ||
| 213 | info.downscale = false; | 218 | info.downscale = false; |
| 214 | switch (setup) { | 219 | switch (setup) { |
| 215 | case ResolutionSetup::Res1_2X: | 220 | case ResolutionSetup::Res1_2X: |
| @@ -269,6 +274,12 @@ void UpdateRescalingInfo() { | |||
| 269 | info.active = info.up_scale != 1 || info.down_shift != 0; | 274 | info.active = info.up_scale != 1 || info.down_shift != 0; |
| 270 | } | 275 | } |
| 271 | 276 | ||
| 277 | void UpdateRescalingInfo() { | ||
| 278 | const auto setup = values.resolution_setup.GetValue(); | ||
| 279 | auto& info = values.resolution_info; | ||
| 280 | TranslateResolutionInfo(setup, info); | ||
| 281 | } | ||
| 282 | |||
| 272 | void RestoreGlobalState(bool is_powered_on) { | 283 | void RestoreGlobalState(bool is_powered_on) { |
| 273 | // If a game is running, DO NOT restore the global settings state | 284 | // If a game is running, DO NOT restore the global settings state |
| 274 | if (is_powered_on) { | 285 | 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 { | |||
| 348 | Category::RendererDebug}; | 348 | Category::RendererDebug}; |
| 349 | Setting<bool> disable_shader_loop_safety_checks{ | 349 | Setting<bool> disable_shader_loop_safety_checks{ |
| 350 | linkage, false, "disable_shader_loop_safety_checks", Category::RendererDebug}; | 350 | linkage, false, "disable_shader_loop_safety_checks", Category::RendererDebug}; |
| 351 | Setting<bool> enable_renderdoc_hotkey{linkage, false, "renderdoc_hotkey", | ||
| 352 | Category::RendererDebug}; | ||
| 351 | 353 | ||
| 352 | // System | 354 | // System |
| 353 | SwitchableSetting<Language, true> language_index{linkage, | 355 | SwitchableSetting<Language, true> language_index{linkage, |
| @@ -379,7 +381,13 @@ struct Values { | |||
| 379 | 381 | ||
| 380 | Setting<s32> current_user{linkage, 0, "current_user", Category::System}; | 382 | Setting<s32> current_user{linkage, 0, "current_user", Category::System}; |
| 381 | 383 | ||
| 382 | SwitchableSetting<bool> use_docked_mode{linkage, true, "use_docked_mode", Category::System}; | 384 | SwitchableSetting<ConsoleMode> use_docked_mode{linkage, |
| 385 | ConsoleMode::Docked, | ||
| 386 | "use_docked_mode", | ||
| 387 | Category::System, | ||
| 388 | Specialization::Radio, | ||
| 389 | true, | ||
| 390 | true}; | ||
| 383 | 391 | ||
| 384 | // Controls | 392 | // Controls |
| 385 | InputSetting<std::array<PlayerInput, 10>> players; | 393 | InputSetting<std::array<PlayerInput, 10>> players; |
| @@ -519,12 +527,15 @@ bool IsGPULevelHigh(); | |||
| 519 | 527 | ||
| 520 | bool IsFastmemEnabled(); | 528 | bool IsFastmemEnabled(); |
| 521 | 529 | ||
| 530 | bool IsDockedMode(); | ||
| 531 | |||
| 522 | float Volume(); | 532 | float Volume(); |
| 523 | 533 | ||
| 524 | std::string GetTimeZoneString(TimeZone time_zone); | 534 | std::string GetTimeZoneString(TimeZone time_zone); |
| 525 | 535 | ||
| 526 | void LogSettings(); | 536 | void LogSettings(); |
| 527 | 537 | ||
| 538 | void TranslateResolutionInfo(ResolutionSetup setup, ResolutionScalingInfo& info); | ||
| 528 | void UpdateRescalingInfo(); | 539 | void UpdateRescalingInfo(); |
| 529 | 540 | ||
| 530 | // Restore the global state of all applicable settings in the Values struct | 541 | // 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 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include <functional> | ||
| 4 | #include <string> | 5 | #include <string> |
| 6 | #include <vector> | ||
| 5 | #include "common/settings_common.h" | 7 | #include "common/settings_common.h" |
| 6 | 8 | ||
| 7 | namespace Settings { | 9 | namespace Settings { |
| @@ -12,6 +14,7 @@ BasicSetting::BasicSetting(Linkage& linkage, const std::string& name, enum Categ | |||
| 12 | : label{name}, category{category_}, id{linkage.count}, save{save_}, | 14 | : label{name}, category{category_}, id{linkage.count}, save{save_}, |
| 13 | runtime_modifiable{runtime_modifiable_}, specialization{specialization_}, | 15 | runtime_modifiable{runtime_modifiable_}, specialization{specialization_}, |
| 14 | other_setting{other_setting_} { | 16 | other_setting{other_setting_} { |
| 17 | linkage.by_key.insert({name, this}); | ||
| 15 | linkage.by_category[category].push_back(this); | 18 | linkage.by_category[category].push_back(this); |
| 16 | linkage.count++; | 19 | linkage.count++; |
| 17 | } | 20 | } |
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 @@ | |||
| 12 | namespace Settings { | 12 | namespace Settings { |
| 13 | 13 | ||
| 14 | enum class Category : u32 { | 14 | enum class Category : u32 { |
| 15 | Android, | ||
| 15 | Audio, | 16 | Audio, |
| 16 | Core, | 17 | Core, |
| 17 | Cpu, | 18 | Cpu, |
| @@ -56,6 +57,7 @@ enum Specialization : u8 { | |||
| 56 | Scalar = 5, // Values are continuous | 57 | Scalar = 5, // Values are continuous |
| 57 | Countable = 6, // Can be stepped through | 58 | Countable = 6, // Can be stepped through |
| 58 | Paired = 7, // Another setting is associated with this setting | 59 | Paired = 7, // Another setting is associated with this setting |
| 60 | Radio = 8, // Setting should be presented in a radio group | ||
| 59 | 61 | ||
| 60 | Percentage = (1 << SpecializationAttributeOffset), // Should be represented as a percentage | 62 | Percentage = (1 << SpecializationAttributeOffset), // Should be represented as a percentage |
| 61 | }; | 63 | }; |
| @@ -67,6 +69,7 @@ public: | |||
| 67 | explicit Linkage(u32 initial_count = 0); | 69 | explicit Linkage(u32 initial_count = 0); |
| 68 | ~Linkage(); | 70 | ~Linkage(); |
| 69 | std::map<Category, std::vector<BasicSetting*>> by_category{}; | 71 | std::map<Category, std::vector<BasicSetting*>> by_category{}; |
| 72 | std::map<std::string, Settings::BasicSetting*> by_key{}; | ||
| 70 | std::vector<std::function<void()>> restore_functions{}; | 73 | std::vector<std::function<void()>> restore_functions{}; |
| 71 | u32 count; | 74 | u32 count; |
| 72 | }; | 75 | }; |
| @@ -222,6 +225,16 @@ public: | |||
| 222 | */ | 225 | */ |
| 223 | [[nodiscard]] virtual constexpr u32 EnumIndex() const = 0; | 226 | [[nodiscard]] virtual constexpr u32 EnumIndex() const = 0; |
| 224 | 227 | ||
| 228 | /** | ||
| 229 | * @returns True if the underlying type is a floating point storage | ||
| 230 | */ | ||
| 231 | [[nodiscard]] virtual constexpr bool IsFloatingPoint() const = 0; | ||
| 232 | |||
| 233 | /** | ||
| 234 | * @returns True if the underlying type is an integer storage | ||
| 235 | */ | ||
| 236 | [[nodiscard]] virtual constexpr bool IsIntegral() const = 0; | ||
| 237 | |||
| 225 | /* | 238 | /* |
| 226 | * Switchable settings | 239 | * Switchable settings |
| 227 | */ | 240 | */ |
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 { | |||
| 12 | 12 | ||
| 13 | template <typename T> | 13 | template <typename T> |
| 14 | struct EnumMetadata { | 14 | struct EnumMetadata { |
| 15 | static constexpr std::vector<std::pair<std::string, T>> Canonicalizations(); | 15 | static std::vector<std::pair<std::string, T>> Canonicalizations(); |
| 16 | static constexpr u32 Index(); | 16 | static u32 Index(); |
| 17 | }; | 17 | }; |
| 18 | 18 | ||
| 19 | #define PAIR_45(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_46(N, __VA_ARGS__)) | 19 | #define PAIR_45(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_46(N, __VA_ARGS__)) |
| @@ -66,11 +66,11 @@ struct EnumMetadata { | |||
| 66 | #define ENUM(NAME, ...) \ | 66 | #define ENUM(NAME, ...) \ |
| 67 | enum class NAME : u32 { __VA_ARGS__ }; \ | 67 | enum class NAME : u32 { __VA_ARGS__ }; \ |
| 68 | template <> \ | 68 | template <> \ |
| 69 | constexpr std::vector<std::pair<std::string, NAME>> EnumMetadata<NAME>::Canonicalizations() { \ | 69 | inline std::vector<std::pair<std::string, NAME>> EnumMetadata<NAME>::Canonicalizations() { \ |
| 70 | return {PAIR(NAME, __VA_ARGS__)}; \ | 70 | return {PAIR(NAME, __VA_ARGS__)}; \ |
| 71 | } \ | 71 | } \ |
| 72 | template <> \ | 72 | template <> \ |
| 73 | constexpr u32 EnumMetadata<NAME>::Index() { \ | 73 | inline u32 EnumMetadata<NAME>::Index() { \ |
| 74 | return __COUNTER__; \ | 74 | return __COUNTER__; \ |
| 75 | } | 75 | } |
| 76 | 76 | ||
| @@ -85,7 +85,7 @@ enum class AudioEngine : u32 { | |||
| 85 | }; | 85 | }; |
| 86 | 86 | ||
| 87 | template <> | 87 | template <> |
| 88 | constexpr std::vector<std::pair<std::string, AudioEngine>> | 88 | inline std::vector<std::pair<std::string, AudioEngine>> |
| 89 | EnumMetadata<AudioEngine>::Canonicalizations() { | 89 | EnumMetadata<AudioEngine>::Canonicalizations() { |
| 90 | return { | 90 | return { |
| 91 | {"auto", AudioEngine::Auto}, | 91 | {"auto", AudioEngine::Auto}, |
| @@ -96,7 +96,7 @@ EnumMetadata<AudioEngine>::Canonicalizations() { | |||
| 96 | } | 96 | } |
| 97 | 97 | ||
| 98 | template <> | 98 | template <> |
| 99 | constexpr u32 EnumMetadata<AudioEngine>::Index() { | 99 | inline u32 EnumMetadata<AudioEngine>::Index() { |
| 100 | // This is just a sufficiently large number that is more than the number of other enums declared | 100 | // This is just a sufficiently large number that is more than the number of other enums declared |
| 101 | // here | 101 | // here |
| 102 | return 100; | 102 | return 100; |
| @@ -146,8 +146,10 @@ ENUM(AntiAliasing, None, Fxaa, Smaa, MaxEnum); | |||
| 146 | 146 | ||
| 147 | ENUM(AspectRatio, R16_9, R4_3, R21_9, R16_10, Stretch); | 147 | ENUM(AspectRatio, R16_9, R4_3, R21_9, R16_10, Stretch); |
| 148 | 148 | ||
| 149 | ENUM(ConsoleMode, Handheld, Docked); | ||
| 150 | |||
| 149 | template <typename Type> | 151 | template <typename Type> |
| 150 | constexpr std::string CanonicalizeEnum(Type id) { | 152 | inline std::string CanonicalizeEnum(Type id) { |
| 151 | const auto group = EnumMetadata<Type>::Canonicalizations(); | 153 | const auto group = EnumMetadata<Type>::Canonicalizations(); |
| 152 | for (auto& [name, value] : group) { | 154 | for (auto& [name, value] : group) { |
| 153 | if (value == id) { | 155 | if (value == id) { |
| @@ -158,7 +160,7 @@ constexpr std::string CanonicalizeEnum(Type id) { | |||
| 158 | } | 160 | } |
| 159 | 161 | ||
| 160 | template <typename Type> | 162 | template <typename Type> |
| 161 | constexpr Type ToEnum(const std::string& canonicalization) { | 163 | inline Type ToEnum(const std::string& canonicalization) { |
| 162 | const auto group = EnumMetadata<Type>::Canonicalizations(); | 164 | const auto group = EnumMetadata<Type>::Canonicalizations(); |
| 163 | for (auto& [name, value] : group) { | 165 | for (auto& [name, value] : group) { |
| 164 | if (name == canonicalization) { | 166 | 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 @@ | |||
| 10 | #include <string> | 10 | #include <string> |
| 11 | #include <typeindex> | 11 | #include <typeindex> |
| 12 | #include <typeinfo> | 12 | #include <typeinfo> |
| 13 | #include <fmt/core.h> | ||
| 13 | #include "common/common_types.h" | 14 | #include "common/common_types.h" |
| 14 | #include "common/settings_common.h" | 15 | #include "common/settings_common.h" |
| 15 | #include "common/settings_enums.h" | 16 | #include "common/settings_enums.h" |
| @@ -115,8 +116,12 @@ protected: | |||
| 115 | } else if constexpr (std::is_same_v<Type, AudioEngine>) { | 116 | } else if constexpr (std::is_same_v<Type, AudioEngine>) { |
| 116 | // Compatibility with old AudioEngine setting being a string | 117 | // Compatibility with old AudioEngine setting being a string |
| 117 | return CanonicalizeEnum(value_); | 118 | return CanonicalizeEnum(value_); |
| 119 | } else if constexpr (std::is_floating_point_v<Type>) { | ||
| 120 | return fmt::format("{:f}", value_); | ||
| 121 | } else if constexpr (std::is_enum_v<Type>) { | ||
| 122 | return std::to_string(static_cast<u32>(value_)); | ||
| 118 | } else { | 123 | } else { |
| 119 | return std::to_string(static_cast<u64>(value_)); | 124 | return std::to_string(value_); |
| 120 | } | 125 | } |
| 121 | } | 126 | } |
| 122 | 127 | ||
| @@ -180,17 +185,19 @@ public: | |||
| 180 | this->SetValue(static_cast<u32>(std::stoul(input))); | 185 | this->SetValue(static_cast<u32>(std::stoul(input))); |
| 181 | } else if constexpr (std::is_same_v<Type, bool>) { | 186 | } else if constexpr (std::is_same_v<Type, bool>) { |
| 182 | this->SetValue(input == "true"); | 187 | this->SetValue(input == "true"); |
| 183 | } else if constexpr (std::is_same_v<Type, AudioEngine>) { | 188 | } else if constexpr (std::is_same_v<Type, float>) { |
| 184 | this->SetValue(ToEnum<Type>(input)); | 189 | this->SetValue(std::stof(input)); |
| 185 | } else { | 190 | } else { |
| 186 | this->SetValue(static_cast<Type>(std::stoll(input))); | 191 | this->SetValue(static_cast<Type>(std::stoll(input))); |
| 187 | } | 192 | } |
| 188 | } catch (std::invalid_argument&) { | 193 | } catch (std::invalid_argument&) { |
| 189 | this->SetValue(this->GetDefault()); | 194 | this->SetValue(this->GetDefault()); |
| 195 | } catch (std::out_of_range&) { | ||
| 196 | this->SetValue(this->GetDefault()); | ||
| 190 | } | 197 | } |
| 191 | } | 198 | } |
| 192 | 199 | ||
| 193 | [[nodiscard]] std::string constexpr Canonicalize() const override final { | 200 | [[nodiscard]] std::string Canonicalize() const override final { |
| 194 | if constexpr (std::is_enum_v<Type>) { | 201 | if constexpr (std::is_enum_v<Type>) { |
| 195 | return CanonicalizeEnum(this->GetValue()); | 202 | return CanonicalizeEnum(this->GetValue()); |
| 196 | } else { | 203 | } else { |
| @@ -215,11 +222,27 @@ public: | |||
| 215 | } | 222 | } |
| 216 | } | 223 | } |
| 217 | 224 | ||
| 225 | [[nodiscard]] constexpr bool IsFloatingPoint() const final { | ||
| 226 | return std::is_floating_point_v<Type>; | ||
| 227 | } | ||
| 228 | |||
| 229 | [[nodiscard]] constexpr bool IsIntegral() const final { | ||
| 230 | return std::is_integral_v<Type>; | ||
| 231 | } | ||
| 232 | |||
| 218 | [[nodiscard]] std::string MinVal() const override final { | 233 | [[nodiscard]] std::string MinVal() const override final { |
| 219 | return this->ToString(minimum); | 234 | if constexpr (std::is_arithmetic_v<Type> && !ranged) { |
| 235 | return this->ToString(std::numeric_limits<Type>::min()); | ||
| 236 | } else { | ||
| 237 | return this->ToString(minimum); | ||
| 238 | } | ||
| 220 | } | 239 | } |
| 221 | [[nodiscard]] std::string MaxVal() const override final { | 240 | [[nodiscard]] std::string MaxVal() const override final { |
| 222 | return this->ToString(maximum); | 241 | if constexpr (std::is_arithmetic_v<Type> && !ranged) { |
| 242 | return this->ToString(std::numeric_limits<Type>::max()); | ||
| 243 | } else { | ||
| 244 | return this->ToString(maximum); | ||
| 245 | } | ||
| 223 | } | 246 | } |
| 224 | 247 | ||
| 225 | [[nodiscard]] constexpr bool Ranged() const override { | 248 | [[nodiscard]] constexpr bool Ranged() const override { |
| @@ -256,11 +279,11 @@ public: | |||
| 256 | * @param runtime_modifiable_ Suggests whether this is modifiable while a guest is loaded | 279 | * @param runtime_modifiable_ Suggests whether this is modifiable while a guest is loaded |
| 257 | * @param other_setting_ A second Setting to associate to this one in metadata | 280 | * @param other_setting_ A second Setting to associate to this one in metadata |
| 258 | */ | 281 | */ |
| 282 | template <typename T = BasicSetting> | ||
| 259 | explicit SwitchableSetting(Linkage& linkage, const Type& default_val, const std::string& name, | 283 | explicit SwitchableSetting(Linkage& linkage, const Type& default_val, const std::string& name, |
| 260 | Category category_, u32 specialization_ = Specialization::Default, | 284 | Category category_, u32 specialization_ = Specialization::Default, |
| 261 | bool save_ = true, bool runtime_modifiable_ = false, | 285 | bool save_ = true, bool runtime_modifiable_ = false, |
| 262 | BasicSetting* other_setting_ = nullptr) | 286 | typename std::enable_if<!ranged, T*>::type other_setting_ = nullptr) |
| 263 | requires(!ranged) | ||
| 264 | : Setting<Type, false>{ | 287 | : Setting<Type, false>{ |
| 265 | linkage, default_val, name, category_, specialization_, | 288 | linkage, default_val, name, category_, specialization_, |
| 266 | save_, runtime_modifiable_, other_setting_} { | 289 | save_, runtime_modifiable_, other_setting_} { |
| @@ -282,12 +305,12 @@ public: | |||
| 282 | * @param runtime_modifiable_ Suggests whether this is modifiable while a guest is loaded | 305 | * @param runtime_modifiable_ Suggests whether this is modifiable while a guest is loaded |
| 283 | * @param other_setting_ A second Setting to associate to this one in metadata | 306 | * @param other_setting_ A second Setting to associate to this one in metadata |
| 284 | */ | 307 | */ |
| 308 | template <typename T = BasicSetting> | ||
| 285 | explicit SwitchableSetting(Linkage& linkage, const Type& default_val, const Type& min_val, | 309 | explicit SwitchableSetting(Linkage& linkage, const Type& default_val, const Type& min_val, |
| 286 | const Type& max_val, const std::string& name, Category category_, | 310 | const Type& max_val, const std::string& name, Category category_, |
| 287 | u32 specialization_ = Specialization::Default, bool save_ = true, | 311 | u32 specialization_ = Specialization::Default, bool save_ = true, |
| 288 | bool runtime_modifiable_ = false, | 312 | bool runtime_modifiable_ = false, |
| 289 | BasicSetting* other_setting_ = nullptr) | 313 | typename std::enable_if<ranged, T*>::type other_setting_ = nullptr) |
| 290 | requires(ranged) | ||
| 291 | : Setting<Type, true>{linkage, default_val, min_val, | 314 | : Setting<Type, true>{linkage, default_val, min_val, |
| 292 | max_val, name, category_, | 315 | max_val, name, category_, |
| 293 | specialization_, save_, runtime_modifiable_, | 316 | 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) { | |||
| 460 | return i & v.swap(); | 460 | return i & v.swap(); |
| 461 | } | 461 | } |
| 462 | 462 | ||
| 463 | template <typename S, typename T, typename F> | ||
| 464 | S operator&(const swap_struct_t<T, F> v, const S& i) { | ||
| 465 | return static_cast<S>(v.swap() & i); | ||
| 466 | } | ||
| 467 | |||
| 468 | // Comparison | 463 | // Comparison |
| 469 | template <typename S, typename T, typename F> | 464 | template <typename S, typename T, typename F> |
| 470 | bool operator<(const S& p, const swap_struct_t<T, F> v) { | 465 | bool operator<(const S& p, const swap_struct_t<T, F> v) { |