diff options
Diffstat (limited to 'src')
290 files changed, 14086 insertions, 3182 deletions
diff --git a/src/audio_core/audio_out.cpp b/src/audio_core/audio_out.cpp index fe3a898ad..20a756dce 100644 --- a/src/audio_core/audio_out.cpp +++ b/src/audio_core/audio_out.cpp | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | #include "audio_core/sink_details.h" | 7 | #include "audio_core/sink_details.h" |
| 8 | #include "common/assert.h" | 8 | #include "common/assert.h" |
| 9 | #include "common/logging/log.h" | 9 | #include "common/logging/log.h" |
| 10 | #include "core/settings.h" | 10 | #include "common/settings.h" |
| 11 | 11 | ||
| 12 | namespace AudioCore { | 12 | namespace AudioCore { |
| 13 | 13 | ||
diff --git a/src/audio_core/audio_renderer.cpp b/src/audio_core/audio_renderer.cpp index d2ce8c814..ae2201c36 100644 --- a/src/audio_core/audio_renderer.cpp +++ b/src/audio_core/audio_renderer.cpp | |||
| @@ -11,8 +11,8 @@ | |||
| 11 | #include "audio_core/info_updater.h" | 11 | #include "audio_core/info_updater.h" |
| 12 | #include "audio_core/voice_context.h" | 12 | #include "audio_core/voice_context.h" |
| 13 | #include "common/logging/log.h" | 13 | #include "common/logging/log.h" |
| 14 | #include "common/settings.h" | ||
| 14 | #include "core/memory.h" | 15 | #include "core/memory.h" |
| 15 | #include "core/settings.h" | ||
| 16 | 16 | ||
| 17 | namespace { | 17 | namespace { |
| 18 | [[nodiscard]] static constexpr s16 ClampToS16(s32 value) { | 18 | [[nodiscard]] static constexpr s16 ClampToS16(s32 value) { |
diff --git a/src/audio_core/cubeb_sink.cpp b/src/audio_core/cubeb_sink.cpp index 043447eaa..93c35e785 100644 --- a/src/audio_core/cubeb_sink.cpp +++ b/src/audio_core/cubeb_sink.cpp | |||
| @@ -11,7 +11,7 @@ | |||
| 11 | #include "common/assert.h" | 11 | #include "common/assert.h" |
| 12 | #include "common/logging/log.h" | 12 | #include "common/logging/log.h" |
| 13 | #include "common/ring_buffer.h" | 13 | #include "common/ring_buffer.h" |
| 14 | #include "core/settings.h" | 14 | #include "common/settings.h" |
| 15 | 15 | ||
| 16 | #ifdef _WIN32 | 16 | #ifdef _WIN32 |
| 17 | #include <objbase.h> | 17 | #include <objbase.h> |
diff --git a/src/audio_core/stream.cpp b/src/audio_core/stream.cpp index b0f6f0c34..ad6c587c2 100644 --- a/src/audio_core/stream.cpp +++ b/src/audio_core/stream.cpp | |||
| @@ -11,8 +11,8 @@ | |||
| 11 | #include "audio_core/stream.h" | 11 | #include "audio_core/stream.h" |
| 12 | #include "common/assert.h" | 12 | #include "common/assert.h" |
| 13 | #include "common/logging/log.h" | 13 | #include "common/logging/log.h" |
| 14 | #include "common/settings.h" | ||
| 14 | #include "core/core_timing.h" | 15 | #include "core/core_timing.h" |
| 15 | #include "core/settings.h" | ||
| 16 | 16 | ||
| 17 | namespace AudioCore { | 17 | namespace AudioCore { |
| 18 | 18 | ||
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 | |||
| 97 | add_library(common STATIC | 97 | add_library(common STATIC |
| 98 | algorithm.h | 98 | algorithm.h |
| 99 | alignment.h | 99 | alignment.h |
| 100 | assert.cpp | ||
| 100 | assert.h | 101 | assert.h |
| 101 | atomic_ops.h | 102 | atomic_ops.h |
| 102 | detached_tasks.cpp | 103 | detached_tasks.cpp |
| @@ -109,6 +110,7 @@ add_library(common STATIC | |||
| 109 | cityhash.h | 110 | cityhash.h |
| 110 | common_funcs.h | 111 | common_funcs.h |
| 111 | common_paths.h | 112 | common_paths.h |
| 113 | common_sizes.h | ||
| 112 | common_types.h | 114 | common_types.h |
| 113 | concepts.h | 115 | concepts.h |
| 114 | div_ceil.h | 116 | div_ceil.h |
| @@ -150,6 +152,10 @@ add_library(common STATIC | |||
| 150 | scm_rev.cpp | 152 | scm_rev.cpp |
| 151 | scm_rev.h | 153 | scm_rev.h |
| 152 | scope_exit.h | 154 | scope_exit.h |
| 155 | settings.cpp | ||
| 156 | settings.h | ||
| 157 | settings_input.cpp | ||
| 158 | settings_input.h | ||
| 153 | spin_lock.cpp | 159 | spin_lock.cpp |
| 154 | spin_lock.h | 160 | spin_lock.h |
| 155 | stream.cpp | 161 | 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 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/assert.h" | ||
| 6 | #include "common/common_funcs.h" | ||
| 7 | |||
| 8 | #include "common/settings.h" | ||
| 9 | |||
| 10 | void assert_handle_failure() { | ||
| 11 | if (Settings::values.use_debug_asserts) { | ||
| 12 | Crash(); | ||
| 13 | } | ||
| 14 | } | ||
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 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <cstdlib> | ||
| 8 | #include "common/common_funcs.h" | ||
| 9 | #include "common/logging/log.h" | 7 | #include "common/logging/log.h" |
| 10 | 8 | ||
| 9 | // Sometimes we want to try to continue even after hitting an assert. | ||
| 10 | // However touching this file yields a global recompilation as this header is included almost | ||
| 11 | // everywhere. So let's just move the handling of the failed assert to a single cpp file. | ||
| 12 | void assert_handle_failure(); | ||
| 13 | |||
| 11 | // For asserts we'd like to keep all the junk executed when an assert happens away from the | 14 | // For asserts we'd like to keep all the junk executed when an assert happens away from the |
| 12 | // important code in the function. One way of doing this is to put all the relevant code inside a | 15 | // important code in the function. One way of doing this is to put all the relevant code inside a |
| 13 | // lambda and force the compiler to not inline it. Unfortunately, MSVC seems to have no syntax to | 16 | // lambda and force the compiler to not inline it. Unfortunately, MSVC seems to have no syntax to |
| @@ -17,15 +20,14 @@ | |||
| 17 | // enough for our purposes. | 20 | // enough for our purposes. |
| 18 | template <typename Fn> | 21 | template <typename Fn> |
| 19 | #if defined(_MSC_VER) | 22 | #if defined(_MSC_VER) |
| 20 | [[msvc::noinline, noreturn]] | 23 | [[msvc::noinline]] |
| 21 | #elif defined(__GNUC__) | 24 | #elif defined(__GNUC__) |
| 22 | [[gnu::cold, gnu::noinline, noreturn]] | 25 | [[gnu::cold, gnu::noinline]] |
| 23 | #endif | 26 | #endif |
| 24 | static void | 27 | static void |
| 25 | assert_noinline_call(const Fn& fn) { | 28 | assert_noinline_call(const Fn& fn) { |
| 26 | fn(); | 29 | fn(); |
| 27 | Crash(); | 30 | assert_handle_failure(); |
| 28 | exit(1); // Keeps GCC's mouth shut about this actually returning | ||
| 29 | } | 31 | } |
| 30 | 32 | ||
| 31 | #define ASSERT(_a_) \ | 33 | #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 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <limits> | ||
| 8 | |||
| 9 | #include "common/common_types.h" | ||
| 10 | |||
| 11 | namespace Common { | ||
| 12 | |||
| 13 | enum : u64 { | ||
| 14 | Size_1_KB = 0x400ULL, | ||
| 15 | Size_64_KB = 64ULL * Size_1_KB, | ||
| 16 | Size_128_KB = 128ULL * Size_1_KB, | ||
| 17 | Size_1_MB = 0x100000ULL, | ||
| 18 | Size_2_MB = 2ULL * Size_1_MB, | ||
| 19 | Size_4_MB = 4ULL * Size_1_MB, | ||
| 20 | Size_5_MB = 5ULL * Size_1_MB, | ||
| 21 | Size_14_MB = 14ULL * Size_1_MB, | ||
| 22 | Size_32_MB = 32ULL * Size_1_MB, | ||
| 23 | Size_33_MB = 33ULL * Size_1_MB, | ||
| 24 | Size_128_MB = 128ULL * Size_1_MB, | ||
| 25 | Size_448_MB = 448ULL * Size_1_MB, | ||
| 26 | Size_507_MB = 507ULL * Size_1_MB, | ||
| 27 | Size_562_MB = 562ULL * Size_1_MB, | ||
| 28 | Size_1554_MB = 1554ULL * Size_1_MB, | ||
| 29 | Size_2048_MB = 2048ULL * Size_1_MB, | ||
| 30 | Size_2193_MB = 2193ULL * Size_1_MB, | ||
| 31 | Size_3285_MB = 3285ULL * Size_1_MB, | ||
| 32 | Size_4916_MB = 4916ULL * Size_1_MB, | ||
| 33 | Size_1_GB = 0x40000000ULL, | ||
| 34 | Size_2_GB = 2ULL * Size_1_GB, | ||
| 35 | Size_4_GB = 4ULL * Size_1_GB, | ||
| 36 | Size_6_GB = 6ULL * Size_1_GB, | ||
| 37 | Size_8_GB = 8ULL * Size_1_GB, | ||
| 38 | Size_64_GB = 64ULL * Size_1_GB, | ||
| 39 | Size_512_GB = 512ULL * Size_1_GB, | ||
| 40 | Size_Invalid = std::numeric_limits<u64>::max(), | ||
| 41 | }; | ||
| 42 | |||
| 43 | } // 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 @@ | |||
| 21 | #include "common/logging/backend.h" | 21 | #include "common/logging/backend.h" |
| 22 | #include "common/logging/log.h" | 22 | #include "common/logging/log.h" |
| 23 | #include "common/logging/text_formatter.h" | 23 | #include "common/logging/text_formatter.h" |
| 24 | #include "common/settings.h" | ||
| 24 | #include "common/string_util.h" | 25 | #include "common/string_util.h" |
| 25 | #include "common/threadsafe_queue.h" | 26 | #include "common/threadsafe_queue.h" |
| 26 | #include "core/settings.h" | ||
| 27 | 27 | ||
| 28 | namespace Log { | 28 | namespace Common::Log { |
| 29 | 29 | ||
| 30 | /** | 30 | /** |
| 31 | * Static state as a singleton. | 31 | * Static state as a singleton. |
| @@ -37,8 +37,11 @@ public: | |||
| 37 | return backend; | 37 | return backend; |
| 38 | } | 38 | } |
| 39 | 39 | ||
| 40 | Impl(Impl const&) = delete; | 40 | Impl(const Impl&) = delete; |
| 41 | const Impl& operator=(Impl const&) = delete; | 41 | Impl& operator=(const Impl&) = delete; |
| 42 | |||
| 43 | Impl(Impl&&) = delete; | ||
| 44 | Impl& operator=(Impl&&) = delete; | ||
| 42 | 45 | ||
| 43 | void PushEntry(Class log_class, Level log_level, const char* filename, unsigned int line_num, | 46 | void PushEntry(Class log_class, Level log_level, const char* filename, unsigned int line_num, |
| 44 | const char* function, std::string message) { | 47 | const char* function, std::string message) { |
| @@ -132,7 +135,7 @@ private: | |||
| 132 | std::mutex writing_mutex; | 135 | std::mutex writing_mutex; |
| 133 | std::thread backend_thread; | 136 | std::thread backend_thread; |
| 134 | std::vector<std::unique_ptr<Backend>> backends; | 137 | std::vector<std::unique_ptr<Backend>> backends; |
| 135 | Common::MPSCQueue<Log::Entry> message_queue; | 138 | MPSCQueue<Entry> message_queue; |
| 136 | Filter filter; | 139 | Filter filter; |
| 137 | std::chrono::steady_clock::time_point time_origin{std::chrono::steady_clock::now()}; | 140 | std::chrono::steady_clock::time_point time_origin{std::chrono::steady_clock::now()}; |
| 138 | }; | 141 | }; |
| @@ -146,16 +149,16 @@ void ColorConsoleBackend::Write(const Entry& entry) { | |||
| 146 | } | 149 | } |
| 147 | 150 | ||
| 148 | FileBackend::FileBackend(const std::string& filename) : bytes_written(0) { | 151 | FileBackend::FileBackend(const std::string& filename) : bytes_written(0) { |
| 149 | if (Common::FS::Exists(filename + ".old.txt")) { | 152 | if (FS::Exists(filename + ".old.txt")) { |
| 150 | Common::FS::Delete(filename + ".old.txt"); | 153 | FS::Delete(filename + ".old.txt"); |
| 151 | } | 154 | } |
| 152 | if (Common::FS::Exists(filename)) { | 155 | if (FS::Exists(filename)) { |
| 153 | Common::FS::Rename(filename, filename + ".old.txt"); | 156 | FS::Rename(filename, filename + ".old.txt"); |
| 154 | } | 157 | } |
| 155 | 158 | ||
| 156 | // _SH_DENYWR allows read only access to the file for other programs. | 159 | // _SH_DENYWR allows read only access to the file for other programs. |
| 157 | // It is #defined to 0 on other platforms | 160 | // It is #defined to 0 on other platforms |
| 158 | file = Common::FS::IOFile(filename, "w", _SH_DENYWR); | 161 | file = FS::IOFile(filename, "w", _SH_DENYWR); |
| 159 | } | 162 | } |
| 160 | 163 | ||
| 161 | void FileBackend::Write(const Entry& entry) { | 164 | void FileBackend::Write(const Entry& entry) { |
| @@ -182,7 +185,7 @@ void FileBackend::Write(const Entry& entry) { | |||
| 182 | 185 | ||
| 183 | void DebuggerBackend::Write(const Entry& entry) { | 186 | void DebuggerBackend::Write(const Entry& entry) { |
| 184 | #ifdef _WIN32 | 187 | #ifdef _WIN32 |
| 185 | ::OutputDebugStringW(Common::UTF8ToUTF16W(FormatLogMessage(entry).append(1, '\n')).c_str()); | 188 | ::OutputDebugStringW(UTF8ToUTF16W(FormatLogMessage(entry).append(1, '\n')).c_str()); |
| 186 | #endif | 189 | #endif |
| 187 | } | 190 | } |
| 188 | 191 | ||
| @@ -212,6 +215,7 @@ void DebuggerBackend::Write(const Entry& entry) { | |||
| 212 | SUB(Service, ARP) \ | 215 | SUB(Service, ARP) \ |
| 213 | SUB(Service, BCAT) \ | 216 | SUB(Service, BCAT) \ |
| 214 | SUB(Service, BPC) \ | 217 | SUB(Service, BPC) \ |
| 218 | SUB(Service, BGTC) \ | ||
| 215 | SUB(Service, BTDRV) \ | 219 | SUB(Service, BTDRV) \ |
| 216 | SUB(Service, BTM) \ | 220 | SUB(Service, BTM) \ |
| 217 | SUB(Service, Capture) \ | 221 | SUB(Service, Capture) \ |
| @@ -341,4 +345,4 @@ void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename, | |||
| 341 | instance.PushEntry(log_class, log_level, filename, line_num, function, | 345 | instance.PushEntry(log_class, log_level, filename, line_num, function, |
| 342 | fmt::vformat(format, args)); | 346 | fmt::vformat(format, args)); |
| 343 | } | 347 | } |
| 344 | } // namespace Log | 348 | } // 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 @@ | |||
| 11 | #include "common/logging/filter.h" | 11 | #include "common/logging/filter.h" |
| 12 | #include "common/logging/log.h" | 12 | #include "common/logging/log.h" |
| 13 | 13 | ||
| 14 | namespace Log { | 14 | namespace Common::Log { |
| 15 | 15 | ||
| 16 | class Filter; | 16 | class Filter; |
| 17 | 17 | ||
| @@ -135,4 +135,4 @@ const char* GetLevelName(Level log_level); | |||
| 135 | * never get the message | 135 | * never get the message |
| 136 | */ | 136 | */ |
| 137 | void SetGlobalFilter(const Filter& filter); | 137 | void SetGlobalFilter(const Filter& filter); |
| 138 | } // namespace Log \ No newline at end of file | 138 | } // 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 @@ | |||
| 7 | #include "common/logging/filter.h" | 7 | #include "common/logging/filter.h" |
| 8 | #include "common/string_util.h" | 8 | #include "common/string_util.h" |
| 9 | 9 | ||
| 10 | namespace Log { | 10 | namespace Common::Log { |
| 11 | namespace { | 11 | namespace { |
| 12 | template <typename It> | 12 | template <typename It> |
| 13 | Level GetLevelByName(const It begin, const It end) { | 13 | Level GetLevelByName(const It begin, const It end) { |
| @@ -103,4 +103,4 @@ bool Filter::IsDebug() const { | |||
| 103 | }); | 103 | }); |
| 104 | } | 104 | } |
| 105 | 105 | ||
| 106 | } // namespace Log | 106 | } // 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 @@ | |||
| 9 | #include <string_view> | 9 | #include <string_view> |
| 10 | #include "common/logging/log.h" | 10 | #include "common/logging/log.h" |
| 11 | 11 | ||
| 12 | namespace Log { | 12 | namespace Common::Log { |
| 13 | 13 | ||
| 14 | /** | 14 | /** |
| 15 | * Implements a log message filter which allows different log classes to have different minimum | 15 | * Implements a log message filter which allows different log classes to have different minimum |
| @@ -51,4 +51,4 @@ public: | |||
| 51 | private: | 51 | private: |
| 52 | std::array<Level, static_cast<std::size_t>(Class::Count)> class_levels; | 52 | std::array<Level, static_cast<std::size_t>(Class::Count)> class_levels; |
| 53 | }; | 53 | }; |
| 54 | } // namespace Log | 54 | } // 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 @@ | |||
| 7 | #include <fmt/format.h> | 7 | #include <fmt/format.h> |
| 8 | #include "common/common_types.h" | 8 | #include "common/common_types.h" |
| 9 | 9 | ||
| 10 | namespace Log { | 10 | namespace Common::Log { |
| 11 | 11 | ||
| 12 | // trims up to and including the last of ../, ..\, src/, src\ in a string | 12 | // trims up to and including the last of ../, ..\, src/, src\ in a string |
| 13 | constexpr const char* TrimSourcePath(std::string_view source) { | 13 | constexpr const char* TrimSourcePath(std::string_view source) { |
| @@ -66,6 +66,7 @@ enum class Class : ClassType { | |||
| 66 | Service_ARP, ///< The ARP service | 66 | Service_ARP, ///< The ARP service |
| 67 | Service_Audio, ///< The Audio (Audio control) service | 67 | Service_Audio, ///< The Audio (Audio control) service |
| 68 | Service_BCAT, ///< The BCAT service | 68 | Service_BCAT, ///< The BCAT service |
| 69 | Service_BGTC, ///< The BGTC (Background Task Controller) service | ||
| 69 | Service_BPC, ///< The BPC service | 70 | Service_BPC, ///< The BPC service |
| 70 | Service_BTDRV, ///< The Bluetooth driver service | 71 | Service_BTDRV, ///< The Bluetooth driver service |
| 71 | Service_BTM, ///< The BTM service | 72 | Service_BTM, ///< The BTM service |
| @@ -147,28 +148,34 @@ void FmtLogMessage(Class log_class, Level log_level, const char* filename, unsig | |||
| 147 | fmt::make_format_args(args...)); | 148 | fmt::make_format_args(args...)); |
| 148 | } | 149 | } |
| 149 | 150 | ||
| 150 | } // namespace Log | 151 | } // namespace Common::Log |
| 151 | 152 | ||
| 152 | #ifdef _DEBUG | 153 | #ifdef _DEBUG |
| 153 | #define LOG_TRACE(log_class, ...) \ | 154 | #define LOG_TRACE(log_class, ...) \ |
| 154 | ::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Trace, \ | 155 | Common::Log::FmtLogMessage(Common::Log::Class::log_class, Common::Log::Level::Trace, \ |
| 155 | ::Log::TrimSourcePath(__FILE__), __LINE__, __func__, __VA_ARGS__) | 156 | Common::Log::TrimSourcePath(__FILE__), __LINE__, __func__, \ |
| 157 | __VA_ARGS__) | ||
| 156 | #else | 158 | #else |
| 157 | #define LOG_TRACE(log_class, fmt, ...) (void(0)) | 159 | #define LOG_TRACE(log_class, fmt, ...) (void(0)) |
| 158 | #endif | 160 | #endif |
| 159 | 161 | ||
| 160 | #define LOG_DEBUG(log_class, ...) \ | 162 | #define LOG_DEBUG(log_class, ...) \ |
| 161 | ::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Debug, \ | 163 | Common::Log::FmtLogMessage(Common::Log::Class::log_class, Common::Log::Level::Debug, \ |
| 162 | ::Log::TrimSourcePath(__FILE__), __LINE__, __func__, __VA_ARGS__) | 164 | Common::Log::TrimSourcePath(__FILE__), __LINE__, __func__, \ |
| 165 | __VA_ARGS__) | ||
| 163 | #define LOG_INFO(log_class, ...) \ | 166 | #define LOG_INFO(log_class, ...) \ |
| 164 | ::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Info, \ | 167 | Common::Log::FmtLogMessage(Common::Log::Class::log_class, Common::Log::Level::Info, \ |
| 165 | ::Log::TrimSourcePath(__FILE__), __LINE__, __func__, __VA_ARGS__) | 168 | Common::Log::TrimSourcePath(__FILE__), __LINE__, __func__, \ |
| 169 | __VA_ARGS__) | ||
| 166 | #define LOG_WARNING(log_class, ...) \ | 170 | #define LOG_WARNING(log_class, ...) \ |
| 167 | ::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Warning, \ | 171 | Common::Log::FmtLogMessage(Common::Log::Class::log_class, Common::Log::Level::Warning, \ |
| 168 | ::Log::TrimSourcePath(__FILE__), __LINE__, __func__, __VA_ARGS__) | 172 | Common::Log::TrimSourcePath(__FILE__), __LINE__, __func__, \ |
| 173 | __VA_ARGS__) | ||
| 169 | #define LOG_ERROR(log_class, ...) \ | 174 | #define LOG_ERROR(log_class, ...) \ |
| 170 | ::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Error, \ | 175 | Common::Log::FmtLogMessage(Common::Log::Class::log_class, Common::Log::Level::Error, \ |
| 171 | ::Log::TrimSourcePath(__FILE__), __LINE__, __func__, __VA_ARGS__) | 176 | Common::Log::TrimSourcePath(__FILE__), __LINE__, __func__, \ |
| 177 | __VA_ARGS__) | ||
| 172 | #define LOG_CRITICAL(log_class, ...) \ | 178 | #define LOG_CRITICAL(log_class, ...) \ |
| 173 | ::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Critical, \ | 179 | Common::Log::FmtLogMessage(Common::Log::Class::log_class, Common::Log::Level::Critical, \ |
| 174 | ::Log::TrimSourcePath(__FILE__), __LINE__, __func__, __VA_ARGS__) | 180 | Common::Log::TrimSourcePath(__FILE__), __LINE__, __func__, \ |
| 181 | __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 @@ | |||
| 16 | #include "common/logging/text_formatter.h" | 16 | #include "common/logging/text_formatter.h" |
| 17 | #include "common/string_util.h" | 17 | #include "common/string_util.h" |
| 18 | 18 | ||
| 19 | namespace Log { | 19 | namespace Common::Log { |
| 20 | 20 | ||
| 21 | std::string FormatLogMessage(const Entry& entry) { | 21 | std::string FormatLogMessage(const Entry& entry) { |
| 22 | unsigned int time_seconds = static_cast<unsigned int>(entry.timestamp.count() / 1000000); | 22 | unsigned int time_seconds = static_cast<unsigned int>(entry.timestamp.count() / 1000000); |
| @@ -108,4 +108,4 @@ void PrintColoredMessage(const Entry& entry) { | |||
| 108 | #undef ESC | 108 | #undef ESC |
| 109 | #endif | 109 | #endif |
| 110 | } | 110 | } |
| 111 | } // namespace Log | 111 | } // 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 @@ | |||
| 7 | #include <cstddef> | 7 | #include <cstddef> |
| 8 | #include <string> | 8 | #include <string> |
| 9 | 9 | ||
| 10 | namespace Log { | 10 | namespace Common::Log { |
| 11 | 11 | ||
| 12 | struct Entry; | 12 | struct Entry; |
| 13 | 13 | ||
| @@ -17,4 +17,4 @@ std::string FormatLogMessage(const Entry& entry); | |||
| 17 | void PrintMessage(const Entry& entry); | 17 | void PrintMessage(const Entry& entry); |
| 18 | /// Prints the same message as `PrintMessage`, but colored according to the severity level. | 18 | /// Prints the same message as `PrintMessage`, but colored according to the severity level. |
| 19 | void PrintColoredMessage(const Entry& entry); | 19 | void PrintColoredMessage(const Entry& entry); |
| 20 | } // namespace Log | 20 | } // 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 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #pragma once | ||
| 6 | |||
| 5 | namespace Common { | 7 | namespace Common { |
| 6 | 8 | ||
| 7 | /// Configure platform specific flags for Nvidia's driver | 9 | /// Configure platform specific flags for Nvidia's driver |
diff --git a/src/core/settings.cpp b/src/common/settings.cpp index 2ae5196e0..702b6598d 100644 --- a/src/core/settings.cpp +++ b/src/common/settings.cpp | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | 1 | // Copyright 2021 yuzu Emulator Project |
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| @@ -7,10 +7,7 @@ | |||
| 7 | #include "common/assert.h" | 7 | #include "common/assert.h" |
| 8 | #include "common/file_util.h" | 8 | #include "common/file_util.h" |
| 9 | #include "common/logging/log.h" | 9 | #include "common/logging/log.h" |
| 10 | #include "core/core.h" | 10 | #include "common/settings.h" |
| 11 | #include "core/hle/service/hid/hid.h" | ||
| 12 | #include "core/settings.h" | ||
| 13 | #include "video_core/renderer_base.h" | ||
| 14 | 11 | ||
| 15 | namespace Settings { | 12 | namespace Settings { |
| 16 | 13 | ||
| @@ -32,14 +29,6 @@ std::string GetTimeZoneString() { | |||
| 32 | return timezones[time_zone_index]; | 29 | return timezones[time_zone_index]; |
| 33 | } | 30 | } |
| 34 | 31 | ||
| 35 | void Apply(Core::System& system) { | ||
| 36 | if (system.IsPoweredOn()) { | ||
| 37 | system.Renderer().RefreshBaseSettings(); | ||
| 38 | } | ||
| 39 | |||
| 40 | Service::HID::ReloadInputDevices(); | ||
| 41 | } | ||
| 42 | |||
| 43 | void LogSettings() { | 32 | void LogSettings() { |
| 44 | const auto log_setting = [](std::string_view name, const auto& value) { | 33 | const auto log_setting = [](std::string_view name, const auto& value) { |
| 45 | LOG_INFO(Config, "{}: {}", name, value); | 34 | LOG_INFO(Config, "{}: {}", name, value); |
diff --git a/src/core/settings.h b/src/common/settings.h index d849dded3..d39b4aa45 100644 --- a/src/core/settings.h +++ b/src/common/settings.h | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | 1 | // Copyright 2021 yuzu Emulator Project |
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| @@ -11,16 +11,13 @@ | |||
| 11 | #include <optional> | 11 | #include <optional> |
| 12 | #include <string> | 12 | #include <string> |
| 13 | #include <vector> | 13 | #include <vector> |
| 14 | #include "common/common_types.h" | ||
| 15 | #include "input_common/settings.h" | ||
| 16 | 14 | ||
| 17 | namespace Core { | 15 | #include "common/common_types.h" |
| 18 | class System; | 16 | #include "common/settings_input.h" |
| 19 | } | ||
| 20 | 17 | ||
| 21 | namespace Settings { | 18 | namespace Settings { |
| 22 | 19 | ||
| 23 | enum class RendererBackend { | 20 | enum class RendererBackend : u32 { |
| 24 | OpenGL = 0, | 21 | OpenGL = 0, |
| 25 | Vulkan = 1, | 22 | Vulkan = 1, |
| 26 | }; | 23 | }; |
| @@ -31,7 +28,7 @@ enum class GPUAccuracy : u32 { | |||
| 31 | Extreme = 2, | 28 | Extreme = 2, |
| 32 | }; | 29 | }; |
| 33 | 30 | ||
| 34 | enum class CPUAccuracy { | 31 | enum class CPUAccuracy : u32 { |
| 35 | Accurate = 0, | 32 | Accurate = 0, |
| 36 | Unsafe = 1, | 33 | Unsafe = 1, |
| 37 | DebugMode = 2, | 34 | DebugMode = 2, |
| @@ -139,6 +136,7 @@ struct Values { | |||
| 139 | Setting<int> vulkan_device; | 136 | Setting<int> vulkan_device; |
| 140 | 137 | ||
| 141 | Setting<u16> resolution_factor{1}; | 138 | Setting<u16> resolution_factor{1}; |
| 139 | Setting<int> fullscreen_mode; | ||
| 142 | Setting<int> aspect_ratio; | 140 | Setting<int> aspect_ratio; |
| 143 | Setting<int> max_anisotropy; | 141 | Setting<int> max_anisotropy; |
| 144 | Setting<bool> use_frame_limit; | 142 | Setting<bool> use_frame_limit; |
| @@ -222,6 +220,8 @@ struct Values { | |||
| 222 | bool quest_flag; | 220 | bool quest_flag; |
| 223 | bool disable_macro_jit; | 221 | bool disable_macro_jit; |
| 224 | bool extended_logging; | 222 | bool extended_logging; |
| 223 | bool use_debug_asserts; | ||
| 224 | bool use_auto_stub; | ||
| 225 | 225 | ||
| 226 | // Miscellaneous | 226 | // Miscellaneous |
| 227 | std::string log_filter; | 227 | std::string log_filter; |
| @@ -253,7 +253,6 @@ float Volume(); | |||
| 253 | 253 | ||
| 254 | std::string GetTimeZoneString(); | 254 | std::string GetTimeZoneString(); |
| 255 | 255 | ||
| 256 | void Apply(Core::System& system); | ||
| 257 | void LogSettings(); | 256 | void LogSettings(); |
| 258 | 257 | ||
| 259 | // Restore the global state of all applicable settings in the Values struct | 258 | // Restore the global state of all applicable settings in the Values struct |
diff --git a/src/input_common/settings.cpp b/src/common/settings_input.cpp index 557e7a9a0..bea2b837b 100644 --- a/src/input_common/settings.cpp +++ b/src/common/settings_input.cpp | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include "input_common/settings.h" | 5 | #include "common/settings_input.h" |
| 6 | 6 | ||
| 7 | namespace Settings { | 7 | namespace Settings { |
| 8 | namespace NativeButton { | 8 | namespace NativeButton { |
diff --git a/src/input_common/settings.h b/src/common/settings_input.h index a59f5d461..609600582 100644 --- a/src/input_common/settings.h +++ b/src/common/settings_input.h | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | 6 | ||
| 7 | #include <array> | 7 | #include <array> |
| 8 | #include <string> | 8 | #include <string> |
| 9 | |||
| 9 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 10 | 11 | ||
| 11 | namespace Settings { | 12 | 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: | |||
| 83 | return true; | 83 | return true; |
| 84 | } | 84 | } |
| 85 | 85 | ||
| 86 | T PopWait() { | 86 | void Wait() { |
| 87 | if (Empty()) { | 87 | if (Empty()) { |
| 88 | std::unique_lock lock{cv_mutex}; | 88 | std::unique_lock lock{cv_mutex}; |
| 89 | cv.wait(lock, [this]() { return !Empty(); }); | 89 | cv.wait(lock, [this]() { return !Empty(); }); |
| 90 | } | 90 | } |
| 91 | } | ||
| 92 | |||
| 93 | T PopWait() { | ||
| 94 | Wait(); | ||
| 91 | T t; | 95 | T t; |
| 92 | Pop(t); | 96 | Pop(t); |
| 93 | return t; | 97 | return t; |
| @@ -156,6 +160,10 @@ public: | |||
| 156 | return spsc_queue.Pop(t); | 160 | return spsc_queue.Pop(t); |
| 157 | } | 161 | } |
| 158 | 162 | ||
| 163 | void Wait() { | ||
| 164 | spsc_queue.Wait(); | ||
| 165 | } | ||
| 166 | |||
| 159 | T PopWait() { | 167 | T PopWait() { |
| 160 | return spsc_queue.PopWait(); | 168 | return spsc_queue.PopWait(); |
| 161 | } | 169 | } |
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 17f251c37..532e418b0 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt | |||
| @@ -141,6 +141,9 @@ add_library(core STATIC | |||
| 141 | hardware_interrupt_manager.h | 141 | hardware_interrupt_manager.h |
| 142 | hle/ipc.h | 142 | hle/ipc.h |
| 143 | hle/ipc_helpers.h | 143 | hle/ipc_helpers.h |
| 144 | hle/kernel/board/nintendo/nx/k_system_control.cpp | ||
| 145 | hle/kernel/board/nintendo/nx/k_system_control.h | ||
| 146 | hle/kernel/board/nintendo/nx/secure_monitor.h | ||
| 144 | hle/kernel/client_port.cpp | 147 | hle/kernel/client_port.cpp |
| 145 | hle/kernel/client_port.h | 148 | hle/kernel/client_port.h |
| 146 | hle/kernel/client_session.cpp | 149 | hle/kernel/client_session.cpp |
| @@ -169,9 +172,13 @@ add_library(core STATIC | |||
| 169 | hle/kernel/k_memory_block.h | 172 | hle/kernel/k_memory_block.h |
| 170 | hle/kernel/k_memory_block_manager.cpp | 173 | hle/kernel/k_memory_block_manager.cpp |
| 171 | hle/kernel/k_memory_block_manager.h | 174 | hle/kernel/k_memory_block_manager.h |
| 175 | hle/kernel/k_memory_layout.cpp | ||
| 176 | hle/kernel/k_memory_layout.board.nintendo_nx.cpp | ||
| 172 | hle/kernel/k_memory_layout.h | 177 | hle/kernel/k_memory_layout.h |
| 173 | hle/kernel/k_memory_manager.cpp | 178 | hle/kernel/k_memory_manager.cpp |
| 174 | hle/kernel/k_memory_manager.h | 179 | hle/kernel/k_memory_manager.h |
| 180 | hle/kernel/k_memory_region.h | ||
| 181 | hle/kernel/k_memory_region_type.h | ||
| 175 | hle/kernel/k_page_bitmap.h | 182 | hle/kernel/k_page_bitmap.h |
| 176 | hle/kernel/k_page_heap.cpp | 183 | hle/kernel/k_page_heap.cpp |
| 177 | hle/kernel/k_page_heap.h | 184 | hle/kernel/k_page_heap.h |
| @@ -196,11 +203,11 @@ add_library(core STATIC | |||
| 196 | hle/kernel/k_spin_lock.h | 203 | hle/kernel/k_spin_lock.h |
| 197 | hle/kernel/k_synchronization_object.cpp | 204 | hle/kernel/k_synchronization_object.cpp |
| 198 | hle/kernel/k_synchronization_object.h | 205 | hle/kernel/k_synchronization_object.h |
| 199 | hle/kernel/k_system_control.cpp | ||
| 200 | hle/kernel/k_system_control.h | 206 | hle/kernel/k_system_control.h |
| 201 | hle/kernel/k_thread.cpp | 207 | hle/kernel/k_thread.cpp |
| 202 | hle/kernel/k_thread.h | 208 | hle/kernel/k_thread.h |
| 203 | hle/kernel/k_thread_queue.h | 209 | hle/kernel/k_thread_queue.h |
| 210 | hle/kernel/k_trace.h | ||
| 204 | hle/kernel/k_writable_event.cpp | 211 | hle/kernel/k_writable_event.cpp |
| 205 | hle/kernel/k_writable_event.h | 212 | hle/kernel/k_writable_event.h |
| 206 | hle/kernel/kernel.cpp | 213 | hle/kernel/kernel.cpp |
| @@ -266,6 +273,7 @@ add_library(core STATIC | |||
| 266 | hle/service/am/applets/profile_select.h | 273 | hle/service/am/applets/profile_select.h |
| 267 | hle/service/am/applets/software_keyboard.cpp | 274 | hle/service/am/applets/software_keyboard.cpp |
| 268 | hle/service/am/applets/software_keyboard.h | 275 | hle/service/am/applets/software_keyboard.h |
| 276 | hle/service/am/applets/software_keyboard_types.h | ||
| 269 | hle/service/am/applets/web_browser.cpp | 277 | hle/service/am/applets/web_browser.cpp |
| 270 | hle/service/am/applets/web_browser.h | 278 | hle/service/am/applets/web_browser.h |
| 271 | hle/service/am/applets/web_types.h | 279 | hle/service/am/applets/web_types.h |
| @@ -614,8 +622,6 @@ add_library(core STATIC | |||
| 614 | perf_stats.h | 622 | perf_stats.h |
| 615 | reporter.cpp | 623 | reporter.cpp |
| 616 | reporter.h | 624 | reporter.h |
| 617 | settings.cpp | ||
| 618 | settings.h | ||
| 619 | telemetry_session.cpp | 625 | telemetry_session.cpp |
| 620 | telemetry_session.h | 626 | telemetry_session.h |
| 621 | tools/freezer.cpp | 627 | tools/freezer.cpp |
| @@ -666,7 +672,7 @@ endif() | |||
| 666 | create_target_directory_groups(core) | 672 | create_target_directory_groups(core) |
| 667 | 673 | ||
| 668 | target_link_libraries(core PUBLIC common PRIVATE audio_core video_core) | 674 | target_link_libraries(core PUBLIC common PRIVATE audio_core video_core) |
| 669 | target_link_libraries(core PUBLIC Boost::boost PRIVATE fmt::fmt nlohmann_json::nlohmann_json mbedtls opus zip) | 675 | target_link_libraries(core PUBLIC Boost::boost PRIVATE fmt::fmt nlohmann_json::nlohmann_json mbedtls Opus::Opus zip) |
| 670 | 676 | ||
| 671 | if (YUZU_ENABLE_BOXCAT) | 677 | if (YUZU_ENABLE_BOXCAT) |
| 672 | target_compile_definitions(core PRIVATE -DYUZU_ENABLE_BOXCAT) | 678 | target_compile_definitions(core PRIVATE -DYUZU_ENABLE_BOXCAT) |
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp index 53d78de32..7aeb2a658 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | #include "common/assert.h" | 10 | #include "common/assert.h" |
| 11 | #include "common/logging/log.h" | 11 | #include "common/logging/log.h" |
| 12 | #include "common/page_table.h" | 12 | #include "common/page_table.h" |
| 13 | #include "common/settings.h" | ||
| 13 | #include "core/arm/cpu_interrupt_handler.h" | 14 | #include "core/arm/cpu_interrupt_handler.h" |
| 14 | #include "core/arm/dynarmic/arm_dynarmic_32.h" | 15 | #include "core/arm/dynarmic/arm_dynarmic_32.h" |
| 15 | #include "core/arm/dynarmic/arm_dynarmic_cp15.h" | 16 | #include "core/arm/dynarmic/arm_dynarmic_cp15.h" |
| @@ -18,7 +19,6 @@ | |||
| 18 | #include "core/core_timing.h" | 19 | #include "core/core_timing.h" |
| 19 | #include "core/hle/kernel/svc.h" | 20 | #include "core/hle/kernel/svc.h" |
| 20 | #include "core/memory.h" | 21 | #include "core/memory.h" |
| 21 | #include "core/settings.h" | ||
| 22 | 22 | ||
| 23 | namespace Core { | 23 | namespace Core { |
| 24 | 24 | ||
| @@ -114,18 +114,17 @@ public: | |||
| 114 | static constexpr u64 minimum_run_cycles = 1000U; | 114 | static constexpr u64 minimum_run_cycles = 1000U; |
| 115 | }; | 115 | }; |
| 116 | 116 | ||
| 117 | std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable& page_table, | 117 | std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable* page_table) const { |
| 118 | std::size_t address_space_bits) const { | ||
| 119 | Dynarmic::A32::UserConfig config; | 118 | Dynarmic::A32::UserConfig config; |
| 120 | config.callbacks = cb.get(); | 119 | config.callbacks = cb.get(); |
| 121 | // TODO(bunnei): Implement page table for 32-bit | ||
| 122 | // config.page_table = &page_table.pointers; | ||
| 123 | config.coprocessors[15] = cp15; | 120 | config.coprocessors[15] = cp15; |
| 124 | config.define_unpredictable_behaviour = true; | 121 | config.define_unpredictable_behaviour = true; |
| 125 | static constexpr std::size_t PAGE_BITS = 12; | 122 | static constexpr std::size_t PAGE_BITS = 12; |
| 126 | static constexpr std::size_t NUM_PAGE_TABLE_ENTRIES = 1 << (32 - PAGE_BITS); | 123 | static constexpr std::size_t NUM_PAGE_TABLE_ENTRIES = 1 << (32 - PAGE_BITS); |
| 127 | config.page_table = reinterpret_cast<std::array<std::uint8_t*, NUM_PAGE_TABLE_ENTRIES>*>( | 124 | if (page_table) { |
| 128 | page_table.pointers.data()); | 125 | config.page_table = reinterpret_cast<std::array<std::uint8_t*, NUM_PAGE_TABLE_ENTRIES>*>( |
| 126 | page_table->pointers.data()); | ||
| 127 | } | ||
| 129 | config.absolute_offset_page_table = true; | 128 | config.absolute_offset_page_table = true; |
| 130 | config.page_table_pointer_mask_bits = Common::PageTable::ATTRIBUTE_BITS; | 129 | config.page_table_pointer_mask_bits = Common::PageTable::ATTRIBUTE_BITS; |
| 131 | config.detect_misaligned_access_via_page_table = 16 | 32 | 64 | 128; | 130 | config.detect_misaligned_access_via_page_table = 16 | 32 | 64 | 128; |
| @@ -138,6 +137,10 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable& | |||
| 138 | // Timing | 137 | // Timing |
| 139 | config.wall_clock_cntpct = uses_wall_clock; | 138 | config.wall_clock_cntpct = uses_wall_clock; |
| 140 | 139 | ||
| 140 | // Code cache size | ||
| 141 | config.code_cache_size = 512 * 1024 * 1024; | ||
| 142 | config.far_code_offset = 256 * 1024 * 1024; | ||
| 143 | |||
| 141 | // Safe optimizations | 144 | // Safe optimizations |
| 142 | if (Settings::values.cpu_accuracy == Settings::CPUAccuracy::DebugMode) { | 145 | if (Settings::values.cpu_accuracy == Settings::CPUAccuracy::DebugMode) { |
| 143 | if (!Settings::values.cpuopt_page_tables) { | 146 | if (!Settings::values.cpuopt_page_tables) { |
| @@ -201,7 +204,8 @@ ARM_Dynarmic_32::ARM_Dynarmic_32(System& system, CPUInterrupts& interrupt_handle | |||
| 201 | : ARM_Interface{system, interrupt_handlers, uses_wall_clock}, | 204 | : ARM_Interface{system, interrupt_handlers, uses_wall_clock}, |
| 202 | cb(std::make_unique<DynarmicCallbacks32>(*this)), | 205 | cb(std::make_unique<DynarmicCallbacks32>(*this)), |
| 203 | cp15(std::make_shared<DynarmicCP15>(*this)), core_index{core_index}, | 206 | cp15(std::make_shared<DynarmicCP15>(*this)), core_index{core_index}, |
| 204 | exclusive_monitor{dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor)} {} | 207 | exclusive_monitor{dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor)}, |
| 208 | jit(MakeJit(nullptr)) {} | ||
| 205 | 209 | ||
| 206 | ARM_Dynarmic_32::~ARM_Dynarmic_32() = default; | 210 | ARM_Dynarmic_32::~ARM_Dynarmic_32() = default; |
| 207 | 211 | ||
| @@ -256,9 +260,6 @@ void ARM_Dynarmic_32::ChangeProcessorID(std::size_t new_core_id) { | |||
| 256 | } | 260 | } |
| 257 | 261 | ||
| 258 | void ARM_Dynarmic_32::SaveContext(ThreadContext32& ctx) { | 262 | void ARM_Dynarmic_32::SaveContext(ThreadContext32& ctx) { |
| 259 | if (!jit) { | ||
| 260 | return; | ||
| 261 | } | ||
| 262 | Dynarmic::A32::Context context; | 263 | Dynarmic::A32::Context context; |
| 263 | jit->SaveContext(context); | 264 | jit->SaveContext(context); |
| 264 | ctx.cpu_registers = context.Regs(); | 265 | ctx.cpu_registers = context.Regs(); |
| @@ -268,9 +269,6 @@ void ARM_Dynarmic_32::SaveContext(ThreadContext32& ctx) { | |||
| 268 | } | 269 | } |
| 269 | 270 | ||
| 270 | void ARM_Dynarmic_32::LoadContext(const ThreadContext32& ctx) { | 271 | void ARM_Dynarmic_32::LoadContext(const ThreadContext32& ctx) { |
| 271 | if (!jit) { | ||
| 272 | return; | ||
| 273 | } | ||
| 274 | Dynarmic::A32::Context context; | 272 | Dynarmic::A32::Context context; |
| 275 | context.Regs() = ctx.cpu_registers; | 273 | context.Regs() = ctx.cpu_registers; |
| 276 | context.ExtRegs() = ctx.extension_registers; | 274 | context.ExtRegs() = ctx.extension_registers; |
| @@ -284,23 +282,14 @@ void ARM_Dynarmic_32::PrepareReschedule() { | |||
| 284 | } | 282 | } |
| 285 | 283 | ||
| 286 | void ARM_Dynarmic_32::ClearInstructionCache() { | 284 | void ARM_Dynarmic_32::ClearInstructionCache() { |
| 287 | if (!jit) { | ||
| 288 | return; | ||
| 289 | } | ||
| 290 | jit->ClearCache(); | 285 | jit->ClearCache(); |
| 291 | } | 286 | } |
| 292 | 287 | ||
| 293 | void ARM_Dynarmic_32::InvalidateCacheRange(VAddr addr, std::size_t size) { | 288 | void ARM_Dynarmic_32::InvalidateCacheRange(VAddr addr, std::size_t size) { |
| 294 | if (!jit) { | ||
| 295 | return; | ||
| 296 | } | ||
| 297 | jit->InvalidateCacheRange(static_cast<u32>(addr), size); | 289 | jit->InvalidateCacheRange(static_cast<u32>(addr), size); |
| 298 | } | 290 | } |
| 299 | 291 | ||
| 300 | void ARM_Dynarmic_32::ClearExclusiveState() { | 292 | void ARM_Dynarmic_32::ClearExclusiveState() { |
| 301 | if (!jit) { | ||
| 302 | return; | ||
| 303 | } | ||
| 304 | jit->ClearExclusiveState(); | 293 | jit->ClearExclusiveState(); |
| 305 | } | 294 | } |
| 306 | 295 | ||
| @@ -316,7 +305,7 @@ void ARM_Dynarmic_32::PageTableChanged(Common::PageTable& page_table, | |||
| 316 | LoadContext(ctx); | 305 | LoadContext(ctx); |
| 317 | return; | 306 | return; |
| 318 | } | 307 | } |
| 319 | jit = MakeJit(page_table, new_address_space_size_in_bits); | 308 | jit = MakeJit(&page_table); |
| 320 | LoadContext(ctx); | 309 | LoadContext(ctx); |
| 321 | jit_cache.emplace(key, jit); | 310 | jit_cache.emplace(key, jit); |
| 322 | } | 311 | } |
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.h b/src/core/arm/dynarmic/arm_dynarmic_32.h index f6c4d4db9..d40aef7a9 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.h +++ b/src/core/arm/dynarmic/arm_dynarmic_32.h | |||
| @@ -68,8 +68,7 @@ public: | |||
| 68 | std::size_t new_address_space_size_in_bits) override; | 68 | std::size_t new_address_space_size_in_bits) override; |
| 69 | 69 | ||
| 70 | private: | 70 | private: |
| 71 | std::shared_ptr<Dynarmic::A32::Jit> MakeJit(Common::PageTable& page_table, | 71 | std::shared_ptr<Dynarmic::A32::Jit> MakeJit(Common::PageTable* page_table) const; |
| 72 | std::size_t address_space_bits) const; | ||
| 73 | 72 | ||
| 74 | using JitCacheKey = std::pair<Common::PageTable*, std::size_t>; | 73 | using JitCacheKey = std::pair<Common::PageTable*, std::size_t>; |
| 75 | using JitCacheType = | 74 | using JitCacheType = |
| @@ -80,10 +79,10 @@ private: | |||
| 80 | 79 | ||
| 81 | std::unique_ptr<DynarmicCallbacks32> cb; | 80 | std::unique_ptr<DynarmicCallbacks32> cb; |
| 82 | JitCacheType jit_cache; | 81 | JitCacheType jit_cache; |
| 83 | std::shared_ptr<Dynarmic::A32::Jit> jit; | ||
| 84 | std::shared_ptr<DynarmicCP15> cp15; | 82 | std::shared_ptr<DynarmicCP15> cp15; |
| 85 | std::size_t core_index; | 83 | std::size_t core_index; |
| 86 | DynarmicExclusiveMonitor& exclusive_monitor; | 84 | DynarmicExclusiveMonitor& exclusive_monitor; |
| 85 | std::shared_ptr<Dynarmic::A32::Jit> jit; | ||
| 87 | }; | 86 | }; |
| 88 | 87 | ||
| 89 | } // namespace Core | 88 | } // namespace Core |
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp index b36b7d918..040529f4d 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | #include "common/assert.h" | 9 | #include "common/assert.h" |
| 10 | #include "common/logging/log.h" | 10 | #include "common/logging/log.h" |
| 11 | #include "common/page_table.h" | 11 | #include "common/page_table.h" |
| 12 | #include "common/settings.h" | ||
| 12 | #include "core/arm/cpu_interrupt_handler.h" | 13 | #include "core/arm/cpu_interrupt_handler.h" |
| 13 | #include "core/arm/dynarmic/arm_dynarmic_64.h" | 14 | #include "core/arm/dynarmic/arm_dynarmic_64.h" |
| 14 | #include "core/arm/dynarmic/arm_exclusive_monitor.h" | 15 | #include "core/arm/dynarmic/arm_exclusive_monitor.h" |
| @@ -19,7 +20,6 @@ | |||
| 19 | #include "core/hle/kernel/process.h" | 20 | #include "core/hle/kernel/process.h" |
| 20 | #include "core/hle/kernel/svc.h" | 21 | #include "core/hle/kernel/svc.h" |
| 21 | #include "core/memory.h" | 22 | #include "core/memory.h" |
| 22 | #include "core/settings.h" | ||
| 23 | 23 | ||
| 24 | namespace Core { | 24 | namespace Core { |
| 25 | 25 | ||
| @@ -142,7 +142,7 @@ public: | |||
| 142 | static constexpr u64 minimum_run_cycles = 1000U; | 142 | static constexpr u64 minimum_run_cycles = 1000U; |
| 143 | }; | 143 | }; |
| 144 | 144 | ||
| 145 | std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable& page_table, | 145 | std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable* page_table, |
| 146 | std::size_t address_space_bits) const { | 146 | std::size_t address_space_bits) const { |
| 147 | Dynarmic::A64::UserConfig config; | 147 | Dynarmic::A64::UserConfig config; |
| 148 | 148 | ||
| @@ -150,13 +150,15 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable& | |||
| 150 | config.callbacks = cb.get(); | 150 | config.callbacks = cb.get(); |
| 151 | 151 | ||
| 152 | // Memory | 152 | // Memory |
| 153 | config.page_table = reinterpret_cast<void**>(page_table.pointers.data()); | 153 | if (page_table) { |
| 154 | config.page_table_address_space_bits = address_space_bits; | 154 | config.page_table = reinterpret_cast<void**>(page_table->pointers.data()); |
| 155 | config.page_table_pointer_mask_bits = Common::PageTable::ATTRIBUTE_BITS; | 155 | config.page_table_address_space_bits = address_space_bits; |
| 156 | config.silently_mirror_page_table = false; | 156 | config.page_table_pointer_mask_bits = Common::PageTable::ATTRIBUTE_BITS; |
| 157 | config.absolute_offset_page_table = true; | 157 | config.silently_mirror_page_table = false; |
| 158 | config.detect_misaligned_access_via_page_table = 16 | 32 | 64 | 128; | 158 | config.absolute_offset_page_table = true; |
| 159 | config.only_detect_misalignment_via_page_table_on_page_boundary = true; | 159 | config.detect_misaligned_access_via_page_table = 16 | 32 | 64 | 128; |
| 160 | config.only_detect_misalignment_via_page_table_on_page_boundary = true; | ||
| 161 | } | ||
| 160 | 162 | ||
| 161 | // Multi-process state | 163 | // Multi-process state |
| 162 | config.processor_id = core_index; | 164 | config.processor_id = core_index; |
| @@ -175,6 +177,10 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable& | |||
| 175 | // Timing | 177 | // Timing |
| 176 | config.wall_clock_cntpct = uses_wall_clock; | 178 | config.wall_clock_cntpct = uses_wall_clock; |
| 177 | 179 | ||
| 180 | // Code cache size | ||
| 181 | config.code_cache_size = 512 * 1024 * 1024; | ||
| 182 | config.far_code_offset = 256 * 1024 * 1024; | ||
| 183 | |||
| 178 | // Safe optimizations | 184 | // Safe optimizations |
| 179 | if (Settings::values.cpu_accuracy == Settings::CPUAccuracy::DebugMode) { | 185 | if (Settings::values.cpu_accuracy == Settings::CPUAccuracy::DebugMode) { |
| 180 | if (!Settings::values.cpuopt_page_tables) { | 186 | if (!Settings::values.cpuopt_page_tables) { |
| @@ -237,7 +243,8 @@ ARM_Dynarmic_64::ARM_Dynarmic_64(System& system, CPUInterrupts& interrupt_handle | |||
| 237 | std::size_t core_index) | 243 | std::size_t core_index) |
| 238 | : ARM_Interface{system, interrupt_handlers, uses_wall_clock}, | 244 | : ARM_Interface{system, interrupt_handlers, uses_wall_clock}, |
| 239 | cb(std::make_unique<DynarmicCallbacks64>(*this)), core_index{core_index}, | 245 | cb(std::make_unique<DynarmicCallbacks64>(*this)), core_index{core_index}, |
| 240 | exclusive_monitor{dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor)} {} | 246 | exclusive_monitor{dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor)}, |
| 247 | jit(MakeJit(nullptr, 48)) {} | ||
| 241 | 248 | ||
| 242 | ARM_Dynarmic_64::~ARM_Dynarmic_64() = default; | 249 | ARM_Dynarmic_64::~ARM_Dynarmic_64() = default; |
| 243 | 250 | ||
| @@ -294,9 +301,6 @@ void ARM_Dynarmic_64::ChangeProcessorID(std::size_t new_core_id) { | |||
| 294 | } | 301 | } |
| 295 | 302 | ||
| 296 | void ARM_Dynarmic_64::SaveContext(ThreadContext64& ctx) { | 303 | void ARM_Dynarmic_64::SaveContext(ThreadContext64& ctx) { |
| 297 | if (!jit) { | ||
| 298 | return; | ||
| 299 | } | ||
| 300 | ctx.cpu_registers = jit->GetRegisters(); | 304 | ctx.cpu_registers = jit->GetRegisters(); |
| 301 | ctx.sp = jit->GetSP(); | 305 | ctx.sp = jit->GetSP(); |
| 302 | ctx.pc = jit->GetPC(); | 306 | ctx.pc = jit->GetPC(); |
| @@ -308,9 +312,6 @@ void ARM_Dynarmic_64::SaveContext(ThreadContext64& ctx) { | |||
| 308 | } | 312 | } |
| 309 | 313 | ||
| 310 | void ARM_Dynarmic_64::LoadContext(const ThreadContext64& ctx) { | 314 | void ARM_Dynarmic_64::LoadContext(const ThreadContext64& ctx) { |
| 311 | if (!jit) { | ||
| 312 | return; | ||
| 313 | } | ||
| 314 | jit->SetRegisters(ctx.cpu_registers); | 315 | jit->SetRegisters(ctx.cpu_registers); |
| 315 | jit->SetSP(ctx.sp); | 316 | jit->SetSP(ctx.sp); |
| 316 | jit->SetPC(ctx.pc); | 317 | jit->SetPC(ctx.pc); |
| @@ -326,23 +327,14 @@ void ARM_Dynarmic_64::PrepareReschedule() { | |||
| 326 | } | 327 | } |
| 327 | 328 | ||
| 328 | void ARM_Dynarmic_64::ClearInstructionCache() { | 329 | void ARM_Dynarmic_64::ClearInstructionCache() { |
| 329 | if (!jit) { | ||
| 330 | return; | ||
| 331 | } | ||
| 332 | jit->ClearCache(); | 330 | jit->ClearCache(); |
| 333 | } | 331 | } |
| 334 | 332 | ||
| 335 | void ARM_Dynarmic_64::InvalidateCacheRange(VAddr addr, std::size_t size) { | 333 | void ARM_Dynarmic_64::InvalidateCacheRange(VAddr addr, std::size_t size) { |
| 336 | if (!jit) { | ||
| 337 | return; | ||
| 338 | } | ||
| 339 | jit->InvalidateCacheRange(addr, size); | 334 | jit->InvalidateCacheRange(addr, size); |
| 340 | } | 335 | } |
| 341 | 336 | ||
| 342 | void ARM_Dynarmic_64::ClearExclusiveState() { | 337 | void ARM_Dynarmic_64::ClearExclusiveState() { |
| 343 | if (!jit) { | ||
| 344 | return; | ||
| 345 | } | ||
| 346 | jit->ClearExclusiveState(); | 338 | jit->ClearExclusiveState(); |
| 347 | } | 339 | } |
| 348 | 340 | ||
| @@ -358,7 +350,7 @@ void ARM_Dynarmic_64::PageTableChanged(Common::PageTable& page_table, | |||
| 358 | LoadContext(ctx); | 350 | LoadContext(ctx); |
| 359 | return; | 351 | return; |
| 360 | } | 352 | } |
| 361 | jit = MakeJit(page_table, new_address_space_size_in_bits); | 353 | jit = MakeJit(&page_table, new_address_space_size_in_bits); |
| 362 | LoadContext(ctx); | 354 | LoadContext(ctx); |
| 363 | jit_cache.emplace(key, jit); | 355 | jit_cache.emplace(key, jit); |
| 364 | } | 356 | } |
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.h b/src/core/arm/dynarmic/arm_dynarmic_64.h index 329b59a32..edef04376 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.h +++ b/src/core/arm/dynarmic/arm_dynarmic_64.h | |||
| @@ -61,7 +61,7 @@ public: | |||
| 61 | std::size_t new_address_space_size_in_bits) override; | 61 | std::size_t new_address_space_size_in_bits) override; |
| 62 | 62 | ||
| 63 | private: | 63 | private: |
| 64 | std::shared_ptr<Dynarmic::A64::Jit> MakeJit(Common::PageTable& page_table, | 64 | std::shared_ptr<Dynarmic::A64::Jit> MakeJit(Common::PageTable* page_table, |
| 65 | std::size_t address_space_bits) const; | 65 | std::size_t address_space_bits) const; |
| 66 | 66 | ||
| 67 | using JitCacheKey = std::pair<Common::PageTable*, std::size_t>; | 67 | using JitCacheKey = std::pair<Common::PageTable*, std::size_t>; |
| @@ -71,10 +71,11 @@ private: | |||
| 71 | friend class DynarmicCallbacks64; | 71 | friend class DynarmicCallbacks64; |
| 72 | std::unique_ptr<DynarmicCallbacks64> cb; | 72 | std::unique_ptr<DynarmicCallbacks64> cb; |
| 73 | JitCacheType jit_cache; | 73 | JitCacheType jit_cache; |
| 74 | std::shared_ptr<Dynarmic::A64::Jit> jit; | ||
| 75 | 74 | ||
| 76 | std::size_t core_index; | 75 | std::size_t core_index; |
| 77 | DynarmicExclusiveMonitor& exclusive_monitor; | 76 | DynarmicExclusiveMonitor& exclusive_monitor; |
| 77 | |||
| 78 | std::shared_ptr<Dynarmic::A64::Jit> jit; | ||
| 78 | }; | 79 | }; |
| 79 | 80 | ||
| 80 | } // namespace Core | 81 | } // namespace Core |
diff --git a/src/core/core.cpp b/src/core/core.cpp index 305f56ff1..d459d6c34 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | #include "common/file_util.h" | 9 | #include "common/file_util.h" |
| 10 | #include "common/logging/log.h" | 10 | #include "common/logging/log.h" |
| 11 | #include "common/microprofile.h" | 11 | #include "common/microprofile.h" |
| 12 | #include "common/settings.h" | ||
| 12 | #include "common/string_util.h" | 13 | #include "common/string_util.h" |
| 13 | #include "core/arm/exclusive_monitor.h" | 14 | #include "core/arm/exclusive_monitor.h" |
| 14 | #include "core/core.h" | 15 | #include "core/core.h" |
| @@ -36,6 +37,7 @@ | |||
| 36 | #include "core/hle/service/apm/controller.h" | 37 | #include "core/hle/service/apm/controller.h" |
| 37 | #include "core/hle/service/filesystem/filesystem.h" | 38 | #include "core/hle/service/filesystem/filesystem.h" |
| 38 | #include "core/hle/service/glue/manager.h" | 39 | #include "core/hle/service/glue/manager.h" |
| 40 | #include "core/hle/service/hid/hid.h" | ||
| 39 | #include "core/hle/service/service.h" | 41 | #include "core/hle/service/service.h" |
| 40 | #include "core/hle/service/sm/sm.h" | 42 | #include "core/hle/service/sm/sm.h" |
| 41 | #include "core/hle/service/time/time_manager.h" | 43 | #include "core/hle/service/time/time_manager.h" |
| @@ -45,7 +47,6 @@ | |||
| 45 | #include "core/network/network.h" | 47 | #include "core/network/network.h" |
| 46 | #include "core/perf_stats.h" | 48 | #include "core/perf_stats.h" |
| 47 | #include "core/reporter.h" | 49 | #include "core/reporter.h" |
| 48 | #include "core/settings.h" | ||
| 49 | #include "core/telemetry_session.h" | 50 | #include "core/telemetry_session.h" |
| 50 | #include "core/tools/freezer.h" | 51 | #include "core/tools/freezer.h" |
| 51 | #include "video_core/renderer_base.h" | 52 | #include "video_core/renderer_base.h" |
| @@ -296,7 +297,7 @@ struct System::Impl { | |||
| 296 | exit_lock = false; | 297 | exit_lock = false; |
| 297 | 298 | ||
| 298 | if (gpu_core) { | 299 | if (gpu_core) { |
| 299 | gpu_core->WaitIdle(); | 300 | gpu_core->ShutDown(); |
| 300 | } | 301 | } |
| 301 | 302 | ||
| 302 | services.reset(); | 303 | services.reset(); |
| @@ -774,4 +775,12 @@ void System::ExecuteProgram(std::size_t program_index) { | |||
| 774 | } | 775 | } |
| 775 | } | 776 | } |
| 776 | 777 | ||
| 778 | void System::ApplySettings() { | ||
| 779 | if (IsPoweredOn()) { | ||
| 780 | Renderer().RefreshBaseSettings(); | ||
| 781 | } | ||
| 782 | |||
| 783 | Service::HID::ReloadInputDevices(); | ||
| 784 | } | ||
| 785 | |||
| 777 | } // namespace Core | 786 | } // namespace Core |
diff --git a/src/core/core.h b/src/core/core.h index 3a8e040c1..f1068d23f 100644 --- a/src/core/core.h +++ b/src/core/core.h | |||
| @@ -388,6 +388,9 @@ public: | |||
| 388 | */ | 388 | */ |
| 389 | void ExecuteProgram(std::size_t program_index); | 389 | void ExecuteProgram(std::size_t program_index); |
| 390 | 390 | ||
| 391 | /// Applies any changes to settings to this core instance. | ||
| 392 | void ApplySettings(); | ||
| 393 | |||
| 391 | private: | 394 | private: |
| 392 | System(); | 395 | System(); |
| 393 | 396 | ||
diff --git a/src/core/crypto/key_manager.cpp b/src/core/crypto/key_manager.cpp index ad116dcc0..070ed439e 100644 --- a/src/core/crypto/key_manager.cpp +++ b/src/core/crypto/key_manager.cpp | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #include "common/file_util.h" | 22 | #include "common/file_util.h" |
| 23 | #include "common/hex_util.h" | 23 | #include "common/hex_util.h" |
| 24 | #include "common/logging/log.h" | 24 | #include "common/logging/log.h" |
| 25 | #include "common/settings.h" | ||
| 25 | #include "common/string_util.h" | 26 | #include "common/string_util.h" |
| 26 | #include "core/crypto/aes_util.h" | 27 | #include "core/crypto/aes_util.h" |
| 27 | #include "core/crypto/key_manager.h" | 28 | #include "core/crypto/key_manager.h" |
| @@ -32,7 +33,6 @@ | |||
| 32 | #include "core/file_sys/registered_cache.h" | 33 | #include "core/file_sys/registered_cache.h" |
| 33 | #include "core/hle/service/filesystem/filesystem.h" | 34 | #include "core/hle/service/filesystem/filesystem.h" |
| 34 | #include "core/loader/loader.h" | 35 | #include "core/loader/loader.h" |
| 35 | #include "core/settings.h" | ||
| 36 | 36 | ||
| 37 | namespace Core::Crypto { | 37 | namespace Core::Crypto { |
| 38 | namespace { | 38 | namespace { |
diff --git a/src/core/file_sys/control_metadata.cpp b/src/core/file_sys/control_metadata.cpp index b0a130345..f66759815 100644 --- a/src/core/file_sys/control_metadata.cpp +++ b/src/core/file_sys/control_metadata.cpp | |||
| @@ -100,6 +100,14 @@ u64 NACP::GetDeviceSaveDataSize() const { | |||
| 100 | return raw.device_save_data_size; | 100 | return raw.device_save_data_size; |
| 101 | } | 101 | } |
| 102 | 102 | ||
| 103 | u32 NACP::GetParentalControlFlag() const { | ||
| 104 | return raw.parental_control; | ||
| 105 | } | ||
| 106 | |||
| 107 | const std::array<u8, 0x20>& NACP::GetRatingAge() const { | ||
| 108 | return raw.rating_age; | ||
| 109 | } | ||
| 110 | |||
| 103 | std::vector<u8> NACP::GetRawBytes() const { | 111 | std::vector<u8> NACP::GetRawBytes() const { |
| 104 | std::vector<u8> out(sizeof(RawNACP)); | 112 | std::vector<u8> out(sizeof(RawNACP)); |
| 105 | std::memcpy(out.data(), &raw, sizeof(RawNACP)); | 113 | std::memcpy(out.data(), &raw, sizeof(RawNACP)); |
diff --git a/src/core/file_sys/control_metadata.h b/src/core/file_sys/control_metadata.h index 403c4219a..dd9837cf5 100644 --- a/src/core/file_sys/control_metadata.h +++ b/src/core/file_sys/control_metadata.h | |||
| @@ -114,6 +114,8 @@ public: | |||
| 114 | std::vector<u8> GetRawBytes() const; | 114 | std::vector<u8> GetRawBytes() const; |
| 115 | bool GetUserAccountSwitchLock() const; | 115 | bool GetUserAccountSwitchLock() const; |
| 116 | u64 GetDeviceSaveDataSize() const; | 116 | u64 GetDeviceSaveDataSize() const; |
| 117 | u32 GetParentalControlFlag() const; | ||
| 118 | const std::array<u8, 0x20>& GetRatingAge() const; | ||
| 117 | 119 | ||
| 118 | private: | 120 | private: |
| 119 | RawNACP raw{}; | 121 | RawNACP raw{}; |
diff --git a/src/core/file_sys/patch_manager.cpp b/src/core/file_sys/patch_manager.cpp index 7c3284df8..cc9b4b637 100644 --- a/src/core/file_sys/patch_manager.cpp +++ b/src/core/file_sys/patch_manager.cpp | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | #include "common/file_util.h" | 10 | #include "common/file_util.h" |
| 11 | #include "common/hex_util.h" | 11 | #include "common/hex_util.h" |
| 12 | #include "common/logging/log.h" | 12 | #include "common/logging/log.h" |
| 13 | #include "common/settings.h" | ||
| 13 | #include "common/string_util.h" | 14 | #include "common/string_util.h" |
| 14 | #include "core/core.h" | 15 | #include "core/core.h" |
| 15 | #include "core/file_sys/common_funcs.h" | 16 | #include "core/file_sys/common_funcs.h" |
| @@ -25,7 +26,6 @@ | |||
| 25 | #include "core/loader/loader.h" | 26 | #include "core/loader/loader.h" |
| 26 | #include "core/loader/nso.h" | 27 | #include "core/loader/nso.h" |
| 27 | #include "core/memory/cheat_engine.h" | 28 | #include "core/memory/cheat_engine.h" |
| 28 | #include "core/settings.h" | ||
| 29 | 29 | ||
| 30 | namespace FileSys { | 30 | namespace FileSys { |
| 31 | namespace { | 31 | namespace { |
diff --git a/src/core/frontend/applets/profile_select.cpp b/src/core/frontend/applets/profile_select.cpp index 4df3574d2..8d960d1ca 100644 --- a/src/core/frontend/applets/profile_select.cpp +++ b/src/core/frontend/applets/profile_select.cpp | |||
| @@ -2,9 +2,9 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include "common/settings.h" | ||
| 5 | #include "core/frontend/applets/profile_select.h" | 6 | #include "core/frontend/applets/profile_select.h" |
| 6 | #include "core/hle/service/acc/profile_manager.h" | 7 | #include "core/hle/service/acc/profile_manager.h" |
| 7 | #include "core/settings.h" | ||
| 8 | 8 | ||
| 9 | namespace Core::Frontend { | 9 | namespace Core::Frontend { |
| 10 | 10 | ||
diff --git a/src/core/frontend/applets/software_keyboard.cpp b/src/core/frontend/applets/software_keyboard.cpp index 856ed33da..12c76c9ee 100644 --- a/src/core/frontend/applets/software_keyboard.cpp +++ b/src/core/frontend/applets/software_keyboard.cpp | |||
| @@ -1,29 +1,149 @@ | |||
| 1 | // Copyright 2018 yuzu emulator team | 1 | // Copyright 2021 yuzu Emulator Project |
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include "common/logging/backend.h" | 5 | #include <thread> |
| 6 | |||
| 7 | #include "common/logging/log.h" | ||
| 6 | #include "common/string_util.h" | 8 | #include "common/string_util.h" |
| 7 | #include "core/frontend/applets/software_keyboard.h" | 9 | #include "core/frontend/applets/software_keyboard.h" |
| 8 | 10 | ||
| 9 | namespace Core::Frontend { | 11 | namespace Core::Frontend { |
| 12 | |||
| 10 | SoftwareKeyboardApplet::~SoftwareKeyboardApplet() = default; | 13 | SoftwareKeyboardApplet::~SoftwareKeyboardApplet() = default; |
| 11 | 14 | ||
| 12 | void DefaultSoftwareKeyboardApplet::RequestText( | 15 | DefaultSoftwareKeyboardApplet::~DefaultSoftwareKeyboardApplet() = default; |
| 13 | std::function<void(std::optional<std::u16string>)> out, | 16 | |
| 14 | SoftwareKeyboardParameters parameters) const { | 17 | void DefaultSoftwareKeyboardApplet::InitializeKeyboard( |
| 15 | if (parameters.initial_text.empty()) | 18 | bool is_inline, KeyboardInitializeParameters initialize_parameters, |
| 16 | out(u"yuzu"); | 19 | std::function<void(Service::AM::Applets::SwkbdResult, std::u16string)> submit_normal_callback_, |
| 20 | std::function<void(Service::AM::Applets::SwkbdReplyType, std::u16string, s32)> | ||
| 21 | submit_inline_callback_) { | ||
| 22 | if (is_inline) { | ||
| 23 | LOG_WARNING( | ||
| 24 | Service_AM, | ||
| 25 | "(STUBBED) called, backend requested to initialize the inline software keyboard."); | ||
| 26 | |||
| 27 | submit_inline_callback = std::move(submit_inline_callback_); | ||
| 28 | } else { | ||
| 29 | LOG_WARNING( | ||
| 30 | Service_AM, | ||
| 31 | "(STUBBED) called, backend requested to initialize the normal software keyboard."); | ||
| 32 | |||
| 33 | submit_normal_callback = std::move(submit_normal_callback_); | ||
| 34 | } | ||
| 35 | |||
| 36 | parameters = std::move(initialize_parameters); | ||
| 37 | |||
| 38 | LOG_INFO(Service_AM, | ||
| 39 | "\nKeyboardInitializeParameters:" | ||
| 40 | "\nok_text={}" | ||
| 41 | "\nheader_text={}" | ||
| 42 | "\nsub_text={}" | ||
| 43 | "\nguide_text={}" | ||
| 44 | "\ninitial_text={}" | ||
| 45 | "\nmax_text_length={}" | ||
| 46 | "\nmin_text_length={}" | ||
| 47 | "\ninitial_cursor_position={}" | ||
| 48 | "\ntype={}" | ||
| 49 | "\npassword_mode={}" | ||
| 50 | "\ntext_draw_type={}" | ||
| 51 | "\nkey_disable_flags={}" | ||
| 52 | "\nuse_blur_background={}" | ||
| 53 | "\nenable_backspace_button={}" | ||
| 54 | "\nenable_return_button={}" | ||
| 55 | "\ndisable_cancel_button={}", | ||
| 56 | Common::UTF16ToUTF8(parameters.ok_text), Common::UTF16ToUTF8(parameters.header_text), | ||
| 57 | Common::UTF16ToUTF8(parameters.sub_text), Common::UTF16ToUTF8(parameters.guide_text), | ||
| 58 | Common::UTF16ToUTF8(parameters.initial_text), parameters.max_text_length, | ||
| 59 | parameters.min_text_length, parameters.initial_cursor_position, parameters.type, | ||
| 60 | parameters.password_mode, parameters.text_draw_type, parameters.key_disable_flags.raw, | ||
| 61 | parameters.use_blur_background, parameters.enable_backspace_button, | ||
| 62 | parameters.enable_return_button, parameters.disable_cancel_button); | ||
| 63 | } | ||
| 64 | |||
| 65 | void DefaultSoftwareKeyboardApplet::ShowNormalKeyboard() const { | ||
| 66 | LOG_WARNING(Service_AM, | ||
| 67 | "(STUBBED) called, backend requested to show the normal software keyboard."); | ||
| 68 | |||
| 69 | SubmitNormalText(u"yuzu"); | ||
| 70 | } | ||
| 71 | |||
| 72 | void DefaultSoftwareKeyboardApplet::ShowTextCheckDialog( | ||
| 73 | Service::AM::Applets::SwkbdTextCheckResult text_check_result, | ||
| 74 | std::u16string text_check_message) const { | ||
| 75 | LOG_WARNING(Service_AM, "(STUBBED) called, backend requested to show the text check dialog."); | ||
| 76 | } | ||
| 77 | |||
| 78 | void DefaultSoftwareKeyboardApplet::ShowInlineKeyboard( | ||
| 79 | InlineAppearParameters appear_parameters) const { | ||
| 80 | LOG_WARNING(Service_AM, | ||
| 81 | "(STUBBED) called, backend requested to show the inline software keyboard."); | ||
| 82 | |||
| 83 | LOG_INFO(Service_AM, | ||
| 84 | "\nInlineAppearParameters:" | ||
| 85 | "\nmax_text_length={}" | ||
| 86 | "\nmin_text_length={}" | ||
| 87 | "\nkey_top_scale_x={}" | ||
| 88 | "\nkey_top_scale_y={}" | ||
| 89 | "\nkey_top_translate_x={}" | ||
| 90 | "\nkey_top_translate_y={}" | ||
| 91 | "\ntype={}" | ||
| 92 | "\nkey_disable_flags={}" | ||
| 93 | "\nkey_top_as_floating={}" | ||
| 94 | "\nenable_backspace_button={}" | ||
| 95 | "\nenable_return_button={}" | ||
| 96 | "\ndisable_cancel_button={}", | ||
| 97 | appear_parameters.max_text_length, appear_parameters.min_text_length, | ||
| 98 | appear_parameters.key_top_scale_x, appear_parameters.key_top_scale_y, | ||
| 99 | appear_parameters.key_top_translate_x, appear_parameters.key_top_translate_y, | ||
| 100 | appear_parameters.type, appear_parameters.key_disable_flags.raw, | ||
| 101 | appear_parameters.key_top_as_floating, appear_parameters.enable_backspace_button, | ||
| 102 | appear_parameters.enable_return_button, appear_parameters.disable_cancel_button); | ||
| 103 | |||
| 104 | std::thread([this] { SubmitInlineText(u"yuzu"); }).detach(); | ||
| 105 | } | ||
| 17 | 106 | ||
| 18 | out(parameters.initial_text); | 107 | void DefaultSoftwareKeyboardApplet::HideInlineKeyboard() const { |
| 108 | LOG_WARNING(Service_AM, | ||
| 109 | "(STUBBED) called, backend requested to hide the inline software keyboard."); | ||
| 19 | } | 110 | } |
| 20 | 111 | ||
| 21 | void DefaultSoftwareKeyboardApplet::SendTextCheckDialog( | 112 | void DefaultSoftwareKeyboardApplet::InlineTextChanged(InlineTextParameters text_parameters) const { |
| 22 | std::u16string error_message, std::function<void()> finished_check) const { | ||
| 23 | LOG_WARNING(Service_AM, | 113 | LOG_WARNING(Service_AM, |
| 24 | "(STUBBED) called - Default fallback software keyboard does not support text " | 114 | "(STUBBED) called, backend requested to change the inline keyboard text."); |
| 25 | "check! (error_message={})", | 115 | |
| 26 | Common::UTF16ToUTF8(error_message)); | 116 | LOG_INFO(Service_AM, |
| 27 | finished_check(); | 117 | "\nInlineTextParameters:" |
| 118 | "\ninput_text={}" | ||
| 119 | "\ncursor_position={}", | ||
| 120 | Common::UTF16ToUTF8(text_parameters.input_text), text_parameters.cursor_position); | ||
| 121 | |||
| 122 | submit_inline_callback(Service::AM::Applets::SwkbdReplyType::ChangedString, | ||
| 123 | text_parameters.input_text, text_parameters.cursor_position); | ||
| 124 | } | ||
| 125 | |||
| 126 | void DefaultSoftwareKeyboardApplet::ExitKeyboard() const { | ||
| 127 | LOG_WARNING(Service_AM, "(STUBBED) called, backend requested to exit the software keyboard."); | ||
| 28 | } | 128 | } |
| 129 | |||
| 130 | void DefaultSoftwareKeyboardApplet::SubmitNormalText(std::u16string text) const { | ||
| 131 | submit_normal_callback(Service::AM::Applets::SwkbdResult::Ok, text); | ||
| 132 | } | ||
| 133 | |||
| 134 | void DefaultSoftwareKeyboardApplet::SubmitInlineText(std::u16string_view text) const { | ||
| 135 | std::this_thread::sleep_for(std::chrono::milliseconds(500)); | ||
| 136 | |||
| 137 | for (std::size_t index = 0; index < text.size(); ++index) { | ||
| 138 | submit_inline_callback(Service::AM::Applets::SwkbdReplyType::ChangedString, | ||
| 139 | std::u16string(text.data(), text.data() + index + 1), | ||
| 140 | static_cast<s32>(index) + 1); | ||
| 141 | |||
| 142 | std::this_thread::sleep_for(std::chrono::milliseconds(250)); | ||
| 143 | } | ||
| 144 | |||
| 145 | submit_inline_callback(Service::AM::Applets::SwkbdReplyType::DecidedEnter, std::u16string(text), | ||
| 146 | static_cast<s32>(text.size())); | ||
| 147 | } | ||
| 148 | |||
| 29 | } // namespace Core::Frontend | 149 | } // namespace Core::Frontend |
diff --git a/src/core/frontend/applets/software_keyboard.h b/src/core/frontend/applets/software_keyboard.h index f9b202664..506eb35bb 100644 --- a/src/core/frontend/applets/software_keyboard.h +++ b/src/core/frontend/applets/software_keyboard.h | |||
| @@ -1,54 +1,116 @@ | |||
| 1 | // Copyright 2018 yuzu emulator team | 1 | // Copyright 2021 yuzu Emulator Project |
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <functional> | 7 | #include <functional> |
| 8 | #include <optional> | 8 | #include <thread> |
| 9 | #include <string> | 9 | |
| 10 | #include "common/bit_field.h" | ||
| 11 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 12 | 11 | ||
| 12 | #include "core/hle/service/am/applets/software_keyboard_types.h" | ||
| 13 | |||
| 13 | namespace Core::Frontend { | 14 | namespace Core::Frontend { |
| 14 | struct SoftwareKeyboardParameters { | 15 | |
| 15 | std::u16string submit_text; | 16 | struct KeyboardInitializeParameters { |
| 17 | std::u16string ok_text; | ||
| 16 | std::u16string header_text; | 18 | std::u16string header_text; |
| 17 | std::u16string sub_text; | 19 | std::u16string sub_text; |
| 18 | std::u16string guide_text; | 20 | std::u16string guide_text; |
| 19 | std::u16string initial_text; | 21 | std::u16string initial_text; |
| 20 | std::size_t max_length; | 22 | u32 max_text_length; |
| 21 | bool password; | 23 | u32 min_text_length; |
| 22 | bool cursor_at_beginning; | 24 | s32 initial_cursor_position; |
| 23 | 25 | Service::AM::Applets::SwkbdType type; | |
| 24 | union { | 26 | Service::AM::Applets::SwkbdPasswordMode password_mode; |
| 25 | u8 value; | 27 | Service::AM::Applets::SwkbdTextDrawType text_draw_type; |
| 26 | 28 | Service::AM::Applets::SwkbdKeyDisableFlags key_disable_flags; | |
| 27 | BitField<1, 1, u8> disable_space; | 29 | bool use_blur_background; |
| 28 | BitField<2, 1, u8> disable_address; | 30 | bool enable_backspace_button; |
| 29 | BitField<3, 1, u8> disable_percent; | 31 | bool enable_return_button; |
| 30 | BitField<4, 1, u8> disable_slash; | 32 | bool disable_cancel_button; |
| 31 | BitField<6, 1, u8> disable_number; | 33 | }; |
| 32 | BitField<7, 1, u8> disable_download_code; | 34 | |
| 33 | }; | 35 | struct InlineAppearParameters { |
| 36 | u32 max_text_length; | ||
| 37 | u32 min_text_length; | ||
| 38 | f32 key_top_scale_x; | ||
| 39 | f32 key_top_scale_y; | ||
| 40 | f32 key_top_translate_x; | ||
| 41 | f32 key_top_translate_y; | ||
| 42 | Service::AM::Applets::SwkbdType type; | ||
| 43 | Service::AM::Applets::SwkbdKeyDisableFlags key_disable_flags; | ||
| 44 | bool key_top_as_floating; | ||
| 45 | bool enable_backspace_button; | ||
| 46 | bool enable_return_button; | ||
| 47 | bool disable_cancel_button; | ||
| 48 | }; | ||
| 49 | |||
| 50 | struct InlineTextParameters { | ||
| 51 | std::u16string input_text; | ||
| 52 | s32 cursor_position; | ||
| 34 | }; | 53 | }; |
| 35 | 54 | ||
| 36 | class SoftwareKeyboardApplet { | 55 | class SoftwareKeyboardApplet { |
| 37 | public: | 56 | public: |
| 38 | virtual ~SoftwareKeyboardApplet(); | 57 | virtual ~SoftwareKeyboardApplet(); |
| 39 | 58 | ||
| 40 | virtual void RequestText(std::function<void(std::optional<std::u16string>)> out, | 59 | virtual void InitializeKeyboard( |
| 41 | SoftwareKeyboardParameters parameters) const = 0; | 60 | bool is_inline, KeyboardInitializeParameters initialize_parameters, |
| 42 | virtual void SendTextCheckDialog(std::u16string error_message, | 61 | std::function<void(Service::AM::Applets::SwkbdResult, std::u16string)> |
| 43 | std::function<void()> finished_check) const = 0; | 62 | submit_normal_callback_, |
| 63 | std::function<void(Service::AM::Applets::SwkbdReplyType, std::u16string, s32)> | ||
| 64 | submit_inline_callback_) = 0; | ||
| 65 | |||
| 66 | virtual void ShowNormalKeyboard() const = 0; | ||
| 67 | |||
| 68 | virtual void ShowTextCheckDialog(Service::AM::Applets::SwkbdTextCheckResult text_check_result, | ||
| 69 | std::u16string text_check_message) const = 0; | ||
| 70 | |||
| 71 | virtual void ShowInlineKeyboard(InlineAppearParameters appear_parameters) const = 0; | ||
| 72 | |||
| 73 | virtual void HideInlineKeyboard() const = 0; | ||
| 74 | |||
| 75 | virtual void InlineTextChanged(InlineTextParameters text_parameters) const = 0; | ||
| 76 | |||
| 77 | virtual void ExitKeyboard() const = 0; | ||
| 44 | }; | 78 | }; |
| 45 | 79 | ||
| 46 | class DefaultSoftwareKeyboardApplet final : public SoftwareKeyboardApplet { | 80 | class DefaultSoftwareKeyboardApplet final : public SoftwareKeyboardApplet { |
| 47 | public: | 81 | public: |
| 48 | void RequestText(std::function<void(std::optional<std::u16string>)> out, | 82 | ~DefaultSoftwareKeyboardApplet() override; |
| 49 | SoftwareKeyboardParameters parameters) const override; | 83 | |
| 50 | void SendTextCheckDialog(std::u16string error_message, | 84 | void InitializeKeyboard( |
| 51 | std::function<void()> finished_check) const override; | 85 | bool is_inline, KeyboardInitializeParameters initialize_parameters, |
| 86 | std::function<void(Service::AM::Applets::SwkbdResult, std::u16string)> | ||
| 87 | submit_normal_callback_, | ||
| 88 | std::function<void(Service::AM::Applets::SwkbdReplyType, std::u16string, s32)> | ||
| 89 | submit_inline_callback_) override; | ||
| 90 | |||
| 91 | void ShowNormalKeyboard() const override; | ||
| 92 | |||
| 93 | void ShowTextCheckDialog(Service::AM::Applets::SwkbdTextCheckResult text_check_result, | ||
| 94 | std::u16string text_check_message) const override; | ||
| 95 | |||
| 96 | void ShowInlineKeyboard(InlineAppearParameters appear_parameters) const override; | ||
| 97 | |||
| 98 | void HideInlineKeyboard() const override; | ||
| 99 | |||
| 100 | void InlineTextChanged(InlineTextParameters text_parameters) const override; | ||
| 101 | |||
| 102 | void ExitKeyboard() const override; | ||
| 103 | |||
| 104 | private: | ||
| 105 | void SubmitNormalText(std::u16string text) const; | ||
| 106 | void SubmitInlineText(std::u16string_view text) const; | ||
| 107 | |||
| 108 | KeyboardInitializeParameters parameters; | ||
| 109 | |||
| 110 | mutable std::function<void(Service::AM::Applets::SwkbdResult, std::u16string)> | ||
| 111 | submit_normal_callback; | ||
| 112 | mutable std::function<void(Service::AM::Applets::SwkbdReplyType, std::u16string, s32)> | ||
| 113 | submit_inline_callback; | ||
| 52 | }; | 114 | }; |
| 53 | 115 | ||
| 54 | } // namespace Core::Frontend | 116 | } // namespace Core::Frontend |
diff --git a/src/core/frontend/emu_window.cpp b/src/core/frontend/emu_window.cpp index ee7a58b1c..474de9206 100644 --- a/src/core/frontend/emu_window.cpp +++ b/src/core/frontend/emu_window.cpp | |||
| @@ -4,9 +4,9 @@ | |||
| 4 | 4 | ||
| 5 | #include <cmath> | 5 | #include <cmath> |
| 6 | #include <mutex> | 6 | #include <mutex> |
| 7 | #include "common/settings.h" | ||
| 7 | #include "core/frontend/emu_window.h" | 8 | #include "core/frontend/emu_window.h" |
| 8 | #include "core/frontend/input.h" | 9 | #include "core/frontend/input.h" |
| 9 | #include "core/settings.h" | ||
| 10 | 10 | ||
| 11 | namespace Core::Frontend { | 11 | namespace Core::Frontend { |
| 12 | 12 | ||
diff --git a/src/core/frontend/framebuffer_layout.cpp b/src/core/frontend/framebuffer_layout.cpp index b9a270a55..0832463d6 100644 --- a/src/core/frontend/framebuffer_layout.cpp +++ b/src/core/frontend/framebuffer_layout.cpp | |||
| @@ -5,8 +5,8 @@ | |||
| 5 | #include <cmath> | 5 | #include <cmath> |
| 6 | 6 | ||
| 7 | #include "common/assert.h" | 7 | #include "common/assert.h" |
| 8 | #include "common/settings.h" | ||
| 8 | #include "core/frontend/framebuffer_layout.h" | 9 | #include "core/frontend/framebuffer_layout.h" |
| 9 | #include "core/settings.h" | ||
| 10 | 10 | ||
| 11 | namespace Layout { | 11 | namespace Layout { |
| 12 | 12 | ||
diff --git a/src/core/frontend/input_interpreter.cpp b/src/core/frontend/input_interpreter.cpp index ec5fe660e..9f6a90e8f 100644 --- a/src/core/frontend/input_interpreter.cpp +++ b/src/core/frontend/input_interpreter.cpp | |||
| @@ -12,7 +12,9 @@ InputInterpreter::InputInterpreter(Core::System& system) | |||
| 12 | : npad{system.ServiceManager() | 12 | : npad{system.ServiceManager() |
| 13 | .GetService<Service::HID::Hid>("hid") | 13 | .GetService<Service::HID::Hid>("hid") |
| 14 | ->GetAppletResource() | 14 | ->GetAppletResource() |
| 15 | ->GetController<Service::HID::Controller_NPad>(Service::HID::HidController::NPad)} {} | 15 | ->GetController<Service::HID::Controller_NPad>(Service::HID::HidController::NPad)} { |
| 16 | ResetButtonStates(); | ||
| 17 | } | ||
| 16 | 18 | ||
| 17 | InputInterpreter::~InputInterpreter() = default; | 19 | InputInterpreter::~InputInterpreter() = default; |
| 18 | 20 | ||
| @@ -25,6 +27,17 @@ void InputInterpreter::PollInput() { | |||
| 25 | button_states[current_index] = button_state; | 27 | button_states[current_index] = button_state; |
| 26 | } | 28 | } |
| 27 | 29 | ||
| 30 | void InputInterpreter::ResetButtonStates() { | ||
| 31 | previous_index = 0; | ||
| 32 | current_index = 0; | ||
| 33 | |||
| 34 | button_states[0] = 0xFFFFFFFF; | ||
| 35 | |||
| 36 | for (std::size_t i = 1; i < button_states.size(); ++i) { | ||
| 37 | button_states[i] = 0; | ||
| 38 | } | ||
| 39 | } | ||
| 40 | |||
| 28 | bool InputInterpreter::IsButtonPressed(HIDButton button) const { | 41 | bool InputInterpreter::IsButtonPressed(HIDButton button) const { |
| 29 | return (button_states[current_index] & (1U << static_cast<u8>(button))) != 0; | 42 | return (button_states[current_index] & (1U << static_cast<u8>(button))) != 0; |
| 30 | } | 43 | } |
diff --git a/src/core/frontend/input_interpreter.h b/src/core/frontend/input_interpreter.h index 73fc47ffb..9495e3daf 100644 --- a/src/core/frontend/input_interpreter.h +++ b/src/core/frontend/input_interpreter.h | |||
| @@ -66,6 +66,9 @@ public: | |||
| 66 | /// Gets a button state from HID and inserts it into the array of button states. | 66 | /// Gets a button state from HID and inserts it into the array of button states. |
| 67 | void PollInput(); | 67 | void PollInput(); |
| 68 | 68 | ||
| 69 | /// Resets all the button states to their defaults. | ||
| 70 | void ResetButtonStates(); | ||
| 71 | |||
| 69 | /** | 72 | /** |
| 70 | * Checks whether the button is pressed. | 73 | * Checks whether the button is pressed. |
| 71 | * | 74 | * |
diff --git a/src/core/hle/kernel/arch/arm64/k_memory_region_device_types.inc b/src/core/hle/kernel/arch/arm64/k_memory_region_device_types.inc new file mode 100644 index 000000000..857b512ba --- /dev/null +++ b/src/core/hle/kernel/arch/arm64/k_memory_region_device_types.inc | |||
| @@ -0,0 +1,20 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | // All architectures must define NumArchitectureDeviceRegions. | ||
| 6 | constexpr inline const auto NumArchitectureDeviceRegions = 3; | ||
| 7 | |||
| 8 | constexpr inline const auto KMemoryRegionType_Uart = | ||
| 9 | KMemoryRegionType_ArchDeviceBase.DeriveSparse(0, NumArchitectureDeviceRegions, 0); | ||
| 10 | constexpr inline const auto KMemoryRegionType_InterruptCpuInterface = | ||
| 11 | KMemoryRegionType_ArchDeviceBase.DeriveSparse(0, NumArchitectureDeviceRegions, 1) | ||
| 12 | .SetAttribute(KMemoryRegionAttr_NoUserMap); | ||
| 13 | constexpr inline const auto KMemoryRegionType_InterruptDistributor = | ||
| 14 | KMemoryRegionType_ArchDeviceBase.DeriveSparse(0, NumArchitectureDeviceRegions, 2) | ||
| 15 | .SetAttribute(KMemoryRegionAttr_NoUserMap); | ||
| 16 | static_assert(KMemoryRegionType_Uart.GetValue() == (0x1D)); | ||
| 17 | static_assert(KMemoryRegionType_InterruptCpuInterface.GetValue() == | ||
| 18 | (0x2D | KMemoryRegionAttr_NoUserMap)); | ||
| 19 | static_assert(KMemoryRegionType_InterruptDistributor.GetValue() == | ||
| 20 | (0x4D | KMemoryRegionAttr_NoUserMap)); | ||
diff --git a/src/core/hle/kernel/board/nintendo/nx/k_memory_region_device_types.inc b/src/core/hle/kernel/board/nintendo/nx/k_memory_region_device_types.inc new file mode 100644 index 000000000..58d6c0b16 --- /dev/null +++ b/src/core/hle/kernel/board/nintendo/nx/k_memory_region_device_types.inc | |||
| @@ -0,0 +1,52 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | // All architectures must define NumBoardDeviceRegions. | ||
| 6 | constexpr inline const auto NumBoardDeviceRegions = 6; | ||
| 7 | // UNUSED: .Derive(NumBoardDeviceRegions, 0); | ||
| 8 | constexpr inline const auto KMemoryRegionType_MemoryController = | ||
| 9 | KMemoryRegionType_BoardDeviceBase.Derive(NumBoardDeviceRegions, 1) | ||
| 10 | .SetAttribute(KMemoryRegionAttr_NoUserMap); | ||
| 11 | constexpr inline const auto KMemoryRegionType_MemoryController1 = | ||
| 12 | KMemoryRegionType_BoardDeviceBase.Derive(NumBoardDeviceRegions, 2) | ||
| 13 | .SetAttribute(KMemoryRegionAttr_NoUserMap); | ||
| 14 | constexpr inline const auto KMemoryRegionType_MemoryController0 = | ||
| 15 | KMemoryRegionType_BoardDeviceBase.Derive(NumBoardDeviceRegions, 3) | ||
| 16 | .SetAttribute(KMemoryRegionAttr_NoUserMap); | ||
| 17 | constexpr inline const auto KMemoryRegionType_PowerManagementController = | ||
| 18 | KMemoryRegionType_BoardDeviceBase.Derive(NumBoardDeviceRegions, 4).DeriveTransition(); | ||
| 19 | constexpr inline const auto KMemoryRegionType_LegacyLpsDevices = | ||
| 20 | KMemoryRegionType_BoardDeviceBase.Derive(NumBoardDeviceRegions, 5); | ||
| 21 | static_assert(KMemoryRegionType_MemoryController.GetValue() == | ||
| 22 | (0x55 | KMemoryRegionAttr_NoUserMap)); | ||
| 23 | static_assert(KMemoryRegionType_MemoryController1.GetValue() == | ||
| 24 | (0x65 | KMemoryRegionAttr_NoUserMap)); | ||
| 25 | static_assert(KMemoryRegionType_MemoryController0.GetValue() == | ||
| 26 | (0x95 | KMemoryRegionAttr_NoUserMap)); | ||
| 27 | static_assert(KMemoryRegionType_PowerManagementController.GetValue() == (0x1A5)); | ||
| 28 | |||
| 29 | static_assert(KMemoryRegionType_LegacyLpsDevices.GetValue() == 0xC5); | ||
| 30 | |||
| 31 | constexpr inline const auto NumLegacyLpsDevices = 7; | ||
| 32 | constexpr inline const auto KMemoryRegionType_LegacyLpsExceptionVectors = | ||
| 33 | KMemoryRegionType_LegacyLpsDevices.Derive(NumLegacyLpsDevices, 0); | ||
| 34 | constexpr inline const auto KMemoryRegionType_LegacyLpsIram = | ||
| 35 | KMemoryRegionType_LegacyLpsDevices.Derive(NumLegacyLpsDevices, 1); | ||
| 36 | constexpr inline const auto KMemoryRegionType_LegacyLpsFlowController = | ||
| 37 | KMemoryRegionType_LegacyLpsDevices.Derive(NumLegacyLpsDevices, 2); | ||
| 38 | constexpr inline const auto KMemoryRegionType_LegacyLpsPrimaryICtlr = | ||
| 39 | KMemoryRegionType_LegacyLpsDevices.Derive(NumLegacyLpsDevices, 3); | ||
| 40 | constexpr inline const auto KMemoryRegionType_LegacyLpsSemaphore = | ||
| 41 | KMemoryRegionType_LegacyLpsDevices.Derive(NumLegacyLpsDevices, 4); | ||
| 42 | constexpr inline const auto KMemoryRegionType_LegacyLpsAtomics = | ||
| 43 | KMemoryRegionType_LegacyLpsDevices.Derive(NumLegacyLpsDevices, 5); | ||
| 44 | constexpr inline const auto KMemoryRegionType_LegacyLpsClkRst = | ||
| 45 | KMemoryRegionType_LegacyLpsDevices.Derive(NumLegacyLpsDevices, 6); | ||
| 46 | static_assert(KMemoryRegionType_LegacyLpsExceptionVectors.GetValue() == 0x3C5); | ||
| 47 | static_assert(KMemoryRegionType_LegacyLpsIram.GetValue() == 0x5C5); | ||
| 48 | static_assert(KMemoryRegionType_LegacyLpsFlowController.GetValue() == 0x6C5); | ||
| 49 | static_assert(KMemoryRegionType_LegacyLpsPrimaryICtlr.GetValue() == 0x9C5); | ||
| 50 | static_assert(KMemoryRegionType_LegacyLpsSemaphore.GetValue() == 0xAC5); | ||
| 51 | static_assert(KMemoryRegionType_LegacyLpsAtomics.GetValue() == 0xCC5); | ||
| 52 | static_assert(KMemoryRegionType_LegacyLpsClkRst.GetValue() == 0x11C5); | ||
diff --git a/src/core/hle/kernel/board/nintendo/nx/k_system_control.cpp b/src/core/hle/kernel/board/nintendo/nx/k_system_control.cpp new file mode 100644 index 000000000..86472b5ce --- /dev/null +++ b/src/core/hle/kernel/board/nintendo/nx/k_system_control.cpp | |||
| @@ -0,0 +1,164 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <random> | ||
| 6 | |||
| 7 | #include "common/common_sizes.h" | ||
| 8 | #include "core/hle/kernel/board/nintendo/nx/k_system_control.h" | ||
| 9 | #include "core/hle/kernel/board/nintendo/nx/secure_monitor.h" | ||
| 10 | #include "core/hle/kernel/k_trace.h" | ||
| 11 | |||
| 12 | namespace Kernel::Board::Nintendo::Nx { | ||
| 13 | |||
| 14 | namespace impl { | ||
| 15 | |||
| 16 | constexpr const std::size_t RequiredNonSecureSystemMemorySizeVi = 0x2238 * 4 * 1024; | ||
| 17 | constexpr const std::size_t RequiredNonSecureSystemMemorySizeNvservices = 0x710 * 4 * 1024; | ||
| 18 | constexpr const std::size_t RequiredNonSecureSystemMemorySizeMisc = 0x80 * 4 * 1024; | ||
| 19 | |||
| 20 | } // namespace impl | ||
| 21 | |||
| 22 | constexpr const std::size_t RequiredNonSecureSystemMemorySize = | ||
| 23 | impl::RequiredNonSecureSystemMemorySizeVi + impl::RequiredNonSecureSystemMemorySizeNvservices + | ||
| 24 | impl::RequiredNonSecureSystemMemorySizeMisc; | ||
| 25 | |||
| 26 | namespace { | ||
| 27 | |||
| 28 | u32 GetMemoryModeForInit() { | ||
| 29 | return 0x01; | ||
| 30 | } | ||
| 31 | |||
| 32 | u32 GetMemorySizeForInit() { | ||
| 33 | return 0; | ||
| 34 | } | ||
| 35 | |||
| 36 | Smc::MemoryArrangement GetMemoryArrangeForInit() { | ||
| 37 | switch (GetMemoryModeForInit() & 0x3F) { | ||
| 38 | case 0x01: | ||
| 39 | default: | ||
| 40 | return Smc::MemoryArrangement_4GB; | ||
| 41 | case 0x02: | ||
| 42 | return Smc::MemoryArrangement_4GBForAppletDev; | ||
| 43 | case 0x03: | ||
| 44 | return Smc::MemoryArrangement_4GBForSystemDev; | ||
| 45 | case 0x11: | ||
| 46 | return Smc::MemoryArrangement_6GB; | ||
| 47 | case 0x12: | ||
| 48 | return Smc::MemoryArrangement_6GBForAppletDev; | ||
| 49 | case 0x21: | ||
| 50 | return Smc::MemoryArrangement_8GB; | ||
| 51 | } | ||
| 52 | } | ||
| 53 | } // namespace | ||
| 54 | |||
| 55 | // Initialization. | ||
| 56 | size_t KSystemControl::Init::GetIntendedMemorySize() { | ||
| 57 | switch (GetMemorySizeForInit()) { | ||
| 58 | case Smc::MemorySize_4GB: | ||
| 59 | default: // All invalid modes should go to 4GB. | ||
| 60 | return Common::Size_4_GB; | ||
| 61 | case Smc::MemorySize_6GB: | ||
| 62 | return Common::Size_6_GB; | ||
| 63 | case Smc::MemorySize_8GB: | ||
| 64 | return Common::Size_8_GB; | ||
| 65 | } | ||
| 66 | } | ||
| 67 | |||
| 68 | PAddr KSystemControl::Init::GetKernelPhysicalBaseAddress(u64 base_address) { | ||
| 69 | return base_address; | ||
| 70 | } | ||
| 71 | |||
| 72 | bool KSystemControl::Init::ShouldIncreaseThreadResourceLimit() { | ||
| 73 | return true; | ||
| 74 | } | ||
| 75 | |||
| 76 | std::size_t KSystemControl::Init::GetApplicationPoolSize() { | ||
| 77 | // Get the base pool size. | ||
| 78 | const size_t base_pool_size = []() -> size_t { | ||
| 79 | switch (GetMemoryArrangeForInit()) { | ||
| 80 | case Smc::MemoryArrangement_4GB: | ||
| 81 | default: | ||
| 82 | return Common::Size_3285_MB; | ||
| 83 | case Smc::MemoryArrangement_4GBForAppletDev: | ||
| 84 | return Common::Size_2048_MB; | ||
| 85 | case Smc::MemoryArrangement_4GBForSystemDev: | ||
| 86 | return Common::Size_3285_MB; | ||
| 87 | case Smc::MemoryArrangement_6GB: | ||
| 88 | return Common::Size_4916_MB; | ||
| 89 | case Smc::MemoryArrangement_6GBForAppletDev: | ||
| 90 | return Common::Size_3285_MB; | ||
| 91 | case Smc::MemoryArrangement_8GB: | ||
| 92 | return Common::Size_4916_MB; | ||
| 93 | } | ||
| 94 | }(); | ||
| 95 | |||
| 96 | // Return (possibly) adjusted size. | ||
| 97 | return base_pool_size; | ||
| 98 | } | ||
| 99 | |||
| 100 | size_t KSystemControl::Init::GetAppletPoolSize() { | ||
| 101 | // Get the base pool size. | ||
| 102 | const size_t base_pool_size = []() -> size_t { | ||
| 103 | switch (GetMemoryArrangeForInit()) { | ||
| 104 | case Smc::MemoryArrangement_4GB: | ||
| 105 | default: | ||
| 106 | return Common::Size_507_MB; | ||
| 107 | case Smc::MemoryArrangement_4GBForAppletDev: | ||
| 108 | return Common::Size_1554_MB; | ||
| 109 | case Smc::MemoryArrangement_4GBForSystemDev: | ||
| 110 | return Common::Size_448_MB; | ||
| 111 | case Smc::MemoryArrangement_6GB: | ||
| 112 | return Common::Size_562_MB; | ||
| 113 | case Smc::MemoryArrangement_6GBForAppletDev: | ||
| 114 | return Common::Size_2193_MB; | ||
| 115 | case Smc::MemoryArrangement_8GB: | ||
| 116 | return Common::Size_2193_MB; | ||
| 117 | } | ||
| 118 | }(); | ||
| 119 | |||
| 120 | // Return (possibly) adjusted size. | ||
| 121 | constexpr size_t ExtraSystemMemoryForAtmosphere = Common::Size_33_MB; | ||
| 122 | return base_pool_size - ExtraSystemMemoryForAtmosphere - KTraceBufferSize; | ||
| 123 | } | ||
| 124 | |||
| 125 | size_t KSystemControl::Init::GetMinimumNonSecureSystemPoolSize() { | ||
| 126 | // Verify that our minimum is at least as large as Nintendo's. | ||
| 127 | constexpr size_t MinimumSize = RequiredNonSecureSystemMemorySize; | ||
| 128 | static_assert(MinimumSize >= 0x29C8000); | ||
| 129 | |||
| 130 | return MinimumSize; | ||
| 131 | } | ||
| 132 | |||
| 133 | namespace { | ||
| 134 | template <typename F> | ||
| 135 | u64 GenerateUniformRange(u64 min, u64 max, F f) { | ||
| 136 | // Handle the case where the difference is too large to represent. | ||
| 137 | if (max == std::numeric_limits<u64>::max() && min == std::numeric_limits<u64>::min()) { | ||
| 138 | return f(); | ||
| 139 | } | ||
| 140 | |||
| 141 | // Iterate until we get a value in range. | ||
| 142 | const u64 range_size = ((max + 1) - min); | ||
| 143 | const u64 effective_max = (std::numeric_limits<u64>::max() / range_size) * range_size; | ||
| 144 | while (true) { | ||
| 145 | if (const u64 rnd = f(); rnd < effective_max) { | ||
| 146 | return min + (rnd % range_size); | ||
| 147 | } | ||
| 148 | } | ||
| 149 | } | ||
| 150 | |||
| 151 | } // Anonymous namespace | ||
| 152 | |||
| 153 | u64 KSystemControl::GenerateRandomU64() { | ||
| 154 | static std::random_device device; | ||
| 155 | static std::mt19937 gen(device()); | ||
| 156 | static std::uniform_int_distribution<u64> distribution(1, std::numeric_limits<u64>::max()); | ||
| 157 | return distribution(gen); | ||
| 158 | } | ||
| 159 | |||
| 160 | u64 KSystemControl::GenerateRandomRange(u64 min, u64 max) { | ||
| 161 | return GenerateUniformRange(min, max, GenerateRandomU64); | ||
| 162 | } | ||
| 163 | |||
| 164 | } // namespace Kernel::Board::Nintendo::Nx | ||
diff --git a/src/core/hle/kernel/board/nintendo/nx/k_system_control.h b/src/core/hle/kernel/board/nintendo/nx/k_system_control.h new file mode 100644 index 000000000..52f230ced --- /dev/null +++ b/src/core/hle/kernel/board/nintendo/nx/k_system_control.h | |||
| @@ -0,0 +1,28 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include "common/common_types.h" | ||
| 8 | |||
| 9 | namespace Kernel::Board::Nintendo::Nx { | ||
| 10 | |||
| 11 | class KSystemControl { | ||
| 12 | public: | ||
| 13 | class Init { | ||
| 14 | public: | ||
| 15 | // Initialization. | ||
| 16 | static std::size_t GetIntendedMemorySize(); | ||
| 17 | static PAddr GetKernelPhysicalBaseAddress(u64 base_address); | ||
| 18 | static bool ShouldIncreaseThreadResourceLimit(); | ||
| 19 | static std::size_t GetApplicationPoolSize(); | ||
| 20 | static std::size_t GetAppletPoolSize(); | ||
| 21 | static std::size_t GetMinimumNonSecureSystemPoolSize(); | ||
| 22 | }; | ||
| 23 | |||
| 24 | static u64 GenerateRandomRange(u64 min, u64 max); | ||
| 25 | static u64 GenerateRandomU64(); | ||
| 26 | }; | ||
| 27 | |||
| 28 | } // namespace Kernel::Board::Nintendo::Nx | ||
diff --git a/src/core/hle/kernel/board/nintendo/nx/secure_monitor.h b/src/core/hle/kernel/board/nintendo/nx/secure_monitor.h new file mode 100644 index 000000000..0c366b252 --- /dev/null +++ b/src/core/hle/kernel/board/nintendo/nx/secure_monitor.h | |||
| @@ -0,0 +1,26 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include "common/common_types.h" | ||
| 8 | |||
| 9 | namespace Kernel::Board::Nintendo::Nx::Smc { | ||
| 10 | |||
| 11 | enum MemorySize { | ||
| 12 | MemorySize_4GB = 0, | ||
| 13 | MemorySize_6GB = 1, | ||
| 14 | MemorySize_8GB = 2, | ||
| 15 | }; | ||
| 16 | |||
| 17 | enum MemoryArrangement { | ||
| 18 | MemoryArrangement_4GB = 0, | ||
| 19 | MemoryArrangement_4GBForAppletDev = 1, | ||
| 20 | MemoryArrangement_4GBForSystemDev = 2, | ||
| 21 | MemoryArrangement_6GB = 3, | ||
| 22 | MemoryArrangement_6GBForAppletDev = 4, | ||
| 23 | MemoryArrangement_8GB = 5, | ||
| 24 | }; | ||
| 25 | |||
| 26 | } // namespace Kernel::Board::Nintendo::Nx::Smc | ||
diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp index 161d9f782..2b363b1d9 100644 --- a/src/core/hle/kernel/hle_ipc.cpp +++ b/src/core/hle/kernel/hle_ipc.cpp | |||
| @@ -75,10 +75,14 @@ void HLERequestContext::ParseCommandBuffer(const HandleTable& handle_table, u32_ | |||
| 75 | if (incoming) { | 75 | if (incoming) { |
| 76 | // Populate the object lists with the data in the IPC request. | 76 | // Populate the object lists with the data in the IPC request. |
| 77 | for (u32 handle = 0; handle < handle_descriptor_header->num_handles_to_copy; ++handle) { | 77 | for (u32 handle = 0; handle < handle_descriptor_header->num_handles_to_copy; ++handle) { |
| 78 | copy_objects.push_back(handle_table.GetGeneric(rp.Pop<Handle>())); | 78 | const u32 copy_handle{rp.Pop<Handle>()}; |
| 79 | copy_handles.push_back(copy_handle); | ||
| 80 | copy_objects.push_back(handle_table.GetGeneric(copy_handle)); | ||
| 79 | } | 81 | } |
| 80 | for (u32 handle = 0; handle < handle_descriptor_header->num_handles_to_move; ++handle) { | 82 | for (u32 handle = 0; handle < handle_descriptor_header->num_handles_to_move; ++handle) { |
| 81 | move_objects.push_back(handle_table.GetGeneric(rp.Pop<Handle>())); | 83 | const u32 move_handle{rp.Pop<Handle>()}; |
| 84 | move_handles.push_back(move_handle); | ||
| 85 | move_objects.push_back(handle_table.GetGeneric(move_handle)); | ||
| 82 | } | 86 | } |
| 83 | } else { | 87 | } else { |
| 84 | // For responses we just ignore the handles, they're empty and will be populated when | 88 | // For responses we just ignore the handles, they're empty and will be populated when |
diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h index 9a769781b..6fba42615 100644 --- a/src/core/hle/kernel/hle_ipc.h +++ b/src/core/hle/kernel/hle_ipc.h | |||
| @@ -210,6 +210,14 @@ public: | |||
| 210 | /// Helper function to test whether the output buffer at buffer_index can be written | 210 | /// Helper function to test whether the output buffer at buffer_index can be written |
| 211 | bool CanWriteBuffer(std::size_t buffer_index = 0) const; | 211 | bool CanWriteBuffer(std::size_t buffer_index = 0) const; |
| 212 | 212 | ||
| 213 | Handle GetCopyHandle(std::size_t index) const { | ||
| 214 | return copy_handles.at(index); | ||
| 215 | } | ||
| 216 | |||
| 217 | Handle GetMoveHandle(std::size_t index) const { | ||
| 218 | return move_handles.at(index); | ||
| 219 | } | ||
| 220 | |||
| 213 | template <typename T> | 221 | template <typename T> |
| 214 | std::shared_ptr<T> GetCopyObject(std::size_t index) { | 222 | std::shared_ptr<T> GetCopyObject(std::size_t index) { |
| 215 | return DynamicObjectCast<T>(copy_objects.at(index)); | 223 | return DynamicObjectCast<T>(copy_objects.at(index)); |
| @@ -285,6 +293,8 @@ private: | |||
| 285 | std::shared_ptr<Kernel::ServerSession> server_session; | 293 | std::shared_ptr<Kernel::ServerSession> server_session; |
| 286 | std::shared_ptr<KThread> thread; | 294 | std::shared_ptr<KThread> thread; |
| 287 | // TODO(yuriks): Check common usage of this and optimize size accordingly | 295 | // TODO(yuriks): Check common usage of this and optimize size accordingly |
| 296 | boost::container::small_vector<Handle, 8> move_handles; | ||
| 297 | boost::container::small_vector<Handle, 8> copy_handles; | ||
| 288 | boost::container::small_vector<std::shared_ptr<Object>, 8> move_objects; | 298 | boost::container::small_vector<std::shared_ptr<Object>, 8> move_objects; |
| 289 | boost::container::small_vector<std::shared_ptr<Object>, 8> copy_objects; | 299 | boost::container::small_vector<std::shared_ptr<Object>, 8> copy_objects; |
| 290 | boost::container::small_vector<std::shared_ptr<SessionRequestHandler>, 8> domain_objects; | 300 | boost::container::small_vector<std::shared_ptr<SessionRequestHandler>, 8> domain_objects; |
diff --git a/src/core/hle/kernel/k_address_space_info.cpp b/src/core/hle/kernel/k_address_space_info.cpp index 24944d15b..c7549f7a2 100644 --- a/src/core/hle/kernel/k_address_space_info.cpp +++ b/src/core/hle/kernel/k_address_space_info.cpp | |||
| @@ -5,45 +5,34 @@ | |||
| 5 | #include <array> | 5 | #include <array> |
| 6 | 6 | ||
| 7 | #include "common/assert.h" | 7 | #include "common/assert.h" |
| 8 | #include "common/common_sizes.h" | ||
| 8 | #include "core/hle/kernel/k_address_space_info.h" | 9 | #include "core/hle/kernel/k_address_space_info.h" |
| 9 | 10 | ||
| 10 | namespace Kernel { | 11 | namespace Kernel { |
| 11 | 12 | ||
| 12 | namespace { | 13 | namespace { |
| 13 | 14 | ||
| 14 | enum : u64 { | ||
| 15 | Size_1_MB = 0x100000, | ||
| 16 | Size_2_MB = 2 * Size_1_MB, | ||
| 17 | Size_128_MB = 128 * Size_1_MB, | ||
| 18 | Size_1_GB = 0x40000000, | ||
| 19 | Size_2_GB = 2 * Size_1_GB, | ||
| 20 | Size_4_GB = 4 * Size_1_GB, | ||
| 21 | Size_6_GB = 6 * Size_1_GB, | ||
| 22 | Size_64_GB = 64 * Size_1_GB, | ||
| 23 | Size_512_GB = 512 * Size_1_GB, | ||
| 24 | Invalid = std::numeric_limits<u64>::max(), | ||
| 25 | }; | ||
| 26 | |||
| 27 | // clang-format off | 15 | // clang-format off |
| 28 | constexpr std::array<KAddressSpaceInfo, 13> AddressSpaceInfos{{ | 16 | constexpr std::array<KAddressSpaceInfo, 13> AddressSpaceInfos{{ |
| 29 | { .bit_width = 32, .address = Size_2_MB , .size = Size_1_GB - Size_2_MB , .type = KAddressSpaceInfo::Type::MapSmall, }, | 17 | { .bit_width = 32, .address = Common::Size_2_MB , .size = Common::Size_1_GB - Common::Size_2_MB , .type = KAddressSpaceInfo::Type::MapSmall, }, |
| 30 | { .bit_width = 32, .address = Size_1_GB , .size = Size_4_GB - Size_1_GB , .type = KAddressSpaceInfo::Type::MapLarge, }, | 18 | { .bit_width = 32, .address = Common::Size_1_GB , .size = Common::Size_4_GB - Common::Size_1_GB , .type = KAddressSpaceInfo::Type::MapLarge, }, |
| 31 | { .bit_width = 32, .address = Invalid , .size = Size_1_GB , .type = KAddressSpaceInfo::Type::Heap, }, | 19 | { .bit_width = 32, .address = Common::Size_Invalid, .size = Common::Size_1_GB , .type = KAddressSpaceInfo::Type::Alias, }, |
| 32 | { .bit_width = 32, .address = Invalid , .size = Size_1_GB , .type = KAddressSpaceInfo::Type::Alias, }, | 20 | { .bit_width = 32, .address = Common::Size_Invalid, .size = Common::Size_1_GB , .type = KAddressSpaceInfo::Type::Heap, }, |
| 33 | { .bit_width = 36, .address = Size_128_MB, .size = Size_2_GB - Size_128_MB, .type = KAddressSpaceInfo::Type::MapSmall, }, | 21 | { .bit_width = 36, .address = Common::Size_128_MB , .size = Common::Size_2_GB - Common::Size_128_MB, .type = KAddressSpaceInfo::Type::MapSmall, }, |
| 34 | { .bit_width = 36, .address = Size_2_GB , .size = Size_64_GB - Size_2_GB , .type = KAddressSpaceInfo::Type::MapLarge, }, | 22 | { .bit_width = 36, .address = Common::Size_2_GB , .size = Common::Size_64_GB - Common::Size_2_GB , .type = KAddressSpaceInfo::Type::MapLarge, }, |
| 35 | { .bit_width = 36, .address = Invalid , .size = Size_6_GB , .type = KAddressSpaceInfo::Type::Heap, }, | 23 | { .bit_width = 36, .address = Common::Size_Invalid, .size = Common::Size_6_GB , .type = KAddressSpaceInfo::Type::Heap, }, |
| 36 | { .bit_width = 36, .address = Invalid , .size = Size_6_GB , .type = KAddressSpaceInfo::Type::Alias, }, | 24 | { .bit_width = 36, .address = Common::Size_Invalid, .size = Common::Size_6_GB , .type = KAddressSpaceInfo::Type::Alias, }, |
| 37 | { .bit_width = 39, .address = Size_128_MB, .size = Size_512_GB - Size_128_MB, .type = KAddressSpaceInfo::Type::Map39Bit, }, | 25 | { .bit_width = 39, .address = Common::Size_128_MB , .size = Common::Size_512_GB - Common::Size_128_MB, .type = KAddressSpaceInfo::Type::Map39Bit, }, |
| 38 | { .bit_width = 39, .address = Invalid , .size = Size_64_GB , .type = KAddressSpaceInfo::Type::MapSmall }, | 26 | { .bit_width = 39, .address = Common::Size_Invalid, .size = Common::Size_64_GB , .type = KAddressSpaceInfo::Type::MapSmall }, |
| 39 | { .bit_width = 39, .address = Invalid , .size = Size_6_GB , .type = KAddressSpaceInfo::Type::Heap, }, | 27 | { .bit_width = 39, .address = Common::Size_Invalid, .size = Common::Size_6_GB , .type = KAddressSpaceInfo::Type::Heap, }, |
| 40 | { .bit_width = 39, .address = Invalid , .size = Size_64_GB , .type = KAddressSpaceInfo::Type::Alias, }, | 28 | { .bit_width = 39, .address = Common::Size_Invalid, .size = Common::Size_64_GB , .type = KAddressSpaceInfo::Type::Alias, }, |
| 41 | { .bit_width = 39, .address = Invalid , .size = Size_2_GB , .type = KAddressSpaceInfo::Type::Stack, }, | 29 | { .bit_width = 39, .address = Common::Size_Invalid, .size = Common::Size_2_GB , .type = KAddressSpaceInfo::Type::Stack, }, |
| 42 | }}; | 30 | }}; |
| 43 | // clang-format on | 31 | // clang-format on |
| 44 | 32 | ||
| 45 | constexpr bool IsAllowedIndexForAddress(std::size_t index) { | 33 | constexpr bool IsAllowedIndexForAddress(std::size_t index) { |
| 46 | return index < AddressSpaceInfos.size() && AddressSpaceInfos[index].address != Invalid; | 34 | return index < AddressSpaceInfos.size() && |
| 35 | AddressSpaceInfos[index].address != Common::Size_Invalid; | ||
| 47 | } | 36 | } |
| 48 | 37 | ||
| 49 | using IndexArray = | 38 | using IndexArray = |
diff --git a/src/core/hle/kernel/k_memory_layout.board.nintendo_nx.cpp b/src/core/hle/kernel/k_memory_layout.board.nintendo_nx.cpp new file mode 100644 index 000000000..a78551291 --- /dev/null +++ b/src/core/hle/kernel/k_memory_layout.board.nintendo_nx.cpp | |||
| @@ -0,0 +1,199 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/alignment.h" | ||
| 6 | #include "core/hle/kernel/k_memory_layout.h" | ||
| 7 | #include "core/hle/kernel/k_memory_manager.h" | ||
| 8 | #include "core/hle/kernel/k_system_control.h" | ||
| 9 | #include "core/hle/kernel/k_trace.h" | ||
| 10 | |||
| 11 | namespace Kernel { | ||
| 12 | |||
| 13 | namespace { | ||
| 14 | |||
| 15 | constexpr size_t CarveoutAlignment = 0x20000; | ||
| 16 | constexpr size_t CarveoutSizeMax = (512ULL * 1024 * 1024) - CarveoutAlignment; | ||
| 17 | |||
| 18 | bool SetupPowerManagementControllerMemoryRegion(KMemoryLayout& memory_layout) { | ||
| 19 | // Above firmware 2.0.0, the PMC is not mappable. | ||
| 20 | return memory_layout.GetPhysicalMemoryRegionTree().Insert( | ||
| 21 | 0x7000E000, 0x400, KMemoryRegionType_None | KMemoryRegionAttr_NoUserMap) && | ||
| 22 | memory_layout.GetPhysicalMemoryRegionTree().Insert( | ||
| 23 | 0x7000E400, 0xC00, | ||
| 24 | KMemoryRegionType_PowerManagementController | KMemoryRegionAttr_NoUserMap); | ||
| 25 | } | ||
| 26 | |||
| 27 | void InsertPoolPartitionRegionIntoBothTrees(KMemoryLayout& memory_layout, size_t start, size_t size, | ||
| 28 | KMemoryRegionType phys_type, | ||
| 29 | KMemoryRegionType virt_type, u32& cur_attr) { | ||
| 30 | const u32 attr = cur_attr++; | ||
| 31 | ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert(start, size, | ||
| 32 | static_cast<u32>(phys_type), attr)); | ||
| 33 | const KMemoryRegion* phys = memory_layout.GetPhysicalMemoryRegionTree().FindByTypeAndAttribute( | ||
| 34 | static_cast<u32>(phys_type), attr); | ||
| 35 | ASSERT(phys != nullptr); | ||
| 36 | ASSERT(phys->GetEndAddress() != 0); | ||
| 37 | ASSERT(memory_layout.GetVirtualMemoryRegionTree().Insert(phys->GetPairAddress(), size, | ||
| 38 | static_cast<u32>(virt_type), attr)); | ||
| 39 | } | ||
| 40 | |||
| 41 | } // namespace | ||
| 42 | |||
| 43 | namespace Init { | ||
| 44 | |||
| 45 | void SetupDevicePhysicalMemoryRegions(KMemoryLayout& memory_layout) { | ||
| 46 | ASSERT(SetupPowerManagementControllerMemoryRegion(memory_layout)); | ||
| 47 | ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert( | ||
| 48 | 0x70019000, 0x1000, KMemoryRegionType_MemoryController | KMemoryRegionAttr_NoUserMap)); | ||
| 49 | ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert( | ||
| 50 | 0x7001C000, 0x1000, KMemoryRegionType_MemoryController0 | KMemoryRegionAttr_NoUserMap)); | ||
| 51 | ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert( | ||
| 52 | 0x7001D000, 0x1000, KMemoryRegionType_MemoryController1 | KMemoryRegionAttr_NoUserMap)); | ||
| 53 | ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert( | ||
| 54 | 0x50040000, 0x1000, KMemoryRegionType_None | KMemoryRegionAttr_NoUserMap)); | ||
| 55 | ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert( | ||
| 56 | 0x50041000, 0x1000, | ||
| 57 | KMemoryRegionType_InterruptDistributor | KMemoryRegionAttr_ShouldKernelMap)); | ||
| 58 | ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert( | ||
| 59 | 0x50042000, 0x1000, | ||
| 60 | KMemoryRegionType_InterruptCpuInterface | KMemoryRegionAttr_ShouldKernelMap)); | ||
| 61 | ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert( | ||
| 62 | 0x50043000, 0x1D000, KMemoryRegionType_None | KMemoryRegionAttr_NoUserMap)); | ||
| 63 | |||
| 64 | // Map IRAM unconditionally, to support debug-logging-to-iram build config. | ||
| 65 | ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert( | ||
| 66 | 0x40000000, 0x40000, KMemoryRegionType_LegacyLpsIram | KMemoryRegionAttr_ShouldKernelMap)); | ||
| 67 | |||
| 68 | // Above firmware 2.0.0, prevent mapping the bpmp exception vectors or the ipatch region. | ||
| 69 | ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert( | ||
| 70 | 0x6000F000, 0x1000, KMemoryRegionType_None | KMemoryRegionAttr_NoUserMap)); | ||
| 71 | ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert( | ||
| 72 | 0x6001DC00, 0x400, KMemoryRegionType_None | KMemoryRegionAttr_NoUserMap)); | ||
| 73 | } | ||
| 74 | |||
| 75 | void SetupDramPhysicalMemoryRegions(KMemoryLayout& memory_layout) { | ||
| 76 | const size_t intended_memory_size = KSystemControl::Init::GetIntendedMemorySize(); | ||
| 77 | const PAddr physical_memory_base_address = | ||
| 78 | KSystemControl::Init::GetKernelPhysicalBaseAddress(DramPhysicalAddress); | ||
| 79 | |||
| 80 | // Insert blocks into the tree. | ||
| 81 | ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert( | ||
| 82 | physical_memory_base_address, intended_memory_size, KMemoryRegionType_Dram)); | ||
| 83 | ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert( | ||
| 84 | physical_memory_base_address, ReservedEarlyDramSize, KMemoryRegionType_DramReservedEarly)); | ||
| 85 | |||
| 86 | // Insert the KTrace block at the end of Dram, if KTrace is enabled. | ||
| 87 | static_assert(!IsKTraceEnabled || KTraceBufferSize > 0); | ||
| 88 | if constexpr (IsKTraceEnabled) { | ||
| 89 | const PAddr ktrace_buffer_phys_addr = | ||
| 90 | physical_memory_base_address + intended_memory_size - KTraceBufferSize; | ||
| 91 | ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert( | ||
| 92 | ktrace_buffer_phys_addr, KTraceBufferSize, KMemoryRegionType_KernelTraceBuffer)); | ||
| 93 | } | ||
| 94 | } | ||
| 95 | |||
| 96 | void SetupPoolPartitionMemoryRegions(KMemoryLayout& memory_layout) { | ||
| 97 | // Start by identifying the extents of the DRAM memory region. | ||
| 98 | const auto dram_extents = memory_layout.GetMainMemoryPhysicalExtents(); | ||
| 99 | ASSERT(dram_extents.GetEndAddress() != 0); | ||
| 100 | |||
| 101 | // Determine the end of the pool region. | ||
| 102 | const u64 pool_end = dram_extents.GetEndAddress() - KTraceBufferSize; | ||
| 103 | |||
| 104 | // Find the start of the kernel DRAM region. | ||
| 105 | const KMemoryRegion* kernel_dram_region = | ||
| 106 | memory_layout.GetPhysicalMemoryRegionTree().FindFirstDerived( | ||
| 107 | KMemoryRegionType_DramKernelBase); | ||
| 108 | ASSERT(kernel_dram_region != nullptr); | ||
| 109 | |||
| 110 | const u64 kernel_dram_start = kernel_dram_region->GetAddress(); | ||
| 111 | ASSERT(Common::IsAligned(kernel_dram_start, CarveoutAlignment)); | ||
| 112 | |||
| 113 | // Find the start of the pool partitions region. | ||
| 114 | const KMemoryRegion* pool_partitions_region = | ||
| 115 | memory_layout.GetPhysicalMemoryRegionTree().FindByTypeAndAttribute( | ||
| 116 | KMemoryRegionType_DramPoolPartition, 0); | ||
| 117 | ASSERT(pool_partitions_region != nullptr); | ||
| 118 | const u64 pool_partitions_start = pool_partitions_region->GetAddress(); | ||
| 119 | |||
| 120 | // Setup the pool partition layouts. | ||
| 121 | // On 5.0.0+, setup modern 4-pool-partition layout. | ||
| 122 | |||
| 123 | // Get Application and Applet pool sizes. | ||
| 124 | const size_t application_pool_size = KSystemControl::Init::GetApplicationPoolSize(); | ||
| 125 | const size_t applet_pool_size = KSystemControl::Init::GetAppletPoolSize(); | ||
| 126 | const size_t unsafe_system_pool_min_size = | ||
| 127 | KSystemControl::Init::GetMinimumNonSecureSystemPoolSize(); | ||
| 128 | |||
| 129 | // Decide on starting addresses for our pools. | ||
| 130 | const u64 application_pool_start = pool_end - application_pool_size; | ||
| 131 | const u64 applet_pool_start = application_pool_start - applet_pool_size; | ||
| 132 | const u64 unsafe_system_pool_start = std::min( | ||
| 133 | kernel_dram_start + CarveoutSizeMax, | ||
| 134 | Common::AlignDown(applet_pool_start - unsafe_system_pool_min_size, CarveoutAlignment)); | ||
| 135 | const size_t unsafe_system_pool_size = applet_pool_start - unsafe_system_pool_start; | ||
| 136 | |||
| 137 | // We want to arrange application pool depending on where the middle of dram is. | ||
| 138 | const u64 dram_midpoint = (dram_extents.GetAddress() + dram_extents.GetEndAddress()) / 2; | ||
| 139 | u32 cur_pool_attr = 0; | ||
| 140 | size_t total_overhead_size = 0; | ||
| 141 | if (dram_extents.GetEndAddress() <= dram_midpoint || dram_midpoint <= application_pool_start) { | ||
| 142 | InsertPoolPartitionRegionIntoBothTrees( | ||
| 143 | memory_layout, application_pool_start, application_pool_size, | ||
| 144 | KMemoryRegionType_DramApplicationPool, KMemoryRegionType_VirtualDramApplicationPool, | ||
| 145 | cur_pool_attr); | ||
| 146 | total_overhead_size += | ||
| 147 | KMemoryManager::CalculateManagementOverheadSize(application_pool_size); | ||
| 148 | } else { | ||
| 149 | const size_t first_application_pool_size = dram_midpoint - application_pool_start; | ||
| 150 | const size_t second_application_pool_size = | ||
| 151 | application_pool_start + application_pool_size - dram_midpoint; | ||
| 152 | InsertPoolPartitionRegionIntoBothTrees( | ||
| 153 | memory_layout, application_pool_start, first_application_pool_size, | ||
| 154 | KMemoryRegionType_DramApplicationPool, KMemoryRegionType_VirtualDramApplicationPool, | ||
| 155 | cur_pool_attr); | ||
| 156 | InsertPoolPartitionRegionIntoBothTrees( | ||
| 157 | memory_layout, dram_midpoint, second_application_pool_size, | ||
| 158 | KMemoryRegionType_DramApplicationPool, KMemoryRegionType_VirtualDramApplicationPool, | ||
| 159 | cur_pool_attr); | ||
| 160 | total_overhead_size += | ||
| 161 | KMemoryManager::CalculateManagementOverheadSize(first_application_pool_size); | ||
| 162 | total_overhead_size += | ||
| 163 | KMemoryManager::CalculateManagementOverheadSize(second_application_pool_size); | ||
| 164 | } | ||
| 165 | |||
| 166 | // Insert the applet pool. | ||
| 167 | InsertPoolPartitionRegionIntoBothTrees(memory_layout, applet_pool_start, applet_pool_size, | ||
| 168 | KMemoryRegionType_DramAppletPool, | ||
| 169 | KMemoryRegionType_VirtualDramAppletPool, cur_pool_attr); | ||
| 170 | total_overhead_size += KMemoryManager::CalculateManagementOverheadSize(applet_pool_size); | ||
| 171 | |||
| 172 | // Insert the nonsecure system pool. | ||
| 173 | InsertPoolPartitionRegionIntoBothTrees( | ||
| 174 | memory_layout, unsafe_system_pool_start, unsafe_system_pool_size, | ||
| 175 | KMemoryRegionType_DramSystemNonSecurePool, KMemoryRegionType_VirtualDramSystemNonSecurePool, | ||
| 176 | cur_pool_attr); | ||
| 177 | total_overhead_size += KMemoryManager::CalculateManagementOverheadSize(unsafe_system_pool_size); | ||
| 178 | |||
| 179 | // Insert the pool management region. | ||
| 180 | total_overhead_size += KMemoryManager::CalculateManagementOverheadSize( | ||
| 181 | (unsafe_system_pool_start - pool_partitions_start) - total_overhead_size); | ||
| 182 | const u64 pool_management_start = unsafe_system_pool_start - total_overhead_size; | ||
| 183 | const size_t pool_management_size = total_overhead_size; | ||
| 184 | u32 pool_management_attr = 0; | ||
| 185 | InsertPoolPartitionRegionIntoBothTrees( | ||
| 186 | memory_layout, pool_management_start, pool_management_size, | ||
| 187 | KMemoryRegionType_DramPoolManagement, KMemoryRegionType_VirtualDramPoolManagement, | ||
| 188 | pool_management_attr); | ||
| 189 | |||
| 190 | // Insert the system pool. | ||
| 191 | const u64 system_pool_size = pool_management_start - pool_partitions_start; | ||
| 192 | InsertPoolPartitionRegionIntoBothTrees(memory_layout, pool_partitions_start, system_pool_size, | ||
| 193 | KMemoryRegionType_DramSystemPool, | ||
| 194 | KMemoryRegionType_VirtualDramSystemPool, cur_pool_attr); | ||
| 195 | } | ||
| 196 | |||
| 197 | } // namespace Init | ||
| 198 | |||
| 199 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/k_memory_layout.cpp b/src/core/hle/kernel/k_memory_layout.cpp new file mode 100644 index 000000000..fb1e2435f --- /dev/null +++ b/src/core/hle/kernel/k_memory_layout.cpp | |||
| @@ -0,0 +1,166 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <array> | ||
| 6 | |||
| 7 | #include "common/alignment.h" | ||
| 8 | #include "core/hle/kernel/k_memory_layout.h" | ||
| 9 | #include "core/hle/kernel/k_system_control.h" | ||
| 10 | |||
| 11 | namespace Kernel { | ||
| 12 | |||
| 13 | namespace { | ||
| 14 | |||
| 15 | template <typename... Args> | ||
| 16 | KMemoryRegion* AllocateRegion(KMemoryRegionAllocator& memory_region_allocator, Args&&... args) { | ||
| 17 | return memory_region_allocator.Allocate(std::forward<Args>(args)...); | ||
| 18 | } | ||
| 19 | |||
| 20 | } // namespace | ||
| 21 | |||
| 22 | KMemoryRegionTree::KMemoryRegionTree(KMemoryRegionAllocator& memory_region_allocator_) | ||
| 23 | : memory_region_allocator{memory_region_allocator_} {} | ||
| 24 | |||
| 25 | void KMemoryRegionTree::InsertDirectly(u64 address, u64 last_address, u32 attr, u32 type_id) { | ||
| 26 | this->insert(*AllocateRegion(memory_region_allocator, address, last_address, attr, type_id)); | ||
| 27 | } | ||
| 28 | |||
| 29 | bool KMemoryRegionTree::Insert(u64 address, size_t size, u32 type_id, u32 new_attr, u32 old_attr) { | ||
| 30 | // Locate the memory region that contains the address. | ||
| 31 | KMemoryRegion* found = this->FindModifiable(address); | ||
| 32 | |||
| 33 | // We require that the old attr is correct. | ||
| 34 | if (found->GetAttributes() != old_attr) { | ||
| 35 | return false; | ||
| 36 | } | ||
| 37 | |||
| 38 | // We further require that the region can be split from the old region. | ||
| 39 | const u64 inserted_region_end = address + size; | ||
| 40 | const u64 inserted_region_last = inserted_region_end - 1; | ||
| 41 | if (found->GetLastAddress() < inserted_region_last) { | ||
| 42 | return false; | ||
| 43 | } | ||
| 44 | |||
| 45 | // Further, we require that the type id is a valid transformation. | ||
| 46 | if (!found->CanDerive(type_id)) { | ||
| 47 | return false; | ||
| 48 | } | ||
| 49 | |||
| 50 | // Cache information from the region before we remove it. | ||
| 51 | const u64 old_address = found->GetAddress(); | ||
| 52 | const u64 old_last = found->GetLastAddress(); | ||
| 53 | const u64 old_pair = found->GetPairAddress(); | ||
| 54 | const u32 old_type = found->GetType(); | ||
| 55 | |||
| 56 | // Erase the existing region from the tree. | ||
| 57 | this->erase(this->iterator_to(*found)); | ||
| 58 | |||
| 59 | // Insert the new region into the tree. | ||
| 60 | if (old_address == address) { | ||
| 61 | // Reuse the old object for the new region, if we can. | ||
| 62 | found->Reset(address, inserted_region_last, old_pair, new_attr, type_id); | ||
| 63 | this->insert(*found); | ||
| 64 | } else { | ||
| 65 | // If we can't re-use, adjust the old region. | ||
| 66 | found->Reset(old_address, address - 1, old_pair, old_attr, old_type); | ||
| 67 | this->insert(*found); | ||
| 68 | |||
| 69 | // Insert a new region for the split. | ||
| 70 | const u64 new_pair = (old_pair != std::numeric_limits<u64>::max()) | ||
| 71 | ? old_pair + (address - old_address) | ||
| 72 | : old_pair; | ||
| 73 | this->insert(*AllocateRegion(memory_region_allocator, address, inserted_region_last, | ||
| 74 | new_pair, new_attr, type_id)); | ||
| 75 | } | ||
| 76 | |||
| 77 | // If we need to insert a region after the region, do so. | ||
| 78 | if (old_last != inserted_region_last) { | ||
| 79 | const u64 after_pair = (old_pair != std::numeric_limits<u64>::max()) | ||
| 80 | ? old_pair + (inserted_region_end - old_address) | ||
| 81 | : old_pair; | ||
| 82 | this->insert(*AllocateRegion(memory_region_allocator, inserted_region_end, old_last, | ||
| 83 | after_pair, old_attr, old_type)); | ||
| 84 | } | ||
| 85 | |||
| 86 | return true; | ||
| 87 | } | ||
| 88 | |||
| 89 | VAddr KMemoryRegionTree::GetRandomAlignedRegion(size_t size, size_t alignment, u32 type_id) { | ||
| 90 | // We want to find the total extents of the type id. | ||
| 91 | const auto extents = this->GetDerivedRegionExtents(static_cast<KMemoryRegionType>(type_id)); | ||
| 92 | |||
| 93 | // Ensure that our alignment is correct. | ||
| 94 | ASSERT(Common::IsAligned(extents.GetAddress(), alignment)); | ||
| 95 | |||
| 96 | const u64 first_address = extents.GetAddress(); | ||
| 97 | const u64 last_address = extents.GetLastAddress(); | ||
| 98 | |||
| 99 | const u64 first_index = first_address / alignment; | ||
| 100 | const u64 last_index = last_address / alignment; | ||
| 101 | |||
| 102 | while (true) { | ||
| 103 | const u64 candidate = | ||
| 104 | KSystemControl::GenerateRandomRange(first_index, last_index) * alignment; | ||
| 105 | |||
| 106 | // Ensure that the candidate doesn't overflow with the size. | ||
| 107 | if (!(candidate < candidate + size)) { | ||
| 108 | continue; | ||
| 109 | } | ||
| 110 | |||
| 111 | const u64 candidate_last = candidate + size - 1; | ||
| 112 | |||
| 113 | // Ensure that the candidate fits within the region. | ||
| 114 | if (candidate_last > last_address) { | ||
| 115 | continue; | ||
| 116 | } | ||
| 117 | |||
| 118 | // Locate the candidate region, and ensure it fits and has the correct type id. | ||
| 119 | if (const auto& candidate_region = *this->Find(candidate); | ||
| 120 | !(candidate_last <= candidate_region.GetLastAddress() && | ||
| 121 | candidate_region.GetType() == type_id)) { | ||
| 122 | continue; | ||
| 123 | } | ||
| 124 | |||
| 125 | return candidate; | ||
| 126 | } | ||
| 127 | } | ||
| 128 | |||
| 129 | KMemoryLayout::KMemoryLayout() | ||
| 130 | : virtual_tree{memory_region_allocator}, physical_tree{memory_region_allocator}, | ||
| 131 | virtual_linear_tree{memory_region_allocator}, physical_linear_tree{memory_region_allocator} {} | ||
| 132 | |||
| 133 | void KMemoryLayout::InitializeLinearMemoryRegionTrees(PAddr aligned_linear_phys_start, | ||
| 134 | VAddr linear_virtual_start) { | ||
| 135 | // Set static differences. | ||
| 136 | linear_phys_to_virt_diff = linear_virtual_start - aligned_linear_phys_start; | ||
| 137 | linear_virt_to_phys_diff = aligned_linear_phys_start - linear_virtual_start; | ||
| 138 | |||
| 139 | // Initialize linear trees. | ||
| 140 | for (auto& region : GetPhysicalMemoryRegionTree()) { | ||
| 141 | if (region.HasTypeAttribute(KMemoryRegionAttr_LinearMapped)) { | ||
| 142 | GetPhysicalLinearMemoryRegionTree().InsertDirectly( | ||
| 143 | region.GetAddress(), region.GetLastAddress(), region.GetAttributes(), | ||
| 144 | region.GetType()); | ||
| 145 | } | ||
| 146 | } | ||
| 147 | |||
| 148 | for (auto& region : GetVirtualMemoryRegionTree()) { | ||
| 149 | if (region.IsDerivedFrom(KMemoryRegionType_Dram)) { | ||
| 150 | GetVirtualLinearMemoryRegionTree().InsertDirectly( | ||
| 151 | region.GetAddress(), region.GetLastAddress(), region.GetAttributes(), | ||
| 152 | region.GetType()); | ||
| 153 | } | ||
| 154 | } | ||
| 155 | } | ||
| 156 | |||
| 157 | size_t KMemoryLayout::GetResourceRegionSizeForInit() { | ||
| 158 | // Calculate resource region size based on whether we allow extra threads. | ||
| 159 | const bool use_extra_resources = KSystemControl::Init::ShouldIncreaseThreadResourceLimit(); | ||
| 160 | size_t resource_region_size = | ||
| 161 | KernelResourceSize + (use_extra_resources ? KernelSlabHeapAdditionalSize : 0); | ||
| 162 | |||
| 163 | return resource_region_size; | ||
| 164 | } | ||
| 165 | |||
| 166 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/k_memory_layout.h b/src/core/hle/kernel/k_memory_layout.h index 0821d2d8c..288642d9a 100644 --- a/src/core/hle/kernel/k_memory_layout.h +++ b/src/core/hle/kernel/k_memory_layout.h | |||
| @@ -1,23 +1,69 @@ | |||
| 1 | // Copyright 2020 yuzu Emulator Project | 1 | // Copyright 2021 yuzu Emulator Project |
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <utility> | ||
| 8 | |||
| 9 | #include "common/alignment.h" | ||
| 10 | #include "common/common_sizes.h" | ||
| 7 | #include "common/common_types.h" | 11 | #include "common/common_types.h" |
| 8 | #include "core/device_memory.h" | 12 | #include "core/device_memory.h" |
| 13 | #include "core/hle/kernel/k_memory_region.h" | ||
| 14 | #include "core/hle/kernel/k_memory_region_type.h" | ||
| 15 | #include "core/hle/kernel/memory_types.h" | ||
| 9 | 16 | ||
| 10 | namespace Kernel { | 17 | namespace Kernel { |
| 11 | 18 | ||
| 12 | constexpr std::size_t KernelAslrAlignment = 2 * 1024 * 1024; | 19 | constexpr std::size_t L1BlockSize = Common::Size_1_GB; |
| 20 | constexpr std::size_t L2BlockSize = Common::Size_2_MB; | ||
| 21 | |||
| 22 | constexpr std::size_t GetMaximumOverheadSize(std::size_t size) { | ||
| 23 | return (Common::DivideUp(size, L1BlockSize) + Common::DivideUp(size, L2BlockSize)) * PageSize; | ||
| 24 | } | ||
| 25 | |||
| 26 | constexpr std::size_t MainMemorySize = Common::Size_4_GB; | ||
| 27 | constexpr std::size_t MainMemorySizeMax = Common::Size_8_GB; | ||
| 28 | |||
| 29 | constexpr std::size_t ReservedEarlyDramSize = 0x60000; | ||
| 30 | constexpr std::size_t DramPhysicalAddress = 0x80000000; | ||
| 31 | |||
| 32 | constexpr std::size_t KernelAslrAlignment = Common::Size_2_MB; | ||
| 13 | constexpr std::size_t KernelVirtualAddressSpaceWidth = 1ULL << 39; | 33 | constexpr std::size_t KernelVirtualAddressSpaceWidth = 1ULL << 39; |
| 14 | constexpr std::size_t KernelPhysicalAddressSpaceWidth = 1ULL << 48; | 34 | constexpr std::size_t KernelPhysicalAddressSpaceWidth = 1ULL << 48; |
| 35 | |||
| 15 | constexpr std::size_t KernelVirtualAddressSpaceBase = 0ULL - KernelVirtualAddressSpaceWidth; | 36 | constexpr std::size_t KernelVirtualAddressSpaceBase = 0ULL - KernelVirtualAddressSpaceWidth; |
| 16 | constexpr std::size_t KernelVirtualAddressSpaceEnd = | 37 | constexpr std::size_t KernelVirtualAddressSpaceEnd = |
| 17 | KernelVirtualAddressSpaceBase + (KernelVirtualAddressSpaceWidth - KernelAslrAlignment); | 38 | KernelVirtualAddressSpaceBase + (KernelVirtualAddressSpaceWidth - KernelAslrAlignment); |
| 18 | constexpr std::size_t KernelVirtualAddressSpaceLast = KernelVirtualAddressSpaceEnd - 1; | 39 | constexpr std::size_t KernelVirtualAddressSpaceLast = KernelVirtualAddressSpaceEnd - 1ULL; |
| 19 | constexpr std::size_t KernelVirtualAddressSpaceSize = | 40 | constexpr std::size_t KernelVirtualAddressSpaceSize = |
| 20 | KernelVirtualAddressSpaceEnd - KernelVirtualAddressSpaceBase; | 41 | KernelVirtualAddressSpaceEnd - KernelVirtualAddressSpaceBase; |
| 42 | constexpr std::size_t KernelVirtualAddressCodeBase = KernelVirtualAddressSpaceBase; | ||
| 43 | constexpr std::size_t KernelVirtualAddressCodeSize = 0x62000; | ||
| 44 | constexpr std::size_t KernelVirtualAddressCodeEnd = | ||
| 45 | KernelVirtualAddressCodeBase + KernelVirtualAddressCodeSize; | ||
| 46 | |||
| 47 | constexpr std::size_t KernelPhysicalAddressSpaceBase = 0ULL; | ||
| 48 | constexpr std::size_t KernelPhysicalAddressSpaceEnd = | ||
| 49 | KernelPhysicalAddressSpaceBase + KernelPhysicalAddressSpaceWidth; | ||
| 50 | constexpr std::size_t KernelPhysicalAddressSpaceLast = KernelPhysicalAddressSpaceEnd - 1ULL; | ||
| 51 | constexpr std::size_t KernelPhysicalAddressSpaceSize = | ||
| 52 | KernelPhysicalAddressSpaceEnd - KernelPhysicalAddressSpaceBase; | ||
| 53 | constexpr std::size_t KernelPhysicalAddressCodeBase = DramPhysicalAddress + ReservedEarlyDramSize; | ||
| 54 | |||
| 55 | constexpr std::size_t KernelPageTableHeapSize = GetMaximumOverheadSize(MainMemorySizeMax); | ||
| 56 | constexpr std::size_t KernelInitialPageHeapSize = Common::Size_128_KB; | ||
| 57 | |||
| 58 | constexpr std::size_t KernelSlabHeapDataSize = Common::Size_5_MB; | ||
| 59 | constexpr std::size_t KernelSlabHeapGapsSize = Common::Size_2_MB - Common::Size_64_KB; | ||
| 60 | constexpr std::size_t KernelSlabHeapSize = KernelSlabHeapDataSize + KernelSlabHeapGapsSize; | ||
| 61 | |||
| 62 | // NOTE: This is calculated from KThread slab counts, assuming KThread size <= 0x860. | ||
| 63 | constexpr std::size_t KernelSlabHeapAdditionalSize = 0x68000ULL; | ||
| 64 | |||
| 65 | constexpr std::size_t KernelResourceSize = | ||
| 66 | KernelPageTableHeapSize + KernelInitialPageHeapSize + KernelSlabHeapSize; | ||
| 21 | 67 | ||
| 22 | constexpr bool IsKernelAddressKey(VAddr key) { | 68 | constexpr bool IsKernelAddressKey(VAddr key) { |
| 23 | return KernelVirtualAddressSpaceBase <= key && key <= KernelVirtualAddressSpaceLast; | 69 | return KernelVirtualAddressSpaceBase <= key && key <= KernelVirtualAddressSpaceLast; |
| @@ -27,64 +73,327 @@ constexpr bool IsKernelAddress(VAddr address) { | |||
| 27 | return KernelVirtualAddressSpaceBase <= address && address < KernelVirtualAddressSpaceEnd; | 73 | return KernelVirtualAddressSpaceBase <= address && address < KernelVirtualAddressSpaceEnd; |
| 28 | } | 74 | } |
| 29 | 75 | ||
| 30 | class KMemoryRegion final { | 76 | class KMemoryLayout final { |
| 31 | friend class KMemoryLayout; | ||
| 32 | |||
| 33 | public: | 77 | public: |
| 34 | constexpr PAddr StartAddress() const { | 78 | KMemoryLayout(); |
| 35 | return start_address; | 79 | |
| 80 | KMemoryRegionTree& GetVirtualMemoryRegionTree() { | ||
| 81 | return virtual_tree; | ||
| 82 | } | ||
| 83 | const KMemoryRegionTree& GetVirtualMemoryRegionTree() const { | ||
| 84 | return virtual_tree; | ||
| 85 | } | ||
| 86 | KMemoryRegionTree& GetPhysicalMemoryRegionTree() { | ||
| 87 | return physical_tree; | ||
| 88 | } | ||
| 89 | const KMemoryRegionTree& GetPhysicalMemoryRegionTree() const { | ||
| 90 | return physical_tree; | ||
| 91 | } | ||
| 92 | KMemoryRegionTree& GetVirtualLinearMemoryRegionTree() { | ||
| 93 | return virtual_linear_tree; | ||
| 94 | } | ||
| 95 | const KMemoryRegionTree& GetVirtualLinearMemoryRegionTree() const { | ||
| 96 | return virtual_linear_tree; | ||
| 97 | } | ||
| 98 | KMemoryRegionTree& GetPhysicalLinearMemoryRegionTree() { | ||
| 99 | return physical_linear_tree; | ||
| 100 | } | ||
| 101 | const KMemoryRegionTree& GetPhysicalLinearMemoryRegionTree() const { | ||
| 102 | return physical_linear_tree; | ||
| 103 | } | ||
| 104 | |||
| 105 | VAddr GetLinearVirtualAddress(PAddr address) const { | ||
| 106 | return address + linear_phys_to_virt_diff; | ||
| 107 | } | ||
| 108 | PAddr GetLinearPhysicalAddress(VAddr address) const { | ||
| 109 | return address + linear_virt_to_phys_diff; | ||
| 110 | } | ||
| 111 | |||
| 112 | const KMemoryRegion* FindVirtual(VAddr address) const { | ||
| 113 | return Find(address, GetVirtualMemoryRegionTree()); | ||
| 114 | } | ||
| 115 | const KMemoryRegion* FindPhysical(PAddr address) const { | ||
| 116 | return Find(address, GetPhysicalMemoryRegionTree()); | ||
| 117 | } | ||
| 118 | |||
| 119 | const KMemoryRegion* FindVirtualLinear(VAddr address) const { | ||
| 120 | return Find(address, GetVirtualLinearMemoryRegionTree()); | ||
| 121 | } | ||
| 122 | const KMemoryRegion* FindPhysicalLinear(PAddr address) const { | ||
| 123 | return Find(address, GetPhysicalLinearMemoryRegionTree()); | ||
| 124 | } | ||
| 125 | |||
| 126 | VAddr GetMainStackTopAddress(s32 core_id) const { | ||
| 127 | return GetStackTopAddress(core_id, KMemoryRegionType_KernelMiscMainStack); | ||
| 128 | } | ||
| 129 | VAddr GetIdleStackTopAddress(s32 core_id) const { | ||
| 130 | return GetStackTopAddress(core_id, KMemoryRegionType_KernelMiscIdleStack); | ||
| 131 | } | ||
| 132 | VAddr GetExceptionStackTopAddress(s32 core_id) const { | ||
| 133 | return GetStackTopAddress(core_id, KMemoryRegionType_KernelMiscExceptionStack); | ||
| 134 | } | ||
| 135 | |||
| 136 | VAddr GetSlabRegionAddress() const { | ||
| 137 | return Dereference(GetVirtualMemoryRegionTree().FindByType(KMemoryRegionType_KernelSlab)) | ||
| 138 | .GetAddress(); | ||
| 139 | } | ||
| 140 | |||
| 141 | const KMemoryRegion& GetDeviceRegion(KMemoryRegionType type) const { | ||
| 142 | return Dereference(GetPhysicalMemoryRegionTree().FindFirstDerived(type)); | ||
| 143 | } | ||
| 144 | PAddr GetDevicePhysicalAddress(KMemoryRegionType type) const { | ||
| 145 | return GetDeviceRegion(type).GetAddress(); | ||
| 146 | } | ||
| 147 | VAddr GetDeviceVirtualAddress(KMemoryRegionType type) const { | ||
| 148 | return GetDeviceRegion(type).GetPairAddress(); | ||
| 149 | } | ||
| 150 | |||
| 151 | const KMemoryRegion& GetPoolManagementRegion() const { | ||
| 152 | return Dereference( | ||
| 153 | GetVirtualMemoryRegionTree().FindByType(KMemoryRegionType_VirtualDramPoolManagement)); | ||
| 154 | } | ||
| 155 | const KMemoryRegion& GetPageTableHeapRegion() const { | ||
| 156 | return Dereference( | ||
| 157 | GetVirtualMemoryRegionTree().FindByType(KMemoryRegionType_VirtualDramKernelPtHeap)); | ||
| 158 | } | ||
| 159 | const KMemoryRegion& GetKernelStackRegion() const { | ||
| 160 | return Dereference(GetVirtualMemoryRegionTree().FindByType(KMemoryRegionType_KernelStack)); | ||
| 161 | } | ||
| 162 | const KMemoryRegion& GetTempRegion() const { | ||
| 163 | return Dereference(GetVirtualMemoryRegionTree().FindByType(KMemoryRegionType_KernelTemp)); | ||
| 164 | } | ||
| 165 | |||
| 166 | const KMemoryRegion& GetKernelTraceBufferRegion() const { | ||
| 167 | return Dereference(GetVirtualLinearMemoryRegionTree().FindByType( | ||
| 168 | KMemoryRegionType_VirtualDramKernelTraceBuffer)); | ||
| 169 | } | ||
| 170 | |||
| 171 | const KMemoryRegion& GetVirtualLinearRegion(VAddr address) const { | ||
| 172 | return Dereference(FindVirtualLinear(address)); | ||
| 173 | } | ||
| 174 | |||
| 175 | const KMemoryRegion* GetPhysicalKernelTraceBufferRegion() const { | ||
| 176 | return GetPhysicalMemoryRegionTree().FindFirstDerived(KMemoryRegionType_KernelTraceBuffer); | ||
| 177 | } | ||
| 178 | const KMemoryRegion* GetPhysicalOnMemoryBootImageRegion() const { | ||
| 179 | return GetPhysicalMemoryRegionTree().FindFirstDerived(KMemoryRegionType_OnMemoryBootImage); | ||
| 180 | } | ||
| 181 | const KMemoryRegion* GetPhysicalDTBRegion() const { | ||
| 182 | return GetPhysicalMemoryRegionTree().FindFirstDerived(KMemoryRegionType_DTB); | ||
| 183 | } | ||
| 184 | |||
| 185 | bool IsHeapPhysicalAddress(const KMemoryRegion*& region, PAddr address) const { | ||
| 186 | return IsTypedAddress(region, address, GetPhysicalLinearMemoryRegionTree(), | ||
| 187 | KMemoryRegionType_DramUserPool); | ||
| 188 | } | ||
| 189 | bool IsHeapVirtualAddress(const KMemoryRegion*& region, VAddr address) const { | ||
| 190 | return IsTypedAddress(region, address, GetVirtualLinearMemoryRegionTree(), | ||
| 191 | KMemoryRegionType_VirtualDramUserPool); | ||
| 192 | } | ||
| 193 | |||
| 194 | bool IsHeapPhysicalAddress(const KMemoryRegion*& region, PAddr address, size_t size) const { | ||
| 195 | return IsTypedAddress(region, address, size, GetPhysicalLinearMemoryRegionTree(), | ||
| 196 | KMemoryRegionType_DramUserPool); | ||
| 197 | } | ||
| 198 | bool IsHeapVirtualAddress(const KMemoryRegion*& region, VAddr address, size_t size) const { | ||
| 199 | return IsTypedAddress(region, address, size, GetVirtualLinearMemoryRegionTree(), | ||
| 200 | KMemoryRegionType_VirtualDramUserPool); | ||
| 201 | } | ||
| 202 | |||
| 203 | bool IsLinearMappedPhysicalAddress(const KMemoryRegion*& region, PAddr address) const { | ||
| 204 | return IsTypedAddress(region, address, GetPhysicalLinearMemoryRegionTree(), | ||
| 205 | static_cast<KMemoryRegionType>(KMemoryRegionAttr_LinearMapped)); | ||
| 206 | } | ||
| 207 | bool IsLinearMappedPhysicalAddress(const KMemoryRegion*& region, PAddr address, | ||
| 208 | size_t size) const { | ||
| 209 | return IsTypedAddress(region, address, size, GetPhysicalLinearMemoryRegionTree(), | ||
| 210 | static_cast<KMemoryRegionType>(KMemoryRegionAttr_LinearMapped)); | ||
| 211 | } | ||
| 212 | |||
| 213 | std::pair<size_t, size_t> GetTotalAndKernelMemorySizes() const { | ||
| 214 | size_t total_size = 0, kernel_size = 0; | ||
| 215 | for (const auto& region : GetPhysicalMemoryRegionTree()) { | ||
| 216 | if (region.IsDerivedFrom(KMemoryRegionType_Dram)) { | ||
| 217 | total_size += region.GetSize(); | ||
| 218 | if (!region.IsDerivedFrom(KMemoryRegionType_DramUserPool)) { | ||
| 219 | kernel_size += region.GetSize(); | ||
| 220 | } | ||
| 221 | } | ||
| 222 | } | ||
| 223 | return std::make_pair(total_size, kernel_size); | ||
| 224 | } | ||
| 225 | |||
| 226 | void InitializeLinearMemoryRegionTrees(PAddr aligned_linear_phys_start, | ||
| 227 | VAddr linear_virtual_start); | ||
| 228 | static size_t GetResourceRegionSizeForInit(); | ||
| 229 | |||
| 230 | auto GetKernelRegionExtents() const { | ||
| 231 | return GetVirtualMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_Kernel); | ||
| 232 | } | ||
| 233 | auto GetKernelCodeRegionExtents() const { | ||
| 234 | return GetVirtualMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_KernelCode); | ||
| 235 | } | ||
| 236 | auto GetKernelStackRegionExtents() const { | ||
| 237 | return GetVirtualMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_KernelStack); | ||
| 238 | } | ||
| 239 | auto GetKernelMiscRegionExtents() const { | ||
| 240 | return GetVirtualMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_KernelMisc); | ||
| 241 | } | ||
| 242 | auto GetKernelSlabRegionExtents() const { | ||
| 243 | return GetVirtualMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_KernelSlab); | ||
| 244 | } | ||
| 245 | |||
| 246 | auto GetLinearRegionPhysicalExtents() const { | ||
| 247 | return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents( | ||
| 248 | KMemoryRegionAttr_LinearMapped); | ||
| 249 | } | ||
| 250 | |||
| 251 | auto GetLinearRegionVirtualExtents() const { | ||
| 252 | const auto physical = GetLinearRegionPhysicalExtents(); | ||
| 253 | return KMemoryRegion(GetLinearVirtualAddress(physical.GetAddress()), | ||
| 254 | GetLinearVirtualAddress(physical.GetLastAddress()), 0, | ||
| 255 | KMemoryRegionType_None); | ||
| 256 | } | ||
| 257 | |||
| 258 | auto GetMainMemoryPhysicalExtents() const { | ||
| 259 | return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_Dram); | ||
| 260 | } | ||
| 261 | auto GetCarveoutRegionExtents() const { | ||
| 262 | return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents( | ||
| 263 | KMemoryRegionAttr_CarveoutProtected); | ||
| 264 | } | ||
| 265 | |||
| 266 | auto GetKernelRegionPhysicalExtents() const { | ||
| 267 | return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents( | ||
| 268 | KMemoryRegionType_DramKernelBase); | ||
| 269 | } | ||
| 270 | auto GetKernelCodeRegionPhysicalExtents() const { | ||
| 271 | return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents( | ||
| 272 | KMemoryRegionType_DramKernelCode); | ||
| 273 | } | ||
| 274 | auto GetKernelSlabRegionPhysicalExtents() const { | ||
| 275 | return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents( | ||
| 276 | KMemoryRegionType_DramKernelSlab); | ||
| 277 | } | ||
| 278 | auto GetKernelPageTableHeapRegionPhysicalExtents() const { | ||
| 279 | return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents( | ||
| 280 | KMemoryRegionType_DramKernelPtHeap); | ||
| 281 | } | ||
| 282 | auto GetKernelInitPageTableRegionPhysicalExtents() const { | ||
| 283 | return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents( | ||
| 284 | KMemoryRegionType_DramKernelInitPt); | ||
| 285 | } | ||
| 286 | |||
| 287 | auto GetKernelPoolManagementRegionPhysicalExtents() const { | ||
| 288 | return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents( | ||
| 289 | KMemoryRegionType_DramPoolManagement); | ||
| 290 | } | ||
| 291 | auto GetKernelPoolPartitionRegionPhysicalExtents() const { | ||
| 292 | return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents( | ||
| 293 | KMemoryRegionType_DramPoolPartition); | ||
| 294 | } | ||
| 295 | auto GetKernelSystemPoolRegionPhysicalExtents() const { | ||
| 296 | return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents( | ||
| 297 | KMemoryRegionType_DramSystemPool); | ||
| 298 | } | ||
| 299 | auto GetKernelSystemNonSecurePoolRegionPhysicalExtents() const { | ||
| 300 | return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents( | ||
| 301 | KMemoryRegionType_DramSystemNonSecurePool); | ||
| 302 | } | ||
| 303 | auto GetKernelAppletPoolRegionPhysicalExtents() const { | ||
| 304 | return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents( | ||
| 305 | KMemoryRegionType_DramAppletPool); | ||
| 306 | } | ||
| 307 | auto GetKernelApplicationPoolRegionPhysicalExtents() const { | ||
| 308 | return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents( | ||
| 309 | KMemoryRegionType_DramApplicationPool); | ||
| 36 | } | 310 | } |
| 37 | 311 | ||
| 38 | constexpr PAddr EndAddress() const { | 312 | auto GetKernelTraceBufferRegionPhysicalExtents() const { |
| 39 | return end_address; | 313 | return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents( |
| 314 | KMemoryRegionType_KernelTraceBuffer); | ||
| 40 | } | 315 | } |
| 41 | 316 | ||
| 42 | private: | 317 | private: |
| 43 | constexpr KMemoryRegion() = default; | 318 | template <typename AddressType> |
| 44 | constexpr KMemoryRegion(PAddr start_address, PAddr end_address) | 319 | static bool IsTypedAddress(const KMemoryRegion*& region, AddressType address, |
| 45 | : start_address{start_address}, end_address{end_address} {} | 320 | const KMemoryRegionTree& tree, KMemoryRegionType type) { |
| 321 | // Check if the cached region already contains the address. | ||
| 322 | if (region != nullptr && region->Contains(address)) { | ||
| 323 | return true; | ||
| 324 | } | ||
| 46 | 325 | ||
| 47 | const PAddr start_address{}; | 326 | // Find the containing region, and update the cache. |
| 48 | const PAddr end_address{}; | 327 | if (const KMemoryRegion* found = tree.Find(address); |
| 49 | }; | 328 | found != nullptr && found->IsDerivedFrom(type)) { |
| 329 | region = found; | ||
| 330 | return true; | ||
| 331 | } else { | ||
| 332 | return false; | ||
| 333 | } | ||
| 334 | } | ||
| 50 | 335 | ||
| 51 | class KMemoryLayout final { | 336 | template <typename AddressType> |
| 52 | public: | 337 | static bool IsTypedAddress(const KMemoryRegion*& region, AddressType address, size_t size, |
| 53 | constexpr const KMemoryRegion& Application() const { | 338 | const KMemoryRegionTree& tree, KMemoryRegionType type) { |
| 54 | return application; | 339 | // Get the end of the checked region. |
| 340 | const u64 last_address = address + size - 1; | ||
| 341 | |||
| 342 | // Walk the tree to verify the region is correct. | ||
| 343 | const KMemoryRegion* cur = | ||
| 344 | (region != nullptr && region->Contains(address)) ? region : tree.Find(address); | ||
| 345 | while (cur != nullptr && cur->IsDerivedFrom(type)) { | ||
| 346 | if (last_address <= cur->GetLastAddress()) { | ||
| 347 | region = cur; | ||
| 348 | return true; | ||
| 349 | } | ||
| 350 | |||
| 351 | cur = cur->GetNext(); | ||
| 352 | } | ||
| 353 | return false; | ||
| 55 | } | 354 | } |
| 56 | 355 | ||
| 57 | constexpr const KMemoryRegion& Applet() const { | 356 | template <typename AddressType> |
| 58 | return applet; | 357 | static const KMemoryRegion* Find(AddressType address, const KMemoryRegionTree& tree) { |
| 358 | return tree.Find(address); | ||
| 59 | } | 359 | } |
| 60 | 360 | ||
| 61 | constexpr const KMemoryRegion& System() const { | 361 | static KMemoryRegion& Dereference(KMemoryRegion* region) { |
| 62 | return system; | 362 | ASSERT(region != nullptr); |
| 363 | return *region; | ||
| 63 | } | 364 | } |
| 64 | 365 | ||
| 65 | static constexpr KMemoryLayout GetDefaultLayout() { | 366 | static const KMemoryRegion& Dereference(const KMemoryRegion* region) { |
| 66 | constexpr std::size_t application_size{0xcd500000}; | 367 | ASSERT(region != nullptr); |
| 67 | constexpr std::size_t applet_size{0x1fb00000}; | 368 | return *region; |
| 68 | constexpr PAddr application_start_address{Core::DramMemoryMap::End - application_size}; | 369 | } |
| 69 | constexpr PAddr application_end_address{Core::DramMemoryMap::End}; | 370 | |
| 70 | constexpr PAddr applet_start_address{application_start_address - applet_size}; | 371 | VAddr GetStackTopAddress(s32 core_id, KMemoryRegionType type) const { |
| 71 | constexpr PAddr applet_end_address{applet_start_address + applet_size}; | 372 | const auto& region = Dereference( |
| 72 | constexpr PAddr system_start_address{Core::DramMemoryMap::SlabHeapEnd}; | 373 | GetVirtualMemoryRegionTree().FindByTypeAndAttribute(type, static_cast<u32>(core_id))); |
| 73 | constexpr PAddr system_end_address{applet_start_address}; | 374 | ASSERT(region.GetEndAddress() != 0); |
| 74 | return {application_start_address, application_end_address, applet_start_address, | 375 | return region.GetEndAddress(); |
| 75 | applet_end_address, system_start_address, system_end_address}; | ||
| 76 | } | 376 | } |
| 77 | 377 | ||
| 78 | private: | 378 | private: |
| 79 | constexpr KMemoryLayout(PAddr application_start_address, std::size_t application_size, | 379 | u64 linear_phys_to_virt_diff{}; |
| 80 | PAddr applet_start_address, std::size_t applet_size, | 380 | u64 linear_virt_to_phys_diff{}; |
| 81 | PAddr system_start_address, std::size_t system_size) | 381 | KMemoryRegionAllocator memory_region_allocator; |
| 82 | : application{application_start_address, application_size}, | 382 | KMemoryRegionTree virtual_tree; |
| 83 | applet{applet_start_address, applet_size}, system{system_start_address, system_size} {} | 383 | KMemoryRegionTree physical_tree; |
| 84 | 384 | KMemoryRegionTree virtual_linear_tree; | |
| 85 | const KMemoryRegion application; | 385 | KMemoryRegionTree physical_linear_tree; |
| 86 | const KMemoryRegion applet; | ||
| 87 | const KMemoryRegion system; | ||
| 88 | }; | 386 | }; |
| 89 | 387 | ||
| 388 | namespace Init { | ||
| 389 | |||
| 390 | // These should be generic, regardless of board. | ||
| 391 | void SetupPoolPartitionMemoryRegions(KMemoryLayout& memory_layout); | ||
| 392 | |||
| 393 | // These may be implemented in a board-specific manner. | ||
| 394 | void SetupDevicePhysicalMemoryRegions(KMemoryLayout& memory_layout); | ||
| 395 | void SetupDramPhysicalMemoryRegions(KMemoryLayout& memory_layout); | ||
| 396 | |||
| 397 | } // namespace Init | ||
| 398 | |||
| 90 | } // namespace Kernel | 399 | } // namespace Kernel |
diff --git a/src/core/hle/kernel/k_memory_manager.cpp b/src/core/hle/kernel/k_memory_manager.cpp index 9027602bf..aa71697b2 100644 --- a/src/core/hle/kernel/k_memory_manager.cpp +++ b/src/core/hle/kernel/k_memory_manager.cpp | |||
| @@ -173,4 +173,16 @@ ResultCode KMemoryManager::Free(KPageLinkedList& page_list, std::size_t num_page | |||
| 173 | return RESULT_SUCCESS; | 173 | return RESULT_SUCCESS; |
| 174 | } | 174 | } |
| 175 | 175 | ||
| 176 | std::size_t KMemoryManager::Impl::CalculateManagementOverheadSize(std::size_t region_size) { | ||
| 177 | const std::size_t ref_count_size = (region_size / PageSize) * sizeof(u16); | ||
| 178 | const std::size_t optimize_map_size = | ||
| 179 | (Common::AlignUp((region_size / PageSize), Common::BitSize<u64>()) / | ||
| 180 | Common::BitSize<u64>()) * | ||
| 181 | sizeof(u64); | ||
| 182 | const std::size_t manager_meta_size = | ||
| 183 | Common::AlignUp(optimize_map_size + ref_count_size, PageSize); | ||
| 184 | const std::size_t page_heap_size = KPageHeap::CalculateManagementOverheadSize(region_size); | ||
| 185 | return manager_meta_size + page_heap_size; | ||
| 186 | } | ||
| 187 | |||
| 176 | } // namespace Kernel | 188 | } // namespace Kernel |
diff --git a/src/core/hle/kernel/k_memory_manager.h b/src/core/hle/kernel/k_memory_manager.h index ae9f683b8..ac840b3d0 100644 --- a/src/core/hle/kernel/k_memory_manager.h +++ b/src/core/hle/kernel/k_memory_manager.h | |||
| @@ -29,6 +29,10 @@ public: | |||
| 29 | 29 | ||
| 30 | Shift = 4, | 30 | Shift = 4, |
| 31 | Mask = (0xF << Shift), | 31 | Mask = (0xF << Shift), |
| 32 | |||
| 33 | // Aliases. | ||
| 34 | Unsafe = Application, | ||
| 35 | Secure = System, | ||
| 32 | }; | 36 | }; |
| 33 | 37 | ||
| 34 | enum class Direction : u32 { | 38 | enum class Direction : u32 { |
| @@ -56,6 +60,10 @@ public: | |||
| 56 | static constexpr std::size_t MaxManagerCount = 10; | 60 | static constexpr std::size_t MaxManagerCount = 10; |
| 57 | 61 | ||
| 58 | public: | 62 | public: |
| 63 | static std::size_t CalculateManagementOverheadSize(std::size_t region_size) { | ||
| 64 | return Impl::CalculateManagementOverheadSize(region_size); | ||
| 65 | } | ||
| 66 | |||
| 59 | static constexpr u32 EncodeOption(Pool pool, Direction dir) { | 67 | static constexpr u32 EncodeOption(Pool pool, Direction dir) { |
| 60 | return (static_cast<u32>(pool) << static_cast<u32>(Pool::Shift)) | | 68 | return (static_cast<u32>(pool) << static_cast<u32>(Pool::Shift)) | |
| 61 | (static_cast<u32>(dir) << static_cast<u32>(Direction::Shift)); | 69 | (static_cast<u32>(dir) << static_cast<u32>(Direction::Shift)); |
| @@ -86,6 +94,16 @@ private: | |||
| 86 | Pool pool{}; | 94 | Pool pool{}; |
| 87 | 95 | ||
| 88 | public: | 96 | public: |
| 97 | static std::size_t CalculateManagementOverheadSize(std::size_t region_size); | ||
| 98 | |||
| 99 | static constexpr std::size_t CalculateOptimizedProcessOverheadSize( | ||
| 100 | std::size_t region_size) { | ||
| 101 | return (Common::AlignUp((region_size / PageSize), Common::BitSize<u64>()) / | ||
| 102 | Common::BitSize<u64>()) * | ||
| 103 | sizeof(u64); | ||
| 104 | } | ||
| 105 | |||
| 106 | public: | ||
| 89 | Impl() = default; | 107 | Impl() = default; |
| 90 | 108 | ||
| 91 | std::size_t Initialize(Pool new_pool, u64 start_address, u64 end_address); | 109 | std::size_t Initialize(Pool new_pool, u64 start_address, u64 end_address); |
diff --git a/src/core/hle/kernel/k_memory_region.h b/src/core/hle/kernel/k_memory_region.h new file mode 100644 index 000000000..a861c04ab --- /dev/null +++ b/src/core/hle/kernel/k_memory_region.h | |||
| @@ -0,0 +1,350 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include "common/assert.h" | ||
| 8 | #include "common/common_types.h" | ||
| 9 | #include "common/intrusive_red_black_tree.h" | ||
| 10 | #include "core/hle/kernel/k_memory_region_type.h" | ||
| 11 | |||
| 12 | namespace Kernel { | ||
| 13 | |||
| 14 | class KMemoryRegionAllocator; | ||
| 15 | |||
| 16 | class KMemoryRegion final : public Common::IntrusiveRedBlackTreeBaseNode<KMemoryRegion>, | ||
| 17 | NonCopyable { | ||
| 18 | friend class KMemoryRegionTree; | ||
| 19 | |||
| 20 | public: | ||
| 21 | constexpr KMemoryRegion() = default; | ||
| 22 | constexpr KMemoryRegion(u64 address_, u64 last_address_) | ||
| 23 | : address{address_}, last_address{last_address_} {} | ||
| 24 | constexpr KMemoryRegion(u64 address_, u64 last_address_, u64 pair_address_, u32 attributes_, | ||
| 25 | u32 type_id_) | ||
| 26 | : address(address_), last_address(last_address_), pair_address(pair_address_), | ||
| 27 | attributes(attributes_), type_id(type_id_) {} | ||
| 28 | constexpr KMemoryRegion(u64 address_, u64 last_address_, u32 attributes_, u32 type_id_) | ||
| 29 | : KMemoryRegion(address_, last_address_, std::numeric_limits<u64>::max(), attributes_, | ||
| 30 | type_id_) {} | ||
| 31 | |||
| 32 | static constexpr int Compare(const KMemoryRegion& lhs, const KMemoryRegion& rhs) { | ||
| 33 | if (lhs.GetAddress() < rhs.GetAddress()) { | ||
| 34 | return -1; | ||
| 35 | } else if (lhs.GetAddress() <= rhs.GetLastAddress()) { | ||
| 36 | return 0; | ||
| 37 | } else { | ||
| 38 | return 1; | ||
| 39 | } | ||
| 40 | } | ||
| 41 | |||
| 42 | private: | ||
| 43 | constexpr void Reset(u64 a, u64 la, u64 p, u32 r, u32 t) { | ||
| 44 | address = a; | ||
| 45 | pair_address = p; | ||
| 46 | last_address = la; | ||
| 47 | attributes = r; | ||
| 48 | type_id = t; | ||
| 49 | } | ||
| 50 | |||
| 51 | public: | ||
| 52 | constexpr u64 GetAddress() const { | ||
| 53 | return address; | ||
| 54 | } | ||
| 55 | |||
| 56 | constexpr u64 GetPairAddress() const { | ||
| 57 | return pair_address; | ||
| 58 | } | ||
| 59 | |||
| 60 | constexpr u64 GetLastAddress() const { | ||
| 61 | return last_address; | ||
| 62 | } | ||
| 63 | |||
| 64 | constexpr u64 GetEndAddress() const { | ||
| 65 | return this->GetLastAddress() + 1; | ||
| 66 | } | ||
| 67 | |||
| 68 | constexpr size_t GetSize() const { | ||
| 69 | return this->GetEndAddress() - this->GetAddress(); | ||
| 70 | } | ||
| 71 | |||
| 72 | constexpr u32 GetAttributes() const { | ||
| 73 | return attributes; | ||
| 74 | } | ||
| 75 | |||
| 76 | constexpr u32 GetType() const { | ||
| 77 | return type_id; | ||
| 78 | } | ||
| 79 | |||
| 80 | constexpr void SetType(u32 type) { | ||
| 81 | ASSERT(this->CanDerive(type)); | ||
| 82 | type_id = type; | ||
| 83 | } | ||
| 84 | |||
| 85 | constexpr bool Contains(u64 address) const { | ||
| 86 | ASSERT(this->GetEndAddress() != 0); | ||
| 87 | return this->GetAddress() <= address && address <= this->GetLastAddress(); | ||
| 88 | } | ||
| 89 | |||
| 90 | constexpr bool IsDerivedFrom(u32 type) const { | ||
| 91 | return (this->GetType() | type) == this->GetType(); | ||
| 92 | } | ||
| 93 | |||
| 94 | constexpr bool HasTypeAttribute(u32 attr) const { | ||
| 95 | return (this->GetType() | attr) == this->GetType(); | ||
| 96 | } | ||
| 97 | |||
| 98 | constexpr bool CanDerive(u32 type) const { | ||
| 99 | return (this->GetType() | type) == type; | ||
| 100 | } | ||
| 101 | |||
| 102 | constexpr void SetPairAddress(u64 a) { | ||
| 103 | pair_address = a; | ||
| 104 | } | ||
| 105 | |||
| 106 | constexpr void SetTypeAttribute(u32 attr) { | ||
| 107 | type_id |= attr; | ||
| 108 | } | ||
| 109 | |||
| 110 | private: | ||
| 111 | u64 address{}; | ||
| 112 | u64 last_address{}; | ||
| 113 | u64 pair_address{}; | ||
| 114 | u32 attributes{}; | ||
| 115 | u32 type_id{}; | ||
| 116 | }; | ||
| 117 | |||
| 118 | class KMemoryRegionTree final : NonCopyable { | ||
| 119 | public: | ||
| 120 | struct DerivedRegionExtents { | ||
| 121 | const KMemoryRegion* first_region{}; | ||
| 122 | const KMemoryRegion* last_region{}; | ||
| 123 | |||
| 124 | constexpr DerivedRegionExtents() = default; | ||
| 125 | |||
| 126 | constexpr u64 GetAddress() const { | ||
| 127 | return this->first_region->GetAddress(); | ||
| 128 | } | ||
| 129 | |||
| 130 | constexpr u64 GetLastAddress() const { | ||
| 131 | return this->last_region->GetLastAddress(); | ||
| 132 | } | ||
| 133 | |||
| 134 | constexpr u64 GetEndAddress() const { | ||
| 135 | return this->GetLastAddress() + 1; | ||
| 136 | } | ||
| 137 | |||
| 138 | constexpr size_t GetSize() const { | ||
| 139 | return this->GetEndAddress() - this->GetAddress(); | ||
| 140 | } | ||
| 141 | }; | ||
| 142 | |||
| 143 | private: | ||
| 144 | using TreeType = | ||
| 145 | Common::IntrusiveRedBlackTreeBaseTraits<KMemoryRegion>::TreeType<KMemoryRegion>; | ||
| 146 | |||
| 147 | public: | ||
| 148 | using value_type = TreeType::value_type; | ||
| 149 | using size_type = TreeType::size_type; | ||
| 150 | using difference_type = TreeType::difference_type; | ||
| 151 | using pointer = TreeType::pointer; | ||
| 152 | using const_pointer = TreeType::const_pointer; | ||
| 153 | using reference = TreeType::reference; | ||
| 154 | using const_reference = TreeType::const_reference; | ||
| 155 | using iterator = TreeType::iterator; | ||
| 156 | using const_iterator = TreeType::const_iterator; | ||
| 157 | |||
| 158 | private: | ||
| 159 | TreeType m_tree{}; | ||
| 160 | KMemoryRegionAllocator& memory_region_allocator; | ||
| 161 | |||
| 162 | public: | ||
| 163 | explicit KMemoryRegionTree(KMemoryRegionAllocator& memory_region_allocator_); | ||
| 164 | |||
| 165 | public: | ||
| 166 | KMemoryRegion* FindModifiable(u64 address) { | ||
| 167 | if (auto it = this->find(KMemoryRegion(address, address, 0, 0)); it != this->end()) { | ||
| 168 | return std::addressof(*it); | ||
| 169 | } else { | ||
| 170 | return nullptr; | ||
| 171 | } | ||
| 172 | } | ||
| 173 | |||
| 174 | const KMemoryRegion* Find(u64 address) const { | ||
| 175 | if (auto it = this->find(KMemoryRegion(address, address, 0, 0)); it != this->cend()) { | ||
| 176 | return std::addressof(*it); | ||
| 177 | } else { | ||
| 178 | return nullptr; | ||
| 179 | } | ||
| 180 | } | ||
| 181 | |||
| 182 | const KMemoryRegion* FindByType(KMemoryRegionType type_id) const { | ||
| 183 | for (auto it = this->cbegin(); it != this->cend(); ++it) { | ||
| 184 | if (it->GetType() == static_cast<u32>(type_id)) { | ||
| 185 | return std::addressof(*it); | ||
| 186 | } | ||
| 187 | } | ||
| 188 | return nullptr; | ||
| 189 | } | ||
| 190 | |||
| 191 | const KMemoryRegion* FindByTypeAndAttribute(u32 type_id, u32 attr) const { | ||
| 192 | for (auto it = this->cbegin(); it != this->cend(); ++it) { | ||
| 193 | if (it->GetType() == type_id && it->GetAttributes() == attr) { | ||
| 194 | return std::addressof(*it); | ||
| 195 | } | ||
| 196 | } | ||
| 197 | return nullptr; | ||
| 198 | } | ||
| 199 | |||
| 200 | const KMemoryRegion* FindFirstDerived(KMemoryRegionType type_id) const { | ||
| 201 | for (auto it = this->cbegin(); it != this->cend(); it++) { | ||
| 202 | if (it->IsDerivedFrom(type_id)) { | ||
| 203 | return std::addressof(*it); | ||
| 204 | } | ||
| 205 | } | ||
| 206 | return nullptr; | ||
| 207 | } | ||
| 208 | |||
| 209 | const KMemoryRegion* FindLastDerived(KMemoryRegionType type_id) const { | ||
| 210 | const KMemoryRegion* region = nullptr; | ||
| 211 | for (auto it = this->begin(); it != this->end(); it++) { | ||
| 212 | if (it->IsDerivedFrom(type_id)) { | ||
| 213 | region = std::addressof(*it); | ||
| 214 | } | ||
| 215 | } | ||
| 216 | return region; | ||
| 217 | } | ||
| 218 | |||
| 219 | DerivedRegionExtents GetDerivedRegionExtents(KMemoryRegionType type_id) const { | ||
| 220 | DerivedRegionExtents extents; | ||
| 221 | |||
| 222 | ASSERT(extents.first_region == nullptr); | ||
| 223 | ASSERT(extents.last_region == nullptr); | ||
| 224 | |||
| 225 | for (auto it = this->cbegin(); it != this->cend(); it++) { | ||
| 226 | if (it->IsDerivedFrom(type_id)) { | ||
| 227 | if (extents.first_region == nullptr) { | ||
| 228 | extents.first_region = std::addressof(*it); | ||
| 229 | } | ||
| 230 | extents.last_region = std::addressof(*it); | ||
| 231 | } | ||
| 232 | } | ||
| 233 | |||
| 234 | ASSERT(extents.first_region != nullptr); | ||
| 235 | ASSERT(extents.last_region != nullptr); | ||
| 236 | |||
| 237 | return extents; | ||
| 238 | } | ||
| 239 | |||
| 240 | DerivedRegionExtents GetDerivedRegionExtents(u32 type_id) const { | ||
| 241 | return GetDerivedRegionExtents(static_cast<KMemoryRegionType>(type_id)); | ||
| 242 | } | ||
| 243 | |||
| 244 | public: | ||
| 245 | void InsertDirectly(u64 address, u64 last_address, u32 attr = 0, u32 type_id = 0); | ||
| 246 | bool Insert(u64 address, size_t size, u32 type_id, u32 new_attr = 0, u32 old_attr = 0); | ||
| 247 | |||
| 248 | VAddr GetRandomAlignedRegion(size_t size, size_t alignment, u32 type_id); | ||
| 249 | |||
| 250 | VAddr GetRandomAlignedRegionWithGuard(size_t size, size_t alignment, u32 type_id, | ||
| 251 | size_t guard_size) { | ||
| 252 | return this->GetRandomAlignedRegion(size + 2 * guard_size, alignment, type_id) + guard_size; | ||
| 253 | } | ||
| 254 | |||
| 255 | public: | ||
| 256 | // Iterator accessors. | ||
| 257 | iterator begin() { | ||
| 258 | return m_tree.begin(); | ||
| 259 | } | ||
| 260 | |||
| 261 | const_iterator begin() const { | ||
| 262 | return m_tree.begin(); | ||
| 263 | } | ||
| 264 | |||
| 265 | iterator end() { | ||
| 266 | return m_tree.end(); | ||
| 267 | } | ||
| 268 | |||
| 269 | const_iterator end() const { | ||
| 270 | return m_tree.end(); | ||
| 271 | } | ||
| 272 | |||
| 273 | const_iterator cbegin() const { | ||
| 274 | return this->begin(); | ||
| 275 | } | ||
| 276 | |||
| 277 | const_iterator cend() const { | ||
| 278 | return this->end(); | ||
| 279 | } | ||
| 280 | |||
| 281 | iterator iterator_to(reference ref) { | ||
| 282 | return m_tree.iterator_to(ref); | ||
| 283 | } | ||
| 284 | |||
| 285 | const_iterator iterator_to(const_reference ref) const { | ||
| 286 | return m_tree.iterator_to(ref); | ||
| 287 | } | ||
| 288 | |||
| 289 | // Content management. | ||
| 290 | bool empty() const { | ||
| 291 | return m_tree.empty(); | ||
| 292 | } | ||
| 293 | |||
| 294 | reference back() { | ||
| 295 | return m_tree.back(); | ||
| 296 | } | ||
| 297 | |||
| 298 | const_reference back() const { | ||
| 299 | return m_tree.back(); | ||
| 300 | } | ||
| 301 | |||
| 302 | reference front() { | ||
| 303 | return m_tree.front(); | ||
| 304 | } | ||
| 305 | |||
| 306 | const_reference front() const { | ||
| 307 | return m_tree.front(); | ||
| 308 | } | ||
| 309 | |||
| 310 | iterator insert(reference ref) { | ||
| 311 | return m_tree.insert(ref); | ||
| 312 | } | ||
| 313 | |||
| 314 | iterator erase(iterator it) { | ||
| 315 | return m_tree.erase(it); | ||
| 316 | } | ||
| 317 | |||
| 318 | iterator find(const_reference ref) const { | ||
| 319 | return m_tree.find(ref); | ||
| 320 | } | ||
| 321 | |||
| 322 | iterator nfind(const_reference ref) const { | ||
| 323 | return m_tree.nfind(ref); | ||
| 324 | } | ||
| 325 | }; | ||
| 326 | |||
| 327 | class KMemoryRegionAllocator final : NonCopyable { | ||
| 328 | public: | ||
| 329 | static constexpr size_t MaxMemoryRegions = 200; | ||
| 330 | |||
| 331 | constexpr KMemoryRegionAllocator() = default; | ||
| 332 | |||
| 333 | template <typename... Args> | ||
| 334 | KMemoryRegion* Allocate(Args&&... args) { | ||
| 335 | // Ensure we stay within the bounds of our heap. | ||
| 336 | ASSERT(this->num_regions < MaxMemoryRegions); | ||
| 337 | |||
| 338 | // Create the new region. | ||
| 339 | KMemoryRegion* region = std::addressof(this->region_heap[this->num_regions++]); | ||
| 340 | new (region) KMemoryRegion(std::forward<Args>(args)...); | ||
| 341 | |||
| 342 | return region; | ||
| 343 | } | ||
| 344 | |||
| 345 | private: | ||
| 346 | std::array<KMemoryRegion, MaxMemoryRegions> region_heap{}; | ||
| 347 | size_t num_regions{}; | ||
| 348 | }; | ||
| 349 | |||
| 350 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/k_memory_region_type.h b/src/core/hle/kernel/k_memory_region_type.h new file mode 100644 index 000000000..a05e66677 --- /dev/null +++ b/src/core/hle/kernel/k_memory_region_type.h | |||
| @@ -0,0 +1,338 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include "common/bit_util.h" | ||
| 8 | #include "common/common_funcs.h" | ||
| 9 | #include "common/common_types.h" | ||
| 10 | |||
| 11 | #define ARCH_ARM64 | ||
| 12 | #define BOARD_NINTENDO_NX | ||
| 13 | |||
| 14 | namespace Kernel { | ||
| 15 | |||
| 16 | enum KMemoryRegionType : u32 { | ||
| 17 | KMemoryRegionAttr_CarveoutProtected = 0x04000000, | ||
| 18 | KMemoryRegionAttr_DidKernelMap = 0x08000000, | ||
| 19 | KMemoryRegionAttr_ShouldKernelMap = 0x10000000, | ||
| 20 | KMemoryRegionAttr_UserReadOnly = 0x20000000, | ||
| 21 | KMemoryRegionAttr_NoUserMap = 0x40000000, | ||
| 22 | KMemoryRegionAttr_LinearMapped = 0x80000000, | ||
| 23 | }; | ||
| 24 | DECLARE_ENUM_FLAG_OPERATORS(KMemoryRegionType); | ||
| 25 | |||
| 26 | namespace impl { | ||
| 27 | |||
| 28 | constexpr size_t BitsForDeriveSparse(size_t n) { | ||
| 29 | return n + 1; | ||
| 30 | } | ||
| 31 | |||
| 32 | constexpr size_t BitsForDeriveDense(size_t n) { | ||
| 33 | size_t low = 0, high = 1; | ||
| 34 | for (size_t i = 0; i < n - 1; ++i) { | ||
| 35 | if ((++low) == high) { | ||
| 36 | ++high; | ||
| 37 | low = 0; | ||
| 38 | } | ||
| 39 | } | ||
| 40 | return high + 1; | ||
| 41 | } | ||
| 42 | |||
| 43 | class KMemoryRegionTypeValue { | ||
| 44 | public: | ||
| 45 | using ValueType = std::underlying_type_t<KMemoryRegionType>; | ||
| 46 | |||
| 47 | constexpr KMemoryRegionTypeValue() = default; | ||
| 48 | |||
| 49 | constexpr operator KMemoryRegionType() const { | ||
| 50 | return static_cast<KMemoryRegionType>(m_value); | ||
| 51 | } | ||
| 52 | |||
| 53 | constexpr ValueType GetValue() const { | ||
| 54 | return m_value; | ||
| 55 | } | ||
| 56 | |||
| 57 | constexpr const KMemoryRegionTypeValue& Finalize() { | ||
| 58 | m_finalized = true; | ||
| 59 | return *this; | ||
| 60 | } | ||
| 61 | |||
| 62 | constexpr const KMemoryRegionTypeValue& SetSparseOnly() { | ||
| 63 | m_sparse_only = true; | ||
| 64 | return *this; | ||
| 65 | } | ||
| 66 | |||
| 67 | constexpr const KMemoryRegionTypeValue& SetDenseOnly() { | ||
| 68 | m_dense_only = true; | ||
| 69 | return *this; | ||
| 70 | } | ||
| 71 | |||
| 72 | constexpr KMemoryRegionTypeValue& SetAttribute(u32 attr) { | ||
| 73 | m_value |= attr; | ||
| 74 | return *this; | ||
| 75 | } | ||
| 76 | |||
| 77 | constexpr KMemoryRegionTypeValue DeriveInitial( | ||
| 78 | size_t i, size_t next = Common::BitSize<ValueType>()) const { | ||
| 79 | KMemoryRegionTypeValue new_type = *this; | ||
| 80 | new_type.m_value = (ValueType{1} << i); | ||
| 81 | new_type.m_next_bit = next; | ||
| 82 | return new_type; | ||
| 83 | } | ||
| 84 | |||
| 85 | constexpr KMemoryRegionTypeValue DeriveAttribute(u32 attr) const { | ||
| 86 | KMemoryRegionTypeValue new_type = *this; | ||
| 87 | new_type.m_value |= attr; | ||
| 88 | return new_type; | ||
| 89 | } | ||
| 90 | |||
| 91 | constexpr KMemoryRegionTypeValue DeriveTransition(size_t ofs = 0, size_t adv = 1) const { | ||
| 92 | KMemoryRegionTypeValue new_type = *this; | ||
| 93 | new_type.m_value |= (ValueType{1} << (m_next_bit + ofs)); | ||
| 94 | new_type.m_next_bit += adv; | ||
| 95 | return new_type; | ||
| 96 | } | ||
| 97 | |||
| 98 | constexpr KMemoryRegionTypeValue DeriveSparse(size_t ofs, size_t n, size_t i) const { | ||
| 99 | KMemoryRegionTypeValue new_type = *this; | ||
| 100 | new_type.m_value |= (ValueType{1} << (m_next_bit + ofs)); | ||
| 101 | new_type.m_value |= (ValueType{1} << (m_next_bit + ofs + 1 + i)); | ||
| 102 | new_type.m_next_bit += ofs + n + 1; | ||
| 103 | return new_type; | ||
| 104 | } | ||
| 105 | |||
| 106 | constexpr KMemoryRegionTypeValue Derive(size_t n, size_t i) const { | ||
| 107 | size_t low = 0, high = 1; | ||
| 108 | for (size_t j = 0; j < i; ++j) { | ||
| 109 | if ((++low) == high) { | ||
| 110 | ++high; | ||
| 111 | low = 0; | ||
| 112 | } | ||
| 113 | } | ||
| 114 | |||
| 115 | KMemoryRegionTypeValue new_type = *this; | ||
| 116 | new_type.m_value |= (ValueType{1} << (m_next_bit + low)); | ||
| 117 | new_type.m_value |= (ValueType{1} << (m_next_bit + high)); | ||
| 118 | new_type.m_next_bit += BitsForDeriveDense(n); | ||
| 119 | return new_type; | ||
| 120 | } | ||
| 121 | |||
| 122 | constexpr KMemoryRegionTypeValue Advance(size_t n) const { | ||
| 123 | KMemoryRegionTypeValue new_type = *this; | ||
| 124 | new_type.m_next_bit += n; | ||
| 125 | return new_type; | ||
| 126 | } | ||
| 127 | |||
| 128 | constexpr bool IsAncestorOf(ValueType v) const { | ||
| 129 | return (m_value | v) == v; | ||
| 130 | } | ||
| 131 | |||
| 132 | private: | ||
| 133 | constexpr KMemoryRegionTypeValue(ValueType v) : m_value(v) {} | ||
| 134 | |||
| 135 | private: | ||
| 136 | ValueType m_value{}; | ||
| 137 | size_t m_next_bit{}; | ||
| 138 | bool m_finalized{}; | ||
| 139 | bool m_sparse_only{}; | ||
| 140 | bool m_dense_only{}; | ||
| 141 | }; | ||
| 142 | |||
| 143 | } // namespace impl | ||
| 144 | |||
| 145 | constexpr auto KMemoryRegionType_None = impl::KMemoryRegionTypeValue(); | ||
| 146 | constexpr auto KMemoryRegionType_Kernel = KMemoryRegionType_None.DeriveInitial(0, 2); | ||
| 147 | constexpr auto KMemoryRegionType_Dram = KMemoryRegionType_None.DeriveInitial(1, 2); | ||
| 148 | static_assert(KMemoryRegionType_Kernel.GetValue() == 0x1); | ||
| 149 | static_assert(KMemoryRegionType_Dram.GetValue() == 0x2); | ||
| 150 | |||
| 151 | constexpr auto KMemoryRegionType_DramKernelBase = | ||
| 152 | KMemoryRegionType_Dram.DeriveSparse(0, 3, 0) | ||
| 153 | .SetAttribute(KMemoryRegionAttr_NoUserMap) | ||
| 154 | .SetAttribute(KMemoryRegionAttr_CarveoutProtected); | ||
| 155 | constexpr auto KMemoryRegionType_DramReservedBase = KMemoryRegionType_Dram.DeriveSparse(0, 3, 1); | ||
| 156 | constexpr auto KMemoryRegionType_DramHeapBase = | ||
| 157 | KMemoryRegionType_Dram.DeriveSparse(0, 3, 2).SetAttribute(KMemoryRegionAttr_LinearMapped); | ||
| 158 | static_assert(KMemoryRegionType_DramKernelBase.GetValue() == | ||
| 159 | (0xE | KMemoryRegionAttr_CarveoutProtected | KMemoryRegionAttr_NoUserMap)); | ||
| 160 | static_assert(KMemoryRegionType_DramReservedBase.GetValue() == (0x16)); | ||
| 161 | static_assert(KMemoryRegionType_DramHeapBase.GetValue() == (0x26 | KMemoryRegionAttr_LinearMapped)); | ||
| 162 | |||
| 163 | constexpr auto KMemoryRegionType_DramKernelCode = | ||
| 164 | KMemoryRegionType_DramKernelBase.DeriveSparse(0, 4, 0); | ||
| 165 | constexpr auto KMemoryRegionType_DramKernelSlab = | ||
| 166 | KMemoryRegionType_DramKernelBase.DeriveSparse(0, 4, 1); | ||
| 167 | constexpr auto KMemoryRegionType_DramKernelPtHeap = | ||
| 168 | KMemoryRegionType_DramKernelBase.DeriveSparse(0, 4, 2).SetAttribute( | ||
| 169 | KMemoryRegionAttr_LinearMapped); | ||
| 170 | constexpr auto KMemoryRegionType_DramKernelInitPt = | ||
| 171 | KMemoryRegionType_DramKernelBase.DeriveSparse(0, 4, 3).SetAttribute( | ||
| 172 | KMemoryRegionAttr_LinearMapped); | ||
| 173 | static_assert(KMemoryRegionType_DramKernelCode.GetValue() == | ||
| 174 | (0xCE | KMemoryRegionAttr_CarveoutProtected | KMemoryRegionAttr_NoUserMap)); | ||
| 175 | static_assert(KMemoryRegionType_DramKernelSlab.GetValue() == | ||
| 176 | (0x14E | KMemoryRegionAttr_CarveoutProtected | KMemoryRegionAttr_NoUserMap)); | ||
| 177 | static_assert(KMemoryRegionType_DramKernelPtHeap.GetValue() == | ||
| 178 | (0x24E | KMemoryRegionAttr_CarveoutProtected | KMemoryRegionAttr_NoUserMap | | ||
| 179 | KMemoryRegionAttr_LinearMapped)); | ||
| 180 | static_assert(KMemoryRegionType_DramKernelInitPt.GetValue() == | ||
| 181 | (0x44E | KMemoryRegionAttr_CarveoutProtected | KMemoryRegionAttr_NoUserMap | | ||
| 182 | KMemoryRegionAttr_LinearMapped)); | ||
| 183 | |||
| 184 | constexpr auto KMemoryRegionType_DramReservedEarly = | ||
| 185 | KMemoryRegionType_DramReservedBase.DeriveAttribute(KMemoryRegionAttr_NoUserMap); | ||
| 186 | static_assert(KMemoryRegionType_DramReservedEarly.GetValue() == | ||
| 187 | (0x16 | KMemoryRegionAttr_NoUserMap)); | ||
| 188 | |||
| 189 | constexpr auto KMemoryRegionType_KernelTraceBuffer = | ||
| 190 | KMemoryRegionType_DramReservedBase.DeriveSparse(0, 3, 0) | ||
| 191 | .SetAttribute(KMemoryRegionAttr_LinearMapped) | ||
| 192 | .SetAttribute(KMemoryRegionAttr_UserReadOnly); | ||
| 193 | constexpr auto KMemoryRegionType_OnMemoryBootImage = | ||
| 194 | KMemoryRegionType_DramReservedBase.DeriveSparse(0, 3, 1); | ||
| 195 | constexpr auto KMemoryRegionType_DTB = KMemoryRegionType_DramReservedBase.DeriveSparse(0, 3, 2); | ||
| 196 | static_assert(KMemoryRegionType_KernelTraceBuffer.GetValue() == | ||
| 197 | (0xD6 | KMemoryRegionAttr_LinearMapped | KMemoryRegionAttr_UserReadOnly)); | ||
| 198 | static_assert(KMemoryRegionType_OnMemoryBootImage.GetValue() == 0x156); | ||
| 199 | static_assert(KMemoryRegionType_DTB.GetValue() == 0x256); | ||
| 200 | |||
| 201 | constexpr auto KMemoryRegionType_DramPoolPartition = | ||
| 202 | KMemoryRegionType_DramHeapBase.DeriveAttribute(KMemoryRegionAttr_NoUserMap); | ||
| 203 | static_assert(KMemoryRegionType_DramPoolPartition.GetValue() == | ||
| 204 | (0x26 | KMemoryRegionAttr_LinearMapped | KMemoryRegionAttr_NoUserMap)); | ||
| 205 | |||
| 206 | constexpr auto KMemoryRegionType_DramPoolManagement = | ||
| 207 | KMemoryRegionType_DramPoolPartition.DeriveTransition(0, 2).DeriveTransition().SetAttribute( | ||
| 208 | KMemoryRegionAttr_CarveoutProtected); | ||
| 209 | constexpr auto KMemoryRegionType_DramUserPool = | ||
| 210 | KMemoryRegionType_DramPoolPartition.DeriveTransition(1, 2).DeriveTransition(); | ||
| 211 | static_assert(KMemoryRegionType_DramPoolManagement.GetValue() == | ||
| 212 | (0x166 | KMemoryRegionAttr_LinearMapped | KMemoryRegionAttr_NoUserMap | | ||
| 213 | KMemoryRegionAttr_CarveoutProtected)); | ||
| 214 | static_assert(KMemoryRegionType_DramUserPool.GetValue() == | ||
| 215 | (0x1A6 | KMemoryRegionAttr_LinearMapped | KMemoryRegionAttr_NoUserMap)); | ||
| 216 | |||
| 217 | constexpr auto KMemoryRegionType_DramApplicationPool = KMemoryRegionType_DramUserPool.Derive(4, 0); | ||
| 218 | constexpr auto KMemoryRegionType_DramAppletPool = KMemoryRegionType_DramUserPool.Derive(4, 1); | ||
| 219 | constexpr auto KMemoryRegionType_DramSystemNonSecurePool = | ||
| 220 | KMemoryRegionType_DramUserPool.Derive(4, 2); | ||
| 221 | constexpr auto KMemoryRegionType_DramSystemPool = | ||
| 222 | KMemoryRegionType_DramUserPool.Derive(4, 3).SetAttribute(KMemoryRegionAttr_CarveoutProtected); | ||
| 223 | static_assert(KMemoryRegionType_DramApplicationPool.GetValue() == | ||
| 224 | (0x7A6 | KMemoryRegionAttr_LinearMapped | KMemoryRegionAttr_NoUserMap)); | ||
| 225 | static_assert(KMemoryRegionType_DramAppletPool.GetValue() == | ||
| 226 | (0xBA6 | KMemoryRegionAttr_LinearMapped | KMemoryRegionAttr_NoUserMap)); | ||
| 227 | static_assert(KMemoryRegionType_DramSystemNonSecurePool.GetValue() == | ||
| 228 | (0xDA6 | KMemoryRegionAttr_LinearMapped | KMemoryRegionAttr_NoUserMap)); | ||
| 229 | static_assert(KMemoryRegionType_DramSystemPool.GetValue() == | ||
| 230 | (0x13A6 | KMemoryRegionAttr_LinearMapped | KMemoryRegionAttr_NoUserMap | | ||
| 231 | KMemoryRegionAttr_CarveoutProtected)); | ||
| 232 | |||
| 233 | constexpr auto KMemoryRegionType_VirtualDramHeapBase = KMemoryRegionType_Dram.DeriveSparse(1, 3, 0); | ||
| 234 | constexpr auto KMemoryRegionType_VirtualDramKernelPtHeap = | ||
| 235 | KMemoryRegionType_Dram.DeriveSparse(1, 3, 1); | ||
| 236 | constexpr auto KMemoryRegionType_VirtualDramKernelTraceBuffer = | ||
| 237 | KMemoryRegionType_Dram.DeriveSparse(1, 3, 2); | ||
| 238 | static_assert(KMemoryRegionType_VirtualDramHeapBase.GetValue() == 0x1A); | ||
| 239 | static_assert(KMemoryRegionType_VirtualDramKernelPtHeap.GetValue() == 0x2A); | ||
| 240 | static_assert(KMemoryRegionType_VirtualDramKernelTraceBuffer.GetValue() == 0x4A); | ||
| 241 | |||
| 242 | constexpr auto KMemoryRegionType_VirtualDramKernelInitPt = | ||
| 243 | KMemoryRegionType_VirtualDramHeapBase.Derive(3, 0); | ||
| 244 | constexpr auto KMemoryRegionType_VirtualDramPoolManagement = | ||
| 245 | KMemoryRegionType_VirtualDramHeapBase.Derive(3, 1); | ||
| 246 | constexpr auto KMemoryRegionType_VirtualDramUserPool = | ||
| 247 | KMemoryRegionType_VirtualDramHeapBase.Derive(3, 2); | ||
| 248 | static_assert(KMemoryRegionType_VirtualDramKernelInitPt.GetValue() == 0x19A); | ||
| 249 | static_assert(KMemoryRegionType_VirtualDramPoolManagement.GetValue() == 0x29A); | ||
| 250 | static_assert(KMemoryRegionType_VirtualDramUserPool.GetValue() == 0x31A); | ||
| 251 | |||
| 252 | // NOTE: For unknown reason, the pools are derived out-of-order here. It's worth eventually trying | ||
| 253 | // to understand why Nintendo made this choice. | ||
| 254 | // UNUSED: .Derive(6, 0); | ||
| 255 | // UNUSED: .Derive(6, 1); | ||
| 256 | constexpr auto KMemoryRegionType_VirtualDramAppletPool = | ||
| 257 | KMemoryRegionType_VirtualDramUserPool.Derive(6, 2); | ||
| 258 | constexpr auto KMemoryRegionType_VirtualDramApplicationPool = | ||
| 259 | KMemoryRegionType_VirtualDramUserPool.Derive(6, 3); | ||
| 260 | constexpr auto KMemoryRegionType_VirtualDramSystemNonSecurePool = | ||
| 261 | KMemoryRegionType_VirtualDramUserPool.Derive(6, 4); | ||
| 262 | constexpr auto KMemoryRegionType_VirtualDramSystemPool = | ||
| 263 | KMemoryRegionType_VirtualDramUserPool.Derive(6, 5); | ||
| 264 | static_assert(KMemoryRegionType_VirtualDramAppletPool.GetValue() == 0x1B1A); | ||
| 265 | static_assert(KMemoryRegionType_VirtualDramApplicationPool.GetValue() == 0x271A); | ||
| 266 | static_assert(KMemoryRegionType_VirtualDramSystemNonSecurePool.GetValue() == 0x2B1A); | ||
| 267 | static_assert(KMemoryRegionType_VirtualDramSystemPool.GetValue() == 0x331A); | ||
| 268 | |||
| 269 | constexpr auto KMemoryRegionType_ArchDeviceBase = | ||
| 270 | KMemoryRegionType_Kernel.DeriveTransition(0, 1).SetSparseOnly(); | ||
| 271 | constexpr auto KMemoryRegionType_BoardDeviceBase = | ||
| 272 | KMemoryRegionType_Kernel.DeriveTransition(0, 2).SetDenseOnly(); | ||
| 273 | static_assert(KMemoryRegionType_ArchDeviceBase.GetValue() == 0x5); | ||
| 274 | static_assert(KMemoryRegionType_BoardDeviceBase.GetValue() == 0x5); | ||
| 275 | |||
| 276 | #if defined(ARCH_ARM64) | ||
| 277 | #include "core/hle/kernel/arch/arm64/k_memory_region_device_types.inc" | ||
| 278 | #elif defined(ARCH_ARM) | ||
| 279 | #error "Unimplemented" | ||
| 280 | #else | ||
| 281 | // Default to no architecture devices. | ||
| 282 | constexpr auto NumArchitectureDeviceRegions = 0; | ||
| 283 | #endif | ||
| 284 | static_assert(NumArchitectureDeviceRegions >= 0); | ||
| 285 | |||
| 286 | #if defined(BOARD_NINTENDO_NX) | ||
| 287 | #include "core/hle/kernel/board/nintendo/nx/k_memory_region_device_types.inc" | ||
| 288 | #else | ||
| 289 | // Default to no board devices. | ||
| 290 | constexpr auto NumBoardDeviceRegions = 0; | ||
| 291 | #endif | ||
| 292 | static_assert(NumBoardDeviceRegions >= 0); | ||
| 293 | |||
| 294 | constexpr auto KMemoryRegionType_KernelCode = KMemoryRegionType_Kernel.DeriveSparse(1, 4, 0); | ||
| 295 | constexpr auto KMemoryRegionType_KernelStack = KMemoryRegionType_Kernel.DeriveSparse(1, 4, 1); | ||
| 296 | constexpr auto KMemoryRegionType_KernelMisc = KMemoryRegionType_Kernel.DeriveSparse(1, 4, 2); | ||
| 297 | constexpr auto KMemoryRegionType_KernelSlab = KMemoryRegionType_Kernel.DeriveSparse(1, 4, 3); | ||
| 298 | static_assert(KMemoryRegionType_KernelCode.GetValue() == 0x19); | ||
| 299 | static_assert(KMemoryRegionType_KernelStack.GetValue() == 0x29); | ||
| 300 | static_assert(KMemoryRegionType_KernelMisc.GetValue() == 0x49); | ||
| 301 | static_assert(KMemoryRegionType_KernelSlab.GetValue() == 0x89); | ||
| 302 | |||
| 303 | constexpr auto KMemoryRegionType_KernelMiscDerivedBase = | ||
| 304 | KMemoryRegionType_KernelMisc.DeriveTransition(); | ||
| 305 | static_assert(KMemoryRegionType_KernelMiscDerivedBase.GetValue() == 0x149); | ||
| 306 | |||
| 307 | // UNUSED: .Derive(7, 0); | ||
| 308 | constexpr auto KMemoryRegionType_KernelMiscMainStack = | ||
| 309 | KMemoryRegionType_KernelMiscDerivedBase.Derive(7, 1); | ||
| 310 | constexpr auto KMemoryRegionType_KernelMiscMappedDevice = | ||
| 311 | KMemoryRegionType_KernelMiscDerivedBase.Derive(7, 2); | ||
| 312 | constexpr auto KMemoryRegionType_KernelMiscExceptionStack = | ||
| 313 | KMemoryRegionType_KernelMiscDerivedBase.Derive(7, 3); | ||
| 314 | constexpr auto KMemoryRegionType_KernelMiscUnknownDebug = | ||
| 315 | KMemoryRegionType_KernelMiscDerivedBase.Derive(7, 4); | ||
| 316 | // UNUSED: .Derive(7, 5); | ||
| 317 | constexpr auto KMemoryRegionType_KernelMiscIdleStack = | ||
| 318 | KMemoryRegionType_KernelMiscDerivedBase.Derive(7, 6); | ||
| 319 | static_assert(KMemoryRegionType_KernelMiscMainStack.GetValue() == 0xB49); | ||
| 320 | static_assert(KMemoryRegionType_KernelMiscMappedDevice.GetValue() == 0xD49); | ||
| 321 | static_assert(KMemoryRegionType_KernelMiscExceptionStack.GetValue() == 0x1349); | ||
| 322 | static_assert(KMemoryRegionType_KernelMiscUnknownDebug.GetValue() == 0x1549); | ||
| 323 | static_assert(KMemoryRegionType_KernelMiscIdleStack.GetValue() == 0x2349); | ||
| 324 | |||
| 325 | constexpr auto KMemoryRegionType_KernelTemp = KMemoryRegionType_Kernel.Advance(2).Derive(2, 0); | ||
| 326 | static_assert(KMemoryRegionType_KernelTemp.GetValue() == 0x31); | ||
| 327 | |||
| 328 | constexpr KMemoryRegionType GetTypeForVirtualLinearMapping(u32 type_id) { | ||
| 329 | if (KMemoryRegionType_KernelTraceBuffer.IsAncestorOf(type_id)) { | ||
| 330 | return KMemoryRegionType_VirtualDramKernelTraceBuffer; | ||
| 331 | } else if (KMemoryRegionType_DramKernelPtHeap.IsAncestorOf(type_id)) { | ||
| 332 | return KMemoryRegionType_VirtualDramKernelPtHeap; | ||
| 333 | } else { | ||
| 334 | return KMemoryRegionType_Dram; | ||
| 335 | } | ||
| 336 | } | ||
| 337 | |||
| 338 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/k_resource_limit.cpp b/src/core/hle/kernel/k_resource_limit.cpp index d7a4a38e6..d05b34ea3 100644 --- a/src/core/hle/kernel/k_resource_limit.cpp +++ b/src/core/hle/kernel/k_resource_limit.cpp | |||
| @@ -2,21 +2,16 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | // This file references various implementation details from Atmosphere, an open-source firmware for | ||
| 6 | // the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX. | ||
| 7 | |||
| 8 | #include "common/assert.h" | 5 | #include "common/assert.h" |
| 9 | #include "core/core.h" | ||
| 10 | #include "core/core_timing.h" | 6 | #include "core/core_timing.h" |
| 11 | #include "core/core_timing_util.h" | ||
| 12 | #include "core/hle/kernel/k_resource_limit.h" | 7 | #include "core/hle/kernel/k_resource_limit.h" |
| 13 | #include "core/hle/kernel/svc_results.h" | 8 | #include "core/hle/kernel/svc_results.h" |
| 14 | 9 | ||
| 15 | namespace Kernel { | 10 | namespace Kernel { |
| 16 | constexpr s64 DefaultTimeout = 10000000000; // 10 seconds | 11 | constexpr s64 DefaultTimeout = 10000000000; // 10 seconds |
| 17 | 12 | ||
| 18 | KResourceLimit::KResourceLimit(KernelCore& kernel, Core::System& system) | 13 | KResourceLimit::KResourceLimit(KernelCore& kernel, const Core::Timing::CoreTiming& core_timing_) |
| 19 | : Object{kernel}, lock{kernel}, cond_var{kernel}, kernel{kernel}, system(system) {} | 14 | : Object{kernel}, lock{kernel}, cond_var{kernel}, core_timing(core_timing_) {} |
| 20 | KResourceLimit::~KResourceLimit() = default; | 15 | KResourceLimit::~KResourceLimit() = default; |
| 21 | 16 | ||
| 22 | s64 KResourceLimit::GetLimitValue(LimitableResource which) const { | 17 | s64 KResourceLimit::GetLimitValue(LimitableResource which) const { |
| @@ -83,7 +78,7 @@ ResultCode KResourceLimit::SetLimitValue(LimitableResource which, s64 value) { | |||
| 83 | } | 78 | } |
| 84 | 79 | ||
| 85 | bool KResourceLimit::Reserve(LimitableResource which, s64 value) { | 80 | bool KResourceLimit::Reserve(LimitableResource which, s64 value) { |
| 86 | return Reserve(which, value, system.CoreTiming().GetGlobalTimeNs().count() + DefaultTimeout); | 81 | return Reserve(which, value, core_timing.GetGlobalTimeNs().count() + DefaultTimeout); |
| 87 | } | 82 | } |
| 88 | 83 | ||
| 89 | bool KResourceLimit::Reserve(LimitableResource which, s64 value, s64 timeout) { | 84 | bool KResourceLimit::Reserve(LimitableResource which, s64 value, s64 timeout) { |
| @@ -114,7 +109,7 @@ bool KResourceLimit::Reserve(LimitableResource which, s64 value, s64 timeout) { | |||
| 114 | } | 109 | } |
| 115 | 110 | ||
| 116 | if (current_hints[index] + value <= limit_values[index] && | 111 | if (current_hints[index] + value <= limit_values[index] && |
| 117 | (timeout < 0 || system.CoreTiming().GetGlobalTimeNs().count() < timeout)) { | 112 | (timeout < 0 || core_timing.GetGlobalTimeNs().count() < timeout)) { |
| 118 | waiter_count++; | 113 | waiter_count++; |
| 119 | cond_var.Wait(&lock, timeout); | 114 | cond_var.Wait(&lock, timeout); |
| 120 | waiter_count--; | 115 | waiter_count--; |
diff --git a/src/core/hle/kernel/k_resource_limit.h b/src/core/hle/kernel/k_resource_limit.h index 58ae456f1..4542317d0 100644 --- a/src/core/hle/kernel/k_resource_limit.h +++ b/src/core/hle/kernel/k_resource_limit.h | |||
| @@ -2,9 +2,6 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | // This file references various implementation details from Atmosphere, an open-source firmware for | ||
| 6 | // the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX. | ||
| 7 | |||
| 8 | #pragma once | 5 | #pragma once |
| 9 | 6 | ||
| 10 | #include <array> | 7 | #include <array> |
| @@ -15,8 +12,8 @@ | |||
| 15 | 12 | ||
| 16 | union ResultCode; | 13 | union ResultCode; |
| 17 | 14 | ||
| 18 | namespace Core { | 15 | namespace Core::Timing { |
| 19 | class System; | 16 | class CoreTiming; |
| 20 | } | 17 | } |
| 21 | 18 | ||
| 22 | namespace Kernel { | 19 | namespace Kernel { |
| @@ -37,7 +34,7 @@ constexpr bool IsValidResourceType(LimitableResource type) { | |||
| 37 | 34 | ||
| 38 | class KResourceLimit final : public Object { | 35 | class KResourceLimit final : public Object { |
| 39 | public: | 36 | public: |
| 40 | explicit KResourceLimit(KernelCore& kernel, Core::System& system); | 37 | explicit KResourceLimit(KernelCore& kernel, const Core::Timing::CoreTiming& core_timing_); |
| 41 | ~KResourceLimit(); | 38 | ~KResourceLimit(); |
| 42 | 39 | ||
| 43 | s64 GetLimitValue(LimitableResource which) const; | 40 | s64 GetLimitValue(LimitableResource which) const; |
| @@ -75,7 +72,6 @@ private: | |||
| 75 | mutable KLightLock lock; | 72 | mutable KLightLock lock; |
| 76 | s32 waiter_count{}; | 73 | s32 waiter_count{}; |
| 77 | KLightConditionVariable cond_var; | 74 | KLightConditionVariable cond_var; |
| 78 | KernelCore& kernel; | 75 | const Core::Timing::CoreTiming& core_timing; |
| 79 | Core::System& system; | ||
| 80 | }; | 76 | }; |
| 81 | } // namespace Kernel | 77 | } // namespace Kernel |
diff --git a/src/core/hle/kernel/k_scheduler.cpp b/src/core/hle/kernel/k_scheduler.cpp index e7de48476..d1df97305 100644 --- a/src/core/hle/kernel/k_scheduler.cpp +++ b/src/core/hle/kernel/k_scheduler.cpp | |||
| @@ -62,7 +62,7 @@ void KScheduler::RescheduleCores(KernelCore& kernel, u64 cores_pending_reschedul | |||
| 62 | } | 62 | } |
| 63 | 63 | ||
| 64 | u64 KScheduler::UpdateHighestPriorityThread(KThread* highest_thread) { | 64 | u64 KScheduler::UpdateHighestPriorityThread(KThread* highest_thread) { |
| 65 | std::scoped_lock lock{guard}; | 65 | KScopedSpinLock lk{guard}; |
| 66 | if (KThread* prev_highest_thread = state.highest_priority_thread; | 66 | if (KThread* prev_highest_thread = state.highest_priority_thread; |
| 67 | prev_highest_thread != highest_thread) { | 67 | prev_highest_thread != highest_thread) { |
| 68 | if (prev_highest_thread != nullptr) { | 68 | if (prev_highest_thread != nullptr) { |
| @@ -637,11 +637,11 @@ void KScheduler::RescheduleCurrentCore() { | |||
| 637 | if (phys_core.IsInterrupted()) { | 637 | if (phys_core.IsInterrupted()) { |
| 638 | phys_core.ClearInterrupt(); | 638 | phys_core.ClearInterrupt(); |
| 639 | } | 639 | } |
| 640 | guard.lock(); | 640 | guard.Lock(); |
| 641 | if (state.needs_scheduling.load()) { | 641 | if (state.needs_scheduling.load()) { |
| 642 | Schedule(); | 642 | Schedule(); |
| 643 | } else { | 643 | } else { |
| 644 | guard.unlock(); | 644 | guard.Unlock(); |
| 645 | } | 645 | } |
| 646 | } | 646 | } |
| 647 | 647 | ||
| @@ -669,7 +669,7 @@ void KScheduler::Unload(KThread* thread) { | |||
| 669 | } else { | 669 | } else { |
| 670 | prev_thread = nullptr; | 670 | prev_thread = nullptr; |
| 671 | } | 671 | } |
| 672 | thread->context_guard.unlock(); | 672 | thread->context_guard.Unlock(); |
| 673 | } | 673 | } |
| 674 | } | 674 | } |
| 675 | 675 | ||
| @@ -713,7 +713,7 @@ void KScheduler::ScheduleImpl() { | |||
| 713 | 713 | ||
| 714 | // If we're not actually switching thread, there's nothing to do. | 714 | // If we're not actually switching thread, there's nothing to do. |
| 715 | if (next_thread == current_thread.load()) { | 715 | if (next_thread == current_thread.load()) { |
| 716 | guard.unlock(); | 716 | guard.Unlock(); |
| 717 | return; | 717 | return; |
| 718 | } | 718 | } |
| 719 | 719 | ||
| @@ -732,7 +732,7 @@ void KScheduler::ScheduleImpl() { | |||
| 732 | } else { | 732 | } else { |
| 733 | old_context = &idle_thread->GetHostContext(); | 733 | old_context = &idle_thread->GetHostContext(); |
| 734 | } | 734 | } |
| 735 | guard.unlock(); | 735 | guard.Unlock(); |
| 736 | 736 | ||
| 737 | Common::Fiber::YieldTo(*old_context, *switch_fiber); | 737 | Common::Fiber::YieldTo(*old_context, *switch_fiber); |
| 738 | /// When a thread wakes up, the scheduler may have changed to other in another core. | 738 | /// When a thread wakes up, the scheduler may have changed to other in another core. |
| @@ -748,24 +748,24 @@ void KScheduler::OnSwitch(void* this_scheduler) { | |||
| 748 | void KScheduler::SwitchToCurrent() { | 748 | void KScheduler::SwitchToCurrent() { |
| 749 | while (true) { | 749 | while (true) { |
| 750 | { | 750 | { |
| 751 | std::scoped_lock lock{guard}; | 751 | KScopedSpinLock lk{guard}; |
| 752 | current_thread.store(state.highest_priority_thread); | 752 | current_thread.store(state.highest_priority_thread); |
| 753 | state.needs_scheduling.store(false); | 753 | state.needs_scheduling.store(false); |
| 754 | } | 754 | } |
| 755 | const auto is_switch_pending = [this] { | 755 | const auto is_switch_pending = [this] { |
| 756 | std::scoped_lock lock{guard}; | 756 | KScopedSpinLock lk{guard}; |
| 757 | return state.needs_scheduling.load(); | 757 | return state.needs_scheduling.load(); |
| 758 | }; | 758 | }; |
| 759 | do { | 759 | do { |
| 760 | auto next_thread = current_thread.load(); | 760 | auto next_thread = current_thread.load(); |
| 761 | if (next_thread != nullptr) { | 761 | if (next_thread != nullptr) { |
| 762 | next_thread->context_guard.lock(); | 762 | next_thread->context_guard.Lock(); |
| 763 | if (next_thread->GetRawState() != ThreadState::Runnable) { | 763 | if (next_thread->GetRawState() != ThreadState::Runnable) { |
| 764 | next_thread->context_guard.unlock(); | 764 | next_thread->context_guard.Unlock(); |
| 765 | break; | 765 | break; |
| 766 | } | 766 | } |
| 767 | if (next_thread->GetActiveCore() != core_id) { | 767 | if (next_thread->GetActiveCore() != core_id) { |
| 768 | next_thread->context_guard.unlock(); | 768 | next_thread->context_guard.Unlock(); |
| 769 | break; | 769 | break; |
| 770 | } | 770 | } |
| 771 | } | 771 | } |
diff --git a/src/core/hle/kernel/k_scheduler.h b/src/core/hle/kernel/k_scheduler.h index f595b9a5c..8e32865aa 100644 --- a/src/core/hle/kernel/k_scheduler.h +++ b/src/core/hle/kernel/k_scheduler.h | |||
| @@ -2,19 +2,16 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | // This file references various implementation details from Atmosphere, an open-source firmware for | ||
| 6 | // the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX. | ||
| 7 | |||
| 8 | #pragma once | 5 | #pragma once |
| 9 | 6 | ||
| 10 | #include <atomic> | 7 | #include <atomic> |
| 11 | 8 | ||
| 12 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| 13 | #include "common/spin_lock.h" | ||
| 14 | #include "core/hle/kernel/global_scheduler_context.h" | 10 | #include "core/hle/kernel/global_scheduler_context.h" |
| 15 | #include "core/hle/kernel/k_priority_queue.h" | 11 | #include "core/hle/kernel/k_priority_queue.h" |
| 16 | #include "core/hle/kernel/k_scheduler_lock.h" | 12 | #include "core/hle/kernel/k_scheduler_lock.h" |
| 17 | #include "core/hle/kernel/k_scoped_lock.h" | 13 | #include "core/hle/kernel/k_scoped_lock.h" |
| 14 | #include "core/hle/kernel/k_spin_lock.h" | ||
| 18 | 15 | ||
| 19 | namespace Common { | 16 | namespace Common { |
| 20 | class Fiber; | 17 | class Fiber; |
| @@ -195,12 +192,12 @@ private: | |||
| 195 | u64 last_context_switch_time{}; | 192 | u64 last_context_switch_time{}; |
| 196 | const s32 core_id; | 193 | const s32 core_id; |
| 197 | 194 | ||
| 198 | Common::SpinLock guard{}; | 195 | KSpinLock guard{}; |
| 199 | }; | 196 | }; |
| 200 | 197 | ||
| 201 | class KScopedSchedulerLock : KScopedLock<GlobalSchedulerContext::LockType> { | 198 | class [[nodiscard]] KScopedSchedulerLock : KScopedLock<GlobalSchedulerContext::LockType> { |
| 202 | public: | 199 | public: |
| 203 | explicit KScopedSchedulerLock(KernelCore& kernel); | 200 | explicit KScopedSchedulerLock(KernelCore & kernel); |
| 204 | ~KScopedSchedulerLock(); | 201 | ~KScopedSchedulerLock(); |
| 205 | }; | 202 | }; |
| 206 | 203 | ||
diff --git a/src/core/hle/kernel/k_scheduler_lock.h b/src/core/hle/kernel/k_scheduler_lock.h index 169455d18..47e315555 100644 --- a/src/core/hle/kernel/k_scheduler_lock.h +++ b/src/core/hle/kernel/k_scheduler_lock.h | |||
| @@ -2,14 +2,11 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | // This file references various implementation details from Atmosphere, an open-source firmware for | ||
| 6 | // the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX. | ||
| 7 | |||
| 8 | #pragma once | 5 | #pragma once |
| 9 | 6 | ||
| 10 | #include "common/assert.h" | 7 | #include "common/assert.h" |
| 11 | #include "common/spin_lock.h" | ||
| 12 | #include "core/hardware_properties.h" | 8 | #include "core/hardware_properties.h" |
| 9 | #include "core/hle/kernel/k_spin_lock.h" | ||
| 13 | #include "core/hle/kernel/k_thread.h" | 10 | #include "core/hle/kernel/k_thread.h" |
| 14 | #include "core/hle/kernel/kernel.h" | 11 | #include "core/hle/kernel/kernel.h" |
| 15 | 12 | ||
| @@ -34,7 +31,7 @@ public: | |||
| 34 | } else { | 31 | } else { |
| 35 | // Otherwise, we want to disable scheduling and acquire the spinlock. | 32 | // Otherwise, we want to disable scheduling and acquire the spinlock. |
| 36 | SchedulerType::DisableScheduling(kernel); | 33 | SchedulerType::DisableScheduling(kernel); |
| 37 | spin_lock.lock(); | 34 | spin_lock.Lock(); |
| 38 | 35 | ||
| 39 | // For debug, ensure that our state is valid. | 36 | // For debug, ensure that our state is valid. |
| 40 | ASSERT(lock_count == 0); | 37 | ASSERT(lock_count == 0); |
| @@ -58,7 +55,7 @@ public: | |||
| 58 | 55 | ||
| 59 | // Note that we no longer hold the lock, and unlock the spinlock. | 56 | // Note that we no longer hold the lock, and unlock the spinlock. |
| 60 | owner_thread = nullptr; | 57 | owner_thread = nullptr; |
| 61 | spin_lock.unlock(); | 58 | spin_lock.Unlock(); |
| 62 | 59 | ||
| 63 | // Enable scheduling, and perform a rescheduling operation. | 60 | // Enable scheduling, and perform a rescheduling operation. |
| 64 | SchedulerType::EnableScheduling(kernel, cores_needing_scheduling); | 61 | SchedulerType::EnableScheduling(kernel, cores_needing_scheduling); |
| @@ -67,7 +64,7 @@ public: | |||
| 67 | 64 | ||
| 68 | private: | 65 | private: |
| 69 | KernelCore& kernel; | 66 | KernelCore& kernel; |
| 70 | Common::SpinLock spin_lock{}; | 67 | KAlignedSpinLock spin_lock{}; |
| 71 | s32 lock_count{}; | 68 | s32 lock_count{}; |
| 72 | KThread* owner_thread{}; | 69 | KThread* owner_thread{}; |
| 73 | }; | 70 | }; |
diff --git a/src/core/hle/kernel/k_scoped_lock.h b/src/core/hle/kernel/k_scoped_lock.h index d7cc557b2..72c3b0252 100644 --- a/src/core/hle/kernel/k_scoped_lock.h +++ b/src/core/hle/kernel/k_scoped_lock.h | |||
| @@ -20,19 +20,22 @@ concept KLockable = !std::is_reference_v<T> && requires(T & t) { | |||
| 20 | }; | 20 | }; |
| 21 | 21 | ||
| 22 | template <typename T> | 22 | template <typename T> |
| 23 | requires KLockable<T> class KScopedLock { | 23 | requires KLockable<T> class [[nodiscard]] KScopedLock { |
| 24 | public: | 24 | public: |
| 25 | explicit KScopedLock(T* l) : lock_ptr(l) { | 25 | explicit KScopedLock(T * l) : lock_ptr(l) { |
| 26 | this->lock_ptr->Lock(); | 26 | this->lock_ptr->Lock(); |
| 27 | } | 27 | } |
| 28 | explicit KScopedLock(T& l) : KScopedLock(std::addressof(l)) { /* ... */ | 28 | explicit KScopedLock(T & l) : KScopedLock(std::addressof(l)) {} |
| 29 | } | 29 | |
| 30 | ~KScopedLock() { | 30 | ~KScopedLock() { |
| 31 | this->lock_ptr->Unlock(); | 31 | this->lock_ptr->Unlock(); |
| 32 | } | 32 | } |
| 33 | 33 | ||
| 34 | KScopedLock(const KScopedLock&) = delete; | 34 | KScopedLock(const KScopedLock&) = delete; |
| 35 | KScopedLock(KScopedLock&&) = delete; | 35 | KScopedLock& operator=(const KScopedLock&) = delete; |
| 36 | |||
| 37 | KScopedLock(KScopedLock &&) = delete; | ||
| 38 | KScopedLock& operator=(KScopedLock&&) = delete; | ||
| 36 | 39 | ||
| 37 | private: | 40 | private: |
| 38 | T* lock_ptr; | 41 | T* lock_ptr; |
diff --git a/src/core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h b/src/core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h index f8189e107..ebecf0c77 100644 --- a/src/core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h +++ b/src/core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h | |||
| @@ -15,9 +15,9 @@ | |||
| 15 | 15 | ||
| 16 | namespace Kernel { | 16 | namespace Kernel { |
| 17 | 17 | ||
| 18 | class KScopedSchedulerLockAndSleep { | 18 | class [[nodiscard]] KScopedSchedulerLockAndSleep { |
| 19 | public: | 19 | public: |
| 20 | explicit KScopedSchedulerLockAndSleep(KernelCore& kernel, KThread* t, s64 timeout) | 20 | explicit KScopedSchedulerLockAndSleep(KernelCore & kernel, KThread * t, s64 timeout) |
| 21 | : kernel(kernel), thread(t), timeout_tick(timeout) { | 21 | : kernel(kernel), thread(t), timeout_tick(timeout) { |
| 22 | // Lock the scheduler. | 22 | // Lock the scheduler. |
| 23 | kernel.GlobalSchedulerContext().scheduler_lock.Lock(); | 23 | kernel.GlobalSchedulerContext().scheduler_lock.Lock(); |
diff --git a/src/core/hle/kernel/k_spin_lock.h b/src/core/hle/kernel/k_spin_lock.h index 12c4b2e88..4d87d006a 100644 --- a/src/core/hle/kernel/k_spin_lock.h +++ b/src/core/hle/kernel/k_spin_lock.h | |||
| @@ -28,6 +28,12 @@ private: | |||
| 28 | std::atomic_flag lck = ATOMIC_FLAG_INIT; | 28 | std::atomic_flag lck = ATOMIC_FLAG_INIT; |
| 29 | }; | 29 | }; |
| 30 | 30 | ||
| 31 | // TODO(bunnei): Alias for now, in case we want to implement these accurately in the future. | ||
| 32 | using KAlignedSpinLock = KSpinLock; | ||
| 33 | using KNotAlignedSpinLock = KSpinLock; | ||
| 34 | |||
| 31 | using KScopedSpinLock = KScopedLock<KSpinLock>; | 35 | using KScopedSpinLock = KScopedLock<KSpinLock>; |
| 36 | using KScopedAlignedSpinLock = KScopedLock<KAlignedSpinLock>; | ||
| 37 | using KScopedNotAlignedSpinLock = KScopedLock<KNotAlignedSpinLock>; | ||
| 32 | 38 | ||
| 33 | } // namespace Kernel | 39 | } // namespace Kernel |
diff --git a/src/core/hle/kernel/k_system_control.cpp b/src/core/hle/kernel/k_system_control.cpp deleted file mode 100644 index aa1682f69..000000000 --- a/src/core/hle/kernel/k_system_control.cpp +++ /dev/null | |||
| @@ -1,42 +0,0 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <random> | ||
| 6 | |||
| 7 | #include "core/hle/kernel/k_system_control.h" | ||
| 8 | |||
| 9 | namespace Kernel { | ||
| 10 | |||
| 11 | namespace { | ||
| 12 | template <typename F> | ||
| 13 | u64 GenerateUniformRange(u64 min, u64 max, F f) { | ||
| 14 | // Handle the case where the difference is too large to represent. | ||
| 15 | if (max == std::numeric_limits<u64>::max() && min == std::numeric_limits<u64>::min()) { | ||
| 16 | return f(); | ||
| 17 | } | ||
| 18 | |||
| 19 | // Iterate until we get a value in range. | ||
| 20 | const u64 range_size = ((max + 1) - min); | ||
| 21 | const u64 effective_max = (std::numeric_limits<u64>::max() / range_size) * range_size; | ||
| 22 | while (true) { | ||
| 23 | if (const u64 rnd = f(); rnd < effective_max) { | ||
| 24 | return min + (rnd % range_size); | ||
| 25 | } | ||
| 26 | } | ||
| 27 | } | ||
| 28 | |||
| 29 | } // Anonymous namespace | ||
| 30 | |||
| 31 | u64 KSystemControl::GenerateRandomU64() { | ||
| 32 | static std::random_device device; | ||
| 33 | static std::mt19937 gen(device()); | ||
| 34 | static std::uniform_int_distribution<u64> distribution(1, std::numeric_limits<u64>::max()); | ||
| 35 | return distribution(gen); | ||
| 36 | } | ||
| 37 | |||
| 38 | u64 KSystemControl::GenerateRandomRange(u64 min, u64 max) { | ||
| 39 | return GenerateUniformRange(min, max, GenerateRandomU64); | ||
| 40 | } | ||
| 41 | |||
| 42 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/k_system_control.h b/src/core/hle/kernel/k_system_control.h index 1d5b64ffa..d755082c2 100644 --- a/src/core/hle/kernel/k_system_control.h +++ b/src/core/hle/kernel/k_system_control.h | |||
| @@ -6,14 +6,18 @@ | |||
| 6 | 6 | ||
| 7 | #include "common/common_types.h" | 7 | #include "common/common_types.h" |
| 8 | 8 | ||
| 9 | namespace Kernel { | 9 | #define BOARD_NINTENDO_NX |
| 10 | |||
| 11 | #ifdef BOARD_NINTENDO_NX | ||
| 10 | 12 | ||
| 11 | class KSystemControl { | 13 | #include "core/hle/kernel/board/nintendo/nx/k_system_control.h" |
| 12 | public: | ||
| 13 | KSystemControl() = default; | ||
| 14 | 14 | ||
| 15 | static u64 GenerateRandomRange(u64 min, u64 max); | 15 | namespace Kernel { |
| 16 | static u64 GenerateRandomU64(); | 16 | |
| 17 | }; | 17 | using Kernel::Board::Nintendo::Nx::KSystemControl; |
| 18 | 18 | ||
| 19 | } // namespace Kernel | 19 | } // namespace Kernel |
| 20 | |||
| 21 | #else | ||
| 22 | #error "Unknown board for KSystemControl" | ||
| 23 | #endif | ||
diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h index 1c19b23dc..b442dfe57 100644 --- a/src/core/hle/kernel/k_thread.h +++ b/src/core/hle/kernel/k_thread.h | |||
| @@ -14,10 +14,10 @@ | |||
| 14 | 14 | ||
| 15 | #include "common/common_types.h" | 15 | #include "common/common_types.h" |
| 16 | #include "common/intrusive_red_black_tree.h" | 16 | #include "common/intrusive_red_black_tree.h" |
| 17 | #include "common/spin_lock.h" | ||
| 18 | #include "core/arm/arm_interface.h" | 17 | #include "core/arm/arm_interface.h" |
| 19 | #include "core/hle/kernel/k_affinity_mask.h" | 18 | #include "core/hle/kernel/k_affinity_mask.h" |
| 20 | #include "core/hle/kernel/k_light_lock.h" | 19 | #include "core/hle/kernel/k_light_lock.h" |
| 20 | #include "core/hle/kernel/k_spin_lock.h" | ||
| 21 | #include "core/hle/kernel/k_synchronization_object.h" | 21 | #include "core/hle/kernel/k_synchronization_object.h" |
| 22 | #include "core/hle/kernel/object.h" | 22 | #include "core/hle/kernel/object.h" |
| 23 | #include "core/hle/kernel/svc_common.h" | 23 | #include "core/hle/kernel/svc_common.h" |
| @@ -402,7 +402,7 @@ public: | |||
| 402 | return wait_cancelled; | 402 | return wait_cancelled; |
| 403 | } | 403 | } |
| 404 | 404 | ||
| 405 | [[nodiscard]] void ClearWaitCancelled() { | 405 | void ClearWaitCancelled() { |
| 406 | wait_cancelled = false; | 406 | wait_cancelled = false; |
| 407 | } | 407 | } |
| 408 | 408 | ||
| @@ -732,7 +732,7 @@ private: | |||
| 732 | s8 priority_inheritance_count{}; | 732 | s8 priority_inheritance_count{}; |
| 733 | bool resource_limit_release_hint{}; | 733 | bool resource_limit_release_hint{}; |
| 734 | StackParameters stack_parameters{}; | 734 | StackParameters stack_parameters{}; |
| 735 | Common::SpinLock context_guard{}; | 735 | KSpinLock context_guard{}; |
| 736 | 736 | ||
| 737 | // For emulation | 737 | // For emulation |
| 738 | std::shared_ptr<Common::Fiber> host_context{}; | 738 | std::shared_ptr<Common::Fiber> host_context{}; |
diff --git a/src/core/hle/kernel/k_trace.h b/src/core/hle/kernel/k_trace.h new file mode 100644 index 000000000..91ebf9ab2 --- /dev/null +++ b/src/core/hle/kernel/k_trace.h | |||
| @@ -0,0 +1,12 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | namespace Kernel { | ||
| 8 | |||
| 9 | constexpr bool IsKTraceEnabled = false; | ||
| 10 | constexpr std::size_t KTraceBufferSize = IsKTraceEnabled ? 16 * 1024 * 1024 : 0; | ||
| 11 | |||
| 12 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 5b6c7792e..5c4f45ab4 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | 1 | // Copyright 2021 yuzu Emulator Project |
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| @@ -12,6 +12,7 @@ | |||
| 12 | #include <utility> | 12 | #include <utility> |
| 13 | 13 | ||
| 14 | #include "common/assert.h" | 14 | #include "common/assert.h" |
| 15 | #include "common/common_sizes.h" | ||
| 15 | #include "common/logging/log.h" | 16 | #include "common/logging/log.h" |
| 16 | #include "common/microprofile.h" | 17 | #include "common/microprofile.h" |
| 17 | #include "common/thread.h" | 18 | #include "common/thread.h" |
| @@ -66,8 +67,13 @@ struct KernelCore::Impl { | |||
| 66 | is_phantom_mode_for_singlecore = false; | 67 | is_phantom_mode_for_singlecore = false; |
| 67 | 68 | ||
| 68 | InitializePhysicalCores(); | 69 | InitializePhysicalCores(); |
| 69 | InitializeSystemResourceLimit(kernel, system); | 70 | |
| 70 | InitializeMemoryLayout(); | 71 | // Derive the initial memory layout from the emulated board |
| 72 | KMemoryLayout memory_layout; | ||
| 73 | DeriveInitialMemoryLayout(memory_layout); | ||
| 74 | InitializeMemoryLayout(memory_layout); | ||
| 75 | InitializeSystemResourceLimit(kernel, system.CoreTiming(), memory_layout); | ||
| 76 | InitializeSlabHeaps(); | ||
| 71 | InitializeSchedulers(); | 77 | InitializeSchedulers(); |
| 72 | InitializeSuspendThreads(); | 78 | InitializeSuspendThreads(); |
| 73 | InitializePreemption(kernel); | 79 | InitializePreemption(kernel); |
| @@ -136,27 +142,33 @@ struct KernelCore::Impl { | |||
| 136 | } | 142 | } |
| 137 | 143 | ||
| 138 | // Creates the default system resource limit | 144 | // Creates the default system resource limit |
| 139 | void InitializeSystemResourceLimit(KernelCore& kernel, Core::System& system) { | 145 | void InitializeSystemResourceLimit(KernelCore& kernel, |
| 140 | system_resource_limit = std::make_shared<KResourceLimit>(kernel, system); | 146 | const Core::Timing::CoreTiming& core_timing, |
| 147 | const KMemoryLayout& memory_layout) { | ||
| 148 | system_resource_limit = std::make_shared<KResourceLimit>(kernel, core_timing); | ||
| 149 | const auto [total_size, kernel_size] = memory_layout.GetTotalAndKernelMemorySizes(); | ||
| 141 | 150 | ||
| 142 | // If setting the default system values fails, then something seriously wrong has occurred. | 151 | // If setting the default system values fails, then something seriously wrong has occurred. |
| 143 | ASSERT(system_resource_limit->SetLimitValue(LimitableResource::PhysicalMemory, 0x100000000) | 152 | ASSERT(system_resource_limit->SetLimitValue(LimitableResource::PhysicalMemory, total_size) |
| 144 | .IsSuccess()); | 153 | .IsSuccess()); |
| 145 | ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Threads, 800).IsSuccess()); | 154 | ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Threads, 800).IsSuccess()); |
| 146 | ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Events, 700).IsSuccess()); | 155 | ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Events, 900).IsSuccess()); |
| 147 | ASSERT(system_resource_limit->SetLimitValue(LimitableResource::TransferMemory, 200) | 156 | ASSERT(system_resource_limit->SetLimitValue(LimitableResource::TransferMemory, 200) |
| 148 | .IsSuccess()); | 157 | .IsSuccess()); |
| 149 | ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Sessions, 933).IsSuccess()); | 158 | ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Sessions, 1133).IsSuccess()); |
| 159 | system_resource_limit->Reserve(LimitableResource::PhysicalMemory, kernel_size); | ||
| 150 | 160 | ||
| 151 | // Derived from recent software updates. The kernel reserves 27MB | ||
| 152 | constexpr u64 kernel_size{0x1b00000}; | ||
| 153 | if (!system_resource_limit->Reserve(LimitableResource::PhysicalMemory, kernel_size)) { | ||
| 154 | UNREACHABLE(); | ||
| 155 | } | ||
| 156 | // Reserve secure applet memory, introduced in firmware 5.0.0 | 161 | // Reserve secure applet memory, introduced in firmware 5.0.0 |
| 157 | constexpr u64 secure_applet_memory_size{0x400000}; | 162 | constexpr u64 secure_applet_memory_size{Common::Size_4_MB}; |
| 158 | ASSERT(system_resource_limit->Reserve(LimitableResource::PhysicalMemory, | 163 | ASSERT(system_resource_limit->Reserve(LimitableResource::PhysicalMemory, |
| 159 | secure_applet_memory_size)); | 164 | secure_applet_memory_size)); |
| 165 | |||
| 166 | // This memory seems to be reserved on hardware, but is not reserved/used by yuzu. | ||
| 167 | // Likely Horizon OS reserved memory | ||
| 168 | // TODO(ameerj): Derive the memory rather than hardcode it. | ||
| 169 | constexpr u64 unknown_reserved_memory{0x2f896000}; | ||
| 170 | ASSERT(system_resource_limit->Reserve(LimitableResource::PhysicalMemory, | ||
| 171 | unknown_reserved_memory)); | ||
| 160 | } | 172 | } |
| 161 | 173 | ||
| 162 | void InitializePreemption(KernelCore& kernel) { | 174 | void InitializePreemption(KernelCore& kernel) { |
| @@ -268,51 +280,319 @@ struct KernelCore::Impl { | |||
| 268 | return schedulers[thread_id]->GetCurrentThread(); | 280 | return schedulers[thread_id]->GetCurrentThread(); |
| 269 | } | 281 | } |
| 270 | 282 | ||
| 271 | void InitializeMemoryLayout() { | 283 | void DeriveInitialMemoryLayout(KMemoryLayout& memory_layout) { |
| 272 | // Initialize memory layout | 284 | // Insert the root region for the virtual memory tree, from which all other regions will |
| 273 | constexpr KMemoryLayout layout{KMemoryLayout::GetDefaultLayout()}; | 285 | // derive. |
| 286 | memory_layout.GetVirtualMemoryRegionTree().InsertDirectly( | ||
| 287 | KernelVirtualAddressSpaceBase, | ||
| 288 | KernelVirtualAddressSpaceBase + KernelVirtualAddressSpaceSize - 1); | ||
| 289 | |||
| 290 | // Insert the root region for the physical memory tree, from which all other regions will | ||
| 291 | // derive. | ||
| 292 | memory_layout.GetPhysicalMemoryRegionTree().InsertDirectly( | ||
| 293 | KernelPhysicalAddressSpaceBase, | ||
| 294 | KernelPhysicalAddressSpaceBase + KernelPhysicalAddressSpaceSize - 1); | ||
| 295 | |||
| 296 | // Save start and end for ease of use. | ||
| 297 | const VAddr code_start_virt_addr = KernelVirtualAddressCodeBase; | ||
| 298 | const VAddr code_end_virt_addr = KernelVirtualAddressCodeEnd; | ||
| 299 | |||
| 300 | // Setup the containing kernel region. | ||
| 301 | constexpr size_t KernelRegionSize = Common::Size_1_GB; | ||
| 302 | constexpr size_t KernelRegionAlign = Common::Size_1_GB; | ||
| 303 | constexpr VAddr kernel_region_start = | ||
| 304 | Common::AlignDown(code_start_virt_addr, KernelRegionAlign); | ||
| 305 | size_t kernel_region_size = KernelRegionSize; | ||
| 306 | if (!(kernel_region_start + KernelRegionSize - 1 <= KernelVirtualAddressSpaceLast)) { | ||
| 307 | kernel_region_size = KernelVirtualAddressSpaceEnd - kernel_region_start; | ||
| 308 | } | ||
| 309 | ASSERT(memory_layout.GetVirtualMemoryRegionTree().Insert( | ||
| 310 | kernel_region_start, kernel_region_size, KMemoryRegionType_Kernel)); | ||
| 311 | |||
| 312 | // Setup the code region. | ||
| 313 | constexpr size_t CodeRegionAlign = PageSize; | ||
| 314 | constexpr VAddr code_region_start = | ||
| 315 | Common::AlignDown(code_start_virt_addr, CodeRegionAlign); | ||
| 316 | constexpr VAddr code_region_end = Common::AlignUp(code_end_virt_addr, CodeRegionAlign); | ||
| 317 | constexpr size_t code_region_size = code_region_end - code_region_start; | ||
| 318 | ASSERT(memory_layout.GetVirtualMemoryRegionTree().Insert( | ||
| 319 | code_region_start, code_region_size, KMemoryRegionType_KernelCode)); | ||
| 320 | |||
| 321 | // Setup board-specific device physical regions. | ||
| 322 | Init::SetupDevicePhysicalMemoryRegions(memory_layout); | ||
| 323 | |||
| 324 | // Determine the amount of space needed for the misc region. | ||
| 325 | size_t misc_region_needed_size; | ||
| 326 | { | ||
| 327 | // Each core has a one page stack for all three stack types (Main, Idle, Exception). | ||
| 328 | misc_region_needed_size = Core::Hardware::NUM_CPU_CORES * (3 * (PageSize + PageSize)); | ||
| 329 | |||
| 330 | // Account for each auto-map device. | ||
| 331 | for (const auto& region : memory_layout.GetPhysicalMemoryRegionTree()) { | ||
| 332 | if (region.HasTypeAttribute(KMemoryRegionAttr_ShouldKernelMap)) { | ||
| 333 | // Check that the region is valid. | ||
| 334 | ASSERT(region.GetEndAddress() != 0); | ||
| 335 | |||
| 336 | // Account for the region. | ||
| 337 | misc_region_needed_size += | ||
| 338 | PageSize + (Common::AlignUp(region.GetLastAddress(), PageSize) - | ||
| 339 | Common::AlignDown(region.GetAddress(), PageSize)); | ||
| 340 | } | ||
| 341 | } | ||
| 342 | |||
| 343 | // Multiply the needed size by three, to account for the need for guard space. | ||
| 344 | misc_region_needed_size *= 3; | ||
| 345 | } | ||
| 346 | |||
| 347 | // Decide on the actual size for the misc region. | ||
| 348 | constexpr size_t MiscRegionAlign = KernelAslrAlignment; | ||
| 349 | constexpr size_t MiscRegionMinimumSize = Common::Size_32_MB; | ||
| 350 | const size_t misc_region_size = Common::AlignUp( | ||
| 351 | std::max(misc_region_needed_size, MiscRegionMinimumSize), MiscRegionAlign); | ||
| 352 | ASSERT(misc_region_size > 0); | ||
| 353 | |||
| 354 | // Setup the misc region. | ||
| 355 | const VAddr misc_region_start = | ||
| 356 | memory_layout.GetVirtualMemoryRegionTree().GetRandomAlignedRegion( | ||
| 357 | misc_region_size, MiscRegionAlign, KMemoryRegionType_Kernel); | ||
| 358 | ASSERT(memory_layout.GetVirtualMemoryRegionTree().Insert( | ||
| 359 | misc_region_start, misc_region_size, KMemoryRegionType_KernelMisc)); | ||
| 360 | |||
| 361 | // Setup the stack region. | ||
| 362 | constexpr size_t StackRegionSize = Common::Size_14_MB; | ||
| 363 | constexpr size_t StackRegionAlign = KernelAslrAlignment; | ||
| 364 | const VAddr stack_region_start = | ||
| 365 | memory_layout.GetVirtualMemoryRegionTree().GetRandomAlignedRegion( | ||
| 366 | StackRegionSize, StackRegionAlign, KMemoryRegionType_Kernel); | ||
| 367 | ASSERT(memory_layout.GetVirtualMemoryRegionTree().Insert( | ||
| 368 | stack_region_start, StackRegionSize, KMemoryRegionType_KernelStack)); | ||
| 369 | |||
| 370 | // Determine the size of the resource region. | ||
| 371 | const size_t resource_region_size = memory_layout.GetResourceRegionSizeForInit(); | ||
| 372 | |||
| 373 | // Determine the size of the slab region. | ||
| 374 | const size_t slab_region_size = Common::AlignUp(KernelSlabHeapSize, PageSize); | ||
| 375 | ASSERT(slab_region_size <= resource_region_size); | ||
| 376 | |||
| 377 | // Setup the slab region. | ||
| 378 | const PAddr code_start_phys_addr = KernelPhysicalAddressCodeBase; | ||
| 379 | const PAddr code_end_phys_addr = code_start_phys_addr + code_region_size; | ||
| 380 | const PAddr slab_start_phys_addr = code_end_phys_addr; | ||
| 381 | const PAddr slab_end_phys_addr = slab_start_phys_addr + slab_region_size; | ||
| 382 | constexpr size_t SlabRegionAlign = KernelAslrAlignment; | ||
| 383 | const size_t slab_region_needed_size = | ||
| 384 | Common::AlignUp(code_end_phys_addr + slab_region_size, SlabRegionAlign) - | ||
| 385 | Common::AlignDown(code_end_phys_addr, SlabRegionAlign); | ||
| 386 | const VAddr slab_region_start = | ||
| 387 | memory_layout.GetVirtualMemoryRegionTree().GetRandomAlignedRegion( | ||
| 388 | slab_region_needed_size, SlabRegionAlign, KMemoryRegionType_Kernel) + | ||
| 389 | (code_end_phys_addr % SlabRegionAlign); | ||
| 390 | ASSERT(memory_layout.GetVirtualMemoryRegionTree().Insert( | ||
| 391 | slab_region_start, slab_region_size, KMemoryRegionType_KernelSlab)); | ||
| 392 | |||
| 393 | // Setup the temp region. | ||
| 394 | constexpr size_t TempRegionSize = Common::Size_128_MB; | ||
| 395 | constexpr size_t TempRegionAlign = KernelAslrAlignment; | ||
| 396 | const VAddr temp_region_start = | ||
| 397 | memory_layout.GetVirtualMemoryRegionTree().GetRandomAlignedRegion( | ||
| 398 | TempRegionSize, TempRegionAlign, KMemoryRegionType_Kernel); | ||
| 399 | ASSERT(memory_layout.GetVirtualMemoryRegionTree().Insert(temp_region_start, TempRegionSize, | ||
| 400 | KMemoryRegionType_KernelTemp)); | ||
| 401 | |||
| 402 | // Automatically map in devices that have auto-map attributes. | ||
| 403 | for (auto& region : memory_layout.GetPhysicalMemoryRegionTree()) { | ||
| 404 | // We only care about kernel regions. | ||
| 405 | if (!region.IsDerivedFrom(KMemoryRegionType_Kernel)) { | ||
| 406 | continue; | ||
| 407 | } | ||
| 408 | |||
| 409 | // Check whether we should map the region. | ||
| 410 | if (!region.HasTypeAttribute(KMemoryRegionAttr_ShouldKernelMap)) { | ||
| 411 | continue; | ||
| 412 | } | ||
| 413 | |||
| 414 | // If this region has already been mapped, no need to consider it. | ||
| 415 | if (region.HasTypeAttribute(KMemoryRegionAttr_DidKernelMap)) { | ||
| 416 | continue; | ||
| 417 | } | ||
| 418 | |||
| 419 | // Check that the region is valid. | ||
| 420 | ASSERT(region.GetEndAddress() != 0); | ||
| 421 | |||
| 422 | // Set the attribute to note we've mapped this region. | ||
| 423 | region.SetTypeAttribute(KMemoryRegionAttr_DidKernelMap); | ||
| 424 | |||
| 425 | // Create a virtual pair region and insert it into the tree. | ||
| 426 | const PAddr map_phys_addr = Common::AlignDown(region.GetAddress(), PageSize); | ||
| 427 | const size_t map_size = | ||
| 428 | Common::AlignUp(region.GetEndAddress(), PageSize) - map_phys_addr; | ||
| 429 | const VAddr map_virt_addr = | ||
| 430 | memory_layout.GetVirtualMemoryRegionTree().GetRandomAlignedRegionWithGuard( | ||
| 431 | map_size, PageSize, KMemoryRegionType_KernelMisc, PageSize); | ||
| 432 | ASSERT(memory_layout.GetVirtualMemoryRegionTree().Insert( | ||
| 433 | map_virt_addr, map_size, KMemoryRegionType_KernelMiscMappedDevice)); | ||
| 434 | region.SetPairAddress(map_virt_addr + region.GetAddress() - map_phys_addr); | ||
| 435 | } | ||
| 436 | |||
| 437 | Init::SetupDramPhysicalMemoryRegions(memory_layout); | ||
| 438 | |||
| 439 | // Insert a physical region for the kernel code region. | ||
| 440 | ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert( | ||
| 441 | code_start_phys_addr, code_region_size, KMemoryRegionType_DramKernelCode)); | ||
| 442 | |||
| 443 | // Insert a physical region for the kernel slab region. | ||
| 444 | ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert( | ||
| 445 | slab_start_phys_addr, slab_region_size, KMemoryRegionType_DramKernelSlab)); | ||
| 446 | |||
| 447 | // Determine size available for kernel page table heaps, requiring > 8 MB. | ||
| 448 | const PAddr resource_end_phys_addr = slab_start_phys_addr + resource_region_size; | ||
| 449 | const size_t page_table_heap_size = resource_end_phys_addr - slab_end_phys_addr; | ||
| 450 | ASSERT(page_table_heap_size / Common::Size_4_MB > 2); | ||
| 451 | |||
| 452 | // Insert a physical region for the kernel page table heap region | ||
| 453 | ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert( | ||
| 454 | slab_end_phys_addr, page_table_heap_size, KMemoryRegionType_DramKernelPtHeap)); | ||
| 455 | |||
| 456 | // All DRAM regions that we haven't tagged by this point will be mapped under the linear | ||
| 457 | // mapping. Tag them. | ||
| 458 | for (auto& region : memory_layout.GetPhysicalMemoryRegionTree()) { | ||
| 459 | if (region.GetType() == KMemoryRegionType_Dram) { | ||
| 460 | // Check that the region is valid. | ||
| 461 | ASSERT(region.GetEndAddress() != 0); | ||
| 462 | |||
| 463 | // Set the linear map attribute. | ||
| 464 | region.SetTypeAttribute(KMemoryRegionAttr_LinearMapped); | ||
| 465 | } | ||
| 466 | } | ||
| 467 | |||
| 468 | // Get the linear region extents. | ||
| 469 | const auto linear_extents = | ||
| 470 | memory_layout.GetPhysicalMemoryRegionTree().GetDerivedRegionExtents( | ||
| 471 | KMemoryRegionAttr_LinearMapped); | ||
| 472 | ASSERT(linear_extents.GetEndAddress() != 0); | ||
| 473 | |||
| 474 | // Setup the linear mapping region. | ||
| 475 | constexpr size_t LinearRegionAlign = Common::Size_1_GB; | ||
| 476 | const PAddr aligned_linear_phys_start = | ||
| 477 | Common::AlignDown(linear_extents.GetAddress(), LinearRegionAlign); | ||
| 478 | const size_t linear_region_size = | ||
| 479 | Common::AlignUp(linear_extents.GetEndAddress(), LinearRegionAlign) - | ||
| 480 | aligned_linear_phys_start; | ||
| 481 | const VAddr linear_region_start = | ||
| 482 | memory_layout.GetVirtualMemoryRegionTree().GetRandomAlignedRegionWithGuard( | ||
| 483 | linear_region_size, LinearRegionAlign, KMemoryRegionType_None, LinearRegionAlign); | ||
| 484 | |||
| 485 | const u64 linear_region_phys_to_virt_diff = linear_region_start - aligned_linear_phys_start; | ||
| 486 | |||
| 487 | // Map and create regions for all the linearly-mapped data. | ||
| 488 | { | ||
| 489 | PAddr cur_phys_addr = 0; | ||
| 490 | u64 cur_size = 0; | ||
| 491 | for (auto& region : memory_layout.GetPhysicalMemoryRegionTree()) { | ||
| 492 | if (!region.HasTypeAttribute(KMemoryRegionAttr_LinearMapped)) { | ||
| 493 | continue; | ||
| 494 | } | ||
| 495 | |||
| 496 | ASSERT(region.GetEndAddress() != 0); | ||
| 497 | |||
| 498 | if (cur_size == 0) { | ||
| 499 | cur_phys_addr = region.GetAddress(); | ||
| 500 | cur_size = region.GetSize(); | ||
| 501 | } else if (cur_phys_addr + cur_size == region.GetAddress()) { | ||
| 502 | cur_size += region.GetSize(); | ||
| 503 | } else { | ||
| 504 | cur_phys_addr = region.GetAddress(); | ||
| 505 | cur_size = region.GetSize(); | ||
| 506 | } | ||
| 507 | |||
| 508 | const VAddr region_virt_addr = | ||
| 509 | region.GetAddress() + linear_region_phys_to_virt_diff; | ||
| 510 | ASSERT(memory_layout.GetVirtualMemoryRegionTree().Insert( | ||
| 511 | region_virt_addr, region.GetSize(), | ||
| 512 | GetTypeForVirtualLinearMapping(region.GetType()))); | ||
| 513 | region.SetPairAddress(region_virt_addr); | ||
| 514 | |||
| 515 | KMemoryRegion* virt_region = | ||
| 516 | memory_layout.GetVirtualMemoryRegionTree().FindModifiable(region_virt_addr); | ||
| 517 | ASSERT(virt_region != nullptr); | ||
| 518 | virt_region->SetPairAddress(region.GetAddress()); | ||
| 519 | } | ||
| 520 | } | ||
| 521 | |||
| 522 | // Insert regions for the initial page table region. | ||
| 523 | ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert( | ||
| 524 | resource_end_phys_addr, KernelPageTableHeapSize, KMemoryRegionType_DramKernelInitPt)); | ||
| 525 | ASSERT(memory_layout.GetVirtualMemoryRegionTree().Insert( | ||
| 526 | resource_end_phys_addr + linear_region_phys_to_virt_diff, KernelPageTableHeapSize, | ||
| 527 | KMemoryRegionType_VirtualDramKernelInitPt)); | ||
| 528 | |||
| 529 | // All linear-mapped DRAM regions that we haven't tagged by this point will be allocated to | ||
| 530 | // some pool partition. Tag them. | ||
| 531 | for (auto& region : memory_layout.GetPhysicalMemoryRegionTree()) { | ||
| 532 | if (region.GetType() == (KMemoryRegionType_Dram | KMemoryRegionAttr_LinearMapped)) { | ||
| 533 | region.SetType(KMemoryRegionType_DramPoolPartition); | ||
| 534 | } | ||
| 535 | } | ||
| 536 | |||
| 537 | // Setup all other memory regions needed to arrange the pool partitions. | ||
| 538 | Init::SetupPoolPartitionMemoryRegions(memory_layout); | ||
| 539 | |||
| 540 | // Cache all linear regions in their own trees for faster access, later. | ||
| 541 | memory_layout.InitializeLinearMemoryRegionTrees(aligned_linear_phys_start, | ||
| 542 | linear_region_start); | ||
| 543 | } | ||
| 544 | |||
| 545 | void InitializeMemoryLayout(const KMemoryLayout& memory_layout) { | ||
| 546 | const auto system_pool = memory_layout.GetKernelSystemPoolRegionPhysicalExtents(); | ||
| 547 | const auto applet_pool = memory_layout.GetKernelAppletPoolRegionPhysicalExtents(); | ||
| 548 | const auto application_pool = memory_layout.GetKernelApplicationPoolRegionPhysicalExtents(); | ||
| 549 | |||
| 550 | // Initialize memory managers | ||
| 551 | memory_manager = std::make_unique<KMemoryManager>(); | ||
| 552 | memory_manager->InitializeManager(KMemoryManager::Pool::Application, | ||
| 553 | application_pool.GetAddress(), | ||
| 554 | application_pool.GetEndAddress()); | ||
| 555 | memory_manager->InitializeManager(KMemoryManager::Pool::Applet, applet_pool.GetAddress(), | ||
| 556 | applet_pool.GetEndAddress()); | ||
| 557 | memory_manager->InitializeManager(KMemoryManager::Pool::System, system_pool.GetAddress(), | ||
| 558 | system_pool.GetEndAddress()); | ||
| 559 | |||
| 560 | // Setup memory regions for emulated processes | ||
| 561 | // TODO(bunnei): These should not be hardcoded regions initialized within the kernel | ||
| 274 | constexpr std::size_t hid_size{0x40000}; | 562 | constexpr std::size_t hid_size{0x40000}; |
| 275 | constexpr std::size_t font_size{0x1100000}; | 563 | constexpr std::size_t font_size{0x1100000}; |
| 276 | constexpr std::size_t irs_size{0x8000}; | 564 | constexpr std::size_t irs_size{0x8000}; |
| 277 | constexpr std::size_t time_size{0x1000}; | 565 | constexpr std::size_t time_size{0x1000}; |
| 278 | constexpr PAddr hid_addr{layout.System().StartAddress()}; | ||
| 279 | constexpr PAddr font_pa{layout.System().StartAddress() + hid_size}; | ||
| 280 | constexpr PAddr irs_addr{layout.System().StartAddress() + hid_size + font_size}; | ||
| 281 | constexpr PAddr time_addr{layout.System().StartAddress() + hid_size + font_size + irs_size}; | ||
| 282 | 566 | ||
| 283 | // Initialize memory manager | 567 | const PAddr hid_phys_addr{system_pool.GetAddress()}; |
| 284 | memory_manager = std::make_unique<KMemoryManager>(); | 568 | const PAddr font_phys_addr{system_pool.GetAddress() + hid_size}; |
| 285 | memory_manager->InitializeManager(KMemoryManager::Pool::Application, | 569 | const PAddr irs_phys_addr{system_pool.GetAddress() + hid_size + font_size}; |
| 286 | layout.Application().StartAddress(), | 570 | const PAddr time_phys_addr{system_pool.GetAddress() + hid_size + font_size + irs_size}; |
| 287 | layout.Application().EndAddress()); | ||
| 288 | memory_manager->InitializeManager(KMemoryManager::Pool::Applet, | ||
| 289 | layout.Applet().StartAddress(), | ||
| 290 | layout.Applet().EndAddress()); | ||
| 291 | memory_manager->InitializeManager(KMemoryManager::Pool::System, | ||
| 292 | layout.System().StartAddress(), | ||
| 293 | layout.System().EndAddress()); | ||
| 294 | 571 | ||
| 295 | hid_shared_mem = Kernel::KSharedMemory::Create( | 572 | hid_shared_mem = Kernel::KSharedMemory::Create( |
| 296 | system.Kernel(), system.DeviceMemory(), nullptr, {hid_addr, hid_size / PageSize}, | 573 | system.Kernel(), system.DeviceMemory(), nullptr, {hid_phys_addr, hid_size / PageSize}, |
| 297 | KMemoryPermission::None, KMemoryPermission::Read, hid_addr, hid_size, | 574 | KMemoryPermission::None, KMemoryPermission::Read, hid_phys_addr, hid_size, |
| 298 | "HID:SharedMemory"); | 575 | "HID:SharedMemory"); |
| 299 | font_shared_mem = Kernel::KSharedMemory::Create( | 576 | font_shared_mem = Kernel::KSharedMemory::Create( |
| 300 | system.Kernel(), system.DeviceMemory(), nullptr, {font_pa, font_size / PageSize}, | 577 | system.Kernel(), system.DeviceMemory(), nullptr, {font_phys_addr, font_size / PageSize}, |
| 301 | KMemoryPermission::None, KMemoryPermission::Read, font_pa, font_size, | 578 | KMemoryPermission::None, KMemoryPermission::Read, font_phys_addr, font_size, |
| 302 | "Font:SharedMemory"); | 579 | "Font:SharedMemory"); |
| 303 | irs_shared_mem = Kernel::KSharedMemory::Create( | 580 | irs_shared_mem = Kernel::KSharedMemory::Create( |
| 304 | system.Kernel(), system.DeviceMemory(), nullptr, {irs_addr, irs_size / PageSize}, | 581 | system.Kernel(), system.DeviceMemory(), nullptr, {irs_phys_addr, irs_size / PageSize}, |
| 305 | KMemoryPermission::None, KMemoryPermission::Read, irs_addr, irs_size, | 582 | KMemoryPermission::None, KMemoryPermission::Read, irs_phys_addr, irs_size, |
| 306 | "IRS:SharedMemory"); | 583 | "IRS:SharedMemory"); |
| 307 | time_shared_mem = Kernel::KSharedMemory::Create( | 584 | time_shared_mem = Kernel::KSharedMemory::Create( |
| 308 | system.Kernel(), system.DeviceMemory(), nullptr, {time_addr, time_size / PageSize}, | 585 | system.Kernel(), system.DeviceMemory(), nullptr, {time_phys_addr, time_size / PageSize}, |
| 309 | KMemoryPermission::None, KMemoryPermission::Read, time_addr, time_size, | 586 | KMemoryPermission::None, KMemoryPermission::Read, time_phys_addr, time_size, |
| 310 | "Time:SharedMemory"); | 587 | "Time:SharedMemory"); |
| 588 | } | ||
| 311 | 589 | ||
| 590 | void InitializeSlabHeaps() { | ||
| 312 | // Allocate slab heaps | 591 | // Allocate slab heaps |
| 313 | user_slab_heap_pages = std::make_unique<KSlabHeap<Page>>(); | 592 | user_slab_heap_pages = std::make_unique<KSlabHeap<Page>>(); |
| 314 | 593 | ||
| 315 | constexpr u64 user_slab_heap_size{0x1ef000}; | 594 | // TODO(ameerj): This should be derived, not hardcoded within the kernel |
| 595 | constexpr u64 user_slab_heap_size{0x3de000}; | ||
| 316 | // Reserve slab heaps | 596 | // Reserve slab heaps |
| 317 | ASSERT( | 597 | ASSERT( |
| 318 | system_resource_limit->Reserve(LimitableResource::PhysicalMemory, user_slab_heap_size)); | 598 | system_resource_limit->Reserve(LimitableResource::PhysicalMemory, user_slab_heap_size)); |
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 56906f2da..a500e63bc 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project / PPSSPP Project | 1 | // Copyright 2021 yuzu Emulator Project |
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index 9d5956ead..e35deb8e2 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | #include "common/alignment.h" | 10 | #include "common/alignment.h" |
| 11 | #include "common/assert.h" | 11 | #include "common/assert.h" |
| 12 | #include "common/logging/log.h" | 12 | #include "common/logging/log.h" |
| 13 | #include "common/settings.h" | ||
| 13 | #include "core/core.h" | 14 | #include "core/core.h" |
| 14 | #include "core/device_memory.h" | 15 | #include "core/device_memory.h" |
| 15 | #include "core/file_sys/program_metadata.h" | 16 | #include "core/file_sys/program_metadata.h" |
| @@ -26,7 +27,6 @@ | |||
| 26 | #include "core/hle/kernel/svc_results.h" | 27 | #include "core/hle/kernel/svc_results.h" |
| 27 | #include "core/hle/lock.h" | 28 | #include "core/hle/lock.h" |
| 28 | #include "core/memory.h" | 29 | #include "core/memory.h" |
| 29 | #include "core/settings.h" | ||
| 30 | 30 | ||
| 31 | namespace Kernel { | 31 | namespace Kernel { |
| 32 | namespace { | 32 | namespace { |
| @@ -120,9 +120,7 @@ std::shared_ptr<Process> Process::Create(Core::System& system, std::string name, | |||
| 120 | std::shared_ptr<Process> process = std::make_shared<Process>(system); | 120 | std::shared_ptr<Process> process = std::make_shared<Process>(system); |
| 121 | process->name = std::move(name); | 121 | process->name = std::move(name); |
| 122 | 122 | ||
| 123 | // TODO: This is inaccurate | 123 | process->resource_limit = kernel.GetSystemResourceLimit(); |
| 124 | // The process should hold a reference to the kernel-wide resource limit. | ||
| 125 | process->resource_limit = std::make_shared<KResourceLimit>(kernel, system); | ||
| 126 | process->status = ProcessStatus::Created; | 124 | process->status = ProcessStatus::Created; |
| 127 | process->program_id = 0; | 125 | process->program_id = 0; |
| 128 | process->process_id = type == ProcessType::KernelInternal ? kernel.CreateNewKernelProcessID() | 126 | process->process_id = type == ProcessType::KernelInternal ? kernel.CreateNewKernelProcessID() |
| @@ -160,17 +158,13 @@ void Process::DecrementThreadCount() { | |||
| 160 | } | 158 | } |
| 161 | 159 | ||
| 162 | u64 Process::GetTotalPhysicalMemoryAvailable() const { | 160 | u64 Process::GetTotalPhysicalMemoryAvailable() const { |
| 163 | // TODO: This is expected to always return the application memory pool size after accurately | ||
| 164 | // reserving kernel resources. The current workaround uses a process-local resource limit of | ||
| 165 | // application memory pool size, which is inaccurate. | ||
| 166 | const u64 capacity{resource_limit->GetFreeValue(LimitableResource::PhysicalMemory) + | 161 | const u64 capacity{resource_limit->GetFreeValue(LimitableResource::PhysicalMemory) + |
| 167 | page_table->GetTotalHeapSize() + GetSystemResourceSize() + image_size + | 162 | page_table->GetTotalHeapSize() + GetSystemResourceSize() + image_size + |
| 168 | main_thread_stack_size}; | 163 | main_thread_stack_size}; |
| 169 | 164 | ASSERT(capacity == kernel.MemoryManager().GetSize(KMemoryManager::Pool::Application)); | |
| 170 | if (capacity < memory_usage_capacity) { | 165 | if (capacity < memory_usage_capacity) { |
| 171 | return capacity; | 166 | return capacity; |
| 172 | } | 167 | } |
| 173 | |||
| 174 | return memory_usage_capacity; | 168 | return memory_usage_capacity; |
| 175 | } | 169 | } |
| 176 | 170 | ||
| @@ -272,10 +266,6 @@ ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, | |||
| 272 | system_resource_size = metadata.GetSystemResourceSize(); | 266 | system_resource_size = metadata.GetSystemResourceSize(); |
| 273 | image_size = code_size; | 267 | image_size = code_size; |
| 274 | 268 | ||
| 275 | // Set initial resource limits | ||
| 276 | resource_limit->SetLimitValue( | ||
| 277 | LimitableResource::PhysicalMemory, | ||
| 278 | kernel.MemoryManager().GetSize(KMemoryManager::Pool::Application)); | ||
| 279 | KScopedResourceReservation memory_reservation(resource_limit, LimitableResource::PhysicalMemory, | 269 | KScopedResourceReservation memory_reservation(resource_limit, LimitableResource::PhysicalMemory, |
| 280 | code_size + system_resource_size); | 270 | code_size + system_resource_size); |
| 281 | if (!memory_reservation.Succeeded()) { | 271 | if (!memory_reservation.Succeeded()) { |
| @@ -324,16 +314,6 @@ ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, | |||
| 324 | UNREACHABLE(); | 314 | UNREACHABLE(); |
| 325 | } | 315 | } |
| 326 | 316 | ||
| 327 | // Set initial resource limits | ||
| 328 | resource_limit->SetLimitValue( | ||
| 329 | LimitableResource::PhysicalMemory, | ||
| 330 | kernel.MemoryManager().GetSize(KMemoryManager::Pool::Application)); | ||
| 331 | |||
| 332 | resource_limit->SetLimitValue(LimitableResource::Threads, 608); | ||
| 333 | resource_limit->SetLimitValue(LimitableResource::Events, 700); | ||
| 334 | resource_limit->SetLimitValue(LimitableResource::TransferMemory, 128); | ||
| 335 | resource_limit->SetLimitValue(LimitableResource::Sessions, 894); | ||
| 336 | |||
| 337 | // Create TLS region | 317 | // Create TLS region |
| 338 | tls_region_address = CreateTLSRegion(); | 318 | tls_region_address = CreateTLSRegion(); |
| 339 | memory_reservation.Commit(); | 319 | memory_reservation.Commit(); |
diff --git a/src/core/hle/kernel/process_capability.cpp b/src/core/hle/kernel/process_capability.cpp index 3fc326eab..1006ee50c 100644 --- a/src/core/hle/kernel/process_capability.cpp +++ b/src/core/hle/kernel/process_capability.cpp | |||
| @@ -281,11 +281,6 @@ ResultCode ProcessCapabilities::HandleSyscallFlags(u32& set_svc_bits, u32 flags) | |||
| 281 | continue; | 281 | continue; |
| 282 | } | 282 | } |
| 283 | 283 | ||
| 284 | if (svc_number >= svc_capabilities.size()) { | ||
| 285 | LOG_ERROR(Kernel, "Process svc capability is out of range! svc_number={}", svc_number); | ||
| 286 | return ResultOutOfRange; | ||
| 287 | } | ||
| 288 | |||
| 289 | svc_capabilities[svc_number] = true; | 284 | svc_capabilities[svc_number] = true; |
| 290 | } | 285 | } |
| 291 | 286 | ||
diff --git a/src/core/hle/kernel/process_capability.h b/src/core/hle/kernel/process_capability.h index 73ad197fa..b7a9b2e45 100644 --- a/src/core/hle/kernel/process_capability.h +++ b/src/core/hle/kernel/process_capability.h | |||
| @@ -68,7 +68,7 @@ enum class ProgramType { | |||
| 68 | class ProcessCapabilities { | 68 | class ProcessCapabilities { |
| 69 | public: | 69 | public: |
| 70 | using InterruptCapabilities = std::bitset<1024>; | 70 | using InterruptCapabilities = std::bitset<1024>; |
| 71 | using SyscallCapabilities = std::bitset<128>; | 71 | using SyscallCapabilities = std::bitset<192>; |
| 72 | 72 | ||
| 73 | ProcessCapabilities() = default; | 73 | ProcessCapabilities() = default; |
| 74 | ProcessCapabilities(const ProcessCapabilities&) = delete; | 74 | ProcessCapabilities(const ProcessCapabilities&) = delete; |
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 326d3b9ec..bebb86154 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp | |||
| @@ -2156,7 +2156,7 @@ static ResultCode CreateResourceLimit(Core::System& system, Handle* out_handle) | |||
| 2156 | LOG_DEBUG(Kernel_SVC, "called"); | 2156 | LOG_DEBUG(Kernel_SVC, "called"); |
| 2157 | 2157 | ||
| 2158 | auto& kernel = system.Kernel(); | 2158 | auto& kernel = system.Kernel(); |
| 2159 | auto resource_limit = std::make_shared<KResourceLimit>(kernel, system); | 2159 | auto resource_limit = std::make_shared<KResourceLimit>(kernel, system.CoreTiming()); |
| 2160 | 2160 | ||
| 2161 | auto* const current_process = kernel.CurrentProcess(); | 2161 | auto* const current_process = kernel.CurrentProcess(); |
| 2162 | ASSERT(current_process != nullptr); | 2162 | ASSERT(current_process != nullptr); |
| @@ -2455,6 +2455,74 @@ static const FunctionDef SVC_Table_32[] = { | |||
| 2455 | {0x79, nullptr, "Unknown"}, | 2455 | {0x79, nullptr, "Unknown"}, |
| 2456 | {0x7A, nullptr, "Unknown"}, | 2456 | {0x7A, nullptr, "Unknown"}, |
| 2457 | {0x7B, nullptr, "TerminateProcess32"}, | 2457 | {0x7B, nullptr, "TerminateProcess32"}, |
| 2458 | {0x7C, nullptr, "GetProcessInfo32"}, | ||
| 2459 | {0x7D, nullptr, "CreateResourceLimit32"}, | ||
| 2460 | {0x7E, nullptr, "SetResourceLimitLimitValue32"}, | ||
| 2461 | {0x7F, nullptr, "CallSecureMonitor32"}, | ||
| 2462 | {0x80, nullptr, "Unknown"}, | ||
| 2463 | {0x81, nullptr, "Unknown"}, | ||
| 2464 | {0x82, nullptr, "Unknown"}, | ||
| 2465 | {0x83, nullptr, "Unknown"}, | ||
| 2466 | {0x84, nullptr, "Unknown"}, | ||
| 2467 | {0x85, nullptr, "Unknown"}, | ||
| 2468 | {0x86, nullptr, "Unknown"}, | ||
| 2469 | {0x87, nullptr, "Unknown"}, | ||
| 2470 | {0x88, nullptr, "Unknown"}, | ||
| 2471 | {0x89, nullptr, "Unknown"}, | ||
| 2472 | {0x8A, nullptr, "Unknown"}, | ||
| 2473 | {0x8B, nullptr, "Unknown"}, | ||
| 2474 | {0x8C, nullptr, "Unknown"}, | ||
| 2475 | {0x8D, nullptr, "Unknown"}, | ||
| 2476 | {0x8E, nullptr, "Unknown"}, | ||
| 2477 | {0x8F, nullptr, "Unknown"}, | ||
| 2478 | {0x90, nullptr, "Unknown"}, | ||
| 2479 | {0x91, nullptr, "Unknown"}, | ||
| 2480 | {0x92, nullptr, "Unknown"}, | ||
| 2481 | {0x93, nullptr, "Unknown"}, | ||
| 2482 | {0x94, nullptr, "Unknown"}, | ||
| 2483 | {0x95, nullptr, "Unknown"}, | ||
| 2484 | {0x96, nullptr, "Unknown"}, | ||
| 2485 | {0x97, nullptr, "Unknown"}, | ||
| 2486 | {0x98, nullptr, "Unknown"}, | ||
| 2487 | {0x99, nullptr, "Unknown"}, | ||
| 2488 | {0x9A, nullptr, "Unknown"}, | ||
| 2489 | {0x9B, nullptr, "Unknown"}, | ||
| 2490 | {0x9C, nullptr, "Unknown"}, | ||
| 2491 | {0x9D, nullptr, "Unknown"}, | ||
| 2492 | {0x9E, nullptr, "Unknown"}, | ||
| 2493 | {0x9F, nullptr, "Unknown"}, | ||
| 2494 | {0xA0, nullptr, "Unknown"}, | ||
| 2495 | {0xA1, nullptr, "Unknown"}, | ||
| 2496 | {0xA2, nullptr, "Unknown"}, | ||
| 2497 | {0xA3, nullptr, "Unknown"}, | ||
| 2498 | {0xA4, nullptr, "Unknown"}, | ||
| 2499 | {0xA5, nullptr, "Unknown"}, | ||
| 2500 | {0xA6, nullptr, "Unknown"}, | ||
| 2501 | {0xA7, nullptr, "Unknown"}, | ||
| 2502 | {0xA8, nullptr, "Unknown"}, | ||
| 2503 | {0xA9, nullptr, "Unknown"}, | ||
| 2504 | {0xAA, nullptr, "Unknown"}, | ||
| 2505 | {0xAB, nullptr, "Unknown"}, | ||
| 2506 | {0xAC, nullptr, "Unknown"}, | ||
| 2507 | {0xAD, nullptr, "Unknown"}, | ||
| 2508 | {0xAE, nullptr, "Unknown"}, | ||
| 2509 | {0xAF, nullptr, "Unknown"}, | ||
| 2510 | {0xB0, nullptr, "Unknown"}, | ||
| 2511 | {0xB1, nullptr, "Unknown"}, | ||
| 2512 | {0xB2, nullptr, "Unknown"}, | ||
| 2513 | {0xB3, nullptr, "Unknown"}, | ||
| 2514 | {0xB4, nullptr, "Unknown"}, | ||
| 2515 | {0xB5, nullptr, "Unknown"}, | ||
| 2516 | {0xB6, nullptr, "Unknown"}, | ||
| 2517 | {0xB7, nullptr, "Unknown"}, | ||
| 2518 | {0xB8, nullptr, "Unknown"}, | ||
| 2519 | {0xB9, nullptr, "Unknown"}, | ||
| 2520 | {0xBA, nullptr, "Unknown"}, | ||
| 2521 | {0xBB, nullptr, "Unknown"}, | ||
| 2522 | {0xBC, nullptr, "Unknown"}, | ||
| 2523 | {0xBD, nullptr, "Unknown"}, | ||
| 2524 | {0xBE, nullptr, "Unknown"}, | ||
| 2525 | {0xBF, nullptr, "Unknown"}, | ||
| 2458 | }; | 2526 | }; |
| 2459 | 2527 | ||
| 2460 | static const FunctionDef SVC_Table_64[] = { | 2528 | static const FunctionDef SVC_Table_64[] = { |
| @@ -2586,6 +2654,70 @@ static const FunctionDef SVC_Table_64[] = { | |||
| 2586 | {0x7D, SvcWrap64<CreateResourceLimit>, "CreateResourceLimit"}, | 2654 | {0x7D, SvcWrap64<CreateResourceLimit>, "CreateResourceLimit"}, |
| 2587 | {0x7E, SvcWrap64<SetResourceLimitLimitValue>, "SetResourceLimitLimitValue"}, | 2655 | {0x7E, SvcWrap64<SetResourceLimitLimitValue>, "SetResourceLimitLimitValue"}, |
| 2588 | {0x7F, nullptr, "CallSecureMonitor"}, | 2656 | {0x7F, nullptr, "CallSecureMonitor"}, |
| 2657 | {0x80, nullptr, "Unknown"}, | ||
| 2658 | {0x81, nullptr, "Unknown"}, | ||
| 2659 | {0x82, nullptr, "Unknown"}, | ||
| 2660 | {0x83, nullptr, "Unknown"}, | ||
| 2661 | {0x84, nullptr, "Unknown"}, | ||
| 2662 | {0x85, nullptr, "Unknown"}, | ||
| 2663 | {0x86, nullptr, "Unknown"}, | ||
| 2664 | {0x87, nullptr, "Unknown"}, | ||
| 2665 | {0x88, nullptr, "Unknown"}, | ||
| 2666 | {0x89, nullptr, "Unknown"}, | ||
| 2667 | {0x8A, nullptr, "Unknown"}, | ||
| 2668 | {0x8B, nullptr, "Unknown"}, | ||
| 2669 | {0x8C, nullptr, "Unknown"}, | ||
| 2670 | {0x8D, nullptr, "Unknown"}, | ||
| 2671 | {0x8E, nullptr, "Unknown"}, | ||
| 2672 | {0x8F, nullptr, "Unknown"}, | ||
| 2673 | {0x90, nullptr, "Unknown"}, | ||
| 2674 | {0x91, nullptr, "Unknown"}, | ||
| 2675 | {0x92, nullptr, "Unknown"}, | ||
| 2676 | {0x93, nullptr, "Unknown"}, | ||
| 2677 | {0x94, nullptr, "Unknown"}, | ||
| 2678 | {0x95, nullptr, "Unknown"}, | ||
| 2679 | {0x96, nullptr, "Unknown"}, | ||
| 2680 | {0x97, nullptr, "Unknown"}, | ||
| 2681 | {0x98, nullptr, "Unknown"}, | ||
| 2682 | {0x99, nullptr, "Unknown"}, | ||
| 2683 | {0x9A, nullptr, "Unknown"}, | ||
| 2684 | {0x9B, nullptr, "Unknown"}, | ||
| 2685 | {0x9C, nullptr, "Unknown"}, | ||
| 2686 | {0x9D, nullptr, "Unknown"}, | ||
| 2687 | {0x9E, nullptr, "Unknown"}, | ||
| 2688 | {0x9F, nullptr, "Unknown"}, | ||
| 2689 | {0xA0, nullptr, "Unknown"}, | ||
| 2690 | {0xA1, nullptr, "Unknown"}, | ||
| 2691 | {0xA2, nullptr, "Unknown"}, | ||
| 2692 | {0xA3, nullptr, "Unknown"}, | ||
| 2693 | {0xA4, nullptr, "Unknown"}, | ||
| 2694 | {0xA5, nullptr, "Unknown"}, | ||
| 2695 | {0xA6, nullptr, "Unknown"}, | ||
| 2696 | {0xA7, nullptr, "Unknown"}, | ||
| 2697 | {0xA8, nullptr, "Unknown"}, | ||
| 2698 | {0xA9, nullptr, "Unknown"}, | ||
| 2699 | {0xAA, nullptr, "Unknown"}, | ||
| 2700 | {0xAB, nullptr, "Unknown"}, | ||
| 2701 | {0xAC, nullptr, "Unknown"}, | ||
| 2702 | {0xAD, nullptr, "Unknown"}, | ||
| 2703 | {0xAE, nullptr, "Unknown"}, | ||
| 2704 | {0xAF, nullptr, "Unknown"}, | ||
| 2705 | {0xB0, nullptr, "Unknown"}, | ||
| 2706 | {0xB1, nullptr, "Unknown"}, | ||
| 2707 | {0xB2, nullptr, "Unknown"}, | ||
| 2708 | {0xB3, nullptr, "Unknown"}, | ||
| 2709 | {0xB4, nullptr, "Unknown"}, | ||
| 2710 | {0xB5, nullptr, "Unknown"}, | ||
| 2711 | {0xB6, nullptr, "Unknown"}, | ||
| 2712 | {0xB7, nullptr, "Unknown"}, | ||
| 2713 | {0xB8, nullptr, "Unknown"}, | ||
| 2714 | {0xB9, nullptr, "Unknown"}, | ||
| 2715 | {0xBA, nullptr, "Unknown"}, | ||
| 2716 | {0xBB, nullptr, "Unknown"}, | ||
| 2717 | {0xBC, nullptr, "Unknown"}, | ||
| 2718 | {0xBD, nullptr, "Unknown"}, | ||
| 2719 | {0xBE, nullptr, "Unknown"}, | ||
| 2720 | {0xBF, nullptr, "Unknown"}, | ||
| 2589 | }; | 2721 | }; |
| 2590 | 2722 | ||
| 2591 | static const FunctionDef* GetSVCInfo32(u32 func_num) { | 2723 | static const FunctionDef* GetSVCInfo32(u32 func_num) { |
diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp index 615e20a54..52535ecc0 100644 --- a/src/core/hle/service/acc/acc.cpp +++ b/src/core/hle/service/acc/acc.cpp | |||
| @@ -610,12 +610,17 @@ public: | |||
| 610 | explicit DAUTH_O(Core::System& system_, Common::UUID) : ServiceFramework{system_, "dauth:o"} { | 610 | explicit DAUTH_O(Core::System& system_, Common::UUID) : ServiceFramework{system_, "dauth:o"} { |
| 611 | // clang-format off | 611 | // clang-format off |
| 612 | static const FunctionInfo functions[] = { | 612 | static const FunctionInfo functions[] = { |
| 613 | {0, nullptr, "EnsureAuthenticationTokenCacheAsync"}, // [5.0.0-5.1.0] GeneratePostData | 613 | {0, nullptr, "EnsureAuthenticationTokenCacheAsync"}, |
| 614 | {1, nullptr, "LoadAuthenticationTokenCache"}, // 6.0.0+ | 614 | {1, nullptr, "LoadAuthenticationTokenCache"}, |
| 615 | {2, nullptr, "InvalidateAuthenticationTokenCache"}, // 6.0.0+ | 615 | {2, nullptr, "InvalidateAuthenticationTokenCache"}, |
| 616 | {10, nullptr, "EnsureEdgeTokenCacheAsync"}, // 6.0.0+ | 616 | {10, nullptr, "EnsureEdgeTokenCacheAsync"}, |
| 617 | {11, nullptr, "LoadEdgeTokenCache"}, // 6.0.0+ | 617 | {11, nullptr, "LoadEdgeTokenCache"}, |
| 618 | {12, nullptr, "InvalidateEdgeTokenCache"}, // 6.0.0+ | 618 | {12, nullptr, "InvalidateEdgeTokenCache"}, |
| 619 | {20, nullptr, "EnsureApplicationAuthenticationCacheAsync"}, | ||
| 620 | {21, nullptr, "LoadApplicationAuthenticationTokenCache"}, | ||
| 621 | {22, nullptr, "LoadApplicationNetworkServiceClientConfigCache"}, | ||
| 622 | {23, nullptr, "IsApplicationAuthenticationCacheAvailable"}, | ||
| 623 | {24, nullptr, "InvalidateApplicationAuthenticationCache"}, | ||
| 619 | }; | 624 | }; |
| 620 | // clang-format on | 625 | // clang-format on |
| 621 | 626 | ||
diff --git a/src/core/hle/service/acc/acc_su.cpp b/src/core/hle/service/acc/acc_su.cpp index 49b22583e..bb6118abf 100644 --- a/src/core/hle/service/acc/acc_su.cpp +++ b/src/core/hle/service/acc/acc_su.cpp | |||
| @@ -17,28 +17,30 @@ ACC_SU::ACC_SU(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> p | |||
| 17 | {3, &ACC_SU::ListOpenUsers, "ListOpenUsers"}, | 17 | {3, &ACC_SU::ListOpenUsers, "ListOpenUsers"}, |
| 18 | {4, &ACC_SU::GetLastOpenedUser, "GetLastOpenedUser"}, | 18 | {4, &ACC_SU::GetLastOpenedUser, "GetLastOpenedUser"}, |
| 19 | {5, &ACC_SU::GetProfile, "GetProfile"}, | 19 | {5, &ACC_SU::GetProfile, "GetProfile"}, |
| 20 | {6, nullptr, "GetProfileDigest"}, // 3.0.0+ | 20 | {6, nullptr, "GetProfileDigest"}, |
| 21 | {50, &ACC_SU::IsUserRegistrationRequestPermitted, "IsUserRegistrationRequestPermitted"}, | 21 | {50, &ACC_SU::IsUserRegistrationRequestPermitted, "IsUserRegistrationRequestPermitted"}, |
| 22 | {51, &ACC_SU::TrySelectUserWithoutInteraction, "TrySelectUserWithoutInteraction"}, | 22 | {51, &ACC_SU::TrySelectUserWithoutInteraction, "TrySelectUserWithoutInteraction"}, |
| 23 | {60, &ACC_SU::ListOpenContextStoredUsers, "ListOpenContextStoredUsers"}, // 5.0.0 - 5.1.0 | 23 | {60, &ACC_SU::ListOpenContextStoredUsers, "ListOpenContextStoredUsers"}, |
| 24 | {99, nullptr, "DebugActivateOpenContextRetention"}, // 6.0.0+ | 24 | {99, nullptr, "DebugActivateOpenContextRetention"}, |
| 25 | {100, nullptr, "GetUserRegistrationNotifier"}, | 25 | {100, nullptr, "GetUserRegistrationNotifier"}, |
| 26 | {101, nullptr, "GetUserStateChangeNotifier"}, | 26 | {101, nullptr, "GetUserStateChangeNotifier"}, |
| 27 | {102, nullptr, "GetBaasAccountManagerForSystemService"}, | 27 | {102, nullptr, "GetBaasAccountManagerForSystemService"}, |
| 28 | {103, nullptr, "GetBaasUserAvailabilityChangeNotifier"}, | 28 | {103, nullptr, "GetBaasUserAvailabilityChangeNotifier"}, |
| 29 | {104, nullptr, "GetProfileUpdateNotifier"}, | 29 | {104, nullptr, "GetProfileUpdateNotifier"}, |
| 30 | {105, nullptr, "CheckNetworkServiceAvailabilityAsync"}, // 4.0.0+ | 30 | {105, nullptr, "CheckNetworkServiceAvailabilityAsync"}, |
| 31 | {106, nullptr, "GetProfileSyncNotifier"}, // 9.0.0+ | 31 | {106, nullptr, "GetProfileSyncNotifier"}, |
| 32 | {110, &ACC_SU::StoreSaveDataThumbnailSystem, "StoreSaveDataThumbnail"}, | 32 | {110, &ACC_SU::StoreSaveDataThumbnailSystem, "StoreSaveDataThumbnail"}, |
| 33 | {111, nullptr, "ClearSaveDataThumbnail"}, | 33 | {111, nullptr, "ClearSaveDataThumbnail"}, |
| 34 | {112, nullptr, "LoadSaveDataThumbnail"}, | 34 | {112, nullptr, "LoadSaveDataThumbnail"}, |
| 35 | {113, nullptr, "GetSaveDataThumbnailExistence"}, // 5.0.0+ | 35 | {113, nullptr, "GetSaveDataThumbnailExistence"}, |
| 36 | {120, nullptr, "ListOpenUsersInApplication"}, // 10.0.0+ | 36 | {120, nullptr, "ListOpenUsersInApplication"}, |
| 37 | {130, nullptr, "ActivateOpenContextRetention"}, // 6.0.0+ | 37 | {130, nullptr, "ActivateOpenContextRetention"}, |
| 38 | {140, &ACC_SU::ListQualifiedUsers, "ListQualifiedUsers"}, // 6.0.0+ | 38 | {140, &ACC_SU::ListQualifiedUsers, "ListQualifiedUsers"}, |
| 39 | {150, nullptr, "AuthenticateApplicationAsync"}, // 10.0.0+ | 39 | {150, nullptr, "AuthenticateApplicationAsync"}, |
| 40 | {190, nullptr, "GetUserLastOpenedApplication"}, // 1.0.0 - 9.2.0 | 40 | {151, nullptr, "Unknown151"}, |
| 41 | {191, nullptr, "ActivateOpenContextHolder"}, // 7.0.0+ | 41 | {152, nullptr, "Unknown152"}, |
| 42 | {190, nullptr, "GetUserLastOpenedApplication"}, | ||
| 43 | {191, nullptr, "ActivateOpenContextHolder"}, | ||
| 42 | {200, nullptr, "BeginUserRegistration"}, | 44 | {200, nullptr, "BeginUserRegistration"}, |
| 43 | {201, nullptr, "CompleteUserRegistration"}, | 45 | {201, nullptr, "CompleteUserRegistration"}, |
| 44 | {202, nullptr, "CancelUserRegistration"}, | 46 | {202, nullptr, "CancelUserRegistration"}, |
| @@ -46,15 +48,15 @@ ACC_SU::ACC_SU(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> p | |||
| 46 | {204, nullptr, "SetUserPosition"}, | 48 | {204, nullptr, "SetUserPosition"}, |
| 47 | {205, &ACC_SU::GetProfileEditor, "GetProfileEditor"}, | 49 | {205, &ACC_SU::GetProfileEditor, "GetProfileEditor"}, |
| 48 | {206, nullptr, "CompleteUserRegistrationForcibly"}, | 50 | {206, nullptr, "CompleteUserRegistrationForcibly"}, |
| 49 | {210, nullptr, "CreateFloatingRegistrationRequest"}, // 3.0.0+ | 51 | {210, nullptr, "CreateFloatingRegistrationRequest"}, |
| 50 | {211, nullptr, "CreateProcedureToRegisterUserWithNintendoAccount"}, // 8.0.0+ | 52 | {211, nullptr, "CreateProcedureToRegisterUserWithNintendoAccount"}, |
| 51 | {212, nullptr, "ResumeProcedureToRegisterUserWithNintendoAccount"}, // 8.0.0+ | 53 | {212, nullptr, "ResumeProcedureToRegisterUserWithNintendoAccount"}, |
| 52 | {230, nullptr, "AuthenticateServiceAsync"}, | 54 | {230, nullptr, "AuthenticateServiceAsync"}, |
| 53 | {250, nullptr, "GetBaasAccountAdministrator"}, | 55 | {250, nullptr, "GetBaasAccountAdministrator"}, |
| 54 | {290, nullptr, "ProxyProcedureForGuestLoginWithNintendoAccount"}, | 56 | {290, nullptr, "ProxyProcedureForGuestLoginWithNintendoAccount"}, |
| 55 | {291, nullptr, "ProxyProcedureForFloatingRegistrationWithNintendoAccount"}, // 3.0.0+ | 57 | {291, nullptr, "ProxyProcedureForFloatingRegistrationWithNintendoAccount"}, |
| 56 | {299, nullptr, "SuspendBackgroundDaemon"}, | 58 | {299, nullptr, "SuspendBackgroundDaemon"}, |
| 57 | {997, nullptr, "DebugInvalidateTokenCacheForUser"}, // 3.0.0+ | 59 | {997, nullptr, "DebugInvalidateTokenCacheForUser"}, |
| 58 | {998, nullptr, "DebugSetUserStateClose"}, | 60 | {998, nullptr, "DebugSetUserStateClose"}, |
| 59 | {999, nullptr, "DebugSetUserStateOpen"}, | 61 | {999, nullptr, "DebugSetUserStateOpen"}, |
| 60 | }; | 62 | }; |
diff --git a/src/core/hle/service/acc/acc_u1.cpp b/src/core/hle/service/acc/acc_u1.cpp index 951081cd0..71982ad5a 100644 --- a/src/core/hle/service/acc/acc_u1.cpp +++ b/src/core/hle/service/acc/acc_u1.cpp | |||
| @@ -17,29 +17,31 @@ ACC_U1::ACC_U1(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> p | |||
| 17 | {3, &ACC_U1::ListOpenUsers, "ListOpenUsers"}, | 17 | {3, &ACC_U1::ListOpenUsers, "ListOpenUsers"}, |
| 18 | {4, &ACC_U1::GetLastOpenedUser, "GetLastOpenedUser"}, | 18 | {4, &ACC_U1::GetLastOpenedUser, "GetLastOpenedUser"}, |
| 19 | {5, &ACC_U1::GetProfile, "GetProfile"}, | 19 | {5, &ACC_U1::GetProfile, "GetProfile"}, |
| 20 | {6, nullptr, "GetProfileDigest"}, // 3.0.0+ | 20 | {6, nullptr, "GetProfileDigest"}, |
| 21 | {50, &ACC_U1::IsUserRegistrationRequestPermitted, "IsUserRegistrationRequestPermitted"}, | 21 | {50, &ACC_U1::IsUserRegistrationRequestPermitted, "IsUserRegistrationRequestPermitted"}, |
| 22 | {51, &ACC_U1::TrySelectUserWithoutInteraction, "TrySelectUserWithoutInteraction"}, | 22 | {51, &ACC_U1::TrySelectUserWithoutInteraction, "TrySelectUserWithoutInteraction"}, |
| 23 | {60, &ACC_U1::ListOpenContextStoredUsers, "ListOpenContextStoredUsers"}, // 5.0.0 - 5.1.0 | 23 | {60, &ACC_U1::ListOpenContextStoredUsers, "ListOpenContextStoredUsers"}, |
| 24 | {99, nullptr, "DebugActivateOpenContextRetention"}, // 6.0.0+ | 24 | {99, nullptr, "DebugActivateOpenContextRetention"}, |
| 25 | {100, nullptr, "GetUserRegistrationNotifier"}, | 25 | {100, nullptr, "GetUserRegistrationNotifier"}, |
| 26 | {101, nullptr, "GetUserStateChangeNotifier"}, | 26 | {101, nullptr, "GetUserStateChangeNotifier"}, |
| 27 | {102, nullptr, "GetBaasAccountManagerForSystemService"}, | 27 | {102, nullptr, "GetBaasAccountManagerForSystemService"}, |
| 28 | {103, nullptr, "GetBaasUserAvailabilityChangeNotifier"}, | 28 | {103, nullptr, "GetBaasUserAvailabilityChangeNotifier"}, |
| 29 | {104, nullptr, "GetProfileUpdateNotifier"}, | 29 | {104, nullptr, "GetProfileUpdateNotifier"}, |
| 30 | {105, nullptr, "CheckNetworkServiceAvailabilityAsync"}, // 4.0.0+ | 30 | {105, nullptr, "CheckNetworkServiceAvailabilityAsync"}, |
| 31 | {106, nullptr, "GetProfileSyncNotifier"}, // 9.0.0+ | 31 | {106, nullptr, "GetProfileSyncNotifier"}, |
| 32 | {110, &ACC_U1::StoreSaveDataThumbnailApplication, "StoreSaveDataThumbnail"}, | 32 | {110, &ACC_U1::StoreSaveDataThumbnailApplication, "StoreSaveDataThumbnail"}, |
| 33 | {111, nullptr, "ClearSaveDataThumbnail"}, | 33 | {111, nullptr, "ClearSaveDataThumbnail"}, |
| 34 | {112, nullptr, "LoadSaveDataThumbnail"}, | 34 | {112, nullptr, "LoadSaveDataThumbnail"}, |
| 35 | {113, nullptr, "GetSaveDataThumbnailExistence"}, // 5.0.0+ | 35 | {113, nullptr, "GetSaveDataThumbnailExistence"}, |
| 36 | {120, nullptr, "ListOpenUsersInApplication"}, // 10.0.0+ | 36 | {120, nullptr, "ListOpenUsersInApplication"}, |
| 37 | {130, nullptr, "ActivateOpenContextRetention"}, // 6.0.0+ | 37 | {130, nullptr, "ActivateOpenContextRetention"}, |
| 38 | {140, &ACC_U1::ListQualifiedUsers, "ListQualifiedUsers"}, // 6.0.0+ | 38 | {140, &ACC_U1::ListQualifiedUsers, "ListQualifiedUsers"}, |
| 39 | {150, nullptr, "AuthenticateApplicationAsync"}, // 10.0.0+ | 39 | {150, nullptr, "AuthenticateApplicationAsync"}, |
| 40 | {190, nullptr, "GetUserLastOpenedApplication"}, // 1.0.0 - 9.2.0 | 40 | {151, nullptr, "Unknown151"}, |
| 41 | {191, nullptr, "ActivateOpenContextHolder"}, // 7.0.0+ | 41 | {152, nullptr, "Unknown152"}, |
| 42 | {997, nullptr, "DebugInvalidateTokenCacheForUser"}, // 3.0.0+ | 42 | {190, nullptr, "GetUserLastOpenedApplication"}, |
| 43 | {191, nullptr, "ActivateOpenContextHolder"}, | ||
| 44 | {997, nullptr, "DebugInvalidateTokenCacheForUser"}, | ||
| 43 | {998, nullptr, "DebugSetUserStateClose"}, | 45 | {998, nullptr, "DebugSetUserStateClose"}, |
| 44 | {999, nullptr, "DebugSetUserStateOpen"}, | 46 | {999, nullptr, "DebugSetUserStateOpen"}, |
| 45 | }; | 47 | }; |
diff --git a/src/core/hle/service/acc/profile_manager.cpp b/src/core/hle/service/acc/profile_manager.cpp index 50b2c58e2..de83d82a4 100644 --- a/src/core/hle/service/acc/profile_manager.cpp +++ b/src/core/hle/service/acc/profile_manager.cpp | |||
| @@ -8,8 +8,8 @@ | |||
| 8 | #include <fmt/format.h> | 8 | #include <fmt/format.h> |
| 9 | 9 | ||
| 10 | #include "common/file_util.h" | 10 | #include "common/file_util.h" |
| 11 | #include "common/settings.h" | ||
| 11 | #include "core/hle/service/acc/profile_manager.h" | 12 | #include "core/hle/service/acc/profile_manager.h" |
| 12 | #include "core/settings.h" | ||
| 13 | 13 | ||
| 14 | namespace Service::Account { | 14 | namespace Service::Account { |
| 15 | 15 | ||
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 8e1fe9438..c59054468 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include <cinttypes> | 7 | #include <cinttypes> |
| 8 | #include <cstring> | 8 | #include <cstring> |
| 9 | #include "audio_core/audio_renderer.h" | 9 | #include "audio_core/audio_renderer.h" |
| 10 | #include "common/settings.h" | ||
| 10 | #include "core/core.h" | 11 | #include "core/core.h" |
| 11 | #include "core/file_sys/control_metadata.h" | 12 | #include "core/file_sys/control_metadata.h" |
| 12 | #include "core/file_sys/patch_manager.h" | 13 | #include "core/file_sys/patch_manager.h" |
| @@ -41,7 +42,6 @@ | |||
| 41 | #include "core/hle/service/set/set.h" | 42 | #include "core/hle/service/set/set.h" |
| 42 | #include "core/hle/service/sm/sm.h" | 43 | #include "core/hle/service/sm/sm.h" |
| 43 | #include "core/hle/service/vi/vi.h" | 44 | #include "core/hle/service/vi/vi.h" |
| 44 | #include "core/settings.h" | ||
| 45 | 45 | ||
| 46 | namespace Service::AM { | 46 | namespace Service::AM { |
| 47 | 47 | ||
| @@ -231,6 +231,7 @@ IDebugFunctions::IDebugFunctions(Core::System& system_) | |||
| 231 | {10, nullptr, "PerformSystemButtonPressing"}, | 231 | {10, nullptr, "PerformSystemButtonPressing"}, |
| 232 | {20, nullptr, "InvalidateTransitionLayer"}, | 232 | {20, nullptr, "InvalidateTransitionLayer"}, |
| 233 | {30, nullptr, "RequestLaunchApplicationWithUserAndArgumentForDebug"}, | 233 | {30, nullptr, "RequestLaunchApplicationWithUserAndArgumentForDebug"}, |
| 234 | {31, nullptr, "RequestLaunchApplicationByApplicationLaunchInfoForDebug"}, | ||
| 234 | {40, nullptr, "GetAppletResourceUsageInfo"}, | 235 | {40, nullptr, "GetAppletResourceUsageInfo"}, |
| 235 | {100, nullptr, "SetCpuBoostModeForApplet"}, | 236 | {100, nullptr, "SetCpuBoostModeForApplet"}, |
| 236 | {101, nullptr, "CancelCpuBoostModeForApplet"}, | 237 | {101, nullptr, "CancelCpuBoostModeForApplet"}, |
| @@ -242,6 +243,7 @@ IDebugFunctions::IDebugFunctions(Core::System& system_) | |||
| 242 | {130, nullptr, "FriendInvitationSetApplicationParameter"}, | 243 | {130, nullptr, "FriendInvitationSetApplicationParameter"}, |
| 243 | {131, nullptr, "FriendInvitationClearApplicationParameter"}, | 244 | {131, nullptr, "FriendInvitationClearApplicationParameter"}, |
| 244 | {132, nullptr, "FriendInvitationPushApplicationParameter"}, | 245 | {132, nullptr, "FriendInvitationPushApplicationParameter"}, |
| 246 | {900, nullptr, "GetGrcProcessLaunchedSystemEvent"}, | ||
| 245 | }; | 247 | }; |
| 246 | // clang-format on | 248 | // clang-format on |
| 247 | 249 | ||
| @@ -295,8 +297,9 @@ ISelfController::ISelfController(Core::System& system_, NVFlinger::NVFlinger& nv | |||
| 295 | {80, nullptr, "SetWirelessPriorityMode"}, | 297 | {80, nullptr, "SetWirelessPriorityMode"}, |
| 296 | {90, &ISelfController::GetAccumulatedSuspendedTickValue, "GetAccumulatedSuspendedTickValue"}, | 298 | {90, &ISelfController::GetAccumulatedSuspendedTickValue, "GetAccumulatedSuspendedTickValue"}, |
| 297 | {91, &ISelfController::GetAccumulatedSuspendedTickChangedEvent, "GetAccumulatedSuspendedTickChangedEvent"}, | 299 | {91, &ISelfController::GetAccumulatedSuspendedTickChangedEvent, "GetAccumulatedSuspendedTickChangedEvent"}, |
| 298 | {100, nullptr, "SetAlbumImageTakenNotificationEnabled"}, | 300 | {100, &ISelfController::SetAlbumImageTakenNotificationEnabled, "SetAlbumImageTakenNotificationEnabled"}, |
| 299 | {110, nullptr, "SetApplicationAlbumUserData"}, | 301 | {110, nullptr, "SetApplicationAlbumUserData"}, |
| 302 | {120, nullptr, "SaveCurrentScreenshot"}, | ||
| 300 | {1000, nullptr, "GetDebugStorageChannel"}, | 303 | {1000, nullptr, "GetDebugStorageChannel"}, |
| 301 | }; | 304 | }; |
| 302 | // clang-format on | 305 | // clang-format on |
| @@ -560,6 +563,21 @@ void ISelfController::GetAccumulatedSuspendedTickChangedEvent(Kernel::HLERequest | |||
| 560 | rb.PushCopyObjects(accumulated_suspended_tick_changed_event->GetReadableEvent()); | 563 | rb.PushCopyObjects(accumulated_suspended_tick_changed_event->GetReadableEvent()); |
| 561 | } | 564 | } |
| 562 | 565 | ||
| 566 | void ISelfController::SetAlbumImageTakenNotificationEnabled(Kernel::HLERequestContext& ctx) { | ||
| 567 | IPC::RequestParser rp{ctx}; | ||
| 568 | |||
| 569 | // This service call sets an internal flag whether a notification is shown when an image is | ||
| 570 | // captured. Currently we do not support capturing images via the capture button, so this can be | ||
| 571 | // stubbed for now. | ||
| 572 | const bool album_image_taken_notification_enabled = rp.Pop<bool>(); | ||
| 573 | |||
| 574 | LOG_WARNING(Service_AM, "(STUBBED) called. album_image_taken_notification_enabled={}", | ||
| 575 | album_image_taken_notification_enabled); | ||
| 576 | |||
| 577 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 578 | rb.Push(RESULT_SUCCESS); | ||
| 579 | } | ||
| 580 | |||
| 563 | AppletMessageQueue::AppletMessageQueue(Kernel::KernelCore& kernel) { | 581 | AppletMessageQueue::AppletMessageQueue(Kernel::KernelCore& kernel) { |
| 564 | on_new_message = Kernel::KEvent::Create(kernel, "AMMessageQueue:OnMessageReceived"); | 582 | on_new_message = Kernel::KEvent::Create(kernel, "AMMessageQueue:OnMessageReceived"); |
| 565 | on_new_message->Initialize(); | 583 | on_new_message->Initialize(); |
| @@ -630,6 +648,7 @@ ICommonStateGetter::ICommonStateGetter(Core::System& system_, | |||
| 630 | {11, nullptr, "ReleaseSleepLock"}, | 648 | {11, nullptr, "ReleaseSleepLock"}, |
| 631 | {12, nullptr, "ReleaseSleepLockTransiently"}, | 649 | {12, nullptr, "ReleaseSleepLockTransiently"}, |
| 632 | {13, nullptr, "GetAcquiredSleepLockEvent"}, | 650 | {13, nullptr, "GetAcquiredSleepLockEvent"}, |
| 651 | {14, nullptr, "GetWakeupCount"}, | ||
| 633 | {20, nullptr, "PushToGeneralChannel"}, | 652 | {20, nullptr, "PushToGeneralChannel"}, |
| 634 | {30, nullptr, "GetHomeButtonReaderLockAccessor"}, | 653 | {30, nullptr, "GetHomeButtonReaderLockAccessor"}, |
| 635 | {31, nullptr, "GetReaderLockAccessorEx"}, | 654 | {31, nullptr, "GetReaderLockAccessorEx"}, |
| @@ -641,6 +660,7 @@ ICommonStateGetter::ICommonStateGetter(Core::System& system_, | |||
| 641 | {53, &ICommonStateGetter::BeginVrModeEx, "BeginVrModeEx"}, | 660 | {53, &ICommonStateGetter::BeginVrModeEx, "BeginVrModeEx"}, |
| 642 | {54, &ICommonStateGetter::EndVrModeEx, "EndVrModeEx"}, | 661 | {54, &ICommonStateGetter::EndVrModeEx, "EndVrModeEx"}, |
| 643 | {55, nullptr, "IsInControllerFirmwareUpdateSection"}, | 662 | {55, nullptr, "IsInControllerFirmwareUpdateSection"}, |
| 663 | {59, nullptr, "SetVrPositionForDebug"}, | ||
| 644 | {60, &ICommonStateGetter::GetDefaultDisplayResolution, "GetDefaultDisplayResolution"}, | 664 | {60, &ICommonStateGetter::GetDefaultDisplayResolution, "GetDefaultDisplayResolution"}, |
| 645 | {61, &ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent, "GetDefaultDisplayResolutionChangeEvent"}, | 665 | {61, &ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent, "GetDefaultDisplayResolutionChangeEvent"}, |
| 646 | {62, nullptr, "GetHdcpAuthenticationState"}, | 666 | {62, nullptr, "GetHdcpAuthenticationState"}, |
| @@ -649,14 +669,21 @@ ICommonStateGetter::ICommonStateGetter(Core::System& system_, | |||
| 649 | {65, nullptr, "GetApplicationIdByContentActionName"}, | 669 | {65, nullptr, "GetApplicationIdByContentActionName"}, |
| 650 | {66, &ICommonStateGetter::SetCpuBoostMode, "SetCpuBoostMode"}, | 670 | {66, &ICommonStateGetter::SetCpuBoostMode, "SetCpuBoostMode"}, |
| 651 | {67, nullptr, "CancelCpuBoostMode"}, | 671 | {67, nullptr, "CancelCpuBoostMode"}, |
| 672 | {68, nullptr, "GetBuiltInDisplayType"}, | ||
| 652 | {80, nullptr, "PerformSystemButtonPressingIfInFocus"}, | 673 | {80, nullptr, "PerformSystemButtonPressingIfInFocus"}, |
| 653 | {90, nullptr, "SetPerformanceConfigurationChangedNotification"}, | 674 | {90, nullptr, "SetPerformanceConfigurationChangedNotification"}, |
| 654 | {91, nullptr, "GetCurrentPerformanceConfiguration"}, | 675 | {91, nullptr, "GetCurrentPerformanceConfiguration"}, |
| 655 | {100, nullptr, "SetHandlingHomeButtonShortPressedEnabled"}, | 676 | {100, nullptr, "SetHandlingHomeButtonShortPressedEnabled"}, |
| 677 | {110, nullptr, "OpenMyGpuErrorHandler"}, | ||
| 656 | {200, nullptr, "GetOperationModeSystemInfo"}, | 678 | {200, nullptr, "GetOperationModeSystemInfo"}, |
| 657 | {300, nullptr, "GetSettingsPlatformRegion"}, | 679 | {300, nullptr, "GetSettingsPlatformRegion"}, |
| 658 | {400, nullptr, "ActivateMigrationService"}, | 680 | {400, nullptr, "ActivateMigrationService"}, |
| 659 | {401, nullptr, "DeactivateMigrationService"}, | 681 | {401, nullptr, "DeactivateMigrationService"}, |
| 682 | {500, nullptr, "DisableSleepTillShutdown"}, | ||
| 683 | {501, nullptr, "SuppressDisablingSleepTemporarily"}, | ||
| 684 | {502, nullptr, "IsSleepEnabled"}, | ||
| 685 | {503, nullptr, "IsDisablingSleepSuppressed"}, | ||
| 686 | {900, nullptr, "SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled"}, | ||
| 660 | }; | 687 | }; |
| 661 | // clang-format on | 688 | // clang-format on |
| 662 | 689 | ||
| @@ -944,7 +971,7 @@ private: | |||
| 944 | 971 | ||
| 945 | auto storage = applet->GetBroker().PopNormalDataToGame(); | 972 | auto storage = applet->GetBroker().PopNormalDataToGame(); |
| 946 | if (storage == nullptr) { | 973 | if (storage == nullptr) { |
| 947 | LOG_ERROR(Service_AM, | 974 | LOG_DEBUG(Service_AM, |
| 948 | "storage is a nullptr. There is no data in the current normal channel"); | 975 | "storage is a nullptr. There is no data in the current normal channel"); |
| 949 | IPC::ResponseBuilder rb{ctx, 2}; | 976 | IPC::ResponseBuilder rb{ctx, 2}; |
| 950 | rb.Push(ERR_NO_DATA_IN_CHANNEL); | 977 | rb.Push(ERR_NO_DATA_IN_CHANNEL); |
| @@ -975,7 +1002,7 @@ private: | |||
| 975 | 1002 | ||
| 976 | auto storage = applet->GetBroker().PopInteractiveDataToGame(); | 1003 | auto storage = applet->GetBroker().PopInteractiveDataToGame(); |
| 977 | if (storage == nullptr) { | 1004 | if (storage == nullptr) { |
| 978 | LOG_ERROR(Service_AM, | 1005 | LOG_DEBUG(Service_AM, |
| 979 | "storage is a nullptr. There is no data in the current interactive channel"); | 1006 | "storage is a nullptr. There is no data in the current interactive channel"); |
| 980 | IPC::ResponseBuilder rb{ctx, 2}; | 1007 | IPC::ResponseBuilder rb{ctx, 2}; |
| 981 | rb.Push(ERR_NO_DATA_IN_CHANNEL); | 1008 | rb.Push(ERR_NO_DATA_IN_CHANNEL); |
| @@ -1098,7 +1125,7 @@ ILibraryAppletCreator::ILibraryAppletCreator(Core::System& system_) | |||
| 1098 | {2, nullptr, "AreAnyLibraryAppletsLeft"}, | 1125 | {2, nullptr, "AreAnyLibraryAppletsLeft"}, |
| 1099 | {10, &ILibraryAppletCreator::CreateStorage, "CreateStorage"}, | 1126 | {10, &ILibraryAppletCreator::CreateStorage, "CreateStorage"}, |
| 1100 | {11, &ILibraryAppletCreator::CreateTransferMemoryStorage, "CreateTransferMemoryStorage"}, | 1127 | {11, &ILibraryAppletCreator::CreateTransferMemoryStorage, "CreateTransferMemoryStorage"}, |
| 1101 | {12, nullptr, "CreateHandleStorage"}, | 1128 | {12, &ILibraryAppletCreator::CreateHandleStorage, "CreateHandleStorage"}, |
| 1102 | }; | 1129 | }; |
| 1103 | RegisterHandlers(functions); | 1130 | RegisterHandlers(functions); |
| 1104 | } | 1131 | } |
| @@ -1107,14 +1134,15 @@ ILibraryAppletCreator::~ILibraryAppletCreator() = default; | |||
| 1107 | 1134 | ||
| 1108 | void ILibraryAppletCreator::CreateLibraryApplet(Kernel::HLERequestContext& ctx) { | 1135 | void ILibraryAppletCreator::CreateLibraryApplet(Kernel::HLERequestContext& ctx) { |
| 1109 | IPC::RequestParser rp{ctx}; | 1136 | IPC::RequestParser rp{ctx}; |
| 1137 | |||
| 1110 | const auto applet_id = rp.PopRaw<Applets::AppletId>(); | 1138 | const auto applet_id = rp.PopRaw<Applets::AppletId>(); |
| 1111 | const auto applet_mode = rp.PopRaw<u32>(); | 1139 | const auto applet_mode = rp.PopRaw<Applets::LibraryAppletMode>(); |
| 1112 | 1140 | ||
| 1113 | LOG_DEBUG(Service_AM, "called with applet_id={:08X}, applet_mode={:08X}", applet_id, | 1141 | LOG_DEBUG(Service_AM, "called with applet_id={:08X}, applet_mode={:08X}", applet_id, |
| 1114 | applet_mode); | 1142 | applet_mode); |
| 1115 | 1143 | ||
| 1116 | const auto& applet_manager{system.GetAppletManager()}; | 1144 | const auto& applet_manager{system.GetAppletManager()}; |
| 1117 | const auto applet = applet_manager.GetApplet(applet_id); | 1145 | const auto applet = applet_manager.GetApplet(applet_id, applet_mode); |
| 1118 | 1146 | ||
| 1119 | if (applet == nullptr) { | 1147 | if (applet == nullptr) { |
| 1120 | LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", applet_id); | 1148 | LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", applet_id); |
| @@ -1132,9 +1160,18 @@ void ILibraryAppletCreator::CreateLibraryApplet(Kernel::HLERequestContext& ctx) | |||
| 1132 | 1160 | ||
| 1133 | void ILibraryAppletCreator::CreateStorage(Kernel::HLERequestContext& ctx) { | 1161 | void ILibraryAppletCreator::CreateStorage(Kernel::HLERequestContext& ctx) { |
| 1134 | IPC::RequestParser rp{ctx}; | 1162 | IPC::RequestParser rp{ctx}; |
| 1135 | const u64 size{rp.Pop<u64>()}; | 1163 | |
| 1164 | const s64 size{rp.Pop<s64>()}; | ||
| 1165 | |||
| 1136 | LOG_DEBUG(Service_AM, "called, size={}", size); | 1166 | LOG_DEBUG(Service_AM, "called, size={}", size); |
| 1137 | 1167 | ||
| 1168 | if (size <= 0) { | ||
| 1169 | LOG_ERROR(Service_AM, "size is less than or equal to 0"); | ||
| 1170 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1171 | rb.Push(RESULT_UNKNOWN); | ||
| 1172 | return; | ||
| 1173 | } | ||
| 1174 | |||
| 1138 | std::vector<u8> buffer(size); | 1175 | std::vector<u8> buffer(size); |
| 1139 | 1176 | ||
| 1140 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 1177 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| @@ -1143,18 +1180,65 @@ void ILibraryAppletCreator::CreateStorage(Kernel::HLERequestContext& ctx) { | |||
| 1143 | } | 1180 | } |
| 1144 | 1181 | ||
| 1145 | void ILibraryAppletCreator::CreateTransferMemoryStorage(Kernel::HLERequestContext& ctx) { | 1182 | void ILibraryAppletCreator::CreateTransferMemoryStorage(Kernel::HLERequestContext& ctx) { |
| 1146 | LOG_DEBUG(Service_AM, "called"); | 1183 | IPC::RequestParser rp{ctx}; |
| 1184 | |||
| 1185 | struct Parameters { | ||
| 1186 | u8 permissions; | ||
| 1187 | s64 size; | ||
| 1188 | }; | ||
| 1189 | |||
| 1190 | const auto parameters{rp.PopRaw<Parameters>()}; | ||
| 1191 | const auto handle{ctx.GetCopyHandle(0)}; | ||
| 1192 | |||
| 1193 | LOG_DEBUG(Service_AM, "called, permissions={}, size={}, handle={:08X}", parameters.permissions, | ||
| 1194 | parameters.size, handle); | ||
| 1195 | |||
| 1196 | if (parameters.size <= 0) { | ||
| 1197 | LOG_ERROR(Service_AM, "size is less than or equal to 0"); | ||
| 1198 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1199 | rb.Push(RESULT_UNKNOWN); | ||
| 1200 | return; | ||
| 1201 | } | ||
| 1202 | |||
| 1203 | auto transfer_mem = | ||
| 1204 | system.CurrentProcess()->GetHandleTable().Get<Kernel::TransferMemory>(handle); | ||
| 1205 | |||
| 1206 | if (transfer_mem == nullptr) { | ||
| 1207 | LOG_ERROR(Service_AM, "transfer_mem is a nullptr for handle={:08X}", handle); | ||
| 1208 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1209 | rb.Push(RESULT_UNKNOWN); | ||
| 1210 | return; | ||
| 1211 | } | ||
| 1212 | |||
| 1213 | const u8* const mem_begin = transfer_mem->GetPointer(); | ||
| 1214 | const u8* const mem_end = mem_begin + transfer_mem->GetSize(); | ||
| 1215 | std::vector<u8> memory{mem_begin, mem_end}; | ||
| 1216 | |||
| 1217 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 1218 | rb.Push(RESULT_SUCCESS); | ||
| 1219 | rb.PushIpcInterface<IStorage>(system, std::move(memory)); | ||
| 1220 | } | ||
| 1147 | 1221 | ||
| 1222 | void ILibraryAppletCreator::CreateHandleStorage(Kernel::HLERequestContext& ctx) { | ||
| 1148 | IPC::RequestParser rp{ctx}; | 1223 | IPC::RequestParser rp{ctx}; |
| 1149 | 1224 | ||
| 1150 | rp.SetCurrentOffset(3); | 1225 | const s64 size{rp.Pop<s64>()}; |
| 1151 | const auto handle{rp.Pop<Kernel::Handle>()}; | 1226 | const auto handle{ctx.GetCopyHandle(0)}; |
| 1227 | |||
| 1228 | LOG_DEBUG(Service_AM, "called, size={}, handle={:08X}", size, handle); | ||
| 1229 | |||
| 1230 | if (size <= 0) { | ||
| 1231 | LOG_ERROR(Service_AM, "size is less than or equal to 0"); | ||
| 1232 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1233 | rb.Push(RESULT_UNKNOWN); | ||
| 1234 | return; | ||
| 1235 | } | ||
| 1152 | 1236 | ||
| 1153 | auto transfer_mem = | 1237 | auto transfer_mem = |
| 1154 | system.CurrentProcess()->GetHandleTable().Get<Kernel::TransferMemory>(handle); | 1238 | system.CurrentProcess()->GetHandleTable().Get<Kernel::TransferMemory>(handle); |
| 1155 | 1239 | ||
| 1156 | if (transfer_mem == nullptr) { | 1240 | if (transfer_mem == nullptr) { |
| 1157 | LOG_ERROR(Service_AM, "shared_mem is a nullpr for handle={:08X}", handle); | 1241 | LOG_ERROR(Service_AM, "transfer_mem is a nullptr for handle={:08X}", handle); |
| 1158 | IPC::ResponseBuilder rb{ctx, 2}; | 1242 | IPC::ResponseBuilder rb{ctx, 2}; |
| 1159 | rb.Push(RESULT_UNKNOWN); | 1243 | rb.Push(RESULT_UNKNOWN); |
| 1160 | return; | 1244 | return; |
| @@ -1188,11 +1272,14 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_) | |||
| 1188 | {25, &IApplicationFunctions::ExtendSaveData, "ExtendSaveData"}, | 1272 | {25, &IApplicationFunctions::ExtendSaveData, "ExtendSaveData"}, |
| 1189 | {26, &IApplicationFunctions::GetSaveDataSize, "GetSaveDataSize"}, | 1273 | {26, &IApplicationFunctions::GetSaveDataSize, "GetSaveDataSize"}, |
| 1190 | {27, nullptr, "CreateCacheStorage"}, | 1274 | {27, nullptr, "CreateCacheStorage"}, |
| 1275 | {28, nullptr, "GetSaveDataSizeMax"}, | ||
| 1276 | {29, nullptr, "GetCacheStorageMax"}, | ||
| 1191 | {30, &IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed, "BeginBlockingHomeButtonShortAndLongPressed"}, | 1277 | {30, &IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed, "BeginBlockingHomeButtonShortAndLongPressed"}, |
| 1192 | {31, &IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed, "EndBlockingHomeButtonShortAndLongPressed"}, | 1278 | {31, &IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed, "EndBlockingHomeButtonShortAndLongPressed"}, |
| 1193 | {32, &IApplicationFunctions::BeginBlockingHomeButton, "BeginBlockingHomeButton"}, | 1279 | {32, &IApplicationFunctions::BeginBlockingHomeButton, "BeginBlockingHomeButton"}, |
| 1194 | {33, &IApplicationFunctions::EndBlockingHomeButton, "EndBlockingHomeButton"}, | 1280 | {33, &IApplicationFunctions::EndBlockingHomeButton, "EndBlockingHomeButton"}, |
| 1195 | {34, nullptr, "SelectApplicationLicense"}, | 1281 | {34, nullptr, "SelectApplicationLicense"}, |
| 1282 | {35, nullptr, "GetDeviceSaveDataSizeMax"}, | ||
| 1196 | {40, &IApplicationFunctions::NotifyRunning, "NotifyRunning"}, | 1283 | {40, &IApplicationFunctions::NotifyRunning, "NotifyRunning"}, |
| 1197 | {50, &IApplicationFunctions::GetPseudoDeviceId, "GetPseudoDeviceId"}, | 1284 | {50, &IApplicationFunctions::GetPseudoDeviceId, "GetPseudoDeviceId"}, |
| 1198 | {60, nullptr, "SetMediaPlaybackStateForApplication"}, | 1285 | {60, nullptr, "SetMediaPlaybackStateForApplication"}, |
| @@ -1216,6 +1303,7 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_) | |||
| 1216 | {123, &IApplicationFunctions::GetPreviousProgramIndex, "GetPreviousProgramIndex"}, | 1303 | {123, &IApplicationFunctions::GetPreviousProgramIndex, "GetPreviousProgramIndex"}, |
| 1217 | {124, nullptr, "EnableApplicationAllThreadDumpOnCrash"}, | 1304 | {124, nullptr, "EnableApplicationAllThreadDumpOnCrash"}, |
| 1218 | {130, &IApplicationFunctions::GetGpuErrorDetectedSystemEvent, "GetGpuErrorDetectedSystemEvent"}, | 1305 | {130, &IApplicationFunctions::GetGpuErrorDetectedSystemEvent, "GetGpuErrorDetectedSystemEvent"}, |
| 1306 | {131, nullptr, "SetDelayTimeToAbortOnGpuError"}, | ||
| 1219 | {140, &IApplicationFunctions::GetFriendInvitationStorageChannelEvent, "GetFriendInvitationStorageChannelEvent"}, | 1307 | {140, &IApplicationFunctions::GetFriendInvitationStorageChannelEvent, "GetFriendInvitationStorageChannelEvent"}, |
| 1220 | {141, &IApplicationFunctions::TryPopFromFriendInvitationStorageChannel, "TryPopFromFriendInvitationStorageChannel"}, | 1308 | {141, &IApplicationFunctions::TryPopFromFriendInvitationStorageChannel, "TryPopFromFriendInvitationStorageChannel"}, |
| 1221 | {150, nullptr, "GetNotificationStorageChannelEvent"}, | 1309 | {150, nullptr, "GetNotificationStorageChannelEvent"}, |
| @@ -1224,6 +1312,8 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_) | |||
| 1224 | {170, nullptr, "SetHdcpAuthenticationActivated"}, | 1312 | {170, nullptr, "SetHdcpAuthenticationActivated"}, |
| 1225 | {180, nullptr, "GetLaunchRequiredVersion"}, | 1313 | {180, nullptr, "GetLaunchRequiredVersion"}, |
| 1226 | {181, nullptr, "UpgradeLaunchRequiredVersion"}, | 1314 | {181, nullptr, "UpgradeLaunchRequiredVersion"}, |
| 1315 | {190, nullptr, "SendServerMaintenanceOverlayNotification"}, | ||
| 1316 | {200, nullptr, "GetLastApplicationExitReason"}, | ||
| 1227 | {500, nullptr, "StartContinuousRecordingFlushForDebug"}, | 1317 | {500, nullptr, "StartContinuousRecordingFlushForDebug"}, |
| 1228 | {1000, nullptr, "CreateMovieMaker"}, | 1318 | {1000, nullptr, "CreateMovieMaker"}, |
| 1229 | {1001, nullptr, "PrepareForJit"}, | 1319 | {1001, nullptr, "PrepareForJit"}, |
| @@ -1690,9 +1780,12 @@ IHomeMenuFunctions::IHomeMenuFunctions(Core::System& system_) | |||
| 1690 | {21, &IHomeMenuFunctions::GetPopFromGeneralChannelEvent, "GetPopFromGeneralChannelEvent"}, | 1780 | {21, &IHomeMenuFunctions::GetPopFromGeneralChannelEvent, "GetPopFromGeneralChannelEvent"}, |
| 1691 | {30, nullptr, "GetHomeButtonWriterLockAccessor"}, | 1781 | {30, nullptr, "GetHomeButtonWriterLockAccessor"}, |
| 1692 | {31, nullptr, "GetWriterLockAccessorEx"}, | 1782 | {31, nullptr, "GetWriterLockAccessorEx"}, |
| 1783 | {40, nullptr, "IsSleepEnabled"}, | ||
| 1784 | {41, nullptr, "IsRebootEnabled"}, | ||
| 1693 | {100, nullptr, "PopRequestLaunchApplicationForDebug"}, | 1785 | {100, nullptr, "PopRequestLaunchApplicationForDebug"}, |
| 1694 | {110, nullptr, "IsForceTerminateApplicationDisabledForDebug"}, | 1786 | {110, nullptr, "IsForceTerminateApplicationDisabledForDebug"}, |
| 1695 | {200, nullptr, "LaunchDevMenu"}, | 1787 | {200, nullptr, "LaunchDevMenu"}, |
| 1788 | {1000, nullptr, "SetLastApplicationExitReason"}, | ||
| 1696 | }; | 1789 | }; |
| 1697 | // clang-format on | 1790 | // clang-format on |
| 1698 | 1791 | ||
| @@ -1736,6 +1829,7 @@ IGlobalStateController::IGlobalStateController(Core::System& system_) | |||
| 1736 | {13, nullptr, "UpdateDefaultDisplayResolution"}, | 1829 | {13, nullptr, "UpdateDefaultDisplayResolution"}, |
| 1737 | {14, nullptr, "ShouldSleepOnBoot"}, | 1830 | {14, nullptr, "ShouldSleepOnBoot"}, |
| 1738 | {15, nullptr, "GetHdcpAuthenticationFailedEvent"}, | 1831 | {15, nullptr, "GetHdcpAuthenticationFailedEvent"}, |
| 1832 | {30, nullptr, "OpenCradleFirmwareUpdater"}, | ||
| 1739 | }; | 1833 | }; |
| 1740 | // clang-format on | 1834 | // clang-format on |
| 1741 | 1835 | ||
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h index 6911f0d6e..aefbdf0d5 100644 --- a/src/core/hle/service/am/am.h +++ b/src/core/hle/service/am/am.h | |||
| @@ -146,6 +146,7 @@ private: | |||
| 146 | void IsAutoSleepDisabled(Kernel::HLERequestContext& ctx); | 146 | void IsAutoSleepDisabled(Kernel::HLERequestContext& ctx); |
| 147 | void GetAccumulatedSuspendedTickValue(Kernel::HLERequestContext& ctx); | 147 | void GetAccumulatedSuspendedTickValue(Kernel::HLERequestContext& ctx); |
| 148 | void GetAccumulatedSuspendedTickChangedEvent(Kernel::HLERequestContext& ctx); | 148 | void GetAccumulatedSuspendedTickChangedEvent(Kernel::HLERequestContext& ctx); |
| 149 | void SetAlbumImageTakenNotificationEnabled(Kernel::HLERequestContext& ctx); | ||
| 149 | 150 | ||
| 150 | enum class ScreenshotPermission : u32 { | 151 | enum class ScreenshotPermission : u32 { |
| 151 | Inherit = 0, | 152 | Inherit = 0, |
| @@ -253,6 +254,7 @@ private: | |||
| 253 | void CreateLibraryApplet(Kernel::HLERequestContext& ctx); | 254 | void CreateLibraryApplet(Kernel::HLERequestContext& ctx); |
| 254 | void CreateStorage(Kernel::HLERequestContext& ctx); | 255 | void CreateStorage(Kernel::HLERequestContext& ctx); |
| 255 | void CreateTransferMemoryStorage(Kernel::HLERequestContext& ctx); | 256 | void CreateTransferMemoryStorage(Kernel::HLERequestContext& ctx); |
| 257 | void CreateHandleStorage(Kernel::HLERequestContext& ctx); | ||
| 256 | }; | 258 | }; |
| 257 | 259 | ||
| 258 | class IApplicationFunctions final : public ServiceFramework<IApplicationFunctions> { | 260 | class IApplicationFunctions final : public ServiceFramework<IApplicationFunctions> { |
diff --git a/src/core/hle/service/am/applets/applets.cpp b/src/core/hle/service/am/applets/applets.cpp index e2f3b7563..5ddad851a 100644 --- a/src/core/hle/service/am/applets/applets.cpp +++ b/src/core/hle/service/am/applets/applets.cpp | |||
| @@ -241,31 +241,31 @@ void AppletManager::ClearAll() { | |||
| 241 | frontend = {}; | 241 | frontend = {}; |
| 242 | } | 242 | } |
| 243 | 243 | ||
| 244 | std::shared_ptr<Applet> AppletManager::GetApplet(AppletId id) const { | 244 | std::shared_ptr<Applet> AppletManager::GetApplet(AppletId id, LibraryAppletMode mode) const { |
| 245 | switch (id) { | 245 | switch (id) { |
| 246 | case AppletId::Auth: | 246 | case AppletId::Auth: |
| 247 | return std::make_shared<Auth>(system, *frontend.parental_controls); | 247 | return std::make_shared<Auth>(system, mode, *frontend.parental_controls); |
| 248 | case AppletId::Controller: | 248 | case AppletId::Controller: |
| 249 | return std::make_shared<Controller>(system, *frontend.controller); | 249 | return std::make_shared<Controller>(system, mode, *frontend.controller); |
| 250 | case AppletId::Error: | 250 | case AppletId::Error: |
| 251 | return std::make_shared<Error>(system, *frontend.error); | 251 | return std::make_shared<Error>(system, mode, *frontend.error); |
| 252 | case AppletId::ProfileSelect: | 252 | case AppletId::ProfileSelect: |
| 253 | return std::make_shared<ProfileSelect>(system, *frontend.profile_select); | 253 | return std::make_shared<ProfileSelect>(system, mode, *frontend.profile_select); |
| 254 | case AppletId::SoftwareKeyboard: | 254 | case AppletId::SoftwareKeyboard: |
| 255 | return std::make_shared<SoftwareKeyboard>(system, *frontend.software_keyboard); | 255 | return std::make_shared<SoftwareKeyboard>(system, mode, *frontend.software_keyboard); |
| 256 | case AppletId::Web: | 256 | case AppletId::Web: |
| 257 | case AppletId::Shop: | 257 | case AppletId::Shop: |
| 258 | case AppletId::OfflineWeb: | 258 | case AppletId::OfflineWeb: |
| 259 | case AppletId::LoginShare: | 259 | case AppletId::LoginShare: |
| 260 | case AppletId::WebAuth: | 260 | case AppletId::WebAuth: |
| 261 | return std::make_shared<WebBrowser>(system, *frontend.web_browser); | 261 | return std::make_shared<WebBrowser>(system, mode, *frontend.web_browser); |
| 262 | case AppletId::PhotoViewer: | 262 | case AppletId::PhotoViewer: |
| 263 | return std::make_shared<PhotoViewer>(system, *frontend.photo_viewer); | 263 | return std::make_shared<PhotoViewer>(system, mode, *frontend.photo_viewer); |
| 264 | default: | 264 | default: |
| 265 | UNIMPLEMENTED_MSG( | 265 | UNIMPLEMENTED_MSG( |
| 266 | "No backend implementation exists for applet_id={:02X}! Falling back to stub applet.", | 266 | "No backend implementation exists for applet_id={:02X}! Falling back to stub applet.", |
| 267 | static_cast<u8>(id)); | 267 | static_cast<u8>(id)); |
| 268 | return std::make_shared<StubApplet>(system, id); | 268 | return std::make_shared<StubApplet>(system, id, mode); |
| 269 | } | 269 | } |
| 270 | } | 270 | } |
| 271 | 271 | ||
diff --git a/src/core/hle/service/am/applets/applets.h b/src/core/hle/service/am/applets/applets.h index b9a006317..26b482015 100644 --- a/src/core/hle/service/am/applets/applets.h +++ b/src/core/hle/service/am/applets/applets.h | |||
| @@ -62,6 +62,14 @@ enum class AppletId : u32 { | |||
| 62 | MyPage = 0x1A, | 62 | MyPage = 0x1A, |
| 63 | }; | 63 | }; |
| 64 | 64 | ||
| 65 | enum class LibraryAppletMode : u32 { | ||
| 66 | AllForeground = 0, | ||
| 67 | Background = 1, | ||
| 68 | NoUI = 2, | ||
| 69 | BackgroundIndirectDisplay = 3, | ||
| 70 | AllForegroundInitiallyHidden = 4, | ||
| 71 | }; | ||
| 72 | |||
| 65 | class AppletDataBroker final { | 73 | class AppletDataBroker final { |
| 66 | public: | 74 | public: |
| 67 | explicit AppletDataBroker(Kernel::KernelCore& kernel_); | 75 | explicit AppletDataBroker(Kernel::KernelCore& kernel_); |
| @@ -200,7 +208,7 @@ public: | |||
| 200 | void SetDefaultAppletsIfMissing(); | 208 | void SetDefaultAppletsIfMissing(); |
| 201 | void ClearAll(); | 209 | void ClearAll(); |
| 202 | 210 | ||
| 203 | std::shared_ptr<Applet> GetApplet(AppletId id) const; | 211 | std::shared_ptr<Applet> GetApplet(AppletId id, LibraryAppletMode mode) const; |
| 204 | 212 | ||
| 205 | private: | 213 | private: |
| 206 | AppletFrontendSet frontend; | 214 | AppletFrontendSet frontend; |
diff --git a/src/core/hle/service/am/applets/controller.cpp b/src/core/hle/service/am/applets/controller.cpp index c2bfe698f..a33f05f97 100644 --- a/src/core/hle/service/am/applets/controller.cpp +++ b/src/core/hle/service/am/applets/controller.cpp | |||
| @@ -45,8 +45,9 @@ static Core::Frontend::ControllerParameters ConvertToFrontendParameters( | |||
| 45 | }; | 45 | }; |
| 46 | } | 46 | } |
| 47 | 47 | ||
| 48 | Controller::Controller(Core::System& system_, const Core::Frontend::ControllerApplet& frontend_) | 48 | Controller::Controller(Core::System& system_, LibraryAppletMode applet_mode_, |
| 49 | : Applet{system_.Kernel()}, frontend{frontend_}, system{system_} {} | 49 | const Core::Frontend::ControllerApplet& frontend_) |
| 50 | : Applet{system_.Kernel()}, applet_mode{applet_mode_}, frontend{frontend_}, system{system_} {} | ||
| 50 | 51 | ||
| 51 | Controller::~Controller() = default; | 52 | Controller::~Controller() = default; |
| 52 | 53 | ||
diff --git a/src/core/hle/service/am/applets/controller.h b/src/core/hle/service/am/applets/controller.h index d4c9da7b1..07cb92bf9 100644 --- a/src/core/hle/service/am/applets/controller.h +++ b/src/core/hle/service/am/applets/controller.h | |||
| @@ -106,7 +106,8 @@ static_assert(sizeof(ControllerSupportResultInfo) == 0xC, | |||
| 106 | 106 | ||
| 107 | class Controller final : public Applet { | 107 | class Controller final : public Applet { |
| 108 | public: | 108 | public: |
| 109 | explicit Controller(Core::System& system_, const Core::Frontend::ControllerApplet& frontend_); | 109 | explicit Controller(Core::System& system_, LibraryAppletMode applet_mode_, |
| 110 | const Core::Frontend::ControllerApplet& frontend_); | ||
| 110 | ~Controller() override; | 111 | ~Controller() override; |
| 111 | 112 | ||
| 112 | void Initialize() override; | 113 | void Initialize() override; |
| @@ -119,6 +120,7 @@ public: | |||
| 119 | void ConfigurationComplete(); | 120 | void ConfigurationComplete(); |
| 120 | 121 | ||
| 121 | private: | 122 | private: |
| 123 | LibraryAppletMode applet_mode; | ||
| 122 | const Core::Frontend::ControllerApplet& frontend; | 124 | const Core::Frontend::ControllerApplet& frontend; |
| 123 | Core::System& system; | 125 | Core::System& system; |
| 124 | 126 | ||
diff --git a/src/core/hle/service/am/applets/error.cpp b/src/core/hle/service/am/applets/error.cpp index 0c8b632e8..a9f0a9c95 100644 --- a/src/core/hle/service/am/applets/error.cpp +++ b/src/core/hle/service/am/applets/error.cpp | |||
| @@ -86,8 +86,9 @@ ResultCode Decode64BitError(u64 error) { | |||
| 86 | 86 | ||
| 87 | } // Anonymous namespace | 87 | } // Anonymous namespace |
| 88 | 88 | ||
| 89 | Error::Error(Core::System& system_, const Core::Frontend::ErrorApplet& frontend_) | 89 | Error::Error(Core::System& system_, LibraryAppletMode applet_mode_, |
| 90 | : Applet{system_.Kernel()}, frontend{frontend_}, system{system_} {} | 90 | const Core::Frontend::ErrorApplet& frontend_) |
| 91 | : Applet{system_.Kernel()}, applet_mode{applet_mode_}, frontend{frontend_}, system{system_} {} | ||
| 91 | 92 | ||
| 92 | Error::~Error() = default; | 93 | Error::~Error() = default; |
| 93 | 94 | ||
diff --git a/src/core/hle/service/am/applets/error.h b/src/core/hle/service/am/applets/error.h index a105cdb0c..a3e520cd4 100644 --- a/src/core/hle/service/am/applets/error.h +++ b/src/core/hle/service/am/applets/error.h | |||
| @@ -25,7 +25,8 @@ enum class ErrorAppletMode : u8 { | |||
| 25 | 25 | ||
| 26 | class Error final : public Applet { | 26 | class Error final : public Applet { |
| 27 | public: | 27 | public: |
| 28 | explicit Error(Core::System& system_, const Core::Frontend::ErrorApplet& frontend_); | 28 | explicit Error(Core::System& system_, LibraryAppletMode applet_mode_, |
| 29 | const Core::Frontend::ErrorApplet& frontend_); | ||
| 29 | ~Error() override; | 30 | ~Error() override; |
| 30 | 31 | ||
| 31 | void Initialize() override; | 32 | void Initialize() override; |
| @@ -40,6 +41,7 @@ public: | |||
| 40 | private: | 41 | private: |
| 41 | union ErrorArguments; | 42 | union ErrorArguments; |
| 42 | 43 | ||
| 44 | LibraryAppletMode applet_mode; | ||
| 43 | const Core::Frontend::ErrorApplet& frontend; | 45 | const Core::Frontend::ErrorApplet& frontend; |
| 44 | ResultCode error_code = RESULT_SUCCESS; | 46 | ResultCode error_code = RESULT_SUCCESS; |
| 45 | ErrorAppletMode mode = ErrorAppletMode::ShowError; | 47 | ErrorAppletMode mode = ErrorAppletMode::ShowError; |
diff --git a/src/core/hle/service/am/applets/general_backend.cpp b/src/core/hle/service/am/applets/general_backend.cpp index 4d1df5cbe..71016cce7 100644 --- a/src/core/hle/service/am/applets/general_backend.cpp +++ b/src/core/hle/service/am/applets/general_backend.cpp | |||
| @@ -37,8 +37,9 @@ static void LogCurrentStorage(AppletDataBroker& broker, std::string_view prefix) | |||
| 37 | } | 37 | } |
| 38 | } | 38 | } |
| 39 | 39 | ||
| 40 | Auth::Auth(Core::System& system_, Core::Frontend::ParentalControlsApplet& frontend_) | 40 | Auth::Auth(Core::System& system_, LibraryAppletMode applet_mode_, |
| 41 | : Applet{system_.Kernel()}, frontend{frontend_}, system{system_} {} | 41 | Core::Frontend::ParentalControlsApplet& frontend_) |
| 42 | : Applet{system_.Kernel()}, applet_mode{applet_mode_}, frontend{frontend_}, system{system_} {} | ||
| 42 | 43 | ||
| 43 | Auth::~Auth() = default; | 44 | Auth::~Auth() = default; |
| 44 | 45 | ||
| @@ -152,8 +153,9 @@ void Auth::AuthFinished(bool is_successful) { | |||
| 152 | broker.SignalStateChanged(); | 153 | broker.SignalStateChanged(); |
| 153 | } | 154 | } |
| 154 | 155 | ||
| 155 | PhotoViewer::PhotoViewer(Core::System& system_, const Core::Frontend::PhotoViewerApplet& frontend_) | 156 | PhotoViewer::PhotoViewer(Core::System& system_, LibraryAppletMode applet_mode_, |
| 156 | : Applet{system_.Kernel()}, frontend{frontend_}, system{system_} {} | 157 | const Core::Frontend::PhotoViewerApplet& frontend_) |
| 158 | : Applet{system_.Kernel()}, applet_mode{applet_mode_}, frontend{frontend_}, system{system_} {} | ||
| 157 | 159 | ||
| 158 | PhotoViewer::~PhotoViewer() = default; | 160 | PhotoViewer::~PhotoViewer() = default; |
| 159 | 161 | ||
| @@ -202,8 +204,8 @@ void PhotoViewer::ViewFinished() { | |||
| 202 | broker.SignalStateChanged(); | 204 | broker.SignalStateChanged(); |
| 203 | } | 205 | } |
| 204 | 206 | ||
| 205 | StubApplet::StubApplet(Core::System& system_, AppletId id_) | 207 | StubApplet::StubApplet(Core::System& system_, AppletId id_, LibraryAppletMode applet_mode_) |
| 206 | : Applet{system_.Kernel()}, id{id_}, system{system_} {} | 208 | : Applet{system_.Kernel()}, id{id_}, applet_mode{applet_mode_}, system{system_} {} |
| 207 | 209 | ||
| 208 | StubApplet::~StubApplet() = default; | 210 | StubApplet::~StubApplet() = default; |
| 209 | 211 | ||
diff --git a/src/core/hle/service/am/applets/general_backend.h b/src/core/hle/service/am/applets/general_backend.h index ba76ae3d3..d9e6d4384 100644 --- a/src/core/hle/service/am/applets/general_backend.h +++ b/src/core/hle/service/am/applets/general_backend.h | |||
| @@ -20,7 +20,8 @@ enum class AuthAppletType : u32 { | |||
| 20 | 20 | ||
| 21 | class Auth final : public Applet { | 21 | class Auth final : public Applet { |
| 22 | public: | 22 | public: |
| 23 | explicit Auth(Core::System& system_, Core::Frontend::ParentalControlsApplet& frontend_); | 23 | explicit Auth(Core::System& system_, LibraryAppletMode applet_mode_, |
| 24 | Core::Frontend::ParentalControlsApplet& frontend_); | ||
| 24 | ~Auth() override; | 25 | ~Auth() override; |
| 25 | 26 | ||
| 26 | void Initialize() override; | 27 | void Initialize() override; |
| @@ -32,6 +33,7 @@ public: | |||
| 32 | void AuthFinished(bool is_successful = true); | 33 | void AuthFinished(bool is_successful = true); |
| 33 | 34 | ||
| 34 | private: | 35 | private: |
| 36 | LibraryAppletMode applet_mode; | ||
| 35 | Core::Frontend::ParentalControlsApplet& frontend; | 37 | Core::Frontend::ParentalControlsApplet& frontend; |
| 36 | Core::System& system; | 38 | Core::System& system; |
| 37 | bool complete = false; | 39 | bool complete = false; |
| @@ -50,7 +52,8 @@ enum class PhotoViewerAppletMode : u8 { | |||
| 50 | 52 | ||
| 51 | class PhotoViewer final : public Applet { | 53 | class PhotoViewer final : public Applet { |
| 52 | public: | 54 | public: |
| 53 | explicit PhotoViewer(Core::System& system_, const Core::Frontend::PhotoViewerApplet& frontend_); | 55 | explicit PhotoViewer(Core::System& system_, LibraryAppletMode applet_mode_, |
| 56 | const Core::Frontend::PhotoViewerApplet& frontend_); | ||
| 54 | ~PhotoViewer() override; | 57 | ~PhotoViewer() override; |
| 55 | 58 | ||
| 56 | void Initialize() override; | 59 | void Initialize() override; |
| @@ -62,6 +65,7 @@ public: | |||
| 62 | void ViewFinished(); | 65 | void ViewFinished(); |
| 63 | 66 | ||
| 64 | private: | 67 | private: |
| 68 | LibraryAppletMode applet_mode; | ||
| 65 | const Core::Frontend::PhotoViewerApplet& frontend; | 69 | const Core::Frontend::PhotoViewerApplet& frontend; |
| 66 | bool complete = false; | 70 | bool complete = false; |
| 67 | PhotoViewerAppletMode mode = PhotoViewerAppletMode::CurrentApp; | 71 | PhotoViewerAppletMode mode = PhotoViewerAppletMode::CurrentApp; |
| @@ -70,7 +74,7 @@ private: | |||
| 70 | 74 | ||
| 71 | class StubApplet final : public Applet { | 75 | class StubApplet final : public Applet { |
| 72 | public: | 76 | public: |
| 73 | explicit StubApplet(Core::System& system_, AppletId id_); | 77 | explicit StubApplet(Core::System& system_, AppletId id_, LibraryAppletMode applet_mode_); |
| 74 | ~StubApplet() override; | 78 | ~StubApplet() override; |
| 75 | 79 | ||
| 76 | void Initialize() override; | 80 | void Initialize() override; |
| @@ -82,6 +86,7 @@ public: | |||
| 82 | 86 | ||
| 83 | private: | 87 | private: |
| 84 | AppletId id; | 88 | AppletId id; |
| 89 | LibraryAppletMode applet_mode; | ||
| 85 | Core::System& system; | 90 | Core::System& system; |
| 86 | }; | 91 | }; |
| 87 | 92 | ||
diff --git a/src/core/hle/service/am/applets/profile_select.cpp b/src/core/hle/service/am/applets/profile_select.cpp index 77fba16c7..ab8b6fcc5 100644 --- a/src/core/hle/service/am/applets/profile_select.cpp +++ b/src/core/hle/service/am/applets/profile_select.cpp | |||
| @@ -15,9 +15,9 @@ namespace Service::AM::Applets { | |||
| 15 | 15 | ||
| 16 | constexpr ResultCode ERR_USER_CANCELLED_SELECTION{ErrorModule::Account, 1}; | 16 | constexpr ResultCode ERR_USER_CANCELLED_SELECTION{ErrorModule::Account, 1}; |
| 17 | 17 | ||
| 18 | ProfileSelect::ProfileSelect(Core::System& system_, | 18 | ProfileSelect::ProfileSelect(Core::System& system_, LibraryAppletMode applet_mode_, |
| 19 | const Core::Frontend::ProfileSelectApplet& frontend_) | 19 | const Core::Frontend::ProfileSelectApplet& frontend_) |
| 20 | : Applet{system_.Kernel()}, frontend{frontend_}, system{system_} {} | 20 | : Applet{system_.Kernel()}, applet_mode{applet_mode_}, frontend{frontend_}, system{system_} {} |
| 21 | 21 | ||
| 22 | ProfileSelect::~ProfileSelect() = default; | 22 | ProfileSelect::~ProfileSelect() = default; |
| 23 | 23 | ||
diff --git a/src/core/hle/service/am/applets/profile_select.h b/src/core/hle/service/am/applets/profile_select.h index 648d33a24..90f054030 100644 --- a/src/core/hle/service/am/applets/profile_select.h +++ b/src/core/hle/service/am/applets/profile_select.h | |||
| @@ -33,7 +33,7 @@ static_assert(sizeof(UserSelectionOutput) == 0x18, "UserSelectionOutput has inco | |||
| 33 | 33 | ||
| 34 | class ProfileSelect final : public Applet { | 34 | class ProfileSelect final : public Applet { |
| 35 | public: | 35 | public: |
| 36 | explicit ProfileSelect(Core::System& system_, | 36 | explicit ProfileSelect(Core::System& system_, LibraryAppletMode applet_mode_, |
| 37 | const Core::Frontend::ProfileSelectApplet& frontend_); | 37 | const Core::Frontend::ProfileSelectApplet& frontend_); |
| 38 | ~ProfileSelect() override; | 38 | ~ProfileSelect() override; |
| 39 | 39 | ||
| @@ -47,6 +47,7 @@ public: | |||
| 47 | void SelectionComplete(std::optional<Common::UUID> uuid); | 47 | void SelectionComplete(std::optional<Common::UUID> uuid); |
| 48 | 48 | ||
| 49 | private: | 49 | private: |
| 50 | LibraryAppletMode applet_mode; | ||
| 50 | const Core::Frontend::ProfileSelectApplet& frontend; | 51 | const Core::Frontend::ProfileSelectApplet& frontend; |
| 51 | 52 | ||
| 52 | UserSelectionConfig config; | 53 | UserSelectionConfig config; |
diff --git a/src/core/hle/service/am/applets/software_keyboard.cpp b/src/core/hle/service/am/applets/software_keyboard.cpp index 79b209c6b..c3a05de9c 100644 --- a/src/core/hle/service/am/applets/software_keyboard.cpp +++ b/src/core/hle/service/am/applets/software_keyboard.cpp | |||
| @@ -1,93 +1,80 @@ | |||
| 1 | // Copyright 2018 yuzu emulator team | 1 | // Copyright 2021 yuzu Emulator Project |
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <cstring> | ||
| 6 | #include "common/assert.h" | ||
| 7 | #include "common/string_util.h" | 5 | #include "common/string_util.h" |
| 8 | #include "core/core.h" | 6 | #include "core/core.h" |
| 9 | #include "core/frontend/applets/software_keyboard.h" | 7 | #include "core/frontend/applets/software_keyboard.h" |
| 10 | #include "core/hle/result.h" | ||
| 11 | #include "core/hle/service/am/am.h" | 8 | #include "core/hle/service/am/am.h" |
| 12 | #include "core/hle/service/am/applets/software_keyboard.h" | 9 | #include "core/hle/service/am/applets/software_keyboard.h" |
| 13 | 10 | ||
| 14 | namespace Service::AM::Applets { | 11 | namespace Service::AM::Applets { |
| 15 | 12 | ||
| 16 | namespace { | 13 | namespace { |
| 17 | enum class Request : u32 { | 14 | |
| 18 | Finalize = 0x4, | 15 | // The maximum number of UTF-16 characters that can be input into the swkbd text field. |
| 19 | SetUserWordInfo = 0x6, | 16 | constexpr u32 DEFAULT_MAX_TEXT_LENGTH = 500; |
| 20 | SetCustomizeDic = 0x7, | 17 | |
| 21 | Calc = 0xa, | 18 | constexpr std::size_t REPLY_BASE_SIZE = sizeof(SwkbdState) + sizeof(SwkbdReplyType); |
| 22 | SetCustomizedDictionaries = 0xb, | 19 | constexpr std::size_t REPLY_UTF8_SIZE = 0x7D4; |
| 23 | UnsetCustomizedDictionaries = 0xc, | 20 | constexpr std::size_t REPLY_UTF16_SIZE = 0x3EC; |
| 24 | UnknownD = 0xd, | 21 | |
| 25 | UnknownE = 0xe, | 22 | constexpr const char* GetTextCheckResultName(SwkbdTextCheckResult text_check_result) { |
| 26 | }; | 23 | switch (text_check_result) { |
| 27 | constexpr std::size_t SWKBD_INLINE_INIT_SIZE = 0x8; | 24 | case SwkbdTextCheckResult::Success: |
| 28 | constexpr std::size_t SWKBD_OUTPUT_BUFFER_SIZE = 0x7D8; | 25 | return "Success"; |
| 29 | constexpr std::size_t SWKBD_OUTPUT_INTERACTIVE_BUFFER_SIZE = 0x7D4; | 26 | case SwkbdTextCheckResult::Failure: |
| 30 | constexpr std::size_t DEFAULT_MAX_LENGTH = 500; | 27 | return "Failure"; |
| 31 | constexpr bool INTERACTIVE_STATUS_OK = false; | 28 | case SwkbdTextCheckResult::Confirm: |
| 29 | return "Confirm"; | ||
| 30 | case SwkbdTextCheckResult::Silent: | ||
| 31 | return "Silent"; | ||
| 32 | default: | ||
| 33 | UNIMPLEMENTED_MSG("Unknown TextCheckResult={}", text_check_result); | ||
| 34 | return "Unknown"; | ||
| 35 | } | ||
| 36 | } | ||
| 37 | |||
| 38 | void SetReplyBase(std::vector<u8>& reply, SwkbdState state, SwkbdReplyType reply_type) { | ||
| 39 | std::memcpy(reply.data(), &state, sizeof(SwkbdState)); | ||
| 40 | std::memcpy(reply.data() + sizeof(SwkbdState), &reply_type, sizeof(SwkbdReplyType)); | ||
| 41 | } | ||
| 42 | |||
| 32 | } // Anonymous namespace | 43 | } // Anonymous namespace |
| 33 | static Core::Frontend::SoftwareKeyboardParameters ConvertToFrontendParameters( | 44 | |
| 34 | KeyboardConfig config, std::u16string initial_text) { | 45 | SoftwareKeyboard::SoftwareKeyboard(Core::System& system_, LibraryAppletMode applet_mode_, |
| 35 | Core::Frontend::SoftwareKeyboardParameters params{}; | 46 | Core::Frontend::SoftwareKeyboardApplet& frontend_) |
| 36 | 47 | : Applet{system_.Kernel()}, applet_mode{applet_mode_}, frontend{frontend_}, system{system_} {} | |
| 37 | params.submit_text = Common::UTF16StringFromFixedZeroTerminatedBuffer( | ||
| 38 | config.submit_text.data(), config.submit_text.size()); | ||
| 39 | params.header_text = Common::UTF16StringFromFixedZeroTerminatedBuffer( | ||
| 40 | config.header_text.data(), config.header_text.size()); | ||
| 41 | params.sub_text = Common::UTF16StringFromFixedZeroTerminatedBuffer(config.sub_text.data(), | ||
| 42 | config.sub_text.size()); | ||
| 43 | params.guide_text = Common::UTF16StringFromFixedZeroTerminatedBuffer(config.guide_text.data(), | ||
| 44 | config.guide_text.size()); | ||
| 45 | params.initial_text = std::move(initial_text); | ||
| 46 | params.max_length = config.length_limit == 0 ? DEFAULT_MAX_LENGTH : config.length_limit; | ||
| 47 | params.password = static_cast<bool>(config.is_password); | ||
| 48 | params.cursor_at_beginning = static_cast<bool>(config.initial_cursor_position); | ||
| 49 | params.value = static_cast<u8>(config.keyset_disable_bitmask); | ||
| 50 | |||
| 51 | return params; | ||
| 52 | } | ||
| 53 | |||
| 54 | SoftwareKeyboard::SoftwareKeyboard(Core::System& system_, | ||
| 55 | const Core::Frontend::SoftwareKeyboardApplet& frontend_) | ||
| 56 | : Applet{system_.Kernel()}, frontend{frontend_}, system{system_} {} | ||
| 57 | 48 | ||
| 58 | SoftwareKeyboard::~SoftwareKeyboard() = default; | 49 | SoftwareKeyboard::~SoftwareKeyboard() = default; |
| 59 | 50 | ||
| 60 | void SoftwareKeyboard::Initialize() { | 51 | void SoftwareKeyboard::Initialize() { |
| 61 | complete = false; | ||
| 62 | is_inline = false; | ||
| 63 | initial_text.clear(); | ||
| 64 | final_data.clear(); | ||
| 65 | |||
| 66 | Applet::Initialize(); | 52 | Applet::Initialize(); |
| 67 | 53 | ||
| 68 | const auto keyboard_config_storage = broker.PopNormalDataToApplet(); | 54 | LOG_INFO(Service_AM, "Initializing Software Keyboard Applet with LibraryAppletMode={}", |
| 69 | ASSERT(keyboard_config_storage != nullptr); | 55 | applet_mode); |
| 70 | const auto& keyboard_config = keyboard_config_storage->GetData(); | ||
| 71 | |||
| 72 | if (keyboard_config.size() == SWKBD_INLINE_INIT_SIZE) { | ||
| 73 | is_inline = true; | ||
| 74 | return; | ||
| 75 | } | ||
| 76 | |||
| 77 | ASSERT(keyboard_config.size() >= sizeof(KeyboardConfig)); | ||
| 78 | std::memcpy(&config, keyboard_config.data(), sizeof(KeyboardConfig)); | ||
| 79 | 56 | ||
| 80 | const auto work_buffer_storage = broker.PopNormalDataToApplet(); | 57 | LOG_DEBUG(Service_AM, |
| 81 | ASSERT_OR_EXECUTE(work_buffer_storage != nullptr, { return; }); | 58 | "Initializing Applet with common_args: arg_version={}, lib_version={}, " |
| 82 | const auto& work_buffer = work_buffer_storage->GetData(); | 59 | "play_startup_sound={}, size={}, system_tick={}, theme_color={}", |
| 60 | common_args.arguments_version, common_args.library_version, | ||
| 61 | common_args.play_startup_sound, common_args.size, common_args.system_tick, | ||
| 62 | common_args.theme_color); | ||
| 83 | 63 | ||
| 84 | if (config.initial_string_size == 0) | 64 | swkbd_applet_version = SwkbdAppletVersion{common_args.library_version}; |
| 85 | return; | ||
| 86 | 65 | ||
| 87 | std::vector<char16_t> string(config.initial_string_size); | 66 | switch (applet_mode) { |
| 88 | std::memcpy(string.data(), work_buffer.data() + config.initial_string_offset, | 67 | case LibraryAppletMode::AllForeground: |
| 89 | string.size() * 2); | 68 | InitializeForeground(); |
| 90 | initial_text = Common::UTF16StringFromFixedZeroTerminatedBuffer(string.data(), string.size()); | 69 | break; |
| 70 | case LibraryAppletMode::Background: | ||
| 71 | case LibraryAppletMode::BackgroundIndirectDisplay: | ||
| 72 | InitializeBackground(applet_mode); | ||
| 73 | break; | ||
| 74 | default: | ||
| 75 | UNREACHABLE_MSG("Invalid LibraryAppletMode={}", applet_mode); | ||
| 76 | break; | ||
| 77 | } | ||
| 91 | } | 78 | } |
| 92 | 79 | ||
| 93 | bool SoftwareKeyboard::TransactionComplete() const { | 80 | bool SoftwareKeyboard::TransactionComplete() const { |
| @@ -95,106 +82,996 @@ bool SoftwareKeyboard::TransactionComplete() const { | |||
| 95 | } | 82 | } |
| 96 | 83 | ||
| 97 | ResultCode SoftwareKeyboard::GetStatus() const { | 84 | ResultCode SoftwareKeyboard::GetStatus() const { |
| 98 | return RESULT_SUCCESS; | 85 | return status; |
| 99 | } | 86 | } |
| 100 | 87 | ||
| 101 | void SoftwareKeyboard::ExecuteInteractive() { | 88 | void SoftwareKeyboard::ExecuteInteractive() { |
| 102 | if (complete) | 89 | if (complete) { |
| 103 | return; | 90 | return; |
| 91 | } | ||
| 104 | 92 | ||
| 105 | const auto storage = broker.PopInteractiveDataToApplet(); | 93 | if (is_background) { |
| 106 | ASSERT(storage != nullptr); | 94 | ProcessInlineKeyboardRequest(); |
| 107 | const auto data = storage->GetData(); | ||
| 108 | if (!is_inline) { | ||
| 109 | const auto status = static_cast<bool>(data[0]); | ||
| 110 | if (status == INTERACTIVE_STATUS_OK) { | ||
| 111 | complete = true; | ||
| 112 | } else { | ||
| 113 | std::array<char16_t, SWKBD_OUTPUT_INTERACTIVE_BUFFER_SIZE / 2 - 2> string; | ||
| 114 | std::memcpy(string.data(), data.data() + 4, string.size() * 2); | ||
| 115 | frontend.SendTextCheckDialog( | ||
| 116 | Common::UTF16StringFromFixedZeroTerminatedBuffer(string.data(), string.size()), | ||
| 117 | [this] { broker.SignalStateChanged(); }); | ||
| 118 | } | ||
| 119 | } else { | 95 | } else { |
| 120 | Request request{}; | 96 | ProcessTextCheck(); |
| 121 | std::memcpy(&request, data.data(), sizeof(Request)); | 97 | } |
| 98 | } | ||
| 99 | |||
| 100 | void SoftwareKeyboard::Execute() { | ||
| 101 | if (complete) { | ||
| 102 | return; | ||
| 103 | } | ||
| 104 | |||
| 105 | if (is_background) { | ||
| 106 | return; | ||
| 107 | } | ||
| 108 | |||
| 109 | ShowNormalKeyboard(); | ||
| 110 | } | ||
| 122 | 111 | ||
| 123 | switch (request) { | 112 | void SoftwareKeyboard::SubmitTextNormal(SwkbdResult result, std::u16string submitted_text) { |
| 124 | case Request::Finalize: | 113 | if (complete) { |
| 125 | complete = true; | 114 | return; |
| 126 | broker.SignalStateChanged(); | 115 | } |
| 116 | |||
| 117 | if (swkbd_config_common.use_text_check && result == SwkbdResult::Ok) { | ||
| 118 | SubmitForTextCheck(submitted_text); | ||
| 119 | } else { | ||
| 120 | SubmitNormalOutputAndExit(result, submitted_text); | ||
| 121 | } | ||
| 122 | } | ||
| 123 | |||
| 124 | void SoftwareKeyboard::SubmitTextInline(SwkbdReplyType reply_type, std::u16string submitted_text, | ||
| 125 | s32 cursor_position) { | ||
| 126 | if (complete) { | ||
| 127 | return; | ||
| 128 | } | ||
| 129 | |||
| 130 | current_text = std::move(submitted_text); | ||
| 131 | current_cursor_position = cursor_position; | ||
| 132 | |||
| 133 | if (inline_use_utf8) { | ||
| 134 | switch (reply_type) { | ||
| 135 | case SwkbdReplyType::ChangedString: | ||
| 136 | reply_type = SwkbdReplyType::ChangedStringUtf8; | ||
| 127 | break; | 137 | break; |
| 128 | case Request::Calc: { | 138 | case SwkbdReplyType::MovedCursor: |
| 129 | broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::vector<u8>{1})); | 139 | reply_type = SwkbdReplyType::MovedCursorUtf8; |
| 130 | broker.SignalStateChanged(); | 140 | break; |
| 141 | case SwkbdReplyType::DecidedEnter: | ||
| 142 | reply_type = SwkbdReplyType::DecidedEnterUtf8; | ||
| 143 | break; | ||
| 144 | default: | ||
| 131 | break; | 145 | break; |
| 132 | } | 146 | } |
| 147 | } | ||
| 148 | |||
| 149 | if (use_changed_string_v2) { | ||
| 150 | switch (reply_type) { | ||
| 151 | case SwkbdReplyType::ChangedString: | ||
| 152 | reply_type = SwkbdReplyType::ChangedStringV2; | ||
| 153 | break; | ||
| 154 | case SwkbdReplyType::ChangedStringUtf8: | ||
| 155 | reply_type = SwkbdReplyType::ChangedStringUtf8V2; | ||
| 156 | break; | ||
| 133 | default: | 157 | default: |
| 134 | UNIMPLEMENTED_MSG("Request {:X} is not implemented", request); | ||
| 135 | break; | 158 | break; |
| 136 | } | 159 | } |
| 137 | } | 160 | } |
| 161 | |||
| 162 | if (use_moved_cursor_v2) { | ||
| 163 | switch (reply_type) { | ||
| 164 | case SwkbdReplyType::MovedCursor: | ||
| 165 | reply_type = SwkbdReplyType::MovedCursorV2; | ||
| 166 | break; | ||
| 167 | case SwkbdReplyType::MovedCursorUtf8: | ||
| 168 | reply_type = SwkbdReplyType::MovedCursorUtf8V2; | ||
| 169 | break; | ||
| 170 | default: | ||
| 171 | break; | ||
| 172 | } | ||
| 173 | } | ||
| 174 | |||
| 175 | SendReply(reply_type); | ||
| 138 | } | 176 | } |
| 139 | 177 | ||
| 140 | void SoftwareKeyboard::Execute() { | 178 | void SoftwareKeyboard::InitializeForeground() { |
| 141 | if (complete) { | 179 | LOG_INFO(Service_AM, "Initializing Normal Software Keyboard Applet."); |
| 142 | broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::move(final_data))); | 180 | |
| 143 | broker.SignalStateChanged(); | 181 | is_background = false; |
| 182 | |||
| 183 | const auto swkbd_config_storage = broker.PopNormalDataToApplet(); | ||
| 184 | ASSERT(swkbd_config_storage != nullptr); | ||
| 185 | |||
| 186 | const auto& swkbd_config_data = swkbd_config_storage->GetData(); | ||
| 187 | ASSERT(swkbd_config_data.size() >= sizeof(SwkbdConfigCommon)); | ||
| 188 | |||
| 189 | std::memcpy(&swkbd_config_common, swkbd_config_data.data(), sizeof(SwkbdConfigCommon)); | ||
| 190 | |||
| 191 | switch (swkbd_applet_version) { | ||
| 192 | case SwkbdAppletVersion::Version5: | ||
| 193 | case SwkbdAppletVersion::Version65542: | ||
| 194 | ASSERT(swkbd_config_data.size() == sizeof(SwkbdConfigCommon) + sizeof(SwkbdConfigOld)); | ||
| 195 | std::memcpy(&swkbd_config_old, swkbd_config_data.data() + sizeof(SwkbdConfigCommon), | ||
| 196 | sizeof(SwkbdConfigOld)); | ||
| 197 | break; | ||
| 198 | case SwkbdAppletVersion::Version196615: | ||
| 199 | case SwkbdAppletVersion::Version262152: | ||
| 200 | case SwkbdAppletVersion::Version327689: | ||
| 201 | ASSERT(swkbd_config_data.size() == sizeof(SwkbdConfigCommon) + sizeof(SwkbdConfigOld2)); | ||
| 202 | std::memcpy(&swkbd_config_old2, swkbd_config_data.data() + sizeof(SwkbdConfigCommon), | ||
| 203 | sizeof(SwkbdConfigOld2)); | ||
| 204 | break; | ||
| 205 | case SwkbdAppletVersion::Version393227: | ||
| 206 | case SwkbdAppletVersion::Version524301: | ||
| 207 | ASSERT(swkbd_config_data.size() == sizeof(SwkbdConfigCommon) + sizeof(SwkbdConfigNew)); | ||
| 208 | std::memcpy(&swkbd_config_new, swkbd_config_data.data() + sizeof(SwkbdConfigCommon), | ||
| 209 | sizeof(SwkbdConfigNew)); | ||
| 210 | break; | ||
| 211 | default: | ||
| 212 | UNIMPLEMENTED_MSG("Unknown SwkbdConfig revision={} with size={}", swkbd_applet_version, | ||
| 213 | swkbd_config_data.size()); | ||
| 214 | ASSERT(swkbd_config_data.size() >= sizeof(SwkbdConfigCommon) + sizeof(SwkbdConfigNew)); | ||
| 215 | std::memcpy(&swkbd_config_new, swkbd_config_data.data() + sizeof(SwkbdConfigCommon), | ||
| 216 | sizeof(SwkbdConfigNew)); | ||
| 217 | break; | ||
| 218 | } | ||
| 219 | |||
| 220 | const auto work_buffer_storage = broker.PopNormalDataToApplet(); | ||
| 221 | ASSERT(work_buffer_storage != nullptr); | ||
| 222 | |||
| 223 | if (swkbd_config_common.initial_string_length == 0) { | ||
| 224 | InitializeFrontendKeyboard(); | ||
| 144 | return; | 225 | return; |
| 145 | } | 226 | } |
| 146 | 227 | ||
| 147 | const auto parameters = ConvertToFrontendParameters(config, initial_text); | 228 | const auto& work_buffer = work_buffer_storage->GetData(); |
| 148 | if (!is_inline) { | 229 | |
| 149 | frontend.RequestText( | 230 | std::vector<char16_t> initial_string(swkbd_config_common.initial_string_length); |
| 150 | [this](std::optional<std::u16string> text) { WriteText(std::move(text)); }, parameters); | 231 | |
| 232 | std::memcpy(initial_string.data(), | ||
| 233 | work_buffer.data() + swkbd_config_common.initial_string_offset, | ||
| 234 | swkbd_config_common.initial_string_length * sizeof(char16_t)); | ||
| 235 | |||
| 236 | initial_text = Common::UTF16StringFromFixedZeroTerminatedBuffer(initial_string.data(), | ||
| 237 | initial_string.size()); | ||
| 238 | |||
| 239 | LOG_DEBUG(Service_AM, "\nInitial Text: {}", Common::UTF16ToUTF8(initial_text)); | ||
| 240 | |||
| 241 | InitializeFrontendKeyboard(); | ||
| 242 | } | ||
| 243 | |||
| 244 | void SoftwareKeyboard::InitializeBackground(LibraryAppletMode applet_mode) { | ||
| 245 | LOG_INFO(Service_AM, "Initializing Inline Software Keyboard Applet."); | ||
| 246 | |||
| 247 | is_background = true; | ||
| 248 | |||
| 249 | const auto swkbd_inline_initialize_arg_storage = broker.PopNormalDataToApplet(); | ||
| 250 | ASSERT(swkbd_inline_initialize_arg_storage != nullptr); | ||
| 251 | |||
| 252 | const auto& swkbd_inline_initialize_arg = swkbd_inline_initialize_arg_storage->GetData(); | ||
| 253 | ASSERT(swkbd_inline_initialize_arg.size() == sizeof(SwkbdInitializeArg)); | ||
| 254 | |||
| 255 | std::memcpy(&swkbd_initialize_arg, swkbd_inline_initialize_arg.data(), | ||
| 256 | swkbd_inline_initialize_arg.size()); | ||
| 257 | |||
| 258 | if (swkbd_initialize_arg.library_applet_mode_flag) { | ||
| 259 | ASSERT(applet_mode == LibraryAppletMode::Background); | ||
| 260 | } else { | ||
| 261 | ASSERT(applet_mode == LibraryAppletMode::BackgroundIndirectDisplay); | ||
| 262 | } | ||
| 263 | } | ||
| 264 | |||
| 265 | void SoftwareKeyboard::ProcessTextCheck() { | ||
| 266 | const auto text_check_storage = broker.PopInteractiveDataToApplet(); | ||
| 267 | ASSERT(text_check_storage != nullptr); | ||
| 268 | |||
| 269 | const auto& text_check_data = text_check_storage->GetData(); | ||
| 270 | ASSERT(text_check_data.size() == sizeof(SwkbdTextCheck)); | ||
| 271 | |||
| 272 | SwkbdTextCheck swkbd_text_check; | ||
| 273 | |||
| 274 | std::memcpy(&swkbd_text_check, text_check_data.data(), sizeof(SwkbdTextCheck)); | ||
| 275 | |||
| 276 | std::u16string text_check_message = Common::UTF16StringFromFixedZeroTerminatedBuffer( | ||
| 277 | swkbd_text_check.text_check_message.data(), swkbd_text_check.text_check_message.size()); | ||
| 278 | |||
| 279 | LOG_INFO(Service_AM, "\nTextCheckResult: {}\nTextCheckMessage: {}", | ||
| 280 | GetTextCheckResultName(swkbd_text_check.text_check_result), | ||
| 281 | Common::UTF16ToUTF8(text_check_message)); | ||
| 282 | |||
| 283 | switch (swkbd_text_check.text_check_result) { | ||
| 284 | case SwkbdTextCheckResult::Success: | ||
| 285 | SubmitNormalOutputAndExit(SwkbdResult::Ok, current_text); | ||
| 286 | break; | ||
| 287 | case SwkbdTextCheckResult::Failure: | ||
| 288 | ShowTextCheckDialog(SwkbdTextCheckResult::Failure, text_check_message); | ||
| 289 | break; | ||
| 290 | case SwkbdTextCheckResult::Confirm: | ||
| 291 | ShowTextCheckDialog(SwkbdTextCheckResult::Confirm, text_check_message); | ||
| 292 | break; | ||
| 293 | case SwkbdTextCheckResult::Silent: | ||
| 294 | default: | ||
| 295 | break; | ||
| 151 | } | 296 | } |
| 152 | } | 297 | } |
| 153 | 298 | ||
| 154 | void SoftwareKeyboard::WriteText(std::optional<std::u16string> text) { | 299 | void SoftwareKeyboard::ProcessInlineKeyboardRequest() { |
| 155 | std::vector<u8> output_main(SWKBD_OUTPUT_BUFFER_SIZE); | 300 | const auto request_data_storage = broker.PopInteractiveDataToApplet(); |
| 301 | ASSERT(request_data_storage != nullptr); | ||
| 302 | |||
| 303 | const auto& request_data = request_data_storage->GetData(); | ||
| 304 | ASSERT(request_data.size() >= sizeof(SwkbdRequestCommand)); | ||
| 156 | 305 | ||
| 157 | if (text.has_value()) { | 306 | SwkbdRequestCommand request_command; |
| 158 | std::vector<u8> output_sub(SWKBD_OUTPUT_BUFFER_SIZE); | ||
| 159 | 307 | ||
| 160 | if (config.utf_8) { | 308 | std::memcpy(&request_command, request_data.data(), sizeof(SwkbdRequestCommand)); |
| 161 | const u64 size = text->size() + sizeof(u64); | ||
| 162 | const auto new_text = Common::UTF16ToUTF8(*text); | ||
| 163 | 309 | ||
| 164 | std::memcpy(output_sub.data(), &size, sizeof(u64)); | 310 | switch (request_command) { |
| 165 | std::memcpy(output_sub.data() + 8, new_text.data(), | 311 | case SwkbdRequestCommand::Finalize: |
| 166 | std::min(new_text.size(), SWKBD_OUTPUT_BUFFER_SIZE - 8)); | 312 | RequestFinalize(request_data); |
| 313 | break; | ||
| 314 | case SwkbdRequestCommand::SetUserWordInfo: | ||
| 315 | RequestSetUserWordInfo(request_data); | ||
| 316 | break; | ||
| 317 | case SwkbdRequestCommand::SetCustomizeDic: | ||
| 318 | RequestSetCustomizeDic(request_data); | ||
| 319 | break; | ||
| 320 | case SwkbdRequestCommand::Calc: | ||
| 321 | RequestCalc(request_data); | ||
| 322 | break; | ||
| 323 | case SwkbdRequestCommand::SetCustomizedDictionaries: | ||
| 324 | RequestSetCustomizedDictionaries(request_data); | ||
| 325 | break; | ||
| 326 | case SwkbdRequestCommand::UnsetCustomizedDictionaries: | ||
| 327 | RequestUnsetCustomizedDictionaries(request_data); | ||
| 328 | break; | ||
| 329 | case SwkbdRequestCommand::SetChangedStringV2Flag: | ||
| 330 | RequestSetChangedStringV2Flag(request_data); | ||
| 331 | break; | ||
| 332 | case SwkbdRequestCommand::SetMovedCursorV2Flag: | ||
| 333 | RequestSetMovedCursorV2Flag(request_data); | ||
| 334 | break; | ||
| 335 | default: | ||
| 336 | UNIMPLEMENTED_MSG("Unknown SwkbdRequestCommand={}", request_command); | ||
| 337 | break; | ||
| 338 | } | ||
| 339 | } | ||
| 167 | 340 | ||
| 168 | output_main[0] = INTERACTIVE_STATUS_OK; | 341 | void SoftwareKeyboard::SubmitNormalOutputAndExit(SwkbdResult result, |
| 169 | std::memcpy(output_main.data() + 4, new_text.data(), | 342 | std::u16string submitted_text) { |
| 170 | std::min(new_text.size(), SWKBD_OUTPUT_BUFFER_SIZE - 4)); | 343 | std::vector<u8> out_data(sizeof(SwkbdResult) + STRING_BUFFER_SIZE); |
| 171 | } else { | ||
| 172 | const u64 size = text->size() * 2 + sizeof(u64); | ||
| 173 | std::memcpy(output_sub.data(), &size, sizeof(u64)); | ||
| 174 | std::memcpy(output_sub.data() + 8, text->data(), | ||
| 175 | std::min(text->size() * 2, SWKBD_OUTPUT_BUFFER_SIZE - 8)); | ||
| 176 | 344 | ||
| 177 | output_main[0] = INTERACTIVE_STATUS_OK; | 345 | if (swkbd_config_common.use_utf8) { |
| 178 | std::memcpy(output_main.data() + 4, text->data(), | 346 | std::string utf8_submitted_text = Common::UTF16ToUTF8(submitted_text); |
| 179 | std::min(text->size() * 2, SWKBD_OUTPUT_BUFFER_SIZE - 4)); | ||
| 180 | } | ||
| 181 | 347 | ||
| 182 | complete = !config.text_check; | 348 | LOG_DEBUG(Service_AM, "\nSwkbdResult: {}\nUTF-8 Submitted Text: {}", result, |
| 183 | final_data = output_main; | 349 | utf8_submitted_text); |
| 184 | 350 | ||
| 185 | if (complete) { | 351 | std::memcpy(out_data.data(), &result, sizeof(SwkbdResult)); |
| 186 | broker.PushNormalDataFromApplet( | 352 | std::memcpy(out_data.data() + sizeof(SwkbdResult), utf8_submitted_text.data(), |
| 187 | std::make_shared<IStorage>(system, std::move(output_main))); | 353 | utf8_submitted_text.size()); |
| 188 | broker.SignalStateChanged(); | ||
| 189 | } else { | ||
| 190 | broker.PushInteractiveDataFromApplet( | ||
| 191 | std::make_shared<IStorage>(system, std::move(output_sub))); | ||
| 192 | } | ||
| 193 | } else { | 354 | } else { |
| 194 | output_main[0] = 1; | 355 | LOG_DEBUG(Service_AM, "\nSwkbdResult: {}\nUTF-16 Submitted Text: {}", result, |
| 195 | complete = true; | 356 | Common::UTF16ToUTF8(submitted_text)); |
| 196 | broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::move(output_main))); | 357 | |
| 197 | broker.SignalStateChanged(); | 358 | std::memcpy(out_data.data(), &result, sizeof(SwkbdResult)); |
| 359 | std::memcpy(out_data.data() + sizeof(SwkbdResult), submitted_text.data(), | ||
| 360 | submitted_text.size() * sizeof(char16_t)); | ||
| 361 | } | ||
| 362 | |||
| 363 | broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::move(out_data))); | ||
| 364 | |||
| 365 | ExitKeyboard(); | ||
| 366 | } | ||
| 367 | |||
| 368 | void SoftwareKeyboard::SubmitForTextCheck(std::u16string submitted_text) { | ||
| 369 | current_text = std::move(submitted_text); | ||
| 370 | |||
| 371 | std::vector<u8> out_data(sizeof(u64) + STRING_BUFFER_SIZE); | ||
| 372 | |||
| 373 | if (swkbd_config_common.use_utf8) { | ||
| 374 | std::string utf8_submitted_text = Common::UTF16ToUTF8(current_text); | ||
| 375 | const u64 buffer_size = sizeof(u64) + utf8_submitted_text.size(); | ||
| 376 | |||
| 377 | LOG_DEBUG(Service_AM, "\nBuffer Size: {}\nUTF-8 Submitted Text: {}", buffer_size, | ||
| 378 | utf8_submitted_text); | ||
| 379 | |||
| 380 | std::memcpy(out_data.data(), &buffer_size, sizeof(u64)); | ||
| 381 | std::memcpy(out_data.data() + sizeof(u64), utf8_submitted_text.data(), | ||
| 382 | utf8_submitted_text.size()); | ||
| 383 | } else { | ||
| 384 | const u64 buffer_size = sizeof(u64) + current_text.size() * sizeof(char16_t); | ||
| 385 | |||
| 386 | LOG_DEBUG(Service_AM, "\nBuffer Size: {}\nUTF-16 Submitted Text: {}", buffer_size, | ||
| 387 | Common::UTF16ToUTF8(current_text)); | ||
| 388 | |||
| 389 | std::memcpy(out_data.data(), &buffer_size, sizeof(u64)); | ||
| 390 | std::memcpy(out_data.data() + sizeof(u64), current_text.data(), | ||
| 391 | current_text.size() * sizeof(char16_t)); | ||
| 392 | } | ||
| 393 | |||
| 394 | broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(out_data))); | ||
| 395 | } | ||
| 396 | |||
| 397 | void SoftwareKeyboard::SendReply(SwkbdReplyType reply_type) { | ||
| 398 | switch (reply_type) { | ||
| 399 | case SwkbdReplyType::FinishedInitialize: | ||
| 400 | ReplyFinishedInitialize(); | ||
| 401 | break; | ||
| 402 | case SwkbdReplyType::Default: | ||
| 403 | ReplyDefault(); | ||
| 404 | break; | ||
| 405 | case SwkbdReplyType::ChangedString: | ||
| 406 | ReplyChangedString(); | ||
| 407 | break; | ||
| 408 | case SwkbdReplyType::MovedCursor: | ||
| 409 | ReplyMovedCursor(); | ||
| 410 | break; | ||
| 411 | case SwkbdReplyType::MovedTab: | ||
| 412 | ReplyMovedTab(); | ||
| 413 | break; | ||
| 414 | case SwkbdReplyType::DecidedEnter: | ||
| 415 | ReplyDecidedEnter(); | ||
| 416 | break; | ||
| 417 | case SwkbdReplyType::DecidedCancel: | ||
| 418 | ReplyDecidedCancel(); | ||
| 419 | break; | ||
| 420 | case SwkbdReplyType::ChangedStringUtf8: | ||
| 421 | ReplyChangedStringUtf8(); | ||
| 422 | break; | ||
| 423 | case SwkbdReplyType::MovedCursorUtf8: | ||
| 424 | ReplyMovedCursorUtf8(); | ||
| 425 | break; | ||
| 426 | case SwkbdReplyType::DecidedEnterUtf8: | ||
| 427 | ReplyDecidedEnterUtf8(); | ||
| 428 | break; | ||
| 429 | case SwkbdReplyType::UnsetCustomizeDic: | ||
| 430 | ReplyUnsetCustomizeDic(); | ||
| 431 | break; | ||
| 432 | case SwkbdReplyType::ReleasedUserWordInfo: | ||
| 433 | ReplyReleasedUserWordInfo(); | ||
| 434 | break; | ||
| 435 | case SwkbdReplyType::UnsetCustomizedDictionaries: | ||
| 436 | ReplyUnsetCustomizedDictionaries(); | ||
| 437 | break; | ||
| 438 | case SwkbdReplyType::ChangedStringV2: | ||
| 439 | ReplyChangedStringV2(); | ||
| 440 | break; | ||
| 441 | case SwkbdReplyType::MovedCursorV2: | ||
| 442 | ReplyMovedCursorV2(); | ||
| 443 | break; | ||
| 444 | case SwkbdReplyType::ChangedStringUtf8V2: | ||
| 445 | ReplyChangedStringUtf8V2(); | ||
| 446 | break; | ||
| 447 | case SwkbdReplyType::MovedCursorUtf8V2: | ||
| 448 | ReplyMovedCursorUtf8V2(); | ||
| 449 | break; | ||
| 450 | default: | ||
| 451 | UNIMPLEMENTED_MSG("Unknown SwkbdReplyType={}", reply_type); | ||
| 452 | ReplyDefault(); | ||
| 453 | break; | ||
| 454 | } | ||
| 455 | } | ||
| 456 | |||
| 457 | void SoftwareKeyboard::ChangeState(SwkbdState state) { | ||
| 458 | swkbd_state = state; | ||
| 459 | |||
| 460 | ReplyDefault(); | ||
| 461 | } | ||
| 462 | |||
| 463 | void SoftwareKeyboard::InitializeFrontendKeyboard() { | ||
| 464 | if (is_background) { | ||
| 465 | const auto& appear_arg = swkbd_calc_arg.appear_arg; | ||
| 466 | |||
| 467 | std::u16string ok_text = Common::UTF16StringFromFixedZeroTerminatedBuffer( | ||
| 468 | appear_arg.ok_text.data(), appear_arg.ok_text.size()); | ||
| 469 | |||
| 470 | const u32 max_text_length = | ||
| 471 | appear_arg.max_text_length > 0 && appear_arg.max_text_length <= DEFAULT_MAX_TEXT_LENGTH | ||
| 472 | ? appear_arg.max_text_length | ||
| 473 | : DEFAULT_MAX_TEXT_LENGTH; | ||
| 474 | |||
| 475 | const u32 min_text_length = | ||
| 476 | appear_arg.min_text_length <= max_text_length ? appear_arg.min_text_length : 0; | ||
| 477 | |||
| 478 | const s32 initial_cursor_position = | ||
| 479 | current_cursor_position > 0 ? current_cursor_position : 0; | ||
| 480 | |||
| 481 | const auto text_draw_type = | ||
| 482 | max_text_length <= 32 ? SwkbdTextDrawType::Line : SwkbdTextDrawType::Box; | ||
| 483 | |||
| 484 | Core::Frontend::KeyboardInitializeParameters initialize_parameters{ | ||
| 485 | .ok_text{ok_text}, | ||
| 486 | .header_text{}, | ||
| 487 | .sub_text{}, | ||
| 488 | .guide_text{}, | ||
| 489 | .initial_text{current_text}, | ||
| 490 | .max_text_length{max_text_length}, | ||
| 491 | .min_text_length{min_text_length}, | ||
| 492 | .initial_cursor_position{initial_cursor_position}, | ||
| 493 | .type{appear_arg.type}, | ||
| 494 | .password_mode{SwkbdPasswordMode::Disabled}, | ||
| 495 | .text_draw_type{text_draw_type}, | ||
| 496 | .key_disable_flags{appear_arg.key_disable_flags}, | ||
| 497 | .use_blur_background{false}, | ||
| 498 | .enable_backspace_button{swkbd_calc_arg.enable_backspace_button}, | ||
| 499 | .enable_return_button{appear_arg.enable_return_button}, | ||
| 500 | .disable_cancel_button{appear_arg.disable_cancel_button}, | ||
| 501 | }; | ||
| 502 | |||
| 503 | frontend.InitializeKeyboard( | ||
| 504 | true, std::move(initialize_parameters), {}, | ||
| 505 | [this](SwkbdReplyType reply_type, std::u16string submitted_text, s32 cursor_position) { | ||
| 506 | SubmitTextInline(reply_type, submitted_text, cursor_position); | ||
| 507 | }); | ||
| 508 | } else { | ||
| 509 | std::u16string ok_text = Common::UTF16StringFromFixedZeroTerminatedBuffer( | ||
| 510 | swkbd_config_common.ok_text.data(), swkbd_config_common.ok_text.size()); | ||
| 511 | |||
| 512 | std::u16string header_text = Common::UTF16StringFromFixedZeroTerminatedBuffer( | ||
| 513 | swkbd_config_common.header_text.data(), swkbd_config_common.header_text.size()); | ||
| 514 | |||
| 515 | std::u16string sub_text = Common::UTF16StringFromFixedZeroTerminatedBuffer( | ||
| 516 | swkbd_config_common.sub_text.data(), swkbd_config_common.sub_text.size()); | ||
| 517 | |||
| 518 | std::u16string guide_text = Common::UTF16StringFromFixedZeroTerminatedBuffer( | ||
| 519 | swkbd_config_common.guide_text.data(), swkbd_config_common.guide_text.size()); | ||
| 520 | |||
| 521 | const u32 max_text_length = | ||
| 522 | swkbd_config_common.max_text_length > 0 && | ||
| 523 | swkbd_config_common.max_text_length <= DEFAULT_MAX_TEXT_LENGTH | ||
| 524 | ? swkbd_config_common.max_text_length | ||
| 525 | : DEFAULT_MAX_TEXT_LENGTH; | ||
| 526 | |||
| 527 | const u32 min_text_length = swkbd_config_common.min_text_length <= max_text_length | ||
| 528 | ? swkbd_config_common.min_text_length | ||
| 529 | : 0; | ||
| 530 | |||
| 531 | const s32 initial_cursor_position = [this] { | ||
| 532 | switch (swkbd_config_common.initial_cursor_position) { | ||
| 533 | case SwkbdInitialCursorPosition::Start: | ||
| 534 | default: | ||
| 535 | return 0; | ||
| 536 | case SwkbdInitialCursorPosition::End: | ||
| 537 | return static_cast<s32>(initial_text.size()); | ||
| 538 | } | ||
| 539 | }(); | ||
| 540 | |||
| 541 | const auto text_draw_type = [this, max_text_length] { | ||
| 542 | switch (swkbd_config_common.text_draw_type) { | ||
| 543 | case SwkbdTextDrawType::Line: | ||
| 544 | default: | ||
| 545 | return max_text_length <= 32 ? SwkbdTextDrawType::Line : SwkbdTextDrawType::Box; | ||
| 546 | case SwkbdTextDrawType::Box: | ||
| 547 | case SwkbdTextDrawType::DownloadCode: | ||
| 548 | return swkbd_config_common.text_draw_type; | ||
| 549 | } | ||
| 550 | }(); | ||
| 551 | |||
| 552 | const auto enable_return_button = text_draw_type == SwkbdTextDrawType::Box | ||
| 553 | ? swkbd_config_common.enable_return_button | ||
| 554 | : false; | ||
| 555 | |||
| 556 | const auto disable_cancel_button = swkbd_applet_version >= SwkbdAppletVersion::Version393227 | ||
| 557 | ? swkbd_config_new.disable_cancel_button | ||
| 558 | : false; | ||
| 559 | |||
| 560 | Core::Frontend::KeyboardInitializeParameters initialize_parameters{ | ||
| 561 | .ok_text{ok_text}, | ||
| 562 | .header_text{header_text}, | ||
| 563 | .sub_text{sub_text}, | ||
| 564 | .guide_text{guide_text}, | ||
| 565 | .initial_text{initial_text}, | ||
| 566 | .max_text_length{max_text_length}, | ||
| 567 | .min_text_length{min_text_length}, | ||
| 568 | .initial_cursor_position{initial_cursor_position}, | ||
| 569 | .type{swkbd_config_common.type}, | ||
| 570 | .password_mode{swkbd_config_common.password_mode}, | ||
| 571 | .text_draw_type{text_draw_type}, | ||
| 572 | .key_disable_flags{swkbd_config_common.key_disable_flags}, | ||
| 573 | .use_blur_background{swkbd_config_common.use_blur_background}, | ||
| 574 | .enable_backspace_button{true}, | ||
| 575 | .enable_return_button{enable_return_button}, | ||
| 576 | .disable_cancel_button{disable_cancel_button}, | ||
| 577 | }; | ||
| 578 | |||
| 579 | frontend.InitializeKeyboard(false, std::move(initialize_parameters), | ||
| 580 | [this](SwkbdResult result, std::u16string submitted_text) { | ||
| 581 | SubmitTextNormal(result, submitted_text); | ||
| 582 | }, | ||
| 583 | {}); | ||
| 584 | } | ||
| 585 | } | ||
| 586 | |||
| 587 | void SoftwareKeyboard::ShowNormalKeyboard() { | ||
| 588 | frontend.ShowNormalKeyboard(); | ||
| 589 | } | ||
| 590 | |||
| 591 | void SoftwareKeyboard::ShowTextCheckDialog(SwkbdTextCheckResult text_check_result, | ||
| 592 | std::u16string text_check_message) { | ||
| 593 | frontend.ShowTextCheckDialog(text_check_result, text_check_message); | ||
| 594 | } | ||
| 595 | |||
| 596 | void SoftwareKeyboard::ShowInlineKeyboard() { | ||
| 597 | if (swkbd_state != SwkbdState::InitializedIsHidden) { | ||
| 598 | return; | ||
| 599 | } | ||
| 600 | |||
| 601 | ChangeState(SwkbdState::InitializedIsAppearing); | ||
| 602 | |||
| 603 | const auto& appear_arg = swkbd_calc_arg.appear_arg; | ||
| 604 | |||
| 605 | const u32 max_text_length = | ||
| 606 | appear_arg.max_text_length > 0 && appear_arg.max_text_length <= DEFAULT_MAX_TEXT_LENGTH | ||
| 607 | ? appear_arg.max_text_length | ||
| 608 | : DEFAULT_MAX_TEXT_LENGTH; | ||
| 609 | |||
| 610 | const u32 min_text_length = | ||
| 611 | appear_arg.min_text_length <= max_text_length ? appear_arg.min_text_length : 0; | ||
| 612 | |||
| 613 | Core::Frontend::InlineAppearParameters appear_parameters{ | ||
| 614 | .max_text_length{max_text_length}, | ||
| 615 | .min_text_length{min_text_length}, | ||
| 616 | .key_top_scale_x{swkbd_calc_arg.key_top_scale_x}, | ||
| 617 | .key_top_scale_y{swkbd_calc_arg.key_top_scale_y}, | ||
| 618 | .key_top_translate_x{swkbd_calc_arg.key_top_translate_x}, | ||
| 619 | .key_top_translate_y{swkbd_calc_arg.key_top_translate_y}, | ||
| 620 | .type{appear_arg.type}, | ||
| 621 | .key_disable_flags{appear_arg.key_disable_flags}, | ||
| 622 | .key_top_as_floating{swkbd_calc_arg.key_top_as_floating}, | ||
| 623 | .enable_backspace_button{swkbd_calc_arg.enable_backspace_button}, | ||
| 624 | .enable_return_button{appear_arg.enable_return_button}, | ||
| 625 | .disable_cancel_button{appear_arg.disable_cancel_button}, | ||
| 626 | }; | ||
| 627 | |||
| 628 | frontend.ShowInlineKeyboard(std::move(appear_parameters)); | ||
| 629 | |||
| 630 | ChangeState(SwkbdState::InitializedIsShown); | ||
| 631 | } | ||
| 632 | |||
| 633 | void SoftwareKeyboard::HideInlineKeyboard() { | ||
| 634 | if (swkbd_state != SwkbdState::InitializedIsShown) { | ||
| 635 | return; | ||
| 636 | } | ||
| 637 | |||
| 638 | ChangeState(SwkbdState::InitializedIsDisappearing); | ||
| 639 | |||
| 640 | frontend.HideInlineKeyboard(); | ||
| 641 | |||
| 642 | ChangeState(SwkbdState::InitializedIsHidden); | ||
| 643 | } | ||
| 644 | |||
| 645 | void SoftwareKeyboard::InlineTextChanged() { | ||
| 646 | Core::Frontend::InlineTextParameters text_parameters{ | ||
| 647 | .input_text{current_text}, | ||
| 648 | .cursor_position{current_cursor_position}, | ||
| 649 | }; | ||
| 650 | |||
| 651 | frontend.InlineTextChanged(std::move(text_parameters)); | ||
| 652 | } | ||
| 653 | |||
| 654 | void SoftwareKeyboard::ExitKeyboard() { | ||
| 655 | complete = true; | ||
| 656 | status = RESULT_SUCCESS; | ||
| 657 | |||
| 658 | frontend.ExitKeyboard(); | ||
| 659 | |||
| 660 | broker.SignalStateChanged(); | ||
| 661 | } | ||
| 662 | |||
| 663 | // Inline Software Keyboard Requests | ||
| 664 | |||
| 665 | void SoftwareKeyboard::RequestFinalize(const std::vector<u8>& request_data) { | ||
| 666 | LOG_DEBUG(Service_AM, "Processing Request: Finalize"); | ||
| 667 | |||
| 668 | ChangeState(SwkbdState::NotInitialized); | ||
| 669 | |||
| 670 | ExitKeyboard(); | ||
| 671 | } | ||
| 672 | |||
| 673 | void SoftwareKeyboard::RequestSetUserWordInfo(const std::vector<u8>& request_data) { | ||
| 674 | LOG_WARNING(Service_AM, "SetUserWordInfo is not implemented."); | ||
| 675 | } | ||
| 676 | |||
| 677 | void SoftwareKeyboard::RequestSetCustomizeDic(const std::vector<u8>& request_data) { | ||
| 678 | LOG_WARNING(Service_AM, "SetCustomizeDic is not implemented."); | ||
| 679 | } | ||
| 680 | |||
| 681 | void SoftwareKeyboard::RequestCalc(const std::vector<u8>& request_data) { | ||
| 682 | LOG_DEBUG(Service_AM, "Processing Request: Calc"); | ||
| 683 | |||
| 684 | ASSERT(request_data.size() == sizeof(SwkbdRequestCommand) + sizeof(SwkbdCalcArg)); | ||
| 685 | |||
| 686 | std::memcpy(&swkbd_calc_arg, request_data.data() + sizeof(SwkbdRequestCommand), | ||
| 687 | sizeof(SwkbdCalcArg)); | ||
| 688 | |||
| 689 | if (swkbd_calc_arg.flags.set_input_text) { | ||
| 690 | current_text = Common::UTF16StringFromFixedZeroTerminatedBuffer( | ||
| 691 | swkbd_calc_arg.input_text.data(), swkbd_calc_arg.input_text.size()); | ||
| 692 | } | ||
| 693 | |||
| 694 | if (swkbd_calc_arg.flags.set_cursor_position) { | ||
| 695 | current_cursor_position = swkbd_calc_arg.cursor_position; | ||
| 696 | } | ||
| 697 | |||
| 698 | if (swkbd_calc_arg.flags.set_utf8_mode) { | ||
| 699 | inline_use_utf8 = swkbd_calc_arg.utf8_mode; | ||
| 700 | } | ||
| 701 | |||
| 702 | if (swkbd_state <= SwkbdState::InitializedIsHidden && | ||
| 703 | swkbd_calc_arg.flags.unset_customize_dic) { | ||
| 704 | ReplyUnsetCustomizeDic(); | ||
| 198 | } | 705 | } |
| 706 | |||
| 707 | if (swkbd_state <= SwkbdState::InitializedIsHidden && | ||
| 708 | swkbd_calc_arg.flags.unset_user_word_info) { | ||
| 709 | ReplyReleasedUserWordInfo(); | ||
| 710 | } | ||
| 711 | |||
| 712 | if (swkbd_state == SwkbdState::NotInitialized && swkbd_calc_arg.flags.set_initialize_arg) { | ||
| 713 | InitializeFrontendKeyboard(); | ||
| 714 | |||
| 715 | ChangeState(SwkbdState::InitializedIsHidden); | ||
| 716 | |||
| 717 | ReplyFinishedInitialize(); | ||
| 718 | } | ||
| 719 | |||
| 720 | if (!swkbd_calc_arg.flags.set_initialize_arg && | ||
| 721 | (swkbd_calc_arg.flags.set_input_text || swkbd_calc_arg.flags.set_cursor_position)) { | ||
| 722 | InlineTextChanged(); | ||
| 723 | } | ||
| 724 | |||
| 725 | if (swkbd_state == SwkbdState::InitializedIsHidden && swkbd_calc_arg.flags.appear) { | ||
| 726 | ShowInlineKeyboard(); | ||
| 727 | return; | ||
| 728 | } | ||
| 729 | |||
| 730 | if (swkbd_state == SwkbdState::InitializedIsShown && swkbd_calc_arg.flags.disappear) { | ||
| 731 | HideInlineKeyboard(); | ||
| 732 | return; | ||
| 733 | } | ||
| 734 | } | ||
| 735 | |||
| 736 | void SoftwareKeyboard::RequestSetCustomizedDictionaries(const std::vector<u8>& request_data) { | ||
| 737 | LOG_WARNING(Service_AM, "SetCustomizedDictionaries is not implemented."); | ||
| 738 | } | ||
| 739 | |||
| 740 | void SoftwareKeyboard::RequestUnsetCustomizedDictionaries(const std::vector<u8>& request_data) { | ||
| 741 | LOG_WARNING(Service_AM, "(STUBBED) Processing Request: UnsetCustomizedDictionaries"); | ||
| 742 | |||
| 743 | ReplyUnsetCustomizedDictionaries(); | ||
| 744 | } | ||
| 745 | |||
| 746 | void SoftwareKeyboard::RequestSetChangedStringV2Flag(const std::vector<u8>& request_data) { | ||
| 747 | LOG_DEBUG(Service_AM, "Processing Request: SetChangedStringV2Flag"); | ||
| 748 | |||
| 749 | ASSERT(request_data.size() == sizeof(SwkbdRequestCommand) + 1); | ||
| 750 | |||
| 751 | std::memcpy(&use_changed_string_v2, request_data.data() + sizeof(SwkbdRequestCommand), 1); | ||
| 752 | } | ||
| 753 | |||
| 754 | void SoftwareKeyboard::RequestSetMovedCursorV2Flag(const std::vector<u8>& request_data) { | ||
| 755 | LOG_DEBUG(Service_AM, "Processing Request: SetMovedCursorV2Flag"); | ||
| 756 | |||
| 757 | ASSERT(request_data.size() == sizeof(SwkbdRequestCommand) + 1); | ||
| 758 | |||
| 759 | std::memcpy(&use_moved_cursor_v2, request_data.data() + sizeof(SwkbdRequestCommand), 1); | ||
| 760 | } | ||
| 761 | |||
| 762 | // Inline Software Keyboard Replies | ||
| 763 | |||
| 764 | void SoftwareKeyboard::ReplyFinishedInitialize() { | ||
| 765 | LOG_DEBUG(Service_AM, "Sending Reply: FinishedInitialize"); | ||
| 766 | |||
| 767 | std::vector<u8> reply(REPLY_BASE_SIZE + 1); | ||
| 768 | |||
| 769 | SetReplyBase(reply, swkbd_state, SwkbdReplyType::FinishedInitialize); | ||
| 770 | |||
| 771 | broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply))); | ||
| 772 | } | ||
| 773 | |||
| 774 | void SoftwareKeyboard::ReplyDefault() { | ||
| 775 | LOG_DEBUG(Service_AM, "Sending Reply: Default"); | ||
| 776 | |||
| 777 | std::vector<u8> reply(REPLY_BASE_SIZE); | ||
| 778 | |||
| 779 | SetReplyBase(reply, swkbd_state, SwkbdReplyType::Default); | ||
| 780 | |||
| 781 | broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply))); | ||
| 782 | } | ||
| 783 | |||
| 784 | void SoftwareKeyboard::ReplyChangedString() { | ||
| 785 | LOG_DEBUG(Service_AM, "Sending Reply: ChangedString"); | ||
| 786 | |||
| 787 | std::vector<u8> reply(REPLY_BASE_SIZE + REPLY_UTF16_SIZE + sizeof(SwkbdChangedStringArg)); | ||
| 788 | |||
| 789 | SetReplyBase(reply, swkbd_state, SwkbdReplyType::ChangedString); | ||
| 790 | |||
| 791 | const SwkbdChangedStringArg changed_string_arg{ | ||
| 792 | .text_length{static_cast<u32>(current_text.size())}, | ||
| 793 | .dictionary_start_cursor_position{-1}, | ||
| 794 | .dictionary_end_cursor_position{-1}, | ||
| 795 | .cursor_position{current_cursor_position}, | ||
| 796 | }; | ||
| 797 | |||
| 798 | std::memcpy(reply.data() + REPLY_BASE_SIZE, current_text.data(), | ||
| 799 | current_text.size() * sizeof(char16_t)); | ||
| 800 | std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE, &changed_string_arg, | ||
| 801 | sizeof(SwkbdChangedStringArg)); | ||
| 802 | |||
| 803 | broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply))); | ||
| 804 | } | ||
| 805 | |||
| 806 | void SoftwareKeyboard::ReplyMovedCursor() { | ||
| 807 | LOG_DEBUG(Service_AM, "Sending Reply: MovedCursor"); | ||
| 808 | |||
| 809 | std::vector<u8> reply(REPLY_BASE_SIZE + REPLY_UTF16_SIZE + sizeof(SwkbdMovedCursorArg)); | ||
| 810 | |||
| 811 | SetReplyBase(reply, swkbd_state, SwkbdReplyType::MovedCursor); | ||
| 812 | |||
| 813 | const SwkbdMovedCursorArg moved_cursor_arg{ | ||
| 814 | .text_length{static_cast<u32>(current_text.size())}, | ||
| 815 | .cursor_position{current_cursor_position}, | ||
| 816 | }; | ||
| 817 | |||
| 818 | std::memcpy(reply.data() + REPLY_BASE_SIZE, current_text.data(), | ||
| 819 | current_text.size() * sizeof(char16_t)); | ||
| 820 | std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE, &moved_cursor_arg, | ||
| 821 | sizeof(SwkbdMovedCursorArg)); | ||
| 822 | |||
| 823 | broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply))); | ||
| 824 | } | ||
| 825 | |||
| 826 | void SoftwareKeyboard::ReplyMovedTab() { | ||
| 827 | LOG_DEBUG(Service_AM, "Sending Reply: MovedTab"); | ||
| 828 | |||
| 829 | std::vector<u8> reply(REPLY_BASE_SIZE + REPLY_UTF16_SIZE + sizeof(SwkbdMovedTabArg)); | ||
| 830 | |||
| 831 | SetReplyBase(reply, swkbd_state, SwkbdReplyType::MovedTab); | ||
| 832 | |||
| 833 | const SwkbdMovedTabArg moved_tab_arg{ | ||
| 834 | .text_length{static_cast<u32>(current_text.size())}, | ||
| 835 | .cursor_position{current_cursor_position}, | ||
| 836 | }; | ||
| 837 | |||
| 838 | std::memcpy(reply.data() + REPLY_BASE_SIZE, current_text.data(), | ||
| 839 | current_text.size() * sizeof(char16_t)); | ||
| 840 | std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE, &moved_tab_arg, | ||
| 841 | sizeof(SwkbdMovedTabArg)); | ||
| 842 | |||
| 843 | broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply))); | ||
| 844 | } | ||
| 845 | |||
| 846 | void SoftwareKeyboard::ReplyDecidedEnter() { | ||
| 847 | LOG_DEBUG(Service_AM, "Sending Reply: DecidedEnter"); | ||
| 848 | |||
| 849 | std::vector<u8> reply(REPLY_BASE_SIZE + REPLY_UTF16_SIZE + sizeof(SwkbdDecidedEnterArg)); | ||
| 850 | |||
| 851 | SetReplyBase(reply, swkbd_state, SwkbdReplyType::DecidedEnter); | ||
| 852 | |||
| 853 | const SwkbdDecidedEnterArg decided_enter_arg{ | ||
| 854 | .text_length{static_cast<u32>(current_text.size())}, | ||
| 855 | }; | ||
| 856 | |||
| 857 | std::memcpy(reply.data() + REPLY_BASE_SIZE, current_text.data(), | ||
| 858 | current_text.size() * sizeof(char16_t)); | ||
| 859 | std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE, &decided_enter_arg, | ||
| 860 | sizeof(SwkbdDecidedEnterArg)); | ||
| 861 | |||
| 862 | broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply))); | ||
| 863 | |||
| 864 | HideInlineKeyboard(); | ||
| 865 | } | ||
| 866 | |||
| 867 | void SoftwareKeyboard::ReplyDecidedCancel() { | ||
| 868 | LOG_DEBUG(Service_AM, "Sending Reply: DecidedCancel"); | ||
| 869 | |||
| 870 | std::vector<u8> reply(REPLY_BASE_SIZE); | ||
| 871 | |||
| 872 | SetReplyBase(reply, swkbd_state, SwkbdReplyType::DecidedCancel); | ||
| 873 | |||
| 874 | broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply))); | ||
| 875 | |||
| 876 | HideInlineKeyboard(); | ||
| 877 | } | ||
| 878 | |||
| 879 | void SoftwareKeyboard::ReplyChangedStringUtf8() { | ||
| 880 | LOG_DEBUG(Service_AM, "Sending Reply: ChangedStringUtf8"); | ||
| 881 | |||
| 882 | std::vector<u8> reply(REPLY_BASE_SIZE + REPLY_UTF8_SIZE + sizeof(SwkbdChangedStringArg)); | ||
| 883 | |||
| 884 | SetReplyBase(reply, swkbd_state, SwkbdReplyType::ChangedStringUtf8); | ||
| 885 | |||
| 886 | std::string utf8_current_text = Common::UTF16ToUTF8(current_text); | ||
| 887 | |||
| 888 | const SwkbdChangedStringArg changed_string_arg{ | ||
| 889 | .text_length{static_cast<u32>(current_text.size())}, | ||
| 890 | .dictionary_start_cursor_position{-1}, | ||
| 891 | .dictionary_end_cursor_position{-1}, | ||
| 892 | .cursor_position{current_cursor_position}, | ||
| 893 | }; | ||
| 894 | |||
| 895 | std::memcpy(reply.data() + REPLY_BASE_SIZE, utf8_current_text.data(), utf8_current_text.size()); | ||
| 896 | std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF8_SIZE, &changed_string_arg, | ||
| 897 | sizeof(SwkbdChangedStringArg)); | ||
| 898 | |||
| 899 | broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply))); | ||
| 199 | } | 900 | } |
| 901 | |||
| 902 | void SoftwareKeyboard::ReplyMovedCursorUtf8() { | ||
| 903 | LOG_DEBUG(Service_AM, "Sending Reply: MovedCursorUtf8"); | ||
| 904 | |||
| 905 | std::vector<u8> reply(REPLY_BASE_SIZE + REPLY_UTF8_SIZE + sizeof(SwkbdMovedCursorArg)); | ||
| 906 | |||
| 907 | SetReplyBase(reply, swkbd_state, SwkbdReplyType::MovedCursorUtf8); | ||
| 908 | |||
| 909 | std::string utf8_current_text = Common::UTF16ToUTF8(current_text); | ||
| 910 | |||
| 911 | const SwkbdMovedCursorArg moved_cursor_arg{ | ||
| 912 | .text_length{static_cast<u32>(current_text.size())}, | ||
| 913 | .cursor_position{current_cursor_position}, | ||
| 914 | }; | ||
| 915 | |||
| 916 | std::memcpy(reply.data() + REPLY_BASE_SIZE, utf8_current_text.data(), utf8_current_text.size()); | ||
| 917 | std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF8_SIZE, &moved_cursor_arg, | ||
| 918 | sizeof(SwkbdMovedCursorArg)); | ||
| 919 | |||
| 920 | broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply))); | ||
| 921 | } | ||
| 922 | |||
| 923 | void SoftwareKeyboard::ReplyDecidedEnterUtf8() { | ||
| 924 | LOG_DEBUG(Service_AM, "Sending Reply: DecidedEnterUtf8"); | ||
| 925 | |||
| 926 | std::vector<u8> reply(REPLY_BASE_SIZE + REPLY_UTF8_SIZE + sizeof(SwkbdDecidedEnterArg)); | ||
| 927 | |||
| 928 | SetReplyBase(reply, swkbd_state, SwkbdReplyType::DecidedEnterUtf8); | ||
| 929 | |||
| 930 | std::string utf8_current_text = Common::UTF16ToUTF8(current_text); | ||
| 931 | |||
| 932 | const SwkbdDecidedEnterArg decided_enter_arg{ | ||
| 933 | .text_length{static_cast<u32>(current_text.size())}, | ||
| 934 | }; | ||
| 935 | |||
| 936 | std::memcpy(reply.data() + REPLY_BASE_SIZE, utf8_current_text.data(), utf8_current_text.size()); | ||
| 937 | std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF8_SIZE, &decided_enter_arg, | ||
| 938 | sizeof(SwkbdDecidedEnterArg)); | ||
| 939 | |||
| 940 | broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply))); | ||
| 941 | |||
| 942 | HideInlineKeyboard(); | ||
| 943 | } | ||
| 944 | |||
| 945 | void SoftwareKeyboard::ReplyUnsetCustomizeDic() { | ||
| 946 | LOG_DEBUG(Service_AM, "Sending Reply: UnsetCustomizeDic"); | ||
| 947 | |||
| 948 | std::vector<u8> reply(REPLY_BASE_SIZE); | ||
| 949 | |||
| 950 | SetReplyBase(reply, swkbd_state, SwkbdReplyType::UnsetCustomizeDic); | ||
| 951 | |||
| 952 | broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply))); | ||
| 953 | } | ||
| 954 | |||
| 955 | void SoftwareKeyboard::ReplyReleasedUserWordInfo() { | ||
| 956 | LOG_DEBUG(Service_AM, "Sending Reply: ReleasedUserWordInfo"); | ||
| 957 | |||
| 958 | std::vector<u8> reply(REPLY_BASE_SIZE); | ||
| 959 | |||
| 960 | SetReplyBase(reply, swkbd_state, SwkbdReplyType::ReleasedUserWordInfo); | ||
| 961 | |||
| 962 | broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply))); | ||
| 963 | } | ||
| 964 | |||
| 965 | void SoftwareKeyboard::ReplyUnsetCustomizedDictionaries() { | ||
| 966 | LOG_DEBUG(Service_AM, "Sending Reply: UnsetCustomizedDictionaries"); | ||
| 967 | |||
| 968 | std::vector<u8> reply(REPLY_BASE_SIZE); | ||
| 969 | |||
| 970 | SetReplyBase(reply, swkbd_state, SwkbdReplyType::UnsetCustomizedDictionaries); | ||
| 971 | |||
| 972 | broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply))); | ||
| 973 | } | ||
| 974 | |||
| 975 | void SoftwareKeyboard::ReplyChangedStringV2() { | ||
| 976 | LOG_DEBUG(Service_AM, "Sending Reply: ChangedStringV2"); | ||
| 977 | |||
| 978 | std::vector<u8> reply(REPLY_BASE_SIZE + REPLY_UTF16_SIZE + sizeof(SwkbdChangedStringArg) + 1); | ||
| 979 | |||
| 980 | SetReplyBase(reply, swkbd_state, SwkbdReplyType::ChangedStringV2); | ||
| 981 | |||
| 982 | const SwkbdChangedStringArg changed_string_arg{ | ||
| 983 | .text_length{static_cast<u32>(current_text.size())}, | ||
| 984 | .dictionary_start_cursor_position{-1}, | ||
| 985 | .dictionary_end_cursor_position{-1}, | ||
| 986 | .cursor_position{current_cursor_position}, | ||
| 987 | }; | ||
| 988 | |||
| 989 | constexpr u8 flag = 0; | ||
| 990 | |||
| 991 | std::memcpy(reply.data() + REPLY_BASE_SIZE, current_text.data(), | ||
| 992 | current_text.size() * sizeof(char16_t)); | ||
| 993 | std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE, &changed_string_arg, | ||
| 994 | sizeof(SwkbdChangedStringArg)); | ||
| 995 | std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE + sizeof(SwkbdChangedStringArg), | ||
| 996 | &flag, 1); | ||
| 997 | |||
| 998 | broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply))); | ||
| 999 | } | ||
| 1000 | |||
| 1001 | void SoftwareKeyboard::ReplyMovedCursorV2() { | ||
| 1002 | LOG_DEBUG(Service_AM, "Sending Reply: MovedCursorV2"); | ||
| 1003 | |||
| 1004 | std::vector<u8> reply(REPLY_BASE_SIZE + REPLY_UTF16_SIZE + sizeof(SwkbdMovedCursorArg) + 1); | ||
| 1005 | |||
| 1006 | SetReplyBase(reply, swkbd_state, SwkbdReplyType::MovedCursorV2); | ||
| 1007 | |||
| 1008 | const SwkbdMovedCursorArg moved_cursor_arg{ | ||
| 1009 | .text_length{static_cast<u32>(current_text.size())}, | ||
| 1010 | .cursor_position{current_cursor_position}, | ||
| 1011 | }; | ||
| 1012 | |||
| 1013 | constexpr u8 flag = 0; | ||
| 1014 | |||
| 1015 | std::memcpy(reply.data() + REPLY_BASE_SIZE, current_text.data(), | ||
| 1016 | current_text.size() * sizeof(char16_t)); | ||
| 1017 | std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE, &moved_cursor_arg, | ||
| 1018 | sizeof(SwkbdMovedCursorArg)); | ||
| 1019 | std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE + sizeof(SwkbdMovedCursorArg), | ||
| 1020 | &flag, 1); | ||
| 1021 | |||
| 1022 | broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply))); | ||
| 1023 | } | ||
| 1024 | |||
| 1025 | void SoftwareKeyboard::ReplyChangedStringUtf8V2() { | ||
| 1026 | LOG_DEBUG(Service_AM, "Sending Reply: ChangedStringUtf8V2"); | ||
| 1027 | |||
| 1028 | std::vector<u8> reply(REPLY_BASE_SIZE + REPLY_UTF8_SIZE + sizeof(SwkbdChangedStringArg) + 1); | ||
| 1029 | |||
| 1030 | SetReplyBase(reply, swkbd_state, SwkbdReplyType::ChangedStringUtf8V2); | ||
| 1031 | |||
| 1032 | std::string utf8_current_text = Common::UTF16ToUTF8(current_text); | ||
| 1033 | |||
| 1034 | const SwkbdChangedStringArg changed_string_arg{ | ||
| 1035 | .text_length{static_cast<u32>(current_text.size())}, | ||
| 1036 | .dictionary_start_cursor_position{-1}, | ||
| 1037 | .dictionary_end_cursor_position{-1}, | ||
| 1038 | .cursor_position{current_cursor_position}, | ||
| 1039 | }; | ||
| 1040 | |||
| 1041 | constexpr u8 flag = 0; | ||
| 1042 | |||
| 1043 | std::memcpy(reply.data() + REPLY_BASE_SIZE, utf8_current_text.data(), utf8_current_text.size()); | ||
| 1044 | std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF8_SIZE, &changed_string_arg, | ||
| 1045 | sizeof(SwkbdChangedStringArg)); | ||
| 1046 | std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF8_SIZE + sizeof(SwkbdChangedStringArg), | ||
| 1047 | &flag, 1); | ||
| 1048 | |||
| 1049 | broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply))); | ||
| 1050 | } | ||
| 1051 | |||
| 1052 | void SoftwareKeyboard::ReplyMovedCursorUtf8V2() { | ||
| 1053 | LOG_DEBUG(Service_AM, "Sending Reply: MovedCursorUtf8V2"); | ||
| 1054 | |||
| 1055 | std::vector<u8> reply(REPLY_BASE_SIZE + REPLY_UTF8_SIZE + sizeof(SwkbdMovedCursorArg) + 1); | ||
| 1056 | |||
| 1057 | SetReplyBase(reply, swkbd_state, SwkbdReplyType::MovedCursorUtf8V2); | ||
| 1058 | |||
| 1059 | std::string utf8_current_text = Common::UTF16ToUTF8(current_text); | ||
| 1060 | |||
| 1061 | const SwkbdMovedCursorArg moved_cursor_arg{ | ||
| 1062 | .text_length{static_cast<u32>(current_text.size())}, | ||
| 1063 | .cursor_position{current_cursor_position}, | ||
| 1064 | }; | ||
| 1065 | |||
| 1066 | constexpr u8 flag = 0; | ||
| 1067 | |||
| 1068 | std::memcpy(reply.data() + REPLY_BASE_SIZE, utf8_current_text.data(), utf8_current_text.size()); | ||
| 1069 | std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF8_SIZE, &moved_cursor_arg, | ||
| 1070 | sizeof(SwkbdMovedCursorArg)); | ||
| 1071 | std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF8_SIZE + sizeof(SwkbdMovedCursorArg), | ||
| 1072 | &flag, 1); | ||
| 1073 | |||
| 1074 | broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply))); | ||
| 1075 | } | ||
| 1076 | |||
| 200 | } // namespace Service::AM::Applets | 1077 | } // namespace Service::AM::Applets |
diff --git a/src/core/hle/service/am/applets/software_keyboard.h b/src/core/hle/service/am/applets/software_keyboard.h index 1d260fef8..85aeb4eb1 100644 --- a/src/core/hle/service/am/applets/software_keyboard.h +++ b/src/core/hle/service/am/applets/software_keyboard.h | |||
| @@ -1,20 +1,14 @@ | |||
| 1 | // Copyright 2018 yuzu emulator team | 1 | // Copyright 2021 yuzu Emulator Project |
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <array> | ||
| 8 | #include <string> | ||
| 9 | #include <vector> | ||
| 10 | |||
| 11 | #include "common/common_funcs.h" | 7 | #include "common/common_funcs.h" |
| 12 | #include "common/common_types.h" | 8 | #include "common/common_types.h" |
| 13 | #include "common/swap.h" | 9 | #include "core/hle/result.h" |
| 14 | #include "core/hle/service/am/am.h" | ||
| 15 | #include "core/hle/service/am/applets/applets.h" | 10 | #include "core/hle/service/am/applets/applets.h" |
| 16 | 11 | #include "core/hle/service/am/applets/software_keyboard_types.h" | |
| 17 | union ResultCode; | ||
| 18 | 12 | ||
| 19 | namespace Core { | 13 | namespace Core { |
| 20 | class System; | 14 | class System; |
| @@ -22,45 +16,10 @@ class System; | |||
| 22 | 16 | ||
| 23 | namespace Service::AM::Applets { | 17 | namespace Service::AM::Applets { |
| 24 | 18 | ||
| 25 | enum class KeysetDisable : u32 { | ||
| 26 | Space = 0x02, | ||
| 27 | Address = 0x04, | ||
| 28 | Percent = 0x08, | ||
| 29 | Slashes = 0x10, | ||
| 30 | Numbers = 0x40, | ||
| 31 | DownloadCode = 0x80, | ||
| 32 | }; | ||
| 33 | |||
| 34 | struct KeyboardConfig { | ||
| 35 | INSERT_PADDING_BYTES(4); | ||
| 36 | std::array<char16_t, 9> submit_text; | ||
| 37 | u16_le left_symbol_key; | ||
| 38 | u16_le right_symbol_key; | ||
| 39 | INSERT_PADDING_BYTES(1); | ||
| 40 | KeysetDisable keyset_disable_bitmask; | ||
| 41 | u32_le initial_cursor_position; | ||
| 42 | std::array<char16_t, 65> header_text; | ||
| 43 | std::array<char16_t, 129> sub_text; | ||
| 44 | std::array<char16_t, 257> guide_text; | ||
| 45 | u32_le length_limit; | ||
| 46 | INSERT_PADDING_BYTES(4); | ||
| 47 | u32_le is_password; | ||
| 48 | INSERT_PADDING_BYTES(5); | ||
| 49 | bool utf_8; | ||
| 50 | bool draw_background; | ||
| 51 | u32_le initial_string_offset; | ||
| 52 | u32_le initial_string_size; | ||
| 53 | u32_le user_dictionary_offset; | ||
| 54 | u32_le user_dictionary_size; | ||
| 55 | bool text_check; | ||
| 56 | u64_le text_check_callback; | ||
| 57 | }; | ||
| 58 | static_assert(sizeof(KeyboardConfig) == 0x3E0, "KeyboardConfig has incorrect size."); | ||
| 59 | |||
| 60 | class SoftwareKeyboard final : public Applet { | 19 | class SoftwareKeyboard final : public Applet { |
| 61 | public: | 20 | public: |
| 62 | explicit SoftwareKeyboard(Core::System& system_, | 21 | explicit SoftwareKeyboard(Core::System& system_, LibraryAppletMode applet_mode_, |
| 63 | const Core::Frontend::SoftwareKeyboardApplet& frontend_); | 22 | Core::Frontend::SoftwareKeyboardApplet& frontend_); |
| 64 | ~SoftwareKeyboard() override; | 23 | ~SoftwareKeyboard() override; |
| 65 | 24 | ||
| 66 | void Initialize() override; | 25 | void Initialize() override; |
| @@ -70,17 +29,139 @@ public: | |||
| 70 | void ExecuteInteractive() override; | 29 | void ExecuteInteractive() override; |
| 71 | void Execute() override; | 30 | void Execute() override; |
| 72 | 31 | ||
| 73 | void WriteText(std::optional<std::u16string> text); | 32 | /** |
| 33 | * Submits the input text to the application. | ||
| 34 | * If text checking is enabled, the application will verify the input text. | ||
| 35 | * If use_utf8 is enabled, the input text will be converted to UTF-8 prior to being submitted. | ||
| 36 | * This should only be used by the normal software keyboard. | ||
| 37 | * | ||
| 38 | * @param result SwkbdResult enum | ||
| 39 | * @param submitted_text UTF-16 encoded string | ||
| 40 | */ | ||
| 41 | void SubmitTextNormal(SwkbdResult result, std::u16string submitted_text); | ||
| 42 | |||
| 43 | /** | ||
| 44 | * Submits the input text to the application. | ||
| 45 | * If utf8_mode is enabled, the input text will be converted to UTF-8 prior to being submitted. | ||
| 46 | * This should only be used by the inline software keyboard. | ||
| 47 | * | ||
| 48 | * @param reply_type SwkbdReplyType enum | ||
| 49 | * @param submitted_text UTF-16 encoded string | ||
| 50 | * @param cursor_position The current position of the text cursor | ||
| 51 | */ | ||
| 52 | void SubmitTextInline(SwkbdReplyType reply_type, std::u16string submitted_text, | ||
| 53 | s32 cursor_position); | ||
| 74 | 54 | ||
| 75 | private: | 55 | private: |
| 76 | const Core::Frontend::SoftwareKeyboardApplet& frontend; | 56 | /// Initializes the normal software keyboard. |
| 57 | void InitializeForeground(); | ||
| 77 | 58 | ||
| 78 | KeyboardConfig config; | 59 | /// Initializes the inline software keyboard. |
| 79 | std::u16string initial_text; | 60 | void InitializeBackground(LibraryAppletMode applet_mode); |
| 80 | bool complete = false; | 61 | |
| 81 | bool is_inline = false; | 62 | /// Processes the text check sent by the application. |
| 82 | std::vector<u8> final_data; | 63 | void ProcessTextCheck(); |
| 64 | |||
| 65 | /// Processes the inline software keyboard request command sent by the application. | ||
| 66 | void ProcessInlineKeyboardRequest(); | ||
| 67 | |||
| 68 | /// Submits the input text and exits the applet. | ||
| 69 | void SubmitNormalOutputAndExit(SwkbdResult result, std::u16string submitted_text); | ||
| 70 | |||
| 71 | /// Submits the input text for text checking. | ||
| 72 | void SubmitForTextCheck(std::u16string submitted_text); | ||
| 73 | |||
| 74 | /// Sends a reply to the application after processing a request command. | ||
| 75 | void SendReply(SwkbdReplyType reply_type); | ||
| 76 | |||
| 77 | /// Changes the inline keyboard state. | ||
| 78 | void ChangeState(SwkbdState state); | ||
| 79 | |||
| 80 | /** | ||
| 81 | * Signals the frontend to initialize the software keyboard with common parameters. | ||
| 82 | * This initializes either the normal software keyboard or the inline software keyboard | ||
| 83 | * depending on the state of is_background. | ||
| 84 | * Note that this does not cause the keyboard to appear. | ||
| 85 | * Use the respective Show*Keyboard() functions to cause the respective keyboards to appear. | ||
| 86 | */ | ||
| 87 | void InitializeFrontendKeyboard(); | ||
| 88 | |||
| 89 | /// Signals the frontend to show the normal software keyboard. | ||
| 90 | void ShowNormalKeyboard(); | ||
| 91 | |||
| 92 | /// Signals the frontend to show the text check dialog. | ||
| 93 | void ShowTextCheckDialog(SwkbdTextCheckResult text_check_result, | ||
| 94 | std::u16string text_check_message); | ||
| 95 | |||
| 96 | /// Signals the frontend to show the inline software keyboard. | ||
| 97 | void ShowInlineKeyboard(); | ||
| 98 | |||
| 99 | /// Signals the frontend to hide the inline software keyboard. | ||
| 100 | void HideInlineKeyboard(); | ||
| 101 | |||
| 102 | /// Signals the frontend that the current inline keyboard text has changed. | ||
| 103 | void InlineTextChanged(); | ||
| 104 | |||
| 105 | /// Signals both the frontend and application that the software keyboard is exiting. | ||
| 106 | void ExitKeyboard(); | ||
| 107 | |||
| 108 | // Inline Software Keyboard Requests | ||
| 109 | |||
| 110 | void RequestFinalize(const std::vector<u8>& request_data); | ||
| 111 | void RequestSetUserWordInfo(const std::vector<u8>& request_data); | ||
| 112 | void RequestSetCustomizeDic(const std::vector<u8>& request_data); | ||
| 113 | void RequestCalc(const std::vector<u8>& request_data); | ||
| 114 | void RequestSetCustomizedDictionaries(const std::vector<u8>& request_data); | ||
| 115 | void RequestUnsetCustomizedDictionaries(const std::vector<u8>& request_data); | ||
| 116 | void RequestSetChangedStringV2Flag(const std::vector<u8>& request_data); | ||
| 117 | void RequestSetMovedCursorV2Flag(const std::vector<u8>& request_data); | ||
| 118 | |||
| 119 | // Inline Software Keyboard Replies | ||
| 120 | |||
| 121 | void ReplyFinishedInitialize(); | ||
| 122 | void ReplyDefault(); | ||
| 123 | void ReplyChangedString(); | ||
| 124 | void ReplyMovedCursor(); | ||
| 125 | void ReplyMovedTab(); | ||
| 126 | void ReplyDecidedEnter(); | ||
| 127 | void ReplyDecidedCancel(); | ||
| 128 | void ReplyChangedStringUtf8(); | ||
| 129 | void ReplyMovedCursorUtf8(); | ||
| 130 | void ReplyDecidedEnterUtf8(); | ||
| 131 | void ReplyUnsetCustomizeDic(); | ||
| 132 | void ReplyReleasedUserWordInfo(); | ||
| 133 | void ReplyUnsetCustomizedDictionaries(); | ||
| 134 | void ReplyChangedStringV2(); | ||
| 135 | void ReplyMovedCursorV2(); | ||
| 136 | void ReplyChangedStringUtf8V2(); | ||
| 137 | void ReplyMovedCursorUtf8V2(); | ||
| 138 | |||
| 139 | LibraryAppletMode applet_mode; | ||
| 140 | Core::Frontend::SoftwareKeyboardApplet& frontend; | ||
| 83 | Core::System& system; | 141 | Core::System& system; |
| 142 | |||
| 143 | SwkbdAppletVersion swkbd_applet_version; | ||
| 144 | |||
| 145 | SwkbdConfigCommon swkbd_config_common; | ||
| 146 | SwkbdConfigOld swkbd_config_old; | ||
| 147 | SwkbdConfigOld2 swkbd_config_old2; | ||
| 148 | SwkbdConfigNew swkbd_config_new; | ||
| 149 | std::u16string initial_text; | ||
| 150 | |||
| 151 | SwkbdState swkbd_state{SwkbdState::NotInitialized}; | ||
| 152 | SwkbdInitializeArg swkbd_initialize_arg; | ||
| 153 | SwkbdCalcArg swkbd_calc_arg; | ||
| 154 | bool use_changed_string_v2{false}; | ||
| 155 | bool use_moved_cursor_v2{false}; | ||
| 156 | bool inline_use_utf8{false}; | ||
| 157 | s32 current_cursor_position{}; | ||
| 158 | |||
| 159 | std::u16string current_text; | ||
| 160 | |||
| 161 | bool is_background{false}; | ||
| 162 | |||
| 163 | bool complete{false}; | ||
| 164 | ResultCode status{RESULT_SUCCESS}; | ||
| 84 | }; | 165 | }; |
| 85 | 166 | ||
| 86 | } // namespace Service::AM::Applets | 167 | } // namespace Service::AM::Applets |
diff --git a/src/core/hle/service/am/applets/software_keyboard_types.h b/src/core/hle/service/am/applets/software_keyboard_types.h new file mode 100644 index 000000000..21aa8e800 --- /dev/null +++ b/src/core/hle/service/am/applets/software_keyboard_types.h | |||
| @@ -0,0 +1,295 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <array> | ||
| 8 | |||
| 9 | #include "common/bit_field.h" | ||
| 10 | #include "common/common_funcs.h" | ||
| 11 | #include "common/common_types.h" | ||
| 12 | #include "common/swap.h" | ||
| 13 | |||
| 14 | namespace Service::AM::Applets { | ||
| 15 | |||
| 16 | constexpr std::size_t MAX_OK_TEXT_LENGTH = 8; | ||
| 17 | constexpr std::size_t MAX_HEADER_TEXT_LENGTH = 64; | ||
| 18 | constexpr std::size_t MAX_SUB_TEXT_LENGTH = 128; | ||
| 19 | constexpr std::size_t MAX_GUIDE_TEXT_LENGTH = 256; | ||
| 20 | constexpr std::size_t STRING_BUFFER_SIZE = 0x7D4; | ||
| 21 | |||
| 22 | enum class SwkbdAppletVersion : u32_le { | ||
| 23 | Version5 = 0x5, // 1.0.0 | ||
| 24 | Version65542 = 0x10006, // 2.0.0 - 2.3.0 | ||
| 25 | Version196615 = 0x30007, // 3.0.0 - 3.0.2 | ||
| 26 | Version262152 = 0x40008, // 4.0.0 - 4.1.0 | ||
| 27 | Version327689 = 0x50009, // 5.0.0 - 5.1.0 | ||
| 28 | Version393227 = 0x6000B, // 6.0.0 - 7.0.1 | ||
| 29 | Version524301 = 0x8000D, // 8.0.0+ | ||
| 30 | }; | ||
| 31 | |||
| 32 | enum class SwkbdType : u32 { | ||
| 33 | Normal, | ||
| 34 | NumberPad, | ||
| 35 | Qwerty, | ||
| 36 | Unknown3, | ||
| 37 | Latin, | ||
| 38 | SimplifiedChinese, | ||
| 39 | TraditionalChinese, | ||
| 40 | Korean, | ||
| 41 | }; | ||
| 42 | |||
| 43 | enum class SwkbdInitialCursorPosition : u32 { | ||
| 44 | Start, | ||
| 45 | End, | ||
| 46 | }; | ||
| 47 | |||
| 48 | enum class SwkbdPasswordMode : u32 { | ||
| 49 | Disabled, | ||
| 50 | Enabled, | ||
| 51 | }; | ||
| 52 | |||
| 53 | enum class SwkbdTextDrawType : u32 { | ||
| 54 | Line, | ||
| 55 | Box, | ||
| 56 | DownloadCode, | ||
| 57 | }; | ||
| 58 | |||
| 59 | enum class SwkbdResult : u32 { | ||
| 60 | Ok, | ||
| 61 | Cancel, | ||
| 62 | }; | ||
| 63 | |||
| 64 | enum class SwkbdTextCheckResult : u32 { | ||
| 65 | Success, | ||
| 66 | Failure, | ||
| 67 | Confirm, | ||
| 68 | Silent, | ||
| 69 | }; | ||
| 70 | |||
| 71 | enum class SwkbdState : u32 { | ||
| 72 | NotInitialized = 0x0, | ||
| 73 | InitializedIsHidden = 0x1, | ||
| 74 | InitializedIsAppearing = 0x2, | ||
| 75 | InitializedIsShown = 0x3, | ||
| 76 | InitializedIsDisappearing = 0x4, | ||
| 77 | }; | ||
| 78 | |||
| 79 | enum class SwkbdRequestCommand : u32 { | ||
| 80 | Finalize = 0x4, | ||
| 81 | SetUserWordInfo = 0x6, | ||
| 82 | SetCustomizeDic = 0x7, | ||
| 83 | Calc = 0xA, | ||
| 84 | SetCustomizedDictionaries = 0xB, | ||
| 85 | UnsetCustomizedDictionaries = 0xC, | ||
| 86 | SetChangedStringV2Flag = 0xD, | ||
| 87 | SetMovedCursorV2Flag = 0xE, | ||
| 88 | }; | ||
| 89 | |||
| 90 | enum class SwkbdReplyType : u32 { | ||
| 91 | FinishedInitialize = 0x0, | ||
| 92 | Default = 0x1, | ||
| 93 | ChangedString = 0x2, | ||
| 94 | MovedCursor = 0x3, | ||
| 95 | MovedTab = 0x4, | ||
| 96 | DecidedEnter = 0x5, | ||
| 97 | DecidedCancel = 0x6, | ||
| 98 | ChangedStringUtf8 = 0x7, | ||
| 99 | MovedCursorUtf8 = 0x8, | ||
| 100 | DecidedEnterUtf8 = 0x9, | ||
| 101 | UnsetCustomizeDic = 0xA, | ||
| 102 | ReleasedUserWordInfo = 0xB, | ||
| 103 | UnsetCustomizedDictionaries = 0xC, | ||
| 104 | ChangedStringV2 = 0xD, | ||
| 105 | MovedCursorV2 = 0xE, | ||
| 106 | ChangedStringUtf8V2 = 0xF, | ||
| 107 | MovedCursorUtf8V2 = 0x10, | ||
| 108 | }; | ||
| 109 | |||
| 110 | struct SwkbdKeyDisableFlags { | ||
| 111 | union { | ||
| 112 | u32 raw{}; | ||
| 113 | |||
| 114 | BitField<1, 1, u32> space; | ||
| 115 | BitField<2, 1, u32> at; | ||
| 116 | BitField<3, 1, u32> percent; | ||
| 117 | BitField<4, 1, u32> slash; | ||
| 118 | BitField<5, 1, u32> backslash; | ||
| 119 | BitField<6, 1, u32> numbers; | ||
| 120 | BitField<7, 1, u32> download_code; | ||
| 121 | BitField<8, 1, u32> username; | ||
| 122 | }; | ||
| 123 | }; | ||
| 124 | static_assert(sizeof(SwkbdKeyDisableFlags) == 0x4, "SwkbdKeyDisableFlags has incorrect size."); | ||
| 125 | |||
| 126 | struct SwkbdConfigCommon { | ||
| 127 | SwkbdType type{}; | ||
| 128 | std::array<char16_t, MAX_OK_TEXT_LENGTH + 1> ok_text{}; | ||
| 129 | char16_t left_optional_symbol_key{}; | ||
| 130 | char16_t right_optional_symbol_key{}; | ||
| 131 | bool use_prediction{}; | ||
| 132 | INSERT_PADDING_BYTES(1); | ||
| 133 | SwkbdKeyDisableFlags key_disable_flags{}; | ||
| 134 | SwkbdInitialCursorPosition initial_cursor_position{}; | ||
| 135 | std::array<char16_t, MAX_HEADER_TEXT_LENGTH + 1> header_text{}; | ||
| 136 | std::array<char16_t, MAX_SUB_TEXT_LENGTH + 1> sub_text{}; | ||
| 137 | std::array<char16_t, MAX_GUIDE_TEXT_LENGTH + 1> guide_text{}; | ||
| 138 | u32 max_text_length{}; | ||
| 139 | u32 min_text_length{}; | ||
| 140 | SwkbdPasswordMode password_mode{}; | ||
| 141 | SwkbdTextDrawType text_draw_type{}; | ||
| 142 | bool enable_return_button{}; | ||
| 143 | bool use_utf8{}; | ||
| 144 | bool use_blur_background{}; | ||
| 145 | INSERT_PADDING_BYTES(1); | ||
| 146 | u32 initial_string_offset{}; | ||
| 147 | u32 initial_string_length{}; | ||
| 148 | u32 user_dictionary_offset{}; | ||
| 149 | u32 user_dictionary_entries{}; | ||
| 150 | bool use_text_check{}; | ||
| 151 | INSERT_PADDING_BYTES(3); | ||
| 152 | }; | ||
| 153 | static_assert(sizeof(SwkbdConfigCommon) == 0x3D4, "SwkbdConfigCommon has incorrect size."); | ||
| 154 | |||
| 155 | #pragma pack(push, 4) | ||
| 156 | // SwkbdAppletVersion 0x5, 0x10006 | ||
| 157 | struct SwkbdConfigOld { | ||
| 158 | INSERT_PADDING_WORDS(1); | ||
| 159 | VAddr text_check_callback{}; | ||
| 160 | }; | ||
| 161 | static_assert(sizeof(SwkbdConfigOld) == 0x3E0 - sizeof(SwkbdConfigCommon), | ||
| 162 | "SwkbdConfigOld has incorrect size."); | ||
| 163 | |||
| 164 | // SwkbdAppletVersion 0x30007, 0x40008, 0x50009 | ||
| 165 | struct SwkbdConfigOld2 { | ||
| 166 | INSERT_PADDING_WORDS(1); | ||
| 167 | VAddr text_check_callback{}; | ||
| 168 | std::array<u32, 8> text_grouping{}; | ||
| 169 | }; | ||
| 170 | static_assert(sizeof(SwkbdConfigOld2) == 0x400 - sizeof(SwkbdConfigCommon), | ||
| 171 | "SwkbdConfigOld2 has incorrect size."); | ||
| 172 | |||
| 173 | // SwkbdAppletVersion 0x6000B, 0x8000D | ||
| 174 | struct SwkbdConfigNew { | ||
| 175 | std::array<u32, 8> text_grouping{}; | ||
| 176 | std::array<u64, 24> customized_dictionary_set_entries{}; | ||
| 177 | u8 total_customized_dictionary_set_entries{}; | ||
| 178 | bool disable_cancel_button{}; | ||
| 179 | INSERT_PADDING_BYTES(18); | ||
| 180 | }; | ||
| 181 | static_assert(sizeof(SwkbdConfigNew) == 0x4C8 - sizeof(SwkbdConfigCommon), | ||
| 182 | "SwkbdConfigNew has incorrect size."); | ||
| 183 | #pragma pack(pop) | ||
| 184 | |||
| 185 | struct SwkbdTextCheck { | ||
| 186 | SwkbdTextCheckResult text_check_result{}; | ||
| 187 | std::array<char16_t, STRING_BUFFER_SIZE / 2> text_check_message{}; | ||
| 188 | }; | ||
| 189 | static_assert(sizeof(SwkbdTextCheck) == 0x7D8, "SwkbdTextCheck has incorrect size."); | ||
| 190 | |||
| 191 | struct SwkbdCalcArgFlags { | ||
| 192 | union { | ||
| 193 | u64 raw{}; | ||
| 194 | |||
| 195 | BitField<0, 1, u64> set_initialize_arg; | ||
| 196 | BitField<1, 1, u64> set_volume; | ||
| 197 | BitField<2, 1, u64> appear; | ||
| 198 | BitField<3, 1, u64> set_input_text; | ||
| 199 | BitField<4, 1, u64> set_cursor_position; | ||
| 200 | BitField<5, 1, u64> set_utf8_mode; | ||
| 201 | BitField<6, 1, u64> unset_customize_dic; | ||
| 202 | BitField<7, 1, u64> disappear; | ||
| 203 | BitField<8, 1, u64> unknown; | ||
| 204 | BitField<9, 1, u64> set_key_top_translate_scale; | ||
| 205 | BitField<10, 1, u64> unset_user_word_info; | ||
| 206 | BitField<11, 1, u64> set_disable_hardware_keyboard; | ||
| 207 | }; | ||
| 208 | }; | ||
| 209 | static_assert(sizeof(SwkbdCalcArgFlags) == 0x8, "SwkbdCalcArgFlags has incorrect size."); | ||
| 210 | |||
| 211 | struct SwkbdInitializeArg { | ||
| 212 | u32 unknown{}; | ||
| 213 | bool library_applet_mode_flag{}; | ||
| 214 | bool is_above_hos_500{}; | ||
| 215 | INSERT_PADDING_BYTES(2); | ||
| 216 | }; | ||
| 217 | static_assert(sizeof(SwkbdInitializeArg) == 0x8, "SwkbdInitializeArg has incorrect size."); | ||
| 218 | |||
| 219 | struct SwkbdAppearArg { | ||
| 220 | SwkbdType type{}; | ||
| 221 | std::array<char16_t, MAX_OK_TEXT_LENGTH + 1> ok_text{}; | ||
| 222 | char16_t left_optional_symbol_key{}; | ||
| 223 | char16_t right_optional_symbol_key{}; | ||
| 224 | bool use_prediction{}; | ||
| 225 | bool disable_cancel_button{}; | ||
| 226 | SwkbdKeyDisableFlags key_disable_flags{}; | ||
| 227 | u32 max_text_length{}; | ||
| 228 | u32 min_text_length{}; | ||
| 229 | bool enable_return_button{}; | ||
| 230 | INSERT_PADDING_BYTES(3); | ||
| 231 | u32 flags{}; | ||
| 232 | INSERT_PADDING_WORDS(6); | ||
| 233 | }; | ||
| 234 | static_assert(sizeof(SwkbdAppearArg) == 0x48, "SwkbdAppearArg has incorrect size."); | ||
| 235 | |||
| 236 | struct SwkbdCalcArg { | ||
| 237 | u32 unknown{}; | ||
| 238 | u16 calc_arg_size{}; | ||
| 239 | INSERT_PADDING_BYTES(2); | ||
| 240 | SwkbdCalcArgFlags flags{}; | ||
| 241 | SwkbdInitializeArg initialize_arg{}; | ||
| 242 | f32 volume{}; | ||
| 243 | s32 cursor_position{}; | ||
| 244 | SwkbdAppearArg appear_arg{}; | ||
| 245 | std::array<char16_t, 0x1FA> input_text{}; | ||
| 246 | bool utf8_mode{}; | ||
| 247 | INSERT_PADDING_BYTES(1); | ||
| 248 | bool enable_backspace_button{}; | ||
| 249 | INSERT_PADDING_BYTES(3); | ||
| 250 | bool key_top_as_floating{}; | ||
| 251 | bool footer_scalable{}; | ||
| 252 | bool alpha_enabled_in_input_mode{}; | ||
| 253 | u8 input_mode_fade_type{}; | ||
| 254 | bool disable_touch{}; | ||
| 255 | bool disable_hardware_keyboard{}; | ||
| 256 | INSERT_PADDING_BYTES(8); | ||
| 257 | f32 key_top_scale_x{}; | ||
| 258 | f32 key_top_scale_y{}; | ||
| 259 | f32 key_top_translate_x{}; | ||
| 260 | f32 key_top_translate_y{}; | ||
| 261 | f32 key_top_bg_alpha{}; | ||
| 262 | f32 footer_bg_alpha{}; | ||
| 263 | f32 balloon_scale{}; | ||
| 264 | INSERT_PADDING_WORDS(4); | ||
| 265 | u8 se_group{}; | ||
| 266 | INSERT_PADDING_BYTES(3); | ||
| 267 | }; | ||
| 268 | static_assert(sizeof(SwkbdCalcArg) == 0x4A0, "SwkbdCalcArg has incorrect size."); | ||
| 269 | |||
| 270 | struct SwkbdChangedStringArg { | ||
| 271 | u32 text_length{}; | ||
| 272 | s32 dictionary_start_cursor_position{}; | ||
| 273 | s32 dictionary_end_cursor_position{}; | ||
| 274 | s32 cursor_position{}; | ||
| 275 | }; | ||
| 276 | static_assert(sizeof(SwkbdChangedStringArg) == 0x10, "SwkbdChangedStringArg has incorrect size."); | ||
| 277 | |||
| 278 | struct SwkbdMovedCursorArg { | ||
| 279 | u32 text_length{}; | ||
| 280 | s32 cursor_position{}; | ||
| 281 | }; | ||
| 282 | static_assert(sizeof(SwkbdMovedCursorArg) == 0x8, "SwkbdMovedCursorArg has incorrect size."); | ||
| 283 | |||
| 284 | struct SwkbdMovedTabArg { | ||
| 285 | u32 text_length{}; | ||
| 286 | s32 cursor_position{}; | ||
| 287 | }; | ||
| 288 | static_assert(sizeof(SwkbdMovedTabArg) == 0x8, "SwkbdMovedTabArg has incorrect size."); | ||
| 289 | |||
| 290 | struct SwkbdDecidedEnterArg { | ||
| 291 | u32 text_length{}; | ||
| 292 | }; | ||
| 293 | static_assert(sizeof(SwkbdDecidedEnterArg) == 0x4, "SwkbdDecidedEnterArg has incorrect size."); | ||
| 294 | |||
| 295 | } // namespace Service::AM::Applets | ||
diff --git a/src/core/hle/service/am/applets/web_browser.cpp b/src/core/hle/service/am/applets/web_browser.cpp index 2ab420789..b28b849bc 100644 --- a/src/core/hle/service/am/applets/web_browser.cpp +++ b/src/core/hle/service/am/applets/web_browser.cpp | |||
| @@ -208,8 +208,9 @@ void ExtractSharedFonts(Core::System& system) { | |||
| 208 | 208 | ||
| 209 | } // namespace | 209 | } // namespace |
| 210 | 210 | ||
| 211 | WebBrowser::WebBrowser(Core::System& system_, const Core::Frontend::WebBrowserApplet& frontend_) | 211 | WebBrowser::WebBrowser(Core::System& system_, LibraryAppletMode applet_mode_, |
| 212 | : Applet{system_.Kernel()}, frontend(frontend_), system{system_} {} | 212 | const Core::Frontend::WebBrowserApplet& frontend_) |
| 213 | : Applet{system_.Kernel()}, applet_mode{applet_mode_}, frontend(frontend_), system{system_} {} | ||
| 213 | 214 | ||
| 214 | WebBrowser::~WebBrowser() = default; | 215 | WebBrowser::~WebBrowser() = default; |
| 215 | 216 | ||
diff --git a/src/core/hle/service/am/applets/web_browser.h b/src/core/hle/service/am/applets/web_browser.h index 04c274754..5eafbae7b 100644 --- a/src/core/hle/service/am/applets/web_browser.h +++ b/src/core/hle/service/am/applets/web_browser.h | |||
| @@ -25,7 +25,8 @@ namespace Service::AM::Applets { | |||
| 25 | 25 | ||
| 26 | class WebBrowser final : public Applet { | 26 | class WebBrowser final : public Applet { |
| 27 | public: | 27 | public: |
| 28 | WebBrowser(Core::System& system_, const Core::Frontend::WebBrowserApplet& frontend_); | 28 | WebBrowser(Core::System& system_, LibraryAppletMode applet_mode_, |
| 29 | const Core::Frontend::WebBrowserApplet& frontend_); | ||
| 29 | 30 | ||
| 30 | ~WebBrowser() override; | 31 | ~WebBrowser() override; |
| 31 | 32 | ||
| @@ -63,6 +64,7 @@ private: | |||
| 63 | void ExecuteWifi(); | 64 | void ExecuteWifi(); |
| 64 | void ExecuteLobby(); | 65 | void ExecuteLobby(); |
| 65 | 66 | ||
| 67 | LibraryAppletMode applet_mode; | ||
| 66 | const Core::Frontend::WebBrowserApplet& frontend; | 68 | const Core::Frontend::WebBrowserApplet& frontend; |
| 67 | 69 | ||
| 68 | bool complete{false}; | 70 | bool complete{false}; |
diff --git a/src/core/hle/service/aoc/aoc_u.cpp b/src/core/hle/service/aoc/aoc_u.cpp index 8d657c0bf..75867e349 100644 --- a/src/core/hle/service/aoc/aoc_u.cpp +++ b/src/core/hle/service/aoc/aoc_u.cpp | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include <vector> | 7 | #include <vector> |
| 8 | 8 | ||
| 9 | #include "common/logging/log.h" | 9 | #include "common/logging/log.h" |
| 10 | #include "common/settings.h" | ||
| 10 | #include "core/core.h" | 11 | #include "core/core.h" |
| 11 | #include "core/file_sys/common_funcs.h" | 12 | #include "core/file_sys/common_funcs.h" |
| 12 | #include "core/file_sys/content_archive.h" | 13 | #include "core/file_sys/content_archive.h" |
| @@ -21,7 +22,6 @@ | |||
| 21 | #include "core/hle/kernel/process.h" | 22 | #include "core/hle/kernel/process.h" |
| 22 | #include "core/hle/service/aoc/aoc_u.h" | 23 | #include "core/hle/service/aoc/aoc_u.h" |
| 23 | #include "core/loader/loader.h" | 24 | #include "core/loader/loader.h" |
| 24 | #include "core/settings.h" | ||
| 25 | 25 | ||
| 26 | namespace Service::AOC { | 26 | namespace Service::AOC { |
| 27 | 27 | ||
| @@ -118,8 +118,10 @@ AOC_U::AOC_U(Core::System& system_) | |||
| 118 | {7, &AOC_U::PrepareAddOnContent, "PrepareAddOnContent"}, | 118 | {7, &AOC_U::PrepareAddOnContent, "PrepareAddOnContent"}, |
| 119 | {8, &AOC_U::GetAddOnContentListChangedEvent, "GetAddOnContentListChangedEvent"}, | 119 | {8, &AOC_U::GetAddOnContentListChangedEvent, "GetAddOnContentListChangedEvent"}, |
| 120 | {9, nullptr, "GetAddOnContentLostErrorCode"}, | 120 | {9, nullptr, "GetAddOnContentLostErrorCode"}, |
| 121 | {10, nullptr, "GetAddOnContentListChangedEventWithProcessId"}, | ||
| 121 | {100, &AOC_U::CreateEcPurchasedEventManager, "CreateEcPurchasedEventManager"}, | 122 | {100, &AOC_U::CreateEcPurchasedEventManager, "CreateEcPurchasedEventManager"}, |
| 122 | {101, &AOC_U::CreatePermanentEcPurchasedEventManager, "CreatePermanentEcPurchasedEventManager"}, | 123 | {101, &AOC_U::CreatePermanentEcPurchasedEventManager, "CreatePermanentEcPurchasedEventManager"}, |
| 124 | {110, nullptr, "CreateContentsServiceManager"}, | ||
| 123 | }; | 125 | }; |
| 124 | // clang-format on | 126 | // clang-format on |
| 125 | 127 | ||
diff --git a/src/core/hle/service/apm/controller.cpp b/src/core/hle/service/apm/controller.cpp index 03636642b..00c174bb0 100644 --- a/src/core/hle/service/apm/controller.cpp +++ b/src/core/hle/service/apm/controller.cpp | |||
| @@ -7,9 +7,9 @@ | |||
| 7 | #include <utility> | 7 | #include <utility> |
| 8 | 8 | ||
| 9 | #include "common/logging/log.h" | 9 | #include "common/logging/log.h" |
| 10 | #include "common/settings.h" | ||
| 10 | #include "core/core_timing.h" | 11 | #include "core/core_timing.h" |
| 11 | #include "core/hle/service/apm/controller.h" | 12 | #include "core/hle/service/apm/controller.h" |
| 12 | #include "core/settings.h" | ||
| 13 | 13 | ||
| 14 | namespace Service::APM { | 14 | namespace Service::APM { |
| 15 | 15 | ||
diff --git a/src/core/hle/service/audio/audin_a.cpp b/src/core/hle/service/audio/audin_a.cpp index 79c3aa920..10acaad19 100644 --- a/src/core/hle/service/audio/audin_a.cpp +++ b/src/core/hle/service/audio/audin_a.cpp | |||
| @@ -9,10 +9,10 @@ namespace Service::Audio { | |||
| 9 | AudInA::AudInA(Core::System& system_) : ServiceFramework{system_, "audin:a"} { | 9 | AudInA::AudInA(Core::System& system_) : ServiceFramework{system_, "audin:a"} { |
| 10 | // clang-format off | 10 | // clang-format off |
| 11 | static const FunctionInfo functions[] = { | 11 | static const FunctionInfo functions[] = { |
| 12 | {0, nullptr, "RequestSuspendAudioIns"}, | 12 | {0, nullptr, "RequestSuspend"}, |
| 13 | {1, nullptr, "RequestResumeAudioIns"}, | 13 | {1, nullptr, "RequestResume"}, |
| 14 | {2, nullptr, "GetAudioInsProcessMasterVolume"}, | 14 | {2, nullptr, "GetProcessMasterVolume"}, |
| 15 | {3, nullptr, "SetAudioInsProcessMasterVolume"}, | 15 | {3, nullptr, "SetProcessMasterVolume"}, |
| 16 | }; | 16 | }; |
| 17 | // clang-format on | 17 | // clang-format on |
| 18 | 18 | ||
diff --git a/src/core/hle/service/audio/audin_u.cpp b/src/core/hle/service/audio/audin_u.cpp index 26a6deddf..ecd05e4a6 100644 --- a/src/core/hle/service/audio/audin_u.cpp +++ b/src/core/hle/service/audio/audin_u.cpp | |||
| @@ -15,19 +15,19 @@ public: | |||
| 15 | // clang-format off | 15 | // clang-format off |
| 16 | static const FunctionInfo functions[] = { | 16 | static const FunctionInfo functions[] = { |
| 17 | {0, nullptr, "GetAudioInState"}, | 17 | {0, nullptr, "GetAudioInState"}, |
| 18 | {1, nullptr, "StartAudioIn"}, | 18 | {1, nullptr, "Start"}, |
| 19 | {2, nullptr, "StopAudioIn"}, | 19 | {2, nullptr, "Stop"}, |
| 20 | {3, nullptr, "AppendAudioInBuffer"}, | 20 | {3, nullptr, "AppendAudioInBuffer"}, |
| 21 | {4, nullptr, "RegisterBufferEvent"}, | 21 | {4, nullptr, "RegisterBufferEvent"}, |
| 22 | {5, nullptr, "GetReleasedAudioInBuffer"}, | 22 | {5, nullptr, "GetReleasedAudioInBuffer"}, |
| 23 | {6, nullptr, "ContainsAudioInBuffer"}, | 23 | {6, nullptr, "ContainsAudioInBuffer"}, |
| 24 | {7, nullptr, "AppendAudioInBufferWithUserEvent"}, | 24 | {7, nullptr, "AppendUacInBuffer"}, |
| 25 | {8, nullptr, "AppendAudioInBufferAuto"}, | 25 | {8, nullptr, "AppendAudioInBufferAuto"}, |
| 26 | {9, nullptr, "GetReleasedAudioInBufferAuto"}, | 26 | {9, nullptr, "GetReleasedAudioInBuffersAuto"}, |
| 27 | {10, nullptr, "AppendAudioInBufferWithUserEventAuto"}, | 27 | {10, nullptr, "AppendUacInBufferAuto"}, |
| 28 | {11, nullptr, "GetAudioInBufferCount"}, | 28 | {11, nullptr, "GetAudioInBufferCount"}, |
| 29 | {12, nullptr, "SetAudioInDeviceGain"}, | 29 | {12, nullptr, "SetDeviceGain"}, |
| 30 | {13, nullptr, "GetAudioInDeviceGain"}, | 30 | {13, nullptr, "GetDeviceGain"}, |
| 31 | {14, nullptr, "FlushAudioInBuffers"}, | 31 | {14, nullptr, "FlushAudioInBuffers"}, |
| 32 | }; | 32 | }; |
| 33 | // clang-format on | 33 | // clang-format on |
diff --git a/src/core/hle/service/audio/audout_a.cpp b/src/core/hle/service/audio/audout_a.cpp index 19825fd5d..3ee522b50 100644 --- a/src/core/hle/service/audio/audout_a.cpp +++ b/src/core/hle/service/audio/audout_a.cpp | |||
| @@ -9,12 +9,12 @@ namespace Service::Audio { | |||
| 9 | AudOutA::AudOutA(Core::System& system_) : ServiceFramework{system_, "audout:a"} { | 9 | AudOutA::AudOutA(Core::System& system_) : ServiceFramework{system_, "audout:a"} { |
| 10 | // clang-format off | 10 | // clang-format off |
| 11 | static const FunctionInfo functions[] = { | 11 | static const FunctionInfo functions[] = { |
| 12 | {0, nullptr, "RequestSuspendAudioOuts"}, | 12 | {0, nullptr, "RequestSuspend"}, |
| 13 | {1, nullptr, "RequestResumeAudioOuts"}, | 13 | {1, nullptr, "RequestResume"}, |
| 14 | {2, nullptr, "GetAudioOutsProcessMasterVolume"}, | 14 | {2, nullptr, "GetProcessMasterVolume"}, |
| 15 | {3, nullptr, "SetAudioOutsProcessMasterVolume"}, | 15 | {3, nullptr, "SetProcessMasterVolume"}, |
| 16 | {4, nullptr, "GetAudioOutsProcessRecordVolume"}, | 16 | {4, nullptr, "GetProcessRecordVolume"}, |
| 17 | {5, nullptr, "SetAudioOutsProcessRecordVolume"}, | 17 | {5, nullptr, "SetProcessRecordVolume"}, |
| 18 | }; | 18 | }; |
| 19 | // clang-format on | 19 | // clang-format on |
| 20 | 20 | ||
diff --git a/src/core/hle/service/audio/audout_u.cpp b/src/core/hle/service/audio/audout_u.cpp index 5ed9cb20e..5f51fca9a 100644 --- a/src/core/hle/service/audio/audout_u.cpp +++ b/src/core/hle/service/audio/audout_u.cpp | |||
| @@ -49,11 +49,11 @@ public: | |||
| 49 | // clang-format off | 49 | // clang-format off |
| 50 | static const FunctionInfo functions[] = { | 50 | static const FunctionInfo functions[] = { |
| 51 | {0, &IAudioOut::GetAudioOutState, "GetAudioOutState"}, | 51 | {0, &IAudioOut::GetAudioOutState, "GetAudioOutState"}, |
| 52 | {1, &IAudioOut::StartAudioOut, "StartAudioOut"}, | 52 | {1, &IAudioOut::StartAudioOut, "Start"}, |
| 53 | {2, &IAudioOut::StopAudioOut, "StopAudioOut"}, | 53 | {2, &IAudioOut::StopAudioOut, "Stop"}, |
| 54 | {3, &IAudioOut::AppendAudioOutBufferImpl, "AppendAudioOutBuffer"}, | 54 | {3, &IAudioOut::AppendAudioOutBufferImpl, "AppendAudioOutBuffer"}, |
| 55 | {4, &IAudioOut::RegisterBufferEvent, "RegisterBufferEvent"}, | 55 | {4, &IAudioOut::RegisterBufferEvent, "RegisterBufferEvent"}, |
| 56 | {5, &IAudioOut::GetReleasedAudioOutBufferImpl, "GetReleasedAudioOutBuffer"}, | 56 | {5, &IAudioOut::GetReleasedAudioOutBufferImpl, "GetReleasedAudioOutBuffers"}, |
| 57 | {6, &IAudioOut::ContainsAudioOutBuffer, "ContainsAudioOutBuffer"}, | 57 | {6, &IAudioOut::ContainsAudioOutBuffer, "ContainsAudioOutBuffer"}, |
| 58 | {7, &IAudioOut::AppendAudioOutBufferImpl, "AppendAudioOutBufferAuto"}, | 58 | {7, &IAudioOut::AppendAudioOutBufferImpl, "AppendAudioOutBufferAuto"}, |
| 59 | {8, &IAudioOut::GetReleasedAudioOutBufferImpl, "GetReleasedAudioOutBufferAuto"}, | 59 | {8, &IAudioOut::GetReleasedAudioOutBufferImpl, "GetReleasedAudioOutBufferAuto"}, |
diff --git a/src/core/hle/service/audio/audrec_a.cpp b/src/core/hle/service/audio/audrec_a.cpp index c5ab7cad4..70fc17ae2 100644 --- a/src/core/hle/service/audio/audrec_a.cpp +++ b/src/core/hle/service/audio/audrec_a.cpp | |||
| @@ -9,8 +9,8 @@ namespace Service::Audio { | |||
| 9 | AudRecA::AudRecA(Core::System& system_) : ServiceFramework{system_, "audrec:a"} { | 9 | AudRecA::AudRecA(Core::System& system_) : ServiceFramework{system_, "audrec:a"} { |
| 10 | // clang-format off | 10 | // clang-format off |
| 11 | static const FunctionInfo functions[] = { | 11 | static const FunctionInfo functions[] = { |
| 12 | {0, nullptr, "RequestSuspendFinalOutputRecorders"}, | 12 | {0, nullptr, "RequestSuspend"}, |
| 13 | {1, nullptr, "RequestResumeFinalOutputRecorders"}, | 13 | {1, nullptr, "RequestResume"}, |
| 14 | }; | 14 | }; |
| 15 | // clang-format on | 15 | // clang-format on |
| 16 | 16 | ||
diff --git a/src/core/hle/service/audio/audrec_u.cpp b/src/core/hle/service/audio/audrec_u.cpp index eb5c63c62..74a65ccff 100644 --- a/src/core/hle/service/audio/audrec_u.cpp +++ b/src/core/hle/service/audio/audrec_u.cpp | |||
| @@ -13,16 +13,17 @@ public: | |||
| 13 | // clang-format off | 13 | // clang-format off |
| 14 | static const FunctionInfo functions[] = { | 14 | static const FunctionInfo functions[] = { |
| 15 | {0, nullptr, "GetFinalOutputRecorderState"}, | 15 | {0, nullptr, "GetFinalOutputRecorderState"}, |
| 16 | {1, nullptr, "StartFinalOutputRecorder"}, | 16 | {1, nullptr, "Start"}, |
| 17 | {2, nullptr, "StopFinalOutputRecorder"}, | 17 | {2, nullptr, "Stop"}, |
| 18 | {3, nullptr, "AppendFinalOutputRecorderBuffer"}, | 18 | {3, nullptr, "AppendFinalOutputRecorderBuffer"}, |
| 19 | {4, nullptr, "RegisterBufferEvent"}, | 19 | {4, nullptr, "RegisterBufferEvent"}, |
| 20 | {5, nullptr, "GetReleasedFinalOutputRecorderBuffer"}, | 20 | {5, nullptr, "GetReleasedFinalOutputRecorderBuffers"}, |
| 21 | {6, nullptr, "ContainsFinalOutputRecorderBuffer"}, | 21 | {6, nullptr, "ContainsFinalOutputRecorderBuffer"}, |
| 22 | {7, nullptr, "GetFinalOutputRecorderBufferEndTime"}, | 22 | {7, nullptr, "GetFinalOutputRecorderBufferEndTime"}, |
| 23 | {8, nullptr, "AppendFinalOutputRecorderBufferAuto"}, | 23 | {8, nullptr, "AppendFinalOutputRecorderBufferAuto"}, |
| 24 | {9, nullptr, "GetReleasedFinalOutputRecorderBufferAuto"}, | 24 | {9, nullptr, "GetReleasedFinalOutputRecorderBufferAuto"}, |
| 25 | {10, nullptr, "FlushFinalOutputRecorderBuffers"}, | 25 | {10, nullptr, "FlushFinalOutputRecorderBuffers"}, |
| 26 | {11, nullptr, "AttachWorkBuffer"}, | ||
| 26 | }; | 27 | }; |
| 27 | // clang-format on | 28 | // clang-format on |
| 28 | 29 | ||
diff --git a/src/core/hle/service/audio/audren_a.cpp b/src/core/hle/service/audio/audren_a.cpp index 5e9f866f0..cf8c34a15 100644 --- a/src/core/hle/service/audio/audren_a.cpp +++ b/src/core/hle/service/audio/audren_a.cpp | |||
| @@ -9,14 +9,14 @@ namespace Service::Audio { | |||
| 9 | AudRenA::AudRenA(Core::System& system_) : ServiceFramework{system_, "audren:a"} { | 9 | AudRenA::AudRenA(Core::System& system_) : ServiceFramework{system_, "audren:a"} { |
| 10 | // clang-format off | 10 | // clang-format off |
| 11 | static const FunctionInfo functions[] = { | 11 | static const FunctionInfo functions[] = { |
| 12 | {0, nullptr, "RequestSuspendAudioRenderers"}, | 12 | {0, nullptr, "RequestSuspend"}, |
| 13 | {1, nullptr, "RequestResumeAudioRenderers"}, | 13 | {1, nullptr, "RequestResume"}, |
| 14 | {2, nullptr, "GetAudioRenderersProcessMasterVolume"}, | 14 | {2, nullptr, "GetProcessMasterVolume"}, |
| 15 | {3, nullptr, "SetAudioRenderersProcessMasterVolume"}, | 15 | {3, nullptr, "SetProcessMasterVolume"}, |
| 16 | {4, nullptr, "RegisterAppletResourceUserId"}, | 16 | {4, nullptr, "RegisterAppletResourceUserId"}, |
| 17 | {5, nullptr, "UnregisterAppletResourceUserId"}, | 17 | {5, nullptr, "UnregisterAppletResourceUserId"}, |
| 18 | {6, nullptr, "GetAudioRenderersProcessRecordVolume"}, | 18 | {6, nullptr, "GetProcessRecordVolume"}, |
| 19 | {7, nullptr, "SetAudioRenderersProcessRecordVolume"}, | 19 | {7, nullptr, "SetProcessRecordVolume"}, |
| 20 | }; | 20 | }; |
| 21 | // clang-format on | 21 | // clang-format on |
| 22 | 22 | ||
diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp index b2b2ffc5a..572be8e00 100644 --- a/src/core/hle/service/audio/audren_u.cpp +++ b/src/core/hle/service/audio/audren_u.cpp | |||
| @@ -332,9 +332,9 @@ AudRenU::AudRenU(Core::System& system_) : ServiceFramework{system_, "audren:u"} | |||
| 332 | // clang-format off | 332 | // clang-format off |
| 333 | static const FunctionInfo functions[] = { | 333 | static const FunctionInfo functions[] = { |
| 334 | {0, &AudRenU::OpenAudioRenderer, "OpenAudioRenderer"}, | 334 | {0, &AudRenU::OpenAudioRenderer, "OpenAudioRenderer"}, |
| 335 | {1, &AudRenU::GetAudioRendererWorkBufferSize, "GetAudioRendererWorkBufferSize"}, | 335 | {1, &AudRenU::GetAudioRendererWorkBufferSize, "GetWorkBufferSize"}, |
| 336 | {2, &AudRenU::GetAudioDeviceService, "GetAudioDeviceService"}, | 336 | {2, &AudRenU::GetAudioDeviceService, "GetAudioDeviceService"}, |
| 337 | {3, &AudRenU::OpenAudioRendererAuto, "OpenAudioRendererAuto"}, | 337 | {3, &AudRenU::OpenAudioRendererForManualExecution, "OpenAudioRendererForManualExecution"}, |
| 338 | {4, &AudRenU::GetAudioDeviceServiceWithRevisionInfo, "GetAudioDeviceServiceWithRevisionInfo"}, | 338 | {4, &AudRenU::GetAudioDeviceServiceWithRevisionInfo, "GetAudioDeviceServiceWithRevisionInfo"}, |
| 339 | }; | 339 | }; |
| 340 | // clang-format on | 340 | // clang-format on |
| @@ -665,7 +665,7 @@ void AudRenU::GetAudioDeviceService(Kernel::HLERequestContext& ctx) { | |||
| 665 | rb.PushIpcInterface<IAudioDevice>(system, Common::MakeMagic('R', 'E', 'V', '1')); | 665 | rb.PushIpcInterface<IAudioDevice>(system, Common::MakeMagic('R', 'E', 'V', '1')); |
| 666 | } | 666 | } |
| 667 | 667 | ||
| 668 | void AudRenU::OpenAudioRendererAuto(Kernel::HLERequestContext& ctx) { | 668 | void AudRenU::OpenAudioRendererForManualExecution(Kernel::HLERequestContext& ctx) { |
| 669 | LOG_DEBUG(Service_Audio, "called"); | 669 | LOG_DEBUG(Service_Audio, "called"); |
| 670 | 670 | ||
| 671 | OpenAudioRendererImpl(ctx); | 671 | OpenAudioRendererImpl(ctx); |
diff --git a/src/core/hle/service/audio/audren_u.h b/src/core/hle/service/audio/audren_u.h index d693dc406..37e8b4716 100644 --- a/src/core/hle/service/audio/audren_u.h +++ b/src/core/hle/service/audio/audren_u.h | |||
| @@ -25,7 +25,7 @@ private: | |||
| 25 | void OpenAudioRenderer(Kernel::HLERequestContext& ctx); | 25 | void OpenAudioRenderer(Kernel::HLERequestContext& ctx); |
| 26 | void GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx); | 26 | void GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx); |
| 27 | void GetAudioDeviceService(Kernel::HLERequestContext& ctx); | 27 | void GetAudioDeviceService(Kernel::HLERequestContext& ctx); |
| 28 | void OpenAudioRendererAuto(Kernel::HLERequestContext& ctx); | 28 | void OpenAudioRendererForManualExecution(Kernel::HLERequestContext& ctx); |
| 29 | void GetAudioDeviceServiceWithRevisionInfo(Kernel::HLERequestContext& ctx); | 29 | void GetAudioDeviceServiceWithRevisionInfo(Kernel::HLERequestContext& ctx); |
| 30 | 30 | ||
| 31 | void OpenAudioRendererImpl(Kernel::HLERequestContext& ctx); | 31 | void OpenAudioRendererImpl(Kernel::HLERequestContext& ctx); |
diff --git a/src/core/hle/service/audio/codecctl.cpp b/src/core/hle/service/audio/codecctl.cpp index 94afec1b6..42961d908 100644 --- a/src/core/hle/service/audio/codecctl.cpp +++ b/src/core/hle/service/audio/codecctl.cpp | |||
| @@ -8,19 +8,19 @@ namespace Service::Audio { | |||
| 8 | 8 | ||
| 9 | CodecCtl::CodecCtl(Core::System& system_) : ServiceFramework{system_, "codecctl"} { | 9 | CodecCtl::CodecCtl(Core::System& system_) : ServiceFramework{system_, "codecctl"} { |
| 10 | static const FunctionInfo functions[] = { | 10 | static const FunctionInfo functions[] = { |
| 11 | {0, nullptr, "InitializeCodecController"}, | 11 | {0, nullptr, "Initialize"}, |
| 12 | {1, nullptr, "FinalizeCodecController"}, | 12 | {1, nullptr, "Finalize"}, |
| 13 | {2, nullptr, "SleepCodecController"}, | 13 | {2, nullptr, "Sleep"}, |
| 14 | {3, nullptr, "WakeCodecController"}, | 14 | {3, nullptr, "Wake"}, |
| 15 | {4, nullptr, "SetCodecVolume"}, | 15 | {4, nullptr, "SetVolume"}, |
| 16 | {5, nullptr, "GetCodecVolumeMax"}, | 16 | {5, nullptr, "GetVolumeMax"}, |
| 17 | {6, nullptr, "GetCodecVolumeMin"}, | 17 | {6, nullptr, "GetVolumeMin"}, |
| 18 | {7, nullptr, "SetCodecActiveTarget"}, | 18 | {7, nullptr, "SetActiveTarget"}, |
| 19 | {8, nullptr, "GetCodecActiveTarget"}, | 19 | {8, nullptr, "GetActiveTarget"}, |
| 20 | {9, nullptr, "BindCodecHeadphoneMicJackInterrupt"}, | 20 | {9, nullptr, "BindHeadphoneMicJackInterrupt"}, |
| 21 | {10, nullptr, "IsCodecHeadphoneMicJackInserted"}, | 21 | {10, nullptr, "IsHeadphoneMicJackInserted"}, |
| 22 | {11, nullptr, "ClearCodecHeadphoneMicJackInterrupt"}, | 22 | {11, nullptr, "ClearHeadphoneMicJackInterrupt"}, |
| 23 | {12, nullptr, "IsCodecDeviceRequested"}, | 23 | {12, nullptr, "IsRequested"}, |
| 24 | }; | 24 | }; |
| 25 | RegisterHandlers(functions); | 25 | RegisterHandlers(functions); |
| 26 | } | 26 | } |
diff --git a/src/core/hle/service/audio/hwopus.cpp b/src/core/hle/service/audio/hwopus.cpp index ea3414fd2..19c578b3a 100644 --- a/src/core/hle/service/audio/hwopus.cpp +++ b/src/core/hle/service/audio/hwopus.cpp | |||
| @@ -297,6 +297,10 @@ HwOpus::HwOpus(Core::System& system_) : ServiceFramework{system_, "hwopus"} { | |||
| 297 | {1, &HwOpus::GetWorkBufferSize, "GetWorkBufferSize"}, | 297 | {1, &HwOpus::GetWorkBufferSize, "GetWorkBufferSize"}, |
| 298 | {2, nullptr, "OpenOpusDecoderForMultiStream"}, | 298 | {2, nullptr, "OpenOpusDecoderForMultiStream"}, |
| 299 | {3, nullptr, "GetWorkBufferSizeForMultiStream"}, | 299 | {3, nullptr, "GetWorkBufferSizeForMultiStream"}, |
| 300 | {4, nullptr, "OpenHardwareOpusDecoderEx"}, | ||
| 301 | {5, nullptr, "GetWorkBufferSizeEx"}, | ||
| 302 | {6, nullptr, "OpenHardwareOpusDecoderForMultiStreamEx"}, | ||
| 303 | {7, nullptr, "GetWorkBufferSizeForMultiStreamEx"}, | ||
| 300 | }; | 304 | }; |
| 301 | RegisterHandlers(functions); | 305 | RegisterHandlers(functions); |
| 302 | } | 306 | } |
diff --git a/src/core/hle/service/bcat/backend/boxcat.cpp b/src/core/hle/service/bcat/backend/boxcat.cpp index e43f3f47f..78c047bd2 100644 --- a/src/core/hle/service/bcat/backend/boxcat.cpp +++ b/src/core/hle/service/bcat/backend/boxcat.cpp | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | #include "common/hex_util.h" | 9 | #include "common/hex_util.h" |
| 10 | #include "common/logging/backend.h" | 10 | #include "common/logging/backend.h" |
| 11 | #include "common/logging/log.h" | 11 | #include "common/logging/log.h" |
| 12 | #include "common/settings.h" | ||
| 12 | #include "core/core.h" | 13 | #include "core/core.h" |
| 13 | #include "core/file_sys/vfs.h" | 14 | #include "core/file_sys/vfs.h" |
| 14 | #include "core/file_sys/vfs_libzip.h" | 15 | #include "core/file_sys/vfs_libzip.h" |
| @@ -16,7 +17,6 @@ | |||
| 16 | #include "core/frontend/applets/error.h" | 17 | #include "core/frontend/applets/error.h" |
| 17 | #include "core/hle/service/am/applets/applets.h" | 18 | #include "core/hle/service/am/applets/applets.h" |
| 18 | #include "core/hle/service/bcat/backend/boxcat.h" | 19 | #include "core/hle/service/bcat/backend/boxcat.h" |
| 19 | #include "core/settings.h" | ||
| 20 | 20 | ||
| 21 | namespace Service::BCAT { | 21 | namespace Service::BCAT { |
| 22 | namespace { | 22 | namespace { |
diff --git a/src/core/hle/service/bcat/module.cpp b/src/core/hle/service/bcat/module.cpp index 503109fdd..c7dd04a6e 100644 --- a/src/core/hle/service/bcat/module.cpp +++ b/src/core/hle/service/bcat/module.cpp | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include "backend/boxcat.h" | 7 | #include "backend/boxcat.h" |
| 8 | #include "common/hex_util.h" | 8 | #include "common/hex_util.h" |
| 9 | #include "common/logging/log.h" | 9 | #include "common/logging/log.h" |
| 10 | #include "common/settings.h" | ||
| 10 | #include "common/string_util.h" | 11 | #include "common/string_util.h" |
| 11 | #include "core/core.h" | 12 | #include "core/core.h" |
| 12 | #include "core/file_sys/vfs.h" | 13 | #include "core/file_sys/vfs.h" |
| @@ -18,7 +19,6 @@ | |||
| 18 | #include "core/hle/service/bcat/bcat.h" | 19 | #include "core/hle/service/bcat/bcat.h" |
| 19 | #include "core/hle/service/bcat/module.h" | 20 | #include "core/hle/service/bcat/module.h" |
| 20 | #include "core/hle/service/filesystem/filesystem.h" | 21 | #include "core/hle/service/filesystem/filesystem.h" |
| 21 | #include "core/settings.h" | ||
| 22 | 22 | ||
| 23 | namespace Service::BCAT { | 23 | namespace Service::BCAT { |
| 24 | 24 | ||
| @@ -155,10 +155,12 @@ public: | |||
| 155 | {30210, nullptr, "SetDeliveryTaskTimer"}, | 155 | {30210, nullptr, "SetDeliveryTaskTimer"}, |
| 156 | {30300, nullptr, "RegisterSystemApplicationDeliveryTasks"}, | 156 | {30300, nullptr, "RegisterSystemApplicationDeliveryTasks"}, |
| 157 | {90100, nullptr, "EnumerateBackgroundDeliveryTask"}, | 157 | {90100, nullptr, "EnumerateBackgroundDeliveryTask"}, |
| 158 | {90101, nullptr, "Unknown90101"}, | ||
| 158 | {90200, nullptr, "GetDeliveryList"}, | 159 | {90200, nullptr, "GetDeliveryList"}, |
| 159 | {90201, &IBcatService::ClearDeliveryCacheStorage, "ClearDeliveryCacheStorage"}, | 160 | {90201, &IBcatService::ClearDeliveryCacheStorage, "ClearDeliveryCacheStorage"}, |
| 160 | {90202, nullptr, "ClearDeliveryTaskSubscriptionStatus"}, | 161 | {90202, nullptr, "ClearDeliveryTaskSubscriptionStatus"}, |
| 161 | {90300, nullptr, "GetPushNotificationLog"}, | 162 | {90300, nullptr, "GetPushNotificationLog"}, |
| 163 | {90301, nullptr, "Unknown90301"}, | ||
| 162 | }; | 164 | }; |
| 163 | // clang-format on | 165 | // clang-format on |
| 164 | RegisterHandlers(functions); | 166 | RegisterHandlers(functions); |
diff --git a/src/core/hle/service/bpc/bpc.cpp b/src/core/hle/service/bpc/bpc.cpp index e4630320e..78e01d8d8 100644 --- a/src/core/hle/service/bpc/bpc.cpp +++ b/src/core/hle/service/bpc/bpc.cpp | |||
| @@ -29,8 +29,8 @@ public: | |||
| 29 | {11, nullptr, "CreateWakeupTimerEx"}, | 29 | {11, nullptr, "CreateWakeupTimerEx"}, |
| 30 | {12, nullptr, "GetLastEnabledWakeupTimerType"}, | 30 | {12, nullptr, "GetLastEnabledWakeupTimerType"}, |
| 31 | {13, nullptr, "CleanAllWakeupTimers"}, | 31 | {13, nullptr, "CleanAllWakeupTimers"}, |
| 32 | {14, nullptr, "Unknown"}, | 32 | {14, nullptr, "GetPowerButton"}, |
| 33 | {15, nullptr, "Unknown2"}, | 33 | {15, nullptr, "SetEnableWakeupTimer"}, |
| 34 | }; | 34 | }; |
| 35 | // clang-format on | 35 | // clang-format on |
| 36 | 36 | ||
diff --git a/src/core/hle/service/btdrv/btdrv.cpp b/src/core/hle/service/btdrv/btdrv.cpp index 17a2ac899..af3a5842d 100644 --- a/src/core/hle/service/btdrv/btdrv.cpp +++ b/src/core/hle/service/btdrv/btdrv.cpp | |||
| @@ -156,6 +156,25 @@ public: | |||
| 156 | {97, nullptr, "RegisterBleHidEvent"}, | 156 | {97, nullptr, "RegisterBleHidEvent"}, |
| 157 | {98, nullptr, "SetBleScanParameter"}, | 157 | {98, nullptr, "SetBleScanParameter"}, |
| 158 | {99, nullptr, "MoveToSecondaryPiconet"}, | 158 | {99, nullptr, "MoveToSecondaryPiconet"}, |
| 159 | {100, nullptr, "IsBluetoothEnabled"}, | ||
| 160 | {128, nullptr, "AcquireAudioEvent"}, | ||
| 161 | {129, nullptr, "GetAudioEventInfo"}, | ||
| 162 | {130, nullptr, "OpenAudioConnection"}, | ||
| 163 | {131, nullptr, "CloseAudioConnection"}, | ||
| 164 | {132, nullptr, "OpenAudioOut"}, | ||
| 165 | {133, nullptr, "CloseAudioOut"}, | ||
| 166 | {134, nullptr, "AcquireAudioOutStateChangedEvent"}, | ||
| 167 | {135, nullptr, "StartAudioOut"}, | ||
| 168 | {136, nullptr, "StopAudioOut"}, | ||
| 169 | {137, nullptr, "GetAudioOutState"}, | ||
| 170 | {138, nullptr, "GetAudioOutFeedingCodec"}, | ||
| 171 | {139, nullptr, "GetAudioOutFeedingParameter"}, | ||
| 172 | {140, nullptr, "AcquireAudioOutBufferAvailableEvent"}, | ||
| 173 | {141, nullptr, "SendAudioData"}, | ||
| 174 | {142, nullptr, "AcquireAudioControlInputStateChangedEvent"}, | ||
| 175 | {143, nullptr, "GetAudioControlInputState"}, | ||
| 176 | {144, nullptr, "AcquireAudioConnectionStateChangedEvent"}, | ||
| 177 | {145, nullptr, "GetConnectedAudioDevice"}, | ||
| 159 | {256, nullptr, "IsManufacturingMode"}, | 178 | {256, nullptr, "IsManufacturingMode"}, |
| 160 | {257, nullptr, "EmulateBluetoothCrash"}, | 179 | {257, nullptr, "EmulateBluetoothCrash"}, |
| 161 | {258, nullptr, "GetBleChannelMap"}, | 180 | {258, nullptr, "GetBleChannelMap"}, |
diff --git a/src/core/hle/service/btm/btm.cpp b/src/core/hle/service/btm/btm.cpp index 9cf2ee92a..d1ebc2388 100644 --- a/src/core/hle/service/btm/btm.cpp +++ b/src/core/hle/service/btm/btm.cpp | |||
| @@ -223,6 +223,7 @@ public: | |||
| 223 | {10, nullptr, "GetGattClientDisconnectionReason"}, | 223 | {10, nullptr, "GetGattClientDisconnectionReason"}, |
| 224 | {11, nullptr, "GetBleConnectionParameter"}, | 224 | {11, nullptr, "GetBleConnectionParameter"}, |
| 225 | {12, nullptr, "GetBleConnectionParameterRequest"}, | 225 | {12, nullptr, "GetBleConnectionParameterRequest"}, |
| 226 | {13, nullptr, "Unknown13"}, | ||
| 226 | }; | 227 | }; |
| 227 | // clang-format on | 228 | // clang-format on |
| 228 | 229 | ||
diff --git a/src/core/hle/service/caps/caps_a.cpp b/src/core/hle/service/caps/caps_a.cpp index 1fe4f0e14..6220e9f77 100644 --- a/src/core/hle/service/caps/caps_a.cpp +++ b/src/core/hle/service/caps/caps_a.cpp | |||
| @@ -49,6 +49,7 @@ CAPS_A::CAPS_A(Core::System& system_) : ServiceFramework{system_, "caps:a"} { | |||
| 49 | {16, nullptr, "GetAlbumMountResult"}, | 49 | {16, nullptr, "GetAlbumMountResult"}, |
| 50 | {17, nullptr, "GetAlbumUsage16"}, | 50 | {17, nullptr, "GetAlbumUsage16"}, |
| 51 | {18, nullptr, "Unknown18"}, | 51 | {18, nullptr, "Unknown18"}, |
| 52 | {19, nullptr, "Unknown19"}, | ||
| 52 | {100, nullptr, "GetAlbumFileCountEx0"}, | 53 | {100, nullptr, "GetAlbumFileCountEx0"}, |
| 53 | {101, nullptr, "GetAlbumFileListEx0"}, | 54 | {101, nullptr, "GetAlbumFileListEx0"}, |
| 54 | {202, nullptr, "SaveEditedScreenShot"}, | 55 | {202, nullptr, "SaveEditedScreenShot"}, |
diff --git a/src/core/hle/service/caps/caps_u.cpp b/src/core/hle/service/caps/caps_u.cpp index 842316a2e..10b8d54b1 100644 --- a/src/core/hle/service/caps/caps_u.cpp +++ b/src/core/hle/service/caps/caps_u.cpp | |||
| @@ -43,6 +43,7 @@ CAPS_U::CAPS_U(Core::System& system_) : ServiceFramework{system_, "caps:u"} { | |||
| 43 | {141, nullptr, "GetAlbumFileList2AafeUidAruidDeprecated"}, | 43 | {141, nullptr, "GetAlbumFileList2AafeUidAruidDeprecated"}, |
| 44 | {142, &CAPS_U::GetAlbumFileList3AaeAruid, "GetAlbumFileList3AaeAruid"}, | 44 | {142, &CAPS_U::GetAlbumFileList3AaeAruid, "GetAlbumFileList3AaeAruid"}, |
| 45 | {143, nullptr, "GetAlbumFileList4AaeUidAruid"}, | 45 | {143, nullptr, "GetAlbumFileList4AaeUidAruid"}, |
| 46 | {144, nullptr, "GetAllAlbumFileList3AaeAruid"}, | ||
| 46 | {60002, nullptr, "OpenAccessorSessionForApplication"}, | 47 | {60002, nullptr, "OpenAccessorSessionForApplication"}, |
| 47 | }; | 48 | }; |
| 48 | // clang-format on | 49 | // clang-format on |
diff --git a/src/core/hle/service/erpt/erpt.cpp b/src/core/hle/service/erpt/erpt.cpp index 4924c61c3..c767926a4 100644 --- a/src/core/hle/service/erpt/erpt.cpp +++ b/src/core/hle/service/erpt/erpt.cpp | |||
| @@ -16,7 +16,7 @@ public: | |||
| 16 | // clang-format off | 16 | // clang-format off |
| 17 | static const FunctionInfo functions[] = { | 17 | static const FunctionInfo functions[] = { |
| 18 | {0, nullptr, "SubmitContext"}, | 18 | {0, nullptr, "SubmitContext"}, |
| 19 | {1, nullptr, "CreateReport"}, | 19 | {1, nullptr, "CreateReportV0"}, |
| 20 | {2, nullptr, "SetInitialLaunchSettingsCompletionTime"}, | 20 | {2, nullptr, "SetInitialLaunchSettingsCompletionTime"}, |
| 21 | {3, nullptr, "ClearInitialLaunchSettingsCompletionTime"}, | 21 | {3, nullptr, "ClearInitialLaunchSettingsCompletionTime"}, |
| 22 | {4, nullptr, "UpdatePowerOnTime"}, | 22 | {4, nullptr, "UpdatePowerOnTime"}, |
| @@ -26,6 +26,11 @@ public: | |||
| 26 | {8, nullptr, "ClearApplicationLaunchTime"}, | 26 | {8, nullptr, "ClearApplicationLaunchTime"}, |
| 27 | {9, nullptr, "SubmitAttachment"}, | 27 | {9, nullptr, "SubmitAttachment"}, |
| 28 | {10, nullptr, "CreateReportWithAttachments"}, | 28 | {10, nullptr, "CreateReportWithAttachments"}, |
| 29 | {11, nullptr, "CreateReport"}, | ||
| 30 | {20, nullptr, "RegisterRunningApplet"}, | ||
| 31 | {21, nullptr, "UnregisterRunningApplet"}, | ||
| 32 | {22, nullptr, "UpdateAppletSuspendedDuration"}, | ||
| 33 | {30, nullptr, "InvalidateForcedShutdownDetection"}, | ||
| 29 | }; | 34 | }; |
| 30 | // clang-format on | 35 | // clang-format on |
| 31 | 36 | ||
diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp index b15c737e1..72ad273b2 100644 --- a/src/core/hle/service/filesystem/filesystem.cpp +++ b/src/core/hle/service/filesystem/filesystem.cpp | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | 6 | ||
| 7 | #include "common/assert.h" | 7 | #include "common/assert.h" |
| 8 | #include "common/file_util.h" | 8 | #include "common/file_util.h" |
| 9 | #include "common/settings.h" | ||
| 9 | #include "core/core.h" | 10 | #include "core/core.h" |
| 10 | #include "core/file_sys/bis_factory.h" | 11 | #include "core/file_sys/bis_factory.h" |
| 11 | #include "core/file_sys/card_image.h" | 12 | #include "core/file_sys/card_image.h" |
| @@ -26,7 +27,6 @@ | |||
| 26 | #include "core/hle/service/filesystem/fsp_pr.h" | 27 | #include "core/hle/service/filesystem/fsp_pr.h" |
| 27 | #include "core/hle/service/filesystem/fsp_srv.h" | 28 | #include "core/hle/service/filesystem/fsp_srv.h" |
| 28 | #include "core/loader/loader.h" | 29 | #include "core/loader/loader.h" |
| 29 | #include "core/settings.h" | ||
| 30 | 30 | ||
| 31 | namespace Service::FileSystem { | 31 | namespace Service::FileSystem { |
| 32 | 32 | ||
diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp index 9cc260515..a0215c4d7 100644 --- a/src/core/hle/service/filesystem/fsp_srv.cpp +++ b/src/core/hle/service/filesystem/fsp_srv.cpp | |||
| @@ -118,9 +118,13 @@ public: | |||
| 118 | explicit IFile(Core::System& system_, FileSys::VirtualFile backend_) | 118 | explicit IFile(Core::System& system_, FileSys::VirtualFile backend_) |
| 119 | : ServiceFramework{system_, "IFile"}, backend(std::move(backend_)) { | 119 | : ServiceFramework{system_, "IFile"}, backend(std::move(backend_)) { |
| 120 | static const FunctionInfo functions[] = { | 120 | static const FunctionInfo functions[] = { |
| 121 | {0, &IFile::Read, "Read"}, {1, &IFile::Write, "Write"}, | 121 | {0, &IFile::Read, "Read"}, |
| 122 | {2, &IFile::Flush, "Flush"}, {3, &IFile::SetSize, "SetSize"}, | 122 | {1, &IFile::Write, "Write"}, |
| 123 | {4, &IFile::GetSize, "GetSize"}, {5, nullptr, "OperateRange"}, | 123 | {2, &IFile::Flush, "Flush"}, |
| 124 | {3, &IFile::SetSize, "SetSize"}, | ||
| 125 | {4, &IFile::GetSize, "GetSize"}, | ||
| 126 | {5, nullptr, "OperateRange"}, | ||
| 127 | {6, nullptr, "OperateRangeWithBuffer"}, | ||
| 124 | }; | 128 | }; |
| 125 | RegisterHandlers(functions); | 129 | RegisterHandlers(functions); |
| 126 | } | 130 | } |
| @@ -708,7 +712,10 @@ FSP_SRV::FSP_SRV(Core::System& system_) | |||
| 708 | {84, nullptr, "ListApplicationAccessibleSaveDataOwnerId"}, | 712 | {84, nullptr, "ListApplicationAccessibleSaveDataOwnerId"}, |
| 709 | {85, nullptr, "OpenSaveDataTransferManagerForSaveDataRepair"}, | 713 | {85, nullptr, "OpenSaveDataTransferManagerForSaveDataRepair"}, |
| 710 | {86, nullptr, "OpenSaveDataMover"}, | 714 | {86, nullptr, "OpenSaveDataMover"}, |
| 715 | {87, nullptr, "OpenSaveDataTransferManagerForRepair"}, | ||
| 711 | {100, nullptr, "OpenImageDirectoryFileSystem"}, | 716 | {100, nullptr, "OpenImageDirectoryFileSystem"}, |
| 717 | {101, nullptr, "OpenBaseFileSystem"}, | ||
| 718 | {102, nullptr, "FormatBaseFileSystem"}, | ||
| 712 | {110, nullptr, "OpenContentStorageFileSystem"}, | 719 | {110, nullptr, "OpenContentStorageFileSystem"}, |
| 713 | {120, nullptr, "OpenCloudBackupWorkStorageFileSystem"}, | 720 | {120, nullptr, "OpenCloudBackupWorkStorageFileSystem"}, |
| 714 | {130, nullptr, "OpenCustomStorageFileSystem"}, | 721 | {130, nullptr, "OpenCustomStorageFileSystem"}, |
| @@ -764,10 +771,12 @@ FSP_SRV::FSP_SRV(Core::System& system_) | |||
| 764 | {1008, nullptr, "OpenRegisteredUpdatePartition"}, | 771 | {1008, nullptr, "OpenRegisteredUpdatePartition"}, |
| 765 | {1009, nullptr, "GetAndClearMemoryReportInfo"}, | 772 | {1009, nullptr, "GetAndClearMemoryReportInfo"}, |
| 766 | {1010, nullptr, "SetDataStorageRedirectTarget"}, | 773 | {1010, nullptr, "SetDataStorageRedirectTarget"}, |
| 767 | {1011, &FSP_SRV::GetAccessLogVersionInfo, "GetAccessLogVersionInfo"}, | 774 | {1011, &FSP_SRV::GetProgramIndexForAccessLog, "GetProgramIndexForAccessLog"}, |
| 768 | {1012, nullptr, "GetFsStackUsage"}, | 775 | {1012, nullptr, "GetFsStackUsage"}, |
| 769 | {1013, nullptr, "UnsetSaveDataRootPath"}, | 776 | {1013, nullptr, "UnsetSaveDataRootPath"}, |
| 770 | {1014, nullptr, "OutputMultiProgramTagAccessLog"}, | 777 | {1014, nullptr, "OutputMultiProgramTagAccessLog"}, |
| 778 | {1016, nullptr, "FlushAccessLogOnSdCard"}, | ||
| 779 | {1017, nullptr, "OutputApplicationInfoAccessLog"}, | ||
| 771 | {1100, nullptr, "OverrideSaveDataTransferTokenSignVerificationKey"}, | 780 | {1100, nullptr, "OverrideSaveDataTransferTokenSignVerificationKey"}, |
| 772 | {1110, nullptr, "CorruptSaveDataFileSystemBySaveDataSpaceId2"}, | 781 | {1110, nullptr, "CorruptSaveDataFileSystemBySaveDataSpaceId2"}, |
| 773 | {1200, &FSP_SRV::OpenMultiCommitManager, "OpenMultiCommitManager"}, | 782 | {1200, &FSP_SRV::OpenMultiCommitManager, "OpenMultiCommitManager"}, |
| @@ -1051,7 +1060,7 @@ void FSP_SRV::OutputAccessLogToSdCard(Kernel::HLERequestContext& ctx) { | |||
| 1051 | rb.Push(RESULT_SUCCESS); | 1060 | rb.Push(RESULT_SUCCESS); |
| 1052 | } | 1061 | } |
| 1053 | 1062 | ||
| 1054 | void FSP_SRV::GetAccessLogVersionInfo(Kernel::HLERequestContext& ctx) { | 1063 | void FSP_SRV::GetProgramIndexForAccessLog(Kernel::HLERequestContext& ctx) { |
| 1055 | LOG_DEBUG(Service_FS, "called"); | 1064 | LOG_DEBUG(Service_FS, "called"); |
| 1056 | 1065 | ||
| 1057 | IPC::ResponseBuilder rb{ctx, 4}; | 1066 | IPC::ResponseBuilder rb{ctx, 4}; |
diff --git a/src/core/hle/service/filesystem/fsp_srv.h b/src/core/hle/service/filesystem/fsp_srv.h index 8ed933279..b01b924eb 100644 --- a/src/core/hle/service/filesystem/fsp_srv.h +++ b/src/core/hle/service/filesystem/fsp_srv.h | |||
| @@ -53,7 +53,7 @@ private: | |||
| 53 | void SetGlobalAccessLogMode(Kernel::HLERequestContext& ctx); | 53 | void SetGlobalAccessLogMode(Kernel::HLERequestContext& ctx); |
| 54 | void GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx); | 54 | void GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx); |
| 55 | void OutputAccessLogToSdCard(Kernel::HLERequestContext& ctx); | 55 | void OutputAccessLogToSdCard(Kernel::HLERequestContext& ctx); |
| 56 | void GetAccessLogVersionInfo(Kernel::HLERequestContext& ctx); | 56 | void GetProgramIndexForAccessLog(Kernel::HLERequestContext& ctx); |
| 57 | void OpenMultiCommitManager(Kernel::HLERequestContext& ctx); | 57 | void OpenMultiCommitManager(Kernel::HLERequestContext& ctx); |
| 58 | 58 | ||
| 59 | FileSystemController& fsc; | 59 | FileSystemController& fsc; |
diff --git a/src/core/hle/service/friend/friend.cpp b/src/core/hle/service/friend/friend.cpp index 0a6621ef2..a35979053 100644 --- a/src/core/hle/service/friend/friend.cpp +++ b/src/core/hle/service/friend/friend.cpp | |||
| @@ -38,7 +38,7 @@ public: | |||
| 38 | {10600, nullptr, "DeclareOpenOnlinePlaySession"}, | 38 | {10600, nullptr, "DeclareOpenOnlinePlaySession"}, |
| 39 | {10601, &IFriendService::DeclareCloseOnlinePlaySession, "DeclareCloseOnlinePlaySession"}, | 39 | {10601, &IFriendService::DeclareCloseOnlinePlaySession, "DeclareCloseOnlinePlaySession"}, |
| 40 | {10610, &IFriendService::UpdateUserPresence, "UpdateUserPresence"}, | 40 | {10610, &IFriendService::UpdateUserPresence, "UpdateUserPresence"}, |
| 41 | {10700, nullptr, "GetPlayHistoryRegistrationKey"}, | 41 | {10700, &IFriendService::GetPlayHistoryRegistrationKey, "GetPlayHistoryRegistrationKey"}, |
| 42 | {10701, nullptr, "GetPlayHistoryRegistrationKeyWithNetworkServiceAccountId"}, | 42 | {10701, nullptr, "GetPlayHistoryRegistrationKeyWithNetworkServiceAccountId"}, |
| 43 | {10702, nullptr, "AddPlayHistory"}, | 43 | {10702, nullptr, "AddPlayHistory"}, |
| 44 | {11000, nullptr, "GetProfileImageUrl"}, | 44 | {11000, nullptr, "GetProfileImageUrl"}, |
| @@ -153,6 +153,18 @@ private: | |||
| 153 | rb.Push(RESULT_SUCCESS); | 153 | rb.Push(RESULT_SUCCESS); |
| 154 | } | 154 | } |
| 155 | 155 | ||
| 156 | void GetPlayHistoryRegistrationKey(Kernel::HLERequestContext& ctx) { | ||
| 157 | IPC::RequestParser rp{ctx}; | ||
| 158 | const auto local_play = rp.Pop<bool>(); | ||
| 159 | const auto uuid = rp.PopRaw<Common::UUID>(); | ||
| 160 | |||
| 161 | LOG_WARNING(Service_Friend, "(STUBBED) called local_play={} uuid={}", local_play, | ||
| 162 | uuid.Format()); | ||
| 163 | |||
| 164 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 165 | rb.Push(RESULT_SUCCESS); | ||
| 166 | } | ||
| 167 | |||
| 156 | void GetFriendList(Kernel::HLERequestContext& ctx) { | 168 | void GetFriendList(Kernel::HLERequestContext& ctx) { |
| 157 | IPC::RequestParser rp{ctx}; | 169 | IPC::RequestParser rp{ctx}; |
| 158 | const auto friend_offset = rp.Pop<u32>(); | 170 | const auto friend_offset = rp.Pop<u32>(); |
diff --git a/src/core/hle/service/glue/arp.cpp b/src/core/hle/service/glue/arp.cpp index fc77e7286..322125135 100644 --- a/src/core/hle/service/glue/arp.cpp +++ b/src/core/hle/service/glue/arp.cpp | |||
| @@ -41,6 +41,12 @@ ARP_R::ARP_R(Core::System& system_, const ARPManager& manager_) | |||
| 41 | {1, &ARP_R::GetApplicationLaunchPropertyWithApplicationId, "GetApplicationLaunchPropertyWithApplicationId"}, | 41 | {1, &ARP_R::GetApplicationLaunchPropertyWithApplicationId, "GetApplicationLaunchPropertyWithApplicationId"}, |
| 42 | {2, &ARP_R::GetApplicationControlProperty, "GetApplicationControlProperty"}, | 42 | {2, &ARP_R::GetApplicationControlProperty, "GetApplicationControlProperty"}, |
| 43 | {3, &ARP_R::GetApplicationControlPropertyWithApplicationId, "GetApplicationControlPropertyWithApplicationId"}, | 43 | {3, &ARP_R::GetApplicationControlPropertyWithApplicationId, "GetApplicationControlPropertyWithApplicationId"}, |
| 44 | {4, nullptr, "GetApplicationInstanceUnregistrationNotifier"}, | ||
| 45 | {5, nullptr, "ListApplicationInstanceId"}, | ||
| 46 | {6, nullptr, "GetMicroApplicationInstanceId"}, | ||
| 47 | {7, nullptr, "GetApplicationCertificate"}, | ||
| 48 | {9998, nullptr, "GetPreomiaApplicationLaunchProperty"}, | ||
| 49 | {9999, nullptr, "GetPreomiaApplicationControlProperty"}, | ||
| 44 | }; | 50 | }; |
| 45 | // clang-format on | 51 | // clang-format on |
| 46 | 52 | ||
| @@ -243,7 +249,8 @@ ARP_W::ARP_W(Core::System& system_, ARPManager& manager_) | |||
| 243 | // clang-format off | 249 | // clang-format off |
| 244 | static const FunctionInfo functions[] = { | 250 | static const FunctionInfo functions[] = { |
| 245 | {0, &ARP_W::AcquireRegistrar, "AcquireRegistrar"}, | 251 | {0, &ARP_W::AcquireRegistrar, "AcquireRegistrar"}, |
| 246 | {1, &ARP_W::DeleteProperties, "DeleteProperties"}, | 252 | {1, &ARP_W::UnregisterApplicationInstance , "UnregisterApplicationInstance "}, |
| 253 | {2, nullptr, "AcquireUpdater"}, | ||
| 247 | }; | 254 | }; |
| 248 | // clang-format on | 255 | // clang-format on |
| 249 | 256 | ||
| @@ -270,7 +277,7 @@ void ARP_W::AcquireRegistrar(Kernel::HLERequestContext& ctx) { | |||
| 270 | rb.PushIpcInterface(registrar); | 277 | rb.PushIpcInterface(registrar); |
| 271 | } | 278 | } |
| 272 | 279 | ||
| 273 | void ARP_W::DeleteProperties(Kernel::HLERequestContext& ctx) { | 280 | void ARP_W::UnregisterApplicationInstance(Kernel::HLERequestContext& ctx) { |
| 274 | IPC::RequestParser rp{ctx}; | 281 | IPC::RequestParser rp{ctx}; |
| 275 | const auto process_id = rp.PopRaw<u64>(); | 282 | const auto process_id = rp.PopRaw<u64>(); |
| 276 | 283 | ||
diff --git a/src/core/hle/service/glue/arp.h b/src/core/hle/service/glue/arp.h index 34b412e26..0df3c5e1f 100644 --- a/src/core/hle/service/glue/arp.h +++ b/src/core/hle/service/glue/arp.h | |||
| @@ -32,7 +32,7 @@ public: | |||
| 32 | 32 | ||
| 33 | private: | 33 | private: |
| 34 | void AcquireRegistrar(Kernel::HLERequestContext& ctx); | 34 | void AcquireRegistrar(Kernel::HLERequestContext& ctx); |
| 35 | void DeleteProperties(Kernel::HLERequestContext& ctx); | 35 | void UnregisterApplicationInstance(Kernel::HLERequestContext& ctx); |
| 36 | 36 | ||
| 37 | ARPManager& manager; | 37 | ARPManager& manager; |
| 38 | std::shared_ptr<IRegistrar> registrar; | 38 | std::shared_ptr<IRegistrar> registrar; |
diff --git a/src/core/hle/service/glue/bgtc.cpp b/src/core/hle/service/glue/bgtc.cpp index a478b68e1..daecfff15 100644 --- a/src/core/hle/service/glue/bgtc.cpp +++ b/src/core/hle/service/glue/bgtc.cpp | |||
| @@ -2,6 +2,9 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include "common/logging/log.h" | ||
| 6 | #include "core/core.h" | ||
| 7 | #include "core/hle/ipc_helpers.h" | ||
| 5 | #include "core/hle/service/glue/bgtc.h" | 8 | #include "core/hle/service/glue/bgtc.h" |
| 6 | 9 | ||
| 7 | namespace Service::Glue { | 10 | namespace Service::Glue { |
| @@ -9,6 +12,26 @@ namespace Service::Glue { | |||
| 9 | BGTC_T::BGTC_T(Core::System& system_) : ServiceFramework{system_, "bgtc:t"} { | 12 | BGTC_T::BGTC_T(Core::System& system_) : ServiceFramework{system_, "bgtc:t"} { |
| 10 | // clang-format off | 13 | // clang-format off |
| 11 | static const FunctionInfo functions[] = { | 14 | static const FunctionInfo functions[] = { |
| 15 | {100, &BGTC_T::OpenTaskService, "OpenTaskService"}, | ||
| 16 | }; | ||
| 17 | // clang-format on | ||
| 18 | |||
| 19 | RegisterHandlers(functions); | ||
| 20 | } | ||
| 21 | |||
| 22 | BGTC_T::~BGTC_T() = default; | ||
| 23 | |||
| 24 | void BGTC_T::OpenTaskService(Kernel::HLERequestContext& ctx) { | ||
| 25 | LOG_DEBUG(Service_BGTC, "called"); | ||
| 26 | |||
| 27 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 28 | rb.Push(RESULT_SUCCESS); | ||
| 29 | rb.PushIpcInterface<ITaskService>(system); | ||
| 30 | } | ||
| 31 | |||
| 32 | ITaskService::ITaskService(Core::System& system_) : ServiceFramework{system_, "ITaskService"} { | ||
| 33 | // clang-format off | ||
| 34 | static const FunctionInfo functions[] = { | ||
| 12 | {1, nullptr, "NotifyTaskStarting"}, | 35 | {1, nullptr, "NotifyTaskStarting"}, |
| 13 | {2, nullptr, "NotifyTaskFinished"}, | 36 | {2, nullptr, "NotifyTaskFinished"}, |
| 14 | {3, nullptr, "GetTriggerEvent"}, | 37 | {3, nullptr, "GetTriggerEvent"}, |
| @@ -20,16 +43,18 @@ BGTC_T::BGTC_T(Core::System& system_) : ServiceFramework{system_, "bgtc:t"} { | |||
| 20 | {13, nullptr, "UnscheduleTask"}, | 43 | {13, nullptr, "UnscheduleTask"}, |
| 21 | {14, nullptr, "GetScheduleEvent"}, | 44 | {14, nullptr, "GetScheduleEvent"}, |
| 22 | {15, nullptr, "SchedulePeriodicTask"}, | 45 | {15, nullptr, "SchedulePeriodicTask"}, |
| 46 | {16, nullptr, "Unknown16"}, | ||
| 23 | {101, nullptr, "GetOperationMode"}, | 47 | {101, nullptr, "GetOperationMode"}, |
| 24 | {102, nullptr, "WillDisconnectNetworkWhenEnteringSleep"}, | 48 | {102, nullptr, "WillDisconnectNetworkWhenEnteringSleep"}, |
| 25 | {103, nullptr, "WillStayHalfAwakeInsteadSleep"}, | 49 | {103, nullptr, "WillStayHalfAwakeInsteadSleep"}, |
| 50 | {200, nullptr, "Unknown200"}, | ||
| 26 | }; | 51 | }; |
| 27 | // clang-format on | 52 | // clang-format on |
| 28 | 53 | ||
| 29 | RegisterHandlers(functions); | 54 | RegisterHandlers(functions); |
| 30 | } | 55 | } |
| 31 | 56 | ||
| 32 | BGTC_T::~BGTC_T() = default; | 57 | ITaskService::~ITaskService() = default; |
| 33 | 58 | ||
| 34 | BGTC_SC::BGTC_SC(Core::System& system_) : ServiceFramework{system_, "bgtc:sc"} { | 59 | BGTC_SC::BGTC_SC(Core::System& system_) : ServiceFramework{system_, "bgtc:sc"} { |
| 35 | // clang-format off | 60 | // clang-format off |
diff --git a/src/core/hle/service/glue/bgtc.h b/src/core/hle/service/glue/bgtc.h index 906116ba6..4c0142fd5 100644 --- a/src/core/hle/service/glue/bgtc.h +++ b/src/core/hle/service/glue/bgtc.h | |||
| @@ -16,6 +16,14 @@ class BGTC_T final : public ServiceFramework<BGTC_T> { | |||
| 16 | public: | 16 | public: |
| 17 | explicit BGTC_T(Core::System& system_); | 17 | explicit BGTC_T(Core::System& system_); |
| 18 | ~BGTC_T() override; | 18 | ~BGTC_T() override; |
| 19 | |||
| 20 | void OpenTaskService(Kernel::HLERequestContext& ctx); | ||
| 21 | }; | ||
| 22 | |||
| 23 | class ITaskService final : public ServiceFramework<ITaskService> { | ||
| 24 | public: | ||
| 25 | explicit ITaskService(Core::System& system_); | ||
| 26 | ~ITaskService() override; | ||
| 19 | }; | 27 | }; |
| 20 | 28 | ||
| 21 | class BGTC_SC final : public ServiceFramework<BGTC_SC> { | 29 | class BGTC_SC final : public ServiceFramework<BGTC_SC> { |
diff --git a/src/core/hle/service/hid/controllers/debug_pad.cpp b/src/core/hle/service/hid/controllers/debug_pad.cpp index ad251ed4a..a460f2f79 100644 --- a/src/core/hle/service/hid/controllers/debug_pad.cpp +++ b/src/core/hle/service/hid/controllers/debug_pad.cpp | |||
| @@ -4,9 +4,9 @@ | |||
| 4 | 4 | ||
| 5 | #include <cstring> | 5 | #include <cstring> |
| 6 | #include "common/common_types.h" | 6 | #include "common/common_types.h" |
| 7 | #include "common/settings.h" | ||
| 7 | #include "core/core_timing.h" | 8 | #include "core/core_timing.h" |
| 8 | #include "core/hle/service/hid/controllers/debug_pad.h" | 9 | #include "core/hle/service/hid/controllers/debug_pad.h" |
| 9 | #include "core/settings.h" | ||
| 10 | 10 | ||
| 11 | namespace Service::HID { | 11 | namespace Service::HID { |
| 12 | 12 | ||
diff --git a/src/core/hle/service/hid/controllers/debug_pad.h b/src/core/hle/service/hid/controllers/debug_pad.h index 555b29d76..0593d7d39 100644 --- a/src/core/hle/service/hid/controllers/debug_pad.h +++ b/src/core/hle/service/hid/controllers/debug_pad.h | |||
| @@ -8,10 +8,10 @@ | |||
| 8 | #include "common/bit_field.h" | 8 | #include "common/bit_field.h" |
| 9 | #include "common/common_funcs.h" | 9 | #include "common/common_funcs.h" |
| 10 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 11 | #include "common/settings.h" | ||
| 11 | #include "common/swap.h" | 12 | #include "common/swap.h" |
| 12 | #include "core/frontend/input.h" | 13 | #include "core/frontend/input.h" |
| 13 | #include "core/hle/service/hid/controllers/controller_base.h" | 14 | #include "core/hle/service/hid/controllers/controller_base.h" |
| 14 | #include "core/settings.h" | ||
| 15 | 15 | ||
| 16 | namespace Service::HID { | 16 | namespace Service::HID { |
| 17 | class Controller_DebugPad final : public ControllerBase { | 17 | class Controller_DebugPad final : public ControllerBase { |
diff --git a/src/core/hle/service/hid/controllers/gesture.cpp b/src/core/hle/service/hid/controllers/gesture.cpp index 93c43a203..155808f6a 100644 --- a/src/core/hle/service/hid/controllers/gesture.cpp +++ b/src/core/hle/service/hid/controllers/gesture.cpp | |||
| @@ -5,10 +5,10 @@ | |||
| 5 | #include <cstring> | 5 | #include <cstring> |
| 6 | #include "common/common_types.h" | 6 | #include "common/common_types.h" |
| 7 | #include "common/logging/log.h" | 7 | #include "common/logging/log.h" |
| 8 | #include "common/settings.h" | ||
| 8 | #include "core/core_timing.h" | 9 | #include "core/core_timing.h" |
| 9 | #include "core/frontend/emu_window.h" | 10 | #include "core/frontend/emu_window.h" |
| 10 | #include "core/hle/service/hid/controllers/gesture.h" | 11 | #include "core/hle/service/hid/controllers/gesture.h" |
| 11 | #include "core/settings.h" | ||
| 12 | 12 | ||
| 13 | namespace Service::HID { | 13 | namespace Service::HID { |
| 14 | constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3BA00; | 14 | constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3BA00; |
diff --git a/src/core/hle/service/hid/controllers/keyboard.cpp b/src/core/hle/service/hid/controllers/keyboard.cpp index c4a59147d..18b76038f 100644 --- a/src/core/hle/service/hid/controllers/keyboard.cpp +++ b/src/core/hle/service/hid/controllers/keyboard.cpp | |||
| @@ -4,9 +4,9 @@ | |||
| 4 | 4 | ||
| 5 | #include <cstring> | 5 | #include <cstring> |
| 6 | #include "common/common_types.h" | 6 | #include "common/common_types.h" |
| 7 | #include "common/settings.h" | ||
| 7 | #include "core/core_timing.h" | 8 | #include "core/core_timing.h" |
| 8 | #include "core/hle/service/hid/controllers/keyboard.h" | 9 | #include "core/hle/service/hid/controllers/keyboard.h" |
| 9 | #include "core/settings.h" | ||
| 10 | 10 | ||
| 11 | namespace Service::HID { | 11 | namespace Service::HID { |
| 12 | constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3800; | 12 | constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3800; |
diff --git a/src/core/hle/service/hid/controllers/keyboard.h b/src/core/hle/service/hid/controllers/keyboard.h index b5b281752..e72948591 100644 --- a/src/core/hle/service/hid/controllers/keyboard.h +++ b/src/core/hle/service/hid/controllers/keyboard.h | |||
| @@ -8,10 +8,10 @@ | |||
| 8 | #include "common/bit_field.h" | 8 | #include "common/bit_field.h" |
| 9 | #include "common/common_funcs.h" | 9 | #include "common/common_funcs.h" |
| 10 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 11 | #include "common/settings.h" | ||
| 11 | #include "common/swap.h" | 12 | #include "common/swap.h" |
| 12 | #include "core/frontend/input.h" | 13 | #include "core/frontend/input.h" |
| 13 | #include "core/hle/service/hid/controllers/controller_base.h" | 14 | #include "core/hle/service/hid/controllers/controller_base.h" |
| 14 | #include "core/settings.h" | ||
| 15 | 15 | ||
| 16 | namespace Service::HID { | 16 | namespace Service::HID { |
| 17 | class Controller_Keyboard final : public ControllerBase { | 17 | class Controller_Keyboard final : public ControllerBase { |
diff --git a/src/core/hle/service/hid/controllers/mouse.h b/src/core/hle/service/hid/controllers/mouse.h index 3b432a36e..0ec0c2b94 100644 --- a/src/core/hle/service/hid/controllers/mouse.h +++ b/src/core/hle/service/hid/controllers/mouse.h | |||
| @@ -7,10 +7,10 @@ | |||
| 7 | #include <array> | 7 | #include <array> |
| 8 | #include "common/bit_field.h" | 8 | #include "common/bit_field.h" |
| 9 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| 10 | #include "common/settings.h" | ||
| 10 | #include "common/swap.h" | 11 | #include "common/swap.h" |
| 11 | #include "core/frontend/input.h" | 12 | #include "core/frontend/input.h" |
| 12 | #include "core/hle/service/hid/controllers/controller_base.h" | 13 | #include "core/hle/service/hid/controllers/controller_base.h" |
| 13 | #include "core/settings.h" | ||
| 14 | 14 | ||
| 15 | namespace Service::HID { | 15 | namespace Service::HID { |
| 16 | class Controller_Mouse final : public ControllerBase { | 16 | class Controller_Mouse final : public ControllerBase { |
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index 70b9f3824..783386fcf 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | #include "common/bit_field.h" | 9 | #include "common/bit_field.h" |
| 10 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 11 | #include "common/logging/log.h" | 11 | #include "common/logging/log.h" |
| 12 | #include "common/settings.h" | ||
| 12 | #include "core/core.h" | 13 | #include "core/core.h" |
| 13 | #include "core/core_timing.h" | 14 | #include "core/core_timing.h" |
| 14 | #include "core/frontend/input.h" | 15 | #include "core/frontend/input.h" |
| @@ -17,7 +18,6 @@ | |||
| 17 | #include "core/hle/kernel/k_writable_event.h" | 18 | #include "core/hle/kernel/k_writable_event.h" |
| 18 | #include "core/hle/kernel/kernel.h" | 19 | #include "core/hle/kernel/kernel.h" |
| 19 | #include "core/hle/service/hid/controllers/npad.h" | 20 | #include "core/hle/service/hid/controllers/npad.h" |
| 20 | #include "core/settings.h" | ||
| 21 | 21 | ||
| 22 | namespace Service::HID { | 22 | namespace Service::HID { |
| 23 | constexpr s32 HID_JOYSTICK_MAX = 0x7fff; | 23 | constexpr s32 HID_JOYSTICK_MAX = 0x7fff; |
| @@ -413,12 +413,16 @@ void Controller_NPad::RequestPadStateUpdate(u32 npad_id) { | |||
| 413 | lstick_entry.y = static_cast<s32>(stick_l_y_f * HID_JOYSTICK_MAX); | 413 | lstick_entry.y = static_cast<s32>(stick_l_y_f * HID_JOYSTICK_MAX); |
| 414 | } | 414 | } |
| 415 | 415 | ||
| 416 | if (controller_type == NPadControllerType::JoyLeft || | 416 | if (controller_type == NPadControllerType::JoyLeft) { |
| 417 | controller_type == NPadControllerType::JoyRight) { | ||
| 418 | pad_state.left_sl.Assign(button_state[SL - BUTTON_HID_BEGIN]->GetStatus()); | 417 | pad_state.left_sl.Assign(button_state[SL - BUTTON_HID_BEGIN]->GetStatus()); |
| 419 | pad_state.left_sr.Assign(button_state[SR - BUTTON_HID_BEGIN]->GetStatus()); | 418 | pad_state.left_sr.Assign(button_state[SR - BUTTON_HID_BEGIN]->GetStatus()); |
| 420 | } | 419 | } |
| 421 | 420 | ||
| 421 | if (controller_type == NPadControllerType::JoyRight) { | ||
| 422 | pad_state.right_sl.Assign(button_state[SL - BUTTON_HID_BEGIN]->GetStatus()); | ||
| 423 | pad_state.right_sr.Assign(button_state[SR - BUTTON_HID_BEGIN]->GetStatus()); | ||
| 424 | } | ||
| 425 | |||
| 422 | if (controller_type == NPadControllerType::GameCube) { | 426 | if (controller_type == NPadControllerType::GameCube) { |
| 423 | trigger_entry.l_analog = static_cast<s32>( | 427 | trigger_entry.l_analog = static_cast<s32>( |
| 424 | button_state[ZL - BUTTON_HID_BEGIN]->GetStatus() ? HID_TRIGGER_MAX : 0); | 428 | button_state[ZL - BUTTON_HID_BEGIN]->GetStatus() ? HID_TRIGGER_MAX : 0); |
| @@ -1134,6 +1138,10 @@ void Controller_NPad::SetUnintendedHomeButtonInputProtectionEnabled(bool is_prot | |||
| 1134 | unintended_home_button_input_protection[NPadIdToIndex(npad_id)] = is_protection_enabled; | 1138 | unintended_home_button_input_protection[NPadIdToIndex(npad_id)] = is_protection_enabled; |
| 1135 | } | 1139 | } |
| 1136 | 1140 | ||
| 1141 | void Controller_NPad::SetAnalogStickUseCenterClamp(bool use_center_clamp) { | ||
| 1142 | analog_stick_use_center_clamp = use_center_clamp; | ||
| 1143 | } | ||
| 1144 | |||
| 1137 | void Controller_NPad::ClearAllConnectedControllers() { | 1145 | void Controller_NPad::ClearAllConnectedControllers() { |
| 1138 | for (auto& controller : connected_controllers) { | 1146 | for (auto& controller : connected_controllers) { |
| 1139 | if (controller.is_connected && controller.type != NPadControllerType::None) { | 1147 | if (controller.is_connected && controller.type != NPadControllerType::None) { |
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index bc2e6779d..14d0ac067 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h | |||
| @@ -8,10 +8,10 @@ | |||
| 8 | #include <atomic> | 8 | #include <atomic> |
| 9 | #include "common/bit_field.h" | 9 | #include "common/bit_field.h" |
| 10 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 11 | #include "common/settings.h" | ||
| 11 | #include "core/frontend/input.h" | 12 | #include "core/frontend/input.h" |
| 12 | #include "core/hle/kernel/object.h" | 13 | #include "core/hle/kernel/object.h" |
| 13 | #include "core/hle/service/hid/controllers/controller_base.h" | 14 | #include "core/hle/service/hid/controllers/controller_base.h" |
| 14 | #include "core/settings.h" | ||
| 15 | 15 | ||
| 16 | namespace Kernel { | 16 | namespace Kernel { |
| 17 | class KEvent; | 17 | class KEvent; |
| @@ -219,6 +219,7 @@ public: | |||
| 219 | LedPattern GetLedPattern(u32 npad_id); | 219 | LedPattern GetLedPattern(u32 npad_id); |
| 220 | bool IsUnintendedHomeButtonInputProtectionEnabled(u32 npad_id) const; | 220 | bool IsUnintendedHomeButtonInputProtectionEnabled(u32 npad_id) const; |
| 221 | void SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled, u32 npad_id); | 221 | void SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled, u32 npad_id); |
| 222 | void SetAnalogStickUseCenterClamp(bool use_center_clamp); | ||
| 222 | void ClearAllConnectedControllers(); | 223 | void ClearAllConnectedControllers(); |
| 223 | void DisconnectAllConnectedControllers(); | 224 | void DisconnectAllConnectedControllers(); |
| 224 | void ConnectAllDisconnectedControllers(); | 225 | void ConnectAllDisconnectedControllers(); |
| @@ -577,6 +578,7 @@ private: | |||
| 577 | std::array<std::array<bool, 2>, 10> vibration_devices_mounted{}; | 578 | std::array<std::array<bool, 2>, 10> vibration_devices_mounted{}; |
| 578 | std::array<ControllerHolder, 10> connected_controllers{}; | 579 | std::array<ControllerHolder, 10> connected_controllers{}; |
| 579 | std::array<bool, 10> unintended_home_button_input_protection{}; | 580 | std::array<bool, 10> unintended_home_button_input_protection{}; |
| 581 | bool analog_stick_use_center_clamp{}; | ||
| 580 | GyroscopeZeroDriftMode gyroscope_zero_drift_mode{GyroscopeZeroDriftMode::Standard}; | 582 | GyroscopeZeroDriftMode gyroscope_zero_drift_mode{GyroscopeZeroDriftMode::Standard}; |
| 581 | bool sixaxis_sensors_enabled{true}; | 583 | bool sixaxis_sensors_enabled{true}; |
| 582 | f32 sixaxis_fusion_parameter1{}; | 584 | f32 sixaxis_fusion_parameter1{}; |
diff --git a/src/core/hle/service/hid/controllers/touchscreen.cpp b/src/core/hle/service/hid/controllers/touchscreen.cpp index be60492a4..b5f8077be 100644 --- a/src/core/hle/service/hid/controllers/touchscreen.cpp +++ b/src/core/hle/service/hid/controllers/touchscreen.cpp | |||
| @@ -6,11 +6,11 @@ | |||
| 6 | #include <cstring> | 6 | #include <cstring> |
| 7 | #include "common/common_types.h" | 7 | #include "common/common_types.h" |
| 8 | #include "common/logging/log.h" | 8 | #include "common/logging/log.h" |
| 9 | #include "common/settings.h" | ||
| 9 | #include "core/core_timing.h" | 10 | #include "core/core_timing.h" |
| 10 | #include "core/frontend/emu_window.h" | 11 | #include "core/frontend/emu_window.h" |
| 11 | #include "core/frontend/input.h" | 12 | #include "core/frontend/input.h" |
| 12 | #include "core/hle/service/hid/controllers/touchscreen.h" | 13 | #include "core/hle/service/hid/controllers/touchscreen.h" |
| 13 | #include "core/settings.h" | ||
| 14 | 14 | ||
| 15 | namespace Service::HID { | 15 | namespace Service::HID { |
| 16 | constexpr std::size_t SHARED_MEMORY_OFFSET = 0x400; | 16 | constexpr std::size_t SHARED_MEMORY_OFFSET = 0x400; |
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index ba27bbb05..4c1c0ac68 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | #include <array> | 5 | #include <array> |
| 6 | #include "common/common_types.h" | 6 | #include "common/common_types.h" |
| 7 | #include "common/logging/log.h" | 7 | #include "common/logging/log.h" |
| 8 | #include "common/settings.h" | ||
| 8 | #include "core/core.h" | 9 | #include "core/core.h" |
| 9 | #include "core/core_timing.h" | 10 | #include "core/core_timing.h" |
| 10 | #include "core/core_timing_util.h" | 11 | #include "core/core_timing_util.h" |
| @@ -23,7 +24,6 @@ | |||
| 23 | #include "core/hle/service/hid/irs.h" | 24 | #include "core/hle/service/hid/irs.h" |
| 24 | #include "core/hle/service/hid/xcd.h" | 25 | #include "core/hle/service/hid/xcd.h" |
| 25 | #include "core/hle/service/service.h" | 26 | #include "core/hle/service/service.h" |
| 26 | #include "core/settings.h" | ||
| 27 | 27 | ||
| 28 | #include "core/hle/service/hid/controllers/controller_base.h" | 28 | #include "core/hle/service/hid/controllers/controller_base.h" |
| 29 | #include "core/hle/service/hid/controllers/debug_pad.h" | 29 | #include "core/hle/service/hid/controllers/debug_pad.h" |
| @@ -263,7 +263,7 @@ Hid::Hid(Core::System& system_) : ServiceFramework{system_, "hid"} { | |||
| 263 | {131, &Hid::IsUnintendedHomeButtonInputProtectionEnabled, "IsUnintendedHomeButtonInputProtectionEnabled"}, | 263 | {131, &Hid::IsUnintendedHomeButtonInputProtectionEnabled, "IsUnintendedHomeButtonInputProtectionEnabled"}, |
| 264 | {132, &Hid::EnableUnintendedHomeButtonInputProtection, "EnableUnintendedHomeButtonInputProtection"}, | 264 | {132, &Hid::EnableUnintendedHomeButtonInputProtection, "EnableUnintendedHomeButtonInputProtection"}, |
| 265 | {133, nullptr, "SetNpadJoyAssignmentModeSingleWithDestination"}, | 265 | {133, nullptr, "SetNpadJoyAssignmentModeSingleWithDestination"}, |
| 266 | {134, nullptr, "SetNpadAnalogStickUseCenterClamp"}, | 266 | {134, &Hid::SetNpadAnalogStickUseCenterClamp, "SetNpadAnalogStickUseCenterClamp"}, |
| 267 | {135, nullptr, "SetNpadCaptureButtonAssignment"}, | 267 | {135, nullptr, "SetNpadCaptureButtonAssignment"}, |
| 268 | {136, nullptr, "ClearNpadCaptureButtonAssignment"}, | 268 | {136, nullptr, "ClearNpadCaptureButtonAssignment"}, |
| 269 | {200, &Hid::GetVibrationDeviceInfo, "GetVibrationDeviceInfo"}, | 269 | {200, &Hid::GetVibrationDeviceInfo, "GetVibrationDeviceInfo"}, |
| @@ -278,6 +278,7 @@ Hid::Hid(Core::System& system_) : ServiceFramework{system_, "hid"} { | |||
| 278 | {209, &Hid::BeginPermitVibrationSession, "BeginPermitVibrationSession"}, | 278 | {209, &Hid::BeginPermitVibrationSession, "BeginPermitVibrationSession"}, |
| 279 | {210, &Hid::EndPermitVibrationSession, "EndPermitVibrationSession"}, | 279 | {210, &Hid::EndPermitVibrationSession, "EndPermitVibrationSession"}, |
| 280 | {211, &Hid::IsVibrationDeviceMounted, "IsVibrationDeviceMounted"}, | 280 | {211, &Hid::IsVibrationDeviceMounted, "IsVibrationDeviceMounted"}, |
| 281 | {212, nullptr, "SendVibrationValueInBool"}, | ||
| 281 | {300, &Hid::ActivateConsoleSixAxisSensor, "ActivateConsoleSixAxisSensor"}, | 282 | {300, &Hid::ActivateConsoleSixAxisSensor, "ActivateConsoleSixAxisSensor"}, |
| 282 | {301, &Hid::StartConsoleSixAxisSensor, "StartConsoleSixAxisSensor"}, | 283 | {301, &Hid::StartConsoleSixAxisSensor, "StartConsoleSixAxisSensor"}, |
| 283 | {302, &Hid::StopConsoleSixAxisSensor, "StopConsoleSixAxisSensor"}, | 284 | {302, &Hid::StopConsoleSixAxisSensor, "StopConsoleSixAxisSensor"}, |
| @@ -1087,6 +1088,27 @@ void Hid::EnableUnintendedHomeButtonInputProtection(Kernel::HLERequestContext& c | |||
| 1087 | rb.Push(RESULT_SUCCESS); | 1088 | rb.Push(RESULT_SUCCESS); |
| 1088 | } | 1089 | } |
| 1089 | 1090 | ||
| 1091 | void Hid::SetNpadAnalogStickUseCenterClamp(Kernel::HLERequestContext& ctx) { | ||
| 1092 | IPC::RequestParser rp{ctx}; | ||
| 1093 | struct Parameters { | ||
| 1094 | bool analog_stick_use_center_clamp; | ||
| 1095 | u64 applet_resource_user_id; | ||
| 1096 | }; | ||
| 1097 | static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size."); | ||
| 1098 | |||
| 1099 | const auto parameters{rp.PopRaw<Parameters>()}; | ||
| 1100 | |||
| 1101 | applet_resource->GetController<Controller_NPad>(HidController::NPad) | ||
| 1102 | .SetAnalogStickUseCenterClamp(parameters.analog_stick_use_center_clamp); | ||
| 1103 | |||
| 1104 | LOG_WARNING(Service_HID, | ||
| 1105 | "(STUBBED) called, analog_stick_use_center_clamp={}, applet_resource_user_id={}", | ||
| 1106 | parameters.analog_stick_use_center_clamp, parameters.applet_resource_user_id); | ||
| 1107 | |||
| 1108 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1109 | rb.Push(RESULT_SUCCESS); | ||
| 1110 | } | ||
| 1111 | |||
| 1090 | void Hid::GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) { | 1112 | void Hid::GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) { |
| 1091 | IPC::RequestParser rp{ctx}; | 1113 | IPC::RequestParser rp{ctx}; |
| 1092 | const auto vibration_device_handle{rp.PopRaw<Controller_NPad::DeviceHandle>()}; | 1114 | const auto vibration_device_handle{rp.PopRaw<Controller_NPad::DeviceHandle>()}; |
| @@ -1553,6 +1575,7 @@ public: | |||
| 1553 | {11, nullptr, "SetTouchScreenAutoPilotState"}, | 1575 | {11, nullptr, "SetTouchScreenAutoPilotState"}, |
| 1554 | {12, nullptr, "UnsetTouchScreenAutoPilotState"}, | 1576 | {12, nullptr, "UnsetTouchScreenAutoPilotState"}, |
| 1555 | {13, nullptr, "GetTouchScreenConfiguration"}, | 1577 | {13, nullptr, "GetTouchScreenConfiguration"}, |
| 1578 | {14, nullptr, "ProcessTouchScreenAutoTune"}, | ||
| 1556 | {20, nullptr, "DeactivateMouse"}, | 1579 | {20, nullptr, "DeactivateMouse"}, |
| 1557 | {21, nullptr, "SetMouseAutoPilotState"}, | 1580 | {21, nullptr, "SetMouseAutoPilotState"}, |
| 1558 | {22, nullptr, "UnsetMouseAutoPilotState"}, | 1581 | {22, nullptr, "UnsetMouseAutoPilotState"}, |
| @@ -1562,6 +1585,7 @@ public: | |||
| 1562 | {50, nullptr, "DeactivateXpad"}, | 1585 | {50, nullptr, "DeactivateXpad"}, |
| 1563 | {51, nullptr, "SetXpadAutoPilotState"}, | 1586 | {51, nullptr, "SetXpadAutoPilotState"}, |
| 1564 | {52, nullptr, "UnsetXpadAutoPilotState"}, | 1587 | {52, nullptr, "UnsetXpadAutoPilotState"}, |
| 1588 | {53, nullptr, "DeactivateJoyXpad"}, | ||
| 1565 | {60, nullptr, "ClearNpadSystemCommonPolicy"}, | 1589 | {60, nullptr, "ClearNpadSystemCommonPolicy"}, |
| 1566 | {61, nullptr, "DeactivateNpad"}, | 1590 | {61, nullptr, "DeactivateNpad"}, |
| 1567 | {62, nullptr, "ForceDisconnectNpad"}, | 1591 | {62, nullptr, "ForceDisconnectNpad"}, |
| @@ -1632,6 +1656,11 @@ public: | |||
| 1632 | {244, nullptr, "RequestKuinaFirmwareVersion"}, | 1656 | {244, nullptr, "RequestKuinaFirmwareVersion"}, |
| 1633 | {245, nullptr, "GetKuinaFirmwareVersion"}, | 1657 | {245, nullptr, "GetKuinaFirmwareVersion"}, |
| 1634 | {246, nullptr, "GetVidPid"}, | 1658 | {246, nullptr, "GetVidPid"}, |
| 1659 | {247, nullptr, "GetAnalogStickCalibrationValue"}, | ||
| 1660 | {248, nullptr, "GetUniquePadIdsFull"}, | ||
| 1661 | {249, nullptr, "ConnectUniquePad"}, | ||
| 1662 | {250, nullptr, "IsVirtual"}, | ||
| 1663 | {251, nullptr, "GetAnalogStickModuleParam"}, | ||
| 1635 | {301, nullptr, "GetAbstractedPadHandles"}, | 1664 | {301, nullptr, "GetAbstractedPadHandles"}, |
| 1636 | {302, nullptr, "GetAbstractedPadState"}, | 1665 | {302, nullptr, "GetAbstractedPadState"}, |
| 1637 | {303, nullptr, "GetAbstractedPadsState"}, | 1666 | {303, nullptr, "GetAbstractedPadsState"}, |
| @@ -1652,12 +1681,16 @@ public: | |||
| 1652 | {401, nullptr, "DisableRailDeviceFiltering"}, | 1681 | {401, nullptr, "DisableRailDeviceFiltering"}, |
| 1653 | {402, nullptr, "EnableWiredPairing"}, | 1682 | {402, nullptr, "EnableWiredPairing"}, |
| 1654 | {403, nullptr, "EnableShipmentModeAutoClear"}, | 1683 | {403, nullptr, "EnableShipmentModeAutoClear"}, |
| 1684 | {404, nullptr, "SetRailEnabled"}, | ||
| 1655 | {500, nullptr, "SetFactoryInt"}, | 1685 | {500, nullptr, "SetFactoryInt"}, |
| 1656 | {501, nullptr, "IsFactoryBootEnabled"}, | 1686 | {501, nullptr, "IsFactoryBootEnabled"}, |
| 1657 | {550, nullptr, "SetAnalogStickModelDataTemporarily"}, | 1687 | {550, nullptr, "SetAnalogStickModelDataTemporarily"}, |
| 1658 | {551, nullptr, "GetAnalogStickModelData"}, | 1688 | {551, nullptr, "GetAnalogStickModelData"}, |
| 1659 | {552, nullptr, "ResetAnalogStickModelData"}, | 1689 | {552, nullptr, "ResetAnalogStickModelData"}, |
| 1660 | {600, nullptr, "ConvertPadState"}, | 1690 | {600, nullptr, "ConvertPadState"}, |
| 1691 | {650, nullptr, "AddButtonPlayData"}, | ||
| 1692 | {651, nullptr, "StartButtonPlayData"}, | ||
| 1693 | {652, nullptr, "StopButtonPlayData"}, | ||
| 1661 | {2000, nullptr, "DeactivateDigitizer"}, | 1694 | {2000, nullptr, "DeactivateDigitizer"}, |
| 1662 | {2001, nullptr, "SetDigitizerAutoPilotState"}, | 1695 | {2001, nullptr, "SetDigitizerAutoPilotState"}, |
| 1663 | {2002, nullptr, "UnsetDigitizerAutoPilotState"}, | 1696 | {2002, nullptr, "UnsetDigitizerAutoPilotState"}, |
| @@ -1689,6 +1722,8 @@ public: | |||
| 1689 | {215, nullptr, "IsNfcActivated"}, | 1722 | {215, nullptr, "IsNfcActivated"}, |
| 1690 | {230, nullptr, "AcquireIrSensorEventHandle"}, | 1723 | {230, nullptr, "AcquireIrSensorEventHandle"}, |
| 1691 | {231, nullptr, "ActivateIrSensor"}, | 1724 | {231, nullptr, "ActivateIrSensor"}, |
| 1725 | {232, nullptr, "GetIrSensorState"}, | ||
| 1726 | {233, nullptr, "GetXcdHandleForNpadWithIrSensor"}, | ||
| 1692 | {301, nullptr, "ActivateNpadSystem"}, | 1727 | {301, nullptr, "ActivateNpadSystem"}, |
| 1693 | {303, nullptr, "ApplyNpadSystemCommonPolicy"}, | 1728 | {303, nullptr, "ApplyNpadSystemCommonPolicy"}, |
| 1694 | {304, nullptr, "EnableAssigningSingleOnSlSrPress"}, | 1729 | {304, nullptr, "EnableAssigningSingleOnSlSrPress"}, |
| @@ -1703,9 +1738,16 @@ public: | |||
| 1703 | {313, nullptr, "GetNpadCaptureButtonAssignment"}, | 1738 | {313, nullptr, "GetNpadCaptureButtonAssignment"}, |
| 1704 | {314, nullptr, "GetAppletFooterUiType"}, | 1739 | {314, nullptr, "GetAppletFooterUiType"}, |
| 1705 | {315, nullptr, "GetAppletDetailedUiType"}, | 1740 | {315, nullptr, "GetAppletDetailedUiType"}, |
| 1741 | {316, nullptr, "GetNpadInterfaceType"}, | ||
| 1742 | {317, nullptr, "GetNpadLeftRightInterfaceType"}, | ||
| 1743 | {318, nullptr, "HasBattery"}, | ||
| 1744 | {319, nullptr, "HasLeftRightBattery"}, | ||
| 1706 | {321, nullptr, "GetUniquePadsFromNpad"}, | 1745 | {321, nullptr, "GetUniquePadsFromNpad"}, |
| 1707 | {322, nullptr, "GetIrSensorState"}, | 1746 | {322, nullptr, "GetIrSensorState"}, |
| 1708 | {323, nullptr, "GetXcdHandleForNpadWithIrSensor"}, | 1747 | {323, nullptr, "GetXcdHandleForNpadWithIrSensor"}, |
| 1748 | {324, nullptr, "GetUniquePadButtonSet"}, | ||
| 1749 | {325, nullptr, "GetUniquePadColor"}, | ||
| 1750 | {326, nullptr, "GetUniquePadAppletDetailedUiType"}, | ||
| 1709 | {500, nullptr, "SetAppletResourceUserId"}, | 1751 | {500, nullptr, "SetAppletResourceUserId"}, |
| 1710 | {501, nullptr, "RegisterAppletResourceUserId"}, | 1752 | {501, nullptr, "RegisterAppletResourceUserId"}, |
| 1711 | {502, nullptr, "UnregisterAppletResourceUserId"}, | 1753 | {502, nullptr, "UnregisterAppletResourceUserId"}, |
| @@ -1716,10 +1758,13 @@ public: | |||
| 1716 | {511, nullptr, "GetVibrationMasterVolume"}, | 1758 | {511, nullptr, "GetVibrationMasterVolume"}, |
| 1717 | {512, nullptr, "BeginPermitVibrationSession"}, | 1759 | {512, nullptr, "BeginPermitVibrationSession"}, |
| 1718 | {513, nullptr, "EndPermitVibrationSession"}, | 1760 | {513, nullptr, "EndPermitVibrationSession"}, |
| 1761 | {514, nullptr, "Unknown514"}, | ||
| 1719 | {520, nullptr, "EnableHandheldHids"}, | 1762 | {520, nullptr, "EnableHandheldHids"}, |
| 1720 | {521, nullptr, "DisableHandheldHids"}, | 1763 | {521, nullptr, "DisableHandheldHids"}, |
| 1721 | {522, nullptr, "SetJoyConRailEnabled"}, | 1764 | {522, nullptr, "SetJoyConRailEnabled"}, |
| 1722 | {523, nullptr, "IsJoyConRailEnabled"}, | 1765 | {523, nullptr, "IsJoyConRailEnabled"}, |
| 1766 | {524, nullptr, "IsHandheldHidsEnabled"}, | ||
| 1767 | {525, nullptr, "IsJoyConAttachedOnAllRail"}, | ||
| 1723 | {540, nullptr, "AcquirePlayReportControllerUsageUpdateEvent"}, | 1768 | {540, nullptr, "AcquirePlayReportControllerUsageUpdateEvent"}, |
| 1724 | {541, nullptr, "GetPlayReportControllerUsages"}, | 1769 | {541, nullptr, "GetPlayReportControllerUsages"}, |
| 1725 | {542, nullptr, "AcquirePlayReportRegisteredDeviceUpdateEvent"}, | 1770 | {542, nullptr, "AcquirePlayReportRegisteredDeviceUpdateEvent"}, |
| @@ -1795,6 +1840,65 @@ public: | |||
| 1795 | {1154, nullptr, "IsFirmwareAvailableForNotification"}, | 1840 | {1154, nullptr, "IsFirmwareAvailableForNotification"}, |
| 1796 | {1155, nullptr, "SetForceHandheldStyleVibration"}, | 1841 | {1155, nullptr, "SetForceHandheldStyleVibration"}, |
| 1797 | {1156, nullptr, "SendConnectionTriggerWithoutTimeoutEvent"}, | 1842 | {1156, nullptr, "SendConnectionTriggerWithoutTimeoutEvent"}, |
| 1843 | {1157, nullptr, "CancelConnectionTrigger"}, | ||
| 1844 | {1200, nullptr, "IsButtonConfigSupported"}, | ||
| 1845 | {1201, nullptr, "IsButtonConfigEmbeddedSupported"}, | ||
| 1846 | {1202, nullptr, "DeleteButtonConfig"}, | ||
| 1847 | {1203, nullptr, "DeleteButtonConfigEmbedded"}, | ||
| 1848 | {1204, nullptr, "SetButtonConfigEnabled"}, | ||
| 1849 | {1205, nullptr, "SetButtonConfigEmbeddedEnabled"}, | ||
| 1850 | {1206, nullptr, "IsButtonConfigEnabled"}, | ||
| 1851 | {1207, nullptr, "IsButtonConfigEmbeddedEnabled"}, | ||
| 1852 | {1208, nullptr, "SetButtonConfigEmbedded"}, | ||
| 1853 | {1209, nullptr, "SetButtonConfigFull"}, | ||
| 1854 | {1210, nullptr, "SetButtonConfigLeft"}, | ||
| 1855 | {1211, nullptr, "SetButtonConfigRight"}, | ||
| 1856 | {1212, nullptr, "GetButtonConfigEmbedded"}, | ||
| 1857 | {1213, nullptr, "GetButtonConfigFull"}, | ||
| 1858 | {1214, nullptr, "GetButtonConfigLeft"}, | ||
| 1859 | {1215, nullptr, "GetButtonConfigRight"}, | ||
| 1860 | {1250, nullptr, "IsCustomButtonConfigSupported"}, | ||
| 1861 | {1251, nullptr, "IsDefaultButtonConfigEmbedded"}, | ||
| 1862 | {1252, nullptr, "IsDefaultButtonConfigFull"}, | ||
| 1863 | {1253, nullptr, "IsDefaultButtonConfigLeft"}, | ||
| 1864 | {1254, nullptr, "IsDefaultButtonConfigRight"}, | ||
| 1865 | {1255, nullptr, "IsButtonConfigStorageEmbeddedEmpty"}, | ||
| 1866 | {1256, nullptr, "IsButtonConfigStorageFullEmpty"}, | ||
| 1867 | {1257, nullptr, "IsButtonConfigStorageLeftEmpty"}, | ||
| 1868 | {1258, nullptr, "IsButtonConfigStorageRightEmpty"}, | ||
| 1869 | {1259, nullptr, "GetButtonConfigStorageEmbeddedDeprecated"}, | ||
| 1870 | {1260, nullptr, "GetButtonConfigStorageFullDeprecated"}, | ||
| 1871 | {1261, nullptr, "GetButtonConfigStorageLeftDeprecated"}, | ||
| 1872 | {1262, nullptr, "GetButtonConfigStorageRightDeprecated"}, | ||
| 1873 | {1263, nullptr, "SetButtonConfigStorageEmbeddedDeprecated"}, | ||
| 1874 | {1264, nullptr, "SetButtonConfigStorageFullDeprecated"}, | ||
| 1875 | {1265, nullptr, "SetButtonConfigStorageLeftDeprecated"}, | ||
| 1876 | {1266, nullptr, "SetButtonConfigStorageRightDeprecated"}, | ||
| 1877 | {1267, nullptr, "DeleteButtonConfigStorageEmbedded"}, | ||
| 1878 | {1268, nullptr, "DeleteButtonConfigStorageFull"}, | ||
| 1879 | {1269, nullptr, "DeleteButtonConfigStorageLeft"}, | ||
| 1880 | {1270, nullptr, "DeleteButtonConfigStorageRight"}, | ||
| 1881 | {1271, nullptr, "IsUsingCustomButtonConfig"}, | ||
| 1882 | {1272, nullptr, "IsAnyCustomButtonConfigEnabled"}, | ||
| 1883 | {1273, nullptr, "SetAllCustomButtonConfigEnabled"}, | ||
| 1884 | {1274, nullptr, "SetDefaultButtonConfig"}, | ||
| 1885 | {1275, nullptr, "SetAllDefaultButtonConfig"}, | ||
| 1886 | {1276, nullptr, "SetHidButtonConfigEmbedded"}, | ||
| 1887 | {1277, nullptr, "SetHidButtonConfigFull"}, | ||
| 1888 | {1278, nullptr, "SetHidButtonConfigLeft"}, | ||
| 1889 | {1279, nullptr, "SetHidButtonConfigRight"}, | ||
| 1890 | {1280, nullptr, "GetHidButtonConfigEmbedded"}, | ||
| 1891 | {1281, nullptr, "GetHidButtonConfigFull"}, | ||
| 1892 | {1282, nullptr, "GetHidButtonConfigLeft"}, | ||
| 1893 | {1283, nullptr, "GetHidButtonConfigRight"}, | ||
| 1894 | {1284, nullptr, "GetButtonConfigStorageEmbedded"}, | ||
| 1895 | {1285, nullptr, "GetButtonConfigStorageFull"}, | ||
| 1896 | {1286, nullptr, "GetButtonConfigStorageLeft"}, | ||
| 1897 | {1287, nullptr, "GetButtonConfigStorageRight"}, | ||
| 1898 | {1288, nullptr, "SetButtonConfigStorageEmbedded"}, | ||
| 1899 | {1289, nullptr, "SetButtonConfigStorageFull"}, | ||
| 1900 | {1290, nullptr, "DeleteButtonConfigStorageRight"}, | ||
| 1901 | {1291, nullptr, "DeleteButtonConfigStorageRight"}, | ||
| 1798 | }; | 1902 | }; |
| 1799 | // clang-format on | 1903 | // clang-format on |
| 1800 | 1904 | ||
diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h index 36ed228c8..c2bdd39a3 100644 --- a/src/core/hle/service/hid/hid.h +++ b/src/core/hle/service/hid/hid.h | |||
| @@ -129,6 +129,7 @@ private: | |||
| 129 | void SwapNpadAssignment(Kernel::HLERequestContext& ctx); | 129 | void SwapNpadAssignment(Kernel::HLERequestContext& ctx); |
| 130 | void IsUnintendedHomeButtonInputProtectionEnabled(Kernel::HLERequestContext& ctx); | 130 | void IsUnintendedHomeButtonInputProtectionEnabled(Kernel::HLERequestContext& ctx); |
| 131 | void EnableUnintendedHomeButtonInputProtection(Kernel::HLERequestContext& ctx); | 131 | void EnableUnintendedHomeButtonInputProtection(Kernel::HLERequestContext& ctx); |
| 132 | void SetNpadAnalogStickUseCenterClamp(Kernel::HLERequestContext& ctx); | ||
| 132 | void GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx); | 133 | void GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx); |
| 133 | void SendVibrationValue(Kernel::HLERequestContext& ctx); | 134 | void SendVibrationValue(Kernel::HLERequestContext& ctx); |
| 134 | void GetActualVibrationValue(Kernel::HLERequestContext& ctx); | 135 | void GetActualVibrationValue(Kernel::HLERequestContext& ctx); |
diff --git a/src/core/hle/service/hid/xcd.cpp b/src/core/hle/service/hid/xcd.cpp index 43a8840d0..b1efa3d05 100644 --- a/src/core/hle/service/hid/xcd.cpp +++ b/src/core/hle/service/hid/xcd.cpp | |||
| @@ -28,6 +28,8 @@ XCD_SYS::XCD_SYS(Core::System& system_) : ServiceFramework{system_, "xcd:sys"} { | |||
| 28 | {20, nullptr, "StartMifareWrite"}, | 28 | {20, nullptr, "StartMifareWrite"}, |
| 29 | {101, nullptr, "GetAwakeTriggerReasonForLeftRail"}, | 29 | {101, nullptr, "GetAwakeTriggerReasonForLeftRail"}, |
| 30 | {102, nullptr, "GetAwakeTriggerReasonForRightRail"}, | 30 | {102, nullptr, "GetAwakeTriggerReasonForRightRail"}, |
| 31 | {103, nullptr, "GetAwakeTriggerBatteryLevelTransitionForLeftRail"}, | ||
| 32 | {104, nullptr, "GetAwakeTriggerBatteryLevelTransitionForRightRail"}, | ||
| 31 | }; | 33 | }; |
| 32 | // clang-format on | 34 | // clang-format on |
| 33 | 35 | ||
diff --git a/src/core/hle/service/ldr/ldr.cpp b/src/core/hle/service/ldr/ldr.cpp index d111c1357..c8bc60ad1 100644 --- a/src/core/hle/service/ldr/ldr.cpp +++ b/src/core/hle/service/ldr/ldr.cpp | |||
| @@ -118,9 +118,9 @@ public: | |||
| 118 | explicit DebugMonitor(Core::System& system_) : ServiceFramework{system_, "ldr:dmnt"} { | 118 | explicit DebugMonitor(Core::System& system_) : ServiceFramework{system_, "ldr:dmnt"} { |
| 119 | // clang-format off | 119 | // clang-format off |
| 120 | static const FunctionInfo functions[] = { | 120 | static const FunctionInfo functions[] = { |
| 121 | {0, nullptr, "AddProcessToDebugLaunchQueue"}, | 121 | {0, nullptr, "SetProgramArgument"}, |
| 122 | {1, nullptr, "ClearDebugLaunchQueue"}, | 122 | {1, nullptr, "FlushArguments"}, |
| 123 | {2, nullptr, "GetNsoInfos"}, | 123 | {2, nullptr, "GetProcessModuleInfo"}, |
| 124 | }; | 124 | }; |
| 125 | // clang-format on | 125 | // clang-format on |
| 126 | 126 | ||
| @@ -135,8 +135,8 @@ public: | |||
| 135 | static const FunctionInfo functions[] = { | 135 | static const FunctionInfo functions[] = { |
| 136 | {0, nullptr, "CreateProcess"}, | 136 | {0, nullptr, "CreateProcess"}, |
| 137 | {1, nullptr, "GetProgramInfo"}, | 137 | {1, nullptr, "GetProgramInfo"}, |
| 138 | {2, nullptr, "RegisterTitle"}, | 138 | {2, nullptr, "PinProgram"}, |
| 139 | {3, nullptr, "UnregisterTitle"}, | 139 | {3, nullptr, "UnpinProgram"}, |
| 140 | {4, nullptr, "SetEnabledProgramVerification"}, | 140 | {4, nullptr, "SetEnabledProgramVerification"}, |
| 141 | }; | 141 | }; |
| 142 | // clang-format on | 142 | // clang-format on |
| @@ -150,8 +150,8 @@ public: | |||
| 150 | explicit Shell(Core::System& system_) : ServiceFramework{system_, "ldr:shel"} { | 150 | explicit Shell(Core::System& system_) : ServiceFramework{system_, "ldr:shel"} { |
| 151 | // clang-format off | 151 | // clang-format off |
| 152 | static const FunctionInfo functions[] = { | 152 | static const FunctionInfo functions[] = { |
| 153 | {0, nullptr, "AddProcessToLaunchQueue"}, | 153 | {0, nullptr, "SetProgramArgument"}, |
| 154 | {1, nullptr, "ClearLaunchQueue"}, | 154 | {1, nullptr, "FlushArguments"}, |
| 155 | }; | 155 | }; |
| 156 | // clang-format on | 156 | // clang-format on |
| 157 | 157 | ||
| @@ -164,19 +164,19 @@ public: | |||
| 164 | explicit RelocatableObject(Core::System& system_) : ServiceFramework{system_, "ldr:ro"} { | 164 | explicit RelocatableObject(Core::System& system_) : ServiceFramework{system_, "ldr:ro"} { |
| 165 | // clang-format off | 165 | // clang-format off |
| 166 | static const FunctionInfo functions[] = { | 166 | static const FunctionInfo functions[] = { |
| 167 | {0, &RelocatableObject::LoadNro, "LoadNro"}, | 167 | {0, &RelocatableObject::LoadModule, "LoadModule"}, |
| 168 | {1, &RelocatableObject::UnloadNro, "UnloadNro"}, | 168 | {1, &RelocatableObject::UnloadModule, "UnloadModule"}, |
| 169 | {2, &RelocatableObject::LoadNrr, "LoadNrr"}, | 169 | {2, &RelocatableObject::RegisterModuleInfo, "RegisterModuleInfo"}, |
| 170 | {3, &RelocatableObject::UnloadNrr, "UnloadNrr"}, | 170 | {3, &RelocatableObject::UnregisterModuleInfo, "UnregisterModuleInfo"}, |
| 171 | {4, &RelocatableObject::Initialize, "Initialize"}, | 171 | {4, &RelocatableObject::Initialize, "Initialize"}, |
| 172 | {10, nullptr, "LoadNrrEx"}, | 172 | {10, nullptr, "RegisterModuleInfo2"}, |
| 173 | }; | 173 | }; |
| 174 | // clang-format on | 174 | // clang-format on |
| 175 | 175 | ||
| 176 | RegisterHandlers(functions); | 176 | RegisterHandlers(functions); |
| 177 | } | 177 | } |
| 178 | 178 | ||
| 179 | void LoadNrr(Kernel::HLERequestContext& ctx) { | 179 | void RegisterModuleInfo(Kernel::HLERequestContext& ctx) { |
| 180 | struct Parameters { | 180 | struct Parameters { |
| 181 | u64_le process_id; | 181 | u64_le process_id; |
| 182 | u64_le nrr_address; | 182 | u64_le nrr_address; |
| @@ -273,7 +273,7 @@ public: | |||
| 273 | rb.Push(RESULT_SUCCESS); | 273 | rb.Push(RESULT_SUCCESS); |
| 274 | } | 274 | } |
| 275 | 275 | ||
| 276 | void UnloadNrr(Kernel::HLERequestContext& ctx) { | 276 | void UnregisterModuleInfo(Kernel::HLERequestContext& ctx) { |
| 277 | IPC::RequestParser rp{ctx}; | 277 | IPC::RequestParser rp{ctx}; |
| 278 | const auto pid = rp.Pop<u64>(); | 278 | const auto pid = rp.Pop<u64>(); |
| 279 | const auto nrr_address = rp.Pop<VAddr>(); | 279 | const auto nrr_address = rp.Pop<VAddr>(); |
| @@ -408,7 +408,7 @@ public: | |||
| 408 | data_start, bss_end_addr - data_start, Kernel::KMemoryPermission::ReadAndWrite); | 408 | data_start, bss_end_addr - data_start, Kernel::KMemoryPermission::ReadAndWrite); |
| 409 | } | 409 | } |
| 410 | 410 | ||
| 411 | void LoadNro(Kernel::HLERequestContext& ctx) { | 411 | void LoadModule(Kernel::HLERequestContext& ctx) { |
| 412 | struct Parameters { | 412 | struct Parameters { |
| 413 | u64_le process_id; | 413 | u64_le process_id; |
| 414 | u64_le image_address; | 414 | u64_le image_address; |
| @@ -546,7 +546,7 @@ public: | |||
| 546 | return RESULT_SUCCESS; | 546 | return RESULT_SUCCESS; |
| 547 | } | 547 | } |
| 548 | 548 | ||
| 549 | void UnloadNro(Kernel::HLERequestContext& ctx) { | 549 | void UnloadModule(Kernel::HLERequestContext& ctx) { |
| 550 | if (!initialized) { | 550 | if (!initialized) { |
| 551 | LOG_ERROR(Service_LDR, "LDR:RO not initialized before use!"); | 551 | LOG_ERROR(Service_LDR, "LDR:RO not initialized before use!"); |
| 552 | IPC::ResponseBuilder rb{ctx, 2}; | 552 | IPC::ResponseBuilder rb{ctx, 2}; |
diff --git a/src/core/hle/service/nfc/nfc.cpp b/src/core/hle/service/nfc/nfc.cpp index 6ab35de47..44a5d5789 100644 --- a/src/core/hle/service/nfc/nfc.cpp +++ b/src/core/hle/service/nfc/nfc.cpp | |||
| @@ -5,12 +5,12 @@ | |||
| 5 | #include <memory> | 5 | #include <memory> |
| 6 | 6 | ||
| 7 | #include "common/logging/log.h" | 7 | #include "common/logging/log.h" |
| 8 | #include "common/settings.h" | ||
| 8 | #include "core/hle/ipc_helpers.h" | 9 | #include "core/hle/ipc_helpers.h" |
| 9 | #include "core/hle/kernel/hle_ipc.h" | 10 | #include "core/hle/kernel/hle_ipc.h" |
| 10 | #include "core/hle/service/nfc/nfc.h" | 11 | #include "core/hle/service/nfc/nfc.h" |
| 11 | #include "core/hle/service/service.h" | 12 | #include "core/hle/service/service.h" |
| 12 | #include "core/hle/service/sm/sm.h" | 13 | #include "core/hle/service/sm/sm.h" |
| 13 | #include "core/settings.h" | ||
| 14 | 14 | ||
| 15 | namespace Service::NFC { | 15 | namespace Service::NFC { |
| 16 | 16 | ||
diff --git a/src/core/hle/service/nifm/nifm.cpp b/src/core/hle/service/nifm/nifm.cpp index afb3342d6..9f110df8e 100644 --- a/src/core/hle/service/nifm/nifm.cpp +++ b/src/core/hle/service/nifm/nifm.cpp | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include "common/settings.h" | ||
| 5 | #include "core/core.h" | 6 | #include "core/core.h" |
| 6 | #include "core/hle/ipc_helpers.h" | 7 | #include "core/hle/ipc_helpers.h" |
| 7 | #include "core/hle/kernel/k_event.h" | 8 | #include "core/hle/kernel/k_event.h" |
| @@ -10,7 +11,6 @@ | |||
| 10 | #include "core/hle/service/nifm/nifm.h" | 11 | #include "core/hle/service/nifm/nifm.h" |
| 11 | #include "core/hle/service/service.h" | 12 | #include "core/hle/service/service.h" |
| 12 | #include "core/network/network.h" | 13 | #include "core/network/network.h" |
| 13 | #include "core/settings.h" | ||
| 14 | 14 | ||
| 15 | namespace Service::NIFM { | 15 | namespace Service::NIFM { |
| 16 | 16 | ||
diff --git a/src/core/hle/service/nim/nim.cpp b/src/core/hle/service/nim/nim.cpp index f3be0b878..fee360ab9 100644 --- a/src/core/hle/service/nim/nim.cpp +++ b/src/core/hle/service/nim/nim.cpp | |||
| @@ -125,51 +125,51 @@ public: | |||
| 125 | {39, nullptr, "PrepareShutdown"}, | 125 | {39, nullptr, "PrepareShutdown"}, |
| 126 | {40, nullptr, "ListApplyDeltaTask"}, | 126 | {40, nullptr, "ListApplyDeltaTask"}, |
| 127 | {41, nullptr, "ClearNotEnoughSpaceStateOfApplyDeltaTask"}, | 127 | {41, nullptr, "ClearNotEnoughSpaceStateOfApplyDeltaTask"}, |
| 128 | {42, nullptr, "Unknown42"}, | 128 | {42, nullptr, "CreateApplyDeltaTaskFromDownloadTask"}, |
| 129 | {43, nullptr, "Unknown43"}, | 129 | {43, nullptr, "GetBackgroundApplyDeltaStressTaskInfo"}, |
| 130 | {44, nullptr, "Unknown44"}, | 130 | {44, nullptr, "GetApplyDeltaTaskRequiredStorage"}, |
| 131 | {45, nullptr, "Unknown45"}, | 131 | {45, nullptr, "CalculateNetworkInstallTaskContentsSize"}, |
| 132 | {46, nullptr, "Unknown46"}, | 132 | {46, nullptr, "PrepareShutdownForSystemUpdate"}, |
| 133 | {47, nullptr, "Unknown47"}, | 133 | {47, nullptr, "FindMaxRequiredApplicationVersionOfTask"}, |
| 134 | {48, nullptr, "Unknown48"}, | 134 | {48, nullptr, "CommitNetworkInstallTaskPartially"}, |
| 135 | {49, nullptr, "Unknown49"}, | 135 | {49, nullptr, "ListNetworkInstallTaskCommittedContentMeta"}, |
| 136 | {50, nullptr, "Unknown50"}, | 136 | {50, nullptr, "ListNetworkInstallTaskNotCommittedContentMeta"}, |
| 137 | {51, nullptr, "Unknown51"}, | 137 | {51, nullptr, "FindMaxRequiredSystemVersionOfTask"}, |
| 138 | {52, nullptr, "Unknown52"}, | 138 | {52, nullptr, "GetNetworkInstallTaskErrorContext"}, |
| 139 | {53, nullptr, "Unknown53"}, | 139 | {53, nullptr, "CreateLocalCommunicationReceiveApplicationTask"}, |
| 140 | {54, nullptr, "Unknown54"}, | 140 | {54, nullptr, "DestroyLocalCommunicationReceiveApplicationTask"}, |
| 141 | {55, nullptr, "Unknown55"}, | 141 | {55, nullptr, "ListLocalCommunicationReceiveApplicationTask"}, |
| 142 | {56, nullptr, "Unknown56"}, | 142 | {56, nullptr, "RequestLocalCommunicationReceiveApplicationTaskRun"}, |
| 143 | {57, nullptr, "Unknown57"}, | 143 | {57, nullptr, "GetLocalCommunicationReceiveApplicationTaskInfo"}, |
| 144 | {58, nullptr, "Unknown58"}, | 144 | {58, nullptr, "CommitLocalCommunicationReceiveApplicationTask"}, |
| 145 | {59, nullptr, "Unknown59"}, | 145 | {59, nullptr, "ListLocalCommunicationReceiveApplicationTaskContentMeta"}, |
| 146 | {60, nullptr, "Unknown60"}, | 146 | {60, nullptr, "CreateLocalCommunicationSendApplicationTask"}, |
| 147 | {61, nullptr, "Unknown61"}, | 147 | {61, nullptr, "RequestLocalCommunicationSendApplicationTaskRun"}, |
| 148 | {62, nullptr, "Unknown62"}, | 148 | {62, nullptr, "GetLocalCommunicationReceiveApplicationTaskErrorContext"}, |
| 149 | {63, nullptr, "Unknown63"}, | 149 | {63, nullptr, "GetLocalCommunicationSendApplicationTaskInfo"}, |
| 150 | {64, nullptr, "Unknown64"}, | 150 | {64, nullptr, "DestroyLocalCommunicationSendApplicationTask"}, |
| 151 | {65, nullptr, "Unknown65"}, | 151 | {65, nullptr, "GetLocalCommunicationSendApplicationTaskErrorContext"}, |
| 152 | {66, nullptr, "Unknown66"}, | 152 | {66, nullptr, "CalculateLocalCommunicationReceiveApplicationTaskRequiredSize"}, |
| 153 | {67, nullptr, "Unknown67"}, | 153 | {67, nullptr, "ListApplicationLocalCommunicationReceiveApplicationTask"}, |
| 154 | {68, nullptr, "Unknown68"}, | 154 | {68, nullptr, "ListApplicationLocalCommunicationSendApplicationTask"}, |
| 155 | {69, nullptr, "Unknown69"}, | 155 | {69, nullptr, "CreateLocalCommunicationReceiveSystemUpdateTask"}, |
| 156 | {70, nullptr, "Unknown70"}, | 156 | {70, nullptr, "DestroyLocalCommunicationReceiveSystemUpdateTask"}, |
| 157 | {71, nullptr, "Unknown71"}, | 157 | {71, nullptr, "ListLocalCommunicationReceiveSystemUpdateTask"}, |
| 158 | {72, nullptr, "Unknown72"}, | 158 | {72, nullptr, "RequestLocalCommunicationReceiveSystemUpdateTaskRun"}, |
| 159 | {73, nullptr, "Unknown73"}, | 159 | {73, nullptr, "GetLocalCommunicationReceiveSystemUpdateTaskInfo"}, |
| 160 | {74, nullptr, "Unknown74"}, | 160 | {74, nullptr, "CommitLocalCommunicationReceiveSystemUpdateTask"}, |
| 161 | {75, nullptr, "Unknown75"}, | 161 | {75, nullptr, "GetLocalCommunicationReceiveSystemUpdateTaskErrorContext"}, |
| 162 | {76, nullptr, "Unknown76"}, | 162 | {76, nullptr, "CreateLocalCommunicationSendSystemUpdateTask"}, |
| 163 | {77, nullptr, "Unknown77"}, | 163 | {77, nullptr, "RequestLocalCommunicationSendSystemUpdateTaskRun"}, |
| 164 | {78, nullptr, "Unknown78"}, | 164 | {78, nullptr, "GetLocalCommunicationSendSystemUpdateTaskInfo"}, |
| 165 | {79, nullptr, "Unknown79"}, | 165 | {79, nullptr, "DestroyLocalCommunicationSendSystemUpdateTask"}, |
| 166 | {80, nullptr, "Unknown80"}, | 166 | {80, nullptr, "GetLocalCommunicationSendSystemUpdateTaskErrorContext"}, |
| 167 | {81, nullptr, "Unknown81"}, | 167 | {81, nullptr, "ListLocalCommunicationSendSystemUpdateTask"}, |
| 168 | {82, nullptr, "Unknown82"}, | 168 | {82, nullptr, "GetReceivedSystemDataPath"}, |
| 169 | {83, nullptr, "Unknown83"}, | 169 | {83, nullptr, "CalculateApplyDeltaTaskOccupiedSize"}, |
| 170 | {84, nullptr, "Unknown84"}, | 170 | {84, nullptr, "Unknown84"}, |
| 171 | {85, nullptr, "Unknown85"}, | 171 | {85, nullptr, "ListNetworkInstallTaskContentMetaFromInstallMeta"}, |
| 172 | {86, nullptr, "Unknown86"}, | 172 | {86, nullptr, "ListNetworkInstallTaskOccupiedSize"}, |
| 173 | {87, nullptr, "Unknown87"}, | 173 | {87, nullptr, "Unknown87"}, |
| 174 | {88, nullptr, "Unknown88"}, | 174 | {88, nullptr, "Unknown88"}, |
| 175 | {89, nullptr, "Unknown89"}, | 175 | {89, nullptr, "Unknown89"}, |
| @@ -202,6 +202,17 @@ public: | |||
| 202 | {116, nullptr, "Unknown116"}, | 202 | {116, nullptr, "Unknown116"}, |
| 203 | {117, nullptr, "Unknown117"}, | 203 | {117, nullptr, "Unknown117"}, |
| 204 | {118, nullptr, "Unknown118"}, | 204 | {118, nullptr, "Unknown118"}, |
| 205 | {119, nullptr, "Unknown119"}, | ||
| 206 | {120, nullptr, "Unknown120"}, | ||
| 207 | {121, nullptr, "Unknown121"}, | ||
| 208 | {122, nullptr, "Unknown122"}, | ||
| 209 | {123, nullptr, "Unknown123"}, | ||
| 210 | {124, nullptr, "Unknown124"}, | ||
| 211 | {125, nullptr, "Unknown125"}, | ||
| 212 | {126, nullptr, "Unknown126"}, | ||
| 213 | {127, nullptr, "Unknown127"}, | ||
| 214 | {128, nullptr, "Unknown128"}, | ||
| 215 | {129, nullptr, "Unknown129"}, | ||
| 205 | }; | 216 | }; |
| 206 | // clang-format on | 217 | // clang-format on |
| 207 | 218 | ||
diff --git a/src/core/hle/service/npns/npns.cpp b/src/core/hle/service/npns/npns.cpp index f7a58f659..e4c703da4 100644 --- a/src/core/hle/service/npns/npns.cpp +++ b/src/core/hle/service/npns/npns.cpp | |||
| @@ -49,6 +49,8 @@ public: | |||
| 49 | {151, nullptr, "GetStateWithHandover"}, | 49 | {151, nullptr, "GetStateWithHandover"}, |
| 50 | {152, nullptr, "GetStateChangeEventWithHandover"}, | 50 | {152, nullptr, "GetStateChangeEventWithHandover"}, |
| 51 | {153, nullptr, "GetDropEventWithHandover"}, | 51 | {153, nullptr, "GetDropEventWithHandover"}, |
| 52 | {154, nullptr, "CreateTokenAsync"}, | ||
| 53 | {155, nullptr, "CreateTokenAsyncWithApplicationId"}, | ||
| 52 | {161, nullptr, "GetRequestChangeStateCancelEvent"}, | 54 | {161, nullptr, "GetRequestChangeStateCancelEvent"}, |
| 53 | {162, nullptr, "RequestChangeStateForceTimedWithCancelEvent"}, | 55 | {162, nullptr, "RequestChangeStateForceTimedWithCancelEvent"}, |
| 54 | {201, nullptr, "RequestChangeStateForceTimed"}, | 56 | {201, nullptr, "RequestChangeStateForceTimed"}, |
| @@ -84,6 +86,7 @@ public: | |||
| 84 | {151, nullptr, "GetStateWithHandover"}, | 86 | {151, nullptr, "GetStateWithHandover"}, |
| 85 | {152, nullptr, "GetStateChangeEventWithHandover"}, | 87 | {152, nullptr, "GetStateChangeEventWithHandover"}, |
| 86 | {153, nullptr, "GetDropEventWithHandover"}, | 88 | {153, nullptr, "GetDropEventWithHandover"}, |
| 89 | {154, nullptr, "CreateTokenAsync"}, | ||
| 87 | }; | 90 | }; |
| 88 | // clang-format on | 91 | // clang-format on |
| 89 | 92 | ||
diff --git a/src/core/hle/service/ns/ns.cpp b/src/core/hle/service/ns/ns.cpp index 6ccf8995c..e373609a1 100644 --- a/src/core/hle/service/ns/ns.cpp +++ b/src/core/hle/service/ns/ns.cpp | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include "common/logging/log.h" | 5 | #include "common/logging/log.h" |
| 6 | #include "common/settings.h" | ||
| 6 | #include "core/core.h" | 7 | #include "core/core.h" |
| 7 | #include "core/file_sys/control_metadata.h" | 8 | #include "core/file_sys/control_metadata.h" |
| 8 | #include "core/file_sys/patch_manager.h" | 9 | #include "core/file_sys/patch_manager.h" |
| @@ -14,7 +15,6 @@ | |||
| 14 | #include "core/hle/service/ns/ns.h" | 15 | #include "core/hle/service/ns/ns.h" |
| 15 | #include "core/hle/service/ns/pl_u.h" | 16 | #include "core/hle/service/ns/pl_u.h" |
| 16 | #include "core/hle/service/set/set.h" | 17 | #include "core/hle/service/set/set.h" |
| 17 | #include "core/settings.h" | ||
| 18 | 18 | ||
| 19 | namespace Service::NS { | 19 | namespace Service::NS { |
| 20 | 20 | ||
| @@ -55,6 +55,7 @@ IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_ | |||
| 55 | {26, nullptr, "BeginInstallApplication"}, | 55 | {26, nullptr, "BeginInstallApplication"}, |
| 56 | {27, nullptr, "DeleteApplicationRecord"}, | 56 | {27, nullptr, "DeleteApplicationRecord"}, |
| 57 | {30, nullptr, "RequestApplicationUpdateInfo"}, | 57 | {30, nullptr, "RequestApplicationUpdateInfo"}, |
| 58 | {31, nullptr, "Unknown31"}, | ||
| 58 | {32, nullptr, "CancelApplicationDownload"}, | 59 | {32, nullptr, "CancelApplicationDownload"}, |
| 59 | {33, nullptr, "ResumeApplicationDownload"}, | 60 | {33, nullptr, "ResumeApplicationDownload"}, |
| 60 | {35, nullptr, "UpdateVersionList"}, | 61 | {35, nullptr, "UpdateVersionList"}, |
| @@ -182,6 +183,7 @@ IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_ | |||
| 182 | {913, nullptr, "ListAllApplicationRecord"}, | 183 | {913, nullptr, "ListAllApplicationRecord"}, |
| 183 | {914, nullptr, "HideApplicationRecord"}, | 184 | {914, nullptr, "HideApplicationRecord"}, |
| 184 | {915, nullptr, "ShowApplicationRecord"}, | 185 | {915, nullptr, "ShowApplicationRecord"}, |
| 186 | {916, nullptr, "IsApplicationAutoDeleteDisabled"}, | ||
| 185 | {1000, nullptr, "RequestVerifyApplicationDeprecated"}, | 187 | {1000, nullptr, "RequestVerifyApplicationDeprecated"}, |
| 186 | {1001, nullptr, "CorruptApplicationForDebug"}, | 188 | {1001, nullptr, "CorruptApplicationForDebug"}, |
| 187 | {1002, nullptr, "RequestVerifyAddOnContentsRights"}, | 189 | {1002, nullptr, "RequestVerifyAddOnContentsRights"}, |
| @@ -201,6 +203,8 @@ IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_ | |||
| 201 | {1310, nullptr, "RequestMoveApplicationEntity"}, | 203 | {1310, nullptr, "RequestMoveApplicationEntity"}, |
| 202 | {1311, nullptr, "EstimateSizeToMove"}, | 204 | {1311, nullptr, "EstimateSizeToMove"}, |
| 203 | {1312, nullptr, "HasMovableEntity"}, | 205 | {1312, nullptr, "HasMovableEntity"}, |
| 206 | {1313, nullptr, "CleanupOrphanContents"}, | ||
| 207 | {1314, nullptr, "CheckPreconditionSatisfiedToMove"}, | ||
| 204 | {1400, nullptr, "PrepareShutdown"}, | 208 | {1400, nullptr, "PrepareShutdown"}, |
| 205 | {1500, nullptr, "FormatSdCard"}, | 209 | {1500, nullptr, "FormatSdCard"}, |
| 206 | {1501, nullptr, "NeedsSystemUpdateToFormatSdCard"}, | 210 | {1501, nullptr, "NeedsSystemUpdateToFormatSdCard"}, |
| @@ -215,6 +219,7 @@ IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_ | |||
| 215 | {1702, nullptr, "GetApplicationDownloadTaskStatus"}, | 219 | {1702, nullptr, "GetApplicationDownloadTaskStatus"}, |
| 216 | {1703, nullptr, "GetApplicationViewDownloadErrorContext"}, | 220 | {1703, nullptr, "GetApplicationViewDownloadErrorContext"}, |
| 217 | {1704, nullptr, "GetApplicationViewWithPromotionInfo"}, | 221 | {1704, nullptr, "GetApplicationViewWithPromotionInfo"}, |
| 222 | {1705, nullptr, "IsPatchAutoDeletableApplication"}, | ||
| 218 | {1800, nullptr, "IsNotificationSetupCompleted"}, | 223 | {1800, nullptr, "IsNotificationSetupCompleted"}, |
| 219 | {1801, nullptr, "GetLastNotificationInfoCount"}, | 224 | {1801, nullptr, "GetLastNotificationInfoCount"}, |
| 220 | {1802, nullptr, "ListLastNotificationInfo"}, | 225 | {1802, nullptr, "ListLastNotificationInfo"}, |
| @@ -269,6 +274,9 @@ IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_ | |||
| 269 | {2351, nullptr, "RequestNoDownloadRightsErrorResolution"}, | 274 | {2351, nullptr, "RequestNoDownloadRightsErrorResolution"}, |
| 270 | {2352, nullptr, "RequestResolveNoDownloadRightsError"}, | 275 | {2352, nullptr, "RequestResolveNoDownloadRightsError"}, |
| 271 | {2353, nullptr, "GetApplicationDownloadTaskInfo"}, | 276 | {2353, nullptr, "GetApplicationDownloadTaskInfo"}, |
| 277 | {2354, nullptr, "PrioritizeApplicationBackgroundTask"}, | ||
| 278 | {2355, nullptr, "Unknown2355"}, | ||
| 279 | {2356, nullptr, "Unknown2356"}, | ||
| 272 | {2400, nullptr, "GetPromotionInfo"}, | 280 | {2400, nullptr, "GetPromotionInfo"}, |
| 273 | {2401, nullptr, "CountPromotionInfo"}, | 281 | {2401, nullptr, "CountPromotionInfo"}, |
| 274 | {2402, nullptr, "ListPromotionInfo"}, | 282 | {2402, nullptr, "ListPromotionInfo"}, |
| @@ -282,6 +290,21 @@ IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_ | |||
| 282 | {2515, nullptr, "CleanupAllPlaceHolderAndFragmentsIfNoTask"}, | 290 | {2515, nullptr, "CleanupAllPlaceHolderAndFragmentsIfNoTask"}, |
| 283 | {2516, nullptr, "EnsureApplicationCertificate"}, | 291 | {2516, nullptr, "EnsureApplicationCertificate"}, |
| 284 | {2800, nullptr, "GetApplicationIdOfPreomia"}, | 292 | {2800, nullptr, "GetApplicationIdOfPreomia"}, |
| 293 | {3000, nullptr, "RegisterDeviceLockKey"}, | ||
| 294 | {3001, nullptr, "UnregisterDeviceLockKey"}, | ||
| 295 | {3002, nullptr, "VerifyDeviceLockKey"}, | ||
| 296 | {3003, nullptr, "HideApplicationIcon"}, | ||
| 297 | {3004, nullptr, "ShowApplicationIcon"}, | ||
| 298 | {3005, nullptr, "HideApplicationTitle"}, | ||
| 299 | {3006, nullptr, "ShowApplicationTitle"}, | ||
| 300 | {3007, nullptr, "EnableGameCard"}, | ||
| 301 | {3008, nullptr, "DisableGameCard"}, | ||
| 302 | {3009, nullptr, "EnableLocalContentShare"}, | ||
| 303 | {3010, nullptr, "DisableLocalContentShare"}, | ||
| 304 | {3011, nullptr, "IsApplicationIconHidden"}, | ||
| 305 | {3012, nullptr, "IsApplicationTitleHidden"}, | ||
| 306 | {3013, nullptr, "IsGameCardEnabled"}, | ||
| 307 | {3014, nullptr, "IsLocalContentShareEnabled"}, | ||
| 285 | {9999, nullptr, "GetApplicationCertificate"}, | 308 | {9999, nullptr, "GetApplicationCertificate"}, |
| 286 | }; | 309 | }; |
| 287 | // clang-format on | 310 | // clang-format on |
| @@ -441,7 +464,11 @@ IApplicationVersionInterface::IApplicationVersionInterface(Core::System& system_ | |||
| 441 | {800, nullptr, "RequestVersionList"}, | 464 | {800, nullptr, "RequestVersionList"}, |
| 442 | {801, nullptr, "ListVersionList"}, | 465 | {801, nullptr, "ListVersionList"}, |
| 443 | {802, nullptr, "RequestVersionListData"}, | 466 | {802, nullptr, "RequestVersionListData"}, |
| 467 | {900, nullptr, "ImportAutoUpdatePolicyJsonForDebug"}, | ||
| 468 | {901, nullptr, "ListDefaultAutoUpdatePolicy"}, | ||
| 469 | {902, nullptr, "ListAutoUpdatePolicyForSpecificApplication"}, | ||
| 444 | {1000, nullptr, "PerformAutoUpdate"}, | 470 | {1000, nullptr, "PerformAutoUpdate"}, |
| 471 | {1001, nullptr, "ListAutoUpdateSchedule"}, | ||
| 445 | }; | 472 | }; |
| 446 | // clang-format on | 473 | // clang-format on |
| 447 | 474 | ||
| @@ -547,6 +574,9 @@ IFactoryResetInterface::~IFactoryResetInterface() = default; | |||
| 547 | NS::NS(const char* name, Core::System& system_) : ServiceFramework{system_, name} { | 574 | NS::NS(const char* name, Core::System& system_) : ServiceFramework{system_, name} { |
| 548 | // clang-format off | 575 | // clang-format off |
| 549 | static const FunctionInfo functions[] = { | 576 | static const FunctionInfo functions[] = { |
| 577 | {7988, nullptr, "GetDynamicRightsInterface"}, | ||
| 578 | {7989, nullptr, "GetReadOnlyApplicationControlDataInterface"}, | ||
| 579 | {7991, nullptr, "GetReadOnlyApplicationRecordInterface"}, | ||
| 550 | {7992, &NS::PushInterface<IECommerceInterface>, "GetECommerceInterface"}, | 580 | {7992, &NS::PushInterface<IECommerceInterface>, "GetECommerceInterface"}, |
| 551 | {7993, &NS::PushInterface<IApplicationVersionInterface>, "GetApplicationVersionInterface"}, | 581 | {7993, &NS::PushInterface<IApplicationVersionInterface>, "GetApplicationVersionInterface"}, |
| 552 | {7994, &NS::PushInterface<IFactoryResetInterface>, "GetFactoryResetInterface"}, | 582 | {7994, &NS::PushInterface<IFactoryResetInterface>, "GetFactoryResetInterface"}, |
| @@ -575,18 +605,22 @@ public: | |||
| 575 | {0, nullptr, "LaunchProgram"}, | 605 | {0, nullptr, "LaunchProgram"}, |
| 576 | {1, nullptr, "TerminateProcess"}, | 606 | {1, nullptr, "TerminateProcess"}, |
| 577 | {2, nullptr, "TerminateProgram"}, | 607 | {2, nullptr, "TerminateProgram"}, |
| 578 | {4, nullptr, "GetShellEventHandle"}, | 608 | {4, nullptr, "GetShellEvent"}, |
| 579 | {5, nullptr, "GetShellEventInfo"}, | 609 | {5, nullptr, "GetShellEventInfo"}, |
| 580 | {6, nullptr, "TerminateApplication"}, | 610 | {6, nullptr, "TerminateApplication"}, |
| 581 | {7, nullptr, "PrepareLaunchProgramFromHost"}, | 611 | {7, nullptr, "PrepareLaunchProgramFromHost"}, |
| 582 | {8, nullptr, "LaunchApplication"}, | 612 | {8, nullptr, "LaunchApplicationFromHost"}, |
| 583 | {9, nullptr, "LaunchApplicationWithStorageIdForDevelop"}, | 613 | {9, nullptr, "LaunchApplicationWithStorageIdForDevelop"}, |
| 584 | {10, nullptr, "IsSystemMemoryResourceLimitBoosted"}, | 614 | {10, nullptr, "IsSystemMemoryResourceLimitBoosted"}, |
| 585 | {11, nullptr, "GetRunningApplicationProcessIdForDevelop"}, | 615 | {11, nullptr, "GetRunningApplicationProcessIdForDevelop"}, |
| 586 | {12, nullptr, "SetCurrentApplicationRightsEnvironmentCanBeActive"}, | 616 | {12, nullptr, "SetCurrentApplicationRightsEnvironmentCanBeActiveForDevelop"}, |
| 587 | {13, nullptr, "CreateApplicationResourceForDevelop"}, | 617 | {13, nullptr, "CreateApplicationResourceForDevelop"}, |
| 588 | {14, nullptr, "IsPreomiaForDevelop"}, | 618 | {14, nullptr, "IsPreomiaForDevelop"}, |
| 589 | {15, nullptr, "GetApplicationProgramIdFromHost"}, | 619 | {15, nullptr, "GetApplicationProgramIdFromHost"}, |
| 620 | {16, nullptr, "RefreshCachedDebugValues"}, | ||
| 621 | {17, nullptr, "PrepareLaunchApplicationFromHost"}, | ||
| 622 | {18, nullptr, "GetLaunchEvent"}, | ||
| 623 | {19, nullptr, "GetLaunchResult"}, | ||
| 590 | }; | 624 | }; |
| 591 | // clang-format on | 625 | // clang-format on |
| 592 | 626 | ||
| @@ -699,6 +733,7 @@ void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system | |||
| 699 | std::make_shared<NS>("ns:rid", system)->InstallAsService(service_manager); | 733 | std::make_shared<NS>("ns:rid", system)->InstallAsService(service_manager); |
| 700 | std::make_shared<NS>("ns:rt", system)->InstallAsService(service_manager); | 734 | std::make_shared<NS>("ns:rt", system)->InstallAsService(service_manager); |
| 701 | std::make_shared<NS>("ns:web", system)->InstallAsService(service_manager); | 735 | std::make_shared<NS>("ns:web", system)->InstallAsService(service_manager); |
| 736 | std::make_shared<NS>("ns:ro", system)->InstallAsService(service_manager); | ||
| 702 | 737 | ||
| 703 | std::make_shared<NS_DEV>(system)->InstallAsService(service_manager); | 738 | std::make_shared<NS_DEV>(system)->InstallAsService(service_manager); |
| 704 | std::make_shared<NS_SU>(system)->InstallAsService(service_manager); | 739 | std::make_shared<NS_SU>(system)->InstallAsService(service_manager); |
diff --git a/src/core/hle/service/ns/pl_u.cpp b/src/core/hle/service/ns/pl_u.cpp index fcd15d81f..da139fdc4 100644 --- a/src/core/hle/service/ns/pl_u.cpp +++ b/src/core/hle/service/ns/pl_u.cpp | |||
| @@ -154,6 +154,10 @@ PL_U::PL_U(Core::System& system_) | |||
| 154 | {100, nullptr, "RequestApplicationFunctionAuthorization"}, | 154 | {100, nullptr, "RequestApplicationFunctionAuthorization"}, |
| 155 | {101, nullptr, "RequestApplicationFunctionAuthorizationByProcessId"}, | 155 | {101, nullptr, "RequestApplicationFunctionAuthorizationByProcessId"}, |
| 156 | {102, nullptr, "RequestApplicationFunctionAuthorizationByApplicationId"}, | 156 | {102, nullptr, "RequestApplicationFunctionAuthorizationByApplicationId"}, |
| 157 | {103, nullptr, "RefreshApplicationFunctionBlackListDebugRecord"}, | ||
| 158 | {104, nullptr, "RequestApplicationFunctionAuthorizationByProgramId"}, | ||
| 159 | {105, nullptr, "GetFunctionBlackListSystemVersionToAuthorize"}, | ||
| 160 | {106, nullptr, "GetFunctionBlackListVersion"}, | ||
| 157 | {1000, nullptr, "LoadNgWordDataForPlatformRegionChina"}, | 161 | {1000, nullptr, "LoadNgWordDataForPlatformRegionChina"}, |
| 158 | {1001, nullptr, "GetNgWordDataSizeForPlatformRegionChina"}, | 162 | {1001, nullptr, "GetNgWordDataSizeForPlatformRegionChina"}, |
| 159 | }; | 163 | }; |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp index 933d42f3f..2edd803f3 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp | |||
| @@ -248,7 +248,13 @@ NvResult nvhost_ctrl_gpu::ZBCSetTable(const std::vector<u8>& input, std::vector< | |||
| 248 | IoctlZbcSetTable params{}; | 248 | IoctlZbcSetTable params{}; |
| 249 | std::memcpy(¶ms, input.data(), input.size()); | 249 | std::memcpy(¶ms, input.data(), input.size()); |
| 250 | // TODO(ogniK): What does this even actually do? | 250 | // TODO(ogniK): What does this even actually do? |
| 251 | std::memcpy(output.data(), ¶ms, output.size()); | 251 | |
| 252 | // Prevent null pointer being passed as arg 1 | ||
| 253 | if (output.empty()) { | ||
| 254 | LOG_WARNING(Service_NVDRV, "Avoiding passing null pointer to memcpy"); | ||
| 255 | } else { | ||
| 256 | std::memcpy(output.data(), ¶ms, output.size()); | ||
| 257 | } | ||
| 252 | return NvResult::Success; | 258 | return NvResult::Success; |
| 253 | } | 259 | } |
| 254 | 260 | ||
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp index 4898dc27a..c2f152190 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp | |||
| @@ -23,17 +23,22 @@ namespace { | |||
| 23 | template <typename T> | 23 | template <typename T> |
| 24 | std::size_t SpliceVectors(const std::vector<u8>& input, std::vector<T>& dst, std::size_t count, | 24 | std::size_t SpliceVectors(const std::vector<u8>& input, std::vector<T>& dst, std::size_t count, |
| 25 | std::size_t offset) { | 25 | std::size_t offset) { |
| 26 | std::memcpy(dst.data(), input.data() + offset, count * sizeof(T)); | 26 | if (!dst.empty()) { |
| 27 | offset += count * sizeof(T); | 27 | std::memcpy(dst.data(), input.data() + offset, count * sizeof(T)); |
| 28 | return offset; | 28 | } |
| 29 | return 0; | ||
| 29 | } | 30 | } |
| 30 | 31 | ||
| 31 | // Write vectors will write data to the output buffer | 32 | // Write vectors will write data to the output buffer |
| 32 | template <typename T> | 33 | template <typename T> |
| 33 | std::size_t WriteVectors(std::vector<u8>& dst, const std::vector<T>& src, std::size_t offset) { | 34 | std::size_t WriteVectors(std::vector<u8>& dst, const std::vector<T>& src, std::size_t offset) { |
| 34 | std::memcpy(dst.data() + offset, src.data(), src.size() * sizeof(T)); | 35 | if (src.empty()) { |
| 35 | offset += src.size() * sizeof(T); | 36 | return 0; |
| 36 | return offset; | 37 | } else { |
| 38 | std::memcpy(dst.data() + offset, src.data(), src.size() * sizeof(T)); | ||
| 39 | offset += src.size() * sizeof(T); | ||
| 40 | return offset; | ||
| 41 | } | ||
| 37 | } | 42 | } |
| 38 | } // Anonymous namespace | 43 | } // Anonymous namespace |
| 39 | 44 | ||
diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp index ac2906e5b..539b02bc4 100644 --- a/src/core/hle/service/nvflinger/nvflinger.cpp +++ b/src/core/hle/service/nvflinger/nvflinger.cpp | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | #include "common/logging/log.h" | 9 | #include "common/logging/log.h" |
| 10 | #include "common/microprofile.h" | 10 | #include "common/microprofile.h" |
| 11 | #include "common/scope_exit.h" | 11 | #include "common/scope_exit.h" |
| 12 | #include "common/settings.h" | ||
| 12 | #include "common/thread.h" | 13 | #include "common/thread.h" |
| 13 | #include "core/core.h" | 14 | #include "core/core.h" |
| 14 | #include "core/core_timing.h" | 15 | #include "core/core_timing.h" |
| @@ -23,7 +24,6 @@ | |||
| 23 | #include "core/hle/service/vi/display/vi_display.h" | 24 | #include "core/hle/service/vi/display/vi_display.h" |
| 24 | #include "core/hle/service/vi/layer/vi_layer.h" | 25 | #include "core/hle/service/vi/layer/vi_layer.h" |
| 25 | #include "core/perf_stats.h" | 26 | #include "core/perf_stats.h" |
| 26 | #include "core/settings.h" | ||
| 27 | #include "video_core/renderer_base.h" | 27 | #include "video_core/renderer_base.h" |
| 28 | 28 | ||
| 29 | namespace Service::NVFlinger { | 29 | namespace Service::NVFlinger { |
diff --git a/src/core/hle/service/olsc/olsc.cpp b/src/core/hle/service/olsc/olsc.cpp index e2ac71fa1..b066c3417 100644 --- a/src/core/hle/service/olsc/olsc.cpp +++ b/src/core/hle/service/olsc/olsc.cpp | |||
| @@ -26,6 +26,7 @@ public: | |||
| 26 | {22, nullptr, "DeleteSaveDataBackupAsync"}, | 26 | {22, nullptr, "DeleteSaveDataBackupAsync"}, |
| 27 | {25, nullptr, "ListDownloadableSaveDataBackupInfoAsync"}, | 27 | {25, nullptr, "ListDownloadableSaveDataBackupInfoAsync"}, |
| 28 | {26, nullptr, "DownloadSaveDataBackupAsync"}, | 28 | {26, nullptr, "DownloadSaveDataBackupAsync"}, |
| 29 | {27, nullptr, "UploadSaveDataBackupAsync"}, | ||
| 29 | {9010, nullptr, "VerifySaveDataBackupLicenseAsyncForDebug"}, | 30 | {9010, nullptr, "VerifySaveDataBackupLicenseAsyncForDebug"}, |
| 30 | {9013, nullptr, "GetSaveDataBackupSettingForDebug"}, | 31 | {9013, nullptr, "GetSaveDataBackupSettingForDebug"}, |
| 31 | {9014, nullptr, "SetSaveDataBackupSettingEnabledForDebug"}, | 32 | {9014, nullptr, "SetSaveDataBackupSettingEnabledForDebug"}, |
diff --git a/src/core/hle/service/pcie/pcie.cpp b/src/core/hle/service/pcie/pcie.cpp index f6686fc4d..9bc851591 100644 --- a/src/core/hle/service/pcie/pcie.cpp +++ b/src/core/hle/service/pcie/pcie.cpp | |||
| @@ -37,7 +37,7 @@ public: | |||
| 37 | {19, nullptr, "SetIrqEnable"}, | 37 | {19, nullptr, "SetIrqEnable"}, |
| 38 | {20, nullptr, "SetAspmEnable"}, | 38 | {20, nullptr, "SetAspmEnable"}, |
| 39 | {21, nullptr, "SetResetUponResumeEnable"}, | 39 | {21, nullptr, "SetResetUponResumeEnable"}, |
| 40 | {22, nullptr, "Unknown22"}, | 40 | {22, nullptr, "ResetFunction"}, |
| 41 | {23, nullptr, "Unknown23"}, | 41 | {23, nullptr, "Unknown23"}, |
| 42 | }; | 42 | }; |
| 43 | // clang-format on | 43 | // clang-format on |
diff --git a/src/core/hle/service/pctl/module.cpp b/src/core/hle/service/pctl/module.cpp index f9089bf2f..dc59702f1 100644 --- a/src/core/hle/service/pctl/module.cpp +++ b/src/core/hle/service/pctl/module.cpp | |||
| @@ -3,16 +3,30 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include "common/logging/log.h" | 5 | #include "common/logging/log.h" |
| 6 | #include "core/core.h" | ||
| 7 | #include "core/file_sys/control_metadata.h" | ||
| 8 | #include "core/file_sys/patch_manager.h" | ||
| 6 | #include "core/hle/ipc_helpers.h" | 9 | #include "core/hle/ipc_helpers.h" |
| 10 | #include "core/hle/kernel/process.h" | ||
| 7 | #include "core/hle/service/pctl/module.h" | 11 | #include "core/hle/service/pctl/module.h" |
| 8 | #include "core/hle/service/pctl/pctl.h" | 12 | #include "core/hle/service/pctl/pctl.h" |
| 9 | 13 | ||
| 10 | namespace Service::PCTL { | 14 | namespace Service::PCTL { |
| 11 | 15 | ||
| 16 | namespace Error { | ||
| 17 | |||
| 18 | constexpr ResultCode ResultNoFreeCommunication{ErrorModule::PCTL, 101}; | ||
| 19 | constexpr ResultCode ResultStereoVisionRestricted{ErrorModule::PCTL, 104}; | ||
| 20 | constexpr ResultCode ResultNoCapability{ErrorModule::PCTL, 131}; | ||
| 21 | constexpr ResultCode ResultNoRestrictionEnabled{ErrorModule::PCTL, 181}; | ||
| 22 | |||
| 23 | } // namespace Error | ||
| 24 | |||
| 12 | class IParentalControlService final : public ServiceFramework<IParentalControlService> { | 25 | class IParentalControlService final : public ServiceFramework<IParentalControlService> { |
| 13 | public: | 26 | public: |
| 14 | explicit IParentalControlService(Core::System& system_) | 27 | explicit IParentalControlService(Core::System& system_, Capability capability) |
| 15 | : ServiceFramework{system_, "IParentalControlService"} { | 28 | : ServiceFramework{system_, "IParentalControlService"}, system(system_), |
| 29 | capability(capability) { | ||
| 16 | // clang-format off | 30 | // clang-format off |
| 17 | static const FunctionInfo functions[] = { | 31 | static const FunctionInfo functions[] = { |
| 18 | {1, &IParentalControlService::Initialize, "Initialize"}, | 32 | {1, &IParentalControlService::Initialize, "Initialize"}, |
| @@ -28,13 +42,13 @@ public: | |||
| 28 | {1010, nullptr, "IsRestrictedSystemSettingsEntered"}, | 42 | {1010, nullptr, "IsRestrictedSystemSettingsEntered"}, |
| 29 | {1011, nullptr, "RevertRestrictedSystemSettingsEntered"}, | 43 | {1011, nullptr, "RevertRestrictedSystemSettingsEntered"}, |
| 30 | {1012, nullptr, "GetRestrictedFeatures"}, | 44 | {1012, nullptr, "GetRestrictedFeatures"}, |
| 31 | {1013, nullptr, "ConfirmStereoVisionPermission"}, | 45 | {1013, &IParentalControlService::ConfirmStereoVisionPermission, "ConfirmStereoVisionPermission"}, |
| 32 | {1014, nullptr, "ConfirmPlayableApplicationVideoOld"}, | 46 | {1014, nullptr, "ConfirmPlayableApplicationVideoOld"}, |
| 33 | {1015, nullptr, "ConfirmPlayableApplicationVideo"}, | 47 | {1015, nullptr, "ConfirmPlayableApplicationVideo"}, |
| 34 | {1016, nullptr, "ConfirmShowNewsPermission"}, | 48 | {1016, nullptr, "ConfirmShowNewsPermission"}, |
| 35 | {1017, nullptr, "EndFreeCommunication"}, | 49 | {1017, nullptr, "EndFreeCommunication"}, |
| 36 | {1018, nullptr, "IsFreeCommunicationAvailable"}, | 50 | {1018, &IParentalControlService::IsFreeCommunicationAvailable, "IsFreeCommunicationAvailable"}, |
| 37 | {1031, nullptr, "IsRestrictionEnabled"}, | 51 | {1031, &IParentalControlService::IsRestrictionEnabled, "IsRestrictionEnabled"}, |
| 38 | {1032, nullptr, "GetSafetyLevel"}, | 52 | {1032, nullptr, "GetSafetyLevel"}, |
| 39 | {1033, nullptr, "SetSafetyLevel"}, | 53 | {1033, nullptr, "SetSafetyLevel"}, |
| 40 | {1034, nullptr, "GetSafetyLevelSettings"}, | 54 | {1034, nullptr, "GetSafetyLevelSettings"}, |
| @@ -50,6 +64,7 @@ public: | |||
| 50 | {1046, nullptr, "DisableFeaturesForReset"}, | 64 | {1046, nullptr, "DisableFeaturesForReset"}, |
| 51 | {1047, nullptr, "NotifyApplicationDownloadStarted"}, | 65 | {1047, nullptr, "NotifyApplicationDownloadStarted"}, |
| 52 | {1048, nullptr, "NotifyNetworkProfileCreated"}, | 66 | {1048, nullptr, "NotifyNetworkProfileCreated"}, |
| 67 | {1049, nullptr, "ResetFreeCommunicationApplicationList"}, | ||
| 53 | {1061, &IParentalControlService::ConfirmStereoVisionRestrictionConfigurable, "ConfirmStereoVisionRestrictionConfigurable"}, | 68 | {1061, &IParentalControlService::ConfirmStereoVisionRestrictionConfigurable, "ConfirmStereoVisionRestrictionConfigurable"}, |
| 54 | {1062, &IParentalControlService::GetStereoVisionRestriction, "GetStereoVisionRestriction"}, | 69 | {1062, &IParentalControlService::GetStereoVisionRestriction, "GetStereoVisionRestriction"}, |
| 55 | {1063, &IParentalControlService::SetStereoVisionRestriction, "SetStereoVisionRestriction"}, | 70 | {1063, &IParentalControlService::SetStereoVisionRestriction, "SetStereoVisionRestriction"}, |
| @@ -69,6 +84,8 @@ public: | |||
| 69 | {1421, nullptr, "GetAccountNickname"}, | 84 | {1421, nullptr, "GetAccountNickname"}, |
| 70 | {1424, nullptr, "GetAccountState"}, | 85 | {1424, nullptr, "GetAccountState"}, |
| 71 | {1425, nullptr, "RequestPostEvents"}, | 86 | {1425, nullptr, "RequestPostEvents"}, |
| 87 | {1426, nullptr, "GetPostEventInterval"}, | ||
| 88 | {1427, nullptr, "SetPostEventInterval"}, | ||
| 72 | {1432, nullptr, "GetSynchronizationEvent"}, | 89 | {1432, nullptr, "GetSynchronizationEvent"}, |
| 73 | {1451, nullptr, "StartPlayTimer"}, | 90 | {1451, nullptr, "StartPlayTimer"}, |
| 74 | {1452, nullptr, "StopPlayTimer"}, | 91 | {1452, nullptr, "StopPlayTimer"}, |
| @@ -119,62 +136,235 @@ public: | |||
| 119 | } | 136 | } |
| 120 | 137 | ||
| 121 | private: | 138 | private: |
| 139 | bool CheckFreeCommunicationPermissionImpl() const { | ||
| 140 | if (states.temporary_unlocked) { | ||
| 141 | return true; | ||
| 142 | } | ||
| 143 | if ((states.application_info.parental_control_flag & 1) == 0) { | ||
| 144 | return true; | ||
| 145 | } | ||
| 146 | if (pin_code[0] == '\0') { | ||
| 147 | return true; | ||
| 148 | } | ||
| 149 | if (!settings.is_free_communication_default_on) { | ||
| 150 | return true; | ||
| 151 | } | ||
| 152 | // TODO(ogniK): Check for blacklisted/exempted applications. Return false can happen here | ||
| 153 | // but as we don't have multiproceses support yet, we can just assume our application is | ||
| 154 | // valid for the time being | ||
| 155 | return true; | ||
| 156 | } | ||
| 157 | |||
| 158 | bool ConfirmStereoVisionPermissionImpl() const { | ||
| 159 | if (states.temporary_unlocked) { | ||
| 160 | return true; | ||
| 161 | } | ||
| 162 | if (pin_code[0] == '\0') { | ||
| 163 | return true; | ||
| 164 | } | ||
| 165 | if (!settings.is_stero_vision_restricted) { | ||
| 166 | return false; | ||
| 167 | } | ||
| 168 | return true; | ||
| 169 | } | ||
| 170 | |||
| 171 | void SetStereoVisionRestrictionImpl(bool is_restricted) { | ||
| 172 | if (settings.disabled) { | ||
| 173 | return; | ||
| 174 | } | ||
| 175 | |||
| 176 | if (pin_code[0] == '\0') { | ||
| 177 | return; | ||
| 178 | } | ||
| 179 | settings.is_stero_vision_restricted = is_restricted; | ||
| 180 | } | ||
| 181 | |||
| 122 | void Initialize(Kernel::HLERequestContext& ctx) { | 182 | void Initialize(Kernel::HLERequestContext& ctx) { |
| 123 | LOG_WARNING(Service_PCTL, "(STUBBED) called"); | 183 | LOG_DEBUG(Service_PCTL, "called"); |
| 184 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 185 | |||
| 186 | if (False(capability & (Capability::Application | Capability::System))) { | ||
| 187 | LOG_ERROR(Service_PCTL, "Invalid capability! capability={:X}", capability); | ||
| 188 | return; | ||
| 189 | } | ||
| 190 | |||
| 191 | // TODO(ogniK): Recovery flag initialization for pctl:r | ||
| 192 | |||
| 193 | const auto tid = system.CurrentProcess()->GetTitleID(); | ||
| 194 | if (tid != 0) { | ||
| 195 | const FileSys::PatchManager pm{tid, system.GetFileSystemController(), | ||
| 196 | system.GetContentProvider()}; | ||
| 197 | const auto control = pm.GetControlMetadata(); | ||
| 198 | if (control.first) { | ||
| 199 | states.tid_from_event = 0; | ||
| 200 | states.launch_time_valid = false; | ||
| 201 | states.is_suspended = false; | ||
| 202 | states.free_communication = false; | ||
| 203 | states.stereo_vision = false; | ||
| 204 | states.application_info = ApplicationInfo{ | ||
| 205 | .tid = tid, | ||
| 206 | .age_rating = control.first->GetRatingAge(), | ||
| 207 | .parental_control_flag = control.first->GetParentalControlFlag(), | ||
| 208 | .capability = capability, | ||
| 209 | }; | ||
| 210 | |||
| 211 | if (False(capability & (Capability::System | Capability::Recovery))) { | ||
| 212 | // TODO(ogniK): Signal application launch event | ||
| 213 | } | ||
| 214 | } | ||
| 215 | } | ||
| 124 | 216 | ||
| 125 | IPC::ResponseBuilder rb{ctx, 2, 0, 0}; | ||
| 126 | rb.Push(RESULT_SUCCESS); | 217 | rb.Push(RESULT_SUCCESS); |
| 127 | } | 218 | } |
| 128 | 219 | ||
| 129 | void CheckFreeCommunicationPermission(Kernel::HLERequestContext& ctx) { | 220 | void CheckFreeCommunicationPermission(Kernel::HLERequestContext& ctx) { |
| 130 | LOG_WARNING(Service_PCTL, "(STUBBED) called"); | 221 | LOG_DEBUG(Service_PCTL, "called"); |
| 222 | |||
| 223 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 224 | if (!CheckFreeCommunicationPermissionImpl()) { | ||
| 225 | rb.Push(Error::ResultNoFreeCommunication); | ||
| 226 | } else { | ||
| 227 | rb.Push(RESULT_SUCCESS); | ||
| 228 | } | ||
| 229 | |||
| 230 | states.free_communication = true; | ||
| 231 | } | ||
| 232 | |||
| 233 | void ConfirmStereoVisionPermission(Kernel::HLERequestContext& ctx) { | ||
| 234 | LOG_DEBUG(Service_PCTL, "called"); | ||
| 235 | states.stereo_vision = true; | ||
| 131 | 236 | ||
| 132 | IPC::ResponseBuilder rb{ctx, 2}; | 237 | IPC::ResponseBuilder rb{ctx, 2}; |
| 133 | rb.Push(RESULT_SUCCESS); | 238 | rb.Push(RESULT_SUCCESS); |
| 134 | } | 239 | } |
| 135 | 240 | ||
| 136 | void ConfirmStereoVisionRestrictionConfigurable(Kernel::HLERequestContext& ctx) { | 241 | void IsFreeCommunicationAvailable(Kernel::HLERequestContext& ctx) { |
| 137 | LOG_WARNING(Service_PCTL, "(STUBBED) called"); | 242 | LOG_WARNING(Service_PCTL, "(STUBBED) called"); |
| 138 | 243 | ||
| 139 | IPC::ResponseBuilder rb{ctx, 2}; | 244 | IPC::ResponseBuilder rb{ctx, 2}; |
| 245 | if (!CheckFreeCommunicationPermissionImpl()) { | ||
| 246 | rb.Push(Error::ResultNoFreeCommunication); | ||
| 247 | } else { | ||
| 248 | rb.Push(RESULT_SUCCESS); | ||
| 249 | } | ||
| 250 | } | ||
| 251 | |||
| 252 | void IsRestrictionEnabled(Kernel::HLERequestContext& ctx) { | ||
| 253 | LOG_DEBUG(Service_PCTL, "called"); | ||
| 254 | |||
| 255 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 256 | if (False(capability & (Capability::Status | Capability::Recovery))) { | ||
| 257 | LOG_ERROR(Service_PCTL, "Application does not have Status or Recovery capabilities!"); | ||
| 258 | rb.Push(Error::ResultNoCapability); | ||
| 259 | rb.Push(false); | ||
| 260 | return; | ||
| 261 | } | ||
| 262 | |||
| 263 | rb.Push(pin_code[0] != '\0'); | ||
| 264 | } | ||
| 265 | |||
| 266 | void ConfirmStereoVisionRestrictionConfigurable(Kernel::HLERequestContext& ctx) { | ||
| 267 | LOG_DEBUG(Service_PCTL, "called"); | ||
| 268 | |||
| 269 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 270 | |||
| 271 | if (False(capability & Capability::StereoVision)) { | ||
| 272 | LOG_ERROR(Service_PCTL, "Application does not have StereoVision capability!"); | ||
| 273 | rb.Push(Error::ResultNoCapability); | ||
| 274 | return; | ||
| 275 | } | ||
| 276 | |||
| 277 | if (pin_code[0] == '\0') { | ||
| 278 | rb.Push(Error::ResultNoRestrictionEnabled); | ||
| 279 | return; | ||
| 280 | } | ||
| 281 | |||
| 140 | rb.Push(RESULT_SUCCESS); | 282 | rb.Push(RESULT_SUCCESS); |
| 141 | } | 283 | } |
| 142 | 284 | ||
| 143 | void IsStereoVisionPermitted(Kernel::HLERequestContext& ctx) { | 285 | void IsStereoVisionPermitted(Kernel::HLERequestContext& ctx) { |
| 144 | LOG_WARNING(Service_PCTL, "(STUBBED) called"); | 286 | LOG_DEBUG(Service_PCTL, "called"); |
| 145 | 287 | ||
| 146 | IPC::ResponseBuilder rb{ctx, 3}; | 288 | IPC::ResponseBuilder rb{ctx, 3}; |
| 147 | rb.Push(RESULT_SUCCESS); | 289 | if (!ConfirmStereoVisionPermissionImpl()) { |
| 148 | rb.Push(true); | 290 | rb.Push(Error::ResultStereoVisionRestricted); |
| 291 | rb.Push(false); | ||
| 292 | } else { | ||
| 293 | rb.Push(RESULT_SUCCESS); | ||
| 294 | rb.Push(true); | ||
| 295 | } | ||
| 149 | } | 296 | } |
| 150 | 297 | ||
| 151 | void SetStereoVisionRestriction(Kernel::HLERequestContext& ctx) { | 298 | void SetStereoVisionRestriction(Kernel::HLERequestContext& ctx) { |
| 152 | IPC::RequestParser rp{ctx}; | 299 | IPC::RequestParser rp{ctx}; |
| 153 | const auto can_use = rp.Pop<bool>(); | 300 | const auto can_use = rp.Pop<bool>(); |
| 154 | LOG_WARNING(Service_PCTL, "(STUBBED) called, can_use={}", can_use); | 301 | LOG_DEBUG(Service_PCTL, "called, can_use={}", can_use); |
| 155 | |||
| 156 | can_use_stereo_vision = can_use; | ||
| 157 | 302 | ||
| 158 | IPC::ResponseBuilder rb{ctx, 2}; | 303 | IPC::ResponseBuilder rb{ctx, 2}; |
| 304 | if (False(capability & Capability::StereoVision)) { | ||
| 305 | LOG_ERROR(Service_PCTL, "Application does not have StereoVision capability!"); | ||
| 306 | rb.Push(Error::ResultNoCapability); | ||
| 307 | return; | ||
| 308 | } | ||
| 309 | |||
| 310 | SetStereoVisionRestrictionImpl(can_use); | ||
| 159 | rb.Push(RESULT_SUCCESS); | 311 | rb.Push(RESULT_SUCCESS); |
| 160 | } | 312 | } |
| 161 | 313 | ||
| 162 | void GetStereoVisionRestriction(Kernel::HLERequestContext& ctx) { | 314 | void GetStereoVisionRestriction(Kernel::HLERequestContext& ctx) { |
| 163 | LOG_WARNING(Service_PCTL, "(STUBBED) called"); | 315 | LOG_DEBUG(Service_PCTL, "called"); |
| 164 | 316 | ||
| 165 | IPC::ResponseBuilder rb{ctx, 3}; | 317 | IPC::ResponseBuilder rb{ctx, 3}; |
| 318 | if (False(capability & Capability::StereoVision)) { | ||
| 319 | LOG_ERROR(Service_PCTL, "Application does not have StereoVision capability!"); | ||
| 320 | rb.Push(Error::ResultNoCapability); | ||
| 321 | rb.Push(false); | ||
| 322 | return; | ||
| 323 | } | ||
| 324 | |||
| 166 | rb.Push(RESULT_SUCCESS); | 325 | rb.Push(RESULT_SUCCESS); |
| 167 | rb.Push(can_use_stereo_vision); | 326 | rb.Push(settings.is_stero_vision_restricted); |
| 168 | } | 327 | } |
| 169 | 328 | ||
| 170 | void ResetConfirmedStereoVisionPermission(Kernel::HLERequestContext& ctx) { | 329 | void ResetConfirmedStereoVisionPermission(Kernel::HLERequestContext& ctx) { |
| 171 | LOG_WARNING(Service_PCTL, "(STUBBED) called"); | 330 | LOG_DEBUG(Service_PCTL, "called"); |
| 331 | |||
| 332 | states.stereo_vision = false; | ||
| 172 | 333 | ||
| 173 | IPC::ResponseBuilder rb{ctx, 2}; | 334 | IPC::ResponseBuilder rb{ctx, 2}; |
| 174 | rb.Push(RESULT_SUCCESS); | 335 | rb.Push(RESULT_SUCCESS); |
| 175 | } | 336 | } |
| 176 | 337 | ||
| 338 | struct ApplicationInfo { | ||
| 339 | u64 tid{}; | ||
| 340 | std::array<u8, 32> age_rating{}; | ||
| 341 | u32 parental_control_flag{}; | ||
| 342 | Capability capability{}; | ||
| 343 | }; | ||
| 344 | |||
| 345 | struct States { | ||
| 346 | u64 current_tid{}; | ||
| 347 | ApplicationInfo application_info{}; | ||
| 348 | u64 tid_from_event{}; | ||
| 349 | bool launch_time_valid{}; | ||
| 350 | bool is_suspended{}; | ||
| 351 | bool temporary_unlocked{}; | ||
| 352 | bool free_communication{}; | ||
| 353 | bool stereo_vision{}; | ||
| 354 | }; | ||
| 355 | |||
| 356 | struct ParentalControlSettings { | ||
| 357 | bool is_stero_vision_restricted{}; | ||
| 358 | bool is_free_communication_default_on{}; | ||
| 359 | bool disabled{}; | ||
| 360 | }; | ||
| 361 | |||
| 362 | States states{}; | ||
| 363 | ParentalControlSettings settings{}; | ||
| 364 | std::array<char, 8> pin_code{}; | ||
| 177 | bool can_use_stereo_vision = true; | 365 | bool can_use_stereo_vision = true; |
| 366 | Core::System& system; | ||
| 367 | Capability capability{}; | ||
| 178 | }; | 368 | }; |
| 179 | 369 | ||
| 180 | void Module::Interface::CreateService(Kernel::HLERequestContext& ctx) { | 370 | void Module::Interface::CreateService(Kernel::HLERequestContext& ctx) { |
| @@ -182,7 +372,9 @@ void Module::Interface::CreateService(Kernel::HLERequestContext& ctx) { | |||
| 182 | 372 | ||
| 183 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 373 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 184 | rb.Push(RESULT_SUCCESS); | 374 | rb.Push(RESULT_SUCCESS); |
| 185 | rb.PushIpcInterface<IParentalControlService>(system); | 375 | // TODO(ogniK): Get TID from process |
| 376 | |||
| 377 | rb.PushIpcInterface<IParentalControlService>(system, capability); | ||
| 186 | } | 378 | } |
| 187 | 379 | ||
| 188 | void Module::Interface::CreateServiceWithoutInitialize(Kernel::HLERequestContext& ctx) { | 380 | void Module::Interface::CreateServiceWithoutInitialize(Kernel::HLERequestContext& ctx) { |
| @@ -190,21 +382,28 @@ void Module::Interface::CreateServiceWithoutInitialize(Kernel::HLERequestContext | |||
| 190 | 382 | ||
| 191 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 383 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 192 | rb.Push(RESULT_SUCCESS); | 384 | rb.Push(RESULT_SUCCESS); |
| 193 | rb.PushIpcInterface<IParentalControlService>(system); | 385 | rb.PushIpcInterface<IParentalControlService>(system, capability); |
| 194 | } | 386 | } |
| 195 | 387 | ||
| 196 | Module::Interface::Interface(Core::System& system_, std::shared_ptr<Module> module_, | 388 | Module::Interface::Interface(Core::System& system_, std::shared_ptr<Module> module_, |
| 197 | const char* name) | 389 | const char* name, Capability capability) |
| 198 | : ServiceFramework{system_, name}, module{std::move(module_)} {} | 390 | : ServiceFramework{system_, name}, module{std::move(module_)}, capability(capability) {} |
| 199 | 391 | ||
| 200 | Module::Interface::~Interface() = default; | 392 | Module::Interface::~Interface() = default; |
| 201 | 393 | ||
| 202 | void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) { | 394 | void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) { |
| 203 | auto module = std::make_shared<Module>(); | 395 | auto module = std::make_shared<Module>(); |
| 204 | std::make_shared<PCTL>(system, module, "pctl")->InstallAsService(service_manager); | 396 | std::make_shared<PCTL>(system, module, "pctl", |
| 205 | std::make_shared<PCTL>(system, module, "pctl:a")->InstallAsService(service_manager); | 397 | Capability::Application | Capability::SnsPost | Capability::Status | |
| 206 | std::make_shared<PCTL>(system, module, "pctl:r")->InstallAsService(service_manager); | 398 | Capability::StereoVision) |
| 207 | std::make_shared<PCTL>(system, module, "pctl:s")->InstallAsService(service_manager); | 399 | ->InstallAsService(service_manager); |
| 400 | // TODO(ogniK): Implement remaining capabilities | ||
| 401 | std::make_shared<PCTL>(system, module, "pctl:a", Capability::None) | ||
| 402 | ->InstallAsService(service_manager); | ||
| 403 | std::make_shared<PCTL>(system, module, "pctl:r", Capability::None) | ||
| 404 | ->InstallAsService(service_manager); | ||
| 405 | std::make_shared<PCTL>(system, module, "pctl:s", Capability::None) | ||
| 406 | ->InstallAsService(service_manager); | ||
| 208 | } | 407 | } |
| 209 | 408 | ||
| 210 | } // namespace Service::PCTL | 409 | } // namespace Service::PCTL |
diff --git a/src/core/hle/service/pctl/module.h b/src/core/hle/service/pctl/module.h index 4c7e09a3b..032481b00 100644 --- a/src/core/hle/service/pctl/module.h +++ b/src/core/hle/service/pctl/module.h | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include "common/common_funcs.h" | ||
| 7 | #include "core/hle/service/service.h" | 8 | #include "core/hle/service/service.h" |
| 8 | 9 | ||
| 9 | namespace Core { | 10 | namespace Core { |
| @@ -12,12 +13,23 @@ class System; | |||
| 12 | 13 | ||
| 13 | namespace Service::PCTL { | 14 | namespace Service::PCTL { |
| 14 | 15 | ||
| 16 | enum class Capability : u32 { | ||
| 17 | None = 0, | ||
| 18 | Application = 1 << 0, | ||
| 19 | SnsPost = 1 << 1, | ||
| 20 | Recovery = 1 << 6, | ||
| 21 | Status = 1 << 8, | ||
| 22 | StereoVision = 1 << 9, | ||
| 23 | System = 1 << 15, | ||
| 24 | }; | ||
| 25 | DECLARE_ENUM_FLAG_OPERATORS(Capability); | ||
| 26 | |||
| 15 | class Module final { | 27 | class Module final { |
| 16 | public: | 28 | public: |
| 17 | class Interface : public ServiceFramework<Interface> { | 29 | class Interface : public ServiceFramework<Interface> { |
| 18 | public: | 30 | public: |
| 19 | explicit Interface(Core::System& system_, std::shared_ptr<Module> module_, | 31 | explicit Interface(Core::System& system_, std::shared_ptr<Module> module_, const char* name, |
| 20 | const char* name); | 32 | Capability capability); |
| 21 | ~Interface() override; | 33 | ~Interface() override; |
| 22 | 34 | ||
| 23 | void CreateService(Kernel::HLERequestContext& ctx); | 35 | void CreateService(Kernel::HLERequestContext& ctx); |
| @@ -25,6 +37,9 @@ public: | |||
| 25 | 37 | ||
| 26 | protected: | 38 | protected: |
| 27 | std::shared_ptr<Module> module; | 39 | std::shared_ptr<Module> module; |
| 40 | |||
| 41 | private: | ||
| 42 | Capability capability{}; | ||
| 28 | }; | 43 | }; |
| 29 | }; | 44 | }; |
| 30 | 45 | ||
diff --git a/src/core/hle/service/pctl/pctl.cpp b/src/core/hle/service/pctl/pctl.cpp index 16dd34f90..e4d155c86 100644 --- a/src/core/hle/service/pctl/pctl.cpp +++ b/src/core/hle/service/pctl/pctl.cpp | |||
| @@ -6,8 +6,9 @@ | |||
| 6 | 6 | ||
| 7 | namespace Service::PCTL { | 7 | namespace Service::PCTL { |
| 8 | 8 | ||
| 9 | PCTL::PCTL(Core::System& system_, std::shared_ptr<Module> module_, const char* name) | 9 | PCTL::PCTL(Core::System& system_, std::shared_ptr<Module> module_, const char* name, |
| 10 | : Interface{system_, std::move(module_), name} { | 10 | Capability capability) |
| 11 | : Interface{system_, std::move(module_), name, capability} { | ||
| 11 | static const FunctionInfo functions[] = { | 12 | static const FunctionInfo functions[] = { |
| 12 | {0, &PCTL::CreateService, "CreateService"}, | 13 | {0, &PCTL::CreateService, "CreateService"}, |
| 13 | {1, &PCTL::CreateServiceWithoutInitialize, "CreateServiceWithoutInitialize"}, | 14 | {1, &PCTL::CreateServiceWithoutInitialize, "CreateServiceWithoutInitialize"}, |
diff --git a/src/core/hle/service/pctl/pctl.h b/src/core/hle/service/pctl/pctl.h index 275d23007..fd0a1e486 100644 --- a/src/core/hle/service/pctl/pctl.h +++ b/src/core/hle/service/pctl/pctl.h | |||
| @@ -14,7 +14,8 @@ namespace Service::PCTL { | |||
| 14 | 14 | ||
| 15 | class PCTL final : public Module::Interface { | 15 | class PCTL final : public Module::Interface { |
| 16 | public: | 16 | public: |
| 17 | explicit PCTL(Core::System& system_, std::shared_ptr<Module> module_, const char* name); | 17 | explicit PCTL(Core::System& system_, std::shared_ptr<Module> module_, const char* name, |
| 18 | Capability capability); | ||
| 18 | ~PCTL() override; | 19 | ~PCTL() override; |
| 19 | }; | 20 | }; |
| 20 | 21 | ||
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index 1da56bc27..41a502d8d 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | #include <fmt/format.h> | 6 | #include <fmt/format.h> |
| 7 | #include "common/assert.h" | 7 | #include "common/assert.h" |
| 8 | #include "common/logging/log.h" | 8 | #include "common/logging/log.h" |
| 9 | #include "common/settings.h" | ||
| 9 | #include "common/string_util.h" | 10 | #include "common/string_util.h" |
| 10 | #include "core/core.h" | 11 | #include "core/core.h" |
| 11 | #include "core/hle/ipc.h" | 12 | #include "core/hle/ipc.h" |
| @@ -146,6 +147,11 @@ void ServiceFrameworkBase::ReportUnimplementedFunction(Kernel::HLERequestContext | |||
| 146 | system.GetReporter().SaveUnimplementedFunctionReport(ctx, ctx.GetCommand(), function_name, | 147 | system.GetReporter().SaveUnimplementedFunctionReport(ctx, ctx.GetCommand(), function_name, |
| 147 | service_name); | 148 | service_name); |
| 148 | UNIMPLEMENTED_MSG("Unknown / unimplemented {}", fmt::to_string(buf)); | 149 | UNIMPLEMENTED_MSG("Unknown / unimplemented {}", fmt::to_string(buf)); |
| 150 | if (Settings::values.use_auto_stub) { | ||
| 151 | LOG_WARNING(Service, "Using auto stub fallback!"); | ||
| 152 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 153 | rb.Push(RESULT_SUCCESS); | ||
| 154 | } | ||
| 149 | } | 155 | } |
| 150 | 156 | ||
| 151 | void ServiceFrameworkBase::InvokeRequest(Kernel::HLERequestContext& ctx) { | 157 | void ServiceFrameworkBase::InvokeRequest(Kernel::HLERequestContext& ctx) { |
diff --git a/src/core/hle/service/set/set.cpp b/src/core/hle/service/set/set.cpp index d953b4303..bc7dc776f 100644 --- a/src/core/hle/service/set/set.cpp +++ b/src/core/hle/service/set/set.cpp | |||
| @@ -6,9 +6,9 @@ | |||
| 6 | #include <array> | 6 | #include <array> |
| 7 | #include <chrono> | 7 | #include <chrono> |
| 8 | #include "common/logging/log.h" | 8 | #include "common/logging/log.h" |
| 9 | #include "common/settings.h" | ||
| 9 | #include "core/hle/ipc_helpers.h" | 10 | #include "core/hle/ipc_helpers.h" |
| 10 | #include "core/hle/service/set/set.h" | 11 | #include "core/hle/service/set/set.h" |
| 11 | #include "core/settings.h" | ||
| 12 | 12 | ||
| 13 | namespace Service::Set { | 13 | namespace Service::Set { |
| 14 | namespace { | 14 | namespace { |
diff --git a/src/core/hle/service/set/set_sys.cpp b/src/core/hle/service/set/set_sys.cpp index b58b2c8c5..5909fdd85 100644 --- a/src/core/hle/service/set/set_sys.cpp +++ b/src/core/hle/service/set/set_sys.cpp | |||
| @@ -261,6 +261,10 @@ SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} { | |||
| 261 | {155, nullptr, "SetAccountOnlineStorageSettings"}, | 261 | {155, nullptr, "SetAccountOnlineStorageSettings"}, |
| 262 | {156, nullptr, "GetPctlReadyFlag"}, | 262 | {156, nullptr, "GetPctlReadyFlag"}, |
| 263 | {157, nullptr, "SetPctlReadyFlag"}, | 263 | {157, nullptr, "SetPctlReadyFlag"}, |
| 264 | {158, nullptr, "GetAnalogStickUserCalibrationL"}, | ||
| 265 | {159, nullptr, "SetAnalogStickUserCalibrationL"}, | ||
| 266 | {160, nullptr, "GetAnalogStickUserCalibrationR"}, | ||
| 267 | {161, nullptr, "SetAnalogStickUserCalibrationR"}, | ||
| 264 | {162, nullptr, "GetPtmBatteryVersion"}, | 268 | {162, nullptr, "GetPtmBatteryVersion"}, |
| 265 | {163, nullptr, "SetPtmBatteryVersion"}, | 269 | {163, nullptr, "SetPtmBatteryVersion"}, |
| 266 | {164, nullptr, "GetUsb30HostEnableFlag"}, | 270 | {164, nullptr, "GetUsb30HostEnableFlag"}, |
| @@ -302,6 +306,8 @@ SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} { | |||
| 302 | {200, nullptr, "SetButtonConfigRegisteredSettings"}, | 306 | {200, nullptr, "SetButtonConfigRegisteredSettings"}, |
| 303 | {201, nullptr, "GetFieldTestingFlag"}, | 307 | {201, nullptr, "GetFieldTestingFlag"}, |
| 304 | {202, nullptr, "SetFieldTestingFlag"}, | 308 | {202, nullptr, "SetFieldTestingFlag"}, |
| 309 | {203, nullptr, "GetPanelCrcMode"}, | ||
| 310 | {204, nullptr, "SetPanelCrcMode"}, | ||
| 305 | }; | 311 | }; |
| 306 | // clang-format on | 312 | // clang-format on |
| 307 | 313 | ||
diff --git a/src/core/hle/service/sm/sm.cpp b/src/core/hle/service/sm/sm.cpp index 2b91a89d1..94608d529 100644 --- a/src/core/hle/service/sm/sm.cpp +++ b/src/core/hle/service/sm/sm.cpp | |||
| @@ -190,10 +190,11 @@ SM::SM(std::shared_ptr<ServiceManager> service_manager_, Core::System& system_) | |||
| 190 | : ServiceFramework{system_, "sm:", 4}, | 190 | : ServiceFramework{system_, "sm:", 4}, |
| 191 | service_manager{std::move(service_manager_)}, kernel{system_.Kernel()} { | 191 | service_manager{std::move(service_manager_)}, kernel{system_.Kernel()} { |
| 192 | static const FunctionInfo functions[] = { | 192 | static const FunctionInfo functions[] = { |
| 193 | {0x00000000, &SM::Initialize, "Initialize"}, | 193 | {0, &SM::Initialize, "Initialize"}, |
| 194 | {0x00000001, &SM::GetService, "GetService"}, | 194 | {1, &SM::GetService, "GetService"}, |
| 195 | {0x00000002, &SM::RegisterService, "RegisterService"}, | 195 | {2, &SM::RegisterService, "RegisterService"}, |
| 196 | {0x00000003, &SM::UnregisterService, "UnregisterService"}, | 196 | {3, &SM::UnregisterService, "UnregisterService"}, |
| 197 | {4, nullptr, "DetachClient"}, | ||
| 197 | }; | 198 | }; |
| 198 | RegisterHandlers(functions); | 199 | RegisterHandlers(functions); |
| 199 | } | 200 | } |
diff --git a/src/core/hle/service/sockets/ethc.cpp b/src/core/hle/service/sockets/ethc.cpp index 05681ca2d..899a64c2f 100644 --- a/src/core/hle/service/sockets/ethc.cpp +++ b/src/core/hle/service/sockets/ethc.cpp | |||
| @@ -15,6 +15,7 @@ ETHC_C::ETHC_C(Core::System& system_) : ServiceFramework{system_, "ethc:c"} { | |||
| 15 | {3, nullptr, "GetMediaList"}, | 15 | {3, nullptr, "GetMediaList"}, |
| 16 | {4, nullptr, "SetMediaType"}, | 16 | {4, nullptr, "SetMediaType"}, |
| 17 | {5, nullptr, "GetMediaType"}, | 17 | {5, nullptr, "GetMediaType"}, |
| 18 | {6, nullptr, "Unknown6"}, | ||
| 18 | }; | 19 | }; |
| 19 | // clang-format on | 20 | // clang-format on |
| 20 | 21 | ||
diff --git a/src/core/hle/service/sockets/nsd.cpp b/src/core/hle/service/sockets/nsd.cpp index 51c3739bb..1159debc5 100644 --- a/src/core/hle/service/sockets/nsd.cpp +++ b/src/core/hle/service/sockets/nsd.cpp | |||
| @@ -9,6 +9,7 @@ namespace Service::Sockets { | |||
| 9 | NSD::NSD(Core::System& system_, const char* name) : ServiceFramework{system_, name} { | 9 | NSD::NSD(Core::System& system_, const char* name) : ServiceFramework{system_, name} { |
| 10 | // clang-format off | 10 | // clang-format off |
| 11 | static const FunctionInfo functions[] = { | 11 | static const FunctionInfo functions[] = { |
| 12 | {5, nullptr, "GetSettingUrl"}, | ||
| 12 | {10, nullptr, "GetSettingName"}, | 13 | {10, nullptr, "GetSettingName"}, |
| 13 | {11, nullptr, "GetEnvironmentIdentifier"}, | 14 | {11, nullptr, "GetEnvironmentIdentifier"}, |
| 14 | {12, nullptr, "GetDeviceId"}, | 15 | {12, nullptr, "GetDeviceId"}, |
diff --git a/src/core/hle/service/sockets/sfdnsres.cpp b/src/core/hle/service/sockets/sfdnsres.cpp index 3a6329f56..5c71f423c 100644 --- a/src/core/hle/service/sockets/sfdnsres.cpp +++ b/src/core/hle/service/sockets/sfdnsres.cpp | |||
| @@ -9,8 +9,8 @@ namespace Service::Sockets { | |||
| 9 | 9 | ||
| 10 | SFDNSRES::SFDNSRES(Core::System& system_) : ServiceFramework{system_, "sfdnsres"} { | 10 | SFDNSRES::SFDNSRES(Core::System& system_) : ServiceFramework{system_, "sfdnsres"} { |
| 11 | static const FunctionInfo functions[] = { | 11 | static const FunctionInfo functions[] = { |
| 12 | {0, nullptr, "SetDnsAddressesPrivate"}, | 12 | {0, nullptr, "SetDnsAddressesPrivateRequest"}, |
| 13 | {1, nullptr, "GetDnsAddressPrivate"}, | 13 | {1, nullptr, "GetDnsAddressPrivateRequest"}, |
| 14 | {2, nullptr, "GetHostByNameRequest"}, | 14 | {2, nullptr, "GetHostByNameRequest"}, |
| 15 | {3, nullptr, "GetHostByAddrRequest"}, | 15 | {3, nullptr, "GetHostByAddrRequest"}, |
| 16 | {4, nullptr, "GetHostStringErrorRequest"}, | 16 | {4, nullptr, "GetHostStringErrorRequest"}, |
diff --git a/src/core/hle/service/spl/module.cpp b/src/core/hle/service/spl/module.cpp index 6903dd534..b1552c3f0 100644 --- a/src/core/hle/service/spl/module.cpp +++ b/src/core/hle/service/spl/module.cpp | |||
| @@ -9,11 +9,11 @@ | |||
| 9 | #include <functional> | 9 | #include <functional> |
| 10 | #include <vector> | 10 | #include <vector> |
| 11 | #include "common/logging/log.h" | 11 | #include "common/logging/log.h" |
| 12 | #include "common/settings.h" | ||
| 12 | #include "core/hle/ipc_helpers.h" | 13 | #include "core/hle/ipc_helpers.h" |
| 13 | #include "core/hle/service/spl/csrng.h" | 14 | #include "core/hle/service/spl/csrng.h" |
| 14 | #include "core/hle/service/spl/module.h" | 15 | #include "core/hle/service/spl/module.h" |
| 15 | #include "core/hle/service/spl/spl.h" | 16 | #include "core/hle/service/spl/spl.h" |
| 16 | #include "core/settings.h" | ||
| 17 | 17 | ||
| 18 | namespace Service::SPL { | 18 | namespace Service::SPL { |
| 19 | 19 | ||
diff --git a/src/core/hle/service/spl/spl.cpp b/src/core/hle/service/spl/spl.cpp index 4e212610f..fff3f3c42 100644 --- a/src/core/hle/service/spl/spl.cpp +++ b/src/core/hle/service/spl/spl.cpp | |||
| @@ -60,6 +60,8 @@ SPL_FS::SPL_FS(Core::System& system_, std::shared_ptr<Module> module_) | |||
| 60 | {4, nullptr, "GenerateAesKey"}, | 60 | {4, nullptr, "GenerateAesKey"}, |
| 61 | {5, nullptr, "SetConfig"}, | 61 | {5, nullptr, "SetConfig"}, |
| 62 | {7, &SPL::GetRandomBytes, "GenerateRandomBytes"}, | 62 | {7, &SPL::GetRandomBytes, "GenerateRandomBytes"}, |
| 63 | {9, nullptr, "ImportLotusKey"}, | ||
| 64 | {10, nullptr, "DecryptLotusMessage"}, | ||
| 63 | {11, nullptr, "IsDevelopment"}, | 65 | {11, nullptr, "IsDevelopment"}, |
| 64 | {12, nullptr, "GenerateSpecificAesKey"}, | 66 | {12, nullptr, "GenerateSpecificAesKey"}, |
| 65 | {14, nullptr, "DecryptAesKey"}, | 67 | {14, nullptr, "DecryptAesKey"}, |
| @@ -123,6 +125,7 @@ SPL_ES::SPL_ES(Core::System& system_, std::shared_ptr<Module> module_) | |||
| 123 | {14, nullptr, "DecryptAesKey"}, | 125 | {14, nullptr, "DecryptAesKey"}, |
| 124 | {15, nullptr, "CryptAesCtr"}, | 126 | {15, nullptr, "CryptAesCtr"}, |
| 125 | {16, nullptr, "ComputeCmac"}, | 127 | {16, nullptr, "ComputeCmac"}, |
| 128 | {17, nullptr, "ImportEsKey"}, | ||
| 126 | {18, nullptr, "UnwrapTitleKey"}, | 129 | {18, nullptr, "UnwrapTitleKey"}, |
| 127 | {20, nullptr, "PrepareEsCommonKey"}, | 130 | {20, nullptr, "PrepareEsCommonKey"}, |
| 128 | {21, nullptr, "AllocateAesKeyslot"}, | 131 | {21, nullptr, "AllocateAesKeyslot"}, |
diff --git a/src/core/hle/service/time/clock_types.h b/src/core/hle/service/time/clock_types.h index b78892223..a9cfe3eb0 100644 --- a/src/core/hle/service/time/clock_types.h +++ b/src/core/hle/service/time/clock_types.h | |||
| @@ -12,6 +12,12 @@ | |||
| 12 | 12 | ||
| 13 | namespace Service::Time::Clock { | 13 | namespace Service::Time::Clock { |
| 14 | 14 | ||
| 15 | enum class TimeType : u8 { | ||
| 16 | UserSystemClock, | ||
| 17 | NetworkSystemClock, | ||
| 18 | LocalSystemClock, | ||
| 19 | }; | ||
| 20 | |||
| 15 | /// https://switchbrew.org/wiki/Glue_services#SteadyClockTimePoint | 21 | /// https://switchbrew.org/wiki/Glue_services#SteadyClockTimePoint |
| 16 | struct SteadyClockTimePoint { | 22 | struct SteadyClockTimePoint { |
| 17 | s64 time_point; | 23 | s64 time_point; |
| @@ -84,7 +90,7 @@ struct ClockSnapshot { | |||
| 84 | SteadyClockTimePoint steady_clock_time_point; | 90 | SteadyClockTimePoint steady_clock_time_point; |
| 85 | TimeZone::LocationName location_name; | 91 | TimeZone::LocationName location_name; |
| 86 | u8 is_automatic_correction_enabled; | 92 | u8 is_automatic_correction_enabled; |
| 87 | u8 type; | 93 | TimeType type; |
| 88 | INSERT_PADDING_BYTES_NOINIT(0x2); | 94 | INSERT_PADDING_BYTES_NOINIT(0x2); |
| 89 | 95 | ||
| 90 | static ResultCode GetCurrentTime(s64& current_time, | 96 | static ResultCode GetCurrentTime(s64& current_time, |
diff --git a/src/core/hle/service/time/time.cpp b/src/core/hle/service/time/time.cpp index 78543688f..63e0247de 100644 --- a/src/core/hle/service/time/time.cpp +++ b/src/core/hle/service/time/time.cpp | |||
| @@ -122,14 +122,16 @@ private: | |||
| 122 | 122 | ||
| 123 | ResultCode Module::Interface::GetClockSnapshotFromSystemClockContextInternal( | 123 | ResultCode Module::Interface::GetClockSnapshotFromSystemClockContextInternal( |
| 124 | Kernel::KThread* thread, Clock::SystemClockContext user_context, | 124 | Kernel::KThread* thread, Clock::SystemClockContext user_context, |
| 125 | Clock::SystemClockContext network_context, u8 type, Clock::ClockSnapshot& clock_snapshot) { | 125 | Clock::SystemClockContext network_context, Clock::TimeType type, |
| 126 | Clock::ClockSnapshot& clock_snapshot) { | ||
| 126 | 127 | ||
| 127 | auto& time_manager{system.GetTimeManager()}; | 128 | auto& time_manager{system.GetTimeManager()}; |
| 128 | 129 | ||
| 130 | clock_snapshot.steady_clock_time_point = | ||
| 131 | time_manager.GetStandardSteadyClockCore().GetCurrentTimePoint(system); | ||
| 129 | clock_snapshot.is_automatic_correction_enabled = | 132 | clock_snapshot.is_automatic_correction_enabled = |
| 130 | time_manager.GetStandardUserSystemClockCore().IsAutomaticCorrectionEnabled(); | 133 | time_manager.GetStandardUserSystemClockCore().IsAutomaticCorrectionEnabled(); |
| 131 | clock_snapshot.user_context = user_context; | 134 | clock_snapshot.type = type; |
| 132 | clock_snapshot.network_context = network_context; | ||
| 133 | 135 | ||
| 134 | if (const ResultCode result{ | 136 | if (const ResultCode result{ |
| 135 | time_manager.GetTimeZoneContentManager().GetTimeZoneManager().GetDeviceLocationName( | 137 | time_manager.GetTimeZoneContentManager().GetTimeZoneManager().GetDeviceLocationName( |
| @@ -138,12 +140,11 @@ ResultCode Module::Interface::GetClockSnapshotFromSystemClockContextInternal( | |||
| 138 | return result; | 140 | return result; |
| 139 | } | 141 | } |
| 140 | 142 | ||
| 141 | const auto current_time_point{ | 143 | clock_snapshot.user_context = user_context; |
| 142 | time_manager.GetStandardSteadyClockCore().GetCurrentTimePoint(system)}; | ||
| 143 | clock_snapshot.steady_clock_time_point = current_time_point; | ||
| 144 | 144 | ||
| 145 | if (const ResultCode result{Clock::ClockSnapshot::GetCurrentTime( | 145 | if (const ResultCode result{Clock::ClockSnapshot::GetCurrentTime( |
| 146 | clock_snapshot.user_time, current_time_point, clock_snapshot.user_context)}; | 146 | clock_snapshot.user_time, clock_snapshot.steady_clock_time_point, |
| 147 | clock_snapshot.user_context)}; | ||
| 147 | result != RESULT_SUCCESS) { | 148 | result != RESULT_SUCCESS) { |
| 148 | return result; | 149 | return result; |
| 149 | } | 150 | } |
| @@ -157,9 +158,12 @@ ResultCode Module::Interface::GetClockSnapshotFromSystemClockContextInternal( | |||
| 157 | } | 158 | } |
| 158 | 159 | ||
| 159 | clock_snapshot.user_calendar_time = userCalendarInfo.time; | 160 | clock_snapshot.user_calendar_time = userCalendarInfo.time; |
| 160 | clock_snapshot.user_calendar_additional_time = userCalendarInfo.additiona_info; | 161 | clock_snapshot.user_calendar_additional_time = userCalendarInfo.additional_info; |
| 162 | |||
| 163 | clock_snapshot.network_context = network_context; | ||
| 161 | 164 | ||
| 162 | if (Clock::ClockSnapshot::GetCurrentTime(clock_snapshot.network_time, current_time_point, | 165 | if (Clock::ClockSnapshot::GetCurrentTime(clock_snapshot.network_time, |
| 166 | clock_snapshot.steady_clock_time_point, | ||
| 163 | clock_snapshot.network_context) != RESULT_SUCCESS) { | 167 | clock_snapshot.network_context) != RESULT_SUCCESS) { |
| 164 | clock_snapshot.network_time = 0; | 168 | clock_snapshot.network_time = 0; |
| 165 | } | 169 | } |
| @@ -173,8 +177,7 @@ ResultCode Module::Interface::GetClockSnapshotFromSystemClockContextInternal( | |||
| 173 | } | 177 | } |
| 174 | 178 | ||
| 175 | clock_snapshot.network_calendar_time = networkCalendarInfo.time; | 179 | clock_snapshot.network_calendar_time = networkCalendarInfo.time; |
| 176 | clock_snapshot.network_calendar_additional_time = networkCalendarInfo.additiona_info; | 180 | clock_snapshot.network_calendar_additional_time = networkCalendarInfo.additional_info; |
| 177 | clock_snapshot.type = type; | ||
| 178 | 181 | ||
| 179 | return RESULT_SUCCESS; | 182 | return RESULT_SUCCESS; |
| 180 | } | 183 | } |
| @@ -257,9 +260,10 @@ void Module::Interface::CalculateMonotonicSystemClockBaseTimePoint(Kernel::HLERe | |||
| 257 | } | 260 | } |
| 258 | 261 | ||
| 259 | void Module::Interface::GetClockSnapshot(Kernel::HLERequestContext& ctx) { | 262 | void Module::Interface::GetClockSnapshot(Kernel::HLERequestContext& ctx) { |
| 260 | LOG_DEBUG(Service_Time, "called"); | ||
| 261 | IPC::RequestParser rp{ctx}; | 263 | IPC::RequestParser rp{ctx}; |
| 262 | const auto type{rp.PopRaw<u8>()}; | 264 | const auto type{rp.PopEnum<Clock::TimeType>()}; |
| 265 | |||
| 266 | LOG_DEBUG(Service_Time, "called, type={}", type); | ||
| 263 | 267 | ||
| 264 | Clock::SystemClockContext user_context{}; | 268 | Clock::SystemClockContext user_context{}; |
| 265 | if (const ResultCode result{ | 269 | if (const ResultCode result{ |
| @@ -270,6 +274,7 @@ void Module::Interface::GetClockSnapshot(Kernel::HLERequestContext& ctx) { | |||
| 270 | rb.Push(result); | 274 | rb.Push(result); |
| 271 | return; | 275 | return; |
| 272 | } | 276 | } |
| 277 | |||
| 273 | Clock::SystemClockContext network_context{}; | 278 | Clock::SystemClockContext network_context{}; |
| 274 | if (const ResultCode result{ | 279 | if (const ResultCode result{ |
| 275 | system.GetTimeManager().GetStandardNetworkSystemClockCore().GetClockContext( | 280 | system.GetTimeManager().GetStandardNetworkSystemClockCore().GetClockContext( |
| @@ -295,14 +300,16 @@ void Module::Interface::GetClockSnapshot(Kernel::HLERequestContext& ctx) { | |||
| 295 | } | 300 | } |
| 296 | 301 | ||
| 297 | void Module::Interface::GetClockSnapshotFromSystemClockContext(Kernel::HLERequestContext& ctx) { | 302 | void Module::Interface::GetClockSnapshotFromSystemClockContext(Kernel::HLERequestContext& ctx) { |
| 298 | LOG_DEBUG(Service_Time, "called"); | ||
| 299 | IPC::RequestParser rp{ctx}; | 303 | IPC::RequestParser rp{ctx}; |
| 300 | const auto type{rp.PopRaw<u8>()}; | 304 | const auto type{rp.PopEnum<Clock::TimeType>()}; |
| 305 | |||
| 301 | rp.AlignWithPadding(); | 306 | rp.AlignWithPadding(); |
| 302 | 307 | ||
| 303 | const Clock::SystemClockContext user_context{rp.PopRaw<Clock::SystemClockContext>()}; | 308 | const Clock::SystemClockContext user_context{rp.PopRaw<Clock::SystemClockContext>()}; |
| 304 | const Clock::SystemClockContext network_context{rp.PopRaw<Clock::SystemClockContext>()}; | 309 | const Clock::SystemClockContext network_context{rp.PopRaw<Clock::SystemClockContext>()}; |
| 305 | 310 | ||
| 311 | LOG_DEBUG(Service_Time, "called, type={}", type); | ||
| 312 | |||
| 306 | Clock::ClockSnapshot clock_snapshot{}; | 313 | Clock::ClockSnapshot clock_snapshot{}; |
| 307 | if (const ResultCode result{GetClockSnapshotFromSystemClockContextInternal( | 314 | if (const ResultCode result{GetClockSnapshotFromSystemClockContextInternal( |
| 308 | &ctx.GetThread(), user_context, network_context, type, clock_snapshot)}; | 315 | &ctx.GetThread(), user_context, network_context, type, clock_snapshot)}; |
| @@ -321,9 +328,14 @@ void Module::Interface::CalculateStandardUserSystemClockDifferenceByUser( | |||
| 321 | Kernel::HLERequestContext& ctx) { | 328 | Kernel::HLERequestContext& ctx) { |
| 322 | LOG_DEBUG(Service_Time, "called"); | 329 | LOG_DEBUG(Service_Time, "called"); |
| 323 | 330 | ||
| 324 | IPC::RequestParser rp{ctx}; | 331 | Clock::ClockSnapshot snapshot_a; |
| 325 | const auto snapshot_a = rp.PopRaw<Clock::ClockSnapshot>(); | 332 | Clock::ClockSnapshot snapshot_b; |
| 326 | const auto snapshot_b = rp.PopRaw<Clock::ClockSnapshot>(); | 333 | |
| 334 | const auto snapshot_a_data = ctx.ReadBuffer(0); | ||
| 335 | const auto snapshot_b_data = ctx.ReadBuffer(1); | ||
| 336 | |||
| 337 | std::memcpy(&snapshot_a, snapshot_a_data.data(), sizeof(Clock::ClockSnapshot)); | ||
| 338 | std::memcpy(&snapshot_b, snapshot_b_data.data(), sizeof(Clock::ClockSnapshot)); | ||
| 327 | 339 | ||
| 328 | auto time_span_type{Clock::TimeSpanType::FromSeconds(snapshot_b.user_context.offset - | 340 | auto time_span_type{Clock::TimeSpanType::FromSeconds(snapshot_b.user_context.offset - |
| 329 | snapshot_a.user_context.offset)}; | 341 | snapshot_a.user_context.offset)}; |
diff --git a/src/core/hle/service/time/time.h b/src/core/hle/service/time/time.h index 4154c7ee9..ce9c479c6 100644 --- a/src/core/hle/service/time/time.h +++ b/src/core/hle/service/time/time.h | |||
| @@ -40,7 +40,7 @@ public: | |||
| 40 | private: | 40 | private: |
| 41 | ResultCode GetClockSnapshotFromSystemClockContextInternal( | 41 | ResultCode GetClockSnapshotFromSystemClockContextInternal( |
| 42 | Kernel::KThread* thread, Clock::SystemClockContext user_context, | 42 | Kernel::KThread* thread, Clock::SystemClockContext user_context, |
| 43 | Clock::SystemClockContext network_context, u8 type, | 43 | Clock::SystemClockContext network_context, Clock::TimeType type, |
| 44 | Clock::ClockSnapshot& cloc_snapshot); | 44 | Clock::ClockSnapshot& cloc_snapshot); |
| 45 | 45 | ||
| 46 | protected: | 46 | protected: |
diff --git a/src/core/hle/service/time/time_manager.cpp b/src/core/hle/service/time/time_manager.cpp index 1f7309f6b..f89c5aaad 100644 --- a/src/core/hle/service/time/time_manager.cpp +++ b/src/core/hle/service/time/time_manager.cpp | |||
| @@ -5,12 +5,12 @@ | |||
| 5 | #include <chrono> | 5 | #include <chrono> |
| 6 | #include <ctime> | 6 | #include <ctime> |
| 7 | 7 | ||
| 8 | #include "common/settings.h" | ||
| 8 | #include "common/time_zone.h" | 9 | #include "common/time_zone.h" |
| 9 | #include "core/hle/service/time/ephemeral_network_system_clock_context_writer.h" | 10 | #include "core/hle/service/time/ephemeral_network_system_clock_context_writer.h" |
| 10 | #include "core/hle/service/time/local_system_clock_context_writer.h" | 11 | #include "core/hle/service/time/local_system_clock_context_writer.h" |
| 11 | #include "core/hle/service/time/network_system_clock_context_writer.h" | 12 | #include "core/hle/service/time/network_system_clock_context_writer.h" |
| 12 | #include "core/hle/service/time/time_manager.h" | 13 | #include "core/hle/service/time/time_manager.h" |
| 13 | #include "core/settings.h" | ||
| 14 | 14 | ||
| 15 | namespace Service::Time { | 15 | namespace Service::Time { |
| 16 | 16 | ||
| @@ -44,7 +44,11 @@ struct TimeManager::Impl final { | |||
| 44 | const auto system_time{Clock::TimeSpanType::FromSeconds(GetExternalRtcValue())}; | 44 | const auto system_time{Clock::TimeSpanType::FromSeconds(GetExternalRtcValue())}; |
| 45 | SetupStandardSteadyClock(system, Common::UUID::Generate(), system_time, {}, {}); | 45 | SetupStandardSteadyClock(system, Common::UUID::Generate(), system_time, {}, {}); |
| 46 | SetupStandardLocalSystemClock(system, {}, system_time.ToSeconds()); | 46 | SetupStandardLocalSystemClock(system, {}, system_time.ToSeconds()); |
| 47 | SetupStandardNetworkSystemClock({}, standard_network_clock_accuracy); | 47 | |
| 48 | Clock::SystemClockContext clock_context{}; | ||
| 49 | standard_local_system_clock_core.GetClockContext(system, clock_context); | ||
| 50 | |||
| 51 | SetupStandardNetworkSystemClock(clock_context, standard_network_clock_accuracy); | ||
| 48 | SetupStandardUserSystemClock(system, {}, Clock::SteadyClockTimePoint::GetRandom()); | 52 | SetupStandardUserSystemClock(system, {}, Clock::SteadyClockTimePoint::GetRandom()); |
| 49 | SetupEphemeralNetworkSystemClock(); | 53 | SetupEphemeralNetworkSystemClock(); |
| 50 | } | 54 | } |
diff --git a/src/core/hle/service/time/time_zone_content_manager.cpp b/src/core/hle/service/time/time_zone_content_manager.cpp index 4177d0a41..3c8e71a3c 100644 --- a/src/core/hle/service/time/time_zone_content_manager.cpp +++ b/src/core/hle/service/time/time_zone_content_manager.cpp | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | #include <sstream> | 5 | #include <sstream> |
| 6 | 6 | ||
| 7 | #include "common/logging/log.h" | 7 | #include "common/logging/log.h" |
| 8 | #include "common/settings.h" | ||
| 8 | #include "common/time_zone.h" | 9 | #include "common/time_zone.h" |
| 9 | #include "core/core.h" | 10 | #include "core/core.h" |
| 10 | #include "core/file_sys/content_archive.h" | 11 | #include "core/file_sys/content_archive.h" |
| @@ -15,7 +16,6 @@ | |||
| 15 | #include "core/hle/service/filesystem/filesystem.h" | 16 | #include "core/hle/service/filesystem/filesystem.h" |
| 16 | #include "core/hle/service/time/time_manager.h" | 17 | #include "core/hle/service/time/time_manager.h" |
| 17 | #include "core/hle/service/time/time_zone_content_manager.h" | 18 | #include "core/hle/service/time/time_zone_content_manager.h" |
| 18 | #include "core/settings.h" | ||
| 19 | 19 | ||
| 20 | namespace Service::Time::TimeZone { | 20 | namespace Service::Time::TimeZone { |
| 21 | 21 | ||
diff --git a/src/core/hle/service/time/time_zone_manager.cpp b/src/core/hle/service/time/time_zone_manager.cpp index bdf0439f2..3032ca193 100644 --- a/src/core/hle/service/time/time_zone_manager.cpp +++ b/src/core/hle/service/time/time_zone_manager.cpp | |||
| @@ -818,7 +818,7 @@ static ResultCode ToCalendarTimeInternal(const TimeZoneRule& rules, s64 time, | |||
| 818 | static ResultCode ToCalendarTimeImpl(const TimeZoneRule& rules, s64 time, CalendarInfo& calendar) { | 818 | static ResultCode ToCalendarTimeImpl(const TimeZoneRule& rules, s64 time, CalendarInfo& calendar) { |
| 819 | CalendarTimeInternal calendar_time{}; | 819 | CalendarTimeInternal calendar_time{}; |
| 820 | const ResultCode result{ | 820 | const ResultCode result{ |
| 821 | ToCalendarTimeInternal(rules, time, calendar_time, calendar.additiona_info)}; | 821 | ToCalendarTimeInternal(rules, time, calendar_time, calendar.additional_info)}; |
| 822 | calendar.time.year = static_cast<s16>(calendar_time.year); | 822 | calendar.time.year = static_cast<s16>(calendar_time.year); |
| 823 | 823 | ||
| 824 | // Internal impl. uses 0-indexed month | 824 | // Internal impl. uses 0-indexed month |
diff --git a/src/core/hle/service/time/time_zone_service.cpp b/src/core/hle/service/time/time_zone_service.cpp index 25cecbc83..3117627cf 100644 --- a/src/core/hle/service/time/time_zone_service.cpp +++ b/src/core/hle/service/time/time_zone_service.cpp | |||
| @@ -20,6 +20,7 @@ ITimeZoneService ::ITimeZoneService(Core::System& system_, | |||
| 20 | {3, nullptr, "LoadLocationNameList"}, | 20 | {3, nullptr, "LoadLocationNameList"}, |
| 21 | {4, &ITimeZoneService::LoadTimeZoneRule, "LoadTimeZoneRule"}, | 21 | {4, &ITimeZoneService::LoadTimeZoneRule, "LoadTimeZoneRule"}, |
| 22 | {5, nullptr, "GetTimeZoneRuleVersion"}, | 22 | {5, nullptr, "GetTimeZoneRuleVersion"}, |
| 23 | {6, nullptr, "GetDeviceLocationNameAndUpdatedTime"}, | ||
| 23 | {100, &ITimeZoneService::ToCalendarTime, "ToCalendarTime"}, | 24 | {100, &ITimeZoneService::ToCalendarTime, "ToCalendarTime"}, |
| 24 | {101, &ITimeZoneService::ToCalendarTimeWithMyRule, "ToCalendarTimeWithMyRule"}, | 25 | {101, &ITimeZoneService::ToCalendarTimeWithMyRule, "ToCalendarTimeWithMyRule"}, |
| 25 | {201, &ITimeZoneService::ToPosixTime, "ToPosixTime"}, | 26 | {201, &ITimeZoneService::ToPosixTime, "ToPosixTime"}, |
diff --git a/src/core/hle/service/time/time_zone_types.h b/src/core/hle/service/time/time_zone_types.h index 4a57e036d..d39103253 100644 --- a/src/core/hle/service/time/time_zone_types.h +++ b/src/core/hle/service/time/time_zone_types.h | |||
| @@ -66,8 +66,8 @@ struct CalendarTime { | |||
| 66 | static_assert(sizeof(CalendarTime) == 0x8, "CalendarTime is incorrect size"); | 66 | static_assert(sizeof(CalendarTime) == 0x8, "CalendarTime is incorrect size"); |
| 67 | 67 | ||
| 68 | struct CalendarInfo { | 68 | struct CalendarInfo { |
| 69 | CalendarTime time{}; | 69 | CalendarTime time; |
| 70 | CalendarAdditionalInfo additiona_info{}; | 70 | CalendarAdditionalInfo additional_info; |
| 71 | }; | 71 | }; |
| 72 | static_assert(sizeof(CalendarInfo) == 0x20, "CalendarInfo is incorrect size"); | 72 | static_assert(sizeof(CalendarInfo) == 0x20, "CalendarInfo is incorrect size"); |
| 73 | 73 | ||
diff --git a/src/core/hle/service/usb/usb.cpp b/src/core/hle/service/usb/usb.cpp index 579de83e4..b3b230a8c 100644 --- a/src/core/hle/service/usb/usb.cpp +++ b/src/core/hle/service/usb/usb.cpp | |||
| @@ -69,15 +69,15 @@ public: | |||
| 69 | : ServiceFramework{system_, "IClientEpSession"} { | 69 | : ServiceFramework{system_, "IClientEpSession"} { |
| 70 | // clang-format off | 70 | // clang-format off |
| 71 | static const FunctionInfo functions[] = { | 71 | static const FunctionInfo functions[] = { |
| 72 | {0, nullptr, "Open"}, | 72 | {0, nullptr, "ReOpen"}, |
| 73 | {1, nullptr, "Close"}, | 73 | {1, nullptr, "Close"}, |
| 74 | {2, nullptr, "Unknown2"}, | 74 | {2, nullptr, "GetCompletionEvent"}, |
| 75 | {3, nullptr, "Populate"}, | 75 | {3, nullptr, "PopulateRing"}, |
| 76 | {4, nullptr, "PostBufferAsync"}, | 76 | {4, nullptr, "PostBufferAsync"}, |
| 77 | {5, nullptr, "GetXferReport"}, | 77 | {5, nullptr, "GetXferReport"}, |
| 78 | {6, nullptr, "PostBufferMultiAsync"}, | 78 | {6, nullptr, "PostBufferMultiAsync"}, |
| 79 | {7, nullptr, "Unknown7"}, | 79 | {7, nullptr, "CreateSmmuSpace"}, |
| 80 | {8, nullptr, "Unknown8"}, | 80 | {8, nullptr, "ShareReportRing"}, |
| 81 | }; | 81 | }; |
| 82 | // clang-format on | 82 | // clang-format on |
| 83 | 83 | ||
| @@ -91,7 +91,7 @@ public: | |||
| 91 | : ServiceFramework{system_, "IClientIfSession"} { | 91 | : ServiceFramework{system_, "IClientIfSession"} { |
| 92 | // clang-format off | 92 | // clang-format off |
| 93 | static const FunctionInfo functions[] = { | 93 | static const FunctionInfo functions[] = { |
| 94 | {0, nullptr, "Unknown0"}, | 94 | {0, nullptr, "GetStateChangeEvent"}, |
| 95 | {1, nullptr, "SetInterface"}, | 95 | {1, nullptr, "SetInterface"}, |
| 96 | {2, nullptr, "GetInterface"}, | 96 | {2, nullptr, "GetInterface"}, |
| 97 | {3, nullptr, "GetAlternateInterface"}, | 97 | {3, nullptr, "GetAlternateInterface"}, |
| @@ -176,15 +176,15 @@ public: | |||
| 176 | : ServiceFramework{system_, "IPdCradleSession"} { | 176 | : ServiceFramework{system_, "IPdCradleSession"} { |
| 177 | // clang-format off | 177 | // clang-format off |
| 178 | static const FunctionInfo functions[] = { | 178 | static const FunctionInfo functions[] = { |
| 179 | {0, nullptr, "VdmUserWrite"}, | 179 | {0, nullptr, "SetCradleVdo"}, |
| 180 | {1, nullptr, "VdmUserRead"}, | 180 | {1, nullptr, "GetCradleVdo"}, |
| 181 | {2, nullptr, "Vdm20Init"}, | 181 | {2, nullptr, "ResetCradleUsbHub"}, |
| 182 | {3, nullptr, "GetFwType"}, | 182 | {3, nullptr, "GetHostPdcFirmwareType"}, |
| 183 | {4, nullptr, "GetFwRevision"}, | 183 | {4, nullptr, "GetHostPdcFirmwareRevision"}, |
| 184 | {5, nullptr, "GetManufacturerId"}, | 184 | {5, nullptr, "GetHostPdcManufactureId"}, |
| 185 | {6, nullptr, "GetDeviceId"}, | 185 | {6, nullptr, "GetHostPdcDeviceId"}, |
| 186 | {7, nullptr, "Unknown7"}, | 186 | {7, nullptr, "AwakeCradle"}, |
| 187 | {8, nullptr, "Unknown8"}, | 187 | {8, nullptr, "SleepCradle"}, |
| 188 | }; | 188 | }; |
| 189 | // clang-format on | 189 | // clang-format on |
| 190 | 190 | ||
| @@ -219,12 +219,12 @@ public: | |||
| 219 | explicit USB_PM(Core::System& system_) : ServiceFramework{system_, "usb:pm"} { | 219 | explicit USB_PM(Core::System& system_) : ServiceFramework{system_, "usb:pm"} { |
| 220 | // clang-format off | 220 | // clang-format off |
| 221 | static const FunctionInfo functions[] = { | 221 | static const FunctionInfo functions[] = { |
| 222 | {0, nullptr, "Unknown0"}, | 222 | {0, nullptr, "GetPowerEvent"}, |
| 223 | {1, nullptr, "Unknown1"}, | 223 | {1, nullptr, "GetPowerState"}, |
| 224 | {2, nullptr, "Unknown2"}, | 224 | {2, nullptr, "GetDataEvent"}, |
| 225 | {3, nullptr, "Unknown3"}, | 225 | {3, nullptr, "GetDataRole"}, |
| 226 | {4, nullptr, "Unknown4"}, | 226 | {4, nullptr, "SetDiagData"}, |
| 227 | {5, nullptr, "Unknown5"}, | 227 | {5, nullptr, "GetDiagData"}, |
| 228 | }; | 228 | }; |
| 229 | // clang-format on | 229 | // clang-format on |
| 230 | 230 | ||
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index 7423287ea..348360b51 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | #include "common/common_funcs.h" | 15 | #include "common/common_funcs.h" |
| 16 | #include "common/logging/log.h" | 16 | #include "common/logging/log.h" |
| 17 | #include "common/math_util.h" | 17 | #include "common/math_util.h" |
| 18 | #include "common/settings.h" | ||
| 18 | #include "common/swap.h" | 19 | #include "common/swap.h" |
| 19 | #include "core/core_timing.h" | 20 | #include "core/core_timing.h" |
| 20 | #include "core/hle/ipc_helpers.h" | 21 | #include "core/hle/ipc_helpers.h" |
| @@ -30,7 +31,6 @@ | |||
| 30 | #include "core/hle/service/vi/vi_m.h" | 31 | #include "core/hle/service/vi/vi_m.h" |
| 31 | #include "core/hle/service/vi/vi_s.h" | 32 | #include "core/hle/service/vi/vi_s.h" |
| 32 | #include "core/hle/service/vi/vi_u.h" | 33 | #include "core/hle/service/vi/vi_u.h" |
| 33 | #include "core/settings.h" | ||
| 34 | 34 | ||
| 35 | namespace Service::VI { | 35 | namespace Service::VI { |
| 36 | 36 | ||
| @@ -695,6 +695,7 @@ public: | |||
| 695 | {2205, &ISystemDisplayService::SetLayerZ, "SetLayerZ"}, | 695 | {2205, &ISystemDisplayService::SetLayerZ, "SetLayerZ"}, |
| 696 | {2207, &ISystemDisplayService::SetLayerVisibility, "SetLayerVisibility"}, | 696 | {2207, &ISystemDisplayService::SetLayerVisibility, "SetLayerVisibility"}, |
| 697 | {2209, nullptr, "SetLayerAlpha"}, | 697 | {2209, nullptr, "SetLayerAlpha"}, |
| 698 | {2210, nullptr, "SetLayerPositionAndSize"}, | ||
| 698 | {2312, nullptr, "CreateStrayLayer"}, | 699 | {2312, nullptr, "CreateStrayLayer"}, |
| 699 | {2400, nullptr, "OpenIndirectLayer"}, | 700 | {2400, nullptr, "OpenIndirectLayer"}, |
| 700 | {2401, nullptr, "CloseIndirectLayer"}, | 701 | {2401, nullptr, "CloseIndirectLayer"}, |
| @@ -718,6 +719,7 @@ public: | |||
| 718 | {3215, nullptr, "SetDisplayGamma"}, | 719 | {3215, nullptr, "SetDisplayGamma"}, |
| 719 | {3216, nullptr, "GetDisplayCmuLuma"}, | 720 | {3216, nullptr, "GetDisplayCmuLuma"}, |
| 720 | {3217, nullptr, "SetDisplayCmuLuma"}, | 721 | {3217, nullptr, "SetDisplayCmuLuma"}, |
| 722 | {3218, nullptr, "SetDisplayCrcMode"}, | ||
| 721 | {6013, nullptr, "GetLayerPresentationSubmissionTimestamps"}, | 723 | {6013, nullptr, "GetLayerPresentationSubmissionTimestamps"}, |
| 722 | {8225, nullptr, "GetSharedBufferMemoryHandleId"}, | 724 | {8225, nullptr, "GetSharedBufferMemoryHandleId"}, |
| 723 | {8250, nullptr, "OpenSharedLayer"}, | 725 | {8250, nullptr, "OpenSharedLayer"}, |
| @@ -729,6 +731,7 @@ public: | |||
| 729 | {8256, nullptr, "GetSharedFrameBufferAcquirableEvent"}, | 731 | {8256, nullptr, "GetSharedFrameBufferAcquirableEvent"}, |
| 730 | {8257, nullptr, "FillSharedFrameBufferColor"}, | 732 | {8257, nullptr, "FillSharedFrameBufferColor"}, |
| 731 | {8258, nullptr, "CancelSharedFrameBuffer"}, | 733 | {8258, nullptr, "CancelSharedFrameBuffer"}, |
| 734 | {9000, nullptr, "GetDp2hdmiController"}, | ||
| 732 | }; | 735 | }; |
| 733 | RegisterHandlers(functions); | 736 | RegisterHandlers(functions); |
| 734 | } | 737 | } |
| @@ -808,10 +811,15 @@ public: | |||
| 808 | {2402, nullptr, "GetDisplayHotplugState"}, | 811 | {2402, nullptr, "GetDisplayHotplugState"}, |
| 809 | {2501, nullptr, "GetCompositorErrorInfo"}, | 812 | {2501, nullptr, "GetCompositorErrorInfo"}, |
| 810 | {2601, nullptr, "GetDisplayErrorEvent"}, | 813 | {2601, nullptr, "GetDisplayErrorEvent"}, |
| 814 | {2701, nullptr, "GetDisplayFatalErrorEvent"}, | ||
| 811 | {4201, nullptr, "SetDisplayAlpha"}, | 815 | {4201, nullptr, "SetDisplayAlpha"}, |
| 812 | {4203, nullptr, "SetDisplayLayerStack"}, | 816 | {4203, nullptr, "SetDisplayLayerStack"}, |
| 813 | {4205, nullptr, "SetDisplayPowerState"}, | 817 | {4205, nullptr, "SetDisplayPowerState"}, |
| 814 | {4206, nullptr, "SetDefaultDisplay"}, | 818 | {4206, nullptr, "SetDefaultDisplay"}, |
| 819 | {4207, nullptr, "ResetDisplayPanel"}, | ||
| 820 | {4208, nullptr, "SetDisplayFatalErrorEnabled"}, | ||
| 821 | {4209, nullptr, "IsDisplayPanelOn"}, | ||
| 822 | {4300, nullptr, "GetInternalPanelId"}, | ||
| 815 | {6000, &IManagerDisplayService::AddToLayerStack, "AddToLayerStack"}, | 823 | {6000, &IManagerDisplayService::AddToLayerStack, "AddToLayerStack"}, |
| 816 | {6001, nullptr, "RemoveFromLayerStack"}, | 824 | {6001, nullptr, "RemoveFromLayerStack"}, |
| 817 | {6002, &IManagerDisplayService::SetLayerVisibility, "SetLayerVisibility"}, | 825 | {6002, &IManagerDisplayService::SetLayerVisibility, "SetLayerVisibility"}, |
diff --git a/src/core/hle/service/wlan/wlan.cpp b/src/core/hle/service/wlan/wlan.cpp index ddbf04069..44957e01d 100644 --- a/src/core/hle/service/wlan/wlan.cpp +++ b/src/core/hle/service/wlan/wlan.cpp | |||
| @@ -46,6 +46,13 @@ public: | |||
| 46 | {28, nullptr, "Unknown28"}, | 46 | {28, nullptr, "Unknown28"}, |
| 47 | {29, nullptr, "Unknown29"}, | 47 | {29, nullptr, "Unknown29"}, |
| 48 | {30, nullptr, "Unknown30"}, | 48 | {30, nullptr, "Unknown30"}, |
| 49 | {31, nullptr, "Unknown31"}, | ||
| 50 | {32, nullptr, "Unknown32"}, | ||
| 51 | {33, nullptr, "Unknown33"}, | ||
| 52 | {34, nullptr, "Unknown34"}, | ||
| 53 | {35, nullptr, "Unknown35"}, | ||
| 54 | {36, nullptr, "Unknown36"}, | ||
| 55 | {37, nullptr, "Unknown37"}, | ||
| 49 | }; | 56 | }; |
| 50 | // clang-format on | 57 | // clang-format on |
| 51 | 58 | ||
diff --git a/src/core/loader/nro.cpp b/src/core/loader/nro.cpp index 14618cb40..0115ed0c4 100644 --- a/src/core/loader/nro.cpp +++ b/src/core/loader/nro.cpp | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| 10 | #include "common/file_util.h" | 10 | #include "common/file_util.h" |
| 11 | #include "common/logging/log.h" | 11 | #include "common/logging/log.h" |
| 12 | #include "common/settings.h" | ||
| 12 | #include "common/swap.h" | 13 | #include "common/swap.h" |
| 13 | #include "core/core.h" | 14 | #include "core/core.h" |
| 14 | #include "core/file_sys/control_metadata.h" | 15 | #include "core/file_sys/control_metadata.h" |
| @@ -22,7 +23,6 @@ | |||
| 22 | #include "core/loader/nro.h" | 23 | #include "core/loader/nro.h" |
| 23 | #include "core/loader/nso.h" | 24 | #include "core/loader/nso.h" |
| 24 | #include "core/memory.h" | 25 | #include "core/memory.h" |
| 25 | #include "core/settings.h" | ||
| 26 | 26 | ||
| 27 | namespace Loader { | 27 | namespace Loader { |
| 28 | 28 | ||
diff --git a/src/core/loader/nso.cpp b/src/core/loader/nso.cpp index cbd048695..0c83dd666 100644 --- a/src/core/loader/nso.cpp +++ b/src/core/loader/nso.cpp | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | #include "common/hex_util.h" | 11 | #include "common/hex_util.h" |
| 12 | #include "common/logging/log.h" | 12 | #include "common/logging/log.h" |
| 13 | #include "common/lz4_compression.h" | 13 | #include "common/lz4_compression.h" |
| 14 | #include "common/settings.h" | ||
| 14 | #include "common/swap.h" | 15 | #include "common/swap.h" |
| 15 | #include "core/core.h" | 16 | #include "core/core.h" |
| 16 | #include "core/file_sys/patch_manager.h" | 17 | #include "core/file_sys/patch_manager.h" |
| @@ -20,7 +21,6 @@ | |||
| 20 | #include "core/hle/kernel/process.h" | 21 | #include "core/hle/kernel/process.h" |
| 21 | #include "core/loader/nso.h" | 22 | #include "core/loader/nso.h" |
| 22 | #include "core/memory.h" | 23 | #include "core/memory.h" |
| 23 | #include "core/settings.h" | ||
| 24 | 24 | ||
| 25 | namespace Loader { | 25 | namespace Loader { |
| 26 | namespace { | 26 | namespace { |
diff --git a/src/core/perf_stats.cpp b/src/core/perf_stats.cpp index b93396a80..c92337079 100644 --- a/src/core/perf_stats.cpp +++ b/src/core/perf_stats.cpp | |||
| @@ -13,8 +13,8 @@ | |||
| 13 | #include <fmt/format.h> | 13 | #include <fmt/format.h> |
| 14 | #include "common/file_util.h" | 14 | #include "common/file_util.h" |
| 15 | #include "common/math_util.h" | 15 | #include "common/math_util.h" |
| 16 | #include "common/settings.h" | ||
| 16 | #include "core/perf_stats.h" | 17 | #include "core/perf_stats.h" |
| 17 | #include "core/settings.h" | ||
| 18 | 18 | ||
| 19 | using namespace std::chrono_literals; | 19 | using namespace std::chrono_literals; |
| 20 | using DoubleSecs = std::chrono::duration<double, std::chrono::seconds::period>; | 20 | using DoubleSecs = std::chrono::duration<double, std::chrono::seconds::period>; |
diff --git a/src/core/reporter.cpp b/src/core/reporter.cpp index 74fb32814..311d4dda8 100644 --- a/src/core/reporter.cpp +++ b/src/core/reporter.cpp | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | #include "common/file_util.h" | 14 | #include "common/file_util.h" |
| 15 | #include "common/hex_util.h" | 15 | #include "common/hex_util.h" |
| 16 | #include "common/scm_rev.h" | 16 | #include "common/scm_rev.h" |
| 17 | #include "common/settings.h" | ||
| 17 | #include "core/arm/arm_interface.h" | 18 | #include "core/arm/arm_interface.h" |
| 18 | #include "core/core.h" | 19 | #include "core/core.h" |
| 19 | #include "core/hle/kernel/hle_ipc.h" | 20 | #include "core/hle/kernel/hle_ipc.h" |
| @@ -22,7 +23,6 @@ | |||
| 22 | #include "core/hle/result.h" | 23 | #include "core/hle/result.h" |
| 23 | #include "core/memory.h" | 24 | #include "core/memory.h" |
| 24 | #include "core/reporter.h" | 25 | #include "core/reporter.h" |
| 25 | #include "core/settings.h" | ||
| 26 | 26 | ||
| 27 | namespace { | 27 | namespace { |
| 28 | 28 | ||
diff --git a/src/core/telemetry_session.cpp b/src/core/telemetry_session.cpp index d11b15f38..6dcff5400 100644 --- a/src/core/telemetry_session.cpp +++ b/src/core/telemetry_session.cpp | |||
| @@ -12,10 +12,10 @@ | |||
| 12 | #include "common/file_util.h" | 12 | #include "common/file_util.h" |
| 13 | #include "common/logging/log.h" | 13 | #include "common/logging/log.h" |
| 14 | 14 | ||
| 15 | #include "common/settings.h" | ||
| 15 | #include "core/file_sys/control_metadata.h" | 16 | #include "core/file_sys/control_metadata.h" |
| 16 | #include "core/file_sys/patch_manager.h" | 17 | #include "core/file_sys/patch_manager.h" |
| 17 | #include "core/loader/loader.h" | 18 | #include "core/loader/loader.h" |
| 18 | #include "core/settings.h" | ||
| 19 | #include "core/telemetry_session.h" | 19 | #include "core/telemetry_session.h" |
| 20 | 20 | ||
| 21 | #ifdef ENABLE_WEB_SERVICE | 21 | #ifdef ENABLE_WEB_SERVICE |
diff --git a/src/input_common/CMakeLists.txt b/src/input_common/CMakeLists.txt index 38ab31898..c3cfe7efc 100644 --- a/src/input_common/CMakeLists.txt +++ b/src/input_common/CMakeLists.txt | |||
| @@ -9,8 +9,6 @@ add_library(input_common STATIC | |||
| 9 | motion_from_button.h | 9 | motion_from_button.h |
| 10 | motion_input.cpp | 10 | motion_input.cpp |
| 11 | motion_input.h | 11 | motion_input.h |
| 12 | settings.cpp | ||
| 13 | settings.h | ||
| 14 | touch_from_button.cpp | 12 | touch_from_button.cpp |
| 15 | touch_from_button.h | 13 | touch_from_button.h |
| 16 | gcadapter/gc_adapter.cpp | 14 | gcadapter/gc_adapter.cpp |
diff --git a/src/input_common/analog_from_button.cpp b/src/input_common/analog_from_button.cpp index 770893687..f8ec179d0 100755 --- a/src/input_common/analog_from_button.cpp +++ b/src/input_common/analog_from_button.cpp | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | #include <cmath> | 7 | #include <cmath> |
| 8 | #include <thread> | 8 | #include <thread> |
| 9 | #include "common/math_util.h" | 9 | #include "common/math_util.h" |
| 10 | #include "core/settings.h" | 10 | #include "common/settings.h" |
| 11 | #include "input_common/analog_from_button.h" | 11 | #include "input_common/analog_from_button.h" |
| 12 | 12 | ||
| 13 | namespace InputCommon { | 13 | namespace InputCommon { |
diff --git a/src/input_common/gcadapter/gc_adapter.cpp b/src/input_common/gcadapter/gc_adapter.cpp index d80195c82..ec3167bea 100644 --- a/src/input_common/gcadapter/gc_adapter.cpp +++ b/src/input_common/gcadapter/gc_adapter.cpp | |||
| @@ -16,8 +16,8 @@ | |||
| 16 | 16 | ||
| 17 | #include "common/logging/log.h" | 17 | #include "common/logging/log.h" |
| 18 | #include "common/param_package.h" | 18 | #include "common/param_package.h" |
| 19 | #include "common/settings_input.h" | ||
| 19 | #include "input_common/gcadapter/gc_adapter.h" | 20 | #include "input_common/gcadapter/gc_adapter.h" |
| 20 | #include "input_common/settings.h" | ||
| 21 | 21 | ||
| 22 | namespace GCAdapter { | 22 | namespace GCAdapter { |
| 23 | 23 | ||
diff --git a/src/input_common/mouse/mouse_input.cpp b/src/input_common/mouse/mouse_input.cpp index 329e416c7..fff1c6b45 100644 --- a/src/input_common/mouse/mouse_input.cpp +++ b/src/input_common/mouse/mouse_input.cpp | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | // Licensed under GPLv2+ | 2 | // Licensed under GPLv2+ |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include "core/settings.h" | 5 | #include "common/settings.h" |
| 6 | #include "input_common/mouse/mouse_input.h" | 6 | #include "input_common/mouse/mouse_input.h" |
| 7 | 7 | ||
| 8 | namespace MouseInput { | 8 | namespace MouseInput { |
diff --git a/src/input_common/mouse/mouse_poller.cpp b/src/input_common/mouse/mouse_poller.cpp index 0e1db54fb..d96104a4e 100644 --- a/src/input_common/mouse/mouse_poller.cpp +++ b/src/input_common/mouse/mouse_poller.cpp | |||
| @@ -5,8 +5,8 @@ | |||
| 5 | #include <mutex> | 5 | #include <mutex> |
| 6 | #include <utility> | 6 | #include <utility> |
| 7 | 7 | ||
| 8 | #include "common/settings.h" | ||
| 8 | #include "common/threadsafe_queue.h" | 9 | #include "common/threadsafe_queue.h" |
| 9 | #include "core/settings.h" | ||
| 10 | #include "input_common/mouse/mouse_input.h" | 10 | #include "input_common/mouse/mouse_input.h" |
| 11 | #include "input_common/mouse/mouse_poller.h" | 11 | #include "input_common/mouse/mouse_poller.h" |
| 12 | 12 | ||
diff --git a/src/input_common/sdl/sdl_impl.cpp b/src/input_common/sdl/sdl_impl.cpp index f67de37e3..9418e78fa 100644 --- a/src/input_common/sdl/sdl_impl.cpp +++ b/src/input_common/sdl/sdl_impl.cpp | |||
| @@ -20,11 +20,11 @@ | |||
| 20 | #include <SDL.h> | 20 | #include <SDL.h> |
| 21 | #include "common/logging/log.h" | 21 | #include "common/logging/log.h" |
| 22 | #include "common/param_package.h" | 22 | #include "common/param_package.h" |
| 23 | #include "common/settings_input.h" | ||
| 23 | #include "common/threadsafe_queue.h" | 24 | #include "common/threadsafe_queue.h" |
| 24 | #include "core/frontend/input.h" | 25 | #include "core/frontend/input.h" |
| 25 | #include "input_common/motion_input.h" | 26 | #include "input_common/motion_input.h" |
| 26 | #include "input_common/sdl/sdl_impl.h" | 27 | #include "input_common/sdl/sdl_impl.h" |
| 27 | #include "input_common/settings.h" | ||
| 28 | 28 | ||
| 29 | namespace InputCommon::SDL { | 29 | namespace InputCommon::SDL { |
| 30 | 30 | ||
| @@ -761,7 +761,7 @@ std::vector<Common::ParamPackage> SDLState::GetInputDevices() { | |||
| 761 | for (const auto& joystick : value) { | 761 | for (const auto& joystick : value) { |
| 762 | if (auto* const controller = joystick->GetSDLGameController()) { | 762 | if (auto* const controller = joystick->GetSDLGameController()) { |
| 763 | std::string name = | 763 | std::string name = |
| 764 | fmt::format("{} {}", SDL_GameControllerName(controller), joystick->GetPort()); | 764 | fmt::format("{} {}", GetControllerName(controller), joystick->GetPort()); |
| 765 | devices.emplace_back(Common::ParamPackage{ | 765 | devices.emplace_back(Common::ParamPackage{ |
| 766 | {"class", "sdl"}, | 766 | {"class", "sdl"}, |
| 767 | {"display", std::move(name)}, | 767 | {"display", std::move(name)}, |
| @@ -782,6 +782,17 @@ std::vector<Common::ParamPackage> SDLState::GetInputDevices() { | |||
| 782 | return devices; | 782 | return devices; |
| 783 | } | 783 | } |
| 784 | 784 | ||
| 785 | std::string SDLState::GetControllerName(SDL_GameController* controller) const { | ||
| 786 | switch (SDL_GameControllerGetType(controller)) { | ||
| 787 | case SDL_CONTROLLER_TYPE_XBOX360: | ||
| 788 | return "XBox 360 Controller"; | ||
| 789 | case SDL_CONTROLLER_TYPE_XBOXONE: | ||
| 790 | return "XBox One Controller"; | ||
| 791 | default: | ||
| 792 | return SDL_GameControllerName(controller); | ||
| 793 | } | ||
| 794 | } | ||
| 795 | |||
| 785 | namespace { | 796 | namespace { |
| 786 | Common::ParamPackage BuildAnalogParamPackageForButton(int port, std::string guid, s32 axis, | 797 | Common::ParamPackage BuildAnalogParamPackageForButton(int port, std::string guid, s32 axis, |
| 787 | float value = 0.1f) { | 798 | float value = 0.1f) { |
| @@ -930,16 +941,19 @@ ButtonMapping SDLState::GetButtonMappingForDevice(const Common::ParamPackage& pa | |||
| 930 | return {}; | 941 | return {}; |
| 931 | } | 942 | } |
| 932 | 943 | ||
| 944 | const bool invert = | ||
| 945 | SDL_GameControllerGetType(controller) != SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO; | ||
| 946 | |||
| 933 | // This list is missing ZL/ZR since those are not considered buttons in SDL GameController. | 947 | // This list is missing ZL/ZR since those are not considered buttons in SDL GameController. |
| 934 | // We will add those afterwards | 948 | // We will add those afterwards |
| 935 | // This list also excludes Screenshot since theres not really a mapping for that | 949 | // This list also excludes Screenshot since theres not really a mapping for that |
| 936 | using ButtonBindings = | 950 | using ButtonBindings = |
| 937 | std::array<std::pair<Settings::NativeButton::Values, SDL_GameControllerButton>, 17>; | 951 | std::array<std::pair<Settings::NativeButton::Values, SDL_GameControllerButton>, 17>; |
| 938 | static constexpr ButtonBindings switch_to_sdl_button{{ | 952 | const ButtonBindings switch_to_sdl_button{{ |
| 939 | {Settings::NativeButton::A, SDL_CONTROLLER_BUTTON_B}, | 953 | {Settings::NativeButton::A, invert ? SDL_CONTROLLER_BUTTON_B : SDL_CONTROLLER_BUTTON_A}, |
| 940 | {Settings::NativeButton::B, SDL_CONTROLLER_BUTTON_A}, | 954 | {Settings::NativeButton::B, invert ? SDL_CONTROLLER_BUTTON_A : SDL_CONTROLLER_BUTTON_B}, |
| 941 | {Settings::NativeButton::X, SDL_CONTROLLER_BUTTON_Y}, | 955 | {Settings::NativeButton::X, invert ? SDL_CONTROLLER_BUTTON_Y : SDL_CONTROLLER_BUTTON_X}, |
| 942 | {Settings::NativeButton::Y, SDL_CONTROLLER_BUTTON_X}, | 956 | {Settings::NativeButton::Y, invert ? SDL_CONTROLLER_BUTTON_X : SDL_CONTROLLER_BUTTON_Y}, |
| 943 | {Settings::NativeButton::LStick, SDL_CONTROLLER_BUTTON_LEFTSTICK}, | 957 | {Settings::NativeButton::LStick, SDL_CONTROLLER_BUTTON_LEFTSTICK}, |
| 944 | {Settings::NativeButton::RStick, SDL_CONTROLLER_BUTTON_RIGHTSTICK}, | 958 | {Settings::NativeButton::RStick, SDL_CONTROLLER_BUTTON_RIGHTSTICK}, |
| 945 | {Settings::NativeButton::L, SDL_CONTROLLER_BUTTON_LEFTSHOULDER}, | 959 | {Settings::NativeButton::L, SDL_CONTROLLER_BUTTON_LEFTSHOULDER}, |
diff --git a/src/input_common/sdl/sdl_impl.h b/src/input_common/sdl/sdl_impl.h index 08044b00d..8b7363f56 100644 --- a/src/input_common/sdl/sdl_impl.h +++ b/src/input_common/sdl/sdl_impl.h | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | #include "input_common/sdl/sdl.h" | 14 | #include "input_common/sdl/sdl.h" |
| 15 | 15 | ||
| 16 | union SDL_Event; | 16 | union SDL_Event; |
| 17 | using SDL_GameController = struct _SDL_GameController; | ||
| 17 | using SDL_Joystick = struct _SDL_Joystick; | 18 | using SDL_Joystick = struct _SDL_Joystick; |
| 18 | using SDL_JoystickID = s32; | 19 | using SDL_JoystickID = s32; |
| 19 | 20 | ||
| @@ -64,6 +65,9 @@ private: | |||
| 64 | /// Needs to be called before SDL_QuitSubSystem. | 65 | /// Needs to be called before SDL_QuitSubSystem. |
| 65 | void CloseJoysticks(); | 66 | void CloseJoysticks(); |
| 66 | 67 | ||
| 68 | /// Returns a custom name for specific controllers because the default name is not correct | ||
| 69 | std::string GetControllerName(SDL_GameController* controller) const; | ||
| 70 | |||
| 67 | // Set to true if SDL supports game controller subsystem | 71 | // Set to true if SDL supports game controller subsystem |
| 68 | bool has_gamecontroller = false; | 72 | bool has_gamecontroller = false; |
| 69 | 73 | ||
diff --git a/src/input_common/touch_from_button.cpp b/src/input_common/touch_from_button.cpp index ffbe4f2ed..e94ba197b 100644 --- a/src/input_common/touch_from_button.cpp +++ b/src/input_common/touch_from_button.cpp | |||
| @@ -2,8 +2,8 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include "common/settings.h" | ||
| 5 | #include "core/frontend/framebuffer_layout.h" | 6 | #include "core/frontend/framebuffer_layout.h" |
| 6 | #include "core/settings.h" | ||
| 7 | #include "input_common/touch_from_button.h" | 7 | #include "input_common/touch_from_button.h" |
| 8 | 8 | ||
| 9 | namespace InputCommon { | 9 | namespace InputCommon { |
diff --git a/src/input_common/udp/client.cpp b/src/input_common/udp/client.cpp index df73f9ff7..8a38a380d 100644 --- a/src/input_common/udp/client.cpp +++ b/src/input_common/udp/client.cpp | |||
| @@ -9,7 +9,7 @@ | |||
| 9 | #include <thread> | 9 | #include <thread> |
| 10 | #include <boost/asio.hpp> | 10 | #include <boost/asio.hpp> |
| 11 | #include "common/logging/log.h" | 11 | #include "common/logging/log.h" |
| 12 | #include "core/settings.h" | 12 | #include "common/settings.h" |
| 13 | #include "input_common/udp/client.h" | 13 | #include "input_common/udp/client.h" |
| 14 | #include "input_common/udp/protocol.h" | 14 | #include "input_common/udp/protocol.h" |
| 15 | 15 | ||
| @@ -27,11 +27,9 @@ class Socket { | |||
| 27 | public: | 27 | public: |
| 28 | using clock = std::chrono::system_clock; | 28 | using clock = std::chrono::system_clock; |
| 29 | 29 | ||
| 30 | explicit Socket(const std::string& host, u16 port, std::size_t pad_index_, | 30 | explicit Socket(const std::string& host, u16 port, SocketCallback callback_) |
| 31 | SocketCallback callback_) | ||
| 32 | : callback(std::move(callback_)), timer(io_service), | 31 | : callback(std::move(callback_)), timer(io_service), |
| 33 | socket(io_service, udp::endpoint(udp::v4(), 0)), client_id(GenerateRandomClientId()), | 32 | socket(io_service, udp::endpoint(udp::v4(), 0)), client_id(GenerateRandomClientId()) { |
| 34 | pad_index(pad_index_) { | ||
| 35 | boost::system::error_code ec{}; | 33 | boost::system::error_code ec{}; |
| 36 | auto ipv4 = boost::asio::ip::make_address_v4(host, ec); | 34 | auto ipv4 = boost::asio::ip::make_address_v4(host, ec); |
| 37 | if (ec.value() != boost::system::errc::success) { | 35 | if (ec.value() != boost::system::errc::success) { |
| @@ -99,15 +97,15 @@ private: | |||
| 99 | void HandleSend(const boost::system::error_code&) { | 97 | void HandleSend(const boost::system::error_code&) { |
| 100 | boost::system::error_code _ignored{}; | 98 | boost::system::error_code _ignored{}; |
| 101 | // Send a request for getting port info for the pad | 99 | // Send a request for getting port info for the pad |
| 102 | const Request::PortInfo port_info{1, {static_cast<u8>(pad_index), 0, 0, 0}}; | 100 | const Request::PortInfo port_info{4, {0, 1, 2, 3}}; |
| 103 | const auto port_message = Request::Create(port_info, client_id); | 101 | const auto port_message = Request::Create(port_info, client_id); |
| 104 | std::memcpy(&send_buffer1, &port_message, PORT_INFO_SIZE); | 102 | std::memcpy(&send_buffer1, &port_message, PORT_INFO_SIZE); |
| 105 | socket.send_to(boost::asio::buffer(send_buffer1), send_endpoint, {}, _ignored); | 103 | socket.send_to(boost::asio::buffer(send_buffer1), send_endpoint, {}, _ignored); |
| 106 | 104 | ||
| 107 | // Send a request for getting pad data for the pad | 105 | // Send a request for getting pad data for the pad |
| 108 | const Request::PadData pad_data{ | 106 | const Request::PadData pad_data{ |
| 109 | Request::PadData::Flags::Id, | 107 | Request::PadData::Flags::AllPorts, |
| 110 | static_cast<u8>(pad_index), | 108 | 0, |
| 111 | EMPTY_MAC_ADDRESS, | 109 | EMPTY_MAC_ADDRESS, |
| 112 | }; | 110 | }; |
| 113 | const auto pad_message = Request::Create(pad_data, client_id); | 111 | const auto pad_message = Request::Create(pad_data, client_id); |
| @@ -122,7 +120,6 @@ private: | |||
| 122 | udp::socket socket; | 120 | udp::socket socket; |
| 123 | 121 | ||
| 124 | const u32 client_id; | 122 | const u32 client_id; |
| 125 | std::size_t pad_index{}; | ||
| 126 | 123 | ||
| 127 | static constexpr std::size_t PORT_INFO_SIZE = sizeof(Message<Request::PortInfo>); | 124 | static constexpr std::size_t PORT_INFO_SIZE = sizeof(Message<Request::PortInfo>); |
| 128 | static constexpr std::size_t PAD_DATA_SIZE = sizeof(Message<Request::PadData>); | 125 | static constexpr std::size_t PAD_DATA_SIZE = sizeof(Message<Request::PadData>); |
| @@ -150,34 +147,32 @@ Client::~Client() { | |||
| 150 | Reset(); | 147 | Reset(); |
| 151 | } | 148 | } |
| 152 | 149 | ||
| 153 | Client::ClientData::ClientData() = default; | 150 | Client::ClientConnection::ClientConnection() = default; |
| 154 | 151 | ||
| 155 | Client::ClientData::~ClientData() = default; | 152 | Client::ClientConnection::~ClientConnection() = default; |
| 156 | 153 | ||
| 157 | std::vector<Common::ParamPackage> Client::GetInputDevices() const { | 154 | std::vector<Common::ParamPackage> Client::GetInputDevices() const { |
| 158 | std::vector<Common::ParamPackage> devices; | 155 | std::vector<Common::ParamPackage> devices; |
| 159 | for (std::size_t client = 0; client < clients.size(); client++) { | 156 | for (std::size_t pad = 0; pad < pads.size(); pad++) { |
| 160 | if (!DeviceConnected(client)) { | 157 | if (!DeviceConnected(pad)) { |
| 161 | continue; | 158 | continue; |
| 162 | } | 159 | } |
| 163 | std::string name = fmt::format("UDP Controller {}", client); | 160 | std::string name = fmt::format("UDP Controller {}", pad); |
| 164 | devices.emplace_back(Common::ParamPackage{ | 161 | devices.emplace_back(Common::ParamPackage{ |
| 165 | {"class", "cemuhookudp"}, | 162 | {"class", "cemuhookudp"}, |
| 166 | {"display", std::move(name)}, | 163 | {"display", std::move(name)}, |
| 167 | {"port", std::to_string(client)}, | 164 | {"port", std::to_string(pad)}, |
| 168 | }); | 165 | }); |
| 169 | } | 166 | } |
| 170 | return devices; | 167 | return devices; |
| 171 | } | 168 | } |
| 172 | 169 | ||
| 173 | bool Client::DeviceConnected(std::size_t client) const { | 170 | bool Client::DeviceConnected(std::size_t pad) const { |
| 174 | // Use last timestamp to detect if the socket has stopped sending data | 171 | // Use last timestamp to detect if the socket has stopped sending data |
| 175 | const auto now = std::chrono::steady_clock::now(); | 172 | const auto now = std::chrono::steady_clock::now(); |
| 176 | const auto time_difference = | 173 | const auto time_difference = static_cast<u64>( |
| 177 | static_cast<u64>(std::chrono::duration_cast<std::chrono::milliseconds>( | 174 | std::chrono::duration_cast<std::chrono::milliseconds>(now - pads[pad].last_update).count()); |
| 178 | now - clients[client].last_motion_update) | 175 | return time_difference < 1000 && pads[pad].connected; |
| 179 | .count()); | ||
| 180 | return time_difference < 1000 && clients[client].active == 1; | ||
| 181 | } | 176 | } |
| 182 | 177 | ||
| 183 | void Client::ReloadSockets() { | 178 | void Client::ReloadSockets() { |
| @@ -202,25 +197,21 @@ void Client::ReloadSockets() { | |||
| 202 | continue; | 197 | continue; |
| 203 | } | 198 | } |
| 204 | 199 | ||
| 205 | for (std::size_t pad = 0; pad < 4; ++pad) { | 200 | const std::size_t client_number = GetClientNumber(udp_input_address, udp_input_port); |
| 206 | const std::size_t client_number = | 201 | if (client_number != MAX_UDP_CLIENTS) { |
| 207 | GetClientNumber(udp_input_address, udp_input_port, pad); | 202 | LOG_ERROR(Input, "Duplicated UDP servers found"); |
| 208 | if (client_number != MAX_UDP_CLIENTS) { | 203 | continue; |
| 209 | LOG_ERROR(Input, "Duplicated UDP servers found"); | ||
| 210 | continue; | ||
| 211 | } | ||
| 212 | StartCommunication(client++, udp_input_address, udp_input_port, pad); | ||
| 213 | } | 204 | } |
| 205 | StartCommunication(client++, udp_input_address, udp_input_port); | ||
| 214 | } | 206 | } |
| 215 | } | 207 | } |
| 216 | 208 | ||
| 217 | std::size_t Client::GetClientNumber(std::string_view host, u16 port, std::size_t pad) const { | 209 | std::size_t Client::GetClientNumber(std::string_view host, u16 port) const { |
| 218 | for (std::size_t client = 0; client < clients.size(); client++) { | 210 | for (std::size_t client = 0; client < clients.size(); client++) { |
| 219 | if (clients[client].active == -1) { | 211 | if (clients[client].active == -1) { |
| 220 | continue; | 212 | continue; |
| 221 | } | 213 | } |
| 222 | if (clients[client].host == host && clients[client].port == port && | 214 | if (clients[client].host == host && clients[client].port == port) { |
| 223 | clients[client].pad_index == pad) { | ||
| 224 | return client; | 215 | return client; |
| 225 | } | 216 | } |
| 226 | } | 217 | } |
| @@ -236,69 +227,75 @@ void Client::OnPortInfo([[maybe_unused]] Response::PortInfo data) { | |||
| 236 | } | 227 | } |
| 237 | 228 | ||
| 238 | void Client::OnPadData(Response::PadData data, std::size_t client) { | 229 | void Client::OnPadData(Response::PadData data, std::size_t client) { |
| 239 | // Accept packets only for the correct pad | 230 | const std::size_t pad_index = (client * PADS_PER_CLIENT) + data.info.id; |
| 240 | if (static_cast<u8>(clients[client].pad_index) != data.info.id) { | 231 | |
| 232 | if (pad_index >= pads.size()) { | ||
| 233 | LOG_ERROR(Input, "Invalid pad id {}", data.info.id); | ||
| 241 | return; | 234 | return; |
| 242 | } | 235 | } |
| 243 | 236 | ||
| 244 | LOG_TRACE(Input, "PadData packet received"); | 237 | LOG_TRACE(Input, "PadData packet received"); |
| 245 | if (data.packet_counter == clients[client].packet_sequence) { | 238 | if (data.packet_counter == pads[pad_index].packet_sequence) { |
| 246 | LOG_WARNING( | 239 | LOG_WARNING( |
| 247 | Input, | 240 | Input, |
| 248 | "PadData packet dropped because its stale info. Current count: {} Packet count: {}", | 241 | "PadData packet dropped because its stale info. Current count: {} Packet count: {}", |
| 249 | clients[client].packet_sequence, data.packet_counter); | 242 | pads[pad_index].packet_sequence, data.packet_counter); |
| 243 | pads[pad_index].connected = false; | ||
| 250 | return; | 244 | return; |
| 251 | } | 245 | } |
| 252 | clients[client].active = static_cast<s8>(data.info.is_pad_active); | 246 | |
| 253 | clients[client].packet_sequence = data.packet_counter; | 247 | clients[client].active = 1; |
| 248 | pads[pad_index].connected = true; | ||
| 249 | pads[pad_index].packet_sequence = data.packet_counter; | ||
| 250 | |||
| 254 | const auto now = std::chrono::steady_clock::now(); | 251 | const auto now = std::chrono::steady_clock::now(); |
| 255 | const auto time_difference = | 252 | const auto time_difference = static_cast<u64>( |
| 256 | static_cast<u64>(std::chrono::duration_cast<std::chrono::microseconds>( | 253 | std::chrono::duration_cast<std::chrono::microseconds>(now - pads[pad_index].last_update) |
| 257 | now - clients[client].last_motion_update) | 254 | .count()); |
| 258 | .count()); | 255 | pads[pad_index].last_update = now; |
| 259 | clients[client].last_motion_update = now; | 256 | |
| 260 | const Common::Vec3f raw_gyroscope = {data.gyro.pitch, data.gyro.roll, -data.gyro.yaw}; | 257 | const Common::Vec3f raw_gyroscope = {data.gyro.pitch, data.gyro.roll, -data.gyro.yaw}; |
| 261 | clients[client].motion.SetAcceleration({data.accel.x, -data.accel.z, data.accel.y}); | 258 | pads[pad_index].motion.SetAcceleration({data.accel.x, -data.accel.z, data.accel.y}); |
| 262 | // Gyroscope values are not it the correct scale from better joy. | 259 | // Gyroscope values are not it the correct scale from better joy. |
| 263 | // Dividing by 312 allows us to make one full turn = 1 turn | 260 | // Dividing by 312 allows us to make one full turn = 1 turn |
| 264 | // This must be a configurable valued called sensitivity | 261 | // This must be a configurable valued called sensitivity |
| 265 | clients[client].motion.SetGyroscope(raw_gyroscope / 312.0f); | 262 | pads[pad_index].motion.SetGyroscope(raw_gyroscope / 312.0f); |
| 266 | clients[client].motion.UpdateRotation(time_difference); | 263 | pads[pad_index].motion.UpdateRotation(time_difference); |
| 267 | clients[client].motion.UpdateOrientation(time_difference); | 264 | pads[pad_index].motion.UpdateOrientation(time_difference); |
| 268 | 265 | ||
| 269 | { | 266 | { |
| 270 | std::lock_guard guard(clients[client].status.update_mutex); | 267 | std::lock_guard guard(pads[pad_index].status.update_mutex); |
| 271 | clients[client].status.motion_status = clients[client].motion.GetMotion(); | 268 | pads[pad_index].status.motion_status = pads[pad_index].motion.GetMotion(); |
| 272 | 269 | ||
| 273 | for (std::size_t id = 0; id < data.touch.size(); ++id) { | 270 | for (std::size_t id = 0; id < data.touch.size(); ++id) { |
| 274 | UpdateTouchInput(data.touch[id], client, id); | 271 | UpdateTouchInput(data.touch[id], client, id); |
| 275 | } | 272 | } |
| 276 | 273 | ||
| 277 | if (configuring) { | 274 | if (configuring) { |
| 278 | const Common::Vec3f gyroscope = clients[client].motion.GetGyroscope(); | 275 | const Common::Vec3f gyroscope = pads[pad_index].motion.GetGyroscope(); |
| 279 | const Common::Vec3f accelerometer = clients[client].motion.GetAcceleration(); | 276 | const Common::Vec3f accelerometer = pads[pad_index].motion.GetAcceleration(); |
| 280 | UpdateYuzuSettings(client, accelerometer, gyroscope); | 277 | UpdateYuzuSettings(client, data.info.id, accelerometer, gyroscope); |
| 281 | } | 278 | } |
| 282 | } | 279 | } |
| 283 | } | 280 | } |
| 284 | 281 | ||
| 285 | void Client::StartCommunication(std::size_t client, const std::string& host, u16 port, | 282 | void Client::StartCommunication(std::size_t client, const std::string& host, u16 port) { |
| 286 | std::size_t pad_index) { | ||
| 287 | SocketCallback callback{[this](Response::Version version) { OnVersion(version); }, | 283 | SocketCallback callback{[this](Response::Version version) { OnVersion(version); }, |
| 288 | [this](Response::PortInfo info) { OnPortInfo(info); }, | 284 | [this](Response::PortInfo info) { OnPortInfo(info); }, |
| 289 | [this, client](Response::PadData data) { OnPadData(data, client); }}; | 285 | [this, client](Response::PadData data) { OnPadData(data, client); }}; |
| 290 | LOG_INFO(Input, "Starting communication with UDP input server on {}:{}:{}", host, port, | 286 | LOG_INFO(Input, "Starting communication with UDP input server on {}:{}", host, port); |
| 291 | pad_index); | ||
| 292 | clients[client].host = host; | 287 | clients[client].host = host; |
| 293 | clients[client].port = port; | 288 | clients[client].port = port; |
| 294 | clients[client].pad_index = pad_index; | ||
| 295 | clients[client].active = 0; | 289 | clients[client].active = 0; |
| 296 | clients[client].socket = std::make_unique<Socket>(host, port, pad_index, callback); | 290 | clients[client].socket = std::make_unique<Socket>(host, port, callback); |
| 297 | clients[client].thread = std::thread{SocketLoop, clients[client].socket.get()}; | 291 | clients[client].thread = std::thread{SocketLoop, clients[client].socket.get()}; |
| 292 | |||
| 298 | // Set motion parameters | 293 | // Set motion parameters |
| 299 | // SetGyroThreshold value should be dependent on GyroscopeZeroDriftMode | 294 | // SetGyroThreshold value should be dependent on GyroscopeZeroDriftMode |
| 300 | // Real HW values are unknown, 0.0001 is an approximate to Standard | 295 | // Real HW values are unknown, 0.0001 is an approximate to Standard |
| 301 | clients[client].motion.SetGyroThreshold(0.0001f); | 296 | for (std::size_t pad = 0; pad < PADS_PER_CLIENT; pad++) { |
| 297 | pads[client * PADS_PER_CLIENT + pad].motion.SetGyroThreshold(0.0001f); | ||
| 298 | } | ||
| 302 | } | 299 | } |
| 303 | 300 | ||
| 304 | void Client::Reset() { | 301 | void Client::Reset() { |
| @@ -311,8 +308,8 @@ void Client::Reset() { | |||
| 311 | } | 308 | } |
| 312 | } | 309 | } |
| 313 | 310 | ||
| 314 | void Client::UpdateYuzuSettings(std::size_t client, const Common::Vec3<float>& acc, | 311 | void Client::UpdateYuzuSettings(std::size_t client, std::size_t pad_index, |
| 315 | const Common::Vec3<float>& gyro) { | 312 | const Common::Vec3<float>& acc, const Common::Vec3<float>& gyro) { |
| 316 | if (gyro.Length() > 0.2f) { | 313 | if (gyro.Length() > 0.2f) { |
| 317 | LOG_DEBUG(Input, "UDP Controller {}: gyro=({}, {}, {}), accel=({}, {}, {})", client, | 314 | LOG_DEBUG(Input, "UDP Controller {}: gyro=({}, {}, {}), accel=({}, {}, {})", client, |
| 318 | gyro[0], gyro[1], gyro[2], acc[0], acc[1], acc[2]); | 315 | gyro[0], gyro[1], gyro[2], acc[0], acc[1], acc[2]); |
| @@ -320,7 +317,7 @@ void Client::UpdateYuzuSettings(std::size_t client, const Common::Vec3<float>& a | |||
| 320 | UDPPadStatus pad{ | 317 | UDPPadStatus pad{ |
| 321 | .host = clients[client].host, | 318 | .host = clients[client].host, |
| 322 | .port = clients[client].port, | 319 | .port = clients[client].port, |
| 323 | .pad_index = clients[client].pad_index, | 320 | .pad_index = pad_index, |
| 324 | }; | 321 | }; |
| 325 | for (std::size_t i = 0; i < 3; ++i) { | 322 | for (std::size_t i = 0; i < 3; ++i) { |
| 326 | if (gyro[i] > 5.0f || gyro[i] < -5.0f) { | 323 | if (gyro[i] > 5.0f || gyro[i] < -5.0f) { |
| @@ -391,19 +388,19 @@ void Client::EndConfiguration() { | |||
| 391 | } | 388 | } |
| 392 | 389 | ||
| 393 | DeviceStatus& Client::GetPadState(const std::string& host, u16 port, std::size_t pad) { | 390 | DeviceStatus& Client::GetPadState(const std::string& host, u16 port, std::size_t pad) { |
| 394 | const std::size_t client_number = GetClientNumber(host, port, pad); | 391 | const std::size_t client_number = GetClientNumber(host, port); |
| 395 | if (client_number == MAX_UDP_CLIENTS) { | 392 | if (client_number == MAX_UDP_CLIENTS || pad >= PADS_PER_CLIENT) { |
| 396 | return clients[0].status; | 393 | return pads[0].status; |
| 397 | } | 394 | } |
| 398 | return clients[client_number].status; | 395 | return pads[(client_number * PADS_PER_CLIENT) + pad].status; |
| 399 | } | 396 | } |
| 400 | 397 | ||
| 401 | const DeviceStatus& Client::GetPadState(const std::string& host, u16 port, std::size_t pad) const { | 398 | const DeviceStatus& Client::GetPadState(const std::string& host, u16 port, std::size_t pad) const { |
| 402 | const std::size_t client_number = GetClientNumber(host, port, pad); | 399 | const std::size_t client_number = GetClientNumber(host, port); |
| 403 | if (client_number == MAX_UDP_CLIENTS) { | 400 | if (client_number == MAX_UDP_CLIENTS || pad >= PADS_PER_CLIENT) { |
| 404 | return clients[0].status; | 401 | return pads[0].status; |
| 405 | } | 402 | } |
| 406 | return clients[client_number].status; | 403 | return pads[(client_number * PADS_PER_CLIENT) + pad].status; |
| 407 | } | 404 | } |
| 408 | 405 | ||
| 409 | Input::TouchStatus& Client::GetTouchState() { | 406 | Input::TouchStatus& Client::GetTouchState() { |
| @@ -422,7 +419,7 @@ const Common::SPSCQueue<UDPPadStatus>& Client::GetPadQueue() const { | |||
| 422 | return pad_queue; | 419 | return pad_queue; |
| 423 | } | 420 | } |
| 424 | 421 | ||
| 425 | void TestCommunication(const std::string& host, u16 port, std::size_t pad_index, | 422 | void TestCommunication(const std::string& host, u16 port, |
| 426 | const std::function<void()>& success_callback, | 423 | const std::function<void()>& success_callback, |
| 427 | const std::function<void()>& failure_callback) { | 424 | const std::function<void()>& failure_callback) { |
| 428 | std::thread([=] { | 425 | std::thread([=] { |
| @@ -432,9 +429,10 @@ void TestCommunication(const std::string& host, u16 port, std::size_t pad_index, | |||
| 432 | .port_info = [](Response::PortInfo) {}, | 429 | .port_info = [](Response::PortInfo) {}, |
| 433 | .pad_data = [&](Response::PadData) { success_event.Set(); }, | 430 | .pad_data = [&](Response::PadData) { success_event.Set(); }, |
| 434 | }; | 431 | }; |
| 435 | Socket socket{host, port, pad_index, std::move(callback)}; | 432 | Socket socket{host, port, std::move(callback)}; |
| 436 | std::thread worker_thread{SocketLoop, &socket}; | 433 | std::thread worker_thread{SocketLoop, &socket}; |
| 437 | const bool result = success_event.WaitFor(std::chrono::seconds(5)); | 434 | const bool result = |
| 435 | success_event.WaitUntil(std::chrono::steady_clock::now() + std::chrono::seconds(10)); | ||
| 438 | socket.Stop(); | 436 | socket.Stop(); |
| 439 | worker_thread.join(); | 437 | worker_thread.join(); |
| 440 | if (result) { | 438 | if (result) { |
| @@ -446,8 +444,7 @@ void TestCommunication(const std::string& host, u16 port, std::size_t pad_index, | |||
| 446 | } | 444 | } |
| 447 | 445 | ||
| 448 | CalibrationConfigurationJob::CalibrationConfigurationJob( | 446 | CalibrationConfigurationJob::CalibrationConfigurationJob( |
| 449 | const std::string& host, u16 port, std::size_t pad_index, | 447 | const std::string& host, u16 port, std::function<void(Status)> status_callback, |
| 450 | std::function<void(Status)> status_callback, | ||
| 451 | std::function<void(u16, u16, u16, u16)> data_callback) { | 448 | std::function<void(u16, u16, u16, u16)> data_callback) { |
| 452 | 449 | ||
| 453 | std::thread([=, this] { | 450 | std::thread([=, this] { |
| @@ -491,7 +488,7 @@ CalibrationConfigurationJob::CalibrationConfigurationJob( | |||
| 491 | complete_event.Set(); | 488 | complete_event.Set(); |
| 492 | } | 489 | } |
| 493 | }}; | 490 | }}; |
| 494 | Socket socket{host, port, pad_index, std::move(callback)}; | 491 | Socket socket{host, port, std::move(callback)}; |
| 495 | std::thread worker_thread{SocketLoop, &socket}; | 492 | std::thread worker_thread{SocketLoop, &socket}; |
| 496 | complete_event.Wait(); | 493 | complete_event.Wait(); |
| 497 | socket.Stop(); | 494 | socket.Stop(); |
diff --git a/src/input_common/udp/client.h b/src/input_common/udp/client.h index e9e438e88..a11ea3068 100644 --- a/src/input_common/udp/client.h +++ b/src/input_common/udp/client.h | |||
| @@ -84,7 +84,7 @@ public: | |||
| 84 | 84 | ||
| 85 | std::vector<Common::ParamPackage> GetInputDevices() const; | 85 | std::vector<Common::ParamPackage> GetInputDevices() const; |
| 86 | 86 | ||
| 87 | bool DeviceConnected(std::size_t client) const; | 87 | bool DeviceConnected(std::size_t pad) const; |
| 88 | void ReloadSockets(); | 88 | void ReloadSockets(); |
| 89 | 89 | ||
| 90 | Common::SPSCQueue<UDPPadStatus>& GetPadQueue(); | 90 | Common::SPSCQueue<UDPPadStatus>& GetPadQueue(); |
| @@ -97,38 +97,40 @@ public: | |||
| 97 | const Input::TouchStatus& GetTouchState() const; | 97 | const Input::TouchStatus& GetTouchState() const; |
| 98 | 98 | ||
| 99 | private: | 99 | private: |
| 100 | struct ClientData { | 100 | struct PadData { |
| 101 | ClientData(); | ||
| 102 | ~ClientData(); | ||
| 103 | |||
| 104 | std::string host{"127.0.0.1"}; | ||
| 105 | u16 port{26760}; | ||
| 106 | std::size_t pad_index{}; | 101 | std::size_t pad_index{}; |
| 107 | std::unique_ptr<Socket> socket; | 102 | bool connected{}; |
| 108 | DeviceStatus status; | 103 | DeviceStatus status; |
| 109 | std::thread thread; | ||
| 110 | u64 packet_sequence{}; | 104 | u64 packet_sequence{}; |
| 111 | s8 active{-1}; | ||
| 112 | 105 | ||
| 113 | // Realtime values | 106 | // Realtime values |
| 114 | // motion is initalized with PID values for drift correction on joycons | 107 | // motion is initalized with PID values for drift correction on joycons |
| 115 | InputCommon::MotionInput motion{0.3f, 0.005f, 0.0f}; | 108 | InputCommon::MotionInput motion{0.3f, 0.005f, 0.0f}; |
| 116 | std::chrono::time_point<std::chrono::steady_clock> last_motion_update; | 109 | std::chrono::time_point<std::chrono::steady_clock> last_update; |
| 110 | }; | ||
| 111 | |||
| 112 | struct ClientConnection { | ||
| 113 | ClientConnection(); | ||
| 114 | ~ClientConnection(); | ||
| 115 | std::string host{"127.0.0.1"}; | ||
| 116 | u16 port{26760}; | ||
| 117 | s8 active{-1}; | ||
| 118 | std::unique_ptr<Socket> socket; | ||
| 119 | std::thread thread; | ||
| 117 | }; | 120 | }; |
| 118 | 121 | ||
| 119 | // For shutting down, clear all data, join all threads, release usb | 122 | // For shutting down, clear all data, join all threads, release usb |
| 120 | void Reset(); | 123 | void Reset(); |
| 121 | 124 | ||
| 122 | // Translates configuration to client number | 125 | // Translates configuration to client number |
| 123 | std::size_t GetClientNumber(std::string_view host, u16 port, std::size_t pad) const; | 126 | std::size_t GetClientNumber(std::string_view host, u16 port) const; |
| 124 | 127 | ||
| 125 | void OnVersion(Response::Version); | 128 | void OnVersion(Response::Version); |
| 126 | void OnPortInfo(Response::PortInfo); | 129 | void OnPortInfo(Response::PortInfo); |
| 127 | void OnPadData(Response::PadData, std::size_t client); | 130 | void OnPadData(Response::PadData, std::size_t client); |
| 128 | void StartCommunication(std::size_t client, const std::string& host, u16 port, | 131 | void StartCommunication(std::size_t client, const std::string& host, u16 port); |
| 129 | std::size_t pad_index); | 132 | void UpdateYuzuSettings(std::size_t client, std::size_t pad_index, |
| 130 | void UpdateYuzuSettings(std::size_t client, const Common::Vec3<float>& acc, | 133 | const Common::Vec3<float>& acc, const Common::Vec3<float>& gyro); |
| 131 | const Common::Vec3<float>& gyro); | ||
| 132 | 134 | ||
| 133 | // Returns an unused finger id, if there is no fingers available std::nullopt will be | 135 | // Returns an unused finger id, if there is no fingers available std::nullopt will be |
| 134 | // returned | 136 | // returned |
| @@ -140,10 +142,12 @@ private: | |||
| 140 | bool configuring = false; | 142 | bool configuring = false; |
| 141 | 143 | ||
| 142 | // Allocate clients for 8 udp servers | 144 | // Allocate clients for 8 udp servers |
| 143 | static constexpr std::size_t MAX_UDP_CLIENTS = 4 * 8; | 145 | static constexpr std::size_t MAX_UDP_CLIENTS = 8; |
| 146 | static constexpr std::size_t PADS_PER_CLIENT = 4; | ||
| 144 | // Each client can have up 2 touch inputs | 147 | // Each client can have up 2 touch inputs |
| 145 | static constexpr std::size_t MAX_TOUCH_FINGERS = MAX_UDP_CLIENTS * 2; | 148 | static constexpr std::size_t MAX_TOUCH_FINGERS = MAX_UDP_CLIENTS * 2; |
| 146 | std::array<ClientData, MAX_UDP_CLIENTS> clients{}; | 149 | std::array<PadData, MAX_UDP_CLIENTS * PADS_PER_CLIENT> pads{}; |
| 150 | std::array<ClientConnection, MAX_UDP_CLIENTS> clients{}; | ||
| 147 | Common::SPSCQueue<UDPPadStatus> pad_queue{}; | 151 | Common::SPSCQueue<UDPPadStatus> pad_queue{}; |
| 148 | Input::TouchStatus touch_status{}; | 152 | Input::TouchStatus touch_status{}; |
| 149 | std::array<std::size_t, MAX_TOUCH_FINGERS> finger_id{}; | 153 | std::array<std::size_t, MAX_TOUCH_FINGERS> finger_id{}; |
| @@ -164,7 +168,7 @@ public: | |||
| 164 | * @param status_callback Callback for job status updates | 168 | * @param status_callback Callback for job status updates |
| 165 | * @param data_callback Called when calibration data is ready | 169 | * @param data_callback Called when calibration data is ready |
| 166 | */ | 170 | */ |
| 167 | explicit CalibrationConfigurationJob(const std::string& host, u16 port, std::size_t pad_index, | 171 | explicit CalibrationConfigurationJob(const std::string& host, u16 port, |
| 168 | std::function<void(Status)> status_callback, | 172 | std::function<void(Status)> status_callback, |
| 169 | std::function<void(u16, u16, u16, u16)> data_callback); | 173 | std::function<void(u16, u16, u16, u16)> data_callback); |
| 170 | ~CalibrationConfigurationJob(); | 174 | ~CalibrationConfigurationJob(); |
| @@ -174,7 +178,7 @@ private: | |||
| 174 | Common::Event complete_event; | 178 | Common::Event complete_event; |
| 175 | }; | 179 | }; |
| 176 | 180 | ||
| 177 | void TestCommunication(const std::string& host, u16 port, std::size_t pad_index, | 181 | void TestCommunication(const std::string& host, u16 port, |
| 178 | const std::function<void()>& success_callback, | 182 | const std::function<void()>& success_callback, |
| 179 | const std::function<void()>& failure_callback); | 183 | const std::function<void()>& failure_callback); |
| 180 | 184 | ||
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index 9b931976a..47190c464 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt | |||
| @@ -236,7 +236,6 @@ add_library(video_core STATIC | |||
| 236 | texture_cache/types.h | 236 | texture_cache/types.h |
| 237 | texture_cache/util.cpp | 237 | texture_cache/util.cpp |
| 238 | texture_cache/util.h | 238 | texture_cache/util.h |
| 239 | textures/astc.cpp | ||
| 240 | textures/astc.h | 239 | textures/astc.h |
| 241 | textures/decoders.cpp | 240 | textures/decoders.cpp |
| 242 | textures/decoders.h | 241 | textures/decoders.h |
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index 4de1e37e5..32dcbd693 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h | |||
| @@ -20,8 +20,8 @@ | |||
| 20 | #include "common/div_ceil.h" | 20 | #include "common/div_ceil.h" |
| 21 | #include "common/microprofile.h" | 21 | #include "common/microprofile.h" |
| 22 | #include "common/scope_exit.h" | 22 | #include "common/scope_exit.h" |
| 23 | #include "common/settings.h" | ||
| 23 | #include "core/memory.h" | 24 | #include "core/memory.h" |
| 24 | #include "core/settings.h" | ||
| 25 | #include "video_core/buffer_cache/buffer_base.h" | 25 | #include "video_core/buffer_cache/buffer_base.h" |
| 26 | #include "video_core/delayed_destruction_ring.h" | 26 | #include "video_core/delayed_destruction_ring.h" |
| 27 | #include "video_core/dirty_flags.h" | 27 | #include "video_core/dirty_flags.h" |
diff --git a/src/video_core/command_classes/codecs/vp9.cpp b/src/video_core/command_classes/codecs/vp9.cpp index 59e586695..29bb31418 100644 --- a/src/video_core/command_classes/codecs/vp9.cpp +++ b/src/video_core/command_classes/codecs/vp9.cpp | |||
| @@ -2,8 +2,9 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <cstring> // for std::memcpy | 5 | #include <algorithm> // for std::copy |
| 6 | #include <numeric> | 6 | #include <numeric> |
| 7 | #include "common/assert.h" | ||
| 7 | #include "video_core/command_classes/codecs/vp9.h" | 8 | #include "video_core/command_classes/codecs/vp9.h" |
| 8 | #include "video_core/gpu.h" | 9 | #include "video_core/gpu.h" |
| 9 | #include "video_core/memory_manager.h" | 10 | #include "video_core/memory_manager.h" |
| @@ -362,7 +363,8 @@ Vp9PictureInfo VP9::GetVp9PictureInfo(const NvdecCommon::NvdecRegisters& state) | |||
| 362 | // surface_luma_offset[0:3] contains the address of the reference frame offsets in the following | 363 | // surface_luma_offset[0:3] contains the address of the reference frame offsets in the following |
| 363 | // order: last, golden, altref, current. It may be worthwhile to track the updates done here | 364 | // order: last, golden, altref, current. It may be worthwhile to track the updates done here |
| 364 | // to avoid buffering frame data needed for reference frame updating in the header composition. | 365 | // to avoid buffering frame data needed for reference frame updating in the header composition. |
| 365 | std::memcpy(vp9_info.frame_offsets.data(), state.surface_luma_offset.data(), 4 * sizeof(u64)); | 366 | std::copy(state.surface_luma_offset.begin(), state.surface_luma_offset.begin() + 4, |
| 367 | vp9_info.frame_offsets.begin()); | ||
| 366 | 368 | ||
| 367 | return vp9_info; | 369 | return vp9_info; |
| 368 | } | 370 | } |
| @@ -821,11 +823,11 @@ const std::vector<u8>& VP9::ComposeFrameHeader(const NvdecCommon::NvdecRegisters | |||
| 821 | 823 | ||
| 822 | // Write headers and frame to buffer | 824 | // Write headers and frame to buffer |
| 823 | frame.resize(uncompressed_header.size() + compressed_header.size() + bitstream.size()); | 825 | frame.resize(uncompressed_header.size() + compressed_header.size() + bitstream.size()); |
| 824 | std::memcpy(frame.data(), uncompressed_header.data(), uncompressed_header.size()); | 826 | std::copy(uncompressed_header.begin(), uncompressed_header.end(), frame.begin()); |
| 825 | std::memcpy(frame.data() + uncompressed_header.size(), compressed_header.data(), | 827 | std::copy(compressed_header.begin(), compressed_header.end(), |
| 826 | compressed_header.size()); | 828 | frame.begin() + uncompressed_header.size()); |
| 827 | std::memcpy(frame.data() + uncompressed_header.size() + compressed_header.size(), | 829 | std::copy(bitstream.begin(), bitstream.end(), |
| 828 | bitstream.data(), bitstream.size()); | 830 | frame.begin() + uncompressed_header.size() + compressed_header.size()); |
| 829 | 831 | ||
| 830 | // keep track of frame number | 832 | // keep track of frame number |
| 831 | current_frame_number++; | 833 | current_frame_number++; |
diff --git a/src/video_core/engines/engine_interface.h b/src/video_core/engines/engine_interface.h index 18a9db7e6..c7ffd68c5 100644 --- a/src/video_core/engines/engine_interface.h +++ b/src/video_core/engines/engine_interface.h | |||
| @@ -4,13 +4,14 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <type_traits> | ||
| 8 | #include "common/common_types.h" | 7 | #include "common/common_types.h" |
| 9 | 8 | ||
| 10 | namespace Tegra::Engines { | 9 | namespace Tegra::Engines { |
| 11 | 10 | ||
| 12 | class EngineInterface { | 11 | class EngineInterface { |
| 13 | public: | 12 | public: |
| 13 | virtual ~EngineInterface() = default; | ||
| 14 | |||
| 14 | /// Write the value to the register identified by method. | 15 | /// Write the value to the register identified by method. |
| 15 | virtual void CallMethod(u32 method, u32 method_argument, bool is_last_call) = 0; | 16 | virtual void CallMethod(u32 method, u32 method_argument, bool is_last_call) = 0; |
| 16 | 17 | ||
diff --git a/src/video_core/engines/fermi_2d.h b/src/video_core/engines/fermi_2d.h index c808a577d..a4170ffff 100644 --- a/src/video_core/engines/fermi_2d.h +++ b/src/video_core/engines/fermi_2d.h | |||
| @@ -35,7 +35,7 @@ namespace Tegra::Engines { | |||
| 35 | class Fermi2D final : public EngineInterface { | 35 | class Fermi2D final : public EngineInterface { |
| 36 | public: | 36 | public: |
| 37 | explicit Fermi2D(); | 37 | explicit Fermi2D(); |
| 38 | ~Fermi2D(); | 38 | ~Fermi2D() override; |
| 39 | 39 | ||
| 40 | /// Binds a rasterizer to this engine. | 40 | /// Binds a rasterizer to this engine. |
| 41 | void BindRasterizer(VideoCore::RasterizerInterface* rasterizer); | 41 | void BindRasterizer(VideoCore::RasterizerInterface* rasterizer); |
diff --git a/src/video_core/engines/kepler_memory.h b/src/video_core/engines/kepler_memory.h index 19808a5c6..0d8ea09a9 100644 --- a/src/video_core/engines/kepler_memory.h +++ b/src/video_core/engines/kepler_memory.h | |||
| @@ -36,7 +36,7 @@ namespace Tegra::Engines { | |||
| 36 | class KeplerMemory final : public EngineInterface { | 36 | class KeplerMemory final : public EngineInterface { |
| 37 | public: | 37 | public: |
| 38 | explicit KeplerMemory(Core::System& system_, MemoryManager& memory_manager); | 38 | explicit KeplerMemory(Core::System& system_, MemoryManager& memory_manager); |
| 39 | ~KeplerMemory(); | 39 | ~KeplerMemory() override; |
| 40 | 40 | ||
| 41 | /// Write the value to the register identified by method. | 41 | /// Write the value to the register identified by method. |
| 42 | void CallMethod(u32 method, u32 method_argument, bool is_last_call) override; | 42 | void CallMethod(u32 method, u32 method_argument, bool is_last_call) override; |
diff --git a/src/video_core/engines/maxwell_dma.cpp b/src/video_core/engines/maxwell_dma.cpp index a2f19559f..2ee980bab 100644 --- a/src/video_core/engines/maxwell_dma.cpp +++ b/src/video_core/engines/maxwell_dma.cpp | |||
| @@ -4,8 +4,8 @@ | |||
| 4 | 4 | ||
| 5 | #include "common/assert.h" | 5 | #include "common/assert.h" |
| 6 | #include "common/logging/log.h" | 6 | #include "common/logging/log.h" |
| 7 | #include "common/settings.h" | ||
| 7 | #include "core/core.h" | 8 | #include "core/core.h" |
| 8 | #include "core/settings.h" | ||
| 9 | #include "video_core/engines/maxwell_3d.h" | 9 | #include "video_core/engines/maxwell_3d.h" |
| 10 | #include "video_core/engines/maxwell_dma.h" | 10 | #include "video_core/engines/maxwell_dma.h" |
| 11 | #include "video_core/memory_manager.h" | 11 | #include "video_core/memory_manager.h" |
diff --git a/src/video_core/engines/maxwell_dma.h b/src/video_core/engines/maxwell_dma.h index 3c59eeb13..c77f02a22 100644 --- a/src/video_core/engines/maxwell_dma.h +++ b/src/video_core/engines/maxwell_dma.h | |||
| @@ -188,7 +188,7 @@ public: | |||
| 188 | static_assert(sizeof(RemapConst) == 12); | 188 | static_assert(sizeof(RemapConst) == 12); |
| 189 | 189 | ||
| 190 | explicit MaxwellDMA(Core::System& system_, MemoryManager& memory_manager_); | 190 | explicit MaxwellDMA(Core::System& system_, MemoryManager& memory_manager_); |
| 191 | ~MaxwellDMA(); | 191 | ~MaxwellDMA() override; |
| 192 | 192 | ||
| 193 | /// Write the value to the register identified by method. | 193 | /// Write the value to the register identified by method. |
| 194 | void CallMethod(u32 method, u32 method_argument, bool is_last_call) override; | 194 | void CallMethod(u32 method, u32 method_argument, bool is_last_call) override; |
diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp index 36c31fec2..7c42f1177 100644 --- a/src/video_core/gpu.cpp +++ b/src/video_core/gpu.cpp | |||
| @@ -6,13 +6,13 @@ | |||
| 6 | 6 | ||
| 7 | #include "common/assert.h" | 7 | #include "common/assert.h" |
| 8 | #include "common/microprofile.h" | 8 | #include "common/microprofile.h" |
| 9 | #include "common/settings.h" | ||
| 9 | #include "core/core.h" | 10 | #include "core/core.h" |
| 10 | #include "core/core_timing.h" | 11 | #include "core/core_timing.h" |
| 11 | #include "core/core_timing_util.h" | 12 | #include "core/core_timing_util.h" |
| 12 | #include "core/frontend/emu_window.h" | 13 | #include "core/frontend/emu_window.h" |
| 13 | #include "core/hardware_interrupt_manager.h" | 14 | #include "core/hardware_interrupt_manager.h" |
| 14 | #include "core/memory.h" | 15 | #include "core/memory.h" |
| 15 | #include "core/settings.h" | ||
| 16 | #include "video_core/engines/fermi_2d.h" | 16 | #include "video_core/engines/fermi_2d.h" |
| 17 | #include "video_core/engines/kepler_compute.h" | 17 | #include "video_core/engines/kepler_compute.h" |
| 18 | #include "video_core/engines/kepler_memory.h" | 18 | #include "video_core/engines/kepler_memory.h" |
| @@ -519,8 +519,8 @@ void GPU::TriggerCpuInterrupt(const u32 syncpoint_id, const u32 value) const { | |||
| 519 | interrupt_manager.GPUInterruptSyncpt(syncpoint_id, value); | 519 | interrupt_manager.GPUInterruptSyncpt(syncpoint_id, value); |
| 520 | } | 520 | } |
| 521 | 521 | ||
| 522 | void GPU::WaitIdle() const { | 522 | void GPU::ShutDown() { |
| 523 | gpu_thread.WaitIdle(); | 523 | gpu_thread.ShutDown(); |
| 524 | } | 524 | } |
| 525 | 525 | ||
| 526 | void GPU::OnCommandListEnd() { | 526 | void GPU::OnCommandListEnd() { |
diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h index d40982a54..b1960ea86 100644 --- a/src/video_core/gpu.h +++ b/src/video_core/gpu.h | |||
| @@ -219,8 +219,8 @@ public: | |||
| 219 | return *shader_notify; | 219 | return *shader_notify; |
| 220 | } | 220 | } |
| 221 | 221 | ||
| 222 | // Waits for the GPU to finish working | 222 | // Stops the GPU execution and waits for the GPU to finish working |
| 223 | void WaitIdle() const; | 223 | void ShutDown(); |
| 224 | 224 | ||
| 225 | /// Allows the CPU/NvFlinger to wait on the GPU before presenting a frame. | 225 | /// Allows the CPU/NvFlinger to wait on the GPU before presenting a frame. |
| 226 | void WaitFence(u32 syncpoint_id, u32 value); | 226 | void WaitFence(u32 syncpoint_id, u32 value); |
diff --git a/src/video_core/gpu_thread.cpp b/src/video_core/gpu_thread.cpp index 99353f15f..cd1fbb9bf 100644 --- a/src/video_core/gpu_thread.cpp +++ b/src/video_core/gpu_thread.cpp | |||
| @@ -5,10 +5,10 @@ | |||
| 5 | #include "common/assert.h" | 5 | #include "common/assert.h" |
| 6 | #include "common/microprofile.h" | 6 | #include "common/microprofile.h" |
| 7 | #include "common/scope_exit.h" | 7 | #include "common/scope_exit.h" |
| 8 | #include "common/settings.h" | ||
| 8 | #include "common/thread.h" | 9 | #include "common/thread.h" |
| 9 | #include "core/core.h" | 10 | #include "core/core.h" |
| 10 | #include "core/frontend/emu_window.h" | 11 | #include "core/frontend/emu_window.h" |
| 11 | #include "core/settings.h" | ||
| 12 | #include "video_core/dma_pusher.h" | 12 | #include "video_core/dma_pusher.h" |
| 13 | #include "video_core/gpu.h" | 13 | #include "video_core/gpu.h" |
| 14 | #include "video_core/gpu_thread.h" | 14 | #include "video_core/gpu_thread.h" |
| @@ -29,8 +29,7 @@ static void RunThread(Core::System& system, VideoCore::RendererBase& renderer, | |||
| 29 | system.RegisterHostThread(); | 29 | system.RegisterHostThread(); |
| 30 | 30 | ||
| 31 | // Wait for first GPU command before acquiring the window context | 31 | // Wait for first GPU command before acquiring the window context |
| 32 | while (state.queue.Empty()) | 32 | state.queue.Wait(); |
| 33 | ; | ||
| 34 | 33 | ||
| 35 | // If emulation was stopped during disk shader loading, abort before trying to acquire context | 34 | // If emulation was stopped during disk shader loading, abort before trying to acquire context |
| 36 | if (!state.is_running) { | 35 | if (!state.is_running) { |
| @@ -57,11 +56,17 @@ static void RunThread(Core::System& system, VideoCore::RendererBase& renderer, | |||
| 57 | } else if (const auto* invalidate = std::get_if<InvalidateRegionCommand>(&next.data)) { | 56 | } else if (const auto* invalidate = std::get_if<InvalidateRegionCommand>(&next.data)) { |
| 58 | rasterizer->OnCPUWrite(invalidate->addr, invalidate->size); | 57 | rasterizer->OnCPUWrite(invalidate->addr, invalidate->size); |
| 59 | } else if (std::holds_alternative<EndProcessingCommand>(next.data)) { | 58 | } else if (std::holds_alternative<EndProcessingCommand>(next.data)) { |
| 60 | return; | 59 | ASSERT(state.is_running == false); |
| 61 | } else { | 60 | } else { |
| 62 | UNREACHABLE(); | 61 | UNREACHABLE(); |
| 63 | } | 62 | } |
| 64 | state.signaled_fence.store(next.fence); | 63 | state.signaled_fence.store(next.fence); |
| 64 | if (next.block) { | ||
| 65 | // We have to lock the write_lock to ensure that the condition_variable wait not get a | ||
| 66 | // race between the check and the lock itself. | ||
| 67 | std::lock_guard lk(state.write_lock); | ||
| 68 | state.cv.notify_all(); | ||
| 69 | } | ||
| 65 | } | 70 | } |
| 66 | } | 71 | } |
| 67 | 72 | ||
| @@ -69,13 +74,7 @@ ThreadManager::ThreadManager(Core::System& system_, bool is_async_) | |||
| 69 | : system{system_}, is_async{is_async_} {} | 74 | : system{system_}, is_async{is_async_} {} |
| 70 | 75 | ||
| 71 | ThreadManager::~ThreadManager() { | 76 | ThreadManager::~ThreadManager() { |
| 72 | if (!thread.joinable()) { | 77 | ShutDown(); |
| 73 | return; | ||
| 74 | } | ||
| 75 | |||
| 76 | // Notify GPU thread that a shutdown is pending | ||
| 77 | PushCommand(EndProcessingCommand()); | ||
| 78 | thread.join(); | ||
| 79 | } | 78 | } |
| 80 | 79 | ||
| 81 | void ThreadManager::StartThread(VideoCore::RendererBase& renderer, | 80 | void ThreadManager::StartThread(VideoCore::RendererBase& renderer, |
| @@ -112,9 +111,8 @@ void ThreadManager::FlushRegion(VAddr addr, u64 size) { | |||
| 112 | case Settings::GPUAccuracy::Extreme: { | 111 | case Settings::GPUAccuracy::Extreme: { |
| 113 | auto& gpu = system.GPU(); | 112 | auto& gpu = system.GPU(); |
| 114 | u64 fence = gpu.RequestFlush(addr, size); | 113 | u64 fence = gpu.RequestFlush(addr, size); |
| 115 | PushCommand(GPUTickCommand()); | 114 | PushCommand(GPUTickCommand(), true); |
| 116 | while (fence > gpu.CurrentFlushRequestFence()) { | 115 | ASSERT(fence <= gpu.CurrentFlushRequestFence()); |
| 117 | } | ||
| 118 | break; | 116 | break; |
| 119 | } | 117 | } |
| 120 | default: | 118 | default: |
| @@ -131,23 +129,45 @@ void ThreadManager::FlushAndInvalidateRegion(VAddr addr, u64 size) { | |||
| 131 | rasterizer->OnCPUWrite(addr, size); | 129 | rasterizer->OnCPUWrite(addr, size); |
| 132 | } | 130 | } |
| 133 | 131 | ||
| 134 | void ThreadManager::WaitIdle() const { | 132 | void ThreadManager::ShutDown() { |
| 135 | while (state.last_fence > state.signaled_fence.load(std::memory_order_relaxed) && | 133 | if (!state.is_running) { |
| 136 | system.IsPoweredOn()) { | 134 | return; |
| 137 | } | 135 | } |
| 136 | |||
| 137 | { | ||
| 138 | std::lock_guard lk(state.write_lock); | ||
| 139 | state.is_running = false; | ||
| 140 | state.cv.notify_all(); | ||
| 141 | } | ||
| 142 | |||
| 143 | if (!thread.joinable()) { | ||
| 144 | return; | ||
| 145 | } | ||
| 146 | |||
| 147 | // Notify GPU thread that a shutdown is pending | ||
| 148 | PushCommand(EndProcessingCommand()); | ||
| 149 | thread.join(); | ||
| 138 | } | 150 | } |
| 139 | 151 | ||
| 140 | void ThreadManager::OnCommandListEnd() { | 152 | void ThreadManager::OnCommandListEnd() { |
| 141 | PushCommand(OnCommandListEndCommand()); | 153 | PushCommand(OnCommandListEndCommand()); |
| 142 | } | 154 | } |
| 143 | 155 | ||
| 144 | u64 ThreadManager::PushCommand(CommandData&& command_data) { | 156 | u64 ThreadManager::PushCommand(CommandData&& command_data, bool block) { |
| 145 | const u64 fence{++state.last_fence}; | ||
| 146 | state.queue.Push(CommandDataContainer(std::move(command_data), fence)); | ||
| 147 | |||
| 148 | if (!is_async) { | 157 | if (!is_async) { |
| 149 | // In synchronous GPU mode, block the caller until the command has executed | 158 | // In synchronous GPU mode, block the caller until the command has executed |
| 150 | WaitIdle(); | 159 | block = true; |
| 160 | } | ||
| 161 | |||
| 162 | std::unique_lock lk(state.write_lock); | ||
| 163 | const u64 fence{++state.last_fence}; | ||
| 164 | state.queue.Push(CommandDataContainer(std::move(command_data), fence, block)); | ||
| 165 | |||
| 166 | if (block) { | ||
| 167 | state.cv.wait(lk, [this, fence] { | ||
| 168 | return fence <= state.signaled_fence.load(std::memory_order_relaxed) || | ||
| 169 | !state.is_running; | ||
| 170 | }); | ||
| 151 | } | 171 | } |
| 152 | 172 | ||
| 153 | return fence; | 173 | return fence; |
diff --git a/src/video_core/gpu_thread.h b/src/video_core/gpu_thread.h index 18269e51c..11a648f38 100644 --- a/src/video_core/gpu_thread.h +++ b/src/video_core/gpu_thread.h | |||
| @@ -90,21 +90,24 @@ using CommandData = | |||
| 90 | struct CommandDataContainer { | 90 | struct CommandDataContainer { |
| 91 | CommandDataContainer() = default; | 91 | CommandDataContainer() = default; |
| 92 | 92 | ||
| 93 | explicit CommandDataContainer(CommandData&& data_, u64 next_fence_) | 93 | explicit CommandDataContainer(CommandData&& data_, u64 next_fence_, bool block_) |
| 94 | : data{std::move(data_)}, fence{next_fence_} {} | 94 | : data{std::move(data_)}, fence{next_fence_}, block(block_) {} |
| 95 | 95 | ||
| 96 | CommandData data; | 96 | CommandData data; |
| 97 | u64 fence{}; | 97 | u64 fence{}; |
| 98 | bool block{}; | ||
| 98 | }; | 99 | }; |
| 99 | 100 | ||
| 100 | /// Struct used to synchronize the GPU thread | 101 | /// Struct used to synchronize the GPU thread |
| 101 | struct SynchState final { | 102 | struct SynchState final { |
| 102 | std::atomic_bool is_running{true}; | 103 | std::atomic_bool is_running{true}; |
| 103 | 104 | ||
| 104 | using CommandQueue = Common::MPSCQueue<CommandDataContainer>; | 105 | using CommandQueue = Common::SPSCQueue<CommandDataContainer>; |
| 106 | std::mutex write_lock; | ||
| 105 | CommandQueue queue; | 107 | CommandQueue queue; |
| 106 | u64 last_fence{}; | 108 | u64 last_fence{}; |
| 107 | std::atomic<u64> signaled_fence{}; | 109 | std::atomic<u64> signaled_fence{}; |
| 110 | std::condition_variable cv; | ||
| 108 | }; | 111 | }; |
| 109 | 112 | ||
| 110 | /// Class used to manage the GPU thread | 113 | /// Class used to manage the GPU thread |
| @@ -132,14 +135,14 @@ public: | |||
| 132 | /// Notify rasterizer that any caches of the specified region should be flushed and invalidated | 135 | /// Notify rasterizer that any caches of the specified region should be flushed and invalidated |
| 133 | void FlushAndInvalidateRegion(VAddr addr, u64 size); | 136 | void FlushAndInvalidateRegion(VAddr addr, u64 size); |
| 134 | 137 | ||
| 135 | // Wait until the gpu thread is idle. | 138 | // Stops the GPU execution and waits for the GPU to finish working |
| 136 | void WaitIdle() const; | 139 | void ShutDown(); |
| 137 | 140 | ||
| 138 | void OnCommandListEnd(); | 141 | void OnCommandListEnd(); |
| 139 | 142 | ||
| 140 | private: | 143 | private: |
| 141 | /// Pushes a command to be executed by the GPU thread | 144 | /// Pushes a command to be executed by the GPU thread |
| 142 | u64 PushCommand(CommandData&& command_data); | 145 | u64 PushCommand(CommandData&& command_data, bool block = false); |
| 143 | 146 | ||
| 144 | Core::System& system; | 147 | Core::System& system; |
| 145 | const bool is_async; | 148 | const bool is_async; |
diff --git a/src/video_core/host_shaders/CMakeLists.txt b/src/video_core/host_shaders/CMakeLists.txt index 3494318ca..2208e1922 100644 --- a/src/video_core/host_shaders/CMakeLists.txt +++ b/src/video_core/host_shaders/CMakeLists.txt | |||
| @@ -1,4 +1,5 @@ | |||
| 1 | set(SHADER_FILES | 1 | set(SHADER_FILES |
| 2 | astc_decoder.comp | ||
| 2 | block_linear_unswizzle_2d.comp | 3 | block_linear_unswizzle_2d.comp |
| 3 | block_linear_unswizzle_3d.comp | 4 | block_linear_unswizzle_3d.comp |
| 4 | convert_depth_to_float.frag | 5 | convert_depth_to_float.frag |
diff --git a/src/video_core/host_shaders/StringShaderHeader.cmake b/src/video_core/host_shaders/StringShaderHeader.cmake index c0fc49768..1b4bc6103 100644 --- a/src/video_core/host_shaders/StringShaderHeader.cmake +++ b/src/video_core/host_shaders/StringShaderHeader.cmake | |||
| @@ -6,7 +6,27 @@ get_filename_component(CONTENTS_NAME ${SOURCE_FILE} NAME) | |||
| 6 | string(REPLACE "." "_" CONTENTS_NAME ${CONTENTS_NAME}) | 6 | string(REPLACE "." "_" CONTENTS_NAME ${CONTENTS_NAME}) |
| 7 | string(TOUPPER ${CONTENTS_NAME} CONTENTS_NAME) | 7 | string(TOUPPER ${CONTENTS_NAME} CONTENTS_NAME) |
| 8 | 8 | ||
| 9 | file(READ ${SOURCE_FILE} CONTENTS) | 9 | FILE(READ ${SOURCE_FILE} line_contents) |
| 10 | |||
| 11 | # Replace double quotes with single quotes, | ||
| 12 | # as double quotes will be used to wrap the lines | ||
| 13 | STRING(REGEX REPLACE "\"" "'" line_contents "${line_contents}") | ||
| 14 | |||
| 15 | # CMake separates list elements with semicolons, but semicolons | ||
| 16 | # are used extensively in the shader code. | ||
| 17 | # Replace with a temporary marker, to be reverted later. | ||
| 18 | STRING(REGEX REPLACE ";" "{{SEMICOLON}}" line_contents "${line_contents}") | ||
| 19 | |||
| 20 | # Make every line an individual element in the CMake list. | ||
| 21 | STRING(REGEX REPLACE "\n" ";" line_contents "${line_contents}") | ||
| 22 | |||
| 23 | # Build the shader string, wrapping each line in double quotes. | ||
| 24 | foreach(line IN LISTS line_contents) | ||
| 25 | string(CONCAT CONTENTS "${CONTENTS}" \"${line}\\n\"\n) | ||
| 26 | endforeach() | ||
| 27 | |||
| 28 | # Revert the original semicolons in the source. | ||
| 29 | STRING(REGEX REPLACE "{{SEMICOLON}}" ";" CONTENTS "${CONTENTS}") | ||
| 10 | 30 | ||
| 11 | get_filename_component(OUTPUT_DIR ${HEADER_FILE} DIRECTORY) | 31 | get_filename_component(OUTPUT_DIR ${HEADER_FILE} DIRECTORY) |
| 12 | make_directory(${OUTPUT_DIR}) | 32 | make_directory(${OUTPUT_DIR}) |
diff --git a/src/video_core/host_shaders/astc_decoder.comp b/src/video_core/host_shaders/astc_decoder.comp new file mode 100644 index 000000000..703e34587 --- /dev/null +++ b/src/video_core/host_shaders/astc_decoder.comp | |||
| @@ -0,0 +1,1339 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #version 450 | ||
| 6 | |||
| 7 | #ifdef VULKAN | ||
| 8 | |||
| 9 | #define BEGIN_PUSH_CONSTANTS layout(push_constant) uniform PushConstants { | ||
| 10 | #define END_PUSH_CONSTANTS }; | ||
| 11 | #define UNIFORM(n) | ||
| 12 | #define BINDING_INPUT_BUFFER 0 | ||
| 13 | #define BINDING_ENC_BUFFER 1 | ||
| 14 | #define BINDING_6_TO_8_BUFFER 2 | ||
| 15 | #define BINDING_7_TO_8_BUFFER 3 | ||
| 16 | #define BINDING_8_TO_8_BUFFER 4 | ||
| 17 | #define BINDING_BYTE_TO_16_BUFFER 5 | ||
| 18 | #define BINDING_SWIZZLE_BUFFER 6 | ||
| 19 | #define BINDING_OUTPUT_IMAGE 7 | ||
| 20 | |||
| 21 | #else // ^^^ Vulkan ^^^ // vvv OpenGL vvv | ||
| 22 | |||
| 23 | #define BEGIN_PUSH_CONSTANTS | ||
| 24 | #define END_PUSH_CONSTANTS | ||
| 25 | #define UNIFORM(n) layout(location = n) uniform | ||
| 26 | #define BINDING_SWIZZLE_BUFFER 0 | ||
| 27 | #define BINDING_INPUT_BUFFER 1 | ||
| 28 | #define BINDING_ENC_BUFFER 2 | ||
| 29 | #define BINDING_6_TO_8_BUFFER 3 | ||
| 30 | #define BINDING_7_TO_8_BUFFER 4 | ||
| 31 | #define BINDING_8_TO_8_BUFFER 5 | ||
| 32 | #define BINDING_BYTE_TO_16_BUFFER 6 | ||
| 33 | #define BINDING_OUTPUT_IMAGE 0 | ||
| 34 | |||
| 35 | #endif | ||
| 36 | |||
| 37 | layout(local_size_x = 32, local_size_y = 32, local_size_z = 1) in; | ||
| 38 | |||
| 39 | BEGIN_PUSH_CONSTANTS | ||
| 40 | UNIFORM(1) uvec2 block_dims; | ||
| 41 | |||
| 42 | UNIFORM(2) uint bytes_per_block_log2; | ||
| 43 | UNIFORM(3) uint layer_stride; | ||
| 44 | UNIFORM(4) uint block_size; | ||
| 45 | UNIFORM(5) uint x_shift; | ||
| 46 | UNIFORM(6) uint block_height; | ||
| 47 | UNIFORM(7) uint block_height_mask; | ||
| 48 | END_PUSH_CONSTANTS | ||
| 49 | |||
| 50 | struct EncodingData { | ||
| 51 | uint encoding; | ||
| 52 | uint num_bits; | ||
| 53 | uint bit_value; | ||
| 54 | uint quint_trit_value; | ||
| 55 | }; | ||
| 56 | |||
| 57 | struct TexelWeightParams { | ||
| 58 | uvec2 size; | ||
| 59 | uint max_weight; | ||
| 60 | bool dual_plane; | ||
| 61 | bool error_state; | ||
| 62 | bool void_extent_ldr; | ||
| 63 | bool void_extent_hdr; | ||
| 64 | }; | ||
| 65 | |||
| 66 | // Swizzle data | ||
| 67 | layout(binding = BINDING_SWIZZLE_BUFFER, std430) readonly buffer SwizzleTable { | ||
| 68 | uint swizzle_table[]; | ||
| 69 | }; | ||
| 70 | |||
| 71 | layout(binding = BINDING_INPUT_BUFFER, std430) readonly buffer InputBufferU32 { | ||
| 72 | uint astc_data[]; | ||
| 73 | }; | ||
| 74 | |||
| 75 | // ASTC Encodings data | ||
| 76 | layout(binding = BINDING_ENC_BUFFER, std430) readonly buffer EncodingsValues { | ||
| 77 | EncodingData encoding_values[]; | ||
| 78 | }; | ||
| 79 | // ASTC Precompiled tables | ||
| 80 | layout(binding = BINDING_6_TO_8_BUFFER, std430) readonly buffer REPLICATE_6_BIT_TO_8 { | ||
| 81 | uint REPLICATE_6_BIT_TO_8_TABLE[]; | ||
| 82 | }; | ||
| 83 | layout(binding = BINDING_7_TO_8_BUFFER, std430) readonly buffer REPLICATE_7_BIT_TO_8 { | ||
| 84 | uint REPLICATE_7_BIT_TO_8_TABLE[]; | ||
| 85 | }; | ||
| 86 | layout(binding = BINDING_8_TO_8_BUFFER, std430) readonly buffer REPLICATE_8_BIT_TO_8 { | ||
| 87 | uint REPLICATE_8_BIT_TO_8_TABLE[]; | ||
| 88 | }; | ||
| 89 | layout(binding = BINDING_BYTE_TO_16_BUFFER, std430) readonly buffer REPLICATE_BYTE_TO_16 { | ||
| 90 | uint REPLICATE_BYTE_TO_16_TABLE[]; | ||
| 91 | }; | ||
| 92 | |||
| 93 | layout(binding = BINDING_OUTPUT_IMAGE, rgba8) uniform writeonly image2DArray dest_image; | ||
| 94 | |||
| 95 | const uint GOB_SIZE_X = 64; | ||
| 96 | const uint GOB_SIZE_Y = 8; | ||
| 97 | const uint GOB_SIZE_Z = 1; | ||
| 98 | const uint GOB_SIZE = GOB_SIZE_X * GOB_SIZE_Y * GOB_SIZE_Z; | ||
| 99 | |||
| 100 | const uint GOB_SIZE_X_SHIFT = 6; | ||
| 101 | const uint GOB_SIZE_Y_SHIFT = 3; | ||
| 102 | const uint GOB_SIZE_Z_SHIFT = 0; | ||
| 103 | const uint GOB_SIZE_SHIFT = GOB_SIZE_X_SHIFT + GOB_SIZE_Y_SHIFT + GOB_SIZE_Z_SHIFT; | ||
| 104 | |||
| 105 | const uvec2 SWIZZLE_MASK = uvec2(GOB_SIZE_X - 1, GOB_SIZE_Y - 1); | ||
| 106 | |||
| 107 | const int BLOCK_SIZE_IN_BYTES = 16; | ||
| 108 | |||
| 109 | const int BLOCK_INFO_ERROR = 0; | ||
| 110 | const int BLOCK_INFO_VOID_EXTENT_HDR = 1; | ||
| 111 | const int BLOCK_INFO_VOID_EXTENT_LDR = 2; | ||
| 112 | const int BLOCK_INFO_NORMAL = 3; | ||
| 113 | |||
| 114 | const int JUST_BITS = 0; | ||
| 115 | const int QUINT = 1; | ||
| 116 | const int TRIT = 2; | ||
| 117 | |||
| 118 | // The following constants are expanded variants of the Replicate() | ||
| 119 | // function calls corresponding to the following arguments: | ||
| 120 | // value: index into the generated table | ||
| 121 | // num_bits: the after "REPLICATE" in the table name. i.e. 4 is num_bits in REPLICATE_4. | ||
| 122 | // to_bit: the integer after "TO_" | ||
| 123 | const uint REPLICATE_BIT_TO_7_TABLE[2] = uint[](0, 127); | ||
| 124 | const uint REPLICATE_1_BIT_TO_9_TABLE[2] = uint[](0, 511); | ||
| 125 | |||
| 126 | const uint REPLICATE_1_BIT_TO_8_TABLE[2] = uint[](0, 255); | ||
| 127 | const uint REPLICATE_2_BIT_TO_8_TABLE[4] = uint[](0, 85, 170, 255); | ||
| 128 | const uint REPLICATE_3_BIT_TO_8_TABLE[8] = uint[](0, 36, 73, 109, 146, 182, 219, 255); | ||
| 129 | const uint REPLICATE_4_BIT_TO_8_TABLE[16] = | ||
| 130 | uint[](0, 17, 34, 51, 68, 85, 102, 119, 136, 153, 170, 187, 204, 221, 238, 255); | ||
| 131 | const uint REPLICATE_5_BIT_TO_8_TABLE[32] = | ||
| 132 | uint[](0, 8, 16, 24, 33, 41, 49, 57, 66, 74, 82, 90, 99, 107, 115, 123, 132, 140, 148, 156, 165, | ||
| 133 | 173, 181, 189, 198, 206, 214, 222, 231, 239, 247, 255); | ||
| 134 | const uint REPLICATE_1_BIT_TO_6_TABLE[2] = uint[](0, 63); | ||
| 135 | const uint REPLICATE_2_BIT_TO_6_TABLE[4] = uint[](0, 21, 42, 63); | ||
| 136 | const uint REPLICATE_3_BIT_TO_6_TABLE[8] = uint[](0, 9, 18, 27, 36, 45, 54, 63); | ||
| 137 | const uint REPLICATE_4_BIT_TO_6_TABLE[16] = | ||
| 138 | uint[](0, 4, 8, 12, 17, 21, 25, 29, 34, 38, 42, 46, 51, 55, 59, 63); | ||
| 139 | const uint REPLICATE_5_BIT_TO_6_TABLE[32] = | ||
| 140 | uint[](0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 33, 35, 37, 39, 41, 43, 45, | ||
| 141 | 47, 49, 51, 53, 55, 57, 59, 61, 63); | ||
| 142 | |||
| 143 | // Input ASTC texture globals | ||
| 144 | uint current_index = 0; | ||
| 145 | int bitsread = 0; | ||
| 146 | uint total_bitsread = 0; | ||
| 147 | uint local_buff[16]; | ||
| 148 | |||
| 149 | // Color data globals | ||
| 150 | uint color_endpoint_data[16]; | ||
| 151 | int color_bitsread = 0; | ||
| 152 | uint total_color_bitsread = 0; | ||
| 153 | int color_index = 0; | ||
| 154 | |||
| 155 | // Four values, two endpoints, four maximum paritions | ||
| 156 | uint color_values[32]; | ||
| 157 | int colvals_index = 0; | ||
| 158 | |||
| 159 | // Weight data globals | ||
| 160 | uint texel_weight_data[16]; | ||
| 161 | int texel_bitsread = 0; | ||
| 162 | uint total_texel_bitsread = 0; | ||
| 163 | int texel_index = 0; | ||
| 164 | |||
| 165 | bool texel_flag = false; | ||
| 166 | |||
| 167 | // Global "vectors" to be pushed into when decoding | ||
| 168 | EncodingData result_vector[100]; | ||
| 169 | int result_index = 0; | ||
| 170 | |||
| 171 | EncodingData texel_vector[100]; | ||
| 172 | int texel_vector_index = 0; | ||
| 173 | |||
| 174 | uint unquantized_texel_weights[2][144]; | ||
| 175 | |||
| 176 | uint SwizzleOffset(uvec2 pos) { | ||
| 177 | pos = pos & SWIZZLE_MASK; | ||
| 178 | return swizzle_table[pos.y * 64 + pos.x]; | ||
| 179 | } | ||
| 180 | |||
| 181 | uint ReadTexel(uint offset) { | ||
| 182 | // extract the 8-bit value from the 32-bit packed data. | ||
| 183 | return bitfieldExtract(astc_data[offset / 4], int((offset * 8) & 24), 8); | ||
| 184 | } | ||
| 185 | |||
| 186 | // Replicates low num_bits such that [(to_bit - 1):(to_bit - 1 - from_bit)] | ||
| 187 | // is the same as [(num_bits - 1):0] and repeats all the way down. | ||
| 188 | uint Replicate(uint val, uint num_bits, uint to_bit) { | ||
| 189 | if (num_bits == 0 || to_bit == 0) { | ||
| 190 | return 0; | ||
| 191 | } | ||
| 192 | const uint v = val & uint((1 << num_bits) - 1); | ||
| 193 | uint res = v; | ||
| 194 | uint reslen = num_bits; | ||
| 195 | while (reslen < to_bit) { | ||
| 196 | uint comp = 0; | ||
| 197 | if (num_bits > to_bit - reslen) { | ||
| 198 | uint newshift = to_bit - reslen; | ||
| 199 | comp = num_bits - newshift; | ||
| 200 | num_bits = newshift; | ||
| 201 | } | ||
| 202 | res = uint(res << num_bits); | ||
| 203 | res = uint(res | (v >> comp)); | ||
| 204 | reslen += num_bits; | ||
| 205 | } | ||
| 206 | return res; | ||
| 207 | } | ||
| 208 | |||
| 209 | uvec4 ReplicateByteTo16(uvec4 value) { | ||
| 210 | return uvec4(REPLICATE_BYTE_TO_16_TABLE[value.x], REPLICATE_BYTE_TO_16_TABLE[value.y], | ||
| 211 | REPLICATE_BYTE_TO_16_TABLE[value.z], REPLICATE_BYTE_TO_16_TABLE[value.w]); | ||
| 212 | } | ||
| 213 | |||
| 214 | uint ReplicateBitTo7(uint value) { | ||
| 215 | return REPLICATE_BIT_TO_7_TABLE[value]; | ||
| 216 | } | ||
| 217 | |||
| 218 | uint ReplicateBitTo9(uint value) { | ||
| 219 | return REPLICATE_1_BIT_TO_9_TABLE[value]; | ||
| 220 | } | ||
| 221 | |||
| 222 | uint FastReplicateTo8(uint value, uint num_bits) { | ||
| 223 | switch (num_bits) { | ||
| 224 | case 1: | ||
| 225 | return REPLICATE_1_BIT_TO_8_TABLE[value]; | ||
| 226 | case 2: | ||
| 227 | return REPLICATE_2_BIT_TO_8_TABLE[value]; | ||
| 228 | case 3: | ||
| 229 | return REPLICATE_3_BIT_TO_8_TABLE[value]; | ||
| 230 | case 4: | ||
| 231 | return REPLICATE_4_BIT_TO_8_TABLE[value]; | ||
| 232 | case 5: | ||
| 233 | return REPLICATE_5_BIT_TO_8_TABLE[value]; | ||
| 234 | case 6: | ||
| 235 | return REPLICATE_6_BIT_TO_8_TABLE[value]; | ||
| 236 | case 7: | ||
| 237 | return REPLICATE_7_BIT_TO_8_TABLE[value]; | ||
| 238 | case 8: | ||
| 239 | return REPLICATE_8_BIT_TO_8_TABLE[value]; | ||
| 240 | } | ||
| 241 | return Replicate(value, num_bits, 8); | ||
| 242 | } | ||
| 243 | |||
| 244 | uint FastReplicateTo6(uint value, uint num_bits) { | ||
| 245 | switch (num_bits) { | ||
| 246 | case 1: | ||
| 247 | return REPLICATE_1_BIT_TO_6_TABLE[value]; | ||
| 248 | case 2: | ||
| 249 | return REPLICATE_2_BIT_TO_6_TABLE[value]; | ||
| 250 | case 3: | ||
| 251 | return REPLICATE_3_BIT_TO_6_TABLE[value]; | ||
| 252 | case 4: | ||
| 253 | return REPLICATE_4_BIT_TO_6_TABLE[value]; | ||
| 254 | case 5: | ||
| 255 | return REPLICATE_5_BIT_TO_6_TABLE[value]; | ||
| 256 | } | ||
| 257 | return Replicate(value, num_bits, 6); | ||
| 258 | } | ||
| 259 | |||
| 260 | uint Div3Floor(uint v) { | ||
| 261 | return (v * 0x5556) >> 16; | ||
| 262 | } | ||
| 263 | |||
| 264 | uint Div3Ceil(uint v) { | ||
| 265 | return Div3Floor(v + 2); | ||
| 266 | } | ||
| 267 | |||
| 268 | uint Div5Floor(uint v) { | ||
| 269 | return (v * 0x3334) >> 16; | ||
| 270 | } | ||
| 271 | |||
| 272 | uint Div5Ceil(uint v) { | ||
| 273 | return Div5Floor(v + 4); | ||
| 274 | } | ||
| 275 | |||
| 276 | uint Hash52(uint p) { | ||
| 277 | p ^= p >> 15; | ||
| 278 | p -= p << 17; | ||
| 279 | p += p << 7; | ||
| 280 | p += p << 4; | ||
| 281 | p ^= p >> 5; | ||
| 282 | p += p << 16; | ||
| 283 | p ^= p >> 7; | ||
| 284 | p ^= p >> 3; | ||
| 285 | p ^= p << 6; | ||
| 286 | p ^= p >> 17; | ||
| 287 | return p; | ||
| 288 | } | ||
| 289 | |||
| 290 | uint SelectPartition(uint seed, uint x, uint y, uint z, uint partition_count, bool small_block) { | ||
| 291 | if (partition_count == 1) { | ||
| 292 | return 0; | ||
| 293 | } | ||
| 294 | if (small_block) { | ||
| 295 | x <<= 1; | ||
| 296 | y <<= 1; | ||
| 297 | z <<= 1; | ||
| 298 | } | ||
| 299 | |||
| 300 | seed += (partition_count - 1) * 1024; | ||
| 301 | |||
| 302 | uint rnum = Hash52(uint(seed)); | ||
| 303 | uint seed1 = uint(rnum & 0xF); | ||
| 304 | uint seed2 = uint((rnum >> 4) & 0xF); | ||
| 305 | uint seed3 = uint((rnum >> 8) & 0xF); | ||
| 306 | uint seed4 = uint((rnum >> 12) & 0xF); | ||
| 307 | uint seed5 = uint((rnum >> 16) & 0xF); | ||
| 308 | uint seed6 = uint((rnum >> 20) & 0xF); | ||
| 309 | uint seed7 = uint((rnum >> 24) & 0xF); | ||
| 310 | uint seed8 = uint((rnum >> 28) & 0xF); | ||
| 311 | uint seed9 = uint((rnum >> 18) & 0xF); | ||
| 312 | uint seed10 = uint((rnum >> 22) & 0xF); | ||
| 313 | uint seed11 = uint((rnum >> 26) & 0xF); | ||
| 314 | uint seed12 = uint(((rnum >> 30) | (rnum << 2)) & 0xF); | ||
| 315 | |||
| 316 | seed1 = (seed1 * seed1); | ||
| 317 | seed2 = (seed2 * seed2); | ||
| 318 | seed3 = (seed3 * seed3); | ||
| 319 | seed4 = (seed4 * seed4); | ||
| 320 | seed5 = (seed5 * seed5); | ||
| 321 | seed6 = (seed6 * seed6); | ||
| 322 | seed7 = (seed7 * seed7); | ||
| 323 | seed8 = (seed8 * seed8); | ||
| 324 | seed9 = (seed9 * seed9); | ||
| 325 | seed10 = (seed10 * seed10); | ||
| 326 | seed11 = (seed11 * seed11); | ||
| 327 | seed12 = (seed12 * seed12); | ||
| 328 | |||
| 329 | int sh1, sh2, sh3; | ||
| 330 | if ((seed & 1) > 0) { | ||
| 331 | sh1 = (seed & 2) > 0 ? 4 : 5; | ||
| 332 | sh2 = (partition_count == 3) ? 6 : 5; | ||
| 333 | } else { | ||
| 334 | sh1 = (partition_count == 3) ? 6 : 5; | ||
| 335 | sh2 = (seed & 2) > 0 ? 4 : 5; | ||
| 336 | } | ||
| 337 | sh3 = (seed & 0x10) > 0 ? sh1 : sh2; | ||
| 338 | |||
| 339 | seed1 = (seed1 >> sh1); | ||
| 340 | seed2 = (seed2 >> sh2); | ||
| 341 | seed3 = (seed3 >> sh1); | ||
| 342 | seed4 = (seed4 >> sh2); | ||
| 343 | seed5 = (seed5 >> sh1); | ||
| 344 | seed6 = (seed6 >> sh2); | ||
| 345 | seed7 = (seed7 >> sh1); | ||
| 346 | seed8 = (seed8 >> sh2); | ||
| 347 | seed9 = (seed9 >> sh3); | ||
| 348 | seed10 = (seed10 >> sh3); | ||
| 349 | seed11 = (seed11 >> sh3); | ||
| 350 | seed12 = (seed12 >> sh3); | ||
| 351 | |||
| 352 | uint a = seed1 * x + seed2 * y + seed11 * z + (rnum >> 14); | ||
| 353 | uint b = seed3 * x + seed4 * y + seed12 * z + (rnum >> 10); | ||
| 354 | uint c = seed5 * x + seed6 * y + seed9 * z + (rnum >> 6); | ||
| 355 | uint d = seed7 * x + seed8 * y + seed10 * z + (rnum >> 2); | ||
| 356 | |||
| 357 | a &= 0x3F; | ||
| 358 | b &= 0x3F; | ||
| 359 | c &= 0x3F; | ||
| 360 | d &= 0x3F; | ||
| 361 | |||
| 362 | if (partition_count < 4) { | ||
| 363 | d = 0; | ||
| 364 | } | ||
| 365 | if (partition_count < 3) { | ||
| 366 | c = 0; | ||
| 367 | } | ||
| 368 | |||
| 369 | if (a >= b && a >= c && a >= d) { | ||
| 370 | return 0; | ||
| 371 | } else if (b >= c && b >= d) { | ||
| 372 | return 1; | ||
| 373 | } else if (c >= d) { | ||
| 374 | return 2; | ||
| 375 | } else { | ||
| 376 | return 3; | ||
| 377 | } | ||
| 378 | } | ||
| 379 | |||
| 380 | uint Select2DPartition(uint seed, uint x, uint y, uint partition_count, bool small_block) { | ||
| 381 | return SelectPartition(seed, x, y, 0, partition_count, small_block); | ||
| 382 | } | ||
| 383 | |||
| 384 | uint ReadBit() { | ||
| 385 | if (current_index >= local_buff.length()) { | ||
| 386 | return 0; | ||
| 387 | } | ||
| 388 | uint bit = bitfieldExtract(local_buff[current_index], bitsread, 1); | ||
| 389 | ++bitsread; | ||
| 390 | ++total_bitsread; | ||
| 391 | if (bitsread == 8) { | ||
| 392 | ++current_index; | ||
| 393 | bitsread = 0; | ||
| 394 | } | ||
| 395 | return bit; | ||
| 396 | } | ||
| 397 | |||
| 398 | uint StreamBits(uint num_bits) { | ||
| 399 | uint ret = 0; | ||
| 400 | for (uint i = 0; i < num_bits; i++) { | ||
| 401 | ret |= ((ReadBit() & 1) << i); | ||
| 402 | } | ||
| 403 | return ret; | ||
| 404 | } | ||
| 405 | |||
| 406 | uint ReadColorBit() { | ||
| 407 | uint bit = 0; | ||
| 408 | if (texel_flag) { | ||
| 409 | bit = bitfieldExtract(texel_weight_data[texel_index], texel_bitsread, 1); | ||
| 410 | ++texel_bitsread; | ||
| 411 | ++total_texel_bitsread; | ||
| 412 | if (texel_bitsread == 8) { | ||
| 413 | ++texel_index; | ||
| 414 | texel_bitsread = 0; | ||
| 415 | } | ||
| 416 | } else { | ||
| 417 | bit = bitfieldExtract(color_endpoint_data[color_index], color_bitsread, 1); | ||
| 418 | ++color_bitsread; | ||
| 419 | ++total_color_bitsread; | ||
| 420 | if (color_bitsread == 8) { | ||
| 421 | ++color_index; | ||
| 422 | color_bitsread = 0; | ||
| 423 | } | ||
| 424 | } | ||
| 425 | return bit; | ||
| 426 | } | ||
| 427 | |||
| 428 | uint StreamColorBits(uint num_bits) { | ||
| 429 | uint ret = 0; | ||
| 430 | for (uint i = 0; i < num_bits; i++) { | ||
| 431 | ret |= ((ReadColorBit() & 1) << i); | ||
| 432 | } | ||
| 433 | return ret; | ||
| 434 | } | ||
| 435 | |||
| 436 | void ResultEmplaceBack(EncodingData val) { | ||
| 437 | if (texel_flag) { | ||
| 438 | texel_vector[texel_vector_index] = val; | ||
| 439 | ++texel_vector_index; | ||
| 440 | } else { | ||
| 441 | result_vector[result_index] = val; | ||
| 442 | ++result_index; | ||
| 443 | } | ||
| 444 | } | ||
| 445 | |||
| 446 | // Returns the number of bits required to encode n_vals values. | ||
| 447 | uint GetBitLength(uint n_vals, uint encoding_index) { | ||
| 448 | uint total_bits = encoding_values[encoding_index].num_bits * n_vals; | ||
| 449 | if (encoding_values[encoding_index].encoding == TRIT) { | ||
| 450 | total_bits += Div5Ceil(n_vals * 8); | ||
| 451 | } else if (encoding_values[encoding_index].encoding == QUINT) { | ||
| 452 | total_bits += Div3Ceil(n_vals * 7); | ||
| 453 | } | ||
| 454 | return total_bits; | ||
| 455 | } | ||
| 456 | |||
| 457 | uint GetNumWeightValues(uvec2 size, bool dual_plane) { | ||
| 458 | uint n_vals = size.x * size.y; | ||
| 459 | if (dual_plane) { | ||
| 460 | n_vals *= 2; | ||
| 461 | } | ||
| 462 | return n_vals; | ||
| 463 | } | ||
| 464 | |||
| 465 | uint GetPackedBitSize(uvec2 size, bool dual_plane, uint max_weight) { | ||
| 466 | uint n_vals = GetNumWeightValues(size, dual_plane); | ||
| 467 | return GetBitLength(n_vals, max_weight); | ||
| 468 | } | ||
| 469 | |||
| 470 | uint BitsBracket(uint bits, uint pos) { | ||
| 471 | return ((bits >> pos) & 1); | ||
| 472 | } | ||
| 473 | |||
| 474 | uint BitsOp(uint bits, uint start, uint end) { | ||
| 475 | if (start == end) { | ||
| 476 | return BitsBracket(bits, start); | ||
| 477 | } else if (start > end) { | ||
| 478 | uint t = start; | ||
| 479 | start = end; | ||
| 480 | end = t; | ||
| 481 | } | ||
| 482 | |||
| 483 | uint mask = (1 << (end - start + 1)) - 1; | ||
| 484 | return ((bits >> start) & mask); | ||
| 485 | } | ||
| 486 | |||
| 487 | void DecodeQuintBlock(uint num_bits) { | ||
| 488 | uint m[3]; | ||
| 489 | uint q[3]; | ||
| 490 | uint Q; | ||
| 491 | m[0] = StreamColorBits(num_bits); | ||
| 492 | Q = StreamColorBits(3); | ||
| 493 | m[1] = StreamColorBits(num_bits); | ||
| 494 | Q |= StreamColorBits(2) << 3; | ||
| 495 | m[2] = StreamColorBits(num_bits); | ||
| 496 | Q |= StreamColorBits(2) << 5; | ||
| 497 | if (BitsOp(Q, 1, 2) == 3 && BitsOp(Q, 5, 6) == 0) { | ||
| 498 | q[0] = 4; | ||
| 499 | q[1] = 4; | ||
| 500 | q[2] = (BitsBracket(Q, 0) << 2) | ((BitsBracket(Q, 4) & ~BitsBracket(Q, 0)) << 1) | | ||
| 501 | (BitsBracket(Q, 3) & ~BitsBracket(Q, 0)); | ||
| 502 | } else { | ||
| 503 | uint C = 0; | ||
| 504 | if (BitsOp(Q, 1, 2) == 3) { | ||
| 505 | q[2] = 4; | ||
| 506 | C = (BitsOp(Q, 3, 4) << 3) | ((~BitsOp(Q, 5, 6) & 3) << 1) | BitsBracket(Q, 0); | ||
| 507 | } else { | ||
| 508 | q[2] = BitsOp(Q, 5, 6); | ||
| 509 | C = BitsOp(Q, 0, 4); | ||
| 510 | } | ||
| 511 | if (BitsOp(C, 0, 2) == 5) { | ||
| 512 | q[1] = 4; | ||
| 513 | q[0] = BitsOp(C, 3, 4); | ||
| 514 | } else { | ||
| 515 | q[1] = BitsOp(C, 3, 4); | ||
| 516 | q[0] = BitsOp(C, 0, 2); | ||
| 517 | } | ||
| 518 | } | ||
| 519 | for (uint i = 0; i < 3; i++) { | ||
| 520 | EncodingData val; | ||
| 521 | val.encoding = QUINT; | ||
| 522 | val.num_bits = num_bits; | ||
| 523 | val.bit_value = m[i]; | ||
| 524 | val.quint_trit_value = q[i]; | ||
| 525 | ResultEmplaceBack(val); | ||
| 526 | } | ||
| 527 | } | ||
| 528 | |||
| 529 | void DecodeTritBlock(uint num_bits) { | ||
| 530 | uint m[5]; | ||
| 531 | uint t[5]; | ||
| 532 | uint T; | ||
| 533 | m[0] = StreamColorBits(num_bits); | ||
| 534 | T = StreamColorBits(2); | ||
| 535 | m[1] = StreamColorBits(num_bits); | ||
| 536 | T |= StreamColorBits(2) << 2; | ||
| 537 | m[2] = StreamColorBits(num_bits); | ||
| 538 | T |= StreamColorBits(1) << 4; | ||
| 539 | m[3] = StreamColorBits(num_bits); | ||
| 540 | T |= StreamColorBits(2) << 5; | ||
| 541 | m[4] = StreamColorBits(num_bits); | ||
| 542 | T |= StreamColorBits(1) << 7; | ||
| 543 | uint C = 0; | ||
| 544 | if (BitsOp(T, 2, 4) == 7) { | ||
| 545 | C = (BitsOp(T, 5, 7) << 2) | BitsOp(T, 0, 1); | ||
| 546 | t[4] = 2; | ||
| 547 | t[3] = 2; | ||
| 548 | } else { | ||
| 549 | C = BitsOp(T, 0, 4); | ||
| 550 | if (BitsOp(T, 5, 6) == 3) { | ||
| 551 | t[4] = 2; | ||
| 552 | t[3] = BitsBracket(T, 7); | ||
| 553 | } else { | ||
| 554 | t[4] = BitsBracket(T, 7); | ||
| 555 | t[3] = BitsOp(T, 5, 6); | ||
| 556 | } | ||
| 557 | } | ||
| 558 | if (BitsOp(C, 0, 1) == 3) { | ||
| 559 | t[2] = 2; | ||
| 560 | t[1] = BitsBracket(C, 4); | ||
| 561 | t[0] = (BitsBracket(C, 3) << 1) | (BitsBracket(C, 2) & ~BitsBracket(C, 3)); | ||
| 562 | } else if (BitsOp(C, 2, 3) == 3) { | ||
| 563 | t[2] = 2; | ||
| 564 | t[1] = 2; | ||
| 565 | t[0] = BitsOp(C, 0, 1); | ||
| 566 | } else { | ||
| 567 | t[2] = BitsBracket(C, 4); | ||
| 568 | t[1] = BitsOp(C, 2, 3); | ||
| 569 | t[0] = (BitsBracket(C, 1) << 1) | (BitsBracket(C, 0) & ~BitsBracket(C, 1)); | ||
| 570 | } | ||
| 571 | for (uint i = 0; i < 5; i++) { | ||
| 572 | EncodingData val; | ||
| 573 | val.encoding = TRIT; | ||
| 574 | val.num_bits = num_bits; | ||
| 575 | val.bit_value = m[i]; | ||
| 576 | val.quint_trit_value = t[i]; | ||
| 577 | ResultEmplaceBack(val); | ||
| 578 | } | ||
| 579 | } | ||
| 580 | |||
| 581 | void DecodeIntegerSequence(uint max_range, uint num_values) { | ||
| 582 | EncodingData val = encoding_values[max_range]; | ||
| 583 | uint vals_decoded = 0; | ||
| 584 | while (vals_decoded < num_values) { | ||
| 585 | switch (val.encoding) { | ||
| 586 | case QUINT: | ||
| 587 | DecodeQuintBlock(val.num_bits); | ||
| 588 | vals_decoded += 3; | ||
| 589 | break; | ||
| 590 | case TRIT: | ||
| 591 | DecodeTritBlock(val.num_bits); | ||
| 592 | vals_decoded += 5; | ||
| 593 | break; | ||
| 594 | case JUST_BITS: | ||
| 595 | val.bit_value = StreamColorBits(val.num_bits); | ||
| 596 | ResultEmplaceBack(val); | ||
| 597 | vals_decoded++; | ||
| 598 | break; | ||
| 599 | } | ||
| 600 | } | ||
| 601 | } | ||
| 602 | |||
| 603 | void DecodeColorValues(uvec4 modes, uint num_partitions, uint color_data_bits) { | ||
| 604 | uint num_values = 0; | ||
| 605 | for (uint i = 0; i < num_partitions; i++) { | ||
| 606 | num_values += ((modes[i] >> 2) + 1) << 1; | ||
| 607 | } | ||
| 608 | int range = 256; | ||
| 609 | while (--range > 0) { | ||
| 610 | EncodingData val = encoding_values[range]; | ||
| 611 | uint bit_length = GetBitLength(num_values, range); | ||
| 612 | if (bit_length <= color_data_bits) { | ||
| 613 | while (--range > 0) { | ||
| 614 | EncodingData newval = encoding_values[range]; | ||
| 615 | if (newval.encoding != val.encoding && newval.num_bits != val.num_bits) { | ||
| 616 | break; | ||
| 617 | } | ||
| 618 | } | ||
| 619 | ++range; | ||
| 620 | break; | ||
| 621 | } | ||
| 622 | } | ||
| 623 | DecodeIntegerSequence(range, num_values); | ||
| 624 | uint out_index = 0; | ||
| 625 | for (int itr = 0; itr < result_index; ++itr) { | ||
| 626 | if (out_index >= num_values) { | ||
| 627 | break; | ||
| 628 | } | ||
| 629 | EncodingData val = result_vector[itr]; | ||
| 630 | uint bitlen = val.num_bits; | ||
| 631 | uint bitval = val.bit_value; | ||
| 632 | uint A = 0, B = 0, C = 0, D = 0; | ||
| 633 | A = ReplicateBitTo9((bitval & 1)); | ||
| 634 | switch (val.encoding) { | ||
| 635 | case JUST_BITS: | ||
| 636 | color_values[out_index++] = FastReplicateTo8(bitval, bitlen); | ||
| 637 | break; | ||
| 638 | case TRIT: { | ||
| 639 | D = val.quint_trit_value; | ||
| 640 | switch (bitlen) { | ||
| 641 | case 1: | ||
| 642 | C = 204; | ||
| 643 | break; | ||
| 644 | case 2: { | ||
| 645 | C = 93; | ||
| 646 | uint b = (bitval >> 1) & 1; | ||
| 647 | B = (b << 8) | (b << 4) | (b << 2) | (b << 1); | ||
| 648 | break; | ||
| 649 | } | ||
| 650 | case 3: { | ||
| 651 | C = 44; | ||
| 652 | uint cb = (bitval >> 1) & 3; | ||
| 653 | B = (cb << 7) | (cb << 2) | cb; | ||
| 654 | break; | ||
| 655 | } | ||
| 656 | case 4: { | ||
| 657 | C = 22; | ||
| 658 | uint dcb = (bitval >> 1) & 7; | ||
| 659 | B = (dcb << 6) | dcb; | ||
| 660 | break; | ||
| 661 | } | ||
| 662 | case 5: { | ||
| 663 | C = 11; | ||
| 664 | uint edcb = (bitval >> 1) & 0xF; | ||
| 665 | B = (edcb << 5) | (edcb >> 2); | ||
| 666 | break; | ||
| 667 | } | ||
| 668 | case 6: { | ||
| 669 | C = 5; | ||
| 670 | uint fedcb = (bitval >> 1) & 0x1F; | ||
| 671 | B = (fedcb << 4) | (fedcb >> 4); | ||
| 672 | break; | ||
| 673 | } | ||
| 674 | } | ||
| 675 | break; | ||
| 676 | } | ||
| 677 | case QUINT: { | ||
| 678 | D = val.quint_trit_value; | ||
| 679 | switch (bitlen) { | ||
| 680 | case 1: | ||
| 681 | C = 113; | ||
| 682 | break; | ||
| 683 | case 2: { | ||
| 684 | C = 54; | ||
| 685 | uint b = (bitval >> 1) & 1; | ||
| 686 | B = (b << 8) | (b << 3) | (b << 2); | ||
| 687 | break; | ||
| 688 | } | ||
| 689 | case 3: { | ||
| 690 | C = 26; | ||
| 691 | uint cb = (bitval >> 1) & 3; | ||
| 692 | B = (cb << 7) | (cb << 1) | (cb >> 1); | ||
| 693 | break; | ||
| 694 | } | ||
| 695 | case 4: { | ||
| 696 | C = 13; | ||
| 697 | uint dcb = (bitval >> 1) & 7; | ||
| 698 | B = (dcb << 6) | (dcb >> 1); | ||
| 699 | break; | ||
| 700 | } | ||
| 701 | case 5: { | ||
| 702 | C = 6; | ||
| 703 | uint edcb = (bitval >> 1) & 0xF; | ||
| 704 | B = (edcb << 5) | (edcb >> 3); | ||
| 705 | break; | ||
| 706 | } | ||
| 707 | } | ||
| 708 | break; | ||
| 709 | } | ||
| 710 | } | ||
| 711 | if (val.encoding != JUST_BITS) { | ||
| 712 | uint T = (D * C) + B; | ||
| 713 | T ^= A; | ||
| 714 | T = (A & 0x80) | (T >> 2); | ||
| 715 | color_values[out_index++] = T; | ||
| 716 | } | ||
| 717 | } | ||
| 718 | } | ||
| 719 | |||
| 720 | ivec2 BitTransferSigned(int a, int b) { | ||
| 721 | ivec2 transferred; | ||
| 722 | transferred.y = b >> 1; | ||
| 723 | transferred.y |= a & 0x80; | ||
| 724 | transferred.x = a >> 1; | ||
| 725 | transferred.x &= 0x3F; | ||
| 726 | if ((transferred.x & 0x20) > 0) { | ||
| 727 | transferred.x -= 0x40; | ||
| 728 | } | ||
| 729 | return transferred; | ||
| 730 | } | ||
| 731 | |||
| 732 | uvec4 ClampByte(ivec4 color) { | ||
| 733 | for (uint i = 0; i < 4; ++i) { | ||
| 734 | color[i] = (color[i] < 0) ? 0 : ((color[i] > 255) ? 255 : color[i]); | ||
| 735 | } | ||
| 736 | return uvec4(color); | ||
| 737 | } | ||
| 738 | |||
| 739 | ivec4 BlueContract(int a, int r, int g, int b) { | ||
| 740 | return ivec4(a, (r + b) >> 1, (g + b) >> 1, b); | ||
| 741 | } | ||
| 742 | |||
| 743 | void ComputeEndpoints(out uvec4 ep1, out uvec4 ep2, uint color_endpoint_mode) { | ||
| 744 | #define READ_UINT_VALUES(N) \ | ||
| 745 | uint v[N]; \ | ||
| 746 | for (uint i = 0; i < N; i++) { \ | ||
| 747 | v[i] = color_values[colvals_index++]; \ | ||
| 748 | } | ||
| 749 | |||
| 750 | #define READ_INT_VALUES(N) \ | ||
| 751 | int v[N]; \ | ||
| 752 | for (uint i = 0; i < N; i++) { \ | ||
| 753 | v[i] = int(color_values[colvals_index++]); \ | ||
| 754 | } | ||
| 755 | |||
| 756 | switch (color_endpoint_mode) { | ||
| 757 | case 0: { | ||
| 758 | READ_UINT_VALUES(2) | ||
| 759 | ep1 = uvec4(0xFF, v[0], v[0], v[0]); | ||
| 760 | ep2 = uvec4(0xFF, v[1], v[1], v[1]); | ||
| 761 | break; | ||
| 762 | } | ||
| 763 | case 1: { | ||
| 764 | READ_UINT_VALUES(2) | ||
| 765 | uint L0 = (v[0] >> 2) | (v[1] & 0xC0); | ||
| 766 | uint L1 = max(L0 + (v[1] & 0x3F), 0xFFU); | ||
| 767 | ep1 = uvec4(0xFF, L0, L0, L0); | ||
| 768 | ep2 = uvec4(0xFF, L1, L1, L1); | ||
| 769 | break; | ||
| 770 | } | ||
| 771 | case 4: { | ||
| 772 | READ_UINT_VALUES(4) | ||
| 773 | ep1 = uvec4(v[2], v[0], v[0], v[0]); | ||
| 774 | ep2 = uvec4(v[3], v[1], v[1], v[1]); | ||
| 775 | break; | ||
| 776 | } | ||
| 777 | case 5: { | ||
| 778 | READ_INT_VALUES(4) | ||
| 779 | ivec2 transferred = BitTransferSigned(v[1], v[0]); | ||
| 780 | v[1] = transferred.x; | ||
| 781 | v[0] = transferred.y; | ||
| 782 | transferred = BitTransferSigned(v[3], v[2]); | ||
| 783 | v[3] = transferred.x; | ||
| 784 | v[2] = transferred.y; | ||
| 785 | ep1 = ClampByte(ivec4(v[2], v[0], v[0], v[0])); | ||
| 786 | ep2 = ClampByte(ivec4(v[2] + v[3], v[0] + v[1], v[0] + v[1], v[0] + v[1])); | ||
| 787 | break; | ||
| 788 | } | ||
| 789 | case 6: { | ||
| 790 | READ_UINT_VALUES(4) | ||
| 791 | ep1 = uvec4(0xFF, (v[0] * v[3]) >> 8, (v[1] * v[3]) >> 8, (v[2] * v[3]) >> 8); | ||
| 792 | ep2 = uvec4(0xFF, v[0], v[1], v[2]); | ||
| 793 | break; | ||
| 794 | } | ||
| 795 | case 8: { | ||
| 796 | READ_UINT_VALUES(6) | ||
| 797 | if ((v[1] + v[3] + v[5]) >= (v[0] + v[2] + v[4])) { | ||
| 798 | ep1 = uvec4(0xFF, v[0], v[2], v[4]); | ||
| 799 | ep2 = uvec4(0xFF, v[1], v[3], v[5]); | ||
| 800 | } else { | ||
| 801 | ep1 = uvec4(BlueContract(0xFF, int(v[1]), int(v[3]), int(v[5]))); | ||
| 802 | ep2 = uvec4(BlueContract(0xFF, int(v[0]), int(v[2]), int(v[4]))); | ||
| 803 | } | ||
| 804 | break; | ||
| 805 | } | ||
| 806 | case 9: { | ||
| 807 | READ_INT_VALUES(6) | ||
| 808 | ivec2 transferred = BitTransferSigned(v[1], v[0]); | ||
| 809 | v[1] = transferred.x; | ||
| 810 | v[0] = transferred.y; | ||
| 811 | transferred = BitTransferSigned(v[3], v[2]); | ||
| 812 | v[3] = transferred.x; | ||
| 813 | v[2] = transferred.y; | ||
| 814 | transferred = BitTransferSigned(v[5], v[4]); | ||
| 815 | v[5] = transferred.x; | ||
| 816 | v[4] = transferred.y; | ||
| 817 | if ((v[1] + v[3] + v[5]) >= 0) { | ||
| 818 | ep1 = ClampByte(ivec4(0xFF, v[0], v[2], v[4])); | ||
| 819 | ep2 = ClampByte(ivec4(0xFF, v[0] + v[1], v[2] + v[3], v[4] + v[5])); | ||
| 820 | } else { | ||
| 821 | ep1 = ClampByte(BlueContract(0xFF, v[0] + v[1], v[2] + v[3], v[4] + v[5])); | ||
| 822 | ep2 = ClampByte(BlueContract(0xFF, v[0], v[2], v[4])); | ||
| 823 | } | ||
| 824 | break; | ||
| 825 | } | ||
| 826 | case 10: { | ||
| 827 | READ_UINT_VALUES(6) | ||
| 828 | ep1 = uvec4(v[4], (v[0] * v[3]) >> 8, (v[1] * v[3]) >> 8, (v[2] * v[3]) >> 8); | ||
| 829 | ep2 = uvec4(v[5], v[0], v[1], v[2]); | ||
| 830 | break; | ||
| 831 | } | ||
| 832 | case 12: { | ||
| 833 | READ_UINT_VALUES(8) | ||
| 834 | if ((v[1] + v[3] + v[5]) >= (v[0] + v[2] + v[4])) { | ||
| 835 | ep1 = uvec4(v[6], v[0], v[2], v[4]); | ||
| 836 | ep2 = uvec4(v[7], v[1], v[3], v[5]); | ||
| 837 | } else { | ||
| 838 | ep1 = uvec4(BlueContract(int(v[7]), int(v[1]), int(v[3]), int(v[5]))); | ||
| 839 | ep2 = uvec4(BlueContract(int(v[6]), int(v[0]), int(v[2]), int(v[4]))); | ||
| 840 | } | ||
| 841 | break; | ||
| 842 | } | ||
| 843 | case 13: { | ||
| 844 | READ_INT_VALUES(8) | ||
| 845 | ivec2 transferred = BitTransferSigned(v[1], v[0]); | ||
| 846 | v[1] = transferred.x; | ||
| 847 | v[0] = transferred.y; | ||
| 848 | transferred = BitTransferSigned(v[3], v[2]); | ||
| 849 | v[3] = transferred.x; | ||
| 850 | v[2] = transferred.y; | ||
| 851 | |||
| 852 | transferred = BitTransferSigned(v[5], v[4]); | ||
| 853 | v[5] = transferred.x; | ||
| 854 | v[4] = transferred.y; | ||
| 855 | |||
| 856 | transferred = BitTransferSigned(v[7], v[6]); | ||
| 857 | v[7] = transferred.x; | ||
| 858 | v[6] = transferred.y; | ||
| 859 | |||
| 860 | if ((v[1] + v[3] + v[5]) >= 0) { | ||
| 861 | ep1 = ClampByte(ivec4(v[6], v[0], v[2], v[4])); | ||
| 862 | ep2 = ClampByte(ivec4(v[7] + v[6], v[0] + v[1], v[2] + v[3], v[4] + v[5])); | ||
| 863 | } else { | ||
| 864 | ep1 = ClampByte(BlueContract(v[6] + v[7], v[0] + v[1], v[2] + v[3], v[4] + v[5])); | ||
| 865 | ep2 = ClampByte(BlueContract(v[6], v[0], v[2], v[4])); | ||
| 866 | } | ||
| 867 | break; | ||
| 868 | } | ||
| 869 | default: { | ||
| 870 | // HDR mode, or more likely a bug computing the color_endpoint_mode | ||
| 871 | ep1 = uvec4(0xFF, 0xFF, 0, 0); | ||
| 872 | ep2 = uvec4(0xFF, 0xFF, 0, 0); | ||
| 873 | break; | ||
| 874 | } | ||
| 875 | } | ||
| 876 | #undef READ_UINT_VALUES | ||
| 877 | #undef READ_INT_VALUES | ||
| 878 | } | ||
| 879 | |||
| 880 | uint UnquantizeTexelWeight(EncodingData val) { | ||
| 881 | uint bitval = val.bit_value; | ||
| 882 | uint bitlen = val.num_bits; | ||
| 883 | uint A = ReplicateBitTo7((bitval & 1)); | ||
| 884 | uint B = 0, C = 0, D = 0; | ||
| 885 | uint result = 0; | ||
| 886 | switch (val.encoding) { | ||
| 887 | case JUST_BITS: | ||
| 888 | result = FastReplicateTo6(bitval, bitlen); | ||
| 889 | break; | ||
| 890 | case TRIT: { | ||
| 891 | D = val.quint_trit_value; | ||
| 892 | switch (bitlen) { | ||
| 893 | case 0: { | ||
| 894 | uint results[3] = {0, 32, 63}; | ||
| 895 | result = results[D]; | ||
| 896 | break; | ||
| 897 | } | ||
| 898 | case 1: { | ||
| 899 | C = 50; | ||
| 900 | break; | ||
| 901 | } | ||
| 902 | case 2: { | ||
| 903 | C = 23; | ||
| 904 | uint b = (bitval >> 1) & 1; | ||
| 905 | B = (b << 6) | (b << 2) | b; | ||
| 906 | break; | ||
| 907 | } | ||
| 908 | case 3: { | ||
| 909 | C = 11; | ||
| 910 | uint cb = (bitval >> 1) & 3; | ||
| 911 | B = (cb << 5) | cb; | ||
| 912 | break; | ||
| 913 | } | ||
| 914 | default: | ||
| 915 | break; | ||
| 916 | } | ||
| 917 | break; | ||
| 918 | } | ||
| 919 | case QUINT: { | ||
| 920 | D = val.quint_trit_value; | ||
| 921 | switch (bitlen) { | ||
| 922 | case 0: { | ||
| 923 | uint results[5] = {0, 16, 32, 47, 63}; | ||
| 924 | result = results[D]; | ||
| 925 | break; | ||
| 926 | } | ||
| 927 | case 1: { | ||
| 928 | C = 28; | ||
| 929 | break; | ||
| 930 | } | ||
| 931 | case 2: { | ||
| 932 | C = 13; | ||
| 933 | uint b = (bitval >> 1) & 1; | ||
| 934 | B = (b << 6) | (b << 1); | ||
| 935 | break; | ||
| 936 | } | ||
| 937 | } | ||
| 938 | break; | ||
| 939 | } | ||
| 940 | } | ||
| 941 | if (val.encoding != JUST_BITS && bitlen > 0) { | ||
| 942 | result = D * C + B; | ||
| 943 | result ^= A; | ||
| 944 | result = (A & 0x20) | (result >> 2); | ||
| 945 | } | ||
| 946 | if (result > 32) { | ||
| 947 | result += 1; | ||
| 948 | } | ||
| 949 | return result; | ||
| 950 | } | ||
| 951 | |||
| 952 | void UnquantizeTexelWeights(bool dual_plane, uvec2 size) { | ||
| 953 | uint weight_idx = 0; | ||
| 954 | uint unquantized[2][144]; | ||
| 955 | uint area = size.x * size.y; | ||
| 956 | for (uint itr = 0; itr < texel_vector_index; itr++) { | ||
| 957 | unquantized[0][weight_idx] = UnquantizeTexelWeight(texel_vector[itr]); | ||
| 958 | if (dual_plane) { | ||
| 959 | ++itr; | ||
| 960 | unquantized[1][weight_idx] = UnquantizeTexelWeight(texel_vector[itr]); | ||
| 961 | if (itr == texel_vector_index) { | ||
| 962 | break; | ||
| 963 | } | ||
| 964 | } | ||
| 965 | if (++weight_idx >= (area)) | ||
| 966 | break; | ||
| 967 | } | ||
| 968 | |||
| 969 | const uint Ds = uint((block_dims.x * 0.5f + 1024) / (block_dims.x - 1)); | ||
| 970 | const uint Dt = uint((block_dims.y * 0.5f + 1024) / (block_dims.y - 1)); | ||
| 971 | const uint k_plane_scale = dual_plane ? 2 : 1; | ||
| 972 | for (uint plane = 0; plane < k_plane_scale; plane++) { | ||
| 973 | for (uint t = 0; t < block_dims.y; t++) { | ||
| 974 | for (uint s = 0; s < block_dims.x; s++) { | ||
| 975 | uint cs = Ds * s; | ||
| 976 | uint ct = Dt * t; | ||
| 977 | uint gs = (cs * (size.x - 1) + 32) >> 6; | ||
| 978 | uint gt = (ct * (size.y - 1) + 32) >> 6; | ||
| 979 | uint js = gs >> 4; | ||
| 980 | uint fs = gs & 0xF; | ||
| 981 | uint jt = gt >> 4; | ||
| 982 | uint ft = gt & 0x0F; | ||
| 983 | uint w11 = (fs * ft + 8) >> 4; | ||
| 984 | uint w10 = ft - w11; | ||
| 985 | uint w01 = fs - w11; | ||
| 986 | uint w00 = 16 - fs - ft + w11; | ||
| 987 | uvec4 w = uvec4(w00, w01, w10, w11); | ||
| 988 | uint v0 = jt * size.x + js; | ||
| 989 | |||
| 990 | uvec4 p = uvec4(0); | ||
| 991 | if (v0 < area) { | ||
| 992 | p.x = unquantized[plane][v0]; | ||
| 993 | } | ||
| 994 | if ((v0 + 1) < (area)) { | ||
| 995 | p.y = unquantized[plane][v0 + 1]; | ||
| 996 | } | ||
| 997 | if ((v0 + size.x) < (area)) { | ||
| 998 | p.z = unquantized[plane][(v0 + size.x)]; | ||
| 999 | } | ||
| 1000 | if ((v0 + size.x + 1) < (area)) { | ||
| 1001 | p.w = unquantized[plane][(v0 + size.x + 1)]; | ||
| 1002 | } | ||
| 1003 | unquantized_texel_weights[plane][t * block_dims.x + s] = (uint(dot(p, w)) + 8) >> 4; | ||
| 1004 | } | ||
| 1005 | } | ||
| 1006 | } | ||
| 1007 | } | ||
| 1008 | |||
| 1009 | int FindLayout(uint mode) { | ||
| 1010 | if ((mode & 3) != 0) { | ||
| 1011 | if ((mode & 8) != 0) { | ||
| 1012 | if ((mode & 4) != 0) { | ||
| 1013 | if ((mode & 0x100) != 0) { | ||
| 1014 | return 4; | ||
| 1015 | } | ||
| 1016 | return 3; | ||
| 1017 | } | ||
| 1018 | return 2; | ||
| 1019 | } | ||
| 1020 | if ((mode & 4) != 0) { | ||
| 1021 | return 1; | ||
| 1022 | } | ||
| 1023 | return 0; | ||
| 1024 | } | ||
| 1025 | if ((mode & 0x100) != 0) { | ||
| 1026 | if ((mode & 0x80) != 0) { | ||
| 1027 | if ((mode & 0x20) != 0) { | ||
| 1028 | return 8; | ||
| 1029 | } | ||
| 1030 | return 7; | ||
| 1031 | } | ||
| 1032 | return 9; | ||
| 1033 | } | ||
| 1034 | if ((mode & 0x80) != 0) { | ||
| 1035 | return 6; | ||
| 1036 | } | ||
| 1037 | return 5; | ||
| 1038 | } | ||
| 1039 | |||
| 1040 | TexelWeightParams DecodeBlockInfo(uint block_index) { | ||
| 1041 | TexelWeightParams params = TexelWeightParams(uvec2(0), 0, false, false, false, false); | ||
| 1042 | uint mode = StreamBits(11); | ||
| 1043 | if ((mode & 0x1ff) == 0x1fc) { | ||
| 1044 | if ((mode & 0x200) != 0) { | ||
| 1045 | params.void_extent_hdr = true; | ||
| 1046 | } else { | ||
| 1047 | params.void_extent_ldr = true; | ||
| 1048 | } | ||
| 1049 | if ((mode & 0x400) == 0 || StreamBits(1) == 0) { | ||
| 1050 | params.error_state = true; | ||
| 1051 | } | ||
| 1052 | return params; | ||
| 1053 | } | ||
| 1054 | if ((mode & 0xf) == 0) { | ||
| 1055 | params.error_state = true; | ||
| 1056 | return params; | ||
| 1057 | } | ||
| 1058 | if ((mode & 3) == 0 && (mode & 0x1c0) == 0x1c0) { | ||
| 1059 | params.error_state = true; | ||
| 1060 | return params; | ||
| 1061 | } | ||
| 1062 | uint A, B; | ||
| 1063 | uint mode_layout = FindLayout(mode); | ||
| 1064 | switch (mode_layout) { | ||
| 1065 | case 0: | ||
| 1066 | A = (mode >> 5) & 0x3; | ||
| 1067 | B = (mode >> 7) & 0x3; | ||
| 1068 | params.size = uvec2(B + 4, A + 2); | ||
| 1069 | break; | ||
| 1070 | case 1: | ||
| 1071 | A = (mode >> 5) & 0x3; | ||
| 1072 | B = (mode >> 7) & 0x3; | ||
| 1073 | params.size = uvec2(B + 8, A + 2); | ||
| 1074 | break; | ||
| 1075 | case 2: | ||
| 1076 | A = (mode >> 5) & 0x3; | ||
| 1077 | B = (mode >> 7) & 0x3; | ||
| 1078 | params.size = uvec2(A + 2, B + 8); | ||
| 1079 | break; | ||
| 1080 | case 3: | ||
| 1081 | A = (mode >> 5) & 0x3; | ||
| 1082 | B = (mode >> 7) & 0x1; | ||
| 1083 | params.size = uvec2(A + 2, B + 6); | ||
| 1084 | break; | ||
| 1085 | case 4: | ||
| 1086 | A = (mode >> 5) & 0x3; | ||
| 1087 | B = (mode >> 7) & 0x1; | ||
| 1088 | params.size = uvec2(B + 2, A + 2); | ||
| 1089 | break; | ||
| 1090 | case 5: | ||
| 1091 | A = (mode >> 5) & 0x3; | ||
| 1092 | params.size = uvec2(12, A + 2); | ||
| 1093 | break; | ||
| 1094 | case 6: | ||
| 1095 | A = (mode >> 5) & 0x3; | ||
| 1096 | params.size = uvec2(A + 2, 12); | ||
| 1097 | break; | ||
| 1098 | case 7: | ||
| 1099 | params.size = uvec2(6, 10); | ||
| 1100 | break; | ||
| 1101 | case 8: | ||
| 1102 | params.size = uvec2(10, 6); | ||
| 1103 | break; | ||
| 1104 | case 9: | ||
| 1105 | A = (mode >> 5) & 0x3; | ||
| 1106 | B = (mode >> 9) & 0x3; | ||
| 1107 | params.size = uvec2(A + 6, B + 6); | ||
| 1108 | break; | ||
| 1109 | default: | ||
| 1110 | params.error_state = true; | ||
| 1111 | break; | ||
| 1112 | } | ||
| 1113 | params.dual_plane = (mode_layout != 9) && ((mode & 0x400) != 0); | ||
| 1114 | uint weight_index = (mode & 0x10) != 0 ? 1 : 0; | ||
| 1115 | if (mode_layout < 5) { | ||
| 1116 | weight_index |= (mode & 0x3) << 1; | ||
| 1117 | } else { | ||
| 1118 | weight_index |= (mode & 0xc) >> 1; | ||
| 1119 | } | ||
| 1120 | weight_index -= 2; | ||
| 1121 | if ((mode_layout != 9) && ((mode & 0x200) != 0)) { | ||
| 1122 | const int max_weights[6] = int[6](9, 11, 15, 19, 23, 31); | ||
| 1123 | params.max_weight = max_weights[weight_index]; | ||
| 1124 | } else { | ||
| 1125 | const int max_weights[6] = int[6](1, 2, 3, 4, 5, 7); | ||
| 1126 | params.max_weight = max_weights[weight_index]; | ||
| 1127 | } | ||
| 1128 | return params; | ||
| 1129 | } | ||
| 1130 | |||
| 1131 | void FillError(ivec3 coord) { | ||
| 1132 | for (uint j = 0; j < block_dims.y; j++) { | ||
| 1133 | for (uint i = 0; i < block_dims.x; i++) { | ||
| 1134 | imageStore(dest_image, coord + ivec3(i, j, 0), vec4(1.0, 1.0, 0.0, 1.0)); | ||
| 1135 | } | ||
| 1136 | } | ||
| 1137 | } | ||
| 1138 | |||
| 1139 | void FillVoidExtentLDR(ivec3 coord) { | ||
| 1140 | StreamBits(52); | ||
| 1141 | uint r_u = StreamBits(16); | ||
| 1142 | uint g_u = StreamBits(16); | ||
| 1143 | uint b_u = StreamBits(16); | ||
| 1144 | uint a_u = StreamBits(16); | ||
| 1145 | float a = float(a_u) / 65535.0f; | ||
| 1146 | float r = float(r_u) / 65535.0f; | ||
| 1147 | float g = float(g_u) / 65535.0f; | ||
| 1148 | float b = float(b_u) / 65535.0f; | ||
| 1149 | for (uint j = 0; j < block_dims.y; j++) { | ||
| 1150 | for (uint i = 0; i < block_dims.x; i++) { | ||
| 1151 | imageStore(dest_image, coord + ivec3(i, j, 0), vec4(r, g, b, a)); | ||
| 1152 | } | ||
| 1153 | } | ||
| 1154 | } | ||
| 1155 | |||
| 1156 | void DecompressBlock(ivec3 coord, uint block_index) { | ||
| 1157 | TexelWeightParams params = DecodeBlockInfo(block_index); | ||
| 1158 | if (params.error_state) { | ||
| 1159 | FillError(coord); | ||
| 1160 | return; | ||
| 1161 | } | ||
| 1162 | if (params.void_extent_hdr) { | ||
| 1163 | FillError(coord); | ||
| 1164 | return; | ||
| 1165 | } | ||
| 1166 | if (params.void_extent_ldr) { | ||
| 1167 | FillVoidExtentLDR(coord); | ||
| 1168 | return; | ||
| 1169 | } | ||
| 1170 | if ((params.size.x > block_dims.x) || (params.size.y > block_dims.y)) { | ||
| 1171 | FillError(coord); | ||
| 1172 | return; | ||
| 1173 | } | ||
| 1174 | uint num_partitions = StreamBits(2) + 1; | ||
| 1175 | if (num_partitions > 4 || (num_partitions == 4 && params.dual_plane)) { | ||
| 1176 | FillError(coord); | ||
| 1177 | return; | ||
| 1178 | } | ||
| 1179 | int plane_index = -1; | ||
| 1180 | uint partition_index = 1; | ||
| 1181 | uvec4 color_endpoint_mode = uvec4(0); | ||
| 1182 | uint ced_pointer = 0; | ||
| 1183 | uint base_cem = 0; | ||
| 1184 | if (num_partitions == 1) { | ||
| 1185 | color_endpoint_mode.x = StreamBits(4); | ||
| 1186 | partition_index = 0; | ||
| 1187 | } else { | ||
| 1188 | partition_index = StreamBits(10); | ||
| 1189 | base_cem = StreamBits(6); | ||
| 1190 | } | ||
| 1191 | uint base_mode = base_cem & 3; | ||
| 1192 | uint weight_bits = GetPackedBitSize(params.size, params.dual_plane, params.max_weight); | ||
| 1193 | uint remaining_bits = 128 - weight_bits - total_bitsread; | ||
| 1194 | uint extra_cem_bits = 0; | ||
| 1195 | if (base_mode > 0) { | ||
| 1196 | switch (num_partitions) { | ||
| 1197 | case 2: | ||
| 1198 | extra_cem_bits += 2; | ||
| 1199 | break; | ||
| 1200 | case 3: | ||
| 1201 | extra_cem_bits += 5; | ||
| 1202 | break; | ||
| 1203 | case 4: | ||
| 1204 | extra_cem_bits += 8; | ||
| 1205 | break; | ||
| 1206 | default: | ||
| 1207 | return; | ||
| 1208 | } | ||
| 1209 | } | ||
| 1210 | remaining_bits -= extra_cem_bits; | ||
| 1211 | uint plane_selector_bits = 0; | ||
| 1212 | if (params.dual_plane) { | ||
| 1213 | plane_selector_bits = 2; | ||
| 1214 | } | ||
| 1215 | remaining_bits -= plane_selector_bits; | ||
| 1216 | if (remaining_bits > 128) { | ||
| 1217 | // Bad data, more remaining bits than 4 bytes | ||
| 1218 | // return early | ||
| 1219 | return; | ||
| 1220 | } | ||
| 1221 | // Read color data... | ||
| 1222 | uint color_data_bits = remaining_bits; | ||
| 1223 | while (remaining_bits > 0) { | ||
| 1224 | int nb = int(min(remaining_bits, 8U)); | ||
| 1225 | uint b = StreamBits(nb); | ||
| 1226 | color_endpoint_data[ced_pointer] = uint(bitfieldExtract(b, 0, nb)); | ||
| 1227 | ++ced_pointer; | ||
| 1228 | remaining_bits -= nb; | ||
| 1229 | } | ||
| 1230 | plane_index = int(StreamBits(plane_selector_bits)); | ||
| 1231 | if (base_mode > 0) { | ||
| 1232 | uint extra_cem = StreamBits(extra_cem_bits); | ||
| 1233 | uint cem = (extra_cem << 6) | base_cem; | ||
| 1234 | cem >>= 2; | ||
| 1235 | uvec4 C = uvec4(0); | ||
| 1236 | for (uint i = 0; i < num_partitions; i++) { | ||
| 1237 | C[i] = (cem & 1); | ||
| 1238 | cem >>= 1; | ||
| 1239 | } | ||
| 1240 | uvec4 M = uvec4(0); | ||
| 1241 | for (uint i = 0; i < num_partitions; i++) { | ||
| 1242 | M[i] = cem & 3; | ||
| 1243 | cem >>= 2; | ||
| 1244 | } | ||
| 1245 | for (uint i = 0; i < num_partitions; i++) { | ||
| 1246 | color_endpoint_mode[i] = base_mode; | ||
| 1247 | if (C[i] == 0) { | ||
| 1248 | --color_endpoint_mode[i]; | ||
| 1249 | } | ||
| 1250 | color_endpoint_mode[i] <<= 2; | ||
| 1251 | color_endpoint_mode[i] |= M[i]; | ||
| 1252 | } | ||
| 1253 | } else if (num_partitions > 1) { | ||
| 1254 | uint cem = base_cem >> 2; | ||
| 1255 | for (uint i = 0; i < num_partitions; i++) { | ||
| 1256 | color_endpoint_mode[i] = cem; | ||
| 1257 | } | ||
| 1258 | } | ||
| 1259 | DecodeColorValues(color_endpoint_mode, num_partitions, color_data_bits); | ||
| 1260 | |||
| 1261 | uvec4 endpoints[4][2]; | ||
| 1262 | for (uint i = 0; i < num_partitions; i++) { | ||
| 1263 | ComputeEndpoints(endpoints[i][0], endpoints[i][1], color_endpoint_mode[i]); | ||
| 1264 | } | ||
| 1265 | |||
| 1266 | for (uint i = 0; i < 16; i++) { | ||
| 1267 | texel_weight_data[i] = local_buff[i]; | ||
| 1268 | } | ||
| 1269 | for (uint i = 0; i < 8; i++) { | ||
| 1270 | #define REVERSE_BYTE(b) ((b * 0x0802U & 0x22110U) | (b * 0x8020U & 0x88440U)) * 0x10101U >> 16 | ||
| 1271 | uint a = REVERSE_BYTE(texel_weight_data[i]); | ||
| 1272 | uint b = REVERSE_BYTE(texel_weight_data[15 - i]); | ||
| 1273 | #undef REVERSE_BYTE | ||
| 1274 | texel_weight_data[i] = uint(bitfieldExtract(b, 0, 8)); | ||
| 1275 | texel_weight_data[15 - i] = uint(bitfieldExtract(a, 0, 8)); | ||
| 1276 | } | ||
| 1277 | uint clear_byte_start = | ||
| 1278 | (GetPackedBitSize(params.size, params.dual_plane, params.max_weight) >> 3) + 1; | ||
| 1279 | texel_weight_data[clear_byte_start - 1] = | ||
| 1280 | texel_weight_data[clear_byte_start - 1] & | ||
| 1281 | uint( | ||
| 1282 | ((1 << (GetPackedBitSize(params.size, params.dual_plane, params.max_weight) % 8)) - 1)); | ||
| 1283 | for (uint i = 0; i < 16 - clear_byte_start; i++) { | ||
| 1284 | texel_weight_data[clear_byte_start + i] = 0U; | ||
| 1285 | } | ||
| 1286 | texel_flag = true; // use texel "vector" and bit stream in integer decoding | ||
| 1287 | DecodeIntegerSequence(params.max_weight, GetNumWeightValues(params.size, params.dual_plane)); | ||
| 1288 | |||
| 1289 | UnquantizeTexelWeights(params.dual_plane, params.size); | ||
| 1290 | |||
| 1291 | for (uint j = 0; j < block_dims.y; j++) { | ||
| 1292 | for (uint i = 0; i < block_dims.x; i++) { | ||
| 1293 | uint local_partition = Select2DPartition(partition_index, i, j, num_partitions, | ||
| 1294 | (block_dims.y * block_dims.x) < 32); | ||
| 1295 | vec4 p; | ||
| 1296 | uvec4 C0 = ReplicateByteTo16(endpoints[local_partition][0]); | ||
| 1297 | uvec4 C1 = ReplicateByteTo16(endpoints[local_partition][1]); | ||
| 1298 | uvec4 plane_vec = uvec4(0); | ||
| 1299 | uvec4 weight_vec = uvec4(0); | ||
| 1300 | for (uint c = 0; c < 4; c++) { | ||
| 1301 | if (params.dual_plane && (((plane_index + 1) & 3) == c)) { | ||
| 1302 | plane_vec[c] = 1; | ||
| 1303 | } | ||
| 1304 | weight_vec[c] = unquantized_texel_weights[plane_vec[c]][j * block_dims.x + i]; | ||
| 1305 | } | ||
| 1306 | vec4 Cf = vec4((C0 * (uvec4(64) - weight_vec) + C1 * weight_vec + uvec4(32)) / 64); | ||
| 1307 | p = (Cf / 65535.0); | ||
| 1308 | imageStore(dest_image, coord + ivec3(i, j, 0), p.gbar); | ||
| 1309 | } | ||
| 1310 | } | ||
| 1311 | } | ||
| 1312 | |||
| 1313 | void main() { | ||
| 1314 | uvec3 pos = gl_GlobalInvocationID; | ||
| 1315 | pos.x <<= bytes_per_block_log2; | ||
| 1316 | |||
| 1317 | // Read as soon as possible due to its latency | ||
| 1318 | const uint swizzle = SwizzleOffset(pos.xy); | ||
| 1319 | |||
| 1320 | const uint block_y = pos.y >> GOB_SIZE_Y_SHIFT; | ||
| 1321 | |||
| 1322 | uint offset = 0; | ||
| 1323 | offset += pos.z * layer_stride; | ||
| 1324 | offset += (block_y >> block_height) * block_size; | ||
| 1325 | offset += (block_y & block_height_mask) << GOB_SIZE_SHIFT; | ||
| 1326 | offset += (pos.x >> GOB_SIZE_X_SHIFT) << x_shift; | ||
| 1327 | offset += swizzle; | ||
| 1328 | |||
| 1329 | const ivec3 coord = ivec3(gl_GlobalInvocationID * uvec3(block_dims, 1)); | ||
| 1330 | uint block_index = | ||
| 1331 | pos.z * gl_WorkGroupSize.x * gl_WorkGroupSize.y + pos.y * gl_WorkGroupSize.x + pos.x; | ||
| 1332 | |||
| 1333 | current_index = 0; | ||
| 1334 | bitsread = 0; | ||
| 1335 | for (int i = 0; i < 16; i++) { | ||
| 1336 | local_buff[i] = ReadTexel(offset + i); | ||
| 1337 | } | ||
| 1338 | DecompressBlock(coord, block_index); | ||
| 1339 | } | ||
diff --git a/src/video_core/host_shaders/source_shader.h.in b/src/video_core/host_shaders/source_shader.h.in index ccdb0d2a9..929dec39b 100644 --- a/src/video_core/host_shaders/source_shader.h.in +++ b/src/video_core/host_shaders/source_shader.h.in | |||
| @@ -4,6 +4,8 @@ | |||
| 4 | 4 | ||
| 5 | namespace HostShaders { | 5 | namespace HostShaders { |
| 6 | 6 | ||
| 7 | constexpr std::string_view @CONTENTS_NAME@ = R"(@CONTENTS@)"; | 7 | constexpr std::string_view @CONTENTS_NAME@ = { |
| 8 | @CONTENTS@ | ||
| 9 | }; | ||
| 8 | 10 | ||
| 9 | } // namespace HostShaders | 11 | } // namespace HostShaders |
diff --git a/src/video_core/macro/macro.cpp b/src/video_core/macro/macro.cpp index cd21a2112..d7fabe605 100644 --- a/src/video_core/macro/macro.cpp +++ b/src/video_core/macro/macro.cpp | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | #include <boost/container_hash/hash.hpp> | 6 | #include <boost/container_hash/hash.hpp> |
| 7 | #include "common/assert.h" | 7 | #include "common/assert.h" |
| 8 | #include "common/logging/log.h" | 8 | #include "common/logging/log.h" |
| 9 | #include "core/settings.h" | 9 | #include "common/settings.h" |
| 10 | #include "video_core/engines/maxwell_3d.h" | 10 | #include "video_core/engines/maxwell_3d.h" |
| 11 | #include "video_core/macro/macro.h" | 11 | #include "video_core/macro/macro.h" |
| 12 | #include "video_core/macro/macro_hle.h" | 12 | #include "video_core/macro/macro_hle.h" |
diff --git a/src/video_core/query_cache.h b/src/video_core/query_cache.h index 203f2af05..aac851253 100644 --- a/src/video_core/query_cache.h +++ b/src/video_core/query_cache.h | |||
| @@ -16,8 +16,8 @@ | |||
| 16 | #include <vector> | 16 | #include <vector> |
| 17 | 17 | ||
| 18 | #include "common/assert.h" | 18 | #include "common/assert.h" |
| 19 | #include "common/settings.h" | ||
| 19 | #include "core/core.h" | 20 | #include "core/core.h" |
| 20 | #include "core/settings.h" | ||
| 21 | #include "video_core/engines/maxwell_3d.h" | 21 | #include "video_core/engines/maxwell_3d.h" |
| 22 | #include "video_core/gpu.h" | 22 | #include "video_core/gpu.h" |
| 23 | #include "video_core/memory_manager.h" | 23 | #include "video_core/memory_manager.h" |
| @@ -208,9 +208,9 @@ public: | |||
| 208 | private: | 208 | private: |
| 209 | /// Flushes a memory range to guest memory and removes it from the cache. | 209 | /// Flushes a memory range to guest memory and removes it from the cache. |
| 210 | void FlushAndRemoveRegion(VAddr addr, std::size_t size) { | 210 | void FlushAndRemoveRegion(VAddr addr, std::size_t size) { |
| 211 | const u64 addr_begin = static_cast<u64>(addr); | 211 | const u64 addr_begin = addr; |
| 212 | const u64 addr_end = addr_begin + static_cast<u64>(size); | 212 | const u64 addr_end = addr_begin + size; |
| 213 | const auto in_range = [addr_begin, addr_end](CachedQuery& query) { | 213 | const auto in_range = [addr_begin, addr_end](const CachedQuery& query) { |
| 214 | const u64 cache_begin = query.GetCpuAddr(); | 214 | const u64 cache_begin = query.GetCpuAddr(); |
| 215 | const u64 cache_end = cache_begin + query.SizeInBytes(); | 215 | const u64 cache_end = cache_begin + query.SizeInBytes(); |
| 216 | return cache_begin < addr_end && addr_begin < cache_end; | 216 | return cache_begin < addr_end && addr_begin < cache_end; |
| @@ -230,8 +230,7 @@ private: | |||
| 230 | rasterizer.UpdatePagesCachedCount(query.GetCpuAddr(), query.SizeInBytes(), -1); | 230 | rasterizer.UpdatePagesCachedCount(query.GetCpuAddr(), query.SizeInBytes(), -1); |
| 231 | query.Flush(); | 231 | query.Flush(); |
| 232 | } | 232 | } |
| 233 | contents.erase(std::remove_if(std::begin(contents), std::end(contents), in_range), | 233 | std::erase_if(contents, in_range); |
| 234 | std::end(contents)); | ||
| 235 | } | 234 | } |
| 236 | } | 235 | } |
| 237 | 236 | ||
diff --git a/src/video_core/renderer_base.cpp b/src/video_core/renderer_base.cpp index a93a1732c..c9a360aaf 100644 --- a/src/video_core/renderer_base.cpp +++ b/src/video_core/renderer_base.cpp | |||
| @@ -3,8 +3,8 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include "common/logging/log.h" | 5 | #include "common/logging/log.h" |
| 6 | #include "common/settings.h" | ||
| 6 | #include "core/frontend/emu_window.h" | 7 | #include "core/frontend/emu_window.h" |
| 7 | #include "core/settings.h" | ||
| 8 | #include "video_core/renderer_base.h" | 8 | #include "video_core/renderer_base.h" |
| 9 | 9 | ||
| 10 | namespace VideoCore { | 10 | namespace VideoCore { |
diff --git a/src/video_core/renderer_opengl/gl_device.cpp b/src/video_core/renderer_opengl/gl_device.cpp index 5776fccdc..b113f54db 100644 --- a/src/video_core/renderer_opengl/gl_device.cpp +++ b/src/video_core/renderer_opengl/gl_device.cpp | |||
| @@ -16,7 +16,7 @@ | |||
| 16 | 16 | ||
| 17 | #include "common/logging/log.h" | 17 | #include "common/logging/log.h" |
| 18 | #include "common/scope_exit.h" | 18 | #include "common/scope_exit.h" |
| 19 | #include "core/settings.h" | 19 | #include "common/settings.h" |
| 20 | #include "video_core/renderer_opengl/gl_device.h" | 20 | #include "video_core/renderer_opengl/gl_device.h" |
| 21 | #include "video_core/renderer_opengl/gl_resource_manager.h" | 21 | #include "video_core/renderer_opengl/gl_resource_manager.h" |
| 22 | 22 | ||
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 4610fd160..0863904e9 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -17,10 +17,10 @@ | |||
| 17 | #include "common/math_util.h" | 17 | #include "common/math_util.h" |
| 18 | #include "common/microprofile.h" | 18 | #include "common/microprofile.h" |
| 19 | #include "common/scope_exit.h" | 19 | #include "common/scope_exit.h" |
| 20 | #include "common/settings.h" | ||
| 20 | #include "core/core.h" | 21 | #include "core/core.h" |
| 21 | #include "core/hle/kernel/process.h" | 22 | #include "core/hle/kernel/process.h" |
| 22 | #include "core/memory.h" | 23 | #include "core/memory.h" |
| 23 | #include "core/settings.h" | ||
| 24 | #include "video_core/engines/kepler_compute.h" | 24 | #include "video_core/engines/kepler_compute.h" |
| 25 | #include "video_core/engines/maxwell_3d.h" | 25 | #include "video_core/engines/maxwell_3d.h" |
| 26 | #include "video_core/engines/shader_type.h" | 26 | #include "video_core/engines/shader_type.h" |
diff --git a/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp b/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp index 955b2abc4..97fb11ac6 100644 --- a/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp | |||
| @@ -12,10 +12,10 @@ | |||
| 12 | #include "common/file_util.h" | 12 | #include "common/file_util.h" |
| 13 | #include "common/logging/log.h" | 13 | #include "common/logging/log.h" |
| 14 | #include "common/scm_rev.h" | 14 | #include "common/scm_rev.h" |
| 15 | #include "common/settings.h" | ||
| 15 | #include "common/zstd_compression.h" | 16 | #include "common/zstd_compression.h" |
| 16 | #include "core/core.h" | 17 | #include "core/core.h" |
| 17 | #include "core/hle/kernel/process.h" | 18 | #include "core/hle/kernel/process.h" |
| 18 | #include "core/settings.h" | ||
| 19 | #include "video_core/engines/shader_type.h" | 19 | #include "video_core/engines/shader_type.h" |
| 20 | #include "video_core/renderer_opengl/gl_shader_cache.h" | 20 | #include "video_core/renderer_opengl/gl_shader_cache.h" |
| 21 | #include "video_core/renderer_opengl/gl_shader_disk_cache.h" | 21 | #include "video_core/renderer_opengl/gl_shader_disk_cache.h" |
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp index e028677e9..623b43d8a 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.cpp +++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp | |||
| @@ -307,7 +307,8 @@ void ApplySwizzle(GLuint handle, PixelFormat format, std::array<SwizzleSource, 4 | |||
| 307 | 307 | ||
| 308 | [[nodiscard]] bool CanBeAccelerated(const TextureCacheRuntime& runtime, | 308 | [[nodiscard]] bool CanBeAccelerated(const TextureCacheRuntime& runtime, |
| 309 | const VideoCommon::ImageInfo& info) { | 309 | const VideoCommon::ImageInfo& info) { |
| 310 | // Disable accelerated uploads for now as they don't implement swizzled uploads | 310 | return !runtime.HasNativeASTC() && IsPixelFormatASTC(info.format); |
| 311 | // Disable other accelerated uploads for now as they don't implement swizzled uploads | ||
| 311 | return false; | 312 | return false; |
| 312 | switch (info.type) { | 313 | switch (info.type) { |
| 313 | case ImageType::e2D: | 314 | case ImageType::e2D: |
| @@ -569,7 +570,11 @@ void TextureCacheRuntime::AccelerateImageUpload(Image& image, const ImageBufferM | |||
| 569 | std::span<const SwizzleParameters> swizzles) { | 570 | std::span<const SwizzleParameters> swizzles) { |
| 570 | switch (image.info.type) { | 571 | switch (image.info.type) { |
| 571 | case ImageType::e2D: | 572 | case ImageType::e2D: |
| 572 | return util_shaders.BlockLinearUpload2D(image, map, swizzles); | 573 | if (IsPixelFormatASTC(image.info.format)) { |
| 574 | return util_shaders.ASTCDecode(image, map, swizzles); | ||
| 575 | } else { | ||
| 576 | return util_shaders.BlockLinearUpload2D(image, map, swizzles); | ||
| 577 | } | ||
| 573 | case ImageType::e3D: | 578 | case ImageType::e3D: |
| 574 | return util_shaders.BlockLinearUpload3D(image, map, swizzles); | 579 | return util_shaders.BlockLinearUpload3D(image, map, swizzles); |
| 575 | case ImageType::Linear: | 580 | case ImageType::Linear: |
| @@ -599,6 +604,10 @@ FormatProperties TextureCacheRuntime::FormatInfo(ImageType type, GLenum internal | |||
| 599 | } | 604 | } |
| 600 | } | 605 | } |
| 601 | 606 | ||
| 607 | bool TextureCacheRuntime::HasNativeASTC() const noexcept { | ||
| 608 | return device.HasASTC(); | ||
| 609 | } | ||
| 610 | |||
| 602 | TextureCacheRuntime::StagingBuffers::StagingBuffers(GLenum storage_flags_, GLenum map_flags_) | 611 | TextureCacheRuntime::StagingBuffers::StagingBuffers(GLenum storage_flags_, GLenum map_flags_) |
| 603 | : storage_flags{storage_flags_}, map_flags{map_flags_} {} | 612 | : storage_flags{storage_flags_}, map_flags{map_flags_} {} |
| 604 | 613 | ||
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.h b/src/video_core/renderer_opengl/gl_texture_cache.h index 3fbaa102f..3c871541b 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.h +++ b/src/video_core/renderer_opengl/gl_texture_cache.h | |||
| @@ -95,6 +95,8 @@ public: | |||
| 95 | return has_broken_texture_view_formats; | 95 | return has_broken_texture_view_formats; |
| 96 | } | 96 | } |
| 97 | 97 | ||
| 98 | bool HasNativeASTC() const noexcept; | ||
| 99 | |||
| 98 | private: | 100 | private: |
| 99 | struct StagingBuffers { | 101 | struct StagingBuffers { |
| 100 | explicit StagingBuffers(GLenum storage_flags_, GLenum map_flags_); | 102 | explicit StagingBuffers(GLenum storage_flags_, GLenum map_flags_); |
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index 9d2acd4d9..cc2e499f9 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp | |||
| @@ -13,13 +13,13 @@ | |||
| 13 | #include "common/assert.h" | 13 | #include "common/assert.h" |
| 14 | #include "common/logging/log.h" | 14 | #include "common/logging/log.h" |
| 15 | #include "common/microprofile.h" | 15 | #include "common/microprofile.h" |
| 16 | #include "common/settings.h" | ||
| 16 | #include "common/telemetry.h" | 17 | #include "common/telemetry.h" |
| 17 | #include "core/core.h" | 18 | #include "core/core.h" |
| 18 | #include "core/core_timing.h" | 19 | #include "core/core_timing.h" |
| 19 | #include "core/frontend/emu_window.h" | 20 | #include "core/frontend/emu_window.h" |
| 20 | #include "core/memory.h" | 21 | #include "core/memory.h" |
| 21 | #include "core/perf_stats.h" | 22 | #include "core/perf_stats.h" |
| 22 | #include "core/settings.h" | ||
| 23 | #include "core/telemetry_session.h" | 23 | #include "core/telemetry_session.h" |
| 24 | #include "video_core/host_shaders/opengl_present_frag.h" | 24 | #include "video_core/host_shaders/opengl_present_frag.h" |
| 25 | #include "video_core/host_shaders/opengl_present_vert.h" | 25 | #include "video_core/host_shaders/opengl_present_vert.h" |
diff --git a/src/video_core/renderer_opengl/util_shaders.cpp b/src/video_core/renderer_opengl/util_shaders.cpp index 2fe4799bc..47fddcb6e 100644 --- a/src/video_core/renderer_opengl/util_shaders.cpp +++ b/src/video_core/renderer_opengl/util_shaders.cpp | |||
| @@ -2,7 +2,6 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <bit> | ||
| 6 | #include <span> | 5 | #include <span> |
| 7 | #include <string_view> | 6 | #include <string_view> |
| 8 | 7 | ||
| @@ -11,6 +10,7 @@ | |||
| 11 | #include "common/assert.h" | 10 | #include "common/assert.h" |
| 12 | #include "common/common_types.h" | 11 | #include "common/common_types.h" |
| 13 | #include "common/div_ceil.h" | 12 | #include "common/div_ceil.h" |
| 13 | #include "video_core/host_shaders/astc_decoder_comp.h" | ||
| 14 | #include "video_core/host_shaders/block_linear_unswizzle_2d_comp.h" | 14 | #include "video_core/host_shaders/block_linear_unswizzle_2d_comp.h" |
| 15 | #include "video_core/host_shaders/block_linear_unswizzle_3d_comp.h" | 15 | #include "video_core/host_shaders/block_linear_unswizzle_3d_comp.h" |
| 16 | #include "video_core/host_shaders/opengl_copy_bc4_comp.h" | 16 | #include "video_core/host_shaders/opengl_copy_bc4_comp.h" |
| @@ -20,16 +20,18 @@ | |||
| 20 | #include "video_core/renderer_opengl/gl_shader_manager.h" | 20 | #include "video_core/renderer_opengl/gl_shader_manager.h" |
| 21 | #include "video_core/renderer_opengl/gl_texture_cache.h" | 21 | #include "video_core/renderer_opengl/gl_texture_cache.h" |
| 22 | #include "video_core/renderer_opengl/util_shaders.h" | 22 | #include "video_core/renderer_opengl/util_shaders.h" |
| 23 | #include "video_core/surface.h" | ||
| 24 | #include "video_core/texture_cache/accelerated_swizzle.h" | 23 | #include "video_core/texture_cache/accelerated_swizzle.h" |
| 25 | #include "video_core/texture_cache/types.h" | 24 | #include "video_core/texture_cache/types.h" |
| 26 | #include "video_core/texture_cache/util.h" | 25 | #include "video_core/texture_cache/util.h" |
| 26 | #include "video_core/textures/astc.h" | ||
| 27 | #include "video_core/textures/decoders.h" | 27 | #include "video_core/textures/decoders.h" |
| 28 | 28 | ||
| 29 | namespace OpenGL { | 29 | namespace OpenGL { |
| 30 | 30 | ||
| 31 | using namespace HostShaders; | 31 | using namespace HostShaders; |
| 32 | using namespace Tegra::Texture::ASTC; | ||
| 32 | 33 | ||
| 34 | using VideoCommon::Extent2D; | ||
| 33 | using VideoCommon::Extent3D; | 35 | using VideoCommon::Extent3D; |
| 34 | using VideoCommon::ImageCopy; | 36 | using VideoCommon::ImageCopy; |
| 35 | using VideoCommon::ImageType; | 37 | using VideoCommon::ImageType; |
| @@ -57,7 +59,7 @@ size_t NumPixelsInCopy(const VideoCommon::ImageCopy& copy) { | |||
| 57 | } // Anonymous namespace | 59 | } // Anonymous namespace |
| 58 | 60 | ||
| 59 | UtilShaders::UtilShaders(ProgramManager& program_manager_) | 61 | UtilShaders::UtilShaders(ProgramManager& program_manager_) |
| 60 | : program_manager{program_manager_}, | 62 | : program_manager{program_manager_}, astc_decoder_program(MakeProgram(ASTC_DECODER_COMP)), |
| 61 | block_linear_unswizzle_2d_program(MakeProgram(BLOCK_LINEAR_UNSWIZZLE_2D_COMP)), | 63 | block_linear_unswizzle_2d_program(MakeProgram(BLOCK_LINEAR_UNSWIZZLE_2D_COMP)), |
| 62 | block_linear_unswizzle_3d_program(MakeProgram(BLOCK_LINEAR_UNSWIZZLE_3D_COMP)), | 64 | block_linear_unswizzle_3d_program(MakeProgram(BLOCK_LINEAR_UNSWIZZLE_3D_COMP)), |
| 63 | pitch_unswizzle_program(MakeProgram(PITCH_UNSWIZZLE_COMP)), | 65 | pitch_unswizzle_program(MakeProgram(PITCH_UNSWIZZLE_COMP)), |
| @@ -65,11 +67,79 @@ UtilShaders::UtilShaders(ProgramManager& program_manager_) | |||
| 65 | copy_bc4_program(MakeProgram(OPENGL_COPY_BC4_COMP)) { | 67 | copy_bc4_program(MakeProgram(OPENGL_COPY_BC4_COMP)) { |
| 66 | const auto swizzle_table = Tegra::Texture::MakeSwizzleTable(); | 68 | const auto swizzle_table = Tegra::Texture::MakeSwizzleTable(); |
| 67 | swizzle_table_buffer.Create(); | 69 | swizzle_table_buffer.Create(); |
| 70 | astc_buffer.Create(); | ||
| 68 | glNamedBufferStorage(swizzle_table_buffer.handle, sizeof(swizzle_table), &swizzle_table, 0); | 71 | glNamedBufferStorage(swizzle_table_buffer.handle, sizeof(swizzle_table), &swizzle_table, 0); |
| 72 | glNamedBufferStorage(astc_buffer.handle, sizeof(ASTC_BUFFER_DATA), &ASTC_BUFFER_DATA, 0); | ||
| 69 | } | 73 | } |
| 70 | 74 | ||
| 71 | UtilShaders::~UtilShaders() = default; | 75 | UtilShaders::~UtilShaders() = default; |
| 72 | 76 | ||
| 77 | void UtilShaders::ASTCDecode(Image& image, const ImageBufferMap& map, | ||
| 78 | std::span<const VideoCommon::SwizzleParameters> swizzles) { | ||
| 79 | static constexpr GLuint BINDING_SWIZZLE_BUFFER = 0; | ||
| 80 | static constexpr GLuint BINDING_INPUT_BUFFER = 1; | ||
| 81 | static constexpr GLuint BINDING_ENC_BUFFER = 2; | ||
| 82 | |||
| 83 | static constexpr GLuint BINDING_6_TO_8_BUFFER = 3; | ||
| 84 | static constexpr GLuint BINDING_7_TO_8_BUFFER = 4; | ||
| 85 | static constexpr GLuint BINDING_8_TO_8_BUFFER = 5; | ||
| 86 | static constexpr GLuint BINDING_BYTE_TO_16_BUFFER = 6; | ||
| 87 | |||
| 88 | static constexpr GLuint BINDING_OUTPUT_IMAGE = 0; | ||
| 89 | |||
| 90 | const Extent2D tile_size{ | ||
| 91 | .width = VideoCore::Surface::DefaultBlockWidth(image.info.format), | ||
| 92 | .height = VideoCore::Surface::DefaultBlockHeight(image.info.format), | ||
| 93 | }; | ||
| 94 | program_manager.BindHostCompute(astc_decoder_program.handle); | ||
| 95 | glBindBufferBase(GL_SHADER_STORAGE_BUFFER, BINDING_SWIZZLE_BUFFER, swizzle_table_buffer.handle); | ||
| 96 | glBindBufferRange(GL_SHADER_STORAGE_BUFFER, BINDING_ENC_BUFFER, astc_buffer.handle, | ||
| 97 | offsetof(AstcBufferData, encoding_values), | ||
| 98 | sizeof(AstcBufferData::encoding_values)); | ||
| 99 | glBindBufferRange(GL_SHADER_STORAGE_BUFFER, BINDING_6_TO_8_BUFFER, astc_buffer.handle, | ||
| 100 | offsetof(AstcBufferData, replicate_6_to_8), | ||
| 101 | sizeof(AstcBufferData::replicate_6_to_8)); | ||
| 102 | glBindBufferRange(GL_SHADER_STORAGE_BUFFER, BINDING_7_TO_8_BUFFER, astc_buffer.handle, | ||
| 103 | offsetof(AstcBufferData, replicate_7_to_8), | ||
| 104 | sizeof(AstcBufferData::replicate_7_to_8)); | ||
| 105 | glBindBufferRange(GL_SHADER_STORAGE_BUFFER, BINDING_8_TO_8_BUFFER, astc_buffer.handle, | ||
| 106 | offsetof(AstcBufferData, replicate_8_to_8), | ||
| 107 | sizeof(AstcBufferData::replicate_8_to_8)); | ||
| 108 | glBindBufferRange(GL_SHADER_STORAGE_BUFFER, BINDING_BYTE_TO_16_BUFFER, astc_buffer.handle, | ||
| 109 | offsetof(AstcBufferData, replicate_byte_to_16), | ||
| 110 | sizeof(AstcBufferData::replicate_byte_to_16)); | ||
| 111 | |||
| 112 | glFlushMappedNamedBufferRange(map.buffer, map.offset, image.guest_size_bytes); | ||
| 113 | glUniform2ui(1, tile_size.width, tile_size.height); | ||
| 114 | // Ensure buffer data is valid before dispatching | ||
| 115 | glFlush(); | ||
| 116 | for (const SwizzleParameters& swizzle : swizzles) { | ||
| 117 | const size_t input_offset = swizzle.buffer_offset + map.offset; | ||
| 118 | const u32 num_dispatches_x = Common::DivCeil(swizzle.num_tiles.width, 32U); | ||
| 119 | const u32 num_dispatches_y = Common::DivCeil(swizzle.num_tiles.height, 32U); | ||
| 120 | |||
| 121 | const auto params = MakeBlockLinearSwizzle2DParams(swizzle, image.info); | ||
| 122 | ASSERT(params.origin == (std::array<u32, 3>{0, 0, 0})); | ||
| 123 | ASSERT(params.destination == (std::array<s32, 3>{0, 0, 0})); | ||
| 124 | |||
| 125 | glUniform1ui(2, params.bytes_per_block_log2); | ||
| 126 | glUniform1ui(3, params.layer_stride); | ||
| 127 | glUniform1ui(4, params.block_size); | ||
| 128 | glUniform1ui(5, params.x_shift); | ||
| 129 | glUniform1ui(6, params.block_height); | ||
| 130 | glUniform1ui(7, params.block_height_mask); | ||
| 131 | |||
| 132 | glBindImageTexture(BINDING_OUTPUT_IMAGE, image.StorageHandle(), swizzle.level, GL_TRUE, 0, | ||
| 133 | GL_WRITE_ONLY, GL_RGBA8); | ||
| 134 | // ASTC texture data | ||
| 135 | glBindBufferRange(GL_SHADER_STORAGE_BUFFER, BINDING_INPUT_BUFFER, map.buffer, input_offset, | ||
| 136 | image.guest_size_bytes - swizzle.buffer_offset); | ||
| 137 | |||
| 138 | glDispatchCompute(num_dispatches_x, num_dispatches_y, image.info.resources.layers); | ||
| 139 | } | ||
| 140 | program_manager.RestoreGuestCompute(); | ||
| 141 | } | ||
| 142 | |||
| 73 | void UtilShaders::BlockLinearUpload2D(Image& image, const ImageBufferMap& map, | 143 | void UtilShaders::BlockLinearUpload2D(Image& image, const ImageBufferMap& map, |
| 74 | std::span<const SwizzleParameters> swizzles) { | 144 | std::span<const SwizzleParameters> swizzles) { |
| 75 | static constexpr Extent3D WORKGROUP_SIZE{32, 32, 1}; | 145 | static constexpr Extent3D WORKGROUP_SIZE{32, 32, 1}; |
diff --git a/src/video_core/renderer_opengl/util_shaders.h b/src/video_core/renderer_opengl/util_shaders.h index 93b009743..53d65f368 100644 --- a/src/video_core/renderer_opengl/util_shaders.h +++ b/src/video_core/renderer_opengl/util_shaders.h | |||
| @@ -40,6 +40,9 @@ public: | |||
| 40 | explicit UtilShaders(ProgramManager& program_manager); | 40 | explicit UtilShaders(ProgramManager& program_manager); |
| 41 | ~UtilShaders(); | 41 | ~UtilShaders(); |
| 42 | 42 | ||
| 43 | void ASTCDecode(Image& image, const ImageBufferMap& map, | ||
| 44 | std::span<const VideoCommon::SwizzleParameters> swizzles); | ||
| 45 | |||
| 43 | void BlockLinearUpload2D(Image& image, const ImageBufferMap& map, | 46 | void BlockLinearUpload2D(Image& image, const ImageBufferMap& map, |
| 44 | std::span<const VideoCommon::SwizzleParameters> swizzles); | 47 | std::span<const VideoCommon::SwizzleParameters> swizzles); |
| 45 | 48 | ||
| @@ -59,7 +62,9 @@ private: | |||
| 59 | ProgramManager& program_manager; | 62 | ProgramManager& program_manager; |
| 60 | 63 | ||
| 61 | OGLBuffer swizzle_table_buffer; | 64 | OGLBuffer swizzle_table_buffer; |
| 65 | OGLBuffer astc_buffer; | ||
| 62 | 66 | ||
| 67 | OGLProgram astc_decoder_program; | ||
| 63 | OGLProgram block_linear_unswizzle_2d_program; | 68 | OGLProgram block_linear_unswizzle_2d_program; |
| 64 | OGLProgram block_linear_unswizzle_3d_program; | 69 | OGLProgram block_linear_unswizzle_3d_program; |
| 65 | OGLProgram pitch_unswizzle_program; | 70 | OGLProgram pitch_unswizzle_program; |
diff --git a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp index 19aaf034f..f088447e9 100644 --- a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp +++ b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp | |||
| @@ -166,7 +166,7 @@ struct FormatTuple { | |||
| 166 | {VK_FORMAT_R16G16_SINT, Attachable | Storage}, // R16G16_SINT | 166 | {VK_FORMAT_R16G16_SINT, Attachable | Storage}, // R16G16_SINT |
| 167 | {VK_FORMAT_R16G16_SNORM, Attachable | Storage}, // R16G16_SNORM | 167 | {VK_FORMAT_R16G16_SNORM, Attachable | Storage}, // R16G16_SNORM |
| 168 | {VK_FORMAT_UNDEFINED}, // R32G32B32_FLOAT | 168 | {VK_FORMAT_UNDEFINED}, // R32G32B32_FLOAT |
| 169 | {VK_FORMAT_R8G8B8A8_SRGB, Attachable}, // A8B8G8R8_SRGB | 169 | {VK_FORMAT_A8B8G8R8_SRGB_PACK32, Attachable}, // A8B8G8R8_SRGB |
| 170 | {VK_FORMAT_R8G8_UNORM, Attachable | Storage}, // R8G8_UNORM | 170 | {VK_FORMAT_R8G8_UNORM, Attachable | Storage}, // R8G8_UNORM |
| 171 | {VK_FORMAT_R8G8_SNORM, Attachable | Storage}, // R8G8_SNORM | 171 | {VK_FORMAT_R8G8_SNORM, Attachable | Storage}, // R8G8_SNORM |
| 172 | {VK_FORMAT_R8G8_SINT, Attachable | Storage}, // R8G8_SINT | 172 | {VK_FORMAT_R8G8_SINT, Attachable | Storage}, // R8G8_SINT |
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index 1cc720ddd..2e0cf4232 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp | |||
| @@ -13,11 +13,11 @@ | |||
| 13 | #include <fmt/format.h> | 13 | #include <fmt/format.h> |
| 14 | 14 | ||
| 15 | #include "common/logging/log.h" | 15 | #include "common/logging/log.h" |
| 16 | #include "common/settings.h" | ||
| 16 | #include "common/telemetry.h" | 17 | #include "common/telemetry.h" |
| 17 | #include "core/core.h" | 18 | #include "core/core.h" |
| 18 | #include "core/core_timing.h" | 19 | #include "core/core_timing.h" |
| 19 | #include "core/frontend/emu_window.h" | 20 | #include "core/frontend/emu_window.h" |
| 20 | #include "core/settings.h" | ||
| 21 | #include "core/telemetry_session.h" | 21 | #include "core/telemetry_session.h" |
| 22 | #include "video_core/gpu.h" | 22 | #include "video_core/gpu.h" |
| 23 | #include "video_core/renderer_vulkan/renderer_vulkan.h" | 23 | #include "video_core/renderer_vulkan/renderer_vulkan.h" |
| @@ -143,7 +143,10 @@ void RendererVulkan::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) { | |||
| 143 | 143 | ||
| 144 | scheduler.WaitWorker(); | 144 | scheduler.WaitWorker(); |
| 145 | 145 | ||
| 146 | swapchain.AcquireNextImage(); | 146 | while (!swapchain.AcquireNextImage()) { |
| 147 | swapchain.Create(layout.width, layout.height, is_srgb); | ||
| 148 | blit_screen.Recreate(); | ||
| 149 | } | ||
| 147 | const VkSemaphore render_semaphore = blit_screen.Draw(*framebuffer, use_accelerated); | 150 | const VkSemaphore render_semaphore = blit_screen.Draw(*framebuffer, use_accelerated); |
| 148 | 151 | ||
| 149 | scheduler.Flush(render_semaphore); | 152 | scheduler.Flush(render_semaphore); |
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp index 668633e7b..8cb65e588 100644 --- a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp | |||
| @@ -176,7 +176,7 @@ void BufferCacheRuntime::BindVertexBuffer(u32 index, VkBuffer buffer, u32 offset | |||
| 176 | u32 stride) { | 176 | u32 stride) { |
| 177 | if (device.IsExtExtendedDynamicStateSupported()) { | 177 | if (device.IsExtExtendedDynamicStateSupported()) { |
| 178 | scheduler.Record([index, buffer, offset, size, stride](vk::CommandBuffer cmdbuf) { | 178 | scheduler.Record([index, buffer, offset, size, stride](vk::CommandBuffer cmdbuf) { |
| 179 | const VkDeviceSize vk_offset = offset; | 179 | const VkDeviceSize vk_offset = buffer != VK_NULL_HANDLE ? offset : 0; |
| 180 | const VkDeviceSize vk_size = buffer != VK_NULL_HANDLE ? size : VK_WHOLE_SIZE; | 180 | const VkDeviceSize vk_size = buffer != VK_NULL_HANDLE ? size : VK_WHOLE_SIZE; |
| 181 | const VkDeviceSize vk_stride = stride; | 181 | const VkDeviceSize vk_stride = stride; |
| 182 | cmdbuf.BindVertexBuffers2EXT(index, 1, &buffer, &vk_offset, &vk_size, &vk_stride); | 182 | cmdbuf.BindVertexBuffers2EXT(index, 1, &buffer, &vk_offset, &vk_size, &vk_stride); |
diff --git a/src/video_core/renderer_vulkan/vk_compute_pass.cpp b/src/video_core/renderer_vulkan/vk_compute_pass.cpp index 2f9a7b028..e11406e58 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pass.cpp +++ b/src/video_core/renderer_vulkan/vk_compute_pass.cpp | |||
| @@ -11,18 +11,39 @@ | |||
| 11 | #include "common/assert.h" | 11 | #include "common/assert.h" |
| 12 | #include "common/common_types.h" | 12 | #include "common/common_types.h" |
| 13 | #include "common/div_ceil.h" | 13 | #include "common/div_ceil.h" |
| 14 | #include "video_core/host_shaders/astc_decoder_comp_spv.h" | ||
| 14 | #include "video_core/host_shaders/vulkan_quad_indexed_comp_spv.h" | 15 | #include "video_core/host_shaders/vulkan_quad_indexed_comp_spv.h" |
| 15 | #include "video_core/host_shaders/vulkan_uint8_comp_spv.h" | 16 | #include "video_core/host_shaders/vulkan_uint8_comp_spv.h" |
| 16 | #include "video_core/renderer_vulkan/vk_compute_pass.h" | 17 | #include "video_core/renderer_vulkan/vk_compute_pass.h" |
| 17 | #include "video_core/renderer_vulkan/vk_descriptor_pool.h" | 18 | #include "video_core/renderer_vulkan/vk_descriptor_pool.h" |
| 18 | #include "video_core/renderer_vulkan/vk_scheduler.h" | 19 | #include "video_core/renderer_vulkan/vk_scheduler.h" |
| 19 | #include "video_core/renderer_vulkan/vk_staging_buffer_pool.h" | 20 | #include "video_core/renderer_vulkan/vk_staging_buffer_pool.h" |
| 21 | #include "video_core/renderer_vulkan/vk_texture_cache.h" | ||
| 20 | #include "video_core/renderer_vulkan/vk_update_descriptor.h" | 22 | #include "video_core/renderer_vulkan/vk_update_descriptor.h" |
| 23 | #include "video_core/texture_cache/accelerated_swizzle.h" | ||
| 24 | #include "video_core/texture_cache/types.h" | ||
| 25 | #include "video_core/textures/astc.h" | ||
| 26 | #include "video_core/textures/decoders.h" | ||
| 21 | #include "video_core/vulkan_common/vulkan_device.h" | 27 | #include "video_core/vulkan_common/vulkan_device.h" |
| 22 | #include "video_core/vulkan_common/vulkan_wrapper.h" | 28 | #include "video_core/vulkan_common/vulkan_wrapper.h" |
| 23 | 29 | ||
| 24 | namespace Vulkan { | 30 | namespace Vulkan { |
| 31 | |||
| 32 | using Tegra::Texture::SWIZZLE_TABLE; | ||
| 33 | using Tegra::Texture::ASTC::EncodingsValues; | ||
| 34 | using namespace Tegra::Texture::ASTC; | ||
| 35 | |||
| 25 | namespace { | 36 | namespace { |
| 37 | |||
| 38 | constexpr u32 ASTC_BINDING_INPUT_BUFFER = 0; | ||
| 39 | constexpr u32 ASTC_BINDING_ENC_BUFFER = 1; | ||
| 40 | constexpr u32 ASTC_BINDING_6_TO_8_BUFFER = 2; | ||
| 41 | constexpr u32 ASTC_BINDING_7_TO_8_BUFFER = 3; | ||
| 42 | constexpr u32 ASTC_BINDING_8_TO_8_BUFFER = 4; | ||
| 43 | constexpr u32 ASTC_BINDING_BYTE_TO_16_BUFFER = 5; | ||
| 44 | constexpr u32 ASTC_BINDING_SWIZZLE_BUFFER = 6; | ||
| 45 | constexpr u32 ASTC_BINDING_OUTPUT_IMAGE = 7; | ||
| 46 | |||
| 26 | VkPushConstantRange BuildComputePushConstantRange(std::size_t size) { | 47 | VkPushConstantRange BuildComputePushConstantRange(std::size_t size) { |
| 27 | return { | 48 | return { |
| 28 | .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT, | 49 | .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT, |
| @@ -50,6 +71,67 @@ std::array<VkDescriptorSetLayoutBinding, 2> BuildInputOutputDescriptorSetBinding | |||
| 50 | }}; | 71 | }}; |
| 51 | } | 72 | } |
| 52 | 73 | ||
| 74 | std::array<VkDescriptorSetLayoutBinding, 8> BuildASTCDescriptorSetBindings() { | ||
| 75 | return {{ | ||
| 76 | { | ||
| 77 | .binding = ASTC_BINDING_INPUT_BUFFER, | ||
| 78 | .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, | ||
| 79 | .descriptorCount = 1, | ||
| 80 | .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT, | ||
| 81 | .pImmutableSamplers = nullptr, | ||
| 82 | }, | ||
| 83 | { | ||
| 84 | .binding = ASTC_BINDING_ENC_BUFFER, | ||
| 85 | .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, | ||
| 86 | .descriptorCount = 1, | ||
| 87 | .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT, | ||
| 88 | .pImmutableSamplers = nullptr, | ||
| 89 | }, | ||
| 90 | { | ||
| 91 | .binding = ASTC_BINDING_6_TO_8_BUFFER, | ||
| 92 | .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, | ||
| 93 | .descriptorCount = 1, | ||
| 94 | .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT, | ||
| 95 | .pImmutableSamplers = nullptr, | ||
| 96 | }, | ||
| 97 | { | ||
| 98 | .binding = ASTC_BINDING_7_TO_8_BUFFER, | ||
| 99 | .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, | ||
| 100 | .descriptorCount = 1, | ||
| 101 | .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT, | ||
| 102 | .pImmutableSamplers = nullptr, | ||
| 103 | }, | ||
| 104 | { | ||
| 105 | .binding = ASTC_BINDING_8_TO_8_BUFFER, | ||
| 106 | .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, | ||
| 107 | .descriptorCount = 1, | ||
| 108 | .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT, | ||
| 109 | .pImmutableSamplers = nullptr, | ||
| 110 | }, | ||
| 111 | { | ||
| 112 | .binding = ASTC_BINDING_BYTE_TO_16_BUFFER, | ||
| 113 | .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, | ||
| 114 | .descriptorCount = 1, | ||
| 115 | .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT, | ||
| 116 | .pImmutableSamplers = nullptr, | ||
| 117 | }, | ||
| 118 | { | ||
| 119 | .binding = ASTC_BINDING_SWIZZLE_BUFFER, | ||
| 120 | .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, | ||
| 121 | .descriptorCount = 1, | ||
| 122 | .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT, | ||
| 123 | .pImmutableSamplers = nullptr, | ||
| 124 | }, | ||
| 125 | { | ||
| 126 | .binding = ASTC_BINDING_OUTPUT_IMAGE, | ||
| 127 | .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, | ||
| 128 | .descriptorCount = 1, | ||
| 129 | .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT, | ||
| 130 | .pImmutableSamplers = nullptr, | ||
| 131 | }, | ||
| 132 | }}; | ||
| 133 | } | ||
| 134 | |||
| 53 | VkDescriptorUpdateTemplateEntryKHR BuildInputOutputDescriptorUpdateTemplate() { | 135 | VkDescriptorUpdateTemplateEntryKHR BuildInputOutputDescriptorUpdateTemplate() { |
| 54 | return { | 136 | return { |
| 55 | .dstBinding = 0, | 137 | .dstBinding = 0, |
| @@ -61,6 +143,94 @@ VkDescriptorUpdateTemplateEntryKHR BuildInputOutputDescriptorUpdateTemplate() { | |||
| 61 | }; | 143 | }; |
| 62 | } | 144 | } |
| 63 | 145 | ||
| 146 | std::array<VkDescriptorUpdateTemplateEntryKHR, 8> BuildASTCPassDescriptorUpdateTemplateEntry() { | ||
| 147 | return {{ | ||
| 148 | { | ||
| 149 | .dstBinding = ASTC_BINDING_INPUT_BUFFER, | ||
| 150 | .dstArrayElement = 0, | ||
| 151 | .descriptorCount = 1, | ||
| 152 | .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, | ||
| 153 | .offset = ASTC_BINDING_INPUT_BUFFER * sizeof(DescriptorUpdateEntry), | ||
| 154 | .stride = sizeof(DescriptorUpdateEntry), | ||
| 155 | }, | ||
| 156 | { | ||
| 157 | .dstBinding = ASTC_BINDING_ENC_BUFFER, | ||
| 158 | .dstArrayElement = 0, | ||
| 159 | .descriptorCount = 1, | ||
| 160 | .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, | ||
| 161 | .offset = ASTC_BINDING_ENC_BUFFER * sizeof(DescriptorUpdateEntry), | ||
| 162 | .stride = sizeof(DescriptorUpdateEntry), | ||
| 163 | }, | ||
| 164 | { | ||
| 165 | .dstBinding = ASTC_BINDING_6_TO_8_BUFFER, | ||
| 166 | .dstArrayElement = 0, | ||
| 167 | .descriptorCount = 1, | ||
| 168 | .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, | ||
| 169 | .offset = ASTC_BINDING_6_TO_8_BUFFER * sizeof(DescriptorUpdateEntry), | ||
| 170 | .stride = sizeof(DescriptorUpdateEntry), | ||
| 171 | }, | ||
| 172 | { | ||
| 173 | .dstBinding = ASTC_BINDING_7_TO_8_BUFFER, | ||
| 174 | .dstArrayElement = 0, | ||
| 175 | .descriptorCount = 1, | ||
| 176 | .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, | ||
| 177 | .offset = ASTC_BINDING_7_TO_8_BUFFER * sizeof(DescriptorUpdateEntry), | ||
| 178 | .stride = sizeof(DescriptorUpdateEntry), | ||
| 179 | }, | ||
| 180 | { | ||
| 181 | .dstBinding = ASTC_BINDING_8_TO_8_BUFFER, | ||
| 182 | .dstArrayElement = 0, | ||
| 183 | .descriptorCount = 1, | ||
| 184 | .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, | ||
| 185 | .offset = ASTC_BINDING_8_TO_8_BUFFER * sizeof(DescriptorUpdateEntry), | ||
| 186 | .stride = sizeof(DescriptorUpdateEntry), | ||
| 187 | }, | ||
| 188 | { | ||
| 189 | .dstBinding = ASTC_BINDING_BYTE_TO_16_BUFFER, | ||
| 190 | .dstArrayElement = 0, | ||
| 191 | .descriptorCount = 1, | ||
| 192 | .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, | ||
| 193 | .offset = ASTC_BINDING_BYTE_TO_16_BUFFER * sizeof(DescriptorUpdateEntry), | ||
| 194 | .stride = sizeof(DescriptorUpdateEntry), | ||
| 195 | }, | ||
| 196 | { | ||
| 197 | .dstBinding = ASTC_BINDING_SWIZZLE_BUFFER, | ||
| 198 | .dstArrayElement = 0, | ||
| 199 | .descriptorCount = 1, | ||
| 200 | .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, | ||
| 201 | .offset = ASTC_BINDING_SWIZZLE_BUFFER * sizeof(DescriptorUpdateEntry), | ||
| 202 | .stride = sizeof(DescriptorUpdateEntry), | ||
| 203 | }, | ||
| 204 | { | ||
| 205 | .dstBinding = ASTC_BINDING_OUTPUT_IMAGE, | ||
| 206 | .dstArrayElement = 0, | ||
| 207 | .descriptorCount = 1, | ||
| 208 | .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, | ||
| 209 | .offset = ASTC_BINDING_OUTPUT_IMAGE * sizeof(DescriptorUpdateEntry), | ||
| 210 | .stride = sizeof(DescriptorUpdateEntry), | ||
| 211 | }, | ||
| 212 | }}; | ||
| 213 | } | ||
| 214 | |||
| 215 | struct AstcPushConstants { | ||
| 216 | std::array<u32, 2> blocks_dims; | ||
| 217 | u32 bytes_per_block_log2; | ||
| 218 | u32 layer_stride; | ||
| 219 | u32 block_size; | ||
| 220 | u32 x_shift; | ||
| 221 | u32 block_height; | ||
| 222 | u32 block_height_mask; | ||
| 223 | }; | ||
| 224 | |||
| 225 | struct AstcBufferData { | ||
| 226 | decltype(SWIZZLE_TABLE) swizzle_table_buffer = SWIZZLE_TABLE; | ||
| 227 | decltype(EncodingsValues) encoding_values = EncodingsValues; | ||
| 228 | decltype(REPLICATE_6_BIT_TO_8_TABLE) replicate_6_to_8 = REPLICATE_6_BIT_TO_8_TABLE; | ||
| 229 | decltype(REPLICATE_7_BIT_TO_8_TABLE) replicate_7_to_8 = REPLICATE_7_BIT_TO_8_TABLE; | ||
| 230 | decltype(REPLICATE_8_BIT_TO_8_TABLE) replicate_8_to_8 = REPLICATE_8_BIT_TO_8_TABLE; | ||
| 231 | decltype(REPLICATE_BYTE_TO_16_TABLE) replicate_byte_to_16 = REPLICATE_BYTE_TO_16_TABLE; | ||
| 232 | } constexpr ASTC_BUFFER_DATA; | ||
| 233 | |||
| 64 | } // Anonymous namespace | 234 | } // Anonymous namespace |
| 65 | 235 | ||
| 66 | VKComputePass::VKComputePass(const Device& device, VKDescriptorPool& descriptor_pool, | 236 | VKComputePass::VKComputePass(const Device& device, VKDescriptorPool& descriptor_pool, |
| @@ -238,4 +408,167 @@ std::pair<VkBuffer, VkDeviceSize> QuadIndexedPass::Assemble( | |||
| 238 | return {staging.buffer, staging.offset}; | 408 | return {staging.buffer, staging.offset}; |
| 239 | } | 409 | } |
| 240 | 410 | ||
| 411 | ASTCDecoderPass::ASTCDecoderPass(const Device& device_, VKScheduler& scheduler_, | ||
| 412 | VKDescriptorPool& descriptor_pool_, | ||
| 413 | StagingBufferPool& staging_buffer_pool_, | ||
| 414 | VKUpdateDescriptorQueue& update_descriptor_queue_, | ||
| 415 | MemoryAllocator& memory_allocator_) | ||
| 416 | : VKComputePass(device_, descriptor_pool_, BuildASTCDescriptorSetBindings(), | ||
| 417 | BuildASTCPassDescriptorUpdateTemplateEntry(), | ||
| 418 | BuildComputePushConstantRange(sizeof(AstcPushConstants)), | ||
| 419 | ASTC_DECODER_COMP_SPV), | ||
| 420 | device{device_}, scheduler{scheduler_}, staging_buffer_pool{staging_buffer_pool_}, | ||
| 421 | update_descriptor_queue{update_descriptor_queue_}, memory_allocator{memory_allocator_} {} | ||
| 422 | |||
| 423 | ASTCDecoderPass::~ASTCDecoderPass() = default; | ||
| 424 | |||
| 425 | void ASTCDecoderPass::MakeDataBuffer() { | ||
| 426 | constexpr size_t TOTAL_BUFFER_SIZE = sizeof(ASTC_BUFFER_DATA) + sizeof(SWIZZLE_TABLE); | ||
| 427 | data_buffer = device.GetLogical().CreateBuffer(VkBufferCreateInfo{ | ||
| 428 | .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, | ||
| 429 | .pNext = nullptr, | ||
| 430 | .flags = 0, | ||
| 431 | .size = TOTAL_BUFFER_SIZE, | ||
| 432 | .usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, | ||
| 433 | .sharingMode = VK_SHARING_MODE_EXCLUSIVE, | ||
| 434 | .queueFamilyIndexCount = 0, | ||
| 435 | .pQueueFamilyIndices = nullptr, | ||
| 436 | }); | ||
| 437 | data_buffer_commit = memory_allocator.Commit(data_buffer, MemoryUsage::Upload); | ||
| 438 | |||
| 439 | const auto staging_ref = staging_buffer_pool.Request(TOTAL_BUFFER_SIZE, MemoryUsage::Upload); | ||
| 440 | std::memcpy(staging_ref.mapped_span.data(), &ASTC_BUFFER_DATA, sizeof(ASTC_BUFFER_DATA)); | ||
| 441 | // Tack on the swizzle table at the end of the buffer | ||
| 442 | std::memcpy(staging_ref.mapped_span.data() + sizeof(ASTC_BUFFER_DATA), &SWIZZLE_TABLE, | ||
| 443 | sizeof(SWIZZLE_TABLE)); | ||
| 444 | |||
| 445 | scheduler.Record([src = staging_ref.buffer, offset = staging_ref.offset, dst = *data_buffer, | ||
| 446 | TOTAL_BUFFER_SIZE](vk::CommandBuffer cmdbuf) { | ||
| 447 | cmdbuf.CopyBuffer(src, dst, | ||
| 448 | VkBufferCopy{ | ||
| 449 | .srcOffset = offset, | ||
| 450 | .dstOffset = 0, | ||
| 451 | .size = TOTAL_BUFFER_SIZE, | ||
| 452 | }); | ||
| 453 | cmdbuf.PipelineBarrier( | ||
| 454 | VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, | ||
| 455 | VkMemoryBarrier{ | ||
| 456 | .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER, | ||
| 457 | .pNext = nullptr, | ||
| 458 | .srcAccessMask = 0, | ||
| 459 | .dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT, | ||
| 460 | }); | ||
| 461 | }); | ||
| 462 | } | ||
| 463 | |||
| 464 | void ASTCDecoderPass::Assemble(Image& image, const StagingBufferRef& map, | ||
| 465 | std::span<const VideoCommon::SwizzleParameters> swizzles) { | ||
| 466 | using namespace VideoCommon::Accelerated; | ||
| 467 | const std::array<u32, 2> block_dims{ | ||
| 468 | VideoCore::Surface::DefaultBlockWidth(image.info.format), | ||
| 469 | VideoCore::Surface::DefaultBlockHeight(image.info.format), | ||
| 470 | }; | ||
| 471 | scheduler.RequestOutsideRenderPassOperationContext(); | ||
| 472 | if (!data_buffer) { | ||
| 473 | MakeDataBuffer(); | ||
| 474 | } | ||
| 475 | const VkPipeline vk_pipeline = *pipeline; | ||
| 476 | const VkImageAspectFlags aspect_mask = image.AspectMask(); | ||
| 477 | const VkImage vk_image = image.Handle(); | ||
| 478 | const bool is_initialized = image.ExchangeInitialization(); | ||
| 479 | scheduler.Record( | ||
| 480 | [vk_pipeline, vk_image, aspect_mask, is_initialized](vk::CommandBuffer cmdbuf) { | ||
| 481 | const VkImageMemoryBarrier image_barrier{ | ||
| 482 | .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, | ||
| 483 | .pNext = nullptr, | ||
| 484 | .srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT, | ||
| 485 | .dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, | ||
| 486 | .oldLayout = is_initialized ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_UNDEFINED, | ||
| 487 | .newLayout = VK_IMAGE_LAYOUT_GENERAL, | ||
| 488 | .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, | ||
| 489 | .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, | ||
| 490 | .image = vk_image, | ||
| 491 | .subresourceRange{ | ||
| 492 | .aspectMask = aspect_mask, | ||
| 493 | .baseMipLevel = 0, | ||
| 494 | .levelCount = VK_REMAINING_MIP_LEVELS, | ||
| 495 | .baseArrayLayer = 0, | ||
| 496 | .layerCount = VK_REMAINING_ARRAY_LAYERS, | ||
| 497 | }, | ||
| 498 | }; | ||
| 499 | cmdbuf.PipelineBarrier(is_initialized ? VK_PIPELINE_STAGE_ALL_COMMANDS_BIT : 0, | ||
| 500 | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, image_barrier); | ||
| 501 | cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, vk_pipeline); | ||
| 502 | }); | ||
| 503 | for (const VideoCommon::SwizzleParameters& swizzle : swizzles) { | ||
| 504 | const size_t input_offset = swizzle.buffer_offset + map.offset; | ||
| 505 | const u32 num_dispatches_x = Common::DivCeil(swizzle.num_tiles.width, 32U); | ||
| 506 | const u32 num_dispatches_y = Common::DivCeil(swizzle.num_tiles.height, 32U); | ||
| 507 | const u32 num_dispatches_z = image.info.resources.layers; | ||
| 508 | |||
| 509 | update_descriptor_queue.Acquire(); | ||
| 510 | update_descriptor_queue.AddBuffer(map.buffer, input_offset, | ||
| 511 | image.guest_size_bytes - swizzle.buffer_offset); | ||
| 512 | update_descriptor_queue.AddBuffer(*data_buffer, offsetof(AstcBufferData, encoding_values), | ||
| 513 | sizeof(AstcBufferData::encoding_values)); | ||
| 514 | update_descriptor_queue.AddBuffer(*data_buffer, offsetof(AstcBufferData, replicate_6_to_8), | ||
| 515 | sizeof(AstcBufferData::replicate_6_to_8)); | ||
| 516 | update_descriptor_queue.AddBuffer(*data_buffer, offsetof(AstcBufferData, replicate_7_to_8), | ||
| 517 | sizeof(AstcBufferData::replicate_7_to_8)); | ||
| 518 | update_descriptor_queue.AddBuffer(*data_buffer, offsetof(AstcBufferData, replicate_8_to_8), | ||
| 519 | sizeof(AstcBufferData::replicate_8_to_8)); | ||
| 520 | update_descriptor_queue.AddBuffer(*data_buffer, | ||
| 521 | offsetof(AstcBufferData, replicate_byte_to_16), | ||
| 522 | sizeof(AstcBufferData::replicate_byte_to_16)); | ||
| 523 | update_descriptor_queue.AddBuffer(*data_buffer, sizeof(AstcBufferData), | ||
| 524 | sizeof(SWIZZLE_TABLE)); | ||
| 525 | update_descriptor_queue.AddImage(image.StorageImageView(swizzle.level)); | ||
| 526 | |||
| 527 | const VkDescriptorSet set = CommitDescriptorSet(update_descriptor_queue); | ||
| 528 | const VkPipelineLayout vk_layout = *layout; | ||
| 529 | |||
| 530 | // To unswizzle the ASTC data | ||
| 531 | const auto params = MakeBlockLinearSwizzle2DParams(swizzle, image.info); | ||
| 532 | ASSERT(params.origin == (std::array<u32, 3>{0, 0, 0})); | ||
| 533 | ASSERT(params.destination == (std::array<s32, 3>{0, 0, 0})); | ||
| 534 | scheduler.Record([vk_layout, num_dispatches_x, num_dispatches_y, num_dispatches_z, | ||
| 535 | block_dims, params, set](vk::CommandBuffer cmdbuf) { | ||
| 536 | const AstcPushConstants uniforms{ | ||
| 537 | .blocks_dims = block_dims, | ||
| 538 | .bytes_per_block_log2 = params.bytes_per_block_log2, | ||
| 539 | .layer_stride = params.layer_stride, | ||
| 540 | .block_size = params.block_size, | ||
| 541 | .x_shift = params.x_shift, | ||
| 542 | .block_height = params.block_height, | ||
| 543 | .block_height_mask = params.block_height_mask, | ||
| 544 | }; | ||
| 545 | cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_COMPUTE, vk_layout, 0, set, {}); | ||
| 546 | cmdbuf.PushConstants(vk_layout, VK_SHADER_STAGE_COMPUTE_BIT, uniforms); | ||
| 547 | cmdbuf.Dispatch(num_dispatches_x, num_dispatches_y, num_dispatches_z); | ||
| 548 | }); | ||
| 549 | } | ||
| 550 | scheduler.Record([vk_image, aspect_mask](vk::CommandBuffer cmdbuf) { | ||
| 551 | const VkImageMemoryBarrier image_barrier{ | ||
| 552 | .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, | ||
| 553 | .pNext = nullptr, | ||
| 554 | .srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT, | ||
| 555 | .dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, | ||
| 556 | .oldLayout = VK_IMAGE_LAYOUT_GENERAL, | ||
| 557 | .newLayout = VK_IMAGE_LAYOUT_GENERAL, | ||
| 558 | .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, | ||
| 559 | .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, | ||
| 560 | .image = vk_image, | ||
| 561 | .subresourceRange{ | ||
| 562 | .aspectMask = aspect_mask, | ||
| 563 | .baseMipLevel = 0, | ||
| 564 | .levelCount = VK_REMAINING_MIP_LEVELS, | ||
| 565 | .baseArrayLayer = 0, | ||
| 566 | .layerCount = VK_REMAINING_ARRAY_LAYERS, | ||
| 567 | }, | ||
| 568 | }; | ||
| 569 | cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, | ||
| 570 | VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, image_barrier); | ||
| 571 | }); | ||
| 572 | } | ||
| 573 | |||
| 241 | } // namespace Vulkan | 574 | } // namespace Vulkan |
diff --git a/src/video_core/renderer_vulkan/vk_compute_pass.h b/src/video_core/renderer_vulkan/vk_compute_pass.h index 17d781d99..5ea187c30 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pass.h +++ b/src/video_core/renderer_vulkan/vk_compute_pass.h | |||
| @@ -11,14 +11,21 @@ | |||
| 11 | #include "common/common_types.h" | 11 | #include "common/common_types.h" |
| 12 | #include "video_core/engines/maxwell_3d.h" | 12 | #include "video_core/engines/maxwell_3d.h" |
| 13 | #include "video_core/renderer_vulkan/vk_descriptor_pool.h" | 13 | #include "video_core/renderer_vulkan/vk_descriptor_pool.h" |
| 14 | #include "video_core/vulkan_common/vulkan_memory_allocator.h" | ||
| 14 | #include "video_core/vulkan_common/vulkan_wrapper.h" | 15 | #include "video_core/vulkan_common/vulkan_wrapper.h" |
| 15 | 16 | ||
| 17 | namespace VideoCommon { | ||
| 18 | struct SwizzleParameters; | ||
| 19 | } | ||
| 20 | |||
| 16 | namespace Vulkan { | 21 | namespace Vulkan { |
| 17 | 22 | ||
| 18 | class Device; | 23 | class Device; |
| 19 | class StagingBufferPool; | 24 | class StagingBufferPool; |
| 20 | class VKScheduler; | 25 | class VKScheduler; |
| 21 | class VKUpdateDescriptorQueue; | 26 | class VKUpdateDescriptorQueue; |
| 27 | class Image; | ||
| 28 | struct StagingBufferRef; | ||
| 22 | 29 | ||
| 23 | class VKComputePass { | 30 | class VKComputePass { |
| 24 | public: | 31 | public: |
| @@ -77,4 +84,29 @@ private: | |||
| 77 | VKUpdateDescriptorQueue& update_descriptor_queue; | 84 | VKUpdateDescriptorQueue& update_descriptor_queue; |
| 78 | }; | 85 | }; |
| 79 | 86 | ||
| 87 | class ASTCDecoderPass final : public VKComputePass { | ||
| 88 | public: | ||
| 89 | explicit ASTCDecoderPass(const Device& device_, VKScheduler& scheduler_, | ||
| 90 | VKDescriptorPool& descriptor_pool_, | ||
| 91 | StagingBufferPool& staging_buffer_pool_, | ||
| 92 | VKUpdateDescriptorQueue& update_descriptor_queue_, | ||
| 93 | MemoryAllocator& memory_allocator_); | ||
| 94 | ~ASTCDecoderPass(); | ||
| 95 | |||
| 96 | void Assemble(Image& image, const StagingBufferRef& map, | ||
| 97 | std::span<const VideoCommon::SwizzleParameters> swizzles); | ||
| 98 | |||
| 99 | private: | ||
| 100 | void MakeDataBuffer(); | ||
| 101 | |||
| 102 | const Device& device; | ||
| 103 | VKScheduler& scheduler; | ||
| 104 | StagingBufferPool& staging_buffer_pool; | ||
| 105 | VKUpdateDescriptorQueue& update_descriptor_queue; | ||
| 106 | MemoryAllocator& memory_allocator; | ||
| 107 | |||
| 108 | vk::Buffer data_buffer; | ||
| 109 | MemoryCommit data_buffer_commit; | ||
| 110 | }; | ||
| 111 | |||
| 80 | } // namespace Vulkan | 112 | } // namespace Vulkan |
diff --git a/src/video_core/renderer_vulkan/vk_master_semaphore.cpp b/src/video_core/renderer_vulkan/vk_master_semaphore.cpp index 56ec5e380..db78ce3d9 100644 --- a/src/video_core/renderer_vulkan/vk_master_semaphore.cpp +++ b/src/video_core/renderer_vulkan/vk_master_semaphore.cpp | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | #include <atomic> | 5 | #include <atomic> |
| 6 | #include <chrono> | 6 | #include <chrono> |
| 7 | 7 | ||
| 8 | #include "core/settings.h" | 8 | #include "common/settings.h" |
| 9 | #include "video_core/renderer_vulkan/vk_master_semaphore.h" | 9 | #include "video_core/renderer_vulkan/vk_master_semaphore.h" |
| 10 | #include "video_core/vulkan_common/vulkan_device.h" | 10 | #include "video_core/vulkan_common/vulkan_device.h" |
| 11 | #include "video_core/vulkan_common/vulkan_wrapper.h" | 11 | #include "video_core/vulkan_common/vulkan_wrapper.h" |
diff --git a/src/video_core/renderer_vulkan/vk_master_semaphore.h b/src/video_core/renderer_vulkan/vk_master_semaphore.h index 2c7ed654d..4b6d64daa 100644 --- a/src/video_core/renderer_vulkan/vk_master_semaphore.h +++ b/src/video_core/renderer_vulkan/vk_master_semaphore.h | |||
| @@ -35,8 +35,8 @@ public: | |||
| 35 | } | 35 | } |
| 36 | 36 | ||
| 37 | /// Returns true when a tick has been hit by the GPU. | 37 | /// Returns true when a tick has been hit by the GPU. |
| 38 | [[nodiscard]] bool IsFree(u64 tick) { | 38 | [[nodiscard]] bool IsFree(u64 tick) const noexcept { |
| 39 | return gpu_tick.load(std::memory_order_relaxed) >= tick; | 39 | return KnownGpuTick() >= tick; |
| 40 | } | 40 | } |
| 41 | 41 | ||
| 42 | /// Advance to the logical tick. | 42 | /// Advance to the logical tick. |
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index dfd38f575..e9a0e7811 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp | |||
| @@ -13,8 +13,8 @@ | |||
| 13 | #include "common/logging/log.h" | 13 | #include "common/logging/log.h" |
| 14 | #include "common/microprofile.h" | 14 | #include "common/microprofile.h" |
| 15 | #include "common/scope_exit.h" | 15 | #include "common/scope_exit.h" |
| 16 | #include "common/settings.h" | ||
| 16 | #include "core/core.h" | 17 | #include "core/core.h" |
| 17 | #include "core/settings.h" | ||
| 18 | #include "video_core/engines/kepler_compute.h" | 18 | #include "video_core/engines/kepler_compute.h" |
| 19 | #include "video_core/engines/maxwell_3d.h" | 19 | #include "video_core/engines/maxwell_3d.h" |
| 20 | #include "video_core/renderer_vulkan/blit_image.h" | 20 | #include "video_core/renderer_vulkan/blit_image.h" |
| @@ -241,7 +241,10 @@ RasterizerVulkan::RasterizerVulkan(Core::Frontend::EmuWindow& emu_window_, Tegra | |||
| 241 | staging_pool(device, memory_allocator, scheduler), descriptor_pool(device, scheduler), | 241 | staging_pool(device, memory_allocator, scheduler), descriptor_pool(device, scheduler), |
| 242 | update_descriptor_queue(device, scheduler), | 242 | update_descriptor_queue(device, scheduler), |
| 243 | blit_image(device, scheduler, state_tracker, descriptor_pool), | 243 | blit_image(device, scheduler, state_tracker, descriptor_pool), |
| 244 | texture_cache_runtime{device, scheduler, memory_allocator, staging_pool, blit_image}, | 244 | astc_decoder_pass(device, scheduler, descriptor_pool, staging_pool, update_descriptor_queue, |
| 245 | memory_allocator), | ||
| 246 | texture_cache_runtime{device, scheduler, memory_allocator, | ||
| 247 | staging_pool, blit_image, astc_decoder_pass}, | ||
| 245 | texture_cache(texture_cache_runtime, *this, maxwell3d, kepler_compute, gpu_memory), | 248 | texture_cache(texture_cache_runtime, *this, maxwell3d, kepler_compute, gpu_memory), |
| 246 | buffer_cache_runtime(device, memory_allocator, scheduler, staging_pool, | 249 | buffer_cache_runtime(device, memory_allocator, scheduler, staging_pool, |
| 247 | update_descriptor_queue, descriptor_pool), | 250 | update_descriptor_queue, descriptor_pool), |
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h index acea1ba2d..235afc6f3 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.h +++ b/src/video_core/renderer_vulkan/vk_rasterizer.h | |||
| @@ -173,6 +173,7 @@ private: | |||
| 173 | VKDescriptorPool descriptor_pool; | 173 | VKDescriptorPool descriptor_pool; |
| 174 | VKUpdateDescriptorQueue update_descriptor_queue; | 174 | VKUpdateDescriptorQueue update_descriptor_queue; |
| 175 | BlitImageHelper blit_image; | 175 | BlitImageHelper blit_image; |
| 176 | ASTCDecoderPass astc_decoder_pass; | ||
| 176 | 177 | ||
| 177 | GraphicsPipelineCacheKey graphics_key; | 178 | GraphicsPipelineCacheKey graphics_key; |
| 178 | 179 | ||
diff --git a/src/video_core/renderer_vulkan/vk_swapchain.cpp b/src/video_core/renderer_vulkan/vk_swapchain.cpp index 0b63bd6c8..dfd5c65ba 100644 --- a/src/video_core/renderer_vulkan/vk_swapchain.cpp +++ b/src/video_core/renderer_vulkan/vk_swapchain.cpp | |||
| @@ -82,11 +82,13 @@ void VKSwapchain::Create(u32 width, u32 height, bool srgb) { | |||
| 82 | resource_ticks.resize(image_count); | 82 | resource_ticks.resize(image_count); |
| 83 | } | 83 | } |
| 84 | 84 | ||
| 85 | void VKSwapchain::AcquireNextImage() { | 85 | bool VKSwapchain::AcquireNextImage() { |
| 86 | device.GetLogical().AcquireNextImageKHR(*swapchain, std::numeric_limits<u64>::max(), | 86 | const VkResult result = |
| 87 | *present_semaphores[frame_index], {}, &image_index); | 87 | device.GetLogical().AcquireNextImageKHR(*swapchain, std::numeric_limits<u64>::max(), |
| 88 | *present_semaphores[frame_index], {}, &image_index); | ||
| 88 | 89 | ||
| 89 | scheduler.Wait(resource_ticks[image_index]); | 90 | scheduler.Wait(resource_ticks[image_index]); |
| 91 | return result == VK_SUCCESS || result == VK_SUBOPTIMAL_KHR; | ||
| 90 | } | 92 | } |
| 91 | 93 | ||
| 92 | bool VKSwapchain::Present(VkSemaphore render_semaphore) { | 94 | bool VKSwapchain::Present(VkSemaphore render_semaphore) { |
diff --git a/src/video_core/renderer_vulkan/vk_swapchain.h b/src/video_core/renderer_vulkan/vk_swapchain.h index a728511e0..adc8d27cf 100644 --- a/src/video_core/renderer_vulkan/vk_swapchain.h +++ b/src/video_core/renderer_vulkan/vk_swapchain.h | |||
| @@ -28,7 +28,7 @@ public: | |||
| 28 | void Create(u32 width, u32 height, bool srgb); | 28 | void Create(u32 width, u32 height, bool srgb); |
| 29 | 29 | ||
| 30 | /// Acquires the next image in the swapchain, waits as needed. | 30 | /// Acquires the next image in the swapchain, waits as needed. |
| 31 | void AcquireNextImage(); | 31 | bool AcquireNextImage(); |
| 32 | 32 | ||
| 33 | /// Presents the rendered image to the swapchain. Returns true when the swapchains had to be | 33 | /// Presents the rendered image to the swapchain. Returns true when the swapchains had to be |
| 34 | /// recreated. Takes responsability for the ownership of fence. | 34 | /// recreated. Takes responsability for the ownership of fence. |
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index 22a1014a9..bc2a53841 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp | |||
| @@ -7,9 +7,12 @@ | |||
| 7 | #include <span> | 7 | #include <span> |
| 8 | #include <vector> | 8 | #include <vector> |
| 9 | 9 | ||
| 10 | #include "common/bit_cast.h" | ||
| 11 | |||
| 10 | #include "video_core/engines/fermi_2d.h" | 12 | #include "video_core/engines/fermi_2d.h" |
| 11 | #include "video_core/renderer_vulkan/blit_image.h" | 13 | #include "video_core/renderer_vulkan/blit_image.h" |
| 12 | #include "video_core/renderer_vulkan/maxwell_to_vk.h" | 14 | #include "video_core/renderer_vulkan/maxwell_to_vk.h" |
| 15 | #include "video_core/renderer_vulkan/vk_compute_pass.h" | ||
| 13 | #include "video_core/renderer_vulkan/vk_rasterizer.h" | 16 | #include "video_core/renderer_vulkan/vk_rasterizer.h" |
| 14 | #include "video_core/renderer_vulkan/vk_scheduler.h" | 17 | #include "video_core/renderer_vulkan/vk_scheduler.h" |
| 15 | #include "video_core/renderer_vulkan/vk_staging_buffer_pool.h" | 18 | #include "video_core/renderer_vulkan/vk_staging_buffer_pool.h" |
| @@ -807,7 +810,7 @@ Image::Image(TextureCacheRuntime& runtime, const ImageInfo& info_, GPUVAddr gpu_ | |||
| 807 | commit = runtime.memory_allocator.Commit(buffer, MemoryUsage::DeviceLocal); | 810 | commit = runtime.memory_allocator.Commit(buffer, MemoryUsage::DeviceLocal); |
| 808 | } | 811 | } |
| 809 | if (IsPixelFormatASTC(info.format) && !runtime.device.IsOptimalAstcSupported()) { | 812 | if (IsPixelFormatASTC(info.format) && !runtime.device.IsOptimalAstcSupported()) { |
| 810 | flags |= VideoCommon::ImageFlagBits::Converted; | 813 | flags |= VideoCommon::ImageFlagBits::AcceleratedUpload; |
| 811 | } | 814 | } |
| 812 | if (runtime.device.HasDebuggingToolAttached()) { | 815 | if (runtime.device.HasDebuggingToolAttached()) { |
| 813 | if (image) { | 816 | if (image) { |
| @@ -816,6 +819,38 @@ Image::Image(TextureCacheRuntime& runtime, const ImageInfo& info_, GPUVAddr gpu_ | |||
| 816 | buffer.SetObjectNameEXT(VideoCommon::Name(*this).c_str()); | 819 | buffer.SetObjectNameEXT(VideoCommon::Name(*this).c_str()); |
| 817 | } | 820 | } |
| 818 | } | 821 | } |
| 822 | static constexpr VkImageViewUsageCreateInfo storage_image_view_usage_create_info{ | ||
| 823 | .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO, | ||
| 824 | .pNext = nullptr, | ||
| 825 | .usage = VK_IMAGE_USAGE_STORAGE_BIT, | ||
| 826 | }; | ||
| 827 | if (IsPixelFormatASTC(info.format) && !runtime.device.IsOptimalAstcSupported()) { | ||
| 828 | const auto& device = runtime.device.GetLogical(); | ||
| 829 | storage_image_views.reserve(info.resources.levels); | ||
| 830 | for (s32 level = 0; level < info.resources.levels; ++level) { | ||
| 831 | storage_image_views.push_back(device.CreateImageView(VkImageViewCreateInfo{ | ||
| 832 | .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, | ||
| 833 | .pNext = &storage_image_view_usage_create_info, | ||
| 834 | .flags = 0, | ||
| 835 | .image = *image, | ||
| 836 | .viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY, | ||
| 837 | .format = VK_FORMAT_A8B8G8R8_UNORM_PACK32, | ||
| 838 | .components{ | ||
| 839 | .r = VK_COMPONENT_SWIZZLE_IDENTITY, | ||
| 840 | .g = VK_COMPONENT_SWIZZLE_IDENTITY, | ||
| 841 | .b = VK_COMPONENT_SWIZZLE_IDENTITY, | ||
| 842 | .a = VK_COMPONENT_SWIZZLE_IDENTITY, | ||
| 843 | }, | ||
| 844 | .subresourceRange{ | ||
| 845 | .aspectMask = aspect_mask, | ||
| 846 | .baseMipLevel = static_cast<u32>(level), | ||
| 847 | .levelCount = 1, | ||
| 848 | .baseArrayLayer = 0, | ||
| 849 | .layerCount = VK_REMAINING_ARRAY_LAYERS, | ||
| 850 | }, | ||
| 851 | })); | ||
| 852 | } | ||
| 853 | } | ||
| 819 | } | 854 | } |
| 820 | 855 | ||
| 821 | void Image::UploadMemory(const StagingBufferRef& map, std::span<const BufferImageCopy> copies) { | 856 | void Image::UploadMemory(const StagingBufferRef& map, std::span<const BufferImageCopy> copies) { |
| @@ -918,7 +953,6 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI | |||
| 918 | } | 953 | } |
| 919 | } | 954 | } |
| 920 | const auto format_info = MaxwellToVK::SurfaceFormat(*device, FormatType::Optimal, true, format); | 955 | const auto format_info = MaxwellToVK::SurfaceFormat(*device, FormatType::Optimal, true, format); |
| 921 | const VkFormat vk_format = format_info.format; | ||
| 922 | const VkImageViewUsageCreateInfo image_view_usage{ | 956 | const VkImageViewUsageCreateInfo image_view_usage{ |
| 923 | .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO, | 957 | .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO, |
| 924 | .pNext = nullptr, | 958 | .pNext = nullptr, |
| @@ -930,7 +964,7 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI | |||
| 930 | .flags = 0, | 964 | .flags = 0, |
| 931 | .image = image.Handle(), | 965 | .image = image.Handle(), |
| 932 | .viewType = VkImageViewType{}, | 966 | .viewType = VkImageViewType{}, |
| 933 | .format = vk_format, | 967 | .format = format_info.format, |
| 934 | .components{ | 968 | .components{ |
| 935 | .r = ComponentSwizzle(swizzle[0]), | 969 | .r = ComponentSwizzle(swizzle[0]), |
| 936 | .g = ComponentSwizzle(swizzle[1]), | 970 | .g = ComponentSwizzle(swizzle[1]), |
| @@ -982,7 +1016,7 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI | |||
| 982 | .pNext = nullptr, | 1016 | .pNext = nullptr, |
| 983 | .flags = 0, | 1017 | .flags = 0, |
| 984 | .buffer = image.Buffer(), | 1018 | .buffer = image.Buffer(), |
| 985 | .format = vk_format, | 1019 | .format = format_info.format, |
| 986 | .offset = 0, // TODO: Redesign buffer cache to support this | 1020 | .offset = 0, // TODO: Redesign buffer cache to support this |
| 987 | .range = image.guest_size_bytes, | 1021 | .range = image.guest_size_bytes, |
| 988 | }); | 1022 | }); |
| @@ -1030,14 +1064,13 @@ vk::ImageView ImageView::MakeDepthStencilView(VkImageAspectFlags aspect_mask) { | |||
| 1030 | Sampler::Sampler(TextureCacheRuntime& runtime, const Tegra::Texture::TSCEntry& tsc) { | 1064 | Sampler::Sampler(TextureCacheRuntime& runtime, const Tegra::Texture::TSCEntry& tsc) { |
| 1031 | const auto& device = runtime.device; | 1065 | const auto& device = runtime.device; |
| 1032 | const bool arbitrary_borders = runtime.device.IsExtCustomBorderColorSupported(); | 1066 | const bool arbitrary_borders = runtime.device.IsExtCustomBorderColorSupported(); |
| 1033 | const std::array<float, 4> color = tsc.BorderColor(); | 1067 | const auto color = tsc.BorderColor(); |
| 1034 | // C++20 bit_cast | 1068 | |
| 1035 | VkClearColorValue border_color; | ||
| 1036 | std::memcpy(&border_color, &color, sizeof(color)); | ||
| 1037 | const VkSamplerCustomBorderColorCreateInfoEXT border_ci{ | 1069 | const VkSamplerCustomBorderColorCreateInfoEXT border_ci{ |
| 1038 | .sType = VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT, | 1070 | .sType = VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT, |
| 1039 | .pNext = nullptr, | 1071 | .pNext = nullptr, |
| 1040 | .customBorderColor = border_color, | 1072 | // TODO: Make use of std::bit_cast once libc++ supports it. |
| 1073 | .customBorderColor = Common::BitCast<VkClearColorValue>(color), | ||
| 1041 | .format = VK_FORMAT_UNDEFINED, | 1074 | .format = VK_FORMAT_UNDEFINED, |
| 1042 | }; | 1075 | }; |
| 1043 | const void* pnext = nullptr; | 1076 | const void* pnext = nullptr; |
| @@ -1167,4 +1200,13 @@ Framebuffer::Framebuffer(TextureCacheRuntime& runtime, std::span<ImageView*, NUM | |||
| 1167 | } | 1200 | } |
| 1168 | } | 1201 | } |
| 1169 | 1202 | ||
| 1203 | void TextureCacheRuntime::AccelerateImageUpload( | ||
| 1204 | Image& image, const StagingBufferRef& map, | ||
| 1205 | std::span<const VideoCommon::SwizzleParameters> swizzles) { | ||
| 1206 | if (IsPixelFormatASTC(image.info.format)) { | ||
| 1207 | return astc_decoder_pass.Assemble(image, map, swizzles); | ||
| 1208 | } | ||
| 1209 | UNREACHABLE(); | ||
| 1210 | } | ||
| 1211 | |||
| 1170 | } // namespace Vulkan | 1212 | } // namespace Vulkan |
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h index 3aee27ce0..628785d5e 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.h +++ b/src/video_core/renderer_vulkan/vk_texture_cache.h | |||
| @@ -20,6 +20,7 @@ using VideoCommon::Offset2D; | |||
| 20 | using VideoCommon::RenderTargets; | 20 | using VideoCommon::RenderTargets; |
| 21 | using VideoCore::Surface::PixelFormat; | 21 | using VideoCore::Surface::PixelFormat; |
| 22 | 22 | ||
| 23 | class ASTCDecoderPass; | ||
| 23 | class BlitImageHelper; | 24 | class BlitImageHelper; |
| 24 | class Device; | 25 | class Device; |
| 25 | class Image; | 26 | class Image; |
| @@ -60,6 +61,7 @@ struct TextureCacheRuntime { | |||
| 60 | MemoryAllocator& memory_allocator; | 61 | MemoryAllocator& memory_allocator; |
| 61 | StagingBufferPool& staging_buffer_pool; | 62 | StagingBufferPool& staging_buffer_pool; |
| 62 | BlitImageHelper& blit_image_helper; | 63 | BlitImageHelper& blit_image_helper; |
| 64 | ASTCDecoderPass& astc_decoder_pass; | ||
| 63 | std::unordered_map<RenderPassKey, vk::RenderPass> renderpass_cache{}; | 65 | std::unordered_map<RenderPassKey, vk::RenderPass> renderpass_cache{}; |
| 64 | 66 | ||
| 65 | void Finish(); | 67 | void Finish(); |
| @@ -83,9 +85,7 @@ struct TextureCacheRuntime { | |||
| 83 | } | 85 | } |
| 84 | 86 | ||
| 85 | void AccelerateImageUpload(Image&, const StagingBufferRef&, | 87 | void AccelerateImageUpload(Image&, const StagingBufferRef&, |
| 86 | std::span<const VideoCommon::SwizzleParameters>) { | 88 | std::span<const VideoCommon::SwizzleParameters>); |
| 87 | UNREACHABLE(); | ||
| 88 | } | ||
| 89 | 89 | ||
| 90 | void InsertUploadMemoryBarrier() {} | 90 | void InsertUploadMemoryBarrier() {} |
| 91 | 91 | ||
| @@ -121,15 +121,26 @@ public: | |||
| 121 | return *buffer; | 121 | return *buffer; |
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | [[nodiscard]] VkImageCreateFlags AspectMask() const noexcept { | 124 | [[nodiscard]] VkImageAspectFlags AspectMask() const noexcept { |
| 125 | return aspect_mask; | 125 | return aspect_mask; |
| 126 | } | 126 | } |
| 127 | 127 | ||
| 128 | [[nodiscard]] VkImageView StorageImageView(s32 level) const noexcept { | ||
| 129 | return *storage_image_views[level]; | ||
| 130 | } | ||
| 131 | |||
| 132 | /// Returns true when the image is already initialized and mark it as initialized | ||
| 133 | [[nodiscard]] bool ExchangeInitialization() noexcept { | ||
| 134 | return std::exchange(initialized, true); | ||
| 135 | } | ||
| 136 | |||
| 128 | private: | 137 | private: |
| 129 | VKScheduler* scheduler; | 138 | VKScheduler* scheduler; |
| 130 | vk::Image image; | 139 | vk::Image image; |
| 131 | vk::Buffer buffer; | 140 | vk::Buffer buffer; |
| 132 | MemoryCommit commit; | 141 | MemoryCommit commit; |
| 142 | vk::ImageView image_view; | ||
| 143 | std::vector<vk::ImageView> storage_image_views; | ||
| 133 | VkImageAspectFlags aspect_mask = 0; | 144 | VkImageAspectFlags aspect_mask = 0; |
| 134 | bool initialized = false; | 145 | bool initialized = false; |
| 135 | }; | 146 | }; |
diff --git a/src/video_core/texture_cache/accelerated_swizzle.h b/src/video_core/texture_cache/accelerated_swizzle.h index 6ec5c78c4..a11c924e1 100644 --- a/src/video_core/texture_cache/accelerated_swizzle.h +++ b/src/video_core/texture_cache/accelerated_swizzle.h | |||
| @@ -13,8 +13,8 @@ | |||
| 13 | namespace VideoCommon::Accelerated { | 13 | namespace VideoCommon::Accelerated { |
| 14 | 14 | ||
| 15 | struct BlockLinearSwizzle2DParams { | 15 | struct BlockLinearSwizzle2DParams { |
| 16 | std::array<u32, 3> origin; | 16 | alignas(16) std::array<u32, 3> origin; |
| 17 | std::array<s32, 3> destination; | 17 | alignas(16) std::array<s32, 3> destination; |
| 18 | u32 bytes_per_block_log2; | 18 | u32 bytes_per_block_log2; |
| 19 | u32 layer_stride; | 19 | u32 layer_stride; |
| 20 | u32 block_size; | 20 | u32 block_size; |
diff --git a/src/video_core/texture_cache/image_view_base.cpp b/src/video_core/texture_cache/image_view_base.cpp index f89a40b4c..e8d632f9e 100644 --- a/src/video_core/texture_cache/image_view_base.cpp +++ b/src/video_core/texture_cache/image_view_base.cpp | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | #include <algorithm> | 5 | #include <algorithm> |
| 6 | 6 | ||
| 7 | #include "common/assert.h" | 7 | #include "common/assert.h" |
| 8 | #include "core/settings.h" | 8 | #include "common/settings.h" |
| 9 | #include "video_core/compatible_formats.h" | 9 | #include "video_core/compatible_formats.h" |
| 10 | #include "video_core/surface.h" | 10 | #include "video_core/surface.h" |
| 11 | #include "video_core/texture_cache/formatter.h" | 11 | #include "video_core/texture_cache/formatter.h" |
diff --git a/src/video_core/texture_cache/util.cpp b/src/video_core/texture_cache/util.cpp index 2c42d1449..0ab297413 100644 --- a/src/video_core/texture_cache/util.cpp +++ b/src/video_core/texture_cache/util.cpp | |||
| @@ -47,7 +47,6 @@ | |||
| 47 | #include "video_core/texture_cache/formatter.h" | 47 | #include "video_core/texture_cache/formatter.h" |
| 48 | #include "video_core/texture_cache/samples_helper.h" | 48 | #include "video_core/texture_cache/samples_helper.h" |
| 49 | #include "video_core/texture_cache/util.h" | 49 | #include "video_core/texture_cache/util.h" |
| 50 | #include "video_core/textures/astc.h" | ||
| 51 | #include "video_core/textures/decoders.h" | 50 | #include "video_core/textures/decoders.h" |
| 52 | 51 | ||
| 53 | namespace VideoCommon { | 52 | namespace VideoCommon { |
| @@ -269,16 +268,19 @@ template <u32 GOB_EXTENT> | |||
| 269 | return num_tiles << shift; | 268 | return num_tiles << shift; |
| 270 | } | 269 | } |
| 271 | 270 | ||
| 272 | [[nodiscard]] constexpr std::array<u32, MAX_MIP_LEVELS> CalculateLevelSizes(const LevelInfo& info, | 271 | [[nodiscard]] constexpr LevelArray CalculateLevelSizes(const LevelInfo& info, u32 num_levels) { |
| 273 | u32 num_levels) { | ||
| 274 | ASSERT(num_levels <= MAX_MIP_LEVELS); | 272 | ASSERT(num_levels <= MAX_MIP_LEVELS); |
| 275 | std::array<u32, MAX_MIP_LEVELS> sizes{}; | 273 | LevelArray sizes{}; |
| 276 | for (u32 level = 0; level < num_levels; ++level) { | 274 | for (u32 level = 0; level < num_levels; ++level) { |
| 277 | sizes[level] = CalculateLevelSize(info, level); | 275 | sizes[level] = CalculateLevelSize(info, level); |
| 278 | } | 276 | } |
| 279 | return sizes; | 277 | return sizes; |
| 280 | } | 278 | } |
| 281 | 279 | ||
| 280 | [[nodiscard]] u32 CalculateLevelBytes(const LevelArray& sizes, u32 num_levels) { | ||
| 281 | return std::reduce(sizes.begin(), sizes.begin() + num_levels, 0U); | ||
| 282 | } | ||
| 283 | |||
| 282 | [[nodiscard]] constexpr LevelInfo MakeLevelInfo(PixelFormat format, Extent3D size, Extent3D block, | 284 | [[nodiscard]] constexpr LevelInfo MakeLevelInfo(PixelFormat format, Extent3D size, Extent3D block, |
| 283 | u32 num_samples, u32 tile_width_spacing) { | 285 | u32 num_samples, u32 tile_width_spacing) { |
| 284 | const auto [samples_x, samples_y] = Samples(num_samples); | 286 | const auto [samples_x, samples_y] = Samples(num_samples); |
| @@ -567,10 +569,10 @@ void SwizzleBlockLinearImage(Tegra::MemoryManager& gpu_memory, GPUVAddr gpu_addr | |||
| 567 | 569 | ||
| 568 | const u32 num_levels = info.resources.levels; | 570 | const u32 num_levels = info.resources.levels; |
| 569 | const std::array sizes = CalculateLevelSizes(level_info, num_levels); | 571 | const std::array sizes = CalculateLevelSizes(level_info, num_levels); |
| 570 | size_t guest_offset = std::reduce(sizes.begin(), sizes.begin() + level, 0); | 572 | size_t guest_offset = CalculateLevelBytes(sizes, level); |
| 571 | const size_t layer_stride = | 573 | const size_t layer_stride = |
| 572 | AlignLayerSize(std::reduce(sizes.begin(), sizes.begin() + num_levels, 0), size, | 574 | AlignLayerSize(CalculateLevelBytes(sizes, num_levels), size, level_info.block, |
| 573 | level_info.block, tile_size.height, info.tile_width_spacing); | 575 | tile_size.height, info.tile_width_spacing); |
| 574 | const size_t subresource_size = sizes[level]; | 576 | const size_t subresource_size = sizes[level]; |
| 575 | 577 | ||
| 576 | const auto dst_data = std::make_unique<u8[]>(subresource_size); | 578 | const auto dst_data = std::make_unique<u8[]>(subresource_size); |
| @@ -644,10 +646,10 @@ u32 CalculateLayerSize(const ImageInfo& info) noexcept { | |||
| 644 | info.tile_width_spacing, info.resources.levels); | 646 | info.tile_width_spacing, info.resources.levels); |
| 645 | } | 647 | } |
| 646 | 648 | ||
| 647 | std::array<u32, MAX_MIP_LEVELS> CalculateMipLevelOffsets(const ImageInfo& info) noexcept { | 649 | LevelArray CalculateMipLevelOffsets(const ImageInfo& info) noexcept { |
| 648 | ASSERT(info.resources.levels <= static_cast<s32>(MAX_MIP_LEVELS)); | 650 | ASSERT(info.resources.levels <= static_cast<s32>(MAX_MIP_LEVELS)); |
| 649 | const LevelInfo level_info = MakeLevelInfo(info); | 651 | const LevelInfo level_info = MakeLevelInfo(info); |
| 650 | std::array<u32, MAX_MIP_LEVELS> offsets{}; | 652 | LevelArray offsets{}; |
| 651 | u32 offset = 0; | 653 | u32 offset = 0; |
| 652 | for (s32 level = 0; level < info.resources.levels; ++level) { | 654 | for (s32 level = 0; level < info.resources.levels; ++level) { |
| 653 | offsets[level] = offset; | 655 | offsets[level] = offset; |
| @@ -813,7 +815,7 @@ std::vector<BufferImageCopy> UnswizzleImage(Tegra::MemoryManager& gpu_memory, GP | |||
| 813 | const Extent2D tile_size = DefaultBlockSize(info.format); | 815 | const Extent2D tile_size = DefaultBlockSize(info.format); |
| 814 | const std::array level_sizes = CalculateLevelSizes(level_info, num_levels); | 816 | const std::array level_sizes = CalculateLevelSizes(level_info, num_levels); |
| 815 | const Extent2D gob = GobSize(bpp_log2, info.block.height, info.tile_width_spacing); | 817 | const Extent2D gob = GobSize(bpp_log2, info.block.height, info.tile_width_spacing); |
| 816 | const u32 layer_size = std::reduce(level_sizes.begin(), level_sizes.begin() + num_levels, 0); | 818 | const u32 layer_size = CalculateLevelBytes(level_sizes, num_levels); |
| 817 | const u32 layer_stride = AlignLayerSize(layer_size, size, level_info.block, tile_size.height, | 819 | const u32 layer_stride = AlignLayerSize(layer_size, size, level_info.block, tile_size.height, |
| 818 | info.tile_width_spacing); | 820 | info.tile_width_spacing); |
| 819 | size_t guest_offset = 0; | 821 | size_t guest_offset = 0; |
| @@ -879,17 +881,8 @@ void ConvertImage(std::span<const u8> input, const ImageInfo& info, std::span<u8 | |||
| 879 | ASSERT(copy.image_extent == mip_size); | 881 | ASSERT(copy.image_extent == mip_size); |
| 880 | ASSERT(copy.buffer_row_length == Common::AlignUp(mip_size.width, tile_size.width)); | 882 | ASSERT(copy.buffer_row_length == Common::AlignUp(mip_size.width, tile_size.width)); |
| 881 | ASSERT(copy.buffer_image_height == Common::AlignUp(mip_size.height, tile_size.height)); | 883 | ASSERT(copy.buffer_image_height == Common::AlignUp(mip_size.height, tile_size.height)); |
| 882 | 884 | DecompressBC4(input.subspan(copy.buffer_offset), copy.image_extent, | |
| 883 | if (IsPixelFormatASTC(info.format)) { | 885 | output.subspan(output_offset)); |
| 884 | ASSERT(copy.image_extent.depth == 1); | ||
| 885 | Tegra::Texture::ASTC::Decompress(input.subspan(copy.buffer_offset), | ||
| 886 | copy.image_extent.width, copy.image_extent.height, | ||
| 887 | copy.image_subresource.num_layers, tile_size.width, | ||
| 888 | tile_size.height, output.subspan(output_offset)); | ||
| 889 | } else { | ||
| 890 | DecompressBC4(input.subspan(copy.buffer_offset), copy.image_extent, | ||
| 891 | output.subspan(output_offset)); | ||
| 892 | } | ||
| 893 | copy.buffer_offset = output_offset; | 886 | copy.buffer_offset = output_offset; |
| 894 | copy.buffer_row_length = mip_size.width; | 887 | copy.buffer_row_length = mip_size.width; |
| 895 | copy.buffer_image_height = mip_size.height; | 888 | copy.buffer_image_height = mip_size.height; |
diff --git a/src/video_core/texture_cache/util.h b/src/video_core/texture_cache/util.h index 4d0072867..cdc5cbc75 100644 --- a/src/video_core/texture_cache/util.h +++ b/src/video_core/texture_cache/util.h | |||
| @@ -20,6 +20,8 @@ namespace VideoCommon { | |||
| 20 | 20 | ||
| 21 | using Tegra::Texture::TICEntry; | 21 | using Tegra::Texture::TICEntry; |
| 22 | 22 | ||
| 23 | using LevelArray = std::array<u32, MAX_MIP_LEVELS>; | ||
| 24 | |||
| 23 | struct OverlapResult { | 25 | struct OverlapResult { |
| 24 | GPUVAddr gpu_addr; | 26 | GPUVAddr gpu_addr; |
| 25 | VAddr cpu_addr; | 27 | VAddr cpu_addr; |
| @@ -36,8 +38,7 @@ struct OverlapResult { | |||
| 36 | 38 | ||
| 37 | [[nodiscard]] u32 CalculateLayerSize(const ImageInfo& info) noexcept; | 39 | [[nodiscard]] u32 CalculateLayerSize(const ImageInfo& info) noexcept; |
| 38 | 40 | ||
| 39 | [[nodiscard]] std::array<u32, MAX_MIP_LEVELS> CalculateMipLevelOffsets( | 41 | [[nodiscard]] LevelArray CalculateMipLevelOffsets(const ImageInfo& info) noexcept; |
| 40 | const ImageInfo& info) noexcept; | ||
| 41 | 42 | ||
| 42 | [[nodiscard]] std::vector<u32> CalculateSliceOffsets(const ImageInfo& info); | 43 | [[nodiscard]] std::vector<u32> CalculateSliceOffsets(const ImageInfo& info); |
| 43 | 44 | ||
diff --git a/src/video_core/textures/astc.cpp b/src/video_core/textures/astc.cpp deleted file mode 100644 index 3625b666c..000000000 --- a/src/video_core/textures/astc.cpp +++ /dev/null | |||
| @@ -1,1710 +0,0 @@ | |||
| 1 | // Copyright 2016 The University of North Carolina at Chapel Hill | ||
| 2 | // | ||
| 3 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | // you may not use this file except in compliance with the License. | ||
| 5 | // You may obtain a copy of the License at | ||
| 6 | // | ||
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | // | ||
| 9 | // Unless required by applicable law or agreed to in writing, software | ||
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | // See the License for the specific language governing permissions and | ||
| 13 | // limitations under the License. | ||
| 14 | // | ||
| 15 | // Please send all BUG REPORTS to <pavel@cs.unc.edu>. | ||
| 16 | // <http://gamma.cs.unc.edu/FasTC/> | ||
| 17 | |||
| 18 | #include <algorithm> | ||
| 19 | #include <cassert> | ||
| 20 | #include <cstring> | ||
| 21 | #include <span> | ||
| 22 | #include <vector> | ||
| 23 | |||
| 24 | #include <boost/container/static_vector.hpp> | ||
| 25 | |||
| 26 | #include "common/common_types.h" | ||
| 27 | |||
| 28 | #include "video_core/textures/astc.h" | ||
| 29 | |||
| 30 | namespace { | ||
| 31 | |||
| 32 | /// Count the number of bits set in a number. | ||
| 33 | constexpr u32 Popcnt(u32 n) { | ||
| 34 | u32 c = 0; | ||
| 35 | for (; n; c++) { | ||
| 36 | n &= n - 1; | ||
| 37 | } | ||
| 38 | return c; | ||
| 39 | } | ||
| 40 | |||
| 41 | } // Anonymous namespace | ||
| 42 | |||
| 43 | class InputBitStream { | ||
| 44 | public: | ||
| 45 | constexpr explicit InputBitStream(std::span<const u8> data, size_t start_offset = 0) | ||
| 46 | : cur_byte{data.data()}, total_bits{data.size()}, next_bit{start_offset % 8} {} | ||
| 47 | |||
| 48 | constexpr size_t GetBitsRead() const { | ||
| 49 | return bits_read; | ||
| 50 | } | ||
| 51 | |||
| 52 | constexpr bool ReadBit() { | ||
| 53 | if (bits_read >= total_bits * 8) { | ||
| 54 | return 0; | ||
| 55 | } | ||
| 56 | const bool bit = ((*cur_byte >> next_bit) & 1) != 0; | ||
| 57 | ++next_bit; | ||
| 58 | while (next_bit >= 8) { | ||
| 59 | next_bit -= 8; | ||
| 60 | ++cur_byte; | ||
| 61 | } | ||
| 62 | ++bits_read; | ||
| 63 | return bit; | ||
| 64 | } | ||
| 65 | |||
| 66 | constexpr u32 ReadBits(std::size_t nBits) { | ||
| 67 | u32 ret = 0; | ||
| 68 | for (std::size_t i = 0; i < nBits; ++i) { | ||
| 69 | ret |= (ReadBit() & 1) << i; | ||
| 70 | } | ||
| 71 | return ret; | ||
| 72 | } | ||
| 73 | |||
| 74 | template <std::size_t nBits> | ||
| 75 | constexpr u32 ReadBits() { | ||
| 76 | u32 ret = 0; | ||
| 77 | for (std::size_t i = 0; i < nBits; ++i) { | ||
| 78 | ret |= (ReadBit() & 1) << i; | ||
| 79 | } | ||
| 80 | return ret; | ||
| 81 | } | ||
| 82 | |||
| 83 | private: | ||
| 84 | const u8* cur_byte; | ||
| 85 | size_t total_bits = 0; | ||
| 86 | size_t next_bit = 0; | ||
| 87 | size_t bits_read = 0; | ||
| 88 | }; | ||
| 89 | |||
| 90 | class OutputBitStream { | ||
| 91 | public: | ||
| 92 | constexpr explicit OutputBitStream(u8* ptr, std::size_t bits = 0, std::size_t start_offset = 0) | ||
| 93 | : cur_byte{ptr}, num_bits{bits}, next_bit{start_offset % 8} {} | ||
| 94 | |||
| 95 | constexpr std::size_t GetBitsWritten() const { | ||
| 96 | return bits_written; | ||
| 97 | } | ||
| 98 | |||
| 99 | constexpr void WriteBitsR(u32 val, u32 nBits) { | ||
| 100 | for (u32 i = 0; i < nBits; i++) { | ||
| 101 | WriteBit((val >> (nBits - i - 1)) & 1); | ||
| 102 | } | ||
| 103 | } | ||
| 104 | |||
| 105 | constexpr void WriteBits(u32 val, u32 nBits) { | ||
| 106 | for (u32 i = 0; i < nBits; i++) { | ||
| 107 | WriteBit((val >> i) & 1); | ||
| 108 | } | ||
| 109 | } | ||
| 110 | |||
| 111 | private: | ||
| 112 | constexpr void WriteBit(bool b) { | ||
| 113 | if (bits_written >= num_bits) { | ||
| 114 | return; | ||
| 115 | } | ||
| 116 | |||
| 117 | const u32 mask = 1 << next_bit++; | ||
| 118 | |||
| 119 | // clear the bit | ||
| 120 | *cur_byte &= static_cast<u8>(~mask); | ||
| 121 | |||
| 122 | // Write the bit, if necessary | ||
| 123 | if (b) | ||
| 124 | *cur_byte |= static_cast<u8>(mask); | ||
| 125 | |||
| 126 | // Next byte? | ||
| 127 | if (next_bit >= 8) { | ||
| 128 | cur_byte += 1; | ||
| 129 | next_bit = 0; | ||
| 130 | } | ||
| 131 | } | ||
| 132 | |||
| 133 | u8* cur_byte; | ||
| 134 | std::size_t num_bits; | ||
| 135 | std::size_t bits_written = 0; | ||
| 136 | std::size_t next_bit = 0; | ||
| 137 | }; | ||
| 138 | |||
| 139 | template <typename IntType> | ||
| 140 | class Bits { | ||
| 141 | public: | ||
| 142 | explicit Bits(const IntType& v) : m_Bits(v) {} | ||
| 143 | |||
| 144 | Bits(const Bits&) = delete; | ||
| 145 | Bits& operator=(const Bits&) = delete; | ||
| 146 | |||
| 147 | u8 operator[](u32 bitPos) const { | ||
| 148 | return static_cast<u8>((m_Bits >> bitPos) & 1); | ||
| 149 | } | ||
| 150 | |||
| 151 | IntType operator()(u32 start, u32 end) const { | ||
| 152 | if (start == end) { | ||
| 153 | return (*this)[start]; | ||
| 154 | } else if (start > end) { | ||
| 155 | u32 t = start; | ||
| 156 | start = end; | ||
| 157 | end = t; | ||
| 158 | } | ||
| 159 | |||
| 160 | u64 mask = (1 << (end - start + 1)) - 1; | ||
| 161 | return (m_Bits >> start) & static_cast<IntType>(mask); | ||
| 162 | } | ||
| 163 | |||
| 164 | private: | ||
| 165 | const IntType& m_Bits; | ||
| 166 | }; | ||
| 167 | |||
| 168 | enum class IntegerEncoding { JustBits, Qus32, Trit }; | ||
| 169 | |||
| 170 | struct IntegerEncodedValue { | ||
| 171 | constexpr IntegerEncodedValue() = default; | ||
| 172 | |||
| 173 | constexpr IntegerEncodedValue(IntegerEncoding encoding_, u32 num_bits_) | ||
| 174 | : encoding{encoding_}, num_bits{num_bits_} {} | ||
| 175 | |||
| 176 | constexpr bool MatchesEncoding(const IntegerEncodedValue& other) const { | ||
| 177 | return encoding == other.encoding && num_bits == other.num_bits; | ||
| 178 | } | ||
| 179 | |||
| 180 | // Returns the number of bits required to encode nVals values. | ||
| 181 | u32 GetBitLength(u32 nVals) const { | ||
| 182 | u32 totalBits = num_bits * nVals; | ||
| 183 | if (encoding == IntegerEncoding::Trit) { | ||
| 184 | totalBits += (nVals * 8 + 4) / 5; | ||
| 185 | } else if (encoding == IntegerEncoding::Qus32) { | ||
| 186 | totalBits += (nVals * 7 + 2) / 3; | ||
| 187 | } | ||
| 188 | return totalBits; | ||
| 189 | } | ||
| 190 | |||
| 191 | IntegerEncoding encoding{}; | ||
| 192 | u32 num_bits = 0; | ||
| 193 | u32 bit_value = 0; | ||
| 194 | union { | ||
| 195 | u32 qus32_value = 0; | ||
| 196 | u32 trit_value; | ||
| 197 | }; | ||
| 198 | }; | ||
| 199 | using IntegerEncodedVector = boost::container::static_vector< | ||
| 200 | IntegerEncodedValue, 256, | ||
| 201 | boost::container::static_vector_options< | ||
| 202 | boost::container::inplace_alignment<alignof(IntegerEncodedValue)>, | ||
| 203 | boost::container::throw_on_overflow<false>>::type>; | ||
| 204 | |||
| 205 | static void DecodeTritBlock(InputBitStream& bits, IntegerEncodedVector& result, u32 nBitsPerValue) { | ||
| 206 | // Implement the algorithm in section C.2.12 | ||
| 207 | std::array<u32, 5> m; | ||
| 208 | std::array<u32, 5> t; | ||
| 209 | u32 T; | ||
| 210 | |||
| 211 | // Read the trit encoded block according to | ||
| 212 | // table C.2.14 | ||
| 213 | m[0] = bits.ReadBits(nBitsPerValue); | ||
| 214 | T = bits.ReadBits<2>(); | ||
| 215 | m[1] = bits.ReadBits(nBitsPerValue); | ||
| 216 | T |= bits.ReadBits<2>() << 2; | ||
| 217 | m[2] = bits.ReadBits(nBitsPerValue); | ||
| 218 | T |= bits.ReadBit() << 4; | ||
| 219 | m[3] = bits.ReadBits(nBitsPerValue); | ||
| 220 | T |= bits.ReadBits<2>() << 5; | ||
| 221 | m[4] = bits.ReadBits(nBitsPerValue); | ||
| 222 | T |= bits.ReadBit() << 7; | ||
| 223 | |||
| 224 | u32 C = 0; | ||
| 225 | |||
| 226 | Bits<u32> Tb(T); | ||
| 227 | if (Tb(2, 4) == 7) { | ||
| 228 | C = (Tb(5, 7) << 2) | Tb(0, 1); | ||
| 229 | t[4] = t[3] = 2; | ||
| 230 | } else { | ||
| 231 | C = Tb(0, 4); | ||
| 232 | if (Tb(5, 6) == 3) { | ||
| 233 | t[4] = 2; | ||
| 234 | t[3] = Tb[7]; | ||
| 235 | } else { | ||
| 236 | t[4] = Tb[7]; | ||
| 237 | t[3] = Tb(5, 6); | ||
| 238 | } | ||
| 239 | } | ||
| 240 | |||
| 241 | Bits<u32> Cb(C); | ||
| 242 | if (Cb(0, 1) == 3) { | ||
| 243 | t[2] = 2; | ||
| 244 | t[1] = Cb[4]; | ||
| 245 | t[0] = (Cb[3] << 1) | (Cb[2] & ~Cb[3]); | ||
| 246 | } else if (Cb(2, 3) == 3) { | ||
| 247 | t[2] = 2; | ||
| 248 | t[1] = 2; | ||
| 249 | t[0] = Cb(0, 1); | ||
| 250 | } else { | ||
| 251 | t[2] = Cb[4]; | ||
| 252 | t[1] = Cb(2, 3); | ||
| 253 | t[0] = (Cb[1] << 1) | (Cb[0] & ~Cb[1]); | ||
| 254 | } | ||
| 255 | |||
| 256 | for (std::size_t i = 0; i < 5; ++i) { | ||
| 257 | IntegerEncodedValue& val = result.emplace_back(IntegerEncoding::Trit, nBitsPerValue); | ||
| 258 | val.bit_value = m[i]; | ||
| 259 | val.trit_value = t[i]; | ||
| 260 | } | ||
| 261 | } | ||
| 262 | |||
| 263 | static void DecodeQus32Block(InputBitStream& bits, IntegerEncodedVector& result, | ||
| 264 | u32 nBitsPerValue) { | ||
| 265 | // Implement the algorithm in section C.2.12 | ||
| 266 | u32 m[3]; | ||
| 267 | u32 q[3]; | ||
| 268 | u32 Q; | ||
| 269 | |||
| 270 | // Read the trit encoded block according to | ||
| 271 | // table C.2.15 | ||
| 272 | m[0] = bits.ReadBits(nBitsPerValue); | ||
| 273 | Q = bits.ReadBits<3>(); | ||
| 274 | m[1] = bits.ReadBits(nBitsPerValue); | ||
| 275 | Q |= bits.ReadBits<2>() << 3; | ||
| 276 | m[2] = bits.ReadBits(nBitsPerValue); | ||
| 277 | Q |= bits.ReadBits<2>() << 5; | ||
| 278 | |||
| 279 | Bits<u32> Qb(Q); | ||
| 280 | if (Qb(1, 2) == 3 && Qb(5, 6) == 0) { | ||
| 281 | q[0] = q[1] = 4; | ||
| 282 | q[2] = (Qb[0] << 2) | ((Qb[4] & ~Qb[0]) << 1) | (Qb[3] & ~Qb[0]); | ||
| 283 | } else { | ||
| 284 | u32 C = 0; | ||
| 285 | if (Qb(1, 2) == 3) { | ||
| 286 | q[2] = 4; | ||
| 287 | C = (Qb(3, 4) << 3) | ((~Qb(5, 6) & 3) << 1) | Qb[0]; | ||
| 288 | } else { | ||
| 289 | q[2] = Qb(5, 6); | ||
| 290 | C = Qb(0, 4); | ||
| 291 | } | ||
| 292 | |||
| 293 | Bits<u32> Cb(C); | ||
| 294 | if (Cb(0, 2) == 5) { | ||
| 295 | q[1] = 4; | ||
| 296 | q[0] = Cb(3, 4); | ||
| 297 | } else { | ||
| 298 | q[1] = Cb(3, 4); | ||
| 299 | q[0] = Cb(0, 2); | ||
| 300 | } | ||
| 301 | } | ||
| 302 | |||
| 303 | for (std::size_t i = 0; i < 3; ++i) { | ||
| 304 | IntegerEncodedValue& val = result.emplace_back(IntegerEncoding::Qus32, nBitsPerValue); | ||
| 305 | val.bit_value = m[i]; | ||
| 306 | val.qus32_value = q[i]; | ||
| 307 | } | ||
| 308 | } | ||
| 309 | |||
| 310 | // Returns a new instance of this struct that corresponds to the | ||
| 311 | // can take no more than maxval values | ||
| 312 | static constexpr IntegerEncodedValue CreateEncoding(u32 maxVal) { | ||
| 313 | while (maxVal > 0) { | ||
| 314 | u32 check = maxVal + 1; | ||
| 315 | |||
| 316 | // Is maxVal a power of two? | ||
| 317 | if (!(check & (check - 1))) { | ||
| 318 | return IntegerEncodedValue(IntegerEncoding::JustBits, Popcnt(maxVal)); | ||
| 319 | } | ||
| 320 | |||
| 321 | // Is maxVal of the type 3*2^n - 1? | ||
| 322 | if ((check % 3 == 0) && !((check / 3) & ((check / 3) - 1))) { | ||
| 323 | return IntegerEncodedValue(IntegerEncoding::Trit, Popcnt(check / 3 - 1)); | ||
| 324 | } | ||
| 325 | |||
| 326 | // Is maxVal of the type 5*2^n - 1? | ||
| 327 | if ((check % 5 == 0) && !((check / 5) & ((check / 5) - 1))) { | ||
| 328 | return IntegerEncodedValue(IntegerEncoding::Qus32, Popcnt(check / 5 - 1)); | ||
| 329 | } | ||
| 330 | |||
| 331 | // Apparently it can't be represented with a bounded integer sequence... | ||
| 332 | // just iterate. | ||
| 333 | maxVal--; | ||
| 334 | } | ||
| 335 | return IntegerEncodedValue(IntegerEncoding::JustBits, 0); | ||
| 336 | } | ||
| 337 | |||
| 338 | static constexpr std::array<IntegerEncodedValue, 256> MakeEncodedValues() { | ||
| 339 | std::array<IntegerEncodedValue, 256> encodings{}; | ||
| 340 | for (std::size_t i = 0; i < encodings.size(); ++i) { | ||
| 341 | encodings[i] = CreateEncoding(static_cast<u32>(i)); | ||
| 342 | } | ||
| 343 | return encodings; | ||
| 344 | } | ||
| 345 | |||
| 346 | static constexpr std::array EncodingsValues = MakeEncodedValues(); | ||
| 347 | |||
| 348 | // Fills result with the values that are encoded in the given | ||
| 349 | // bitstream. We must know beforehand what the maximum possible | ||
| 350 | // value is, and how many values we're decoding. | ||
| 351 | static void DecodeIntegerSequence(IntegerEncodedVector& result, InputBitStream& bits, u32 maxRange, | ||
| 352 | u32 nValues) { | ||
| 353 | // Determine encoding parameters | ||
| 354 | IntegerEncodedValue val = EncodingsValues[maxRange]; | ||
| 355 | |||
| 356 | // Start decoding | ||
| 357 | u32 nValsDecoded = 0; | ||
| 358 | while (nValsDecoded < nValues) { | ||
| 359 | switch (val.encoding) { | ||
| 360 | case IntegerEncoding::Qus32: | ||
| 361 | DecodeQus32Block(bits, result, val.num_bits); | ||
| 362 | nValsDecoded += 3; | ||
| 363 | break; | ||
| 364 | |||
| 365 | case IntegerEncoding::Trit: | ||
| 366 | DecodeTritBlock(bits, result, val.num_bits); | ||
| 367 | nValsDecoded += 5; | ||
| 368 | break; | ||
| 369 | |||
| 370 | case IntegerEncoding::JustBits: | ||
| 371 | val.bit_value = bits.ReadBits(val.num_bits); | ||
| 372 | result.push_back(val); | ||
| 373 | nValsDecoded++; | ||
| 374 | break; | ||
| 375 | } | ||
| 376 | } | ||
| 377 | } | ||
| 378 | |||
| 379 | namespace ASTCC { | ||
| 380 | |||
| 381 | struct TexelWeightParams { | ||
| 382 | u32 m_Width = 0; | ||
| 383 | u32 m_Height = 0; | ||
| 384 | bool m_bDualPlane = false; | ||
| 385 | u32 m_MaxWeight = 0; | ||
| 386 | bool m_bError = false; | ||
| 387 | bool m_bVoidExtentLDR = false; | ||
| 388 | bool m_bVoidExtentHDR = false; | ||
| 389 | |||
| 390 | u32 GetPackedBitSize() const { | ||
| 391 | // How many indices do we have? | ||
| 392 | u32 nIdxs = m_Height * m_Width; | ||
| 393 | if (m_bDualPlane) { | ||
| 394 | nIdxs *= 2; | ||
| 395 | } | ||
| 396 | |||
| 397 | return EncodingsValues[m_MaxWeight].GetBitLength(nIdxs); | ||
| 398 | } | ||
| 399 | |||
| 400 | u32 GetNumWeightValues() const { | ||
| 401 | u32 ret = m_Width * m_Height; | ||
| 402 | if (m_bDualPlane) { | ||
| 403 | ret *= 2; | ||
| 404 | } | ||
| 405 | return ret; | ||
| 406 | } | ||
| 407 | }; | ||
| 408 | |||
| 409 | static TexelWeightParams DecodeBlockInfo(InputBitStream& strm) { | ||
| 410 | TexelWeightParams params; | ||
| 411 | |||
| 412 | // Read the entire block mode all at once | ||
| 413 | u16 modeBits = static_cast<u16>(strm.ReadBits<11>()); | ||
| 414 | |||
| 415 | // Does this match the void extent block mode? | ||
| 416 | if ((modeBits & 0x01FF) == 0x1FC) { | ||
| 417 | if (modeBits & 0x200) { | ||
| 418 | params.m_bVoidExtentHDR = true; | ||
| 419 | } else { | ||
| 420 | params.m_bVoidExtentLDR = true; | ||
| 421 | } | ||
| 422 | |||
| 423 | // Next two bits must be one. | ||
| 424 | if (!(modeBits & 0x400) || !strm.ReadBit()) { | ||
| 425 | params.m_bError = true; | ||
| 426 | } | ||
| 427 | |||
| 428 | return params; | ||
| 429 | } | ||
| 430 | |||
| 431 | // First check if the last four bits are zero | ||
| 432 | if ((modeBits & 0xF) == 0) { | ||
| 433 | params.m_bError = true; | ||
| 434 | return params; | ||
| 435 | } | ||
| 436 | |||
| 437 | // If the last two bits are zero, then if bits | ||
| 438 | // [6-8] are all ones, this is also reserved. | ||
| 439 | if ((modeBits & 0x3) == 0 && (modeBits & 0x1C0) == 0x1C0) { | ||
| 440 | params.m_bError = true; | ||
| 441 | return params; | ||
| 442 | } | ||
| 443 | |||
| 444 | // Otherwise, there is no error... Figure out the layout | ||
| 445 | // of the block mode. Layout is determined by a number | ||
| 446 | // between 0 and 9 corresponding to table C.2.8 of the | ||
| 447 | // ASTC spec. | ||
| 448 | u32 layout = 0; | ||
| 449 | |||
| 450 | if ((modeBits & 0x1) || (modeBits & 0x2)) { | ||
| 451 | // layout is in [0-4] | ||
| 452 | if (modeBits & 0x8) { | ||
| 453 | // layout is in [2-4] | ||
| 454 | if (modeBits & 0x4) { | ||
| 455 | // layout is in [3-4] | ||
| 456 | if (modeBits & 0x100) { | ||
| 457 | layout = 4; | ||
| 458 | } else { | ||
| 459 | layout = 3; | ||
| 460 | } | ||
| 461 | } else { | ||
| 462 | layout = 2; | ||
| 463 | } | ||
| 464 | } else { | ||
| 465 | // layout is in [0-1] | ||
| 466 | if (modeBits & 0x4) { | ||
| 467 | layout = 1; | ||
| 468 | } else { | ||
| 469 | layout = 0; | ||
| 470 | } | ||
| 471 | } | ||
| 472 | } else { | ||
| 473 | // layout is in [5-9] | ||
| 474 | if (modeBits & 0x100) { | ||
| 475 | // layout is in [7-9] | ||
| 476 | if (modeBits & 0x80) { | ||
| 477 | // layout is in [7-8] | ||
| 478 | assert((modeBits & 0x40) == 0U); | ||
| 479 | if (modeBits & 0x20) { | ||
| 480 | layout = 8; | ||
| 481 | } else { | ||
| 482 | layout = 7; | ||
| 483 | } | ||
| 484 | } else { | ||
| 485 | layout = 9; | ||
| 486 | } | ||
| 487 | } else { | ||
| 488 | // layout is in [5-6] | ||
| 489 | if (modeBits & 0x80) { | ||
| 490 | layout = 6; | ||
| 491 | } else { | ||
| 492 | layout = 5; | ||
| 493 | } | ||
| 494 | } | ||
| 495 | } | ||
| 496 | |||
| 497 | assert(layout < 10); | ||
| 498 | |||
| 499 | // Determine R | ||
| 500 | u32 R = !!(modeBits & 0x10); | ||
| 501 | if (layout < 5) { | ||
| 502 | R |= (modeBits & 0x3) << 1; | ||
| 503 | } else { | ||
| 504 | R |= (modeBits & 0xC) >> 1; | ||
| 505 | } | ||
| 506 | assert(2 <= R && R <= 7); | ||
| 507 | |||
| 508 | // Determine width & height | ||
| 509 | switch (layout) { | ||
| 510 | case 0: { | ||
| 511 | u32 A = (modeBits >> 5) & 0x3; | ||
| 512 | u32 B = (modeBits >> 7) & 0x3; | ||
| 513 | params.m_Width = B + 4; | ||
| 514 | params.m_Height = A + 2; | ||
| 515 | break; | ||
| 516 | } | ||
| 517 | |||
| 518 | case 1: { | ||
| 519 | u32 A = (modeBits >> 5) & 0x3; | ||
| 520 | u32 B = (modeBits >> 7) & 0x3; | ||
| 521 | params.m_Width = B + 8; | ||
| 522 | params.m_Height = A + 2; | ||
| 523 | break; | ||
| 524 | } | ||
| 525 | |||
| 526 | case 2: { | ||
| 527 | u32 A = (modeBits >> 5) & 0x3; | ||
| 528 | u32 B = (modeBits >> 7) & 0x3; | ||
| 529 | params.m_Width = A + 2; | ||
| 530 | params.m_Height = B + 8; | ||
| 531 | break; | ||
| 532 | } | ||
| 533 | |||
| 534 | case 3: { | ||
| 535 | u32 A = (modeBits >> 5) & 0x3; | ||
| 536 | u32 B = (modeBits >> 7) & 0x1; | ||
| 537 | params.m_Width = A + 2; | ||
| 538 | params.m_Height = B + 6; | ||
| 539 | break; | ||
| 540 | } | ||
| 541 | |||
| 542 | case 4: { | ||
| 543 | u32 A = (modeBits >> 5) & 0x3; | ||
| 544 | u32 B = (modeBits >> 7) & 0x1; | ||
| 545 | params.m_Width = B + 2; | ||
| 546 | params.m_Height = A + 2; | ||
| 547 | break; | ||
| 548 | } | ||
| 549 | |||
| 550 | case 5: { | ||
| 551 | u32 A = (modeBits >> 5) & 0x3; | ||
| 552 | params.m_Width = 12; | ||
| 553 | params.m_Height = A + 2; | ||
| 554 | break; | ||
| 555 | } | ||
| 556 | |||
| 557 | case 6: { | ||
| 558 | u32 A = (modeBits >> 5) & 0x3; | ||
| 559 | params.m_Width = A + 2; | ||
| 560 | params.m_Height = 12; | ||
| 561 | break; | ||
| 562 | } | ||
| 563 | |||
| 564 | case 7: { | ||
| 565 | params.m_Width = 6; | ||
| 566 | params.m_Height = 10; | ||
| 567 | break; | ||
| 568 | } | ||
| 569 | |||
| 570 | case 8: { | ||
| 571 | params.m_Width = 10; | ||
| 572 | params.m_Height = 6; | ||
| 573 | break; | ||
| 574 | } | ||
| 575 | |||
| 576 | case 9: { | ||
| 577 | u32 A = (modeBits >> 5) & 0x3; | ||
| 578 | u32 B = (modeBits >> 9) & 0x3; | ||
| 579 | params.m_Width = A + 6; | ||
| 580 | params.m_Height = B + 6; | ||
| 581 | break; | ||
| 582 | } | ||
| 583 | |||
| 584 | default: | ||
| 585 | assert(false && "Don't know this layout..."); | ||
| 586 | params.m_bError = true; | ||
| 587 | break; | ||
| 588 | } | ||
| 589 | |||
| 590 | // Determine whether or not we're using dual planes | ||
| 591 | // and/or high precision layouts. | ||
| 592 | bool D = (layout != 9) && (modeBits & 0x400); | ||
| 593 | bool H = (layout != 9) && (modeBits & 0x200); | ||
| 594 | |||
| 595 | if (H) { | ||
| 596 | const u32 maxWeights[6] = {9, 11, 15, 19, 23, 31}; | ||
| 597 | params.m_MaxWeight = maxWeights[R - 2]; | ||
| 598 | } else { | ||
| 599 | const u32 maxWeights[6] = {1, 2, 3, 4, 5, 7}; | ||
| 600 | params.m_MaxWeight = maxWeights[R - 2]; | ||
| 601 | } | ||
| 602 | |||
| 603 | params.m_bDualPlane = D; | ||
| 604 | |||
| 605 | return params; | ||
| 606 | } | ||
| 607 | |||
| 608 | static void FillVoidExtentLDR(InputBitStream& strm, std::span<u32> outBuf, u32 blockWidth, | ||
| 609 | u32 blockHeight) { | ||
| 610 | // Don't actually care about the void extent, just read the bits... | ||
| 611 | for (s32 i = 0; i < 4; ++i) { | ||
| 612 | strm.ReadBits<13>(); | ||
| 613 | } | ||
| 614 | |||
| 615 | // Decode the RGBA components and renormalize them to the range [0, 255] | ||
| 616 | u16 r = static_cast<u16>(strm.ReadBits<16>()); | ||
| 617 | u16 g = static_cast<u16>(strm.ReadBits<16>()); | ||
| 618 | u16 b = static_cast<u16>(strm.ReadBits<16>()); | ||
| 619 | u16 a = static_cast<u16>(strm.ReadBits<16>()); | ||
| 620 | |||
| 621 | u32 rgba = (r >> 8) | (g & 0xFF00) | (static_cast<u32>(b) & 0xFF00) << 8 | | ||
| 622 | (static_cast<u32>(a) & 0xFF00) << 16; | ||
| 623 | |||
| 624 | for (u32 j = 0; j < blockHeight; j++) { | ||
| 625 | for (u32 i = 0; i < blockWidth; i++) { | ||
| 626 | outBuf[j * blockWidth + i] = rgba; | ||
| 627 | } | ||
| 628 | } | ||
| 629 | } | ||
| 630 | |||
| 631 | static void FillError(std::span<u32> outBuf, u32 blockWidth, u32 blockHeight) { | ||
| 632 | for (u32 j = 0; j < blockHeight; j++) { | ||
| 633 | for (u32 i = 0; i < blockWidth; i++) { | ||
| 634 | outBuf[j * blockWidth + i] = 0xFFFF00FF; | ||
| 635 | } | ||
| 636 | } | ||
| 637 | } | ||
| 638 | |||
| 639 | // Replicates low numBits such that [(toBit - 1):(toBit - 1 - fromBit)] | ||
| 640 | // is the same as [(numBits - 1):0] and repeats all the way down. | ||
| 641 | template <typename IntType> | ||
| 642 | static constexpr IntType Replicate(IntType val, u32 numBits, u32 toBit) { | ||
| 643 | if (numBits == 0) { | ||
| 644 | return 0; | ||
| 645 | } | ||
| 646 | if (toBit == 0) { | ||
| 647 | return 0; | ||
| 648 | } | ||
| 649 | const IntType v = val & static_cast<IntType>((1 << numBits) - 1); | ||
| 650 | IntType res = v; | ||
| 651 | u32 reslen = numBits; | ||
| 652 | while (reslen < toBit) { | ||
| 653 | u32 comp = 0; | ||
| 654 | if (numBits > toBit - reslen) { | ||
| 655 | u32 newshift = toBit - reslen; | ||
| 656 | comp = numBits - newshift; | ||
| 657 | numBits = newshift; | ||
| 658 | } | ||
| 659 | res = static_cast<IntType>(res << numBits); | ||
| 660 | res = static_cast<IntType>(res | (v >> comp)); | ||
| 661 | reslen += numBits; | ||
| 662 | } | ||
| 663 | return res; | ||
| 664 | } | ||
| 665 | |||
| 666 | static constexpr std::size_t NumReplicateEntries(u32 num_bits) { | ||
| 667 | return std::size_t(1) << num_bits; | ||
| 668 | } | ||
| 669 | |||
| 670 | template <typename IntType, u32 num_bits, u32 to_bit> | ||
| 671 | static constexpr auto MakeReplicateTable() { | ||
| 672 | std::array<IntType, NumReplicateEntries(num_bits)> table{}; | ||
| 673 | for (IntType value = 0; value < static_cast<IntType>(std::size(table)); ++value) { | ||
| 674 | table[value] = Replicate(value, num_bits, to_bit); | ||
| 675 | } | ||
| 676 | return table; | ||
| 677 | } | ||
| 678 | |||
| 679 | static constexpr auto REPLICATE_BYTE_TO_16_TABLE = MakeReplicateTable<u32, 8, 16>(); | ||
| 680 | static constexpr u32 ReplicateByteTo16(std::size_t value) { | ||
| 681 | return REPLICATE_BYTE_TO_16_TABLE[value]; | ||
| 682 | } | ||
| 683 | |||
| 684 | static constexpr auto REPLICATE_BIT_TO_7_TABLE = MakeReplicateTable<u32, 1, 7>(); | ||
| 685 | static constexpr u32 ReplicateBitTo7(std::size_t value) { | ||
| 686 | return REPLICATE_BIT_TO_7_TABLE[value]; | ||
| 687 | } | ||
| 688 | |||
| 689 | static constexpr auto REPLICATE_BIT_TO_9_TABLE = MakeReplicateTable<u32, 1, 9>(); | ||
| 690 | static constexpr u32 ReplicateBitTo9(std::size_t value) { | ||
| 691 | return REPLICATE_BIT_TO_9_TABLE[value]; | ||
| 692 | } | ||
| 693 | |||
| 694 | static constexpr auto REPLICATE_1_BIT_TO_8_TABLE = MakeReplicateTable<u32, 1, 8>(); | ||
| 695 | static constexpr auto REPLICATE_2_BIT_TO_8_TABLE = MakeReplicateTable<u32, 2, 8>(); | ||
| 696 | static constexpr auto REPLICATE_3_BIT_TO_8_TABLE = MakeReplicateTable<u32, 3, 8>(); | ||
| 697 | static constexpr auto REPLICATE_4_BIT_TO_8_TABLE = MakeReplicateTable<u32, 4, 8>(); | ||
| 698 | static constexpr auto REPLICATE_5_BIT_TO_8_TABLE = MakeReplicateTable<u32, 5, 8>(); | ||
| 699 | static constexpr auto REPLICATE_6_BIT_TO_8_TABLE = MakeReplicateTable<u32, 6, 8>(); | ||
| 700 | static constexpr auto REPLICATE_7_BIT_TO_8_TABLE = MakeReplicateTable<u32, 7, 8>(); | ||
| 701 | static constexpr auto REPLICATE_8_BIT_TO_8_TABLE = MakeReplicateTable<u32, 8, 8>(); | ||
| 702 | /// Use a precompiled table with the most common usages, if it's not in the expected range, fallback | ||
| 703 | /// to the runtime implementation | ||
| 704 | static constexpr u32 FastReplicateTo8(u32 value, u32 num_bits) { | ||
| 705 | switch (num_bits) { | ||
| 706 | case 1: | ||
| 707 | return REPLICATE_1_BIT_TO_8_TABLE[value]; | ||
| 708 | case 2: | ||
| 709 | return REPLICATE_2_BIT_TO_8_TABLE[value]; | ||
| 710 | case 3: | ||
| 711 | return REPLICATE_3_BIT_TO_8_TABLE[value]; | ||
| 712 | case 4: | ||
| 713 | return REPLICATE_4_BIT_TO_8_TABLE[value]; | ||
| 714 | case 5: | ||
| 715 | return REPLICATE_5_BIT_TO_8_TABLE[value]; | ||
| 716 | case 6: | ||
| 717 | return REPLICATE_6_BIT_TO_8_TABLE[value]; | ||
| 718 | case 7: | ||
| 719 | return REPLICATE_7_BIT_TO_8_TABLE[value]; | ||
| 720 | case 8: | ||
| 721 | return REPLICATE_8_BIT_TO_8_TABLE[value]; | ||
| 722 | default: | ||
| 723 | return Replicate(value, num_bits, 8); | ||
| 724 | } | ||
| 725 | } | ||
| 726 | |||
| 727 | static constexpr auto REPLICATE_1_BIT_TO_6_TABLE = MakeReplicateTable<u32, 1, 6>(); | ||
| 728 | static constexpr auto REPLICATE_2_BIT_TO_6_TABLE = MakeReplicateTable<u32, 2, 6>(); | ||
| 729 | static constexpr auto REPLICATE_3_BIT_TO_6_TABLE = MakeReplicateTable<u32, 3, 6>(); | ||
| 730 | static constexpr auto REPLICATE_4_BIT_TO_6_TABLE = MakeReplicateTable<u32, 4, 6>(); | ||
| 731 | static constexpr auto REPLICATE_5_BIT_TO_6_TABLE = MakeReplicateTable<u32, 5, 6>(); | ||
| 732 | static constexpr u32 FastReplicateTo6(u32 value, u32 num_bits) { | ||
| 733 | switch (num_bits) { | ||
| 734 | case 1: | ||
| 735 | return REPLICATE_1_BIT_TO_6_TABLE[value]; | ||
| 736 | case 2: | ||
| 737 | return REPLICATE_2_BIT_TO_6_TABLE[value]; | ||
| 738 | case 3: | ||
| 739 | return REPLICATE_3_BIT_TO_6_TABLE[value]; | ||
| 740 | case 4: | ||
| 741 | return REPLICATE_4_BIT_TO_6_TABLE[value]; | ||
| 742 | case 5: | ||
| 743 | return REPLICATE_5_BIT_TO_6_TABLE[value]; | ||
| 744 | default: | ||
| 745 | return Replicate(value, num_bits, 6); | ||
| 746 | } | ||
| 747 | } | ||
| 748 | |||
| 749 | class Pixel { | ||
| 750 | protected: | ||
| 751 | using ChannelType = s16; | ||
| 752 | u8 m_BitDepth[4] = {8, 8, 8, 8}; | ||
| 753 | s16 color[4] = {}; | ||
| 754 | |||
| 755 | public: | ||
| 756 | Pixel() = default; | ||
| 757 | Pixel(u32 a, u32 r, u32 g, u32 b, u32 bitDepth = 8) | ||
| 758 | : m_BitDepth{u8(bitDepth), u8(bitDepth), u8(bitDepth), u8(bitDepth)}, | ||
| 759 | color{static_cast<ChannelType>(a), static_cast<ChannelType>(r), | ||
| 760 | static_cast<ChannelType>(g), static_cast<ChannelType>(b)} {} | ||
| 761 | |||
| 762 | // Changes the depth of each pixel. This scales the values to | ||
| 763 | // the appropriate bit depth by either truncating the least | ||
| 764 | // significant bits when going from larger to smaller bit depth | ||
| 765 | // or by repeating the most significant bits when going from | ||
| 766 | // smaller to larger bit depths. | ||
| 767 | void ChangeBitDepth() { | ||
| 768 | for (u32 i = 0; i < 4; i++) { | ||
| 769 | Component(i) = ChangeBitDepth(Component(i), m_BitDepth[i]); | ||
| 770 | m_BitDepth[i] = 8; | ||
| 771 | } | ||
| 772 | } | ||
| 773 | |||
| 774 | template <typename IntType> | ||
| 775 | static float ConvertChannelToFloat(IntType channel, u8 bitDepth) { | ||
| 776 | float denominator = static_cast<float>((1 << bitDepth) - 1); | ||
| 777 | return static_cast<float>(channel) / denominator; | ||
| 778 | } | ||
| 779 | |||
| 780 | // Changes the bit depth of a single component. See the comment | ||
| 781 | // above for how we do this. | ||
| 782 | static ChannelType ChangeBitDepth(Pixel::ChannelType val, u8 oldDepth) { | ||
| 783 | assert(oldDepth <= 8); | ||
| 784 | |||
| 785 | if (oldDepth == 8) { | ||
| 786 | // Do nothing | ||
| 787 | return val; | ||
| 788 | } else if (oldDepth == 0) { | ||
| 789 | return static_cast<ChannelType>((1 << 8) - 1); | ||
| 790 | } else if (8 > oldDepth) { | ||
| 791 | return static_cast<ChannelType>(FastReplicateTo8(static_cast<u32>(val), oldDepth)); | ||
| 792 | } else { | ||
| 793 | // oldDepth > newDepth | ||
| 794 | const u8 bitsWasted = static_cast<u8>(oldDepth - 8); | ||
| 795 | u16 v = static_cast<u16>(val); | ||
| 796 | v = static_cast<u16>((v + (1 << (bitsWasted - 1))) >> bitsWasted); | ||
| 797 | v = ::std::min<u16>(::std::max<u16>(0, v), static_cast<u16>((1 << 8) - 1)); | ||
| 798 | return static_cast<u8>(v); | ||
| 799 | } | ||
| 800 | |||
| 801 | assert(false && "We shouldn't get here."); | ||
| 802 | return 0; | ||
| 803 | } | ||
| 804 | |||
| 805 | const ChannelType& A() const { | ||
| 806 | return color[0]; | ||
| 807 | } | ||
| 808 | ChannelType& A() { | ||
| 809 | return color[0]; | ||
| 810 | } | ||
| 811 | const ChannelType& R() const { | ||
| 812 | return color[1]; | ||
| 813 | } | ||
| 814 | ChannelType& R() { | ||
| 815 | return color[1]; | ||
| 816 | } | ||
| 817 | const ChannelType& G() const { | ||
| 818 | return color[2]; | ||
| 819 | } | ||
| 820 | ChannelType& G() { | ||
| 821 | return color[2]; | ||
| 822 | } | ||
| 823 | const ChannelType& B() const { | ||
| 824 | return color[3]; | ||
| 825 | } | ||
| 826 | ChannelType& B() { | ||
| 827 | return color[3]; | ||
| 828 | } | ||
| 829 | const ChannelType& Component(u32 idx) const { | ||
| 830 | return color[idx]; | ||
| 831 | } | ||
| 832 | ChannelType& Component(u32 idx) { | ||
| 833 | return color[idx]; | ||
| 834 | } | ||
| 835 | |||
| 836 | void GetBitDepth(u8 (&outDepth)[4]) const { | ||
| 837 | for (s32 i = 0; i < 4; i++) { | ||
| 838 | outDepth[i] = m_BitDepth[i]; | ||
| 839 | } | ||
| 840 | } | ||
| 841 | |||
| 842 | // Take all of the components, transform them to their 8-bit variants, | ||
| 843 | // and then pack each channel into an R8G8B8A8 32-bit integer. We assume | ||
| 844 | // that the architecture is little-endian, so the alpha channel will end | ||
| 845 | // up in the most-significant byte. | ||
| 846 | u32 Pack() const { | ||
| 847 | Pixel eightBit(*this); | ||
| 848 | eightBit.ChangeBitDepth(); | ||
| 849 | |||
| 850 | u32 r = 0; | ||
| 851 | r |= eightBit.A(); | ||
| 852 | r <<= 8; | ||
| 853 | r |= eightBit.B(); | ||
| 854 | r <<= 8; | ||
| 855 | r |= eightBit.G(); | ||
| 856 | r <<= 8; | ||
| 857 | r |= eightBit.R(); | ||
| 858 | return r; | ||
| 859 | } | ||
| 860 | |||
| 861 | // Clamps the pixel to the range [0,255] | ||
| 862 | void ClampByte() { | ||
| 863 | for (u32 i = 0; i < 4; i++) { | ||
| 864 | color[i] = (color[i] < 0) ? 0 : ((color[i] > 255) ? 255 : color[i]); | ||
| 865 | } | ||
| 866 | } | ||
| 867 | |||
| 868 | void MakeOpaque() { | ||
| 869 | A() = 255; | ||
| 870 | } | ||
| 871 | }; | ||
| 872 | |||
| 873 | static void DecodeColorValues(u32* out, std::span<u8> data, const u32* modes, const u32 nPartitions, | ||
| 874 | const u32 nBitsForColorData) { | ||
| 875 | // First figure out how many color values we have | ||
| 876 | u32 nValues = 0; | ||
| 877 | for (u32 i = 0; i < nPartitions; i++) { | ||
| 878 | nValues += ((modes[i] >> 2) + 1) << 1; | ||
| 879 | } | ||
| 880 | |||
| 881 | // Then based on the number of values and the remaining number of bits, | ||
| 882 | // figure out the max value for each of them... | ||
| 883 | u32 range = 256; | ||
| 884 | while (--range > 0) { | ||
| 885 | IntegerEncodedValue val = EncodingsValues[range]; | ||
| 886 | u32 bitLength = val.GetBitLength(nValues); | ||
| 887 | if (bitLength <= nBitsForColorData) { | ||
| 888 | // Find the smallest possible range that matches the given encoding | ||
| 889 | while (--range > 0) { | ||
| 890 | IntegerEncodedValue newval = EncodingsValues[range]; | ||
| 891 | if (!newval.MatchesEncoding(val)) { | ||
| 892 | break; | ||
| 893 | } | ||
| 894 | } | ||
| 895 | |||
| 896 | // Return to last matching range. | ||
| 897 | range++; | ||
| 898 | break; | ||
| 899 | } | ||
| 900 | } | ||
| 901 | |||
| 902 | // We now have enough to decode our integer sequence. | ||
| 903 | IntegerEncodedVector decodedColorValues; | ||
| 904 | |||
| 905 | InputBitStream colorStream(data, 0); | ||
| 906 | DecodeIntegerSequence(decodedColorValues, colorStream, range, nValues); | ||
| 907 | |||
| 908 | // Once we have the decoded values, we need to dequantize them to the 0-255 range | ||
| 909 | // This procedure is outlined in ASTC spec C.2.13 | ||
| 910 | u32 outIdx = 0; | ||
| 911 | for (auto itr = decodedColorValues.begin(); itr != decodedColorValues.end(); ++itr) { | ||
| 912 | // Have we already decoded all that we need? | ||
| 913 | if (outIdx >= nValues) { | ||
| 914 | break; | ||
| 915 | } | ||
| 916 | |||
| 917 | const IntegerEncodedValue& val = *itr; | ||
| 918 | u32 bitlen = val.num_bits; | ||
| 919 | u32 bitval = val.bit_value; | ||
| 920 | |||
| 921 | assert(bitlen >= 1); | ||
| 922 | |||
| 923 | u32 A = 0, B = 0, C = 0, D = 0; | ||
| 924 | // A is just the lsb replicated 9 times. | ||
| 925 | A = ReplicateBitTo9(bitval & 1); | ||
| 926 | |||
| 927 | switch (val.encoding) { | ||
| 928 | // Replicate bits | ||
| 929 | case IntegerEncoding::JustBits: | ||
| 930 | out[outIdx++] = FastReplicateTo8(bitval, bitlen); | ||
| 931 | break; | ||
| 932 | |||
| 933 | // Use algorithm in C.2.13 | ||
| 934 | case IntegerEncoding::Trit: { | ||
| 935 | |||
| 936 | D = val.trit_value; | ||
| 937 | |||
| 938 | switch (bitlen) { | ||
| 939 | case 1: { | ||
| 940 | C = 204; | ||
| 941 | } break; | ||
| 942 | |||
| 943 | case 2: { | ||
| 944 | C = 93; | ||
| 945 | // B = b000b0bb0 | ||
| 946 | u32 b = (bitval >> 1) & 1; | ||
| 947 | B = (b << 8) | (b << 4) | (b << 2) | (b << 1); | ||
| 948 | } break; | ||
| 949 | |||
| 950 | case 3: { | ||
| 951 | C = 44; | ||
| 952 | // B = cb000cbcb | ||
| 953 | u32 cb = (bitval >> 1) & 3; | ||
| 954 | B = (cb << 7) | (cb << 2) | cb; | ||
| 955 | } break; | ||
| 956 | |||
| 957 | case 4: { | ||
| 958 | C = 22; | ||
| 959 | // B = dcb000dcb | ||
| 960 | u32 dcb = (bitval >> 1) & 7; | ||
| 961 | B = (dcb << 6) | dcb; | ||
| 962 | } break; | ||
| 963 | |||
| 964 | case 5: { | ||
| 965 | C = 11; | ||
| 966 | // B = edcb000ed | ||
| 967 | u32 edcb = (bitval >> 1) & 0xF; | ||
| 968 | B = (edcb << 5) | (edcb >> 2); | ||
| 969 | } break; | ||
| 970 | |||
| 971 | case 6: { | ||
| 972 | C = 5; | ||
| 973 | // B = fedcb000f | ||
| 974 | u32 fedcb = (bitval >> 1) & 0x1F; | ||
| 975 | B = (fedcb << 4) | (fedcb >> 4); | ||
| 976 | } break; | ||
| 977 | |||
| 978 | default: | ||
| 979 | assert(false && "Unsupported trit encoding for color values!"); | ||
| 980 | break; | ||
| 981 | } // switch(bitlen) | ||
| 982 | } // case IntegerEncoding::Trit | ||
| 983 | break; | ||
| 984 | |||
| 985 | case IntegerEncoding::Qus32: { | ||
| 986 | |||
| 987 | D = val.qus32_value; | ||
| 988 | |||
| 989 | switch (bitlen) { | ||
| 990 | case 1: { | ||
| 991 | C = 113; | ||
| 992 | } break; | ||
| 993 | |||
| 994 | case 2: { | ||
| 995 | C = 54; | ||
| 996 | // B = b0000bb00 | ||
| 997 | u32 b = (bitval >> 1) & 1; | ||
| 998 | B = (b << 8) | (b << 3) | (b << 2); | ||
| 999 | } break; | ||
| 1000 | |||
| 1001 | case 3: { | ||
| 1002 | C = 26; | ||
| 1003 | // B = cb0000cbc | ||
| 1004 | u32 cb = (bitval >> 1) & 3; | ||
| 1005 | B = (cb << 7) | (cb << 1) | (cb >> 1); | ||
| 1006 | } break; | ||
| 1007 | |||
| 1008 | case 4: { | ||
| 1009 | C = 13; | ||
| 1010 | // B = dcb0000dc | ||
| 1011 | u32 dcb = (bitval >> 1) & 7; | ||
| 1012 | B = (dcb << 6) | (dcb >> 1); | ||
| 1013 | } break; | ||
| 1014 | |||
| 1015 | case 5: { | ||
| 1016 | C = 6; | ||
| 1017 | // B = edcb0000e | ||
| 1018 | u32 edcb = (bitval >> 1) & 0xF; | ||
| 1019 | B = (edcb << 5) | (edcb >> 3); | ||
| 1020 | } break; | ||
| 1021 | |||
| 1022 | default: | ||
| 1023 | assert(false && "Unsupported quint encoding for color values!"); | ||
| 1024 | break; | ||
| 1025 | } // switch(bitlen) | ||
| 1026 | } // case IntegerEncoding::Qus32 | ||
| 1027 | break; | ||
| 1028 | } // switch(val.encoding) | ||
| 1029 | |||
| 1030 | if (val.encoding != IntegerEncoding::JustBits) { | ||
| 1031 | u32 T = D * C + B; | ||
| 1032 | T ^= A; | ||
| 1033 | T = (A & 0x80) | (T >> 2); | ||
| 1034 | out[outIdx++] = T; | ||
| 1035 | } | ||
| 1036 | } | ||
| 1037 | |||
| 1038 | // Make sure that each of our values is in the proper range... | ||
| 1039 | for (u32 i = 0; i < nValues; i++) { | ||
| 1040 | assert(out[i] <= 255); | ||
| 1041 | } | ||
| 1042 | } | ||
| 1043 | |||
| 1044 | static u32 UnquantizeTexelWeight(const IntegerEncodedValue& val) { | ||
| 1045 | u32 bitval = val.bit_value; | ||
| 1046 | u32 bitlen = val.num_bits; | ||
| 1047 | |||
| 1048 | u32 A = ReplicateBitTo7(bitval & 1); | ||
| 1049 | u32 B = 0, C = 0, D = 0; | ||
| 1050 | |||
| 1051 | u32 result = 0; | ||
| 1052 | switch (val.encoding) { | ||
| 1053 | case IntegerEncoding::JustBits: | ||
| 1054 | result = FastReplicateTo6(bitval, bitlen); | ||
| 1055 | break; | ||
| 1056 | |||
| 1057 | case IntegerEncoding::Trit: { | ||
| 1058 | D = val.trit_value; | ||
| 1059 | assert(D < 3); | ||
| 1060 | |||
| 1061 | switch (bitlen) { | ||
| 1062 | case 0: { | ||
| 1063 | u32 results[3] = {0, 32, 63}; | ||
| 1064 | result = results[D]; | ||
| 1065 | } break; | ||
| 1066 | |||
| 1067 | case 1: { | ||
| 1068 | C = 50; | ||
| 1069 | } break; | ||
| 1070 | |||
| 1071 | case 2: { | ||
| 1072 | C = 23; | ||
| 1073 | u32 b = (bitval >> 1) & 1; | ||
| 1074 | B = (b << 6) | (b << 2) | b; | ||
| 1075 | } break; | ||
| 1076 | |||
| 1077 | case 3: { | ||
| 1078 | C = 11; | ||
| 1079 | u32 cb = (bitval >> 1) & 3; | ||
| 1080 | B = (cb << 5) | cb; | ||
| 1081 | } break; | ||
| 1082 | |||
| 1083 | default: | ||
| 1084 | assert(false && "Invalid trit encoding for texel weight"); | ||
| 1085 | break; | ||
| 1086 | } | ||
| 1087 | } break; | ||
| 1088 | |||
| 1089 | case IntegerEncoding::Qus32: { | ||
| 1090 | D = val.qus32_value; | ||
| 1091 | assert(D < 5); | ||
| 1092 | |||
| 1093 | switch (bitlen) { | ||
| 1094 | case 0: { | ||
| 1095 | u32 results[5] = {0, 16, 32, 47, 63}; | ||
| 1096 | result = results[D]; | ||
| 1097 | } break; | ||
| 1098 | |||
| 1099 | case 1: { | ||
| 1100 | C = 28; | ||
| 1101 | } break; | ||
| 1102 | |||
| 1103 | case 2: { | ||
| 1104 | C = 13; | ||
| 1105 | u32 b = (bitval >> 1) & 1; | ||
| 1106 | B = (b << 6) | (b << 1); | ||
| 1107 | } break; | ||
| 1108 | |||
| 1109 | default: | ||
| 1110 | assert(false && "Invalid quint encoding for texel weight"); | ||
| 1111 | break; | ||
| 1112 | } | ||
| 1113 | } break; | ||
| 1114 | } | ||
| 1115 | |||
| 1116 | if (val.encoding != IntegerEncoding::JustBits && bitlen > 0) { | ||
| 1117 | // Decode the value... | ||
| 1118 | result = D * C + B; | ||
| 1119 | result ^= A; | ||
| 1120 | result = (A & 0x20) | (result >> 2); | ||
| 1121 | } | ||
| 1122 | |||
| 1123 | assert(result < 64); | ||
| 1124 | |||
| 1125 | // Change from [0,63] to [0,64] | ||
| 1126 | if (result > 32) { | ||
| 1127 | result += 1; | ||
| 1128 | } | ||
| 1129 | |||
| 1130 | return result; | ||
| 1131 | } | ||
| 1132 | |||
| 1133 | static void UnquantizeTexelWeights(u32 out[2][144], const IntegerEncodedVector& weights, | ||
| 1134 | const TexelWeightParams& params, const u32 blockWidth, | ||
| 1135 | const u32 blockHeight) { | ||
| 1136 | u32 weightIdx = 0; | ||
| 1137 | u32 unquantized[2][144]; | ||
| 1138 | |||
| 1139 | for (auto itr = weights.begin(); itr != weights.end(); ++itr) { | ||
| 1140 | unquantized[0][weightIdx] = UnquantizeTexelWeight(*itr); | ||
| 1141 | |||
| 1142 | if (params.m_bDualPlane) { | ||
| 1143 | ++itr; | ||
| 1144 | unquantized[1][weightIdx] = UnquantizeTexelWeight(*itr); | ||
| 1145 | if (itr == weights.end()) { | ||
| 1146 | break; | ||
| 1147 | } | ||
| 1148 | } | ||
| 1149 | |||
| 1150 | if (++weightIdx >= (params.m_Width * params.m_Height)) | ||
| 1151 | break; | ||
| 1152 | } | ||
| 1153 | |||
| 1154 | // Do infill if necessary (Section C.2.18) ... | ||
| 1155 | u32 Ds = (1024 + (blockWidth / 2)) / (blockWidth - 1); | ||
| 1156 | u32 Dt = (1024 + (blockHeight / 2)) / (blockHeight - 1); | ||
| 1157 | |||
| 1158 | const u32 kPlaneScale = params.m_bDualPlane ? 2U : 1U; | ||
| 1159 | for (u32 plane = 0; plane < kPlaneScale; plane++) | ||
| 1160 | for (u32 t = 0; t < blockHeight; t++) | ||
| 1161 | for (u32 s = 0; s < blockWidth; s++) { | ||
| 1162 | u32 cs = Ds * s; | ||
| 1163 | u32 ct = Dt * t; | ||
| 1164 | |||
| 1165 | u32 gs = (cs * (params.m_Width - 1) + 32) >> 6; | ||
| 1166 | u32 gt = (ct * (params.m_Height - 1) + 32) >> 6; | ||
| 1167 | |||
| 1168 | u32 js = gs >> 4; | ||
| 1169 | u32 fs = gs & 0xF; | ||
| 1170 | |||
| 1171 | u32 jt = gt >> 4; | ||
| 1172 | u32 ft = gt & 0x0F; | ||
| 1173 | |||
| 1174 | u32 w11 = (fs * ft + 8) >> 4; | ||
| 1175 | u32 w10 = ft - w11; | ||
| 1176 | u32 w01 = fs - w11; | ||
| 1177 | u32 w00 = 16 - fs - ft + w11; | ||
| 1178 | |||
| 1179 | u32 v0 = js + jt * params.m_Width; | ||
| 1180 | |||
| 1181 | #define FIND_TEXEL(tidx, bidx) \ | ||
| 1182 | u32 p##bidx = 0; \ | ||
| 1183 | do { \ | ||
| 1184 | if ((tidx) < (params.m_Width * params.m_Height)) { \ | ||
| 1185 | p##bidx = unquantized[plane][(tidx)]; \ | ||
| 1186 | } \ | ||
| 1187 | } while (0) | ||
| 1188 | |||
| 1189 | FIND_TEXEL(v0, 00); | ||
| 1190 | FIND_TEXEL(v0 + 1, 01); | ||
| 1191 | FIND_TEXEL(v0 + params.m_Width, 10); | ||
| 1192 | FIND_TEXEL(v0 + params.m_Width + 1, 11); | ||
| 1193 | |||
| 1194 | #undef FIND_TEXEL | ||
| 1195 | |||
| 1196 | out[plane][t * blockWidth + s] = | ||
| 1197 | (p00 * w00 + p01 * w01 + p10 * w10 + p11 * w11 + 8) >> 4; | ||
| 1198 | } | ||
| 1199 | } | ||
| 1200 | |||
| 1201 | // Transfers a bit as described in C.2.14 | ||
| 1202 | static inline void BitTransferSigned(s32& a, s32& b) { | ||
| 1203 | b >>= 1; | ||
| 1204 | b |= a & 0x80; | ||
| 1205 | a >>= 1; | ||
| 1206 | a &= 0x3F; | ||
| 1207 | if (a & 0x20) | ||
| 1208 | a -= 0x40; | ||
| 1209 | } | ||
| 1210 | |||
| 1211 | // Adds more precision to the blue channel as described | ||
| 1212 | // in C.2.14 | ||
| 1213 | static inline Pixel BlueContract(s32 a, s32 r, s32 g, s32 b) { | ||
| 1214 | return Pixel(static_cast<s16>(a), static_cast<s16>((r + b) >> 1), | ||
| 1215 | static_cast<s16>((g + b) >> 1), static_cast<s16>(b)); | ||
| 1216 | } | ||
| 1217 | |||
| 1218 | // Partition selection functions as specified in | ||
| 1219 | // C.2.21 | ||
| 1220 | static inline u32 hash52(u32 p) { | ||
| 1221 | p ^= p >> 15; | ||
| 1222 | p -= p << 17; | ||
| 1223 | p += p << 7; | ||
| 1224 | p += p << 4; | ||
| 1225 | p ^= p >> 5; | ||
| 1226 | p += p << 16; | ||
| 1227 | p ^= p >> 7; | ||
| 1228 | p ^= p >> 3; | ||
| 1229 | p ^= p << 6; | ||
| 1230 | p ^= p >> 17; | ||
| 1231 | return p; | ||
| 1232 | } | ||
| 1233 | |||
| 1234 | static u32 SelectPartition(s32 seed, s32 x, s32 y, s32 z, s32 partitionCount, s32 smallBlock) { | ||
| 1235 | if (1 == partitionCount) | ||
| 1236 | return 0; | ||
| 1237 | |||
| 1238 | if (smallBlock) { | ||
| 1239 | x <<= 1; | ||
| 1240 | y <<= 1; | ||
| 1241 | z <<= 1; | ||
| 1242 | } | ||
| 1243 | |||
| 1244 | seed += (partitionCount - 1) * 1024; | ||
| 1245 | |||
| 1246 | u32 rnum = hash52(static_cast<u32>(seed)); | ||
| 1247 | u8 seed1 = static_cast<u8>(rnum & 0xF); | ||
| 1248 | u8 seed2 = static_cast<u8>((rnum >> 4) & 0xF); | ||
| 1249 | u8 seed3 = static_cast<u8>((rnum >> 8) & 0xF); | ||
| 1250 | u8 seed4 = static_cast<u8>((rnum >> 12) & 0xF); | ||
| 1251 | u8 seed5 = static_cast<u8>((rnum >> 16) & 0xF); | ||
| 1252 | u8 seed6 = static_cast<u8>((rnum >> 20) & 0xF); | ||
| 1253 | u8 seed7 = static_cast<u8>((rnum >> 24) & 0xF); | ||
| 1254 | u8 seed8 = static_cast<u8>((rnum >> 28) & 0xF); | ||
| 1255 | u8 seed9 = static_cast<u8>((rnum >> 18) & 0xF); | ||
| 1256 | u8 seed10 = static_cast<u8>((rnum >> 22) & 0xF); | ||
| 1257 | u8 seed11 = static_cast<u8>((rnum >> 26) & 0xF); | ||
| 1258 | u8 seed12 = static_cast<u8>(((rnum >> 30) | (rnum << 2)) & 0xF); | ||
| 1259 | |||
| 1260 | seed1 = static_cast<u8>(seed1 * seed1); | ||
| 1261 | seed2 = static_cast<u8>(seed2 * seed2); | ||
| 1262 | seed3 = static_cast<u8>(seed3 * seed3); | ||
| 1263 | seed4 = static_cast<u8>(seed4 * seed4); | ||
| 1264 | seed5 = static_cast<u8>(seed5 * seed5); | ||
| 1265 | seed6 = static_cast<u8>(seed6 * seed6); | ||
| 1266 | seed7 = static_cast<u8>(seed7 * seed7); | ||
| 1267 | seed8 = static_cast<u8>(seed8 * seed8); | ||
| 1268 | seed9 = static_cast<u8>(seed9 * seed9); | ||
| 1269 | seed10 = static_cast<u8>(seed10 * seed10); | ||
| 1270 | seed11 = static_cast<u8>(seed11 * seed11); | ||
| 1271 | seed12 = static_cast<u8>(seed12 * seed12); | ||
| 1272 | |||
| 1273 | s32 sh1, sh2, sh3; | ||
| 1274 | if (seed & 1) { | ||
| 1275 | sh1 = (seed & 2) ? 4 : 5; | ||
| 1276 | sh2 = (partitionCount == 3) ? 6 : 5; | ||
| 1277 | } else { | ||
| 1278 | sh1 = (partitionCount == 3) ? 6 : 5; | ||
| 1279 | sh2 = (seed & 2) ? 4 : 5; | ||
| 1280 | } | ||
| 1281 | sh3 = (seed & 0x10) ? sh1 : sh2; | ||
| 1282 | |||
| 1283 | seed1 = static_cast<u8>(seed1 >> sh1); | ||
| 1284 | seed2 = static_cast<u8>(seed2 >> sh2); | ||
| 1285 | seed3 = static_cast<u8>(seed3 >> sh1); | ||
| 1286 | seed4 = static_cast<u8>(seed4 >> sh2); | ||
| 1287 | seed5 = static_cast<u8>(seed5 >> sh1); | ||
| 1288 | seed6 = static_cast<u8>(seed6 >> sh2); | ||
| 1289 | seed7 = static_cast<u8>(seed7 >> sh1); | ||
| 1290 | seed8 = static_cast<u8>(seed8 >> sh2); | ||
| 1291 | seed9 = static_cast<u8>(seed9 >> sh3); | ||
| 1292 | seed10 = static_cast<u8>(seed10 >> sh3); | ||
| 1293 | seed11 = static_cast<u8>(seed11 >> sh3); | ||
| 1294 | seed12 = static_cast<u8>(seed12 >> sh3); | ||
| 1295 | |||
| 1296 | s32 a = seed1 * x + seed2 * y + seed11 * z + (rnum >> 14); | ||
| 1297 | s32 b = seed3 * x + seed4 * y + seed12 * z + (rnum >> 10); | ||
| 1298 | s32 c = seed5 * x + seed6 * y + seed9 * z + (rnum >> 6); | ||
| 1299 | s32 d = seed7 * x + seed8 * y + seed10 * z + (rnum >> 2); | ||
| 1300 | |||
| 1301 | a &= 0x3F; | ||
| 1302 | b &= 0x3F; | ||
| 1303 | c &= 0x3F; | ||
| 1304 | d &= 0x3F; | ||
| 1305 | |||
| 1306 | if (partitionCount < 4) | ||
| 1307 | d = 0; | ||
| 1308 | if (partitionCount < 3) | ||
| 1309 | c = 0; | ||
| 1310 | |||
| 1311 | if (a >= b && a >= c && a >= d) | ||
| 1312 | return 0; | ||
| 1313 | else if (b >= c && b >= d) | ||
| 1314 | return 1; | ||
| 1315 | else if (c >= d) | ||
| 1316 | return 2; | ||
| 1317 | return 3; | ||
| 1318 | } | ||
| 1319 | |||
| 1320 | static inline u32 Select2DPartition(s32 seed, s32 x, s32 y, s32 partitionCount, s32 smallBlock) { | ||
| 1321 | return SelectPartition(seed, x, y, 0, partitionCount, smallBlock); | ||
| 1322 | } | ||
| 1323 | |||
| 1324 | // Section C.2.14 | ||
| 1325 | static void ComputeEndpos32s(Pixel& ep1, Pixel& ep2, const u32*& colorValues, | ||
| 1326 | u32 colorEndpos32Mode) { | ||
| 1327 | #define READ_UINT_VALUES(N) \ | ||
| 1328 | u32 v[N]; \ | ||
| 1329 | for (u32 i = 0; i < N; i++) { \ | ||
| 1330 | v[i] = *(colorValues++); \ | ||
| 1331 | } | ||
| 1332 | |||
| 1333 | #define READ_INT_VALUES(N) \ | ||
| 1334 | s32 v[N]; \ | ||
| 1335 | for (u32 i = 0; i < N; i++) { \ | ||
| 1336 | v[i] = static_cast<s32>(*(colorValues++)); \ | ||
| 1337 | } | ||
| 1338 | |||
| 1339 | switch (colorEndpos32Mode) { | ||
| 1340 | case 0: { | ||
| 1341 | READ_UINT_VALUES(2) | ||
| 1342 | ep1 = Pixel(0xFF, v[0], v[0], v[0]); | ||
| 1343 | ep2 = Pixel(0xFF, v[1], v[1], v[1]); | ||
| 1344 | } break; | ||
| 1345 | |||
| 1346 | case 1: { | ||
| 1347 | READ_UINT_VALUES(2) | ||
| 1348 | u32 L0 = (v[0] >> 2) | (v[1] & 0xC0); | ||
| 1349 | u32 L1 = std::max(L0 + (v[1] & 0x3F), 0xFFU); | ||
| 1350 | ep1 = Pixel(0xFF, L0, L0, L0); | ||
| 1351 | ep2 = Pixel(0xFF, L1, L1, L1); | ||
| 1352 | } break; | ||
| 1353 | |||
| 1354 | case 4: { | ||
| 1355 | READ_UINT_VALUES(4) | ||
| 1356 | ep1 = Pixel(v[2], v[0], v[0], v[0]); | ||
| 1357 | ep2 = Pixel(v[3], v[1], v[1], v[1]); | ||
| 1358 | } break; | ||
| 1359 | |||
| 1360 | case 5: { | ||
| 1361 | READ_INT_VALUES(4) | ||
| 1362 | BitTransferSigned(v[1], v[0]); | ||
| 1363 | BitTransferSigned(v[3], v[2]); | ||
| 1364 | ep1 = Pixel(v[2], v[0], v[0], v[0]); | ||
| 1365 | ep2 = Pixel(v[2] + v[3], v[0] + v[1], v[0] + v[1], v[0] + v[1]); | ||
| 1366 | ep1.ClampByte(); | ||
| 1367 | ep2.ClampByte(); | ||
| 1368 | } break; | ||
| 1369 | |||
| 1370 | case 6: { | ||
| 1371 | READ_UINT_VALUES(4) | ||
| 1372 | ep1 = Pixel(0xFF, v[0] * v[3] >> 8, v[1] * v[3] >> 8, v[2] * v[3] >> 8); | ||
| 1373 | ep2 = Pixel(0xFF, v[0], v[1], v[2]); | ||
| 1374 | } break; | ||
| 1375 | |||
| 1376 | case 8: { | ||
| 1377 | READ_UINT_VALUES(6) | ||
| 1378 | if (v[1] + v[3] + v[5] >= v[0] + v[2] + v[4]) { | ||
| 1379 | ep1 = Pixel(0xFF, v[0], v[2], v[4]); | ||
| 1380 | ep2 = Pixel(0xFF, v[1], v[3], v[5]); | ||
| 1381 | } else { | ||
| 1382 | ep1 = BlueContract(0xFF, v[1], v[3], v[5]); | ||
| 1383 | ep2 = BlueContract(0xFF, v[0], v[2], v[4]); | ||
| 1384 | } | ||
| 1385 | } break; | ||
| 1386 | |||
| 1387 | case 9: { | ||
| 1388 | READ_INT_VALUES(6) | ||
| 1389 | BitTransferSigned(v[1], v[0]); | ||
| 1390 | BitTransferSigned(v[3], v[2]); | ||
| 1391 | BitTransferSigned(v[5], v[4]); | ||
| 1392 | if (v[1] + v[3] + v[5] >= 0) { | ||
| 1393 | ep1 = Pixel(0xFF, v[0], v[2], v[4]); | ||
| 1394 | ep2 = Pixel(0xFF, v[0] + v[1], v[2] + v[3], v[4] + v[5]); | ||
| 1395 | } else { | ||
| 1396 | ep1 = BlueContract(0xFF, v[0] + v[1], v[2] + v[3], v[4] + v[5]); | ||
| 1397 | ep2 = BlueContract(0xFF, v[0], v[2], v[4]); | ||
| 1398 | } | ||
| 1399 | ep1.ClampByte(); | ||
| 1400 | ep2.ClampByte(); | ||
| 1401 | } break; | ||
| 1402 | |||
| 1403 | case 10: { | ||
| 1404 | READ_UINT_VALUES(6) | ||
| 1405 | ep1 = Pixel(v[4], v[0] * v[3] >> 8, v[1] * v[3] >> 8, v[2] * v[3] >> 8); | ||
| 1406 | ep2 = Pixel(v[5], v[0], v[1], v[2]); | ||
| 1407 | } break; | ||
| 1408 | |||
| 1409 | case 12: { | ||
| 1410 | READ_UINT_VALUES(8) | ||
| 1411 | if (v[1] + v[3] + v[5] >= v[0] + v[2] + v[4]) { | ||
| 1412 | ep1 = Pixel(v[6], v[0], v[2], v[4]); | ||
| 1413 | ep2 = Pixel(v[7], v[1], v[3], v[5]); | ||
| 1414 | } else { | ||
| 1415 | ep1 = BlueContract(v[7], v[1], v[3], v[5]); | ||
| 1416 | ep2 = BlueContract(v[6], v[0], v[2], v[4]); | ||
| 1417 | } | ||
| 1418 | } break; | ||
| 1419 | |||
| 1420 | case 13: { | ||
| 1421 | READ_INT_VALUES(8) | ||
| 1422 | BitTransferSigned(v[1], v[0]); | ||
| 1423 | BitTransferSigned(v[3], v[2]); | ||
| 1424 | BitTransferSigned(v[5], v[4]); | ||
| 1425 | BitTransferSigned(v[7], v[6]); | ||
| 1426 | if (v[1] + v[3] + v[5] >= 0) { | ||
| 1427 | ep1 = Pixel(v[6], v[0], v[2], v[4]); | ||
| 1428 | ep2 = Pixel(v[7] + v[6], v[0] + v[1], v[2] + v[3], v[4] + v[5]); | ||
| 1429 | } else { | ||
| 1430 | ep1 = BlueContract(v[6] + v[7], v[0] + v[1], v[2] + v[3], v[4] + v[5]); | ||
| 1431 | ep2 = BlueContract(v[6], v[0], v[2], v[4]); | ||
| 1432 | } | ||
| 1433 | ep1.ClampByte(); | ||
| 1434 | ep2.ClampByte(); | ||
| 1435 | } break; | ||
| 1436 | |||
| 1437 | default: | ||
| 1438 | assert(false && "Unsupported color endpoint mode (is it HDR?)"); | ||
| 1439 | break; | ||
| 1440 | } | ||
| 1441 | |||
| 1442 | #undef READ_UINT_VALUES | ||
| 1443 | #undef READ_INT_VALUES | ||
| 1444 | } | ||
| 1445 | |||
| 1446 | static void DecompressBlock(std::span<const u8, 16> inBuf, const u32 blockWidth, | ||
| 1447 | const u32 blockHeight, std::span<u32, 12 * 12> outBuf) { | ||
| 1448 | InputBitStream strm(inBuf); | ||
| 1449 | TexelWeightParams weightParams = DecodeBlockInfo(strm); | ||
| 1450 | |||
| 1451 | // Was there an error? | ||
| 1452 | if (weightParams.m_bError) { | ||
| 1453 | assert(false && "Invalid block mode"); | ||
| 1454 | FillError(outBuf, blockWidth, blockHeight); | ||
| 1455 | return; | ||
| 1456 | } | ||
| 1457 | |||
| 1458 | if (weightParams.m_bVoidExtentLDR) { | ||
| 1459 | FillVoidExtentLDR(strm, outBuf, blockWidth, blockHeight); | ||
| 1460 | return; | ||
| 1461 | } | ||
| 1462 | |||
| 1463 | if (weightParams.m_bVoidExtentHDR) { | ||
| 1464 | assert(false && "HDR void extent blocks are unsupported!"); | ||
| 1465 | FillError(outBuf, blockWidth, blockHeight); | ||
| 1466 | return; | ||
| 1467 | } | ||
| 1468 | |||
| 1469 | if (weightParams.m_Width > blockWidth) { | ||
| 1470 | assert(false && "Texel weight grid width should be smaller than block width"); | ||
| 1471 | FillError(outBuf, blockWidth, blockHeight); | ||
| 1472 | return; | ||
| 1473 | } | ||
| 1474 | |||
| 1475 | if (weightParams.m_Height > blockHeight) { | ||
| 1476 | assert(false && "Texel weight grid height should be smaller than block height"); | ||
| 1477 | FillError(outBuf, blockWidth, blockHeight); | ||
| 1478 | return; | ||
| 1479 | } | ||
| 1480 | |||
| 1481 | // Read num partitions | ||
| 1482 | u32 nPartitions = strm.ReadBits<2>() + 1; | ||
| 1483 | assert(nPartitions <= 4); | ||
| 1484 | |||
| 1485 | if (nPartitions == 4 && weightParams.m_bDualPlane) { | ||
| 1486 | assert(false && "Dual plane mode is incompatible with four partition blocks"); | ||
| 1487 | FillError(outBuf, blockWidth, blockHeight); | ||
| 1488 | return; | ||
| 1489 | } | ||
| 1490 | |||
| 1491 | // Based on the number of partitions, read the color endpos32 mode for | ||
| 1492 | // each partition. | ||
| 1493 | |||
| 1494 | // Determine partitions, partition index, and color endpos32 modes | ||
| 1495 | s32 planeIdx = -1; | ||
| 1496 | u32 partitionIndex; | ||
| 1497 | u32 colorEndpos32Mode[4] = {0, 0, 0, 0}; | ||
| 1498 | |||
| 1499 | // Define color data. | ||
| 1500 | u8 colorEndpos32Data[16]; | ||
| 1501 | memset(colorEndpos32Data, 0, sizeof(colorEndpos32Data)); | ||
| 1502 | OutputBitStream colorEndpos32Stream(colorEndpos32Data, 16 * 8, 0); | ||
| 1503 | |||
| 1504 | // Read extra config data... | ||
| 1505 | u32 baseCEM = 0; | ||
| 1506 | if (nPartitions == 1) { | ||
| 1507 | colorEndpos32Mode[0] = strm.ReadBits<4>(); | ||
| 1508 | partitionIndex = 0; | ||
| 1509 | } else { | ||
| 1510 | partitionIndex = strm.ReadBits<10>(); | ||
| 1511 | baseCEM = strm.ReadBits<6>(); | ||
| 1512 | } | ||
| 1513 | u32 baseMode = (baseCEM & 3); | ||
| 1514 | |||
| 1515 | // Remaining bits are color endpos32 data... | ||
| 1516 | u32 nWeightBits = weightParams.GetPackedBitSize(); | ||
| 1517 | s32 remainingBits = 128 - nWeightBits - static_cast<s32>(strm.GetBitsRead()); | ||
| 1518 | |||
| 1519 | // Consider extra bits prior to texel data... | ||
| 1520 | u32 extraCEMbits = 0; | ||
| 1521 | if (baseMode) { | ||
| 1522 | switch (nPartitions) { | ||
| 1523 | case 2: | ||
| 1524 | extraCEMbits += 2; | ||
| 1525 | break; | ||
| 1526 | case 3: | ||
| 1527 | extraCEMbits += 5; | ||
| 1528 | break; | ||
| 1529 | case 4: | ||
| 1530 | extraCEMbits += 8; | ||
| 1531 | break; | ||
| 1532 | default: | ||
| 1533 | assert(false); | ||
| 1534 | break; | ||
| 1535 | } | ||
| 1536 | } | ||
| 1537 | remainingBits -= extraCEMbits; | ||
| 1538 | |||
| 1539 | // Do we have a dual plane situation? | ||
| 1540 | u32 planeSelectorBits = 0; | ||
| 1541 | if (weightParams.m_bDualPlane) { | ||
| 1542 | planeSelectorBits = 2; | ||
| 1543 | } | ||
| 1544 | remainingBits -= planeSelectorBits; | ||
| 1545 | |||
| 1546 | // Read color data... | ||
| 1547 | u32 colorDataBits = remainingBits; | ||
| 1548 | while (remainingBits > 0) { | ||
| 1549 | u32 nb = std::min(remainingBits, 8); | ||
| 1550 | u32 b = strm.ReadBits(nb); | ||
| 1551 | colorEndpos32Stream.WriteBits(b, nb); | ||
| 1552 | remainingBits -= 8; | ||
| 1553 | } | ||
| 1554 | |||
| 1555 | // Read the plane selection bits | ||
| 1556 | planeIdx = strm.ReadBits(planeSelectorBits); | ||
| 1557 | |||
| 1558 | // Read the rest of the CEM | ||
| 1559 | if (baseMode) { | ||
| 1560 | u32 extraCEM = strm.ReadBits(extraCEMbits); | ||
| 1561 | u32 CEM = (extraCEM << 6) | baseCEM; | ||
| 1562 | CEM >>= 2; | ||
| 1563 | |||
| 1564 | bool C[4] = {0}; | ||
| 1565 | for (u32 i = 0; i < nPartitions; i++) { | ||
| 1566 | C[i] = CEM & 1; | ||
| 1567 | CEM >>= 1; | ||
| 1568 | } | ||
| 1569 | |||
| 1570 | u8 M[4] = {0}; | ||
| 1571 | for (u32 i = 0; i < nPartitions; i++) { | ||
| 1572 | M[i] = CEM & 3; | ||
| 1573 | CEM >>= 2; | ||
| 1574 | assert(M[i] <= 3); | ||
| 1575 | } | ||
| 1576 | |||
| 1577 | for (u32 i = 0; i < nPartitions; i++) { | ||
| 1578 | colorEndpos32Mode[i] = baseMode; | ||
| 1579 | if (!(C[i])) | ||
| 1580 | colorEndpos32Mode[i] -= 1; | ||
| 1581 | colorEndpos32Mode[i] <<= 2; | ||
| 1582 | colorEndpos32Mode[i] |= M[i]; | ||
| 1583 | } | ||
| 1584 | } else if (nPartitions > 1) { | ||
| 1585 | u32 CEM = baseCEM >> 2; | ||
| 1586 | for (u32 i = 0; i < nPartitions; i++) { | ||
| 1587 | colorEndpos32Mode[i] = CEM; | ||
| 1588 | } | ||
| 1589 | } | ||
| 1590 | |||
| 1591 | // Make sure everything up till here is sane. | ||
| 1592 | for (u32 i = 0; i < nPartitions; i++) { | ||
| 1593 | assert(colorEndpos32Mode[i] < 16); | ||
| 1594 | } | ||
| 1595 | assert(strm.GetBitsRead() + weightParams.GetPackedBitSize() == 128); | ||
| 1596 | |||
| 1597 | // Decode both color data and texel weight data | ||
| 1598 | u32 colorValues[32]; // Four values, two endpos32s, four maximum paritions | ||
| 1599 | DecodeColorValues(colorValues, colorEndpos32Data, colorEndpos32Mode, nPartitions, | ||
| 1600 | colorDataBits); | ||
| 1601 | |||
| 1602 | Pixel endpos32s[4][2]; | ||
| 1603 | const u32* colorValuesPtr = colorValues; | ||
| 1604 | for (u32 i = 0; i < nPartitions; i++) { | ||
| 1605 | ComputeEndpos32s(endpos32s[i][0], endpos32s[i][1], colorValuesPtr, colorEndpos32Mode[i]); | ||
| 1606 | } | ||
| 1607 | |||
| 1608 | // Read the texel weight data.. | ||
| 1609 | std::array<u8, 16> texelWeightData; | ||
| 1610 | std::ranges::copy(inBuf, texelWeightData.begin()); | ||
| 1611 | |||
| 1612 | // Reverse everything | ||
| 1613 | for (u32 i = 0; i < 8; i++) { | ||
| 1614 | // Taken from http://graphics.stanford.edu/~seander/bithacks.html#ReverseByteWith64Bits | ||
| 1615 | #define REVERSE_BYTE(b) (((b)*0x80200802ULL) & 0x0884422110ULL) * 0x0101010101ULL >> 32 | ||
| 1616 | u8 a = static_cast<u8>(REVERSE_BYTE(texelWeightData[i])); | ||
| 1617 | u8 b = static_cast<u8>(REVERSE_BYTE(texelWeightData[15 - i])); | ||
| 1618 | #undef REVERSE_BYTE | ||
| 1619 | |||
| 1620 | texelWeightData[i] = b; | ||
| 1621 | texelWeightData[15 - i] = a; | ||
| 1622 | } | ||
| 1623 | |||
| 1624 | // Make sure that higher non-texel bits are set to zero | ||
| 1625 | const u32 clearByteStart = (weightParams.GetPackedBitSize() >> 3) + 1; | ||
| 1626 | if (clearByteStart > 0 && clearByteStart <= texelWeightData.size()) { | ||
| 1627 | texelWeightData[clearByteStart - 1] &= | ||
| 1628 | static_cast<u8>((1 << (weightParams.GetPackedBitSize() % 8)) - 1); | ||
| 1629 | std::memset(texelWeightData.data() + clearByteStart, 0, | ||
| 1630 | std::min(16U - clearByteStart, 16U)); | ||
| 1631 | } | ||
| 1632 | |||
| 1633 | IntegerEncodedVector texelWeightValues; | ||
| 1634 | |||
| 1635 | InputBitStream weightStream(texelWeightData); | ||
| 1636 | |||
| 1637 | DecodeIntegerSequence(texelWeightValues, weightStream, weightParams.m_MaxWeight, | ||
| 1638 | weightParams.GetNumWeightValues()); | ||
| 1639 | |||
| 1640 | // Blocks can be at most 12x12, so we can have as many as 144 weights | ||
| 1641 | u32 weights[2][144]; | ||
| 1642 | UnquantizeTexelWeights(weights, texelWeightValues, weightParams, blockWidth, blockHeight); | ||
| 1643 | |||
| 1644 | // Now that we have endpos32s and weights, we can s32erpolate and generate | ||
| 1645 | // the proper decoding... | ||
| 1646 | for (u32 j = 0; j < blockHeight; j++) | ||
| 1647 | for (u32 i = 0; i < blockWidth; i++) { | ||
| 1648 | u32 partition = Select2DPartition(partitionIndex, i, j, nPartitions, | ||
| 1649 | (blockHeight * blockWidth) < 32); | ||
| 1650 | assert(partition < nPartitions); | ||
| 1651 | |||
| 1652 | Pixel p; | ||
| 1653 | for (u32 c = 0; c < 4; c++) { | ||
| 1654 | u32 C0 = endpos32s[partition][0].Component(c); | ||
| 1655 | C0 = ReplicateByteTo16(C0); | ||
| 1656 | u32 C1 = endpos32s[partition][1].Component(c); | ||
| 1657 | C1 = ReplicateByteTo16(C1); | ||
| 1658 | |||
| 1659 | u32 plane = 0; | ||
| 1660 | if (weightParams.m_bDualPlane && (((planeIdx + 1) & 3) == c)) { | ||
| 1661 | plane = 1; | ||
| 1662 | } | ||
| 1663 | |||
| 1664 | u32 weight = weights[plane][j * blockWidth + i]; | ||
| 1665 | u32 C = (C0 * (64 - weight) + C1 * weight + 32) / 64; | ||
| 1666 | if (C == 65535) { | ||
| 1667 | p.Component(c) = 255; | ||
| 1668 | } else { | ||
| 1669 | double Cf = static_cast<double>(C); | ||
| 1670 | p.Component(c) = static_cast<u16>(255.0 * (Cf / 65536.0) + 0.5); | ||
| 1671 | } | ||
| 1672 | } | ||
| 1673 | |||
| 1674 | outBuf[j * blockWidth + i] = p.Pack(); | ||
| 1675 | } | ||
| 1676 | } | ||
| 1677 | |||
| 1678 | } // namespace ASTCC | ||
| 1679 | |||
| 1680 | namespace Tegra::Texture::ASTC { | ||
| 1681 | |||
| 1682 | void Decompress(std::span<const uint8_t> data, uint32_t width, uint32_t height, uint32_t depth, | ||
| 1683 | uint32_t block_width, uint32_t block_height, std::span<uint8_t> output) { | ||
| 1684 | u32 block_index = 0; | ||
| 1685 | std::size_t depth_offset = 0; | ||
| 1686 | for (u32 z = 0; z < depth; z++) { | ||
| 1687 | for (u32 y = 0; y < height; y += block_height) { | ||
| 1688 | for (u32 x = 0; x < width; x += block_width) { | ||
| 1689 | const std::span<const u8, 16> blockPtr{data.subspan(block_index * 16, 16)}; | ||
| 1690 | |||
| 1691 | // Blocks can be at most 12x12 | ||
| 1692 | std::array<u32, 12 * 12> uncompData; | ||
| 1693 | ASTCC::DecompressBlock(blockPtr, block_width, block_height, uncompData); | ||
| 1694 | |||
| 1695 | u32 decompWidth = std::min(block_width, width - x); | ||
| 1696 | u32 decompHeight = std::min(block_height, height - y); | ||
| 1697 | |||
| 1698 | const std::span<u8> outRow = output.subspan(depth_offset + (y * width + x) * 4); | ||
| 1699 | for (u32 jj = 0; jj < decompHeight; jj++) { | ||
| 1700 | std::memcpy(outRow.data() + jj * width * 4, | ||
| 1701 | uncompData.data() + jj * block_width, decompWidth * 4); | ||
| 1702 | } | ||
| 1703 | ++block_index; | ||
| 1704 | } | ||
| 1705 | } | ||
| 1706 | depth_offset += height * width * 4; | ||
| 1707 | } | ||
| 1708 | } | ||
| 1709 | |||
| 1710 | } // namespace Tegra::Texture::ASTC | ||
diff --git a/src/video_core/textures/astc.h b/src/video_core/textures/astc.h index 9105119bc..c1c73fda5 100644 --- a/src/video_core/textures/astc.h +++ b/src/video_core/textures/astc.h | |||
| @@ -4,11 +4,129 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <cstdint> | 7 | #include <bit> |
| 8 | #include "common/common_types.h" | ||
| 8 | 9 | ||
| 9 | namespace Tegra::Texture::ASTC { | 10 | namespace Tegra::Texture::ASTC { |
| 10 | 11 | ||
| 11 | void Decompress(std::span<const uint8_t> data, uint32_t width, uint32_t height, uint32_t depth, | 12 | enum class IntegerEncoding { JustBits, Quint, Trit }; |
| 12 | uint32_t block_width, uint32_t block_height, std::span<uint8_t> output); | 13 | |
| 14 | struct IntegerEncodedValue { | ||
| 15 | constexpr IntegerEncodedValue() = default; | ||
| 16 | |||
| 17 | constexpr IntegerEncodedValue(IntegerEncoding encoding_, u32 num_bits_) | ||
| 18 | : encoding{encoding_}, num_bits{num_bits_} {} | ||
| 19 | |||
| 20 | constexpr bool MatchesEncoding(const IntegerEncodedValue& other) const { | ||
| 21 | return encoding == other.encoding && num_bits == other.num_bits; | ||
| 22 | } | ||
| 23 | |||
| 24 | // Returns the number of bits required to encode num_vals values. | ||
| 25 | u32 GetBitLength(u32 num_vals) const { | ||
| 26 | u32 total_bits = num_bits * num_vals; | ||
| 27 | if (encoding == IntegerEncoding::Trit) { | ||
| 28 | total_bits += (num_vals * 8 + 4) / 5; | ||
| 29 | } else if (encoding == IntegerEncoding::Quint) { | ||
| 30 | total_bits += (num_vals * 7 + 2) / 3; | ||
| 31 | } | ||
| 32 | return total_bits; | ||
| 33 | } | ||
| 34 | |||
| 35 | IntegerEncoding encoding{}; | ||
| 36 | u32 num_bits = 0; | ||
| 37 | u32 bit_value = 0; | ||
| 38 | union { | ||
| 39 | u32 quint_value = 0; | ||
| 40 | u32 trit_value; | ||
| 41 | }; | ||
| 42 | }; | ||
| 43 | |||
| 44 | // Returns a new instance of this struct that corresponds to the | ||
| 45 | // can take no more than mav_value values | ||
| 46 | constexpr IntegerEncodedValue CreateEncoding(u32 mav_value) { | ||
| 47 | while (mav_value > 0) { | ||
| 48 | u32 check = mav_value + 1; | ||
| 49 | |||
| 50 | // Is mav_value a power of two? | ||
| 51 | if (!(check & (check - 1))) { | ||
| 52 | return IntegerEncodedValue(IntegerEncoding::JustBits, std::popcount(mav_value)); | ||
| 53 | } | ||
| 54 | |||
| 55 | // Is mav_value of the type 3*2^n - 1? | ||
| 56 | if ((check % 3 == 0) && !((check / 3) & ((check / 3) - 1))) { | ||
| 57 | return IntegerEncodedValue(IntegerEncoding::Trit, std::popcount(check / 3 - 1)); | ||
| 58 | } | ||
| 59 | |||
| 60 | // Is mav_value of the type 5*2^n - 1? | ||
| 61 | if ((check % 5 == 0) && !((check / 5) & ((check / 5) - 1))) { | ||
| 62 | return IntegerEncodedValue(IntegerEncoding::Quint, std::popcount(check / 5 - 1)); | ||
| 63 | } | ||
| 64 | |||
| 65 | // Apparently it can't be represented with a bounded integer sequence... | ||
| 66 | // just iterate. | ||
| 67 | mav_value--; | ||
| 68 | } | ||
| 69 | return IntegerEncodedValue(IntegerEncoding::JustBits, 0); | ||
| 70 | } | ||
| 71 | |||
| 72 | constexpr std::array<IntegerEncodedValue, 256> MakeEncodedValues() { | ||
| 73 | std::array<IntegerEncodedValue, 256> encodings{}; | ||
| 74 | for (std::size_t i = 0; i < encodings.size(); ++i) { | ||
| 75 | encodings[i] = CreateEncoding(static_cast<u32>(i)); | ||
| 76 | } | ||
| 77 | return encodings; | ||
| 78 | } | ||
| 79 | |||
| 80 | constexpr std::array<IntegerEncodedValue, 256> EncodingsValues = MakeEncodedValues(); | ||
| 81 | |||
| 82 | // Replicates low num_bits such that [(to_bit - 1):(to_bit - 1 - from_bit)] | ||
| 83 | // is the same as [(num_bits - 1):0] and repeats all the way down. | ||
| 84 | template <typename IntType> | ||
| 85 | constexpr IntType Replicate(IntType val, u32 num_bits, u32 to_bit) { | ||
| 86 | if (num_bits == 0 || to_bit == 0) { | ||
| 87 | return 0; | ||
| 88 | } | ||
| 89 | const IntType v = val & static_cast<IntType>((1 << num_bits) - 1); | ||
| 90 | IntType res = v; | ||
| 91 | u32 reslen = num_bits; | ||
| 92 | while (reslen < to_bit) { | ||
| 93 | u32 comp = 0; | ||
| 94 | if (num_bits > to_bit - reslen) { | ||
| 95 | u32 newshift = to_bit - reslen; | ||
| 96 | comp = num_bits - newshift; | ||
| 97 | num_bits = newshift; | ||
| 98 | } | ||
| 99 | res = static_cast<IntType>(res << num_bits); | ||
| 100 | res = static_cast<IntType>(res | (v >> comp)); | ||
| 101 | reslen += num_bits; | ||
| 102 | } | ||
| 103 | return res; | ||
| 104 | } | ||
| 105 | |||
| 106 | constexpr std::size_t NumReplicateEntries(u32 num_bits) { | ||
| 107 | return std::size_t(1) << num_bits; | ||
| 108 | } | ||
| 109 | |||
| 110 | template <typename IntType, u32 num_bits, u32 to_bit> | ||
| 111 | constexpr auto MakeReplicateTable() { | ||
| 112 | std::array<IntType, NumReplicateEntries(num_bits)> table{}; | ||
| 113 | for (IntType value = 0; value < static_cast<IntType>(std::size(table)); ++value) { | ||
| 114 | table[value] = Replicate(value, num_bits, to_bit); | ||
| 115 | } | ||
| 116 | return table; | ||
| 117 | } | ||
| 118 | |||
| 119 | constexpr auto REPLICATE_BYTE_TO_16_TABLE = MakeReplicateTable<u32, 8, 16>(); | ||
| 120 | constexpr auto REPLICATE_6_BIT_TO_8_TABLE = MakeReplicateTable<u32, 6, 8>(); | ||
| 121 | constexpr auto REPLICATE_7_BIT_TO_8_TABLE = MakeReplicateTable<u32, 7, 8>(); | ||
| 122 | constexpr auto REPLICATE_8_BIT_TO_8_TABLE = MakeReplicateTable<u32, 8, 8>(); | ||
| 123 | |||
| 124 | struct AstcBufferData { | ||
| 125 | decltype(EncodingsValues) encoding_values = EncodingsValues; | ||
| 126 | decltype(REPLICATE_6_BIT_TO_8_TABLE) replicate_6_to_8 = REPLICATE_6_BIT_TO_8_TABLE; | ||
| 127 | decltype(REPLICATE_7_BIT_TO_8_TABLE) replicate_7_to_8 = REPLICATE_7_BIT_TO_8_TABLE; | ||
| 128 | decltype(REPLICATE_8_BIT_TO_8_TABLE) replicate_8_to_8 = REPLICATE_8_BIT_TO_8_TABLE; | ||
| 129 | decltype(REPLICATE_BYTE_TO_16_TABLE) replicate_byte_to_16 = REPLICATE_BYTE_TO_16_TABLE; | ||
| 130 | } constexpr ASTC_BUFFER_DATA; | ||
| 13 | 131 | ||
| 14 | } // namespace Tegra::Texture::ASTC | 132 | } // namespace Tegra::Texture::ASTC |
diff --git a/src/video_core/textures/decoders.cpp b/src/video_core/textures/decoders.cpp index 62685a183..3a463d5db 100644 --- a/src/video_core/textures/decoders.cpp +++ b/src/video_core/textures/decoders.cpp | |||
| @@ -17,26 +17,7 @@ | |||
| 17 | #include "video_core/textures/texture.h" | 17 | #include "video_core/textures/texture.h" |
| 18 | 18 | ||
| 19 | namespace Tegra::Texture { | 19 | namespace Tegra::Texture { |
| 20 | |||
| 21 | namespace { | 20 | namespace { |
| 22 | /** | ||
| 23 | * This table represents the internal swizzle of a gob, in format 16 bytes x 2 sector packing. | ||
| 24 | * Calculates the offset of an (x, y) position within a swizzled texture. | ||
| 25 | * Taken from the Tegra X1 Technical Reference Manual. pages 1187-1188 | ||
| 26 | */ | ||
| 27 | constexpr SwizzleTable MakeSwizzleTableConst() { | ||
| 28 | SwizzleTable table{}; | ||
| 29 | for (u32 y = 0; y < table.size(); ++y) { | ||
| 30 | for (u32 x = 0; x < table[0].size(); ++x) { | ||
| 31 | table[y][x] = ((x % 64) / 32) * 256 + ((y % 8) / 2) * 64 + ((x % 32) / 16) * 32 + | ||
| 32 | (y % 2) * 16 + (x % 16); | ||
| 33 | } | ||
| 34 | } | ||
| 35 | return table; | ||
| 36 | } | ||
| 37 | |||
| 38 | constexpr SwizzleTable SWIZZLE_TABLE = MakeSwizzleTableConst(); | ||
| 39 | |||
| 40 | template <bool TO_LINEAR> | 21 | template <bool TO_LINEAR> |
| 41 | void Swizzle(std::span<u8> output, std::span<const u8> input, u32 bytes_per_pixel, u32 width, | 22 | void Swizzle(std::span<u8> output, std::span<const u8> input, u32 bytes_per_pixel, u32 width, |
| 42 | u32 height, u32 depth, u32 block_height, u32 block_depth, u32 stride_alignment) { | 23 | u32 height, u32 depth, u32 block_height, u32 block_depth, u32 stride_alignment) { |
| @@ -91,10 +72,6 @@ void Swizzle(std::span<u8> output, std::span<const u8> input, u32 bytes_per_pixe | |||
| 91 | } | 72 | } |
| 92 | } // Anonymous namespace | 73 | } // Anonymous namespace |
| 93 | 74 | ||
| 94 | SwizzleTable MakeSwizzleTable() { | ||
| 95 | return SWIZZLE_TABLE; | ||
| 96 | } | ||
| 97 | |||
| 98 | void UnswizzleTexture(std::span<u8> output, std::span<const u8> input, u32 bytes_per_pixel, | 75 | void UnswizzleTexture(std::span<u8> output, std::span<const u8> input, u32 bytes_per_pixel, |
| 99 | u32 width, u32 height, u32 depth, u32 block_height, u32 block_depth, | 76 | u32 width, u32 height, u32 depth, u32 block_height, u32 block_depth, |
| 100 | u32 stride_alignment) { | 77 | u32 stride_alignment) { |
diff --git a/src/video_core/textures/decoders.h b/src/video_core/textures/decoders.h index d7cdc81e8..4c14cefbf 100644 --- a/src/video_core/textures/decoders.h +++ b/src/video_core/textures/decoders.h | |||
| @@ -23,8 +23,22 @@ constexpr u32 GOB_SIZE_SHIFT = GOB_SIZE_X_SHIFT + GOB_SIZE_Y_SHIFT + GOB_SIZE_Z_ | |||
| 23 | 23 | ||
| 24 | using SwizzleTable = std::array<std::array<u32, GOB_SIZE_X>, GOB_SIZE_Y>; | 24 | using SwizzleTable = std::array<std::array<u32, GOB_SIZE_X>, GOB_SIZE_Y>; |
| 25 | 25 | ||
| 26 | /// Returns a z-order swizzle table | 26 | /** |
| 27 | SwizzleTable MakeSwizzleTable(); | 27 | * This table represents the internal swizzle of a gob, in format 16 bytes x 2 sector packing. |
| 28 | * Calculates the offset of an (x, y) position within a swizzled texture. | ||
| 29 | * Taken from the Tegra X1 Technical Reference Manual. pages 1187-1188 | ||
| 30 | */ | ||
| 31 | constexpr SwizzleTable MakeSwizzleTable() { | ||
| 32 | SwizzleTable table{}; | ||
| 33 | for (u32 y = 0; y < table.size(); ++y) { | ||
| 34 | for (u32 x = 0; x < table[0].size(); ++x) { | ||
| 35 | table[y][x] = ((x % 64) / 32) * 256 + ((y % 8) / 2) * 64 + ((x % 32) / 16) * 32 + | ||
| 36 | (y % 2) * 16 + (x % 16); | ||
| 37 | } | ||
| 38 | } | ||
| 39 | return table; | ||
| 40 | } | ||
| 41 | constexpr SwizzleTable SWIZZLE_TABLE = MakeSwizzleTable(); | ||
| 28 | 42 | ||
| 29 | /// Unswizzles a block linear texture into linear memory. | 43 | /// Unswizzles a block linear texture into linear memory. |
| 30 | void UnswizzleTexture(std::span<u8> output, std::span<const u8> input, u32 bytes_per_pixel, | 44 | void UnswizzleTexture(std::span<u8> output, std::span<const u8> input, u32 bytes_per_pixel, |
diff --git a/src/video_core/textures/texture.cpp b/src/video_core/textures/texture.cpp index ae5621a7d..a552543ed 100644 --- a/src/video_core/textures/texture.cpp +++ b/src/video_core/textures/texture.cpp | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | #include <array> | 6 | #include <array> |
| 7 | 7 | ||
| 8 | #include "common/cityhash.h" | 8 | #include "common/cityhash.h" |
| 9 | #include "core/settings.h" | 9 | #include "common/settings.h" |
| 10 | #include "video_core/textures/texture.h" | 10 | #include "video_core/textures/texture.h" |
| 11 | 11 | ||
| 12 | using Tegra::Texture::TICEntry; | 12 | using Tegra::Texture::TICEntry; |
diff --git a/src/video_core/video_core.cpp b/src/video_core/video_core.cpp index e1b38c6ac..3b575db4d 100644 --- a/src/video_core/video_core.cpp +++ b/src/video_core/video_core.cpp | |||
| @@ -5,8 +5,8 @@ | |||
| 5 | #include <memory> | 5 | #include <memory> |
| 6 | 6 | ||
| 7 | #include "common/logging/log.h" | 7 | #include "common/logging/log.h" |
| 8 | #include "common/settings.h" | ||
| 8 | #include "core/core.h" | 9 | #include "core/core.h" |
| 9 | #include "core/settings.h" | ||
| 10 | #include "video_core/renderer_base.h" | 10 | #include "video_core/renderer_base.h" |
| 11 | #include "video_core/renderer_opengl/renderer_opengl.h" | 11 | #include "video_core/renderer_opengl/renderer_opengl.h" |
| 12 | #include "video_core/renderer_vulkan/renderer_vulkan.h" | 12 | #include "video_core/renderer_vulkan/renderer_vulkan.h" |
diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp index 34d396434..64206b3d2 100644 --- a/src/video_core/vulkan_common/vulkan_device.cpp +++ b/src/video_core/vulkan_common/vulkan_device.cpp | |||
| @@ -12,7 +12,7 @@ | |||
| 12 | #include <vector> | 12 | #include <vector> |
| 13 | 13 | ||
| 14 | #include "common/assert.h" | 14 | #include "common/assert.h" |
| 15 | #include "core/settings.h" | 15 | #include "common/settings.h" |
| 16 | #include "video_core/vulkan_common/nsight_aftermath_tracker.h" | 16 | #include "video_core/vulkan_common/nsight_aftermath_tracker.h" |
| 17 | #include "video_core/vulkan_common/vulkan_device.h" | 17 | #include "video_core/vulkan_common/vulkan_device.h" |
| 18 | #include "video_core/vulkan_common/vulkan_wrapper.h" | 18 | #include "video_core/vulkan_common/vulkan_wrapper.h" |
| @@ -51,7 +51,7 @@ constexpr std::array REQUIRED_EXTENSIONS{ | |||
| 51 | #ifdef _WIN32 | 51 | #ifdef _WIN32 |
| 52 | VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME, | 52 | VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME, |
| 53 | #endif | 53 | #endif |
| 54 | #ifdef __linux__ | 54 | #ifdef __unix__ |
| 55 | VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME, | 55 | VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME, |
| 56 | #endif | 56 | #endif |
| 57 | }; | 57 | }; |
| @@ -294,6 +294,15 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR | |||
| 294 | }; | 294 | }; |
| 295 | SetNext(next, bit8_storage); | 295 | SetNext(next, bit8_storage); |
| 296 | 296 | ||
| 297 | VkPhysicalDeviceRobustness2FeaturesEXT robustness2{ | ||
| 298 | .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT, | ||
| 299 | .pNext = nullptr, | ||
| 300 | .robustBufferAccess2 = true, | ||
| 301 | .robustImageAccess2 = true, | ||
| 302 | .nullDescriptor = true, | ||
| 303 | }; | ||
| 304 | SetNext(next, robustness2); | ||
| 305 | |||
| 297 | VkPhysicalDeviceHostQueryResetFeaturesEXT host_query_reset{ | 306 | VkPhysicalDeviceHostQueryResetFeaturesEXT host_query_reset{ |
| 298 | .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES_EXT, | 307 | .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES_EXT, |
| 299 | .pNext = nullptr, | 308 | .pNext = nullptr, |
diff --git a/src/video_core/vulkan_common/vulkan_memory_allocator.cpp b/src/video_core/vulkan_common/vulkan_memory_allocator.cpp index 2a8b7a907..fa37aa79a 100644 --- a/src/video_core/vulkan_common/vulkan_memory_allocator.cpp +++ b/src/video_core/vulkan_common/vulkan_memory_allocator.cpp | |||
| @@ -62,7 +62,7 @@ public: | |||
| 62 | : memory{std::move(memory_)}, allocation_size{allocation_size_}, property_flags{properties}, | 62 | : memory{std::move(memory_)}, allocation_size{allocation_size_}, property_flags{properties}, |
| 63 | shifted_memory_type{1U << type} {} | 63 | shifted_memory_type{1U << type} {} |
| 64 | 64 | ||
| 65 | #if defined(_WIN32) || defined(__linux__) | 65 | #if defined(_WIN32) || defined(__unix__) |
| 66 | ~MemoryAllocation() { | 66 | ~MemoryAllocation() { |
| 67 | if (owning_opengl_handle != 0) { | 67 | if (owning_opengl_handle != 0) { |
| 68 | glDeleteMemoryObjectsEXT(1, &owning_opengl_handle); | 68 | glDeleteMemoryObjectsEXT(1, &owning_opengl_handle); |
| @@ -114,7 +114,7 @@ public: | |||
| 114 | } | 114 | } |
| 115 | return owning_opengl_handle; | 115 | return owning_opengl_handle; |
| 116 | } | 116 | } |
| 117 | #elif __linux__ | 117 | #elif __unix__ |
| 118 | [[nodiscard]] u32 ExportOpenGLHandle() { | 118 | [[nodiscard]] u32 ExportOpenGLHandle() { |
| 119 | if (!owning_opengl_handle) { | 119 | if (!owning_opengl_handle) { |
| 120 | glCreateMemoryObjectsEXT(1, &owning_opengl_handle); | 120 | glCreateMemoryObjectsEXT(1, &owning_opengl_handle); |
| @@ -165,7 +165,7 @@ private: | |||
| 165 | const u32 shifted_memory_type; ///< Shifted Vulkan memory type. | 165 | const u32 shifted_memory_type; ///< Shifted Vulkan memory type. |
| 166 | std::vector<Range> commits; ///< All commit ranges done from this allocation. | 166 | std::vector<Range> commits; ///< All commit ranges done from this allocation. |
| 167 | std::span<u8> memory_mapped_span; ///< Memory mapped span. Empty if not queried before. | 167 | std::span<u8> memory_mapped_span; ///< Memory mapped span. Empty if not queried before. |
| 168 | #if defined(_WIN32) || defined(__linux__) | 168 | #if defined(_WIN32) || defined(__unix__) |
| 169 | u32 owning_opengl_handle{}; ///< Owning OpenGL memory object handle. | 169 | u32 owning_opengl_handle{}; ///< Owning OpenGL memory object handle. |
| 170 | #endif | 170 | #endif |
| 171 | }; | 171 | }; |
| @@ -249,7 +249,7 @@ void MemoryAllocator::AllocMemory(VkMemoryPropertyFlags flags, u32 type_mask, u6 | |||
| 249 | .pNext = nullptr, | 249 | .pNext = nullptr, |
| 250 | #ifdef _WIN32 | 250 | #ifdef _WIN32 |
| 251 | .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT, | 251 | .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT, |
| 252 | #elif __linux__ | 252 | #elif __unix__ |
| 253 | .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT, | 253 | .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT, |
| 254 | #else | 254 | #else |
| 255 | .handleTypes = 0, | 255 | .handleTypes = 0, |
diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index b025ced1c..cc0790e07 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt | |||
| @@ -18,6 +18,7 @@ add_executable(yuzu | |||
| 18 | applets/profile_select.h | 18 | applets/profile_select.h |
| 19 | applets/software_keyboard.cpp | 19 | applets/software_keyboard.cpp |
| 20 | applets/software_keyboard.h | 20 | applets/software_keyboard.h |
| 21 | applets/software_keyboard.ui | ||
| 21 | applets/web_browser.cpp | 22 | applets/web_browser.cpp |
| 22 | applets/web_browser.h | 23 | applets/web_browser.h |
| 23 | bootmanager.cpp | 24 | bootmanager.cpp |
| @@ -143,6 +144,9 @@ add_executable(yuzu | |||
| 143 | uisettings.h | 144 | uisettings.h |
| 144 | util/limitable_input_dialog.cpp | 145 | util/limitable_input_dialog.cpp |
| 145 | util/limitable_input_dialog.h | 146 | util/limitable_input_dialog.h |
| 147 | util/overlay_dialog.cpp | ||
| 148 | util/overlay_dialog.h | ||
| 149 | util/overlay_dialog.ui | ||
| 146 | util/sequence_dialog/sequence_dialog.cpp | 150 | util/sequence_dialog/sequence_dialog.cpp |
| 147 | util/sequence_dialog/sequence_dialog.h | 151 | util/sequence_dialog/sequence_dialog.h |
| 148 | util/url_request_interceptor.cpp | 152 | util/url_request_interceptor.cpp |
diff --git a/src/yuzu/applets/controller.cpp b/src/yuzu/applets/controller.cpp index b92cd6886..836d90fda 100644 --- a/src/yuzu/applets/controller.cpp +++ b/src/yuzu/applets/controller.cpp | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include "yuzu/applets/controller.h" | 16 | #include "yuzu/applets/controller.h" |
| 17 | #include "yuzu/configuration/configure_input.h" | 17 | #include "yuzu/configuration/configure_input.h" |
| 18 | #include "yuzu/configuration/configure_input_profile_dialog.h" | 18 | #include "yuzu/configuration/configure_input_profile_dialog.h" |
| 19 | #include "yuzu/configuration/configure_motion_touch.h" | ||
| 19 | #include "yuzu/configuration/configure_vibration.h" | 20 | #include "yuzu/configuration/configure_vibration.h" |
| 20 | #include "yuzu/configuration/input_profiles.h" | 21 | #include "yuzu/configuration/input_profiles.h" |
| 21 | #include "yuzu/main.h" | 22 | #include "yuzu/main.h" |
| @@ -206,6 +207,9 @@ QtControllerSelectorDialog::QtControllerSelectorDialog( | |||
| 206 | connect(ui->vibrationButton, &QPushButton::clicked, this, | 207 | connect(ui->vibrationButton, &QPushButton::clicked, this, |
| 207 | &QtControllerSelectorDialog::CallConfigureVibrationDialog); | 208 | &QtControllerSelectorDialog::CallConfigureVibrationDialog); |
| 208 | 209 | ||
| 210 | connect(ui->motionButton, &QPushButton::clicked, this, | ||
| 211 | &QtControllerSelectorDialog::CallConfigureMotionTouchDialog); | ||
| 212 | |||
| 209 | connect(ui->inputConfigButton, &QPushButton::clicked, this, | 213 | connect(ui->inputConfigButton, &QPushButton::clicked, this, |
| 210 | &QtControllerSelectorDialog::CallConfigureInputProfileDialog); | 214 | &QtControllerSelectorDialog::CallConfigureInputProfileDialog); |
| 211 | 215 | ||
| @@ -276,6 +280,18 @@ void QtControllerSelectorDialog::CallConfigureVibrationDialog() { | |||
| 276 | } | 280 | } |
| 277 | } | 281 | } |
| 278 | 282 | ||
| 283 | void QtControllerSelectorDialog::CallConfigureMotionTouchDialog() { | ||
| 284 | ConfigureMotionTouch dialog(this, input_subsystem); | ||
| 285 | |||
| 286 | dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint | | ||
| 287 | Qt::WindowSystemMenuHint); | ||
| 288 | dialog.setWindowModality(Qt::WindowModal); | ||
| 289 | |||
| 290 | if (dialog.exec() == QDialog::Accepted) { | ||
| 291 | dialog.ApplyConfiguration(); | ||
| 292 | } | ||
| 293 | } | ||
| 294 | |||
| 279 | void QtControllerSelectorDialog::CallConfigureInputProfileDialog() { | 295 | void QtControllerSelectorDialog::CallConfigureInputProfileDialog() { |
| 280 | ConfigureInputProfileDialog dialog(this, input_subsystem, input_profiles.get()); | 296 | ConfigureInputProfileDialog dialog(this, input_subsystem, input_profiles.get()); |
| 281 | 297 | ||
diff --git a/src/yuzu/applets/controller.h b/src/yuzu/applets/controller.h index 3518eed56..9b57aea1a 100644 --- a/src/yuzu/applets/controller.h +++ b/src/yuzu/applets/controller.h | |||
| @@ -51,6 +51,9 @@ private: | |||
| 51 | // Initializes the "Configure Vibration" Dialog. | 51 | // Initializes the "Configure Vibration" Dialog. |
| 52 | void CallConfigureVibrationDialog(); | 52 | void CallConfigureVibrationDialog(); |
| 53 | 53 | ||
| 54 | // Initializes the "Configure Motion / Touch" Dialog. | ||
| 55 | void CallConfigureMotionTouchDialog(); | ||
| 56 | |||
| 54 | // Initializes the "Create Input Profile" Dialog. | 57 | // Initializes the "Create Input Profile" Dialog. |
| 55 | void CallConfigureInputProfileDialog(); | 58 | void CallConfigureInputProfileDialog(); |
| 56 | 59 | ||
diff --git a/src/yuzu/applets/error.cpp b/src/yuzu/applets/error.cpp index 8ee03ddb3..085688cd4 100644 --- a/src/yuzu/applets/error.cpp +++ b/src/yuzu/applets/error.cpp | |||
| @@ -19,11 +19,11 @@ QtErrorDisplay::~QtErrorDisplay() = default; | |||
| 19 | void QtErrorDisplay::ShowError(ResultCode error, std::function<void()> finished) const { | 19 | void QtErrorDisplay::ShowError(ResultCode error, std::function<void()> finished) const { |
| 20 | callback = std::move(finished); | 20 | callback = std::move(finished); |
| 21 | emit MainWindowDisplayError( | 21 | emit MainWindowDisplayError( |
| 22 | tr("An error has occurred.\nPlease try again or contact the developer of the " | 22 | tr("Error Code: %1-%2 (0x%3)") |
| 23 | "software.\n\nError Code: %1-%2 (0x%3)") | ||
| 24 | .arg(static_cast<u32>(error.module.Value()) + 2000, 4, 10, QChar::fromLatin1('0')) | 23 | .arg(static_cast<u32>(error.module.Value()) + 2000, 4, 10, QChar::fromLatin1('0')) |
| 25 | .arg(error.description, 4, 10, QChar::fromLatin1('0')) | 24 | .arg(error.description, 4, 10, QChar::fromLatin1('0')) |
| 26 | .arg(error.raw, 8, 16, QChar::fromLatin1('0'))); | 25 | .arg(error.raw, 8, 16, QChar::fromLatin1('0')), |
| 26 | tr("An error has occurred.\nPlease try again or contact the developer of the software.")); | ||
| 27 | } | 27 | } |
| 28 | 28 | ||
| 29 | void QtErrorDisplay::ShowErrorWithTimestamp(ResultCode error, std::chrono::seconds time, | 29 | void QtErrorDisplay::ShowErrorWithTimestamp(ResultCode error, std::chrono::seconds time, |
| @@ -32,13 +32,14 @@ void QtErrorDisplay::ShowErrorWithTimestamp(ResultCode error, std::chrono::secon | |||
| 32 | 32 | ||
| 33 | const QDateTime date_time = QDateTime::fromSecsSinceEpoch(time.count()); | 33 | const QDateTime date_time = QDateTime::fromSecsSinceEpoch(time.count()); |
| 34 | emit MainWindowDisplayError( | 34 | emit MainWindowDisplayError( |
| 35 | tr("An error occurred on %1 at %2.\nPlease try again or contact the " | 35 | tr("Error Code: %1-%2 (0x%3)") |
| 36 | "developer of the software.\n\nError Code: %3-%4 (0x%5)") | ||
| 37 | .arg(date_time.toString(QStringLiteral("dddd, MMMM d, yyyy"))) | ||
| 38 | .arg(date_time.toString(QStringLiteral("h:mm:ss A"))) | ||
| 39 | .arg(static_cast<u32>(error.module.Value()) + 2000, 4, 10, QChar::fromLatin1('0')) | 36 | .arg(static_cast<u32>(error.module.Value()) + 2000, 4, 10, QChar::fromLatin1('0')) |
| 40 | .arg(error.description, 4, 10, QChar::fromLatin1('0')) | 37 | .arg(error.description, 4, 10, QChar::fromLatin1('0')) |
| 41 | .arg(error.raw, 8, 16, QChar::fromLatin1('0'))); | 38 | .arg(error.raw, 8, 16, QChar::fromLatin1('0')), |
| 39 | tr("An error occurred on %1 at %2.\nPlease try again or contact the developer of the " | ||
| 40 | "software.") | ||
| 41 | .arg(date_time.toString(QStringLiteral("dddd, MMMM d, yyyy"))) | ||
| 42 | .arg(date_time.toString(QStringLiteral("h:mm:ss A")))); | ||
| 42 | } | 43 | } |
| 43 | 44 | ||
| 44 | void QtErrorDisplay::ShowCustomErrorText(ResultCode error, std::string dialog_text, | 45 | void QtErrorDisplay::ShowCustomErrorText(ResultCode error, std::string dialog_text, |
| @@ -46,10 +47,11 @@ void QtErrorDisplay::ShowCustomErrorText(ResultCode error, std::string dialog_te | |||
| 46 | std::function<void()> finished) const { | 47 | std::function<void()> finished) const { |
| 47 | callback = std::move(finished); | 48 | callback = std::move(finished); |
| 48 | emit MainWindowDisplayError( | 49 | emit MainWindowDisplayError( |
| 49 | tr("An error has occurred.\nError Code: %1-%2 (0x%3)\n\n%4\n\n%5") | 50 | tr("Error Code: %1-%2 (0x%3)") |
| 50 | .arg(static_cast<u32>(error.module.Value()) + 2000, 4, 10, QChar::fromLatin1('0')) | 51 | .arg(static_cast<u32>(error.module.Value()) + 2000, 4, 10, QChar::fromLatin1('0')) |
| 51 | .arg(error.description, 4, 10, QChar::fromLatin1('0')) | 52 | .arg(error.description, 4, 10, QChar::fromLatin1('0')) |
| 52 | .arg(error.raw, 8, 16, QChar::fromLatin1('0')) | 53 | .arg(error.raw, 8, 16, QChar::fromLatin1('0')), |
| 54 | tr("An error has occurred.\n\n%1\n\n%2") | ||
| 53 | .arg(QString::fromStdString(dialog_text)) | 55 | .arg(QString::fromStdString(dialog_text)) |
| 54 | .arg(QString::fromStdString(fullscreen_text))); | 56 | .arg(QString::fromStdString(fullscreen_text))); |
| 55 | } | 57 | } |
diff --git a/src/yuzu/applets/error.h b/src/yuzu/applets/error.h index b0932d895..8bd895a32 100644 --- a/src/yuzu/applets/error.h +++ b/src/yuzu/applets/error.h | |||
| @@ -24,7 +24,7 @@ public: | |||
| 24 | std::function<void()> finished) const override; | 24 | std::function<void()> finished) const override; |
| 25 | 25 | ||
| 26 | signals: | 26 | signals: |
| 27 | void MainWindowDisplayError(QString error) const; | 27 | void MainWindowDisplayError(QString error_code, QString error_text) const; |
| 28 | 28 | ||
| 29 | private: | 29 | private: |
| 30 | void MainWindowFinishedError(); | 30 | void MainWindowFinishedError(); |
diff --git a/src/yuzu/applets/software_keyboard.cpp b/src/yuzu/applets/software_keyboard.cpp index ab8cfd8ee..fd3368479 100644 --- a/src/yuzu/applets/software_keyboard.cpp +++ b/src/yuzu/applets/software_keyboard.cpp | |||
| @@ -1,153 +1,1641 @@ | |||
| 1 | // Copyright 2018 yuzu Emulator Project | 1 | // Copyright 2021 yuzu Emulator Project |
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <algorithm> | 5 | #include <QCursor> |
| 6 | #include <mutex> | 6 | #include <QKeyEvent> |
| 7 | #include <QDialogButtonBox> | 7 | #include <QScreen> |
| 8 | #include <QFont> | 8 | |
| 9 | #include <QLabel> | 9 | #include "common/logging/log.h" |
| 10 | #include <QLineEdit> | 10 | #include "common/settings.h" |
| 11 | #include <QVBoxLayout> | 11 | #include "common/string_util.h" |
| 12 | #include "core/hle/lock.h" | 12 | #include "core/core.h" |
| 13 | #include "core/frontend/input_interpreter.h" | ||
| 14 | #include "ui_software_keyboard.h" | ||
| 13 | #include "yuzu/applets/software_keyboard.h" | 15 | #include "yuzu/applets/software_keyboard.h" |
| 14 | #include "yuzu/main.h" | 16 | #include "yuzu/main.h" |
| 17 | #include "yuzu/util/overlay_dialog.h" | ||
| 18 | |||
| 19 | namespace { | ||
| 20 | |||
| 21 | using namespace Service::AM::Applets; | ||
| 22 | |||
| 23 | constexpr float BASE_HEADER_FONT_SIZE = 23.0f; | ||
| 24 | constexpr float BASE_SUB_FONT_SIZE = 17.0f; | ||
| 25 | constexpr float BASE_EDITOR_FONT_SIZE = 26.0f; | ||
| 26 | constexpr float BASE_CHAR_BUTTON_FONT_SIZE = 28.0f; | ||
| 27 | constexpr float BASE_LABEL_BUTTON_FONT_SIZE = 18.0f; | ||
| 28 | constexpr float BASE_ICON_BUTTON_SIZE = 36.0f; | ||
| 29 | [[maybe_unused]] constexpr float BASE_WIDTH = 1280.0f; | ||
| 30 | constexpr float BASE_HEIGHT = 720.0f; | ||
| 31 | |||
| 32 | } // Anonymous namespace | ||
| 33 | |||
| 34 | QtSoftwareKeyboardDialog::QtSoftwareKeyboardDialog( | ||
| 35 | QWidget* parent, Core::System& system_, bool is_inline_, | ||
| 36 | Core::Frontend::KeyboardInitializeParameters initialize_parameters_) | ||
| 37 | : QDialog(parent), ui{std::make_unique<Ui::QtSoftwareKeyboardDialog>()}, system{system_}, | ||
| 38 | is_inline{is_inline_}, initialize_parameters{std::move(initialize_parameters_)} { | ||
| 39 | ui->setupUi(this); | ||
| 40 | |||
| 41 | setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint | Qt::WindowTitleHint | | ||
| 42 | Qt::WindowSystemMenuHint | Qt::CustomizeWindowHint); | ||
| 43 | setWindowModality(Qt::WindowModal); | ||
| 44 | setAttribute(Qt::WA_DeleteOnClose); | ||
| 45 | setAttribute(Qt::WA_TranslucentBackground); | ||
| 46 | |||
| 47 | keyboard_buttons = {{ | ||
| 48 | {{ | ||
| 49 | { | ||
| 50 | ui->button_1, | ||
| 51 | ui->button_2, | ||
| 52 | ui->button_3, | ||
| 53 | ui->button_4, | ||
| 54 | ui->button_5, | ||
| 55 | ui->button_6, | ||
| 56 | ui->button_7, | ||
| 57 | ui->button_8, | ||
| 58 | ui->button_9, | ||
| 59 | ui->button_0, | ||
| 60 | ui->button_minus, | ||
| 61 | ui->button_backspace, | ||
| 62 | }, | ||
| 63 | { | ||
| 64 | ui->button_q, | ||
| 65 | ui->button_w, | ||
| 66 | ui->button_e, | ||
| 67 | ui->button_r, | ||
| 68 | ui->button_t, | ||
| 69 | ui->button_y, | ||
| 70 | ui->button_u, | ||
| 71 | ui->button_i, | ||
| 72 | ui->button_o, | ||
| 73 | ui->button_p, | ||
| 74 | ui->button_slash, | ||
| 75 | ui->button_return, | ||
| 76 | }, | ||
| 77 | { | ||
| 78 | ui->button_a, | ||
| 79 | ui->button_s, | ||
| 80 | ui->button_d, | ||
| 81 | ui->button_f, | ||
| 82 | ui->button_g, | ||
| 83 | ui->button_h, | ||
| 84 | ui->button_j, | ||
| 85 | ui->button_k, | ||
| 86 | ui->button_l, | ||
| 87 | ui->button_colon, | ||
| 88 | ui->button_apostrophe, | ||
| 89 | ui->button_return, | ||
| 90 | }, | ||
| 91 | { | ||
| 92 | ui->button_z, | ||
| 93 | ui->button_x, | ||
| 94 | ui->button_c, | ||
| 95 | ui->button_v, | ||
| 96 | ui->button_b, | ||
| 97 | ui->button_n, | ||
| 98 | ui->button_m, | ||
| 99 | ui->button_comma, | ||
| 100 | ui->button_dot, | ||
| 101 | ui->button_question, | ||
| 102 | ui->button_exclamation, | ||
| 103 | ui->button_ok, | ||
| 104 | }, | ||
| 105 | { | ||
| 106 | ui->button_shift, | ||
| 107 | ui->button_shift, | ||
| 108 | ui->button_space, | ||
| 109 | ui->button_space, | ||
| 110 | ui->button_space, | ||
| 111 | ui->button_space, | ||
| 112 | ui->button_space, | ||
| 113 | ui->button_space, | ||
| 114 | ui->button_space, | ||
| 115 | ui->button_space, | ||
| 116 | ui->button_space, | ||
| 117 | ui->button_ok, | ||
| 118 | }, | ||
| 119 | }}, | ||
| 120 | {{ | ||
| 121 | { | ||
| 122 | ui->button_hash, | ||
| 123 | ui->button_left_bracket, | ||
| 124 | ui->button_right_bracket, | ||
| 125 | ui->button_dollar, | ||
| 126 | ui->button_percent, | ||
| 127 | ui->button_circumflex, | ||
| 128 | ui->button_ampersand, | ||
| 129 | ui->button_asterisk, | ||
| 130 | ui->button_left_parenthesis, | ||
| 131 | ui->button_right_parenthesis, | ||
| 132 | ui->button_underscore, | ||
| 133 | ui->button_backspace_shift, | ||
| 134 | }, | ||
| 135 | { | ||
| 136 | ui->button_q_shift, | ||
| 137 | ui->button_w_shift, | ||
| 138 | ui->button_e_shift, | ||
| 139 | ui->button_r_shift, | ||
| 140 | ui->button_t_shift, | ||
| 141 | ui->button_y_shift, | ||
| 142 | ui->button_u_shift, | ||
| 143 | ui->button_i_shift, | ||
| 144 | ui->button_o_shift, | ||
| 145 | ui->button_p_shift, | ||
| 146 | ui->button_at, | ||
| 147 | ui->button_return_shift, | ||
| 148 | }, | ||
| 149 | { | ||
| 150 | ui->button_a_shift, | ||
| 151 | ui->button_s_shift, | ||
| 152 | ui->button_d_shift, | ||
| 153 | ui->button_f_shift, | ||
| 154 | ui->button_g_shift, | ||
| 155 | ui->button_h_shift, | ||
| 156 | ui->button_j_shift, | ||
| 157 | ui->button_k_shift, | ||
| 158 | ui->button_l_shift, | ||
| 159 | ui->button_semicolon, | ||
| 160 | ui->button_quotation, | ||
| 161 | ui->button_return_shift, | ||
| 162 | }, | ||
| 163 | { | ||
| 164 | ui->button_z_shift, | ||
| 165 | ui->button_x_shift, | ||
| 166 | ui->button_c_shift, | ||
| 167 | ui->button_v_shift, | ||
| 168 | ui->button_b_shift, | ||
| 169 | ui->button_n_shift, | ||
| 170 | ui->button_m_shift, | ||
| 171 | ui->button_less_than, | ||
| 172 | ui->button_greater_than, | ||
| 173 | ui->button_plus, | ||
| 174 | ui->button_equal, | ||
| 175 | ui->button_ok_shift, | ||
| 176 | }, | ||
| 177 | { | ||
| 178 | ui->button_shift_shift, | ||
| 179 | ui->button_shift_shift, | ||
| 180 | ui->button_space_shift, | ||
| 181 | ui->button_space_shift, | ||
| 182 | ui->button_space_shift, | ||
| 183 | ui->button_space_shift, | ||
| 184 | ui->button_space_shift, | ||
| 185 | ui->button_space_shift, | ||
| 186 | ui->button_space_shift, | ||
| 187 | ui->button_space_shift, | ||
| 188 | ui->button_space_shift, | ||
| 189 | ui->button_ok_shift, | ||
| 190 | }, | ||
| 191 | }}, | ||
| 192 | }}; | ||
| 15 | 193 | ||
| 16 | QtSoftwareKeyboardValidator::QtSoftwareKeyboardValidator( | 194 | numberpad_buttons = {{ |
| 17 | Core::Frontend::SoftwareKeyboardParameters parameters) | 195 | { |
| 18 | : parameters(std::move(parameters)) {} | 196 | ui->button_1_num, |
| 197 | ui->button_2_num, | ||
| 198 | ui->button_3_num, | ||
| 199 | ui->button_backspace_num, | ||
| 200 | }, | ||
| 201 | { | ||
| 202 | ui->button_4_num, | ||
| 203 | ui->button_5_num, | ||
| 204 | ui->button_6_num, | ||
| 205 | ui->button_ok_num, | ||
| 206 | }, | ||
| 207 | { | ||
| 208 | ui->button_7_num, | ||
| 209 | ui->button_8_num, | ||
| 210 | ui->button_9_num, | ||
| 211 | ui->button_ok_num, | ||
| 212 | }, | ||
| 213 | { | ||
| 214 | nullptr, | ||
| 215 | ui->button_0_num, | ||
| 216 | nullptr, | ||
| 217 | ui->button_ok_num, | ||
| 218 | }, | ||
| 219 | }}; | ||
| 19 | 220 | ||
| 20 | QValidator::State QtSoftwareKeyboardValidator::validate(QString& input, int& pos) const { | 221 | all_buttons = { |
| 21 | if (input.size() > static_cast<s64>(parameters.max_length)) { | 222 | ui->button_1, |
| 22 | return Invalid; | 223 | ui->button_2, |
| 224 | ui->button_3, | ||
| 225 | ui->button_4, | ||
| 226 | ui->button_5, | ||
| 227 | ui->button_6, | ||
| 228 | ui->button_7, | ||
| 229 | ui->button_8, | ||
| 230 | ui->button_9, | ||
| 231 | ui->button_0, | ||
| 232 | ui->button_minus, | ||
| 233 | ui->button_backspace, | ||
| 234 | ui->button_q, | ||
| 235 | ui->button_w, | ||
| 236 | ui->button_e, | ||
| 237 | ui->button_r, | ||
| 238 | ui->button_t, | ||
| 239 | ui->button_y, | ||
| 240 | ui->button_u, | ||
| 241 | ui->button_i, | ||
| 242 | ui->button_o, | ||
| 243 | ui->button_p, | ||
| 244 | ui->button_slash, | ||
| 245 | ui->button_return, | ||
| 246 | ui->button_a, | ||
| 247 | ui->button_s, | ||
| 248 | ui->button_d, | ||
| 249 | ui->button_f, | ||
| 250 | ui->button_g, | ||
| 251 | ui->button_h, | ||
| 252 | ui->button_j, | ||
| 253 | ui->button_k, | ||
| 254 | ui->button_l, | ||
| 255 | ui->button_colon, | ||
| 256 | ui->button_apostrophe, | ||
| 257 | ui->button_z, | ||
| 258 | ui->button_x, | ||
| 259 | ui->button_c, | ||
| 260 | ui->button_v, | ||
| 261 | ui->button_b, | ||
| 262 | ui->button_n, | ||
| 263 | ui->button_m, | ||
| 264 | ui->button_comma, | ||
| 265 | ui->button_dot, | ||
| 266 | ui->button_question, | ||
| 267 | ui->button_exclamation, | ||
| 268 | ui->button_ok, | ||
| 269 | ui->button_shift, | ||
| 270 | ui->button_space, | ||
| 271 | ui->button_hash, | ||
| 272 | ui->button_left_bracket, | ||
| 273 | ui->button_right_bracket, | ||
| 274 | ui->button_dollar, | ||
| 275 | ui->button_percent, | ||
| 276 | ui->button_circumflex, | ||
| 277 | ui->button_ampersand, | ||
| 278 | ui->button_asterisk, | ||
| 279 | ui->button_left_parenthesis, | ||
| 280 | ui->button_right_parenthesis, | ||
| 281 | ui->button_underscore, | ||
| 282 | ui->button_backspace_shift, | ||
| 283 | ui->button_q_shift, | ||
| 284 | ui->button_w_shift, | ||
| 285 | ui->button_e_shift, | ||
| 286 | ui->button_r_shift, | ||
| 287 | ui->button_t_shift, | ||
| 288 | ui->button_y_shift, | ||
| 289 | ui->button_u_shift, | ||
| 290 | ui->button_i_shift, | ||
| 291 | ui->button_o_shift, | ||
| 292 | ui->button_p_shift, | ||
| 293 | ui->button_at, | ||
| 294 | ui->button_return_shift, | ||
| 295 | ui->button_a_shift, | ||
| 296 | ui->button_s_shift, | ||
| 297 | ui->button_d_shift, | ||
| 298 | ui->button_f_shift, | ||
| 299 | ui->button_g_shift, | ||
| 300 | ui->button_h_shift, | ||
| 301 | ui->button_j_shift, | ||
| 302 | ui->button_k_shift, | ||
| 303 | ui->button_l_shift, | ||
| 304 | ui->button_semicolon, | ||
| 305 | ui->button_quotation, | ||
| 306 | ui->button_z_shift, | ||
| 307 | ui->button_x_shift, | ||
| 308 | ui->button_c_shift, | ||
| 309 | ui->button_v_shift, | ||
| 310 | ui->button_b_shift, | ||
| 311 | ui->button_n_shift, | ||
| 312 | ui->button_m_shift, | ||
| 313 | ui->button_less_than, | ||
| 314 | ui->button_greater_than, | ||
| 315 | ui->button_plus, | ||
| 316 | ui->button_equal, | ||
| 317 | ui->button_ok_shift, | ||
| 318 | ui->button_shift_shift, | ||
| 319 | ui->button_space_shift, | ||
| 320 | ui->button_1_num, | ||
| 321 | ui->button_2_num, | ||
| 322 | ui->button_3_num, | ||
| 323 | ui->button_backspace_num, | ||
| 324 | ui->button_4_num, | ||
| 325 | ui->button_5_num, | ||
| 326 | ui->button_6_num, | ||
| 327 | ui->button_ok_num, | ||
| 328 | ui->button_7_num, | ||
| 329 | ui->button_8_num, | ||
| 330 | ui->button_9_num, | ||
| 331 | ui->button_0_num, | ||
| 332 | }; | ||
| 333 | |||
| 334 | SetupMouseHover(); | ||
| 335 | |||
| 336 | if (!initialize_parameters.ok_text.empty()) { | ||
| 337 | ui->button_ok->setText(QString::fromStdU16String(initialize_parameters.ok_text)); | ||
| 23 | } | 338 | } |
| 24 | if (parameters.disable_space && input.contains(QLatin1Char{' '})) { | 339 | |
| 25 | return Invalid; | 340 | ui->label_header->setText(QString::fromStdU16String(initialize_parameters.header_text)); |
| 341 | ui->label_sub->setText(QString::fromStdU16String(initialize_parameters.sub_text)); | ||
| 342 | |||
| 343 | current_text = initialize_parameters.initial_text; | ||
| 344 | cursor_position = initialize_parameters.initial_cursor_position; | ||
| 345 | |||
| 346 | SetTextDrawType(); | ||
| 347 | |||
| 348 | for (auto* button : all_buttons) { | ||
| 349 | connect(button, &QPushButton::clicked, this, [this, button](bool) { | ||
| 350 | if (is_inline) { | ||
| 351 | InlineKeyboardButtonClicked(button); | ||
| 352 | } else { | ||
| 353 | NormalKeyboardButtonClicked(button); | ||
| 354 | } | ||
| 355 | }); | ||
| 26 | } | 356 | } |
| 27 | if (parameters.disable_address && input.contains(QLatin1Char{'@'})) { | 357 | |
| 28 | return Invalid; | 358 | // TODO (Morph): Remove this when InputInterpreter no longer relies on the HID backend |
| 359 | if (system.IsPoweredOn()) { | ||
| 360 | input_interpreter = std::make_unique<InputInterpreter>(system); | ||
| 29 | } | 361 | } |
| 30 | if (parameters.disable_percent && input.contains(QLatin1Char{'%'})) { | 362 | } |
| 31 | return Invalid; | 363 | |
| 364 | QtSoftwareKeyboardDialog::~QtSoftwareKeyboardDialog() { | ||
| 365 | StopInputThread(); | ||
| 366 | } | ||
| 367 | |||
| 368 | void QtSoftwareKeyboardDialog::ShowNormalKeyboard(QPoint pos, QSize size) { | ||
| 369 | if (isVisible()) { | ||
| 370 | return; | ||
| 32 | } | 371 | } |
| 33 | if (parameters.disable_slash && | 372 | |
| 34 | (input.contains(QLatin1Char{'/'}) || input.contains(QLatin1Char{'\\'}))) { | 373 | MoveAndResizeWindow(pos, size); |
| 35 | return Invalid; | 374 | |
| 375 | SetKeyboardType(); | ||
| 376 | SetPasswordMode(); | ||
| 377 | SetControllerImage(); | ||
| 378 | DisableKeyboardButtons(); | ||
| 379 | SetBackspaceOkEnabled(); | ||
| 380 | |||
| 381 | open(); | ||
| 382 | } | ||
| 383 | |||
| 384 | void QtSoftwareKeyboardDialog::ShowTextCheckDialog( | ||
| 385 | Service::AM::Applets::SwkbdTextCheckResult text_check_result, | ||
| 386 | std::u16string text_check_message) { | ||
| 387 | switch (text_check_result) { | ||
| 388 | case SwkbdTextCheckResult::Success: | ||
| 389 | case SwkbdTextCheckResult::Silent: | ||
| 390 | default: | ||
| 391 | break; | ||
| 392 | case SwkbdTextCheckResult::Failure: { | ||
| 393 | StopInputThread(); | ||
| 394 | |||
| 395 | OverlayDialog dialog(this, system, QString{}, QString::fromStdU16String(text_check_message), | ||
| 396 | QString{}, tr("OK"), Qt::AlignCenter); | ||
| 397 | dialog.exec(); | ||
| 398 | |||
| 399 | StartInputThread(); | ||
| 400 | break; | ||
| 36 | } | 401 | } |
| 37 | if (parameters.disable_number && | 402 | case SwkbdTextCheckResult::Confirm: { |
| 38 | std::any_of(input.begin(), input.end(), [](QChar c) { return c.isDigit(); })) { | 403 | StopInputThread(); |
| 39 | return Invalid; | 404 | |
| 405 | OverlayDialog dialog(this, system, QString{}, QString::fromStdU16String(text_check_message), | ||
| 406 | tr("Cancel"), tr("OK"), Qt::AlignCenter); | ||
| 407 | if (dialog.exec() == QDialog::Accepted) { | ||
| 408 | emit SubmitNormalText(SwkbdResult::Ok, current_text); | ||
| 409 | break; | ||
| 410 | } | ||
| 411 | |||
| 412 | StartInputThread(); | ||
| 413 | break; | ||
| 40 | } | 414 | } |
| 415 | } | ||
| 416 | } | ||
| 417 | |||
| 418 | void QtSoftwareKeyboardDialog::ShowInlineKeyboard( | ||
| 419 | Core::Frontend::InlineAppearParameters appear_parameters, QPoint pos, QSize size) { | ||
| 420 | MoveAndResizeWindow(pos, size); | ||
| 421 | |||
| 422 | ui->topOSK->setStyleSheet(QStringLiteral("background: rgba(0, 0, 0, 0);")); | ||
| 423 | |||
| 424 | ui->headerOSK->hide(); | ||
| 425 | ui->subOSK->hide(); | ||
| 426 | ui->inputOSK->hide(); | ||
| 427 | ui->charactersOSK->hide(); | ||
| 428 | ui->inputBoxOSK->hide(); | ||
| 429 | ui->charactersBoxOSK->hide(); | ||
| 430 | |||
| 431 | initialize_parameters.max_text_length = appear_parameters.max_text_length; | ||
| 432 | initialize_parameters.min_text_length = appear_parameters.min_text_length; | ||
| 433 | initialize_parameters.type = appear_parameters.type; | ||
| 434 | initialize_parameters.key_disable_flags = appear_parameters.key_disable_flags; | ||
| 435 | initialize_parameters.enable_backspace_button = appear_parameters.enable_backspace_button; | ||
| 436 | initialize_parameters.enable_return_button = appear_parameters.enable_return_button; | ||
| 437 | initialize_parameters.disable_cancel_button = initialize_parameters.disable_cancel_button; | ||
| 41 | 438 | ||
| 42 | if (parameters.disable_download_code && std::any_of(input.begin(), input.end(), [](QChar c) { | 439 | SetKeyboardType(); |
| 43 | return c == QLatin1Char{'O'} || c == QLatin1Char{'I'}; | 440 | SetControllerImage(); |
| 44 | })) { | 441 | DisableKeyboardButtons(); |
| 45 | return Invalid; | 442 | SetBackspaceOkEnabled(); |
| 443 | |||
| 444 | open(); | ||
| 445 | } | ||
| 446 | |||
| 447 | void QtSoftwareKeyboardDialog::HideInlineKeyboard() { | ||
| 448 | StopInputThread(); | ||
| 449 | QDialog::hide(); | ||
| 450 | } | ||
| 451 | |||
| 452 | void QtSoftwareKeyboardDialog::InlineTextChanged( | ||
| 453 | Core::Frontend::InlineTextParameters text_parameters) { | ||
| 454 | current_text = text_parameters.input_text; | ||
| 455 | cursor_position = text_parameters.cursor_position; | ||
| 456 | |||
| 457 | SetBackspaceOkEnabled(); | ||
| 458 | } | ||
| 459 | |||
| 460 | void QtSoftwareKeyboardDialog::ExitKeyboard() { | ||
| 461 | StopInputThread(); | ||
| 462 | QDialog::done(QDialog::Accepted); | ||
| 463 | } | ||
| 464 | |||
| 465 | void QtSoftwareKeyboardDialog::open() { | ||
| 466 | QDialog::open(); | ||
| 467 | |||
| 468 | row = 0; | ||
| 469 | column = 0; | ||
| 470 | |||
| 471 | const auto* const curr_button = | ||
| 472 | keyboard_buttons[static_cast<int>(bottom_osk_index)][row][column]; | ||
| 473 | |||
| 474 | // This is a workaround for setFocus() randomly not showing focus in the UI | ||
| 475 | QCursor::setPos(curr_button->mapToGlobal(curr_button->rect().center())); | ||
| 476 | |||
| 477 | StartInputThread(); | ||
| 478 | } | ||
| 479 | |||
| 480 | void QtSoftwareKeyboardDialog::reject() { | ||
| 481 | // Pressing the ESC key in a dialog calls QDialog::reject(). | ||
| 482 | // We will override this behavior to the "Cancel" action on the software keyboard. | ||
| 483 | if (is_inline) { | ||
| 484 | emit SubmitInlineText(SwkbdReplyType::DecidedCancel, current_text, cursor_position); | ||
| 485 | } else { | ||
| 486 | emit SubmitNormalText(SwkbdResult::Cancel, current_text); | ||
| 46 | } | 487 | } |
| 488 | } | ||
| 489 | |||
| 490 | void QtSoftwareKeyboardDialog::keyPressEvent(QKeyEvent* event) { | ||
| 491 | if (!is_inline) { | ||
| 492 | QDialog::keyPressEvent(event); | ||
| 493 | return; | ||
| 494 | } | ||
| 495 | |||
| 496 | const auto entered_key = event->key(); | ||
| 47 | 497 | ||
| 48 | return Acceptable; | 498 | switch (entered_key) { |
| 499 | case Qt::Key_Escape: | ||
| 500 | QDialog::keyPressEvent(event); | ||
| 501 | return; | ||
| 502 | case Qt::Key_Backspace: | ||
| 503 | switch (bottom_osk_index) { | ||
| 504 | case BottomOSKIndex::LowerCase: | ||
| 505 | ui->button_backspace->click(); | ||
| 506 | break; | ||
| 507 | case BottomOSKIndex::UpperCase: | ||
| 508 | ui->button_backspace_shift->click(); | ||
| 509 | break; | ||
| 510 | case BottomOSKIndex::NumberPad: | ||
| 511 | ui->button_backspace_num->click(); | ||
| 512 | break; | ||
| 513 | default: | ||
| 514 | break; | ||
| 515 | } | ||
| 516 | return; | ||
| 517 | case Qt::Key_Return: | ||
| 518 | switch (bottom_osk_index) { | ||
| 519 | case BottomOSKIndex::LowerCase: | ||
| 520 | ui->button_ok->click(); | ||
| 521 | break; | ||
| 522 | case BottomOSKIndex::UpperCase: | ||
| 523 | ui->button_ok_shift->click(); | ||
| 524 | break; | ||
| 525 | case BottomOSKIndex::NumberPad: | ||
| 526 | ui->button_ok_num->click(); | ||
| 527 | break; | ||
| 528 | default: | ||
| 529 | break; | ||
| 530 | } | ||
| 531 | return; | ||
| 532 | case Qt::Key_Left: | ||
| 533 | MoveTextCursorDirection(Direction::Left); | ||
| 534 | return; | ||
| 535 | case Qt::Key_Right: | ||
| 536 | MoveTextCursorDirection(Direction::Right); | ||
| 537 | return; | ||
| 538 | default: | ||
| 539 | break; | ||
| 540 | } | ||
| 541 | |||
| 542 | const auto entered_text = event->text(); | ||
| 543 | |||
| 544 | if (entered_text.isEmpty()) { | ||
| 545 | return; | ||
| 546 | } | ||
| 547 | |||
| 548 | InlineTextInsertString(entered_text.toStdU16String()); | ||
| 49 | } | 549 | } |
| 50 | 550 | ||
| 51 | QtSoftwareKeyboardDialog::QtSoftwareKeyboardDialog( | 551 | void QtSoftwareKeyboardDialog::MoveAndResizeWindow(QPoint pos, QSize size) { |
| 52 | QWidget* parent, Core::Frontend::SoftwareKeyboardParameters parameters_) | 552 | QDialog::move(pos); |
| 53 | : QDialog(parent), parameters(std::move(parameters_)) { | 553 | QDialog::resize(size); |
| 54 | layout = new QVBoxLayout; | 554 | |
| 55 | 555 | // High DPI | |
| 56 | header_label = new QLabel(QString::fromStdU16String(parameters.header_text)); | 556 | const float dpi_scale = qApp->screenAt(pos)->logicalDotsPerInch() / 96.0f; |
| 57 | header_label->setFont({header_label->font().family(), 11, QFont::Bold}); | 557 | |
| 58 | if (header_label->text().isEmpty()) | 558 | RescaleKeyboardElements(size.width(), size.height(), dpi_scale); |
| 59 | header_label->setText(tr("Enter text:")); | 559 | } |
| 60 | 560 | ||
| 61 | sub_label = new QLabel(QString::fromStdU16String(parameters.sub_text)); | 561 | void QtSoftwareKeyboardDialog::RescaleKeyboardElements(float width, float height, float dpi_scale) { |
| 62 | sub_label->setFont({sub_label->font().family(), sub_label->font().pointSize(), | 562 | const auto header_font_size = BASE_HEADER_FONT_SIZE * (height / BASE_HEIGHT) / dpi_scale; |
| 63 | sub_label->font().weight(), true}); | 563 | const auto sub_font_size = BASE_SUB_FONT_SIZE * (height / BASE_HEIGHT) / dpi_scale; |
| 64 | sub_label->setHidden(parameters.sub_text.empty()); | 564 | const auto editor_font_size = BASE_EDITOR_FONT_SIZE * (height / BASE_HEIGHT) / dpi_scale; |
| 65 | 565 | const auto char_button_font_size = | |
| 66 | guide_label = new QLabel(QString::fromStdU16String(parameters.guide_text)); | 566 | BASE_CHAR_BUTTON_FONT_SIZE * (height / BASE_HEIGHT) / dpi_scale; |
| 67 | guide_label->setHidden(parameters.guide_text.empty()); | 567 | const auto label_button_font_size = |
| 68 | 568 | BASE_LABEL_BUTTON_FONT_SIZE * (height / BASE_HEIGHT) / dpi_scale; | |
| 69 | length_label = new QLabel(QStringLiteral("0/%1").arg(parameters.max_length)); | 569 | |
| 70 | length_label->setAlignment(Qt::AlignRight); | 570 | QFont header_font(QStringLiteral("MS Shell Dlg 2"), header_font_size, QFont::Normal); |
| 71 | length_label->setFont({length_label->font().family(), 8}); | 571 | QFont sub_font(QStringLiteral("MS Shell Dlg 2"), sub_font_size, QFont::Normal); |
| 72 | 572 | QFont editor_font(QStringLiteral("MS Shell Dlg 2"), editor_font_size, QFont::Normal); | |
| 73 | line_edit = new QLineEdit; | 573 | QFont char_button_font(QStringLiteral("MS Shell Dlg 2"), char_button_font_size, QFont::Normal); |
| 74 | line_edit->setValidator(new QtSoftwareKeyboardValidator(parameters)); | 574 | QFont label_button_font(QStringLiteral("MS Shell Dlg 2"), label_button_font_size, |
| 75 | line_edit->setMaxLength(static_cast<int>(parameters.max_length)); | 575 | QFont::Normal); |
| 76 | line_edit->setText(QString::fromStdU16String(parameters.initial_text)); | 576 | |
| 77 | line_edit->setCursorPosition( | 577 | ui->label_header->setFont(header_font); |
| 78 | parameters.cursor_at_beginning ? 0 : static_cast<int>(parameters.initial_text.size())); | 578 | ui->label_sub->setFont(sub_font); |
| 79 | line_edit->setEchoMode(parameters.password ? QLineEdit::Password : QLineEdit::Normal); | 579 | ui->line_edit_osk->setFont(editor_font); |
| 80 | 580 | ui->text_edit_osk->setFont(editor_font); | |
| 81 | connect(line_edit, &QLineEdit::textChanged, this, [this](const QString& text) { | 581 | ui->label_characters->setFont(sub_font); |
| 82 | length_label->setText(QStringLiteral("%1/%2").arg(text.size()).arg(parameters.max_length)); | 582 | ui->label_characters_box->setFont(sub_font); |
| 83 | }); | 583 | |
| 84 | 584 | ui->label_shift->setFont(label_button_font); | |
| 85 | buttons = new QDialogButtonBox(QDialogButtonBox::Cancel); | 585 | ui->label_shift_shift->setFont(label_button_font); |
| 86 | if (parameters.submit_text.empty()) { | 586 | ui->label_cancel->setFont(label_button_font); |
| 87 | buttons->addButton(QDialogButtonBox::Ok); | 587 | ui->label_cancel_shift->setFont(label_button_font); |
| 588 | ui->label_cancel_num->setFont(label_button_font); | ||
| 589 | ui->label_enter->setFont(label_button_font); | ||
| 590 | ui->label_enter_shift->setFont(label_button_font); | ||
| 591 | ui->label_enter_num->setFont(label_button_font); | ||
| 592 | |||
| 593 | for (auto* button : all_buttons) { | ||
| 594 | if (button == ui->button_return || button == ui->button_return_shift) { | ||
| 595 | button->setFont(label_button_font); | ||
| 596 | continue; | ||
| 597 | } | ||
| 598 | |||
| 599 | if (button == ui->button_space || button == ui->button_space_shift) { | ||
| 600 | button->setFont(label_button_font); | ||
| 601 | continue; | ||
| 602 | } | ||
| 603 | |||
| 604 | if (button == ui->button_shift || button == ui->button_shift_shift) { | ||
| 605 | button->setFont(label_button_font); | ||
| 606 | button->setIconSize(QSize(BASE_ICON_BUTTON_SIZE, BASE_ICON_BUTTON_SIZE) * | ||
| 607 | (height / BASE_HEIGHT)); | ||
| 608 | continue; | ||
| 609 | } | ||
| 610 | |||
| 611 | if (button == ui->button_backspace || button == ui->button_backspace_shift || | ||
| 612 | button == ui->button_backspace_num) { | ||
| 613 | button->setFont(label_button_font); | ||
| 614 | button->setIconSize(QSize(BASE_ICON_BUTTON_SIZE, BASE_ICON_BUTTON_SIZE) * | ||
| 615 | (height / BASE_HEIGHT)); | ||
| 616 | continue; | ||
| 617 | } | ||
| 618 | |||
| 619 | if (button == ui->button_ok || button == ui->button_ok_shift || | ||
| 620 | button == ui->button_ok_num) { | ||
| 621 | button->setFont(label_button_font); | ||
| 622 | continue; | ||
| 623 | } | ||
| 624 | |||
| 625 | button->setFont(char_button_font); | ||
| 626 | } | ||
| 627 | } | ||
| 628 | |||
| 629 | void QtSoftwareKeyboardDialog::SetKeyboardType() { | ||
| 630 | switch (initialize_parameters.type) { | ||
| 631 | case SwkbdType::Normal: | ||
| 632 | case SwkbdType::Qwerty: | ||
| 633 | case SwkbdType::Unknown3: | ||
| 634 | case SwkbdType::Latin: | ||
| 635 | case SwkbdType::SimplifiedChinese: | ||
| 636 | case SwkbdType::TraditionalChinese: | ||
| 637 | case SwkbdType::Korean: | ||
| 638 | default: { | ||
| 639 | bottom_osk_index = BottomOSKIndex::LowerCase; | ||
| 640 | ui->bottomOSK->setCurrentIndex(static_cast<int>(bottom_osk_index)); | ||
| 641 | |||
| 642 | ui->verticalLayout_2->setStretch(0, 320); | ||
| 643 | ui->verticalLayout_2->setStretch(1, 400); | ||
| 644 | |||
| 645 | ui->gridLineOSK->setRowStretch(5, 94); | ||
| 646 | ui->gridBoxOSK->setRowStretch(2, 81); | ||
| 647 | break; | ||
| 648 | } | ||
| 649 | case SwkbdType::NumberPad: { | ||
| 650 | bottom_osk_index = BottomOSKIndex::NumberPad; | ||
| 651 | ui->bottomOSK->setCurrentIndex(static_cast<int>(bottom_osk_index)); | ||
| 652 | |||
| 653 | ui->verticalLayout_2->setStretch(0, 370); | ||
| 654 | ui->verticalLayout_2->setStretch(1, 350); | ||
| 655 | |||
| 656 | ui->gridLineOSK->setRowStretch(5, 144); | ||
| 657 | ui->gridBoxOSK->setRowStretch(2, 131); | ||
| 658 | break; | ||
| 659 | } | ||
| 660 | } | ||
| 661 | } | ||
| 662 | |||
| 663 | void QtSoftwareKeyboardDialog::SetPasswordMode() { | ||
| 664 | switch (initialize_parameters.password_mode) { | ||
| 665 | case SwkbdPasswordMode::Disabled: | ||
| 666 | default: | ||
| 667 | ui->line_edit_osk->setEchoMode(QLineEdit::Normal); | ||
| 668 | break; | ||
| 669 | case SwkbdPasswordMode::Enabled: | ||
| 670 | ui->line_edit_osk->setEchoMode(QLineEdit::Password); | ||
| 671 | break; | ||
| 672 | } | ||
| 673 | } | ||
| 674 | |||
| 675 | void QtSoftwareKeyboardDialog::SetTextDrawType() { | ||
| 676 | switch (initialize_parameters.text_draw_type) { | ||
| 677 | case SwkbdTextDrawType::Line: | ||
| 678 | case SwkbdTextDrawType::DownloadCode: { | ||
| 679 | ui->topOSK->setCurrentIndex(0); | ||
| 680 | |||
| 681 | if (initialize_parameters.max_text_length <= 10) { | ||
| 682 | ui->gridLineOSK->setColumnStretch(0, 390); | ||
| 683 | ui->gridLineOSK->setColumnStretch(1, 500); | ||
| 684 | ui->gridLineOSK->setColumnStretch(2, 390); | ||
| 685 | } else { | ||
| 686 | ui->gridLineOSK->setColumnStretch(0, 130); | ||
| 687 | ui->gridLineOSK->setColumnStretch(1, 1020); | ||
| 688 | ui->gridLineOSK->setColumnStretch(2, 130); | ||
| 689 | } | ||
| 690 | |||
| 691 | if (is_inline) { | ||
| 692 | return; | ||
| 693 | } | ||
| 694 | |||
| 695 | connect(ui->line_edit_osk, &QLineEdit::textChanged, [this](const QString& changed_string) { | ||
| 696 | const auto is_valid = ValidateInputText(changed_string); | ||
| 697 | |||
| 698 | const auto text_length = static_cast<u32>(changed_string.length()); | ||
| 699 | |||
| 700 | ui->label_characters->setText(QStringLiteral("%1/%2") | ||
| 701 | .arg(text_length) | ||
| 702 | .arg(initialize_parameters.max_text_length)); | ||
| 703 | |||
| 704 | ui->button_ok->setEnabled(is_valid); | ||
| 705 | ui->button_ok_shift->setEnabled(is_valid); | ||
| 706 | ui->button_ok_num->setEnabled(is_valid); | ||
| 707 | |||
| 708 | ui->line_edit_osk->setFocus(); | ||
| 709 | }); | ||
| 710 | |||
| 711 | connect(ui->line_edit_osk, &QLineEdit::cursorPositionChanged, | ||
| 712 | [this](int old_cursor_position, int new_cursor_position) { | ||
| 713 | ui->button_backspace->setEnabled( | ||
| 714 | initialize_parameters.enable_backspace_button && new_cursor_position > 0); | ||
| 715 | ui->button_backspace_shift->setEnabled( | ||
| 716 | initialize_parameters.enable_backspace_button && new_cursor_position > 0); | ||
| 717 | ui->button_backspace_num->setEnabled( | ||
| 718 | initialize_parameters.enable_backspace_button && new_cursor_position > 0); | ||
| 719 | |||
| 720 | ui->line_edit_osk->setFocus(); | ||
| 721 | }); | ||
| 722 | |||
| 723 | connect(ui->line_edit_osk, &QLineEdit::returnPressed, [this] { | ||
| 724 | switch (bottom_osk_index) { | ||
| 725 | case BottomOSKIndex::LowerCase: | ||
| 726 | ui->button_ok->click(); | ||
| 727 | break; | ||
| 728 | case BottomOSKIndex::UpperCase: | ||
| 729 | ui->button_ok_shift->click(); | ||
| 730 | break; | ||
| 731 | case BottomOSKIndex::NumberPad: | ||
| 732 | ui->button_ok_num->click(); | ||
| 733 | break; | ||
| 734 | default: | ||
| 735 | break; | ||
| 736 | } | ||
| 737 | }); | ||
| 738 | |||
| 739 | ui->line_edit_osk->setPlaceholderText( | ||
| 740 | QString::fromStdU16String(initialize_parameters.guide_text)); | ||
| 741 | ui->line_edit_osk->setText(QString::fromStdU16String(initialize_parameters.initial_text)); | ||
| 742 | ui->line_edit_osk->setMaxLength(initialize_parameters.max_text_length); | ||
| 743 | ui->line_edit_osk->setCursorPosition(initialize_parameters.initial_cursor_position); | ||
| 744 | |||
| 745 | ui->label_characters->setText(QStringLiteral("%1/%2") | ||
| 746 | .arg(initialize_parameters.initial_text.size()) | ||
| 747 | .arg(initialize_parameters.max_text_length)); | ||
| 748 | break; | ||
| 749 | } | ||
| 750 | case SwkbdTextDrawType::Box: | ||
| 751 | default: { | ||
| 752 | ui->topOSK->setCurrentIndex(1); | ||
| 753 | |||
| 754 | if (is_inline) { | ||
| 755 | return; | ||
| 756 | } | ||
| 757 | |||
| 758 | connect(ui->text_edit_osk, &QTextEdit::textChanged, [this] { | ||
| 759 | if (static_cast<u32>(ui->text_edit_osk->toPlainText().length()) > | ||
| 760 | initialize_parameters.max_text_length) { | ||
| 761 | auto text_cursor = ui->text_edit_osk->textCursor(); | ||
| 762 | ui->text_edit_osk->setTextCursor(text_cursor); | ||
| 763 | text_cursor.deletePreviousChar(); | ||
| 764 | } | ||
| 765 | |||
| 766 | const auto is_valid = ValidateInputText(ui->text_edit_osk->toPlainText()); | ||
| 767 | |||
| 768 | const auto text_length = static_cast<u32>(ui->text_edit_osk->toPlainText().length()); | ||
| 769 | |||
| 770 | ui->label_characters_box->setText(QStringLiteral("%1/%2") | ||
| 771 | .arg(text_length) | ||
| 772 | .arg(initialize_parameters.max_text_length)); | ||
| 773 | |||
| 774 | ui->button_ok->setEnabled(is_valid); | ||
| 775 | ui->button_ok_shift->setEnabled(is_valid); | ||
| 776 | ui->button_ok_num->setEnabled(is_valid); | ||
| 777 | |||
| 778 | ui->text_edit_osk->setFocus(); | ||
| 779 | }); | ||
| 780 | |||
| 781 | connect(ui->text_edit_osk, &QTextEdit::cursorPositionChanged, [this] { | ||
| 782 | const auto new_cursor_position = ui->text_edit_osk->textCursor().position(); | ||
| 783 | |||
| 784 | ui->button_backspace->setEnabled(initialize_parameters.enable_backspace_button && | ||
| 785 | new_cursor_position > 0); | ||
| 786 | ui->button_backspace_shift->setEnabled(initialize_parameters.enable_backspace_button && | ||
| 787 | new_cursor_position > 0); | ||
| 788 | ui->button_backspace_num->setEnabled(initialize_parameters.enable_backspace_button && | ||
| 789 | new_cursor_position > 0); | ||
| 790 | |||
| 791 | ui->text_edit_osk->setFocus(); | ||
| 792 | }); | ||
| 793 | |||
| 794 | ui->text_edit_osk->setPlaceholderText( | ||
| 795 | QString::fromStdU16String(initialize_parameters.guide_text)); | ||
| 796 | ui->text_edit_osk->setText(QString::fromStdU16String(initialize_parameters.initial_text)); | ||
| 797 | ui->text_edit_osk->moveCursor(initialize_parameters.initial_cursor_position == 0 | ||
| 798 | ? QTextCursor::Start | ||
| 799 | : QTextCursor::End); | ||
| 800 | |||
| 801 | ui->label_characters_box->setText(QStringLiteral("%1/%2") | ||
| 802 | .arg(initialize_parameters.initial_text.size()) | ||
| 803 | .arg(initialize_parameters.max_text_length)); | ||
| 804 | break; | ||
| 805 | } | ||
| 806 | } | ||
| 807 | } | ||
| 808 | |||
| 809 | void QtSoftwareKeyboardDialog::SetControllerImage() { | ||
| 810 | const auto controller_type = Settings::values.players.GetValue()[8].connected | ||
| 811 | ? Settings::values.players.GetValue()[8].controller_type | ||
| 812 | : Settings::values.players.GetValue()[0].controller_type; | ||
| 813 | |||
| 814 | const QString theme = [] { | ||
| 815 | if (QIcon::themeName().contains(QStringLiteral("dark")) || | ||
| 816 | QIcon::themeName().contains(QStringLiteral("midnight"))) { | ||
| 817 | return QStringLiteral("_dark"); | ||
| 818 | } else { | ||
| 819 | return QString{}; | ||
| 820 | } | ||
| 821 | }(); | ||
| 822 | |||
| 823 | switch (controller_type) { | ||
| 824 | case Settings::ControllerType::ProController: | ||
| 825 | case Settings::ControllerType::GameCube: | ||
| 826 | ui->icon_controller->setStyleSheet( | ||
| 827 | QStringLiteral("image: url(:/overlay/controller_pro%1.png);").arg(theme)); | ||
| 828 | ui->icon_controller_shift->setStyleSheet( | ||
| 829 | QStringLiteral("image: url(:/overlay/controller_pro%1.png);").arg(theme)); | ||
| 830 | ui->icon_controller_num->setStyleSheet( | ||
| 831 | QStringLiteral("image: url(:/overlay/controller_pro%1.png);").arg(theme)); | ||
| 832 | break; | ||
| 833 | case Settings::ControllerType::DualJoyconDetached: | ||
| 834 | ui->icon_controller->setStyleSheet( | ||
| 835 | QStringLiteral("image: url(:/overlay/controller_dual_joycon%1.png);").arg(theme)); | ||
| 836 | ui->icon_controller_shift->setStyleSheet( | ||
| 837 | QStringLiteral("image: url(:/overlay/controller_dual_joycon%1.png);").arg(theme)); | ||
| 838 | ui->icon_controller_num->setStyleSheet( | ||
| 839 | QStringLiteral("image: url(:/overlay/controller_dual_joycon%1.png);").arg(theme)); | ||
| 840 | break; | ||
| 841 | case Settings::ControllerType::LeftJoycon: | ||
| 842 | ui->icon_controller->setStyleSheet( | ||
| 843 | QStringLiteral("image: url(:/overlay/controller_single_joycon_left%1.png);") | ||
| 844 | .arg(theme)); | ||
| 845 | ui->icon_controller_shift->setStyleSheet( | ||
| 846 | QStringLiteral("image: url(:/overlay/controller_single_joycon_left%1.png);") | ||
| 847 | .arg(theme)); | ||
| 848 | ui->icon_controller_num->setStyleSheet( | ||
| 849 | QStringLiteral("image: url(:/overlay/controller_single_joycon_left%1.png);") | ||
| 850 | .arg(theme)); | ||
| 851 | break; | ||
| 852 | case Settings::ControllerType::RightJoycon: | ||
| 853 | ui->icon_controller->setStyleSheet( | ||
| 854 | QStringLiteral("image: url(:/overlay/controller_single_joycon_right%1.png);") | ||
| 855 | .arg(theme)); | ||
| 856 | ui->icon_controller_shift->setStyleSheet( | ||
| 857 | QStringLiteral("image: url(:/overlay/controller_single_joycon_right%1.png);") | ||
| 858 | .arg(theme)); | ||
| 859 | ui->icon_controller_num->setStyleSheet( | ||
| 860 | QStringLiteral("image: url(:/overlay/controller_single_joycon_right%1.png);") | ||
| 861 | .arg(theme)); | ||
| 862 | break; | ||
| 863 | case Settings::ControllerType::Handheld: | ||
| 864 | ui->icon_controller->setStyleSheet( | ||
| 865 | QStringLiteral("image: url(:/overlay/controller_handheld%1.png);").arg(theme)); | ||
| 866 | ui->icon_controller_shift->setStyleSheet( | ||
| 867 | QStringLiteral("image: url(:/overlay/controller_handheld%1.png);").arg(theme)); | ||
| 868 | ui->icon_controller_num->setStyleSheet( | ||
| 869 | QStringLiteral("image: url(:/overlay/controller_handheld%1.png);").arg(theme)); | ||
| 870 | break; | ||
| 871 | default: | ||
| 872 | break; | ||
| 873 | } | ||
| 874 | } | ||
| 875 | |||
| 876 | void QtSoftwareKeyboardDialog::DisableKeyboardButtons() { | ||
| 877 | switch (bottom_osk_index) { | ||
| 878 | case BottomOSKIndex::LowerCase: | ||
| 879 | case BottomOSKIndex::UpperCase: | ||
| 880 | default: { | ||
| 881 | for (const auto& keys : keyboard_buttons) { | ||
| 882 | for (const auto& rows : keys) { | ||
| 883 | for (auto* button : rows) { | ||
| 884 | if (!button) { | ||
| 885 | continue; | ||
| 886 | } | ||
| 887 | |||
| 888 | button->setEnabled(true); | ||
| 889 | } | ||
| 890 | } | ||
| 891 | } | ||
| 892 | |||
| 893 | const auto& key_disable_flags = initialize_parameters.key_disable_flags; | ||
| 894 | |||
| 895 | ui->button_space->setDisabled(key_disable_flags.space); | ||
| 896 | ui->button_space_shift->setDisabled(key_disable_flags.space); | ||
| 897 | |||
| 898 | ui->button_at->setDisabled(key_disable_flags.at || key_disable_flags.username); | ||
| 899 | |||
| 900 | ui->button_percent->setDisabled(key_disable_flags.percent || key_disable_flags.username); | ||
| 901 | |||
| 902 | ui->button_slash->setDisabled(key_disable_flags.slash); | ||
| 903 | |||
| 904 | ui->button_1->setDisabled(key_disable_flags.numbers); | ||
| 905 | ui->button_2->setDisabled(key_disable_flags.numbers); | ||
| 906 | ui->button_3->setDisabled(key_disable_flags.numbers); | ||
| 907 | ui->button_4->setDisabled(key_disable_flags.numbers); | ||
| 908 | ui->button_5->setDisabled(key_disable_flags.numbers); | ||
| 909 | ui->button_6->setDisabled(key_disable_flags.numbers); | ||
| 910 | ui->button_7->setDisabled(key_disable_flags.numbers); | ||
| 911 | ui->button_8->setDisabled(key_disable_flags.numbers); | ||
| 912 | ui->button_9->setDisabled(key_disable_flags.numbers); | ||
| 913 | ui->button_0->setDisabled(key_disable_flags.numbers); | ||
| 914 | |||
| 915 | ui->button_return->setEnabled(initialize_parameters.enable_return_button); | ||
| 916 | ui->button_return_shift->setEnabled(initialize_parameters.enable_return_button); | ||
| 917 | break; | ||
| 918 | } | ||
| 919 | case BottomOSKIndex::NumberPad: { | ||
| 920 | for (const auto& rows : numberpad_buttons) { | ||
| 921 | for (auto* button : rows) { | ||
| 922 | if (!button) { | ||
| 923 | continue; | ||
| 924 | } | ||
| 925 | |||
| 926 | button->setEnabled(true); | ||
| 927 | } | ||
| 928 | } | ||
| 929 | break; | ||
| 930 | } | ||
| 931 | } | ||
| 932 | } | ||
| 933 | |||
| 934 | void QtSoftwareKeyboardDialog::SetBackspaceOkEnabled() { | ||
| 935 | if (is_inline) { | ||
| 936 | ui->button_ok->setEnabled(current_text.size() >= initialize_parameters.min_text_length); | ||
| 937 | ui->button_ok_shift->setEnabled(current_text.size() >= | ||
| 938 | initialize_parameters.min_text_length); | ||
| 939 | ui->button_ok_num->setEnabled(current_text.size() >= initialize_parameters.min_text_length); | ||
| 940 | |||
| 941 | ui->button_backspace->setEnabled(initialize_parameters.enable_backspace_button && | ||
| 942 | cursor_position > 0); | ||
| 943 | ui->button_backspace_shift->setEnabled(initialize_parameters.enable_backspace_button && | ||
| 944 | cursor_position > 0); | ||
| 945 | ui->button_backspace_num->setEnabled(initialize_parameters.enable_backspace_button && | ||
| 946 | cursor_position > 0); | ||
| 88 | } else { | 947 | } else { |
| 89 | buttons->addButton(QString::fromStdU16String(parameters.submit_text), | 948 | const auto text_length = [this] { |
| 90 | QDialogButtonBox::AcceptRole); | 949 | if (ui->topOSK->currentIndex() == 1) { |
| 950 | return static_cast<u32>(ui->text_edit_osk->toPlainText().length()); | ||
| 951 | } else { | ||
| 952 | return static_cast<u32>(ui->line_edit_osk->text().length()); | ||
| 953 | } | ||
| 954 | }(); | ||
| 955 | |||
| 956 | const auto normal_cursor_position = [this] { | ||
| 957 | if (ui->topOSK->currentIndex() == 1) { | ||
| 958 | return ui->text_edit_osk->textCursor().position(); | ||
| 959 | } else { | ||
| 960 | return ui->line_edit_osk->cursorPosition(); | ||
| 961 | } | ||
| 962 | }(); | ||
| 963 | |||
| 964 | ui->button_ok->setEnabled(text_length >= initialize_parameters.min_text_length); | ||
| 965 | ui->button_ok_shift->setEnabled(text_length >= initialize_parameters.min_text_length); | ||
| 966 | ui->button_ok_num->setEnabled(text_length >= initialize_parameters.min_text_length); | ||
| 967 | |||
| 968 | ui->button_backspace->setEnabled(initialize_parameters.enable_backspace_button && | ||
| 969 | normal_cursor_position > 0); | ||
| 970 | ui->button_backspace_shift->setEnabled(initialize_parameters.enable_backspace_button && | ||
| 971 | normal_cursor_position > 0); | ||
| 972 | ui->button_backspace_num->setEnabled(initialize_parameters.enable_backspace_button && | ||
| 973 | normal_cursor_position > 0); | ||
| 91 | } | 974 | } |
| 92 | connect(buttons, &QDialogButtonBox::accepted, this, &QtSoftwareKeyboardDialog::accept); | ||
| 93 | connect(buttons, &QDialogButtonBox::rejected, this, &QtSoftwareKeyboardDialog::reject); | ||
| 94 | layout->addWidget(header_label); | ||
| 95 | layout->addWidget(sub_label); | ||
| 96 | layout->addWidget(guide_label); | ||
| 97 | layout->addWidget(length_label); | ||
| 98 | layout->addWidget(line_edit); | ||
| 99 | layout->addWidget(buttons); | ||
| 100 | setLayout(layout); | ||
| 101 | setWindowTitle(tr("Software Keyboard")); | ||
| 102 | } | 975 | } |
| 103 | 976 | ||
| 104 | QtSoftwareKeyboardDialog::~QtSoftwareKeyboardDialog() = default; | 977 | bool QtSoftwareKeyboardDialog::ValidateInputText(const QString& input_text) { |
| 978 | const auto& key_disable_flags = initialize_parameters.key_disable_flags; | ||
| 979 | |||
| 980 | const auto input_text_length = static_cast<u32>(input_text.length()); | ||
| 981 | |||
| 982 | if (input_text_length < initialize_parameters.min_text_length || | ||
| 983 | input_text_length > initialize_parameters.max_text_length) { | ||
| 984 | return false; | ||
| 985 | } | ||
| 986 | |||
| 987 | if (key_disable_flags.space && input_text.contains(QLatin1Char{' '})) { | ||
| 988 | return false; | ||
| 989 | } | ||
| 990 | |||
| 991 | if ((key_disable_flags.at || key_disable_flags.username) && | ||
| 992 | input_text.contains(QLatin1Char{'@'})) { | ||
| 993 | return false; | ||
| 994 | } | ||
| 995 | |||
| 996 | if ((key_disable_flags.percent || key_disable_flags.username) && | ||
| 997 | input_text.contains(QLatin1Char{'%'})) { | ||
| 998 | return false; | ||
| 999 | } | ||
| 1000 | |||
| 1001 | if (key_disable_flags.slash && input_text.contains(QLatin1Char{'/'})) { | ||
| 1002 | return false; | ||
| 1003 | } | ||
| 1004 | |||
| 1005 | if ((key_disable_flags.backslash || key_disable_flags.username) && | ||
| 1006 | input_text.contains(QLatin1Char('\\'))) { | ||
| 1007 | return false; | ||
| 1008 | } | ||
| 105 | 1009 | ||
| 106 | void QtSoftwareKeyboardDialog::accept() { | 1010 | if (key_disable_flags.numbers && |
| 107 | text = line_edit->text().toStdU16String(); | 1011 | std::any_of(input_text.begin(), input_text.end(), [](QChar c) { return c.isDigit(); })) { |
| 108 | QDialog::accept(); | 1012 | return false; |
| 1013 | } | ||
| 1014 | |||
| 1015 | if (bottom_osk_index == BottomOSKIndex::NumberPad && | ||
| 1016 | std::any_of(input_text.begin(), input_text.end(), [](QChar c) { return !c.isDigit(); })) { | ||
| 1017 | return false; | ||
| 1018 | } | ||
| 1019 | |||
| 1020 | return true; | ||
| 109 | } | 1021 | } |
| 110 | 1022 | ||
| 111 | void QtSoftwareKeyboardDialog::reject() { | 1023 | void QtSoftwareKeyboardDialog::ChangeBottomOSKIndex() { |
| 112 | text.clear(); | 1024 | switch (bottom_osk_index) { |
| 113 | QDialog::reject(); | 1025 | case BottomOSKIndex::LowerCase: |
| 1026 | bottom_osk_index = BottomOSKIndex::UpperCase; | ||
| 1027 | ui->bottomOSK->setCurrentIndex(static_cast<int>(bottom_osk_index)); | ||
| 1028 | |||
| 1029 | ui->button_shift_shift->setStyleSheet( | ||
| 1030 | QStringLiteral("background-image: url(:/overlay/osk_button_shift_lock_off.png);" | ||
| 1031 | "\nbackground-position: left top;" | ||
| 1032 | "\nbackground-repeat: no-repeat;" | ||
| 1033 | "\nbackground-origin: content;")); | ||
| 1034 | |||
| 1035 | ui->button_shift_shift->setIconSize(ui->button_shift->iconSize()); | ||
| 1036 | ui->button_backspace_shift->setIconSize(ui->button_backspace->iconSize()); | ||
| 1037 | break; | ||
| 1038 | case BottomOSKIndex::UpperCase: | ||
| 1039 | if (caps_lock_enabled) { | ||
| 1040 | caps_lock_enabled = false; | ||
| 1041 | |||
| 1042 | ui->button_shift_shift->setStyleSheet( | ||
| 1043 | QStringLiteral("background-image: url(:/overlay/osk_button_shift_lock_off.png);" | ||
| 1044 | "\nbackground-position: left top;" | ||
| 1045 | "\nbackground-repeat: no-repeat;" | ||
| 1046 | "\nbackground-origin: content;")); | ||
| 1047 | |||
| 1048 | ui->button_shift_shift->setIconSize(ui->button_shift->iconSize()); | ||
| 1049 | ui->button_backspace_shift->setIconSize(ui->button_backspace->iconSize()); | ||
| 1050 | |||
| 1051 | ui->label_shift_shift->setText(QStringLiteral("Caps Lock")); | ||
| 1052 | |||
| 1053 | bottom_osk_index = BottomOSKIndex::LowerCase; | ||
| 1054 | ui->bottomOSK->setCurrentIndex(static_cast<int>(bottom_osk_index)); | ||
| 1055 | } else { | ||
| 1056 | caps_lock_enabled = true; | ||
| 1057 | |||
| 1058 | ui->button_shift_shift->setStyleSheet( | ||
| 1059 | QStringLiteral("background-image: url(:/overlay/osk_button_shift_lock_on.png);" | ||
| 1060 | "\nbackground-position: left top;" | ||
| 1061 | "\nbackground-repeat: no-repeat;" | ||
| 1062 | "\nbackground-origin: content;")); | ||
| 1063 | |||
| 1064 | ui->button_shift_shift->setIconSize(ui->button_shift->iconSize()); | ||
| 1065 | ui->button_backspace_shift->setIconSize(ui->button_backspace->iconSize()); | ||
| 1066 | |||
| 1067 | ui->label_shift_shift->setText(QStringLiteral("Caps Lock Off")); | ||
| 1068 | } | ||
| 1069 | break; | ||
| 1070 | case BottomOSKIndex::NumberPad: | ||
| 1071 | default: | ||
| 1072 | break; | ||
| 1073 | } | ||
| 114 | } | 1074 | } |
| 115 | 1075 | ||
| 116 | std::u16string QtSoftwareKeyboardDialog::GetText() const { | 1076 | void QtSoftwareKeyboardDialog::NormalKeyboardButtonClicked(QPushButton* button) { |
| 117 | return text; | 1077 | if (button == ui->button_ampersand) { |
| 1078 | if (ui->topOSK->currentIndex() == 1) { | ||
| 1079 | ui->text_edit_osk->insertPlainText(QStringLiteral("&")); | ||
| 1080 | } else { | ||
| 1081 | ui->line_edit_osk->insert(QStringLiteral("&")); | ||
| 1082 | } | ||
| 1083 | return; | ||
| 1084 | } | ||
| 1085 | |||
| 1086 | if (button == ui->button_return || button == ui->button_return_shift) { | ||
| 1087 | if (ui->topOSK->currentIndex() == 1) { | ||
| 1088 | ui->text_edit_osk->insertPlainText(QStringLiteral("\n")); | ||
| 1089 | } else { | ||
| 1090 | ui->line_edit_osk->insert(QStringLiteral("\n")); | ||
| 1091 | } | ||
| 1092 | return; | ||
| 1093 | } | ||
| 1094 | |||
| 1095 | if (button == ui->button_space || button == ui->button_space_shift) { | ||
| 1096 | if (ui->topOSK->currentIndex() == 1) { | ||
| 1097 | ui->text_edit_osk->insertPlainText(QStringLiteral(" ")); | ||
| 1098 | } else { | ||
| 1099 | ui->line_edit_osk->insert(QStringLiteral(" ")); | ||
| 1100 | } | ||
| 1101 | return; | ||
| 1102 | } | ||
| 1103 | |||
| 1104 | if (button == ui->button_shift || button == ui->button_shift_shift) { | ||
| 1105 | ChangeBottomOSKIndex(); | ||
| 1106 | return; | ||
| 1107 | } | ||
| 1108 | |||
| 1109 | if (button == ui->button_backspace || button == ui->button_backspace_shift || | ||
| 1110 | button == ui->button_backspace_num) { | ||
| 1111 | if (ui->topOSK->currentIndex() == 1) { | ||
| 1112 | auto text_cursor = ui->text_edit_osk->textCursor(); | ||
| 1113 | ui->text_edit_osk->setTextCursor(text_cursor); | ||
| 1114 | text_cursor.deletePreviousChar(); | ||
| 1115 | } else { | ||
| 1116 | ui->line_edit_osk->backspace(); | ||
| 1117 | } | ||
| 1118 | return; | ||
| 1119 | } | ||
| 1120 | |||
| 1121 | if (button == ui->button_ok || button == ui->button_ok_shift || button == ui->button_ok_num) { | ||
| 1122 | if (ui->topOSK->currentIndex() == 1) { | ||
| 1123 | emit SubmitNormalText(SwkbdResult::Ok, | ||
| 1124 | ui->text_edit_osk->toPlainText().toStdU16String()); | ||
| 1125 | } else { | ||
| 1126 | emit SubmitNormalText(SwkbdResult::Ok, ui->line_edit_osk->text().toStdU16String()); | ||
| 1127 | } | ||
| 1128 | return; | ||
| 1129 | } | ||
| 1130 | |||
| 1131 | if (ui->topOSK->currentIndex() == 1) { | ||
| 1132 | ui->text_edit_osk->insertPlainText(button->text()); | ||
| 1133 | } else { | ||
| 1134 | ui->line_edit_osk->insert(button->text()); | ||
| 1135 | } | ||
| 1136 | |||
| 1137 | // Revert the keyboard to lowercase if the shift key is active. | ||
| 1138 | if (bottom_osk_index == BottomOSKIndex::UpperCase && !caps_lock_enabled) { | ||
| 1139 | // This is set to true since ChangeBottomOSKIndex will change bottom_osk_index to LowerCase | ||
| 1140 | // if bottom_osk_index is UpperCase and caps_lock_enabled is true. | ||
| 1141 | caps_lock_enabled = true; | ||
| 1142 | ChangeBottomOSKIndex(); | ||
| 1143 | } | ||
| 1144 | } | ||
| 1145 | |||
| 1146 | void QtSoftwareKeyboardDialog::InlineKeyboardButtonClicked(QPushButton* button) { | ||
| 1147 | if (!button->isEnabled()) { | ||
| 1148 | return; | ||
| 1149 | } | ||
| 1150 | |||
| 1151 | if (button == ui->button_ampersand) { | ||
| 1152 | InlineTextInsertString(u"&"); | ||
| 1153 | return; | ||
| 1154 | } | ||
| 1155 | |||
| 1156 | if (button == ui->button_return || button == ui->button_return_shift) { | ||
| 1157 | InlineTextInsertString(u"\n"); | ||
| 1158 | return; | ||
| 1159 | } | ||
| 1160 | |||
| 1161 | if (button == ui->button_space || button == ui->button_space_shift) { | ||
| 1162 | InlineTextInsertString(u" "); | ||
| 1163 | return; | ||
| 1164 | } | ||
| 1165 | |||
| 1166 | if (button == ui->button_shift || button == ui->button_shift_shift) { | ||
| 1167 | ChangeBottomOSKIndex(); | ||
| 1168 | return; | ||
| 1169 | } | ||
| 1170 | |||
| 1171 | if (button == ui->button_backspace || button == ui->button_backspace_shift || | ||
| 1172 | button == ui->button_backspace_num) { | ||
| 1173 | if (cursor_position <= 0 || current_text.empty()) { | ||
| 1174 | cursor_position = 0; | ||
| 1175 | return; | ||
| 1176 | } | ||
| 1177 | |||
| 1178 | --cursor_position; | ||
| 1179 | |||
| 1180 | current_text.erase(cursor_position, 1); | ||
| 1181 | |||
| 1182 | SetBackspaceOkEnabled(); | ||
| 1183 | |||
| 1184 | emit SubmitInlineText(SwkbdReplyType::ChangedString, current_text, cursor_position); | ||
| 1185 | return; | ||
| 1186 | } | ||
| 1187 | |||
| 1188 | if (button == ui->button_ok || button == ui->button_ok_shift || button == ui->button_ok_num) { | ||
| 1189 | emit SubmitInlineText(SwkbdReplyType::DecidedEnter, current_text, cursor_position); | ||
| 1190 | return; | ||
| 1191 | } | ||
| 1192 | |||
| 1193 | InlineTextInsertString(button->text().toStdU16String()); | ||
| 1194 | |||
| 1195 | // Revert the keyboard to lowercase if the shift key is active. | ||
| 1196 | if (bottom_osk_index == BottomOSKIndex::UpperCase && !caps_lock_enabled) { | ||
| 1197 | // This is set to true since ChangeBottomOSKIndex will change bottom_osk_index to LowerCase | ||
| 1198 | // if bottom_osk_index is UpperCase and caps_lock_enabled is true. | ||
| 1199 | caps_lock_enabled = true; | ||
| 1200 | ChangeBottomOSKIndex(); | ||
| 1201 | } | ||
| 1202 | } | ||
| 1203 | |||
| 1204 | void QtSoftwareKeyboardDialog::InlineTextInsertString(std::u16string_view string) { | ||
| 1205 | if ((current_text.size() + string.size()) > initialize_parameters.max_text_length) { | ||
| 1206 | return; | ||
| 1207 | } | ||
| 1208 | |||
| 1209 | current_text.insert(cursor_position, string); | ||
| 1210 | |||
| 1211 | cursor_position += static_cast<s32>(string.size()); | ||
| 1212 | |||
| 1213 | SetBackspaceOkEnabled(); | ||
| 1214 | |||
| 1215 | emit SubmitInlineText(SwkbdReplyType::ChangedString, current_text, cursor_position); | ||
| 1216 | } | ||
| 1217 | |||
| 1218 | void QtSoftwareKeyboardDialog::SetupMouseHover() { | ||
| 1219 | // setFocus() has a bug where continuously changing focus will cause the focus UI to | ||
| 1220 | // mysteriously disappear. A workaround we have found is using the mouse to hover over | ||
| 1221 | // the buttons to act in place of the button focus. As a result, we will have to set | ||
| 1222 | // a blank cursor when hovering over all the buttons and set a no focus policy so the | ||
| 1223 | // buttons do not stay in focus in addition to the mouse hover. | ||
| 1224 | for (auto* button : all_buttons) { | ||
| 1225 | button->setCursor(QCursor(Qt::BlankCursor)); | ||
| 1226 | button->setFocusPolicy(Qt::NoFocus); | ||
| 1227 | } | ||
| 1228 | } | ||
| 1229 | |||
| 1230 | template <HIDButton... T> | ||
| 1231 | void QtSoftwareKeyboardDialog::HandleButtonPressedOnce() { | ||
| 1232 | const auto f = [this](HIDButton button) { | ||
| 1233 | if (input_interpreter->IsButtonPressedOnce(button)) { | ||
| 1234 | TranslateButtonPress(button); | ||
| 1235 | } | ||
| 1236 | }; | ||
| 1237 | |||
| 1238 | (f(T), ...); | ||
| 1239 | } | ||
| 1240 | |||
| 1241 | template <HIDButton... T> | ||
| 1242 | void QtSoftwareKeyboardDialog::HandleButtonHold() { | ||
| 1243 | const auto f = [this](HIDButton button) { | ||
| 1244 | if (input_interpreter->IsButtonHeld(button)) { | ||
| 1245 | TranslateButtonPress(button); | ||
| 1246 | } | ||
| 1247 | }; | ||
| 1248 | |||
| 1249 | (f(T), ...); | ||
| 1250 | } | ||
| 1251 | |||
| 1252 | void QtSoftwareKeyboardDialog::TranslateButtonPress(HIDButton button) { | ||
| 1253 | switch (button) { | ||
| 1254 | case HIDButton::A: | ||
| 1255 | switch (bottom_osk_index) { | ||
| 1256 | case BottomOSKIndex::LowerCase: | ||
| 1257 | case BottomOSKIndex::UpperCase: | ||
| 1258 | keyboard_buttons[static_cast<std::size_t>(bottom_osk_index)][row][column]->click(); | ||
| 1259 | break; | ||
| 1260 | case BottomOSKIndex::NumberPad: | ||
| 1261 | numberpad_buttons[row][column]->click(); | ||
| 1262 | break; | ||
| 1263 | default: | ||
| 1264 | break; | ||
| 1265 | } | ||
| 1266 | break; | ||
| 1267 | case HIDButton::B: | ||
| 1268 | switch (bottom_osk_index) { | ||
| 1269 | case BottomOSKIndex::LowerCase: | ||
| 1270 | ui->button_backspace->click(); | ||
| 1271 | break; | ||
| 1272 | case BottomOSKIndex::UpperCase: | ||
| 1273 | ui->button_backspace_shift->click(); | ||
| 1274 | break; | ||
| 1275 | case BottomOSKIndex::NumberPad: | ||
| 1276 | ui->button_backspace_num->click(); | ||
| 1277 | break; | ||
| 1278 | default: | ||
| 1279 | break; | ||
| 1280 | } | ||
| 1281 | break; | ||
| 1282 | case HIDButton::X: | ||
| 1283 | if (is_inline) { | ||
| 1284 | emit SubmitInlineText(SwkbdReplyType::DecidedCancel, current_text, cursor_position); | ||
| 1285 | } else { | ||
| 1286 | if (ui->topOSK->currentIndex() == 1) { | ||
| 1287 | emit SubmitNormalText(SwkbdResult::Cancel, | ||
| 1288 | ui->text_edit_osk->toPlainText().toStdU16String()); | ||
| 1289 | } else { | ||
| 1290 | emit SubmitNormalText(SwkbdResult::Cancel, | ||
| 1291 | ui->line_edit_osk->text().toStdU16String()); | ||
| 1292 | } | ||
| 1293 | } | ||
| 1294 | break; | ||
| 1295 | case HIDButton::Y: | ||
| 1296 | switch (bottom_osk_index) { | ||
| 1297 | case BottomOSKIndex::LowerCase: | ||
| 1298 | ui->button_space->click(); | ||
| 1299 | break; | ||
| 1300 | case BottomOSKIndex::UpperCase: | ||
| 1301 | ui->button_space_shift->click(); | ||
| 1302 | break; | ||
| 1303 | case BottomOSKIndex::NumberPad: | ||
| 1304 | default: | ||
| 1305 | break; | ||
| 1306 | } | ||
| 1307 | break; | ||
| 1308 | case HIDButton::LStick: | ||
| 1309 | case HIDButton::RStick: | ||
| 1310 | switch (bottom_osk_index) { | ||
| 1311 | case BottomOSKIndex::LowerCase: | ||
| 1312 | ui->button_shift->click(); | ||
| 1313 | break; | ||
| 1314 | case BottomOSKIndex::UpperCase: | ||
| 1315 | ui->button_shift_shift->click(); | ||
| 1316 | break; | ||
| 1317 | case BottomOSKIndex::NumberPad: | ||
| 1318 | default: | ||
| 1319 | break; | ||
| 1320 | } | ||
| 1321 | break; | ||
| 1322 | case HIDButton::L: | ||
| 1323 | MoveTextCursorDirection(Direction::Left); | ||
| 1324 | break; | ||
| 1325 | case HIDButton::R: | ||
| 1326 | MoveTextCursorDirection(Direction::Right); | ||
| 1327 | break; | ||
| 1328 | case HIDButton::Plus: | ||
| 1329 | switch (bottom_osk_index) { | ||
| 1330 | case BottomOSKIndex::LowerCase: | ||
| 1331 | ui->button_ok->click(); | ||
| 1332 | break; | ||
| 1333 | case BottomOSKIndex::UpperCase: | ||
| 1334 | ui->button_ok_shift->click(); | ||
| 1335 | break; | ||
| 1336 | case BottomOSKIndex::NumberPad: | ||
| 1337 | ui->button_ok_num->click(); | ||
| 1338 | break; | ||
| 1339 | default: | ||
| 1340 | break; | ||
| 1341 | } | ||
| 1342 | break; | ||
| 1343 | case HIDButton::DLeft: | ||
| 1344 | case HIDButton::LStickLeft: | ||
| 1345 | case HIDButton::RStickLeft: | ||
| 1346 | MoveButtonDirection(Direction::Left); | ||
| 1347 | break; | ||
| 1348 | case HIDButton::DUp: | ||
| 1349 | case HIDButton::LStickUp: | ||
| 1350 | case HIDButton::RStickUp: | ||
| 1351 | MoveButtonDirection(Direction::Up); | ||
| 1352 | break; | ||
| 1353 | case HIDButton::DRight: | ||
| 1354 | case HIDButton::LStickRight: | ||
| 1355 | case HIDButton::RStickRight: | ||
| 1356 | MoveButtonDirection(Direction::Right); | ||
| 1357 | break; | ||
| 1358 | case HIDButton::DDown: | ||
| 1359 | case HIDButton::LStickDown: | ||
| 1360 | case HIDButton::RStickDown: | ||
| 1361 | MoveButtonDirection(Direction::Down); | ||
| 1362 | break; | ||
| 1363 | default: | ||
| 1364 | break; | ||
| 1365 | } | ||
| 1366 | } | ||
| 1367 | |||
| 1368 | void QtSoftwareKeyboardDialog::MoveButtonDirection(Direction direction) { | ||
| 1369 | // Changes the row or column index depending on the direction. | ||
| 1370 | auto move_direction = [this, direction](std::size_t max_rows, std::size_t max_columns) { | ||
| 1371 | switch (direction) { | ||
| 1372 | case Direction::Left: | ||
| 1373 | column = (column + max_columns - 1) % max_columns; | ||
| 1374 | break; | ||
| 1375 | case Direction::Up: | ||
| 1376 | row = (row + max_rows - 1) % max_rows; | ||
| 1377 | break; | ||
| 1378 | case Direction::Right: | ||
| 1379 | column = (column + 1) % max_columns; | ||
| 1380 | break; | ||
| 1381 | case Direction::Down: | ||
| 1382 | row = (row + 1) % max_rows; | ||
| 1383 | break; | ||
| 1384 | default: | ||
| 1385 | break; | ||
| 1386 | } | ||
| 1387 | }; | ||
| 1388 | |||
| 1389 | switch (bottom_osk_index) { | ||
| 1390 | case BottomOSKIndex::LowerCase: | ||
| 1391 | case BottomOSKIndex::UpperCase: { | ||
| 1392 | const auto index = static_cast<std::size_t>(bottom_osk_index); | ||
| 1393 | |||
| 1394 | const auto* const prev_button = keyboard_buttons[index][row][column]; | ||
| 1395 | move_direction(NUM_ROWS_NORMAL, NUM_COLUMNS_NORMAL); | ||
| 1396 | auto* curr_button = keyboard_buttons[index][row][column]; | ||
| 1397 | |||
| 1398 | while (!curr_button || !curr_button->isEnabled() || curr_button == prev_button) { | ||
| 1399 | move_direction(NUM_ROWS_NORMAL, NUM_COLUMNS_NORMAL); | ||
| 1400 | curr_button = keyboard_buttons[index][row][column]; | ||
| 1401 | } | ||
| 1402 | |||
| 1403 | // This is a workaround for setFocus() randomly not showing focus in the UI | ||
| 1404 | QCursor::setPos(curr_button->mapToGlobal(curr_button->rect().center())); | ||
| 1405 | break; | ||
| 1406 | } | ||
| 1407 | case BottomOSKIndex::NumberPad: { | ||
| 1408 | const auto* const prev_button = numberpad_buttons[row][column]; | ||
| 1409 | move_direction(NUM_ROWS_NUMPAD, NUM_COLUMNS_NUMPAD); | ||
| 1410 | auto* curr_button = numberpad_buttons[row][column]; | ||
| 1411 | |||
| 1412 | while (!curr_button || !curr_button->isEnabled() || curr_button == prev_button) { | ||
| 1413 | move_direction(NUM_ROWS_NUMPAD, NUM_COLUMNS_NUMPAD); | ||
| 1414 | curr_button = numberpad_buttons[row][column]; | ||
| 1415 | } | ||
| 1416 | |||
| 1417 | // This is a workaround for setFocus() randomly not showing focus in the UI | ||
| 1418 | QCursor::setPos(curr_button->mapToGlobal(curr_button->rect().center())); | ||
| 1419 | break; | ||
| 1420 | } | ||
| 1421 | default: | ||
| 1422 | break; | ||
| 1423 | } | ||
| 1424 | } | ||
| 1425 | |||
| 1426 | void QtSoftwareKeyboardDialog::MoveTextCursorDirection(Direction direction) { | ||
| 1427 | switch (direction) { | ||
| 1428 | case Direction::Left: | ||
| 1429 | if (is_inline) { | ||
| 1430 | if (cursor_position <= 0) { | ||
| 1431 | cursor_position = 0; | ||
| 1432 | } else { | ||
| 1433 | --cursor_position; | ||
| 1434 | emit SubmitInlineText(SwkbdReplyType::MovedCursor, current_text, cursor_position); | ||
| 1435 | } | ||
| 1436 | } else { | ||
| 1437 | if (ui->topOSK->currentIndex() == 1) { | ||
| 1438 | ui->text_edit_osk->moveCursor(QTextCursor::Left); | ||
| 1439 | } else { | ||
| 1440 | ui->line_edit_osk->setCursorPosition(ui->line_edit_osk->cursorPosition() - 1); | ||
| 1441 | } | ||
| 1442 | } | ||
| 1443 | break; | ||
| 1444 | case Direction::Right: | ||
| 1445 | if (is_inline) { | ||
| 1446 | if (cursor_position >= static_cast<s32>(current_text.size())) { | ||
| 1447 | cursor_position = static_cast<s32>(current_text.size()); | ||
| 1448 | } else { | ||
| 1449 | ++cursor_position; | ||
| 1450 | emit SubmitInlineText(SwkbdReplyType::MovedCursor, current_text, cursor_position); | ||
| 1451 | } | ||
| 1452 | } else { | ||
| 1453 | if (ui->topOSK->currentIndex() == 1) { | ||
| 1454 | ui->text_edit_osk->moveCursor(QTextCursor::Right); | ||
| 1455 | } else { | ||
| 1456 | ui->line_edit_osk->setCursorPosition(ui->line_edit_osk->cursorPosition() + 1); | ||
| 1457 | } | ||
| 1458 | } | ||
| 1459 | break; | ||
| 1460 | default: | ||
| 1461 | break; | ||
| 1462 | } | ||
| 1463 | } | ||
| 1464 | |||
| 1465 | void QtSoftwareKeyboardDialog::StartInputThread() { | ||
| 1466 | if (input_thread_running) { | ||
| 1467 | return; | ||
| 1468 | } | ||
| 1469 | |||
| 1470 | input_thread_running = true; | ||
| 1471 | |||
| 1472 | input_thread = std::thread(&QtSoftwareKeyboardDialog::InputThread, this); | ||
| 1473 | } | ||
| 1474 | |||
| 1475 | void QtSoftwareKeyboardDialog::StopInputThread() { | ||
| 1476 | input_thread_running = false; | ||
| 1477 | |||
| 1478 | if (input_thread.joinable()) { | ||
| 1479 | input_thread.join(); | ||
| 1480 | } | ||
| 1481 | |||
| 1482 | if (input_interpreter) { | ||
| 1483 | input_interpreter->ResetButtonStates(); | ||
| 1484 | } | ||
| 1485 | } | ||
| 1486 | |||
| 1487 | void QtSoftwareKeyboardDialog::InputThread() { | ||
| 1488 | while (input_thread_running) { | ||
| 1489 | input_interpreter->PollInput(); | ||
| 1490 | |||
| 1491 | HandleButtonPressedOnce<HIDButton::A, HIDButton::B, HIDButton::X, HIDButton::Y, | ||
| 1492 | HIDButton::LStick, HIDButton::RStick, HIDButton::L, HIDButton::R, | ||
| 1493 | HIDButton::Plus, HIDButton::DLeft, HIDButton::DUp, | ||
| 1494 | HIDButton::DRight, HIDButton::DDown, HIDButton::LStickLeft, | ||
| 1495 | HIDButton::LStickUp, HIDButton::LStickRight, HIDButton::LStickDown, | ||
| 1496 | HIDButton::RStickLeft, HIDButton::RStickUp, HIDButton::RStickRight, | ||
| 1497 | HIDButton::RStickDown>(); | ||
| 1498 | |||
| 1499 | HandleButtonHold<HIDButton::B, HIDButton::L, HIDButton::R, HIDButton::DLeft, HIDButton::DUp, | ||
| 1500 | HIDButton::DRight, HIDButton::DDown, HIDButton::LStickLeft, | ||
| 1501 | HIDButton::LStickUp, HIDButton::LStickRight, HIDButton::LStickDown, | ||
| 1502 | HIDButton::RStickLeft, HIDButton::RStickUp, HIDButton::RStickRight, | ||
| 1503 | HIDButton::RStickDown>(); | ||
| 1504 | |||
| 1505 | std::this_thread::sleep_for(std::chrono::milliseconds(50)); | ||
| 1506 | } | ||
| 118 | } | 1507 | } |
| 119 | 1508 | ||
| 120 | QtSoftwareKeyboard::QtSoftwareKeyboard(GMainWindow& main_window) { | 1509 | QtSoftwareKeyboard::QtSoftwareKeyboard(GMainWindow& main_window) { |
| 121 | connect(this, &QtSoftwareKeyboard::MainWindowGetText, &main_window, | 1510 | connect(this, &QtSoftwareKeyboard::MainWindowInitializeKeyboard, &main_window, |
| 122 | &GMainWindow::SoftwareKeyboardGetText, Qt::QueuedConnection); | 1511 | &GMainWindow::SoftwareKeyboardInitialize, Qt::QueuedConnection); |
| 123 | connect(this, &QtSoftwareKeyboard::MainWindowTextCheckDialog, &main_window, | 1512 | connect(this, &QtSoftwareKeyboard::MainWindowShowNormalKeyboard, &main_window, |
| 124 | &GMainWindow::SoftwareKeyboardInvokeCheckDialog, Qt::BlockingQueuedConnection); | 1513 | &GMainWindow::SoftwareKeyboardShowNormal, Qt::QueuedConnection); |
| 125 | connect(&main_window, &GMainWindow::SoftwareKeyboardFinishedText, this, | 1514 | connect(this, &QtSoftwareKeyboard::MainWindowShowTextCheckDialog, &main_window, |
| 126 | &QtSoftwareKeyboard::MainWindowFinishedText, Qt::QueuedConnection); | 1515 | &GMainWindow::SoftwareKeyboardShowTextCheck, Qt::QueuedConnection); |
| 1516 | connect(this, &QtSoftwareKeyboard::MainWindowShowInlineKeyboard, &main_window, | ||
| 1517 | &GMainWindow::SoftwareKeyboardShowInline, Qt::QueuedConnection); | ||
| 1518 | connect(this, &QtSoftwareKeyboard::MainWindowHideInlineKeyboard, &main_window, | ||
| 1519 | &GMainWindow::SoftwareKeyboardHideInline, Qt::QueuedConnection); | ||
| 1520 | connect(this, &QtSoftwareKeyboard::MainWindowInlineTextChanged, &main_window, | ||
| 1521 | &GMainWindow::SoftwareKeyboardInlineTextChanged, Qt::QueuedConnection); | ||
| 1522 | connect(this, &QtSoftwareKeyboard::MainWindowExitKeyboard, &main_window, | ||
| 1523 | &GMainWindow::SoftwareKeyboardExit, Qt::QueuedConnection); | ||
| 1524 | connect(&main_window, &GMainWindow::SoftwareKeyboardSubmitNormalText, this, | ||
| 1525 | &QtSoftwareKeyboard::SubmitNormalText, Qt::QueuedConnection); | ||
| 1526 | connect(&main_window, &GMainWindow::SoftwareKeyboardSubmitInlineText, this, | ||
| 1527 | &QtSoftwareKeyboard::SubmitInlineText, Qt::QueuedConnection); | ||
| 127 | } | 1528 | } |
| 128 | 1529 | ||
| 129 | QtSoftwareKeyboard::~QtSoftwareKeyboard() = default; | 1530 | QtSoftwareKeyboard::~QtSoftwareKeyboard() = default; |
| 130 | 1531 | ||
| 131 | void QtSoftwareKeyboard::RequestText(std::function<void(std::optional<std::u16string>)> out, | 1532 | void QtSoftwareKeyboard::InitializeKeyboard( |
| 132 | Core::Frontend::SoftwareKeyboardParameters parameters) const { | 1533 | bool is_inline, Core::Frontend::KeyboardInitializeParameters initialize_parameters, |
| 133 | text_output = std::move(out); | 1534 | std::function<void(Service::AM::Applets::SwkbdResult, std::u16string)> submit_normal_callback_, |
| 134 | emit MainWindowGetText(parameters); | 1535 | std::function<void(Service::AM::Applets::SwkbdReplyType, std::u16string, s32)> |
| 1536 | submit_inline_callback_) { | ||
| 1537 | if (is_inline) { | ||
| 1538 | submit_inline_callback = std::move(submit_inline_callback_); | ||
| 1539 | } else { | ||
| 1540 | submit_normal_callback = std::move(submit_normal_callback_); | ||
| 1541 | } | ||
| 1542 | |||
| 1543 | LOG_INFO(Service_AM, | ||
| 1544 | "\nKeyboardInitializeParameters:" | ||
| 1545 | "\nok_text={}" | ||
| 1546 | "\nheader_text={}" | ||
| 1547 | "\nsub_text={}" | ||
| 1548 | "\nguide_text={}" | ||
| 1549 | "\ninitial_text={}" | ||
| 1550 | "\nmax_text_length={}" | ||
| 1551 | "\nmin_text_length={}" | ||
| 1552 | "\ninitial_cursor_position={}" | ||
| 1553 | "\ntype={}" | ||
| 1554 | "\npassword_mode={}" | ||
| 1555 | "\ntext_draw_type={}" | ||
| 1556 | "\nkey_disable_flags={}" | ||
| 1557 | "\nuse_blur_background={}" | ||
| 1558 | "\nenable_backspace_button={}" | ||
| 1559 | "\nenable_return_button={}" | ||
| 1560 | "\ndisable_cancel_button={}", | ||
| 1561 | Common::UTF16ToUTF8(initialize_parameters.ok_text), | ||
| 1562 | Common::UTF16ToUTF8(initialize_parameters.header_text), | ||
| 1563 | Common::UTF16ToUTF8(initialize_parameters.sub_text), | ||
| 1564 | Common::UTF16ToUTF8(initialize_parameters.guide_text), | ||
| 1565 | Common::UTF16ToUTF8(initialize_parameters.initial_text), | ||
| 1566 | initialize_parameters.max_text_length, initialize_parameters.min_text_length, | ||
| 1567 | initialize_parameters.initial_cursor_position, initialize_parameters.type, | ||
| 1568 | initialize_parameters.password_mode, initialize_parameters.text_draw_type, | ||
| 1569 | initialize_parameters.key_disable_flags.raw, initialize_parameters.use_blur_background, | ||
| 1570 | initialize_parameters.enable_backspace_button, | ||
| 1571 | initialize_parameters.enable_return_button, | ||
| 1572 | initialize_parameters.disable_cancel_button); | ||
| 1573 | |||
| 1574 | emit MainWindowInitializeKeyboard(is_inline, std::move(initialize_parameters)); | ||
| 1575 | } | ||
| 1576 | |||
| 1577 | void QtSoftwareKeyboard::ShowNormalKeyboard() const { | ||
| 1578 | emit MainWindowShowNormalKeyboard(); | ||
| 1579 | } | ||
| 1580 | |||
| 1581 | void QtSoftwareKeyboard::ShowTextCheckDialog( | ||
| 1582 | Service::AM::Applets::SwkbdTextCheckResult text_check_result, | ||
| 1583 | std::u16string text_check_message) const { | ||
| 1584 | emit MainWindowShowTextCheckDialog(text_check_result, text_check_message); | ||
| 1585 | } | ||
| 1586 | |||
| 1587 | void QtSoftwareKeyboard::ShowInlineKeyboard( | ||
| 1588 | Core::Frontend::InlineAppearParameters appear_parameters) const { | ||
| 1589 | LOG_INFO(Service_AM, | ||
| 1590 | "\nInlineAppearParameters:" | ||
| 1591 | "\nmax_text_length={}" | ||
| 1592 | "\nmin_text_length={}" | ||
| 1593 | "\nkey_top_scale_x={}" | ||
| 1594 | "\nkey_top_scale_y={}" | ||
| 1595 | "\nkey_top_translate_x={}" | ||
| 1596 | "\nkey_top_translate_y={}" | ||
| 1597 | "\ntype={}" | ||
| 1598 | "\nkey_disable_flags={}" | ||
| 1599 | "\nkey_top_as_floating={}" | ||
| 1600 | "\nenable_backspace_button={}" | ||
| 1601 | "\nenable_return_button={}" | ||
| 1602 | "\ndisable_cancel_button={}", | ||
| 1603 | appear_parameters.max_text_length, appear_parameters.min_text_length, | ||
| 1604 | appear_parameters.key_top_scale_x, appear_parameters.key_top_scale_y, | ||
| 1605 | appear_parameters.key_top_translate_x, appear_parameters.key_top_translate_y, | ||
| 1606 | appear_parameters.type, appear_parameters.key_disable_flags.raw, | ||
| 1607 | appear_parameters.key_top_as_floating, appear_parameters.enable_backspace_button, | ||
| 1608 | appear_parameters.enable_return_button, appear_parameters.disable_cancel_button); | ||
| 1609 | |||
| 1610 | emit MainWindowShowInlineKeyboard(std::move(appear_parameters)); | ||
| 1611 | } | ||
| 1612 | |||
| 1613 | void QtSoftwareKeyboard::HideInlineKeyboard() const { | ||
| 1614 | emit MainWindowHideInlineKeyboard(); | ||
| 1615 | } | ||
| 1616 | |||
| 1617 | void QtSoftwareKeyboard::InlineTextChanged( | ||
| 1618 | Core::Frontend::InlineTextParameters text_parameters) const { | ||
| 1619 | LOG_INFO(Service_AM, | ||
| 1620 | "\nInlineTextParameters:" | ||
| 1621 | "\ninput_text={}" | ||
| 1622 | "\ncursor_position={}", | ||
| 1623 | Common::UTF16ToUTF8(text_parameters.input_text), text_parameters.cursor_position); | ||
| 1624 | |||
| 1625 | emit MainWindowInlineTextChanged(std::move(text_parameters)); | ||
| 135 | } | 1626 | } |
| 136 | 1627 | ||
| 137 | void QtSoftwareKeyboard::SendTextCheckDialog(std::u16string error_message, | 1628 | void QtSoftwareKeyboard::ExitKeyboard() const { |
| 138 | std::function<void()> finished_check_) const { | 1629 | emit MainWindowExitKeyboard(); |
| 139 | finished_check = std::move(finished_check_); | ||
| 140 | emit MainWindowTextCheckDialog(error_message); | ||
| 141 | } | 1630 | } |
| 142 | 1631 | ||
| 143 | void QtSoftwareKeyboard::MainWindowFinishedText(std::optional<std::u16string> text) { | 1632 | void QtSoftwareKeyboard::SubmitNormalText(Service::AM::Applets::SwkbdResult result, |
| 144 | // Acquire the HLE mutex | 1633 | std::u16string submitted_text) const { |
| 145 | std::lock_guard lock{HLE::g_hle_lock}; | 1634 | submit_normal_callback(result, submitted_text); |
| 146 | text_output(std::move(text)); | ||
| 147 | } | 1635 | } |
| 148 | 1636 | ||
| 149 | void QtSoftwareKeyboard::MainWindowFinishedCheckDialog() { | 1637 | void QtSoftwareKeyboard::SubmitInlineText(Service::AM::Applets::SwkbdReplyType reply_type, |
| 150 | // Acquire the HLE mutex | 1638 | std::u16string submitted_text, |
| 151 | std::lock_guard lock{HLE::g_hle_lock}; | 1639 | s32 cursor_position) const { |
| 152 | finished_check(); | 1640 | submit_inline_callback(reply_type, submitted_text, cursor_position); |
| 153 | } | 1641 | } |
diff --git a/src/yuzu/applets/software_keyboard.h b/src/yuzu/applets/software_keyboard.h index 9e1094cce..1a03c098c 100644 --- a/src/yuzu/applets/software_keyboard.h +++ b/src/yuzu/applets/software_keyboard.h | |||
| @@ -1,54 +1,228 @@ | |||
| 1 | // Copyright 2018 yuzu Emulator Project | 1 | // Copyright 2021 yuzu Emulator Project |
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <array> | ||
| 8 | #include <atomic> | ||
| 9 | #include <memory> | ||
| 10 | #include <thread> | ||
| 11 | |||
| 7 | #include <QDialog> | 12 | #include <QDialog> |
| 8 | #include <QValidator> | 13 | #include <QValidator> |
| 14 | |||
| 9 | #include "core/frontend/applets/software_keyboard.h" | 15 | #include "core/frontend/applets/software_keyboard.h" |
| 10 | 16 | ||
| 11 | class GMainWindow; | 17 | enum class HIDButton : u8; |
| 12 | class QDialogButtonBox; | ||
| 13 | class QLabel; | ||
| 14 | class QLineEdit; | ||
| 15 | class QVBoxLayout; | ||
| 16 | class QtSoftwareKeyboard; | ||
| 17 | 18 | ||
| 18 | class QtSoftwareKeyboardValidator final : public QValidator { | 19 | class InputInterpreter; |
| 19 | public: | ||
| 20 | explicit QtSoftwareKeyboardValidator(Core::Frontend::SoftwareKeyboardParameters parameters); | ||
| 21 | State validate(QString& input, int& pos) const override; | ||
| 22 | 20 | ||
| 23 | private: | 21 | namespace Core { |
| 24 | Core::Frontend::SoftwareKeyboardParameters parameters; | 22 | class System; |
| 25 | }; | 23 | } |
| 24 | |||
| 25 | namespace Ui { | ||
| 26 | class QtSoftwareKeyboardDialog; | ||
| 27 | } | ||
| 28 | |||
| 29 | class GMainWindow; | ||
| 26 | 30 | ||
| 27 | class QtSoftwareKeyboardDialog final : public QDialog { | 31 | class QtSoftwareKeyboardDialog final : public QDialog { |
| 28 | Q_OBJECT | 32 | Q_OBJECT |
| 29 | 33 | ||
| 30 | public: | 34 | public: |
| 31 | QtSoftwareKeyboardDialog(QWidget* parent, | 35 | QtSoftwareKeyboardDialog(QWidget* parent, Core::System& system_, bool is_inline_, |
| 32 | Core::Frontend::SoftwareKeyboardParameters parameters); | 36 | Core::Frontend::KeyboardInitializeParameters initialize_parameters_); |
| 33 | ~QtSoftwareKeyboardDialog() override; | 37 | ~QtSoftwareKeyboardDialog() override; |
| 34 | 38 | ||
| 35 | void accept() override; | 39 | void ShowNormalKeyboard(QPoint pos, QSize size); |
| 40 | |||
| 41 | void ShowTextCheckDialog(Service::AM::Applets::SwkbdTextCheckResult text_check_result, | ||
| 42 | std::u16string text_check_message); | ||
| 43 | |||
| 44 | void ShowInlineKeyboard(Core::Frontend::InlineAppearParameters appear_parameters, QPoint pos, | ||
| 45 | QSize size); | ||
| 46 | |||
| 47 | void HideInlineKeyboard(); | ||
| 48 | |||
| 49 | void InlineTextChanged(Core::Frontend::InlineTextParameters text_parameters); | ||
| 50 | |||
| 51 | void ExitKeyboard(); | ||
| 52 | |||
| 53 | signals: | ||
| 54 | void SubmitNormalText(Service::AM::Applets::SwkbdResult result, | ||
| 55 | std::u16string submitted_text) const; | ||
| 56 | |||
| 57 | void SubmitInlineText(Service::AM::Applets::SwkbdReplyType reply_type, | ||
| 58 | std::u16string submitted_text, s32 cursor_position) const; | ||
| 59 | |||
| 60 | public slots: | ||
| 61 | void open() override; | ||
| 36 | void reject() override; | 62 | void reject() override; |
| 37 | 63 | ||
| 38 | std::u16string GetText() const; | 64 | protected: |
| 65 | /// We override the keyPressEvent for inputting text into the inline software keyboard. | ||
| 66 | void keyPressEvent(QKeyEvent* event) override; | ||
| 39 | 67 | ||
| 40 | private: | 68 | private: |
| 41 | std::u16string text; | 69 | enum class Direction { |
| 70 | Left, | ||
| 71 | Up, | ||
| 72 | Right, | ||
| 73 | Down, | ||
| 74 | }; | ||
| 75 | |||
| 76 | enum class BottomOSKIndex { | ||
| 77 | LowerCase, | ||
| 78 | UpperCase, | ||
| 79 | NumberPad, | ||
| 80 | }; | ||
| 81 | |||
| 82 | /** | ||
| 83 | * Moves and resizes the window to a specified position and size. | ||
| 84 | * | ||
| 85 | * @param pos Top-left window position | ||
| 86 | * @param size Window size | ||
| 87 | */ | ||
| 88 | void MoveAndResizeWindow(QPoint pos, QSize size); | ||
| 89 | |||
| 90 | /** | ||
| 91 | * Rescales all keyboard elements to account for High DPI displays. | ||
| 92 | * | ||
| 93 | * @param width Window width | ||
| 94 | * @param height Window height | ||
| 95 | * @param dpi_scale Display scaling factor | ||
| 96 | */ | ||
| 97 | void RescaleKeyboardElements(float width, float height, float dpi_scale); | ||
| 98 | |||
| 99 | /// Sets the keyboard type based on initialize_parameters. | ||
| 100 | void SetKeyboardType(); | ||
| 101 | |||
| 102 | /// Sets the password mode based on initialize_parameters. | ||
| 103 | void SetPasswordMode(); | ||
| 104 | |||
| 105 | /// Sets the text draw type based on initialize_parameters. | ||
| 106 | void SetTextDrawType(); | ||
| 107 | |||
| 108 | /// Sets the controller image at the bottom left of the software keyboard. | ||
| 109 | void SetControllerImage(); | ||
| 110 | |||
| 111 | /// Disables buttons based on initialize_parameters. | ||
| 112 | void DisableKeyboardButtons(); | ||
| 113 | |||
| 114 | /// Changes whether the backspace or/and ok buttons should be enabled or disabled. | ||
| 115 | void SetBackspaceOkEnabled(); | ||
| 116 | |||
| 117 | /** | ||
| 118 | * Validates the input text sent in based on the parameters in initialize_parameters. | ||
| 119 | * | ||
| 120 | * @param input_text Input text | ||
| 121 | * | ||
| 122 | * @returns True if the input text is valid, false otherwise. | ||
| 123 | */ | ||
| 124 | bool ValidateInputText(const QString& input_text); | ||
| 125 | |||
| 126 | /// Switches between LowerCase and UpperCase (Shift and Caps Lock) | ||
| 127 | void ChangeBottomOSKIndex(); | ||
| 128 | |||
| 129 | /// Processes a keyboard button click from the UI as normal keyboard input. | ||
| 130 | void NormalKeyboardButtonClicked(QPushButton* button); | ||
| 131 | |||
| 132 | /// Processes a keyboard button click from the UI as inline keyboard input. | ||
| 133 | void InlineKeyboardButtonClicked(QPushButton* button); | ||
| 134 | |||
| 135 | /** | ||
| 136 | * Inserts a string of arbitrary length into the current_text at the current cursor position. | ||
| 137 | * This is only used for the inline software keyboard. | ||
| 138 | */ | ||
| 139 | void InlineTextInsertString(std::u16string_view string); | ||
| 42 | 140 | ||
| 43 | QDialogButtonBox* buttons; | 141 | /// Setup the mouse hover workaround for "focusing" buttons. This should only be called once. |
| 44 | QLabel* header_label; | 142 | void SetupMouseHover(); |
| 45 | QLabel* sub_label; | ||
| 46 | QLabel* guide_label; | ||
| 47 | QLabel* length_label; | ||
| 48 | QLineEdit* line_edit; | ||
| 49 | QVBoxLayout* layout; | ||
| 50 | 143 | ||
| 51 | Core::Frontend::SoftwareKeyboardParameters parameters; | 144 | /** |
| 145 | * Handles button presses and converts them into keyboard input. | ||
| 146 | * | ||
| 147 | * @tparam HIDButton The list of buttons that can be converted into keyboard input. | ||
| 148 | */ | ||
| 149 | template <HIDButton... T> | ||
| 150 | void HandleButtonPressedOnce(); | ||
| 151 | |||
| 152 | /** | ||
| 153 | * Handles button holds and converts them into keyboard input. | ||
| 154 | * | ||
| 155 | * @tparam HIDButton The list of buttons that can be converted into keyboard input. | ||
| 156 | */ | ||
| 157 | template <HIDButton... T> | ||
| 158 | void HandleButtonHold(); | ||
| 159 | |||
| 160 | /** | ||
| 161 | * Translates a button press to focus or click a keyboard button. | ||
| 162 | * | ||
| 163 | * @param button The button press to process. | ||
| 164 | */ | ||
| 165 | void TranslateButtonPress(HIDButton button); | ||
| 166 | |||
| 167 | /** | ||
| 168 | * Moves the focus of a button in a certain direction. | ||
| 169 | * | ||
| 170 | * @param direction The direction to move. | ||
| 171 | */ | ||
| 172 | void MoveButtonDirection(Direction direction); | ||
| 173 | |||
| 174 | /** | ||
| 175 | * Moves the text cursor in a certain direction. | ||
| 176 | * | ||
| 177 | * @param direction The direction to move. | ||
| 178 | */ | ||
| 179 | void MoveTextCursorDirection(Direction direction); | ||
| 180 | |||
| 181 | void StartInputThread(); | ||
| 182 | void StopInputThread(); | ||
| 183 | |||
| 184 | /// The thread where input is being polled and processed. | ||
| 185 | void InputThread(); | ||
| 186 | |||
| 187 | std::unique_ptr<Ui::QtSoftwareKeyboardDialog> ui; | ||
| 188 | |||
| 189 | Core::System& system; | ||
| 190 | |||
| 191 | // True if it is the inline software keyboard. | ||
| 192 | bool is_inline; | ||
| 193 | |||
| 194 | // Common software keyboard initialize parameters. | ||
| 195 | Core::Frontend::KeyboardInitializeParameters initialize_parameters; | ||
| 196 | |||
| 197 | // Used only by the inline software keyboard since the QLineEdit or QTextEdit is hidden. | ||
| 198 | std::u16string current_text; | ||
| 199 | s32 cursor_position{0}; | ||
| 200 | |||
| 201 | static constexpr std::size_t NUM_ROWS_NORMAL = 5; | ||
| 202 | static constexpr std::size_t NUM_COLUMNS_NORMAL = 12; | ||
| 203 | static constexpr std::size_t NUM_ROWS_NUMPAD = 4; | ||
| 204 | static constexpr std::size_t NUM_COLUMNS_NUMPAD = 4; | ||
| 205 | |||
| 206 | // Stores the normal keyboard layout. | ||
| 207 | std::array<std::array<std::array<QPushButton*, NUM_COLUMNS_NORMAL>, NUM_ROWS_NORMAL>, 2> | ||
| 208 | keyboard_buttons; | ||
| 209 | // Stores the numberpad keyboard layout. | ||
| 210 | std::array<std::array<QPushButton*, NUM_COLUMNS_NUMPAD>, NUM_ROWS_NUMPAD> numberpad_buttons; | ||
| 211 | |||
| 212 | // Contains a set of all buttons used in keyboard_buttons and numberpad_buttons. | ||
| 213 | std::array<QPushButton*, 110> all_buttons; | ||
| 214 | |||
| 215 | std::size_t row{0}; | ||
| 216 | std::size_t column{0}; | ||
| 217 | |||
| 218 | BottomOSKIndex bottom_osk_index{BottomOSKIndex::LowerCase}; | ||
| 219 | std::atomic<bool> caps_lock_enabled{false}; | ||
| 220 | |||
| 221 | std::unique_ptr<InputInterpreter> input_interpreter; | ||
| 222 | |||
| 223 | std::thread input_thread; | ||
| 224 | |||
| 225 | std::atomic<bool> input_thread_running{}; | ||
| 52 | }; | 226 | }; |
| 53 | 227 | ||
| 54 | class QtSoftwareKeyboard final : public QObject, public Core::Frontend::SoftwareKeyboardApplet { | 228 | class QtSoftwareKeyboard final : public QObject, public Core::Frontend::SoftwareKeyboardApplet { |
| @@ -58,19 +232,54 @@ public: | |||
| 58 | explicit QtSoftwareKeyboard(GMainWindow& parent); | 232 | explicit QtSoftwareKeyboard(GMainWindow& parent); |
| 59 | ~QtSoftwareKeyboard() override; | 233 | ~QtSoftwareKeyboard() override; |
| 60 | 234 | ||
| 61 | void RequestText(std::function<void(std::optional<std::u16string>)> out, | 235 | void InitializeKeyboard( |
| 62 | Core::Frontend::SoftwareKeyboardParameters parameters) const override; | 236 | bool is_inline, Core::Frontend::KeyboardInitializeParameters initialize_parameters, |
| 63 | void SendTextCheckDialog(std::u16string error_message, | 237 | std::function<void(Service::AM::Applets::SwkbdResult, std::u16string)> |
| 64 | std::function<void()> finished_check_) const override; | 238 | submit_normal_callback_, |
| 239 | std::function<void(Service::AM::Applets::SwkbdReplyType, std::u16string, s32)> | ||
| 240 | submit_inline_callback_) override; | ||
| 241 | |||
| 242 | void ShowNormalKeyboard() const override; | ||
| 243 | |||
| 244 | void ShowTextCheckDialog(Service::AM::Applets::SwkbdTextCheckResult text_check_result, | ||
| 245 | std::u16string text_check_message) const override; | ||
| 246 | |||
| 247 | void ShowInlineKeyboard( | ||
| 248 | Core::Frontend::InlineAppearParameters appear_parameters) const override; | ||
| 249 | |||
| 250 | void HideInlineKeyboard() const override; | ||
| 251 | |||
| 252 | void InlineTextChanged(Core::Frontend::InlineTextParameters text_parameters) const override; | ||
| 253 | |||
| 254 | void ExitKeyboard() const override; | ||
| 65 | 255 | ||
| 66 | signals: | 256 | signals: |
| 67 | void MainWindowGetText(Core::Frontend::SoftwareKeyboardParameters parameters) const; | 257 | void MainWindowInitializeKeyboard( |
| 68 | void MainWindowTextCheckDialog(std::u16string error_message) const; | 258 | bool is_inline, Core::Frontend::KeyboardInitializeParameters initialize_parameters) const; |
| 259 | |||
| 260 | void MainWindowShowNormalKeyboard() const; | ||
| 261 | |||
| 262 | void MainWindowShowTextCheckDialog(Service::AM::Applets::SwkbdTextCheckResult text_check_result, | ||
| 263 | std::u16string text_check_message) const; | ||
| 264 | |||
| 265 | void MainWindowShowInlineKeyboard( | ||
| 266 | Core::Frontend::InlineAppearParameters appear_parameters) const; | ||
| 267 | |||
| 268 | void MainWindowHideInlineKeyboard() const; | ||
| 269 | |||
| 270 | void MainWindowInlineTextChanged(Core::Frontend::InlineTextParameters text_parameters) const; | ||
| 271 | |||
| 272 | void MainWindowExitKeyboard() const; | ||
| 69 | 273 | ||
| 70 | private: | 274 | private: |
| 71 | void MainWindowFinishedText(std::optional<std::u16string> text); | 275 | void SubmitNormalText(Service::AM::Applets::SwkbdResult result, |
| 72 | void MainWindowFinishedCheckDialog(); | 276 | std::u16string submitted_text) const; |
| 277 | |||
| 278 | void SubmitInlineText(Service::AM::Applets::SwkbdReplyType reply_type, | ||
| 279 | std::u16string submitted_text, s32 cursor_position) const; | ||
| 73 | 280 | ||
| 74 | mutable std::function<void(std::optional<std::u16string>)> text_output; | 281 | mutable std::function<void(Service::AM::Applets::SwkbdResult, std::u16string)> |
| 75 | mutable std::function<void()> finished_check; | 282 | submit_normal_callback; |
| 283 | mutable std::function<void(Service::AM::Applets::SwkbdReplyType, std::u16string, s32)> | ||
| 284 | submit_inline_callback; | ||
| 76 | }; | 285 | }; |
diff --git a/src/yuzu/applets/software_keyboard.ui b/src/yuzu/applets/software_keyboard.ui new file mode 100644 index 000000000..b0a1fcde9 --- /dev/null +++ b/src/yuzu/applets/software_keyboard.ui | |||
| @@ -0,0 +1,3503 @@ | |||
| 1 | <?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | <ui version="4.0"> | ||
| 3 | <class>QtSoftwareKeyboardDialog</class> | ||
| 4 | <widget class="QDialog" name="QtSoftwareKeyboardDialog"> | ||
| 5 | <property name="geometry"> | ||
| 6 | <rect> | ||
| 7 | <x>0</x> | ||
| 8 | <y>0</y> | ||
| 9 | <width>1280</width> | ||
| 10 | <height>720</height> | ||
| 11 | </rect> | ||
| 12 | </property> | ||
| 13 | <property name="windowTitle"> | ||
| 14 | <string>Software Keyboard</string> | ||
| 15 | </property> | ||
| 16 | <property name="styleSheet"> | ||
| 17 | <string notr="true"/> | ||
| 18 | </property> | ||
| 19 | <layout class="QVBoxLayout" name="verticalLayout"> | ||
| 20 | <property name="spacing"> | ||
| 21 | <number>0</number> | ||
| 22 | </property> | ||
| 23 | <property name="leftMargin"> | ||
| 24 | <number>0</number> | ||
| 25 | </property> | ||
| 26 | <property name="topMargin"> | ||
| 27 | <number>0</number> | ||
| 28 | </property> | ||
| 29 | <property name="rightMargin"> | ||
| 30 | <number>0</number> | ||
| 31 | </property> | ||
| 32 | <property name="bottomMargin"> | ||
| 33 | <number>0</number> | ||
| 34 | </property> | ||
| 35 | <item> | ||
| 36 | <widget class="QWidget" name="mainOSK" native="true"> | ||
| 37 | <layout class="QVBoxLayout" name="verticalLayout_2" stretch="320,400"> | ||
| 38 | <property name="spacing"> | ||
| 39 | <number>0</number> | ||
| 40 | </property> | ||
| 41 | <property name="leftMargin"> | ||
| 42 | <number>0</number> | ||
| 43 | </property> | ||
| 44 | <property name="topMargin"> | ||
| 45 | <number>0</number> | ||
| 46 | </property> | ||
| 47 | <property name="rightMargin"> | ||
| 48 | <number>0</number> | ||
| 49 | </property> | ||
| 50 | <property name="bottomMargin"> | ||
| 51 | <number>0</number> | ||
| 52 | </property> | ||
| 53 | <item> | ||
| 54 | <widget class="QStackedWidget" name="topOSK"> | ||
| 55 | <property name="currentIndex"> | ||
| 56 | <number>0</number> | ||
| 57 | </property> | ||
| 58 | <widget class="QWidget" name="lineOSK"> | ||
| 59 | <property name="minimumSize"> | ||
| 60 | <size> | ||
| 61 | <width>0</width> | ||
| 62 | <height>100</height> | ||
| 63 | </size> | ||
| 64 | </property> | ||
| 65 | <layout class="QVBoxLayout" name="lineOSKVerticalLayout"> | ||
| 66 | <property name="spacing"> | ||
| 67 | <number>0</number> | ||
| 68 | </property> | ||
| 69 | <property name="leftMargin"> | ||
| 70 | <number>0</number> | ||
| 71 | </property> | ||
| 72 | <property name="topMargin"> | ||
| 73 | <number>0</number> | ||
| 74 | </property> | ||
| 75 | <property name="rightMargin"> | ||
| 76 | <number>0</number> | ||
| 77 | </property> | ||
| 78 | <property name="bottomMargin"> | ||
| 79 | <number>0</number> | ||
| 80 | </property> | ||
| 81 | <item> | ||
| 82 | <layout class="QGridLayout" name="gridLineOSK" rowstretch="40,50,23,48,65,94" columnstretch="130,1020,130"> | ||
| 83 | <property name="topMargin"> | ||
| 84 | <number>0</number> | ||
| 85 | </property> | ||
| 86 | <property name="spacing"> | ||
| 87 | <number>0</number> | ||
| 88 | </property> | ||
| 89 | <item row="4" column="2"> | ||
| 90 | <spacer name="horizontalSpacer_3"> | ||
| 91 | <property name="orientation"> | ||
| 92 | <enum>Qt::Horizontal</enum> | ||
| 93 | </property> | ||
| 94 | <property name="sizeHint" stdset="0"> | ||
| 95 | <size> | ||
| 96 | <width>40</width> | ||
| 97 | <height>20</height> | ||
| 98 | </size> | ||
| 99 | </property> | ||
| 100 | </spacer> | ||
| 101 | </item> | ||
| 102 | <item row="4" column="0"> | ||
| 103 | <spacer name="horizontalSpacer_4"> | ||
| 104 | <property name="orientation"> | ||
| 105 | <enum>Qt::Horizontal</enum> | ||
| 106 | </property> | ||
| 107 | <property name="sizeHint" stdset="0"> | ||
| 108 | <size> | ||
| 109 | <width>40</width> | ||
| 110 | <height>20</height> | ||
| 111 | </size> | ||
| 112 | </property> | ||
| 113 | </spacer> | ||
| 114 | </item> | ||
| 115 | <item row="5" column="1"> | ||
| 116 | <widget class="QWidget" name="charactersOSK" native="true"> | ||
| 117 | <layout class="QVBoxLayout" name="verticalLayout_5"> | ||
| 118 | <property name="spacing"> | ||
| 119 | <number>0</number> | ||
| 120 | </property> | ||
| 121 | <property name="leftMargin"> | ||
| 122 | <number>0</number> | ||
| 123 | </property> | ||
| 124 | <property name="topMargin"> | ||
| 125 | <number>0</number> | ||
| 126 | </property> | ||
| 127 | <property name="rightMargin"> | ||
| 128 | <number>0</number> | ||
| 129 | </property> | ||
| 130 | <property name="bottomMargin"> | ||
| 131 | <number>0</number> | ||
| 132 | </property> | ||
| 133 | <item alignment="Qt::AlignRight|Qt::AlignTop"> | ||
| 134 | <widget class="QLabel" name="label_characters"> | ||
| 135 | <property name="font"> | ||
| 136 | <font> | ||
| 137 | <pointsize>17</pointsize> | ||
| 138 | </font> | ||
| 139 | </property> | ||
| 140 | <property name="text"> | ||
| 141 | <string notr="true">0/32</string> | ||
| 142 | </property> | ||
| 143 | <property name="alignment"> | ||
| 144 | <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> | ||
| 145 | </property> | ||
| 146 | </widget> | ||
| 147 | </item> | ||
| 148 | </layout> | ||
| 149 | </widget> | ||
| 150 | </item> | ||
| 151 | <item row="3" column="1"> | ||
| 152 | <spacer name="verticalSpacer_2"> | ||
| 153 | <property name="orientation"> | ||
| 154 | <enum>Qt::Vertical</enum> | ||
| 155 | </property> | ||
| 156 | <property name="sizeHint" stdset="0"> | ||
| 157 | <size> | ||
| 158 | <width>20</width> | ||
| 159 | <height>40</height> | ||
| 160 | </size> | ||
| 161 | </property> | ||
| 162 | </spacer> | ||
| 163 | </item> | ||
| 164 | <item row="5" column="0"> | ||
| 165 | <spacer name="verticalSpacer_3"> | ||
| 166 | <property name="orientation"> | ||
| 167 | <enum>Qt::Vertical</enum> | ||
| 168 | </property> | ||
| 169 | <property name="sizeHint" stdset="0"> | ||
| 170 | <size> | ||
| 171 | <width>20</width> | ||
| 172 | <height>40</height> | ||
| 173 | </size> | ||
| 174 | </property> | ||
| 175 | </spacer> | ||
| 176 | </item> | ||
| 177 | <item row="4" column="1"> | ||
| 178 | <widget class="QWidget" name="inputOSK" native="true"> | ||
| 179 | <layout class="QVBoxLayout" name="verticalLayout_3"> | ||
| 180 | <item> | ||
| 181 | <widget class="QLineEdit" name="line_edit_osk"> | ||
| 182 | <property name="font"> | ||
| 183 | <font> | ||
| 184 | <pointsize>26</pointsize> | ||
| 185 | <weight>50</weight> | ||
| 186 | <bold>false</bold> | ||
| 187 | </font> | ||
| 188 | </property> | ||
| 189 | <property name="focusPolicy"> | ||
| 190 | <enum>Qt::StrongFocus</enum> | ||
| 191 | </property> | ||
| 192 | <property name="text"> | ||
| 193 | <string/> | ||
| 194 | </property> | ||
| 195 | <property name="maxLength"> | ||
| 196 | <number>32</number> | ||
| 197 | </property> | ||
| 198 | <property name="placeholderText"> | ||
| 199 | <string>Enter Text</string> | ||
| 200 | </property> | ||
| 201 | </widget> | ||
| 202 | </item> | ||
| 203 | </layout> | ||
| 204 | </widget> | ||
| 205 | </item> | ||
| 206 | <item row="0" column="1"> | ||
| 207 | <spacer name="verticalSpacer_4"> | ||
| 208 | <property name="orientation"> | ||
| 209 | <enum>Qt::Vertical</enum> | ||
| 210 | </property> | ||
| 211 | <property name="sizeHint" stdset="0"> | ||
| 212 | <size> | ||
| 213 | <width>20</width> | ||
| 214 | <height>40</height> | ||
| 215 | </size> | ||
| 216 | </property> | ||
| 217 | </spacer> | ||
| 218 | </item> | ||
| 219 | <item row="1" column="0" colspan="3"> | ||
| 220 | <widget class="QWidget" name="headerOSK" native="true"> | ||
| 221 | <layout class="QHBoxLayout" name="horizontalLayout_4" stretch="130,1020,130"> | ||
| 222 | <property name="spacing"> | ||
| 223 | <number>0</number> | ||
| 224 | </property> | ||
| 225 | <property name="leftMargin"> | ||
| 226 | <number>0</number> | ||
| 227 | </property> | ||
| 228 | <property name="topMargin"> | ||
| 229 | <number>0</number> | ||
| 230 | </property> | ||
| 231 | <property name="rightMargin"> | ||
| 232 | <number>0</number> | ||
| 233 | </property> | ||
| 234 | <property name="bottomMargin"> | ||
| 235 | <number>0</number> | ||
| 236 | </property> | ||
| 237 | <item> | ||
| 238 | <spacer name="horizontalSpacer_18"> | ||
| 239 | <property name="orientation"> | ||
| 240 | <enum>Qt::Horizontal</enum> | ||
| 241 | </property> | ||
| 242 | <property name="sizeHint" stdset="0"> | ||
| 243 | <size> | ||
| 244 | <width>127</width> | ||
| 245 | <height>20</height> | ||
| 246 | </size> | ||
| 247 | </property> | ||
| 248 | </spacer> | ||
| 249 | </item> | ||
| 250 | <item> | ||
| 251 | <widget class="QLabel" name="label_header"> | ||
| 252 | <property name="font"> | ||
| 253 | <font> | ||
| 254 | <pointsize>23</pointsize> | ||
| 255 | </font> | ||
| 256 | </property> | ||
| 257 | <property name="text"> | ||
| 258 | <string/> | ||
| 259 | </property> | ||
| 260 | </widget> | ||
| 261 | </item> | ||
| 262 | <item> | ||
| 263 | <spacer name="horizontalSpacer_19"> | ||
| 264 | <property name="orientation"> | ||
| 265 | <enum>Qt::Horizontal</enum> | ||
| 266 | </property> | ||
| 267 | <property name="sizeHint" stdset="0"> | ||
| 268 | <size> | ||
| 269 | <width>127</width> | ||
| 270 | <height>20</height> | ||
| 271 | </size> | ||
| 272 | </property> | ||
| 273 | </spacer> | ||
| 274 | </item> | ||
| 275 | </layout> | ||
| 276 | </widget> | ||
| 277 | </item> | ||
| 278 | <item row="2" column="0" colspan="3"> | ||
| 279 | <widget class="QWidget" name="subOSK" native="true"> | ||
| 280 | <layout class="QHBoxLayout" name="horizontalLayout_3" stretch="130,1020,130"> | ||
| 281 | <property name="spacing"> | ||
| 282 | <number>0</number> | ||
| 283 | </property> | ||
| 284 | <property name="leftMargin"> | ||
| 285 | <number>0</number> | ||
| 286 | </property> | ||
| 287 | <property name="topMargin"> | ||
| 288 | <number>0</number> | ||
| 289 | </property> | ||
| 290 | <property name="rightMargin"> | ||
| 291 | <number>0</number> | ||
| 292 | </property> | ||
| 293 | <property name="bottomMargin"> | ||
| 294 | <number>0</number> | ||
| 295 | </property> | ||
| 296 | <item> | ||
| 297 | <spacer name="horizontalSpacer_16"> | ||
| 298 | <property name="orientation"> | ||
| 299 | <enum>Qt::Horizontal</enum> | ||
| 300 | </property> | ||
| 301 | <property name="sizeHint" stdset="0"> | ||
| 302 | <size> | ||
| 303 | <width>127</width> | ||
| 304 | <height>20</height> | ||
| 305 | </size> | ||
| 306 | </property> | ||
| 307 | </spacer> | ||
| 308 | </item> | ||
| 309 | <item> | ||
| 310 | <widget class="QLabel" name="label_sub"> | ||
| 311 | <property name="font"> | ||
| 312 | <font> | ||
| 313 | <pointsize>17</pointsize> | ||
| 314 | </font> | ||
| 315 | </property> | ||
| 316 | <property name="text"> | ||
| 317 | <string/> | ||
| 318 | </property> | ||
| 319 | </widget> | ||
| 320 | </item> | ||
| 321 | <item> | ||
| 322 | <spacer name="horizontalSpacer_17"> | ||
| 323 | <property name="orientation"> | ||
| 324 | <enum>Qt::Horizontal</enum> | ||
| 325 | </property> | ||
| 326 | <property name="sizeHint" stdset="0"> | ||
| 327 | <size> | ||
| 328 | <width>127</width> | ||
| 329 | <height>20</height> | ||
| 330 | </size> | ||
| 331 | </property> | ||
| 332 | </spacer> | ||
| 333 | </item> | ||
| 334 | </layout> | ||
| 335 | </widget> | ||
| 336 | </item> | ||
| 337 | </layout> | ||
| 338 | </item> | ||
| 339 | </layout> | ||
| 340 | </widget> | ||
| 341 | <widget class="QWidget" name="boxOSK"> | ||
| 342 | <layout class="QVBoxLayout" name="boxOSKVerticalLayout"> | ||
| 343 | <property name="spacing"> | ||
| 344 | <number>0</number> | ||
| 345 | </property> | ||
| 346 | <property name="leftMargin"> | ||
| 347 | <number>0</number> | ||
| 348 | </property> | ||
| 349 | <property name="topMargin"> | ||
| 350 | <number>0</number> | ||
| 351 | </property> | ||
| 352 | <property name="rightMargin"> | ||
| 353 | <number>0</number> | ||
| 354 | </property> | ||
| 355 | <property name="bottomMargin"> | ||
| 356 | <number>0</number> | ||
| 357 | </property> | ||
| 358 | <item> | ||
| 359 | <layout class="QGridLayout" name="gridBoxOSK" rowstretch="61,178,81" columnstretch="120,1040,120"> | ||
| 360 | <property name="leftMargin"> | ||
| 361 | <number>0</number> | ||
| 362 | </property> | ||
| 363 | <property name="topMargin"> | ||
| 364 | <number>0</number> | ||
| 365 | </property> | ||
| 366 | <property name="rightMargin"> | ||
| 367 | <number>0</number> | ||
| 368 | </property> | ||
| 369 | <property name="bottomMargin"> | ||
| 370 | <number>0</number> | ||
| 371 | </property> | ||
| 372 | <property name="spacing"> | ||
| 373 | <number>0</number> | ||
| 374 | </property> | ||
| 375 | <item row="0" column="1"> | ||
| 376 | <spacer name="verticalSpacer_5"> | ||
| 377 | <property name="orientation"> | ||
| 378 | <enum>Qt::Vertical</enum> | ||
| 379 | </property> | ||
| 380 | <property name="sizeHint" stdset="0"> | ||
| 381 | <size> | ||
| 382 | <width>20</width> | ||
| 383 | <height>40</height> | ||
| 384 | </size> | ||
| 385 | </property> | ||
| 386 | </spacer> | ||
| 387 | </item> | ||
| 388 | <item row="1" column="0"> | ||
| 389 | <spacer name="horizontalSpacer_20"> | ||
| 390 | <property name="orientation"> | ||
| 391 | <enum>Qt::Horizontal</enum> | ||
| 392 | </property> | ||
| 393 | <property name="sizeHint" stdset="0"> | ||
| 394 | <size> | ||
| 395 | <width>40</width> | ||
| 396 | <height>20</height> | ||
| 397 | </size> | ||
| 398 | </property> | ||
| 399 | </spacer> | ||
| 400 | </item> | ||
| 401 | <item row="1" column="2"> | ||
| 402 | <spacer name="horizontalSpacer_21"> | ||
| 403 | <property name="orientation"> | ||
| 404 | <enum>Qt::Horizontal</enum> | ||
| 405 | </property> | ||
| 406 | <property name="sizeHint" stdset="0"> | ||
| 407 | <size> | ||
| 408 | <width>40</width> | ||
| 409 | <height>20</height> | ||
| 410 | </size> | ||
| 411 | </property> | ||
| 412 | </spacer> | ||
| 413 | </item> | ||
| 414 | <item row="2" column="1" alignment="Qt::AlignRight|Qt::AlignTop"> | ||
| 415 | <widget class="QWidget" name="charactersBoxOSK" native="true"> | ||
| 416 | <layout class="QVBoxLayout" name="verticalLayout_4"> | ||
| 417 | <property name="spacing"> | ||
| 418 | <number>0</number> | ||
| 419 | </property> | ||
| 420 | <property name="leftMargin"> | ||
| 421 | <number>0</number> | ||
| 422 | </property> | ||
| 423 | <property name="topMargin"> | ||
| 424 | <number>0</number> | ||
| 425 | </property> | ||
| 426 | <property name="rightMargin"> | ||
| 427 | <number>0</number> | ||
| 428 | </property> | ||
| 429 | <property name="bottomMargin"> | ||
| 430 | <number>0</number> | ||
| 431 | </property> | ||
| 432 | <item> | ||
| 433 | <widget class="QLabel" name="label_characters_box"> | ||
| 434 | <property name="enabled"> | ||
| 435 | <bool>true</bool> | ||
| 436 | </property> | ||
| 437 | <property name="font"> | ||
| 438 | <font> | ||
| 439 | <pointsize>17</pointsize> | ||
| 440 | </font> | ||
| 441 | </property> | ||
| 442 | <property name="text"> | ||
| 443 | <string notr="true">0/500</string> | ||
| 444 | </property> | ||
| 445 | </widget> | ||
| 446 | </item> | ||
| 447 | </layout> | ||
| 448 | </widget> | ||
| 449 | </item> | ||
| 450 | <item row="1" column="1"> | ||
| 451 | <widget class="QWidget" name="inputBoxOSK" native="true"> | ||
| 452 | <layout class="QVBoxLayout" name="verticalLayout_6"> | ||
| 453 | <property name="spacing"> | ||
| 454 | <number>0</number> | ||
| 455 | </property> | ||
| 456 | <property name="leftMargin"> | ||
| 457 | <number>14</number> | ||
| 458 | </property> | ||
| 459 | <property name="topMargin"> | ||
| 460 | <number>9</number> | ||
| 461 | </property> | ||
| 462 | <property name="rightMargin"> | ||
| 463 | <number>14</number> | ||
| 464 | </property> | ||
| 465 | <property name="bottomMargin"> | ||
| 466 | <number>9</number> | ||
| 467 | </property> | ||
| 468 | <item> | ||
| 469 | <widget class="QTextEdit" name="text_edit_osk"> | ||
| 470 | <property name="font"> | ||
| 471 | <font> | ||
| 472 | <pointsize>26</pointsize> | ||
| 473 | </font> | ||
| 474 | </property> | ||
| 475 | <property name="focusPolicy"> | ||
| 476 | <enum>Qt::StrongFocus</enum> | ||
| 477 | </property> | ||
| 478 | <property name="html"> | ||
| 479 | <string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> | ||
| 480 | <html><head><meta name="qrichtext" content="1" /><style type="text/css"> | ||
| 481 | p, li { white-space: pre-wrap; } | ||
| 482 | </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:26pt; font-weight:400; font-style:normal;"> | ||
| 483 | <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html></string> | ||
| 484 | </property> | ||
| 485 | </widget> | ||
| 486 | </item> | ||
| 487 | </layout> | ||
| 488 | </widget> | ||
| 489 | </item> | ||
| 490 | </layout> | ||
| 491 | </item> | ||
| 492 | </layout> | ||
| 493 | </widget> | ||
| 494 | </widget> | ||
| 495 | </item> | ||
| 496 | <item> | ||
| 497 | <widget class="QStackedWidget" name="bottomOSK"> | ||
| 498 | <property name="currentIndex"> | ||
| 499 | <number>0</number> | ||
| 500 | </property> | ||
| 501 | <widget class="QWidget" name="normalOSK"> | ||
| 502 | <layout class="QVBoxLayout" name="normalPageVerticalLayout"> | ||
| 503 | <property name="leftMargin"> | ||
| 504 | <number>0</number> | ||
| 505 | </property> | ||
| 506 | <property name="topMargin"> | ||
| 507 | <number>0</number> | ||
| 508 | </property> | ||
| 509 | <property name="rightMargin"> | ||
| 510 | <number>0</number> | ||
| 511 | </property> | ||
| 512 | <property name="bottomMargin"> | ||
| 513 | <number>0</number> | ||
| 514 | </property> | ||
| 515 | <item> | ||
| 516 | <layout class="QGridLayout" name="kbOSKnormal" rowstretch="15,63,63,63,63,63,70" columnstretch="54,96,96,96,96,96,96,96,96,96,96,96,116,54"> | ||
| 517 | <property name="spacing"> | ||
| 518 | <number>0</number> | ||
| 519 | </property> | ||
| 520 | <item row="6" column="1" colspan="12"> | ||
| 521 | <widget class="QWidget" name="legendOSK" native="true"> | ||
| 522 | <layout class="QHBoxLayout" name="horizontalLayout_2" stretch="70,525,25,12,22,41,25,12,22,41,25,12,47,37,29,12,69,37,29,12,56,8"> | ||
| 523 | <property name="spacing"> | ||
| 524 | <number>0</number> | ||
| 525 | </property> | ||
| 526 | <property name="leftMargin"> | ||
| 527 | <number>2</number> | ||
| 528 | </property> | ||
| 529 | <property name="topMargin"> | ||
| 530 | <number>0</number> | ||
| 531 | </property> | ||
| 532 | <property name="rightMargin"> | ||
| 533 | <number>0</number> | ||
| 534 | </property> | ||
| 535 | <property name="bottomMargin"> | ||
| 536 | <number>0</number> | ||
| 537 | </property> | ||
| 538 | <item> | ||
| 539 | <widget class="QWidget" name="icon_controller" native="true"> | ||
| 540 | <property name="styleSheet"> | ||
| 541 | <string notr="true"/> | ||
| 542 | </property> | ||
| 543 | </widget> | ||
| 544 | </item> | ||
| 545 | <item> | ||
| 546 | <spacer name="horizontalSpacer_5"> | ||
| 547 | <property name="orientation"> | ||
| 548 | <enum>Qt::Horizontal</enum> | ||
| 549 | </property> | ||
| 550 | <property name="sizeHint" stdset="0"> | ||
| 551 | <size> | ||
| 552 | <width>0</width> | ||
| 553 | <height>20</height> | ||
| 554 | </size> | ||
| 555 | </property> | ||
| 556 | </spacer> | ||
| 557 | </item> | ||
| 558 | <item> | ||
| 559 | <widget class="QWidget" name="button_L" native="true"/> | ||
| 560 | </item> | ||
| 561 | <item> | ||
| 562 | <spacer name="horizontalSpacer_14"> | ||
| 563 | <property name="orientation"> | ||
| 564 | <enum>Qt::Horizontal</enum> | ||
| 565 | </property> | ||
| 566 | <property name="sizeHint" stdset="0"> | ||
| 567 | <size> | ||
| 568 | <width>0</width> | ||
| 569 | <height>20</height> | ||
| 570 | </size> | ||
| 571 | </property> | ||
| 572 | </spacer> | ||
| 573 | </item> | ||
| 574 | <item> | ||
| 575 | <widget class="QWidget" name="arrow_left" native="true"/> | ||
| 576 | </item> | ||
| 577 | <item> | ||
| 578 | <spacer name="horizontalSpacer_13"> | ||
| 579 | <property name="orientation"> | ||
| 580 | <enum>Qt::Horizontal</enum> | ||
| 581 | </property> | ||
| 582 | <property name="sizeHint" stdset="0"> | ||
| 583 | <size> | ||
| 584 | <width>0</width> | ||
| 585 | <height>20</height> | ||
| 586 | </size> | ||
| 587 | </property> | ||
| 588 | </spacer> | ||
| 589 | </item> | ||
| 590 | <item> | ||
| 591 | <widget class="QWidget" name="button_R" native="true"/> | ||
| 592 | </item> | ||
| 593 | <item> | ||
| 594 | <spacer name="horizontalSpacer_12"> | ||
| 595 | <property name="orientation"> | ||
| 596 | <enum>Qt::Horizontal</enum> | ||
| 597 | </property> | ||
| 598 | <property name="sizeHint" stdset="0"> | ||
| 599 | <size> | ||
| 600 | <width>0</width> | ||
| 601 | <height>20</height> | ||
| 602 | </size> | ||
| 603 | </property> | ||
| 604 | </spacer> | ||
| 605 | </item> | ||
| 606 | <item> | ||
| 607 | <widget class="QWidget" name="arrow_right" native="true"/> | ||
| 608 | </item> | ||
| 609 | <item> | ||
| 610 | <spacer name="horizontalSpacer_11"> | ||
| 611 | <property name="orientation"> | ||
| 612 | <enum>Qt::Horizontal</enum> | ||
| 613 | </property> | ||
| 614 | <property name="sizeHint" stdset="0"> | ||
| 615 | <size> | ||
| 616 | <width>0</width> | ||
| 617 | <height>20</height> | ||
| 618 | </size> | ||
| 619 | </property> | ||
| 620 | </spacer> | ||
| 621 | </item> | ||
| 622 | <item> | ||
| 623 | <widget class="QWidget" name="button_press_stick" native="true"/> | ||
| 624 | </item> | ||
| 625 | <item> | ||
| 626 | <spacer name="horizontalSpacer_10"> | ||
| 627 | <property name="orientation"> | ||
| 628 | <enum>Qt::Horizontal</enum> | ||
| 629 | </property> | ||
| 630 | <property name="sizeHint" stdset="0"> | ||
| 631 | <size> | ||
| 632 | <width>0</width> | ||
| 633 | <height>20</height> | ||
| 634 | </size> | ||
| 635 | </property> | ||
| 636 | </spacer> | ||
| 637 | </item> | ||
| 638 | <item> | ||
| 639 | <widget class="QLabel" name="label_shift"> | ||
| 640 | <property name="font"> | ||
| 641 | <font> | ||
| 642 | <pointsize>18</pointsize> | ||
| 643 | </font> | ||
| 644 | </property> | ||
| 645 | <property name="text"> | ||
| 646 | <string notr="true">Shift</string> | ||
| 647 | </property> | ||
| 648 | </widget> | ||
| 649 | </item> | ||
| 650 | <item> | ||
| 651 | <spacer name="horizontalSpacer_15"> | ||
| 652 | <property name="orientation"> | ||
| 653 | <enum>Qt::Horizontal</enum> | ||
| 654 | </property> | ||
| 655 | <property name="sizeHint" stdset="0"> | ||
| 656 | <size> | ||
| 657 | <width>0</width> | ||
| 658 | <height>20</height> | ||
| 659 | </size> | ||
| 660 | </property> | ||
| 661 | </spacer> | ||
| 662 | </item> | ||
| 663 | <item> | ||
| 664 | <widget class="QWidget" name="button_X" native="true"/> | ||
| 665 | </item> | ||
| 666 | <item> | ||
| 667 | <spacer name="horizontalSpacer_9"> | ||
| 668 | <property name="orientation"> | ||
| 669 | <enum>Qt::Horizontal</enum> | ||
| 670 | </property> | ||
| 671 | <property name="sizeHint" stdset="0"> | ||
| 672 | <size> | ||
| 673 | <width>0</width> | ||
| 674 | <height>20</height> | ||
| 675 | </size> | ||
| 676 | </property> | ||
| 677 | </spacer> | ||
| 678 | </item> | ||
| 679 | <item> | ||
| 680 | <widget class="QLabel" name="label_cancel"> | ||
| 681 | <property name="font"> | ||
| 682 | <font> | ||
| 683 | <pointsize>18</pointsize> | ||
| 684 | </font> | ||
| 685 | </property> | ||
| 686 | <property name="text"> | ||
| 687 | <string notr="true">Cancel</string> | ||
| 688 | </property> | ||
| 689 | </widget> | ||
| 690 | </item> | ||
| 691 | <item> | ||
| 692 | <spacer name="horizontalSpacer_8"> | ||
| 693 | <property name="orientation"> | ||
| 694 | <enum>Qt::Horizontal</enum> | ||
| 695 | </property> | ||
| 696 | <property name="sizeHint" stdset="0"> | ||
| 697 | <size> | ||
| 698 | <width>0</width> | ||
| 699 | <height>20</height> | ||
| 700 | </size> | ||
| 701 | </property> | ||
| 702 | </spacer> | ||
| 703 | </item> | ||
| 704 | <item> | ||
| 705 | <widget class="QWidget" name="button_A" native="true"/> | ||
| 706 | </item> | ||
| 707 | <item> | ||
| 708 | <spacer name="horizontalSpacer_7"> | ||
| 709 | <property name="orientation"> | ||
| 710 | <enum>Qt::Horizontal</enum> | ||
| 711 | </property> | ||
| 712 | <property name="sizeHint" stdset="0"> | ||
| 713 | <size> | ||
| 714 | <width>0</width> | ||
| 715 | <height>20</height> | ||
| 716 | </size> | ||
| 717 | </property> | ||
| 718 | </spacer> | ||
| 719 | </item> | ||
| 720 | <item> | ||
| 721 | <widget class="QLabel" name="label_enter"> | ||
| 722 | <property name="font"> | ||
| 723 | <font> | ||
| 724 | <pointsize>18</pointsize> | ||
| 725 | </font> | ||
| 726 | </property> | ||
| 727 | <property name="text"> | ||
| 728 | <string notr="true">Enter</string> | ||
| 729 | </property> | ||
| 730 | </widget> | ||
| 731 | </item> | ||
| 732 | <item> | ||
| 733 | <spacer name="horizontalSpacer_6"> | ||
| 734 | <property name="orientation"> | ||
| 735 | <enum>Qt::Horizontal</enum> | ||
| 736 | </property> | ||
| 737 | <property name="sizeHint" stdset="0"> | ||
| 738 | <size> | ||
| 739 | <width>0</width> | ||
| 740 | <height>20</height> | ||
| 741 | </size> | ||
| 742 | </property> | ||
| 743 | </spacer> | ||
| 744 | </item> | ||
| 745 | </layout> | ||
| 746 | </widget> | ||
| 747 | </item> | ||
| 748 | <item row="1" column="11"> | ||
| 749 | <widget class="QPushButton" name="button_minus"> | ||
| 750 | <property name="sizePolicy"> | ||
| 751 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 752 | <horstretch>1</horstretch> | ||
| 753 | <verstretch>1</verstretch> | ||
| 754 | </sizepolicy> | ||
| 755 | </property> | ||
| 756 | <property name="font"> | ||
| 757 | <font> | ||
| 758 | <pointsize>28</pointsize> | ||
| 759 | </font> | ||
| 760 | </property> | ||
| 761 | <property name="text"> | ||
| 762 | <string notr="true">-</string> | ||
| 763 | </property> | ||
| 764 | </widget> | ||
| 765 | </item> | ||
| 766 | <item row="3" column="11"> | ||
| 767 | <widget class="QPushButton" name="button_apostrophe"> | ||
| 768 | <property name="sizePolicy"> | ||
| 769 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 770 | <horstretch>1</horstretch> | ||
| 771 | <verstretch>1</verstretch> | ||
| 772 | </sizepolicy> | ||
| 773 | </property> | ||
| 774 | <property name="font"> | ||
| 775 | <font> | ||
| 776 | <pointsize>28</pointsize> | ||
| 777 | </font> | ||
| 778 | </property> | ||
| 779 | <property name="text"> | ||
| 780 | <string notr="true">'</string> | ||
| 781 | </property> | ||
| 782 | </widget> | ||
| 783 | </item> | ||
| 784 | <item row="2" column="11"> | ||
| 785 | <widget class="QPushButton" name="button_slash"> | ||
| 786 | <property name="sizePolicy"> | ||
| 787 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 788 | <horstretch>1</horstretch> | ||
| 789 | <verstretch>1</verstretch> | ||
| 790 | </sizepolicy> | ||
| 791 | </property> | ||
| 792 | <property name="font"> | ||
| 793 | <font> | ||
| 794 | <pointsize>28</pointsize> | ||
| 795 | </font> | ||
| 796 | </property> | ||
| 797 | <property name="text"> | ||
| 798 | <string notr="true">/</string> | ||
| 799 | </property> | ||
| 800 | </widget> | ||
| 801 | </item> | ||
| 802 | <item row="4" column="11"> | ||
| 803 | <widget class="QPushButton" name="button_exclamation"> | ||
| 804 | <property name="sizePolicy"> | ||
| 805 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 806 | <horstretch>1</horstretch> | ||
| 807 | <verstretch>1</verstretch> | ||
| 808 | </sizepolicy> | ||
| 809 | </property> | ||
| 810 | <property name="font"> | ||
| 811 | <font> | ||
| 812 | <pointsize>28</pointsize> | ||
| 813 | </font> | ||
| 814 | </property> | ||
| 815 | <property name="text"> | ||
| 816 | <string notr="true">!</string> | ||
| 817 | </property> | ||
| 818 | </widget> | ||
| 819 | </item> | ||
| 820 | <item row="1" column="7"> | ||
| 821 | <widget class="QPushButton" name="button_7"> | ||
| 822 | <property name="sizePolicy"> | ||
| 823 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 824 | <horstretch>1</horstretch> | ||
| 825 | <verstretch>1</verstretch> | ||
| 826 | </sizepolicy> | ||
| 827 | </property> | ||
| 828 | <property name="font"> | ||
| 829 | <font> | ||
| 830 | <pointsize>28</pointsize> | ||
| 831 | </font> | ||
| 832 | </property> | ||
| 833 | <property name="text"> | ||
| 834 | <string notr="true">7</string> | ||
| 835 | </property> | ||
| 836 | </widget> | ||
| 837 | </item> | ||
| 838 | <item row="1" column="8"> | ||
| 839 | <widget class="QPushButton" name="button_8"> | ||
| 840 | <property name="sizePolicy"> | ||
| 841 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 842 | <horstretch>1</horstretch> | ||
| 843 | <verstretch>1</verstretch> | ||
| 844 | </sizepolicy> | ||
| 845 | </property> | ||
| 846 | <property name="font"> | ||
| 847 | <font> | ||
| 848 | <pointsize>28</pointsize> | ||
| 849 | </font> | ||
| 850 | </property> | ||
| 851 | <property name="text"> | ||
| 852 | <string notr="true">8</string> | ||
| 853 | </property> | ||
| 854 | </widget> | ||
| 855 | </item> | ||
| 856 | <item row="1" column="10"> | ||
| 857 | <widget class="QPushButton" name="button_0"> | ||
| 858 | <property name="sizePolicy"> | ||
| 859 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 860 | <horstretch>1</horstretch> | ||
| 861 | <verstretch>1</verstretch> | ||
| 862 | </sizepolicy> | ||
| 863 | </property> | ||
| 864 | <property name="font"> | ||
| 865 | <font> | ||
| 866 | <pointsize>28</pointsize> | ||
| 867 | </font> | ||
| 868 | </property> | ||
| 869 | <property name="text"> | ||
| 870 | <string notr="true">0</string> | ||
| 871 | </property> | ||
| 872 | </widget> | ||
| 873 | </item> | ||
| 874 | <item row="1" column="9"> | ||
| 875 | <widget class="QPushButton" name="button_9"> | ||
| 876 | <property name="sizePolicy"> | ||
| 877 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 878 | <horstretch>1</horstretch> | ||
| 879 | <verstretch>1</verstretch> | ||
| 880 | </sizepolicy> | ||
| 881 | </property> | ||
| 882 | <property name="font"> | ||
| 883 | <font> | ||
| 884 | <pointsize>28</pointsize> | ||
| 885 | </font> | ||
| 886 | </property> | ||
| 887 | <property name="text"> | ||
| 888 | <string notr="true">9</string> | ||
| 889 | </property> | ||
| 890 | </widget> | ||
| 891 | </item> | ||
| 892 | <item row="2" column="2"> | ||
| 893 | <widget class="QPushButton" name="button_w"> | ||
| 894 | <property name="sizePolicy"> | ||
| 895 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 896 | <horstretch>1</horstretch> | ||
| 897 | <verstretch>1</verstretch> | ||
| 898 | </sizepolicy> | ||
| 899 | </property> | ||
| 900 | <property name="font"> | ||
| 901 | <font> | ||
| 902 | <pointsize>28</pointsize> | ||
| 903 | </font> | ||
| 904 | </property> | ||
| 905 | <property name="text"> | ||
| 906 | <string notr="true">w</string> | ||
| 907 | </property> | ||
| 908 | </widget> | ||
| 909 | </item> | ||
| 910 | <item row="2" column="4"> | ||
| 911 | <widget class="QPushButton" name="button_r"> | ||
| 912 | <property name="sizePolicy"> | ||
| 913 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 914 | <horstretch>1</horstretch> | ||
| 915 | <verstretch>1</verstretch> | ||
| 916 | </sizepolicy> | ||
| 917 | </property> | ||
| 918 | <property name="font"> | ||
| 919 | <font> | ||
| 920 | <pointsize>28</pointsize> | ||
| 921 | </font> | ||
| 922 | </property> | ||
| 923 | <property name="text"> | ||
| 924 | <string notr="true">r</string> | ||
| 925 | </property> | ||
| 926 | </widget> | ||
| 927 | </item> | ||
| 928 | <item row="2" column="3"> | ||
| 929 | <widget class="QPushButton" name="button_e"> | ||
| 930 | <property name="sizePolicy"> | ||
| 931 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 932 | <horstretch>1</horstretch> | ||
| 933 | <verstretch>1</verstretch> | ||
| 934 | </sizepolicy> | ||
| 935 | </property> | ||
| 936 | <property name="font"> | ||
| 937 | <font> | ||
| 938 | <pointsize>28</pointsize> | ||
| 939 | </font> | ||
| 940 | </property> | ||
| 941 | <property name="text"> | ||
| 942 | <string notr="true">e</string> | ||
| 943 | </property> | ||
| 944 | </widget> | ||
| 945 | </item> | ||
| 946 | <item row="2" column="1"> | ||
| 947 | <widget class="QPushButton" name="button_q"> | ||
| 948 | <property name="sizePolicy"> | ||
| 949 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 950 | <horstretch>1</horstretch> | ||
| 951 | <verstretch>1</verstretch> | ||
| 952 | </sizepolicy> | ||
| 953 | </property> | ||
| 954 | <property name="font"> | ||
| 955 | <font> | ||
| 956 | <pointsize>28</pointsize> | ||
| 957 | </font> | ||
| 958 | </property> | ||
| 959 | <property name="text"> | ||
| 960 | <string notr="true">q</string> | ||
| 961 | </property> | ||
| 962 | </widget> | ||
| 963 | </item> | ||
| 964 | <item row="2" column="7"> | ||
| 965 | <widget class="QPushButton" name="button_u"> | ||
| 966 | <property name="sizePolicy"> | ||
| 967 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 968 | <horstretch>1</horstretch> | ||
| 969 | <verstretch>1</verstretch> | ||
| 970 | </sizepolicy> | ||
| 971 | </property> | ||
| 972 | <property name="font"> | ||
| 973 | <font> | ||
| 974 | <pointsize>28</pointsize> | ||
| 975 | </font> | ||
| 976 | </property> | ||
| 977 | <property name="text"> | ||
| 978 | <string notr="true">u</string> | ||
| 979 | </property> | ||
| 980 | </widget> | ||
| 981 | </item> | ||
| 982 | <item row="2" column="6"> | ||
| 983 | <widget class="QPushButton" name="button_y"> | ||
| 984 | <property name="sizePolicy"> | ||
| 985 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 986 | <horstretch>1</horstretch> | ||
| 987 | <verstretch>1</verstretch> | ||
| 988 | </sizepolicy> | ||
| 989 | </property> | ||
| 990 | <property name="font"> | ||
| 991 | <font> | ||
| 992 | <pointsize>28</pointsize> | ||
| 993 | </font> | ||
| 994 | </property> | ||
| 995 | <property name="text"> | ||
| 996 | <string notr="true">y</string> | ||
| 997 | </property> | ||
| 998 | </widget> | ||
| 999 | </item> | ||
| 1000 | <item row="2" column="5"> | ||
| 1001 | <widget class="QPushButton" name="button_t"> | ||
| 1002 | <property name="sizePolicy"> | ||
| 1003 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 1004 | <horstretch>1</horstretch> | ||
| 1005 | <verstretch>1</verstretch> | ||
| 1006 | </sizepolicy> | ||
| 1007 | </property> | ||
| 1008 | <property name="font"> | ||
| 1009 | <font> | ||
| 1010 | <pointsize>28</pointsize> | ||
| 1011 | </font> | ||
| 1012 | </property> | ||
| 1013 | <property name="text"> | ||
| 1014 | <string notr="true">t</string> | ||
| 1015 | </property> | ||
| 1016 | </widget> | ||
| 1017 | </item> | ||
| 1018 | <item row="2" column="9"> | ||
| 1019 | <widget class="QPushButton" name="button_o"> | ||
| 1020 | <property name="sizePolicy"> | ||
| 1021 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 1022 | <horstretch>1</horstretch> | ||
| 1023 | <verstretch>1</verstretch> | ||
| 1024 | </sizepolicy> | ||
| 1025 | </property> | ||
| 1026 | <property name="font"> | ||
| 1027 | <font> | ||
| 1028 | <pointsize>28</pointsize> | ||
| 1029 | </font> | ||
| 1030 | </property> | ||
| 1031 | <property name="text"> | ||
| 1032 | <string notr="true">o</string> | ||
| 1033 | </property> | ||
| 1034 | </widget> | ||
| 1035 | </item> | ||
| 1036 | <item row="2" column="10"> | ||
| 1037 | <widget class="QPushButton" name="button_p"> | ||
| 1038 | <property name="sizePolicy"> | ||
| 1039 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 1040 | <horstretch>1</horstretch> | ||
| 1041 | <verstretch>1</verstretch> | ||
| 1042 | </sizepolicy> | ||
| 1043 | </property> | ||
| 1044 | <property name="font"> | ||
| 1045 | <font> | ||
| 1046 | <pointsize>28</pointsize> | ||
| 1047 | </font> | ||
| 1048 | </property> | ||
| 1049 | <property name="text"> | ||
| 1050 | <string notr="true">p</string> | ||
| 1051 | </property> | ||
| 1052 | </widget> | ||
| 1053 | </item> | ||
| 1054 | <item row="2" column="8"> | ||
| 1055 | <widget class="QPushButton" name="button_i"> | ||
| 1056 | <property name="sizePolicy"> | ||
| 1057 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 1058 | <horstretch>1</horstretch> | ||
| 1059 | <verstretch>1</verstretch> | ||
| 1060 | </sizepolicy> | ||
| 1061 | </property> | ||
| 1062 | <property name="font"> | ||
| 1063 | <font> | ||
| 1064 | <pointsize>28</pointsize> | ||
| 1065 | </font> | ||
| 1066 | </property> | ||
| 1067 | <property name="text"> | ||
| 1068 | <string notr="true">i</string> | ||
| 1069 | </property> | ||
| 1070 | </widget> | ||
| 1071 | </item> | ||
| 1072 | <item row="3" column="1"> | ||
| 1073 | <widget class="QPushButton" name="button_a"> | ||
| 1074 | <property name="sizePolicy"> | ||
| 1075 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 1076 | <horstretch>1</horstretch> | ||
| 1077 | <verstretch>1</verstretch> | ||
| 1078 | </sizepolicy> | ||
| 1079 | </property> | ||
| 1080 | <property name="font"> | ||
| 1081 | <font> | ||
| 1082 | <pointsize>28</pointsize> | ||
| 1083 | </font> | ||
| 1084 | </property> | ||
| 1085 | <property name="text"> | ||
| 1086 | <string notr="true">a</string> | ||
| 1087 | </property> | ||
| 1088 | </widget> | ||
| 1089 | </item> | ||
| 1090 | <item row="3" column="2"> | ||
| 1091 | <widget class="QPushButton" name="button_s"> | ||
| 1092 | <property name="sizePolicy"> | ||
| 1093 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 1094 | <horstretch>1</horstretch> | ||
| 1095 | <verstretch>1</verstretch> | ||
| 1096 | </sizepolicy> | ||
| 1097 | </property> | ||
| 1098 | <property name="font"> | ||
| 1099 | <font> | ||
| 1100 | <pointsize>28</pointsize> | ||
| 1101 | </font> | ||
| 1102 | </property> | ||
| 1103 | <property name="text"> | ||
| 1104 | <string notr="true">s</string> | ||
| 1105 | </property> | ||
| 1106 | </widget> | ||
| 1107 | </item> | ||
| 1108 | <item row="3" column="3"> | ||
| 1109 | <widget class="QPushButton" name="button_d"> | ||
| 1110 | <property name="sizePolicy"> | ||
| 1111 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 1112 | <horstretch>1</horstretch> | ||
| 1113 | <verstretch>1</verstretch> | ||
| 1114 | </sizepolicy> | ||
| 1115 | </property> | ||
| 1116 | <property name="font"> | ||
| 1117 | <font> | ||
| 1118 | <pointsize>28</pointsize> | ||
| 1119 | </font> | ||
| 1120 | </property> | ||
| 1121 | <property name="text"> | ||
| 1122 | <string notr="true">d</string> | ||
| 1123 | </property> | ||
| 1124 | </widget> | ||
| 1125 | </item> | ||
| 1126 | <item row="3" column="4"> | ||
| 1127 | <widget class="QPushButton" name="button_f"> | ||
| 1128 | <property name="sizePolicy"> | ||
| 1129 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 1130 | <horstretch>1</horstretch> | ||
| 1131 | <verstretch>1</verstretch> | ||
| 1132 | </sizepolicy> | ||
| 1133 | </property> | ||
| 1134 | <property name="font"> | ||
| 1135 | <font> | ||
| 1136 | <pointsize>28</pointsize> | ||
| 1137 | </font> | ||
| 1138 | </property> | ||
| 1139 | <property name="text"> | ||
| 1140 | <string notr="true">f</string> | ||
| 1141 | </property> | ||
| 1142 | </widget> | ||
| 1143 | </item> | ||
| 1144 | <item row="3" column="6"> | ||
| 1145 | <widget class="QPushButton" name="button_h"> | ||
| 1146 | <property name="sizePolicy"> | ||
| 1147 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 1148 | <horstretch>1</horstretch> | ||
| 1149 | <verstretch>1</verstretch> | ||
| 1150 | </sizepolicy> | ||
| 1151 | </property> | ||
| 1152 | <property name="font"> | ||
| 1153 | <font> | ||
| 1154 | <pointsize>28</pointsize> | ||
| 1155 | </font> | ||
| 1156 | </property> | ||
| 1157 | <property name="text"> | ||
| 1158 | <string notr="true">h</string> | ||
| 1159 | </property> | ||
| 1160 | </widget> | ||
| 1161 | </item> | ||
| 1162 | <item row="3" column="7"> | ||
| 1163 | <widget class="QPushButton" name="button_j"> | ||
| 1164 | <property name="sizePolicy"> | ||
| 1165 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 1166 | <horstretch>1</horstretch> | ||
| 1167 | <verstretch>1</verstretch> | ||
| 1168 | </sizepolicy> | ||
| 1169 | </property> | ||
| 1170 | <property name="font"> | ||
| 1171 | <font> | ||
| 1172 | <pointsize>28</pointsize> | ||
| 1173 | </font> | ||
| 1174 | </property> | ||
| 1175 | <property name="text"> | ||
| 1176 | <string notr="true">j</string> | ||
| 1177 | </property> | ||
| 1178 | </widget> | ||
| 1179 | </item> | ||
| 1180 | <item row="3" column="5"> | ||
| 1181 | <widget class="QPushButton" name="button_g"> | ||
| 1182 | <property name="sizePolicy"> | ||
| 1183 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 1184 | <horstretch>1</horstretch> | ||
| 1185 | <verstretch>1</verstretch> | ||
| 1186 | </sizepolicy> | ||
| 1187 | </property> | ||
| 1188 | <property name="font"> | ||
| 1189 | <font> | ||
| 1190 | <pointsize>28</pointsize> | ||
| 1191 | </font> | ||
| 1192 | </property> | ||
| 1193 | <property name="text"> | ||
| 1194 | <string notr="true">g</string> | ||
| 1195 | </property> | ||
| 1196 | </widget> | ||
| 1197 | </item> | ||
| 1198 | <item row="3" column="8"> | ||
| 1199 | <widget class="QPushButton" name="button_k"> | ||
| 1200 | <property name="sizePolicy"> | ||
| 1201 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 1202 | <horstretch>1</horstretch> | ||
| 1203 | <verstretch>1</verstretch> | ||
| 1204 | </sizepolicy> | ||
| 1205 | </property> | ||
| 1206 | <property name="font"> | ||
| 1207 | <font> | ||
| 1208 | <pointsize>28</pointsize> | ||
| 1209 | </font> | ||
| 1210 | </property> | ||
| 1211 | <property name="text"> | ||
| 1212 | <string notr="true">k</string> | ||
| 1213 | </property> | ||
| 1214 | </widget> | ||
| 1215 | </item> | ||
| 1216 | <item row="3" column="9"> | ||
| 1217 | <widget class="QPushButton" name="button_l"> | ||
| 1218 | <property name="sizePolicy"> | ||
| 1219 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 1220 | <horstretch>1</horstretch> | ||
| 1221 | <verstretch>1</verstretch> | ||
| 1222 | </sizepolicy> | ||
| 1223 | </property> | ||
| 1224 | <property name="font"> | ||
| 1225 | <font> | ||
| 1226 | <pointsize>28</pointsize> | ||
| 1227 | </font> | ||
| 1228 | </property> | ||
| 1229 | <property name="text"> | ||
| 1230 | <string notr="true">l</string> | ||
| 1231 | </property> | ||
| 1232 | </widget> | ||
| 1233 | </item> | ||
| 1234 | <item row="3" column="10"> | ||
| 1235 | <widget class="QPushButton" name="button_colon"> | ||
| 1236 | <property name="sizePolicy"> | ||
| 1237 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 1238 | <horstretch>1</horstretch> | ||
| 1239 | <verstretch>1</verstretch> | ||
| 1240 | </sizepolicy> | ||
| 1241 | </property> | ||
| 1242 | <property name="font"> | ||
| 1243 | <font> | ||
| 1244 | <pointsize>28</pointsize> | ||
| 1245 | </font> | ||
| 1246 | </property> | ||
| 1247 | <property name="text"> | ||
| 1248 | <string notr="true">:</string> | ||
| 1249 | </property> | ||
| 1250 | </widget> | ||
| 1251 | </item> | ||
| 1252 | <item row="2" column="12" rowspan="2"> | ||
| 1253 | <widget class="QPushButton" name="button_return"> | ||
| 1254 | <property name="sizePolicy"> | ||
| 1255 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 1256 | <horstretch>1</horstretch> | ||
| 1257 | <verstretch>1</verstretch> | ||
| 1258 | </sizepolicy> | ||
| 1259 | </property> | ||
| 1260 | <property name="font"> | ||
| 1261 | <font> | ||
| 1262 | <pointsize>18</pointsize> | ||
| 1263 | </font> | ||
| 1264 | </property> | ||
| 1265 | <property name="text"> | ||
| 1266 | <string notr="true">Return</string> | ||
| 1267 | </property> | ||
| 1268 | </widget> | ||
| 1269 | </item> | ||
| 1270 | <item row="4" column="12" rowspan="2"> | ||
| 1271 | <widget class="QPushButton" name="button_ok"> | ||
| 1272 | <property name="sizePolicy"> | ||
| 1273 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 1274 | <horstretch>1</horstretch> | ||
| 1275 | <verstretch>1</verstretch> | ||
| 1276 | </sizepolicy> | ||
| 1277 | </property> | ||
| 1278 | <property name="font"> | ||
| 1279 | <font> | ||
| 1280 | <pointsize>18</pointsize> | ||
| 1281 | </font> | ||
| 1282 | </property> | ||
| 1283 | <property name="text"> | ||
| 1284 | <string notr="true">OK</string> | ||
| 1285 | </property> | ||
| 1286 | </widget> | ||
| 1287 | </item> | ||
| 1288 | <item row="4" column="1"> | ||
| 1289 | <widget class="QPushButton" name="button_z"> | ||
| 1290 | <property name="sizePolicy"> | ||
| 1291 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 1292 | <horstretch>1</horstretch> | ||
| 1293 | <verstretch>1</verstretch> | ||
| 1294 | </sizepolicy> | ||
| 1295 | </property> | ||
| 1296 | <property name="font"> | ||
| 1297 | <font> | ||
| 1298 | <pointsize>28</pointsize> | ||
| 1299 | </font> | ||
| 1300 | </property> | ||
| 1301 | <property name="text"> | ||
| 1302 | <string notr="true">z</string> | ||
| 1303 | </property> | ||
| 1304 | </widget> | ||
| 1305 | </item> | ||
| 1306 | <item row="4" column="3"> | ||
| 1307 | <widget class="QPushButton" name="button_c"> | ||
| 1308 | <property name="sizePolicy"> | ||
| 1309 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 1310 | <horstretch>1</horstretch> | ||
| 1311 | <verstretch>1</verstretch> | ||
| 1312 | </sizepolicy> | ||
| 1313 | </property> | ||
| 1314 | <property name="font"> | ||
| 1315 | <font> | ||
| 1316 | <pointsize>28</pointsize> | ||
| 1317 | </font> | ||
| 1318 | </property> | ||
| 1319 | <property name="text"> | ||
| 1320 | <string notr="true">c</string> | ||
| 1321 | </property> | ||
| 1322 | </widget> | ||
| 1323 | </item> | ||
| 1324 | <item row="4" column="2"> | ||
| 1325 | <widget class="QPushButton" name="button_x"> | ||
| 1326 | <property name="sizePolicy"> | ||
| 1327 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 1328 | <horstretch>1</horstretch> | ||
| 1329 | <verstretch>1</verstretch> | ||
| 1330 | </sizepolicy> | ||
| 1331 | </property> | ||
| 1332 | <property name="font"> | ||
| 1333 | <font> | ||
| 1334 | <pointsize>28</pointsize> | ||
| 1335 | </font> | ||
| 1336 | </property> | ||
| 1337 | <property name="text"> | ||
| 1338 | <string notr="true">x</string> | ||
| 1339 | </property> | ||
| 1340 | </widget> | ||
| 1341 | </item> | ||
| 1342 | <item row="4" column="4"> | ||
| 1343 | <widget class="QPushButton" name="button_v"> | ||
| 1344 | <property name="sizePolicy"> | ||
| 1345 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 1346 | <horstretch>1</horstretch> | ||
| 1347 | <verstretch>1</verstretch> | ||
| 1348 | </sizepolicy> | ||
| 1349 | </property> | ||
| 1350 | <property name="font"> | ||
| 1351 | <font> | ||
| 1352 | <pointsize>28</pointsize> | ||
| 1353 | </font> | ||
| 1354 | </property> | ||
| 1355 | <property name="text"> | ||
| 1356 | <string notr="true">v</string> | ||
| 1357 | </property> | ||
| 1358 | </widget> | ||
| 1359 | </item> | ||
| 1360 | <item row="4" column="7"> | ||
| 1361 | <widget class="QPushButton" name="button_m"> | ||
| 1362 | <property name="sizePolicy"> | ||
| 1363 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 1364 | <horstretch>1</horstretch> | ||
| 1365 | <verstretch>1</verstretch> | ||
| 1366 | </sizepolicy> | ||
| 1367 | </property> | ||
| 1368 | <property name="font"> | ||
| 1369 | <font> | ||
| 1370 | <pointsize>28</pointsize> | ||
| 1371 | </font> | ||
| 1372 | </property> | ||
| 1373 | <property name="text"> | ||
| 1374 | <string notr="true">m</string> | ||
| 1375 | </property> | ||
| 1376 | </widget> | ||
| 1377 | </item> | ||
| 1378 | <item row="4" column="8"> | ||
| 1379 | <widget class="QPushButton" name="button_comma"> | ||
| 1380 | <property name="sizePolicy"> | ||
| 1381 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 1382 | <horstretch>1</horstretch> | ||
| 1383 | <verstretch>1</verstretch> | ||
| 1384 | </sizepolicy> | ||
| 1385 | </property> | ||
| 1386 | <property name="font"> | ||
| 1387 | <font> | ||
| 1388 | <pointsize>28</pointsize> | ||
| 1389 | </font> | ||
| 1390 | </property> | ||
| 1391 | <property name="text"> | ||
| 1392 | <string notr="true">,</string> | ||
| 1393 | </property> | ||
| 1394 | </widget> | ||
| 1395 | </item> | ||
| 1396 | <item row="4" column="6"> | ||
| 1397 | <widget class="QPushButton" name="button_n"> | ||
| 1398 | <property name="sizePolicy"> | ||
| 1399 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 1400 | <horstretch>1</horstretch> | ||
| 1401 | <verstretch>1</verstretch> | ||
| 1402 | </sizepolicy> | ||
| 1403 | </property> | ||
| 1404 | <property name="font"> | ||
| 1405 | <font> | ||
| 1406 | <pointsize>28</pointsize> | ||
| 1407 | </font> | ||
| 1408 | </property> | ||
| 1409 | <property name="text"> | ||
| 1410 | <string notr="true">n</string> | ||
| 1411 | </property> | ||
| 1412 | </widget> | ||
| 1413 | </item> | ||
| 1414 | <item row="4" column="5"> | ||
| 1415 | <widget class="QPushButton" name="button_b"> | ||
| 1416 | <property name="sizePolicy"> | ||
| 1417 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 1418 | <horstretch>1</horstretch> | ||
| 1419 | <verstretch>1</verstretch> | ||
| 1420 | </sizepolicy> | ||
| 1421 | </property> | ||
| 1422 | <property name="font"> | ||
| 1423 | <font> | ||
| 1424 | <pointsize>28</pointsize> | ||
| 1425 | </font> | ||
| 1426 | </property> | ||
| 1427 | <property name="text"> | ||
| 1428 | <string notr="true">b</string> | ||
| 1429 | </property> | ||
| 1430 | </widget> | ||
| 1431 | </item> | ||
| 1432 | <item row="5" column="1" colspan="2"> | ||
| 1433 | <widget class="QPushButton" name="button_shift"> | ||
| 1434 | <property name="sizePolicy"> | ||
| 1435 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 1436 | <horstretch>1</horstretch> | ||
| 1437 | <verstretch>1</verstretch> | ||
| 1438 | </sizepolicy> | ||
| 1439 | </property> | ||
| 1440 | <property name="font"> | ||
| 1441 | <font> | ||
| 1442 | <pointsize>18</pointsize> | ||
| 1443 | </font> | ||
| 1444 | </property> | ||
| 1445 | <property name="text"> | ||
| 1446 | <string notr="true"/> | ||
| 1447 | </property> | ||
| 1448 | <property name="checkable"> | ||
| 1449 | <bool>true</bool> | ||
| 1450 | </property> | ||
| 1451 | <property name="checked"> | ||
| 1452 | <bool>false</bool> | ||
| 1453 | </property> | ||
| 1454 | </widget> | ||
| 1455 | </item> | ||
| 1456 | <item row="4" column="10"> | ||
| 1457 | <widget class="QPushButton" name="button_question"> | ||
| 1458 | <property name="sizePolicy"> | ||
| 1459 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 1460 | <horstretch>1</horstretch> | ||
| 1461 | <verstretch>1</verstretch> | ||
| 1462 | </sizepolicy> | ||
| 1463 | </property> | ||
| 1464 | <property name="font"> | ||
| 1465 | <font> | ||
| 1466 | <pointsize>28</pointsize> | ||
| 1467 | </font> | ||
| 1468 | </property> | ||
| 1469 | <property name="text"> | ||
| 1470 | <string notr="true">?</string> | ||
| 1471 | </property> | ||
| 1472 | </widget> | ||
| 1473 | </item> | ||
| 1474 | <item row="4" column="9"> | ||
| 1475 | <widget class="QPushButton" name="button_dot"> | ||
| 1476 | <property name="sizePolicy"> | ||
| 1477 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 1478 | <horstretch>1</horstretch> | ||
| 1479 | <verstretch>1</verstretch> | ||
| 1480 | </sizepolicy> | ||
| 1481 | </property> | ||
| 1482 | <property name="font"> | ||
| 1483 | <font> | ||
| 1484 | <pointsize>28</pointsize> | ||
| 1485 | </font> | ||
| 1486 | </property> | ||
| 1487 | <property name="text"> | ||
| 1488 | <string notr="true">.</string> | ||
| 1489 | </property> | ||
| 1490 | </widget> | ||
| 1491 | </item> | ||
| 1492 | <item row="1" column="1"> | ||
| 1493 | <widget class="QPushButton" name="button_1"> | ||
| 1494 | <property name="sizePolicy"> | ||
| 1495 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 1496 | <horstretch>1</horstretch> | ||
| 1497 | <verstretch>1</verstretch> | ||
| 1498 | </sizepolicy> | ||
| 1499 | </property> | ||
| 1500 | <property name="font"> | ||
| 1501 | <font> | ||
| 1502 | <pointsize>28</pointsize> | ||
| 1503 | </font> | ||
| 1504 | </property> | ||
| 1505 | <property name="text"> | ||
| 1506 | <string notr="true">1</string> | ||
| 1507 | </property> | ||
| 1508 | </widget> | ||
| 1509 | </item> | ||
| 1510 | <item row="1" column="3"> | ||
| 1511 | <widget class="QPushButton" name="button_3"> | ||
| 1512 | <property name="sizePolicy"> | ||
| 1513 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 1514 | <horstretch>1</horstretch> | ||
| 1515 | <verstretch>1</verstretch> | ||
| 1516 | </sizepolicy> | ||
| 1517 | </property> | ||
| 1518 | <property name="font"> | ||
| 1519 | <font> | ||
| 1520 | <pointsize>28</pointsize> | ||
| 1521 | </font> | ||
| 1522 | </property> | ||
| 1523 | <property name="text"> | ||
| 1524 | <string notr="true">3</string> | ||
| 1525 | </property> | ||
| 1526 | </widget> | ||
| 1527 | </item> | ||
| 1528 | <item row="1" column="4"> | ||
| 1529 | <widget class="QPushButton" name="button_4"> | ||
| 1530 | <property name="sizePolicy"> | ||
| 1531 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 1532 | <horstretch>1</horstretch> | ||
| 1533 | <verstretch>1</verstretch> | ||
| 1534 | </sizepolicy> | ||
| 1535 | </property> | ||
| 1536 | <property name="font"> | ||
| 1537 | <font> | ||
| 1538 | <pointsize>28</pointsize> | ||
| 1539 | </font> | ||
| 1540 | </property> | ||
| 1541 | <property name="text"> | ||
| 1542 | <string notr="true">4</string> | ||
| 1543 | </property> | ||
| 1544 | </widget> | ||
| 1545 | </item> | ||
| 1546 | <item row="1" column="2"> | ||
| 1547 | <widget class="QPushButton" name="button_2"> | ||
| 1548 | <property name="sizePolicy"> | ||
| 1549 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 1550 | <horstretch>1</horstretch> | ||
| 1551 | <verstretch>1</verstretch> | ||
| 1552 | </sizepolicy> | ||
| 1553 | </property> | ||
| 1554 | <property name="font"> | ||
| 1555 | <font> | ||
| 1556 | <pointsize>28</pointsize> | ||
| 1557 | </font> | ||
| 1558 | </property> | ||
| 1559 | <property name="text"> | ||
| 1560 | <string notr="true">2</string> | ||
| 1561 | </property> | ||
| 1562 | </widget> | ||
| 1563 | </item> | ||
| 1564 | <item row="1" column="6"> | ||
| 1565 | <widget class="QPushButton" name="button_6"> | ||
| 1566 | <property name="sizePolicy"> | ||
| 1567 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 1568 | <horstretch>1</horstretch> | ||
| 1569 | <verstretch>1</verstretch> | ||
| 1570 | </sizepolicy> | ||
| 1571 | </property> | ||
| 1572 | <property name="font"> | ||
| 1573 | <font> | ||
| 1574 | <pointsize>28</pointsize> | ||
| 1575 | </font> | ||
| 1576 | </property> | ||
| 1577 | <property name="text"> | ||
| 1578 | <string notr="true">6</string> | ||
| 1579 | </property> | ||
| 1580 | </widget> | ||
| 1581 | </item> | ||
| 1582 | <item row="1" column="5"> | ||
| 1583 | <widget class="QPushButton" name="button_5"> | ||
| 1584 | <property name="sizePolicy"> | ||
| 1585 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 1586 | <horstretch>1</horstretch> | ||
| 1587 | <verstretch>1</verstretch> | ||
| 1588 | </sizepolicy> | ||
| 1589 | </property> | ||
| 1590 | <property name="font"> | ||
| 1591 | <font> | ||
| 1592 | <pointsize>28</pointsize> | ||
| 1593 | </font> | ||
| 1594 | </property> | ||
| 1595 | <property name="text"> | ||
| 1596 | <string notr="true">5</string> | ||
| 1597 | </property> | ||
| 1598 | </widget> | ||
| 1599 | </item> | ||
| 1600 | <item row="5" column="3" colspan="9"> | ||
| 1601 | <widget class="QPushButton" name="button_space"> | ||
| 1602 | <property name="sizePolicy"> | ||
| 1603 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 1604 | <horstretch>1</horstretch> | ||
| 1605 | <verstretch>1</verstretch> | ||
| 1606 | </sizepolicy> | ||
| 1607 | </property> | ||
| 1608 | <property name="font"> | ||
| 1609 | <font> | ||
| 1610 | <pointsize>18</pointsize> | ||
| 1611 | </font> | ||
| 1612 | </property> | ||
| 1613 | <property name="text"> | ||
| 1614 | <string notr="true">Space</string> | ||
| 1615 | </property> | ||
| 1616 | </widget> | ||
| 1617 | </item> | ||
| 1618 | <item row="1" column="12"> | ||
| 1619 | <widget class="QPushButton" name="button_backspace"> | ||
| 1620 | <property name="sizePolicy"> | ||
| 1621 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 1622 | <horstretch>1</horstretch> | ||
| 1623 | <verstretch>1</verstretch> | ||
| 1624 | </sizepolicy> | ||
| 1625 | </property> | ||
| 1626 | <property name="font"> | ||
| 1627 | <font> | ||
| 1628 | <pointsize>18</pointsize> | ||
| 1629 | </font> | ||
| 1630 | </property> | ||
| 1631 | <property name="text"> | ||
| 1632 | <string notr="true"/> | ||
| 1633 | </property> | ||
| 1634 | </widget> | ||
| 1635 | </item> | ||
| 1636 | <item row="1" column="0"> | ||
| 1637 | <spacer name="horizontalSpacer"> | ||
| 1638 | <property name="orientation"> | ||
| 1639 | <enum>Qt::Horizontal</enum> | ||
| 1640 | </property> | ||
| 1641 | <property name="sizeHint" stdset="0"> | ||
| 1642 | <size> | ||
| 1643 | <width>40</width> | ||
| 1644 | <height>20</height> | ||
| 1645 | </size> | ||
| 1646 | </property> | ||
| 1647 | </spacer> | ||
| 1648 | </item> | ||
| 1649 | <item row="0" column="1"> | ||
| 1650 | <spacer name="verticalSpacer"> | ||
| 1651 | <property name="orientation"> | ||
| 1652 | <enum>Qt::Vertical</enum> | ||
| 1653 | </property> | ||
| 1654 | <property name="sizeHint" stdset="0"> | ||
| 1655 | <size> | ||
| 1656 | <width>20</width> | ||
| 1657 | <height>0</height> | ||
| 1658 | </size> | ||
| 1659 | </property> | ||
| 1660 | </spacer> | ||
| 1661 | </item> | ||
| 1662 | <item row="1" column="13"> | ||
| 1663 | <spacer name="horizontalSpacer_2"> | ||
| 1664 | <property name="orientation"> | ||
| 1665 | <enum>Qt::Horizontal</enum> | ||
| 1666 | </property> | ||
| 1667 | <property name="sizeHint" stdset="0"> | ||
| 1668 | <size> | ||
| 1669 | <width>40</width> | ||
| 1670 | <height>20</height> | ||
| 1671 | </size> | ||
| 1672 | </property> | ||
| 1673 | </spacer> | ||
| 1674 | </item> | ||
| 1675 | </layout> | ||
| 1676 | </item> | ||
| 1677 | </layout> | ||
| 1678 | </widget> | ||
| 1679 | <widget class="QWidget" name="shiftOSK"> | ||
| 1680 | <layout class="QVBoxLayout" name="shiftPageVerticalLayout"> | ||
| 1681 | <property name="leftMargin"> | ||
| 1682 | <number>0</number> | ||
| 1683 | </property> | ||
| 1684 | <property name="topMargin"> | ||
| 1685 | <number>0</number> | ||
| 1686 | </property> | ||
| 1687 | <property name="rightMargin"> | ||
| 1688 | <number>0</number> | ||
| 1689 | </property> | ||
| 1690 | <property name="bottomMargin"> | ||
| 1691 | <number>0</number> | ||
| 1692 | </property> | ||
| 1693 | <item> | ||
| 1694 | <layout class="QGridLayout" name="kbOSKshift" rowstretch="15,63,63,63,63,63,70" columnstretch="54,96,96,96,96,96,96,96,96,96,96,96,116,54"> | ||
| 1695 | <property name="spacing"> | ||
| 1696 | <number>0</number> | ||
| 1697 | </property> | ||
| 1698 | <item row="6" column="1" colspan="12"> | ||
| 1699 | <widget class="QWidget" name="legendOSKshift" native="true"> | ||
| 1700 | <layout class="QHBoxLayout" name="horizontalLayout_5" stretch="70,464,25,12,22,41,25,12,22,41,25,12,95,37,29,12,69,37,29,12,56,8"> | ||
| 1701 | <property name="spacing"> | ||
| 1702 | <number>0</number> | ||
| 1703 | </property> | ||
| 1704 | <property name="leftMargin"> | ||
| 1705 | <number>2</number> | ||
| 1706 | </property> | ||
| 1707 | <property name="topMargin"> | ||
| 1708 | <number>0</number> | ||
| 1709 | </property> | ||
| 1710 | <property name="rightMargin"> | ||
| 1711 | <number>0</number> | ||
| 1712 | </property> | ||
| 1713 | <property name="bottomMargin"> | ||
| 1714 | <number>0</number> | ||
| 1715 | </property> | ||
| 1716 | <item> | ||
| 1717 | <widget class="QWidget" name="icon_controller_shift" native="true"> | ||
| 1718 | <property name="styleSheet"> | ||
| 1719 | <string notr="true"/> | ||
| 1720 | </property> | ||
| 1721 | </widget> | ||
| 1722 | </item> | ||
| 1723 | <item> | ||
| 1724 | <spacer name="horizontalSpacer_22"> | ||
| 1725 | <property name="orientation"> | ||
| 1726 | <enum>Qt::Horizontal</enum> | ||
| 1727 | </property> | ||
| 1728 | <property name="sizeHint" stdset="0"> | ||
| 1729 | <size> | ||
| 1730 | <width>0</width> | ||
| 1731 | <height>20</height> | ||
| 1732 | </size> | ||
| 1733 | </property> | ||
| 1734 | </spacer> | ||
| 1735 | </item> | ||
| 1736 | <item> | ||
| 1737 | <widget class="QWidget" name="button_L_shift" native="true"/> | ||
| 1738 | </item> | ||
| 1739 | <item> | ||
| 1740 | <spacer name="horizontalSpacer_23"> | ||
| 1741 | <property name="orientation"> | ||
| 1742 | <enum>Qt::Horizontal</enum> | ||
| 1743 | </property> | ||
| 1744 | <property name="sizeHint" stdset="0"> | ||
| 1745 | <size> | ||
| 1746 | <width>0</width> | ||
| 1747 | <height>20</height> | ||
| 1748 | </size> | ||
| 1749 | </property> | ||
| 1750 | </spacer> | ||
| 1751 | </item> | ||
| 1752 | <item> | ||
| 1753 | <widget class="QWidget" name="arrow_left_shift" native="true"/> | ||
| 1754 | </item> | ||
| 1755 | <item> | ||
| 1756 | <spacer name="horizontalSpacer_24"> | ||
| 1757 | <property name="orientation"> | ||
| 1758 | <enum>Qt::Horizontal</enum> | ||
| 1759 | </property> | ||
| 1760 | <property name="sizeHint" stdset="0"> | ||
| 1761 | <size> | ||
| 1762 | <width>0</width> | ||
| 1763 | <height>20</height> | ||
| 1764 | </size> | ||
| 1765 | </property> | ||
| 1766 | </spacer> | ||
| 1767 | </item> | ||
| 1768 | <item> | ||
| 1769 | <widget class="QWidget" name="button_R_shift" native="true"/> | ||
| 1770 | </item> | ||
| 1771 | <item> | ||
| 1772 | <spacer name="horizontalSpacer_25"> | ||
| 1773 | <property name="orientation"> | ||
| 1774 | <enum>Qt::Horizontal</enum> | ||
| 1775 | </property> | ||
| 1776 | <property name="sizeHint" stdset="0"> | ||
| 1777 | <size> | ||
| 1778 | <width>0</width> | ||
| 1779 | <height>20</height> | ||
| 1780 | </size> | ||
| 1781 | </property> | ||
| 1782 | </spacer> | ||
| 1783 | </item> | ||
| 1784 | <item> | ||
| 1785 | <widget class="QWidget" name="arrow_right_shift" native="true"/> | ||
| 1786 | </item> | ||
| 1787 | <item> | ||
| 1788 | <spacer name="horizontalSpacer_26"> | ||
| 1789 | <property name="orientation"> | ||
| 1790 | <enum>Qt::Horizontal</enum> | ||
| 1791 | </property> | ||
| 1792 | <property name="sizeHint" stdset="0"> | ||
| 1793 | <size> | ||
| 1794 | <width>0</width> | ||
| 1795 | <height>20</height> | ||
| 1796 | </size> | ||
| 1797 | </property> | ||
| 1798 | </spacer> | ||
| 1799 | </item> | ||
| 1800 | <item> | ||
| 1801 | <widget class="QWidget" name="button_press_stick_shift" native="true"/> | ||
| 1802 | </item> | ||
| 1803 | <item> | ||
| 1804 | <spacer name="horizontalSpacer_27"> | ||
| 1805 | <property name="orientation"> | ||
| 1806 | <enum>Qt::Horizontal</enum> | ||
| 1807 | </property> | ||
| 1808 | <property name="sizeHint" stdset="0"> | ||
| 1809 | <size> | ||
| 1810 | <width>0</width> | ||
| 1811 | <height>20</height> | ||
| 1812 | </size> | ||
| 1813 | </property> | ||
| 1814 | </spacer> | ||
| 1815 | </item> | ||
| 1816 | <item> | ||
| 1817 | <widget class="QLabel" name="label_shift_shift"> | ||
| 1818 | <property name="font"> | ||
| 1819 | <font> | ||
| 1820 | <pointsize>18</pointsize> | ||
| 1821 | </font> | ||
| 1822 | </property> | ||
| 1823 | <property name="text"> | ||
| 1824 | <string notr="true">Caps Lock</string> | ||
| 1825 | </property> | ||
| 1826 | </widget> | ||
| 1827 | </item> | ||
| 1828 | <item> | ||
| 1829 | <spacer name="horizontalSpacer_28"> | ||
| 1830 | <property name="orientation"> | ||
| 1831 | <enum>Qt::Horizontal</enum> | ||
| 1832 | </property> | ||
| 1833 | <property name="sizeHint" stdset="0"> | ||
| 1834 | <size> | ||
| 1835 | <width>0</width> | ||
| 1836 | <height>20</height> | ||
| 1837 | </size> | ||
| 1838 | </property> | ||
| 1839 | </spacer> | ||
| 1840 | </item> | ||
| 1841 | <item> | ||
| 1842 | <widget class="QWidget" name="button_X_shift" native="true"/> | ||
| 1843 | </item> | ||
| 1844 | <item> | ||
| 1845 | <spacer name="horizontalSpacer_29"> | ||
| 1846 | <property name="orientation"> | ||
| 1847 | <enum>Qt::Horizontal</enum> | ||
| 1848 | </property> | ||
| 1849 | <property name="sizeHint" stdset="0"> | ||
| 1850 | <size> | ||
| 1851 | <width>0</width> | ||
| 1852 | <height>20</height> | ||
| 1853 | </size> | ||
| 1854 | </property> | ||
| 1855 | </spacer> | ||
| 1856 | </item> | ||
| 1857 | <item> | ||
| 1858 | <widget class="QLabel" name="label_cancel_shift"> | ||
| 1859 | <property name="font"> | ||
| 1860 | <font> | ||
| 1861 | <pointsize>18</pointsize> | ||
| 1862 | </font> | ||
| 1863 | </property> | ||
| 1864 | <property name="text"> | ||
| 1865 | <string notr="true">Cancel</string> | ||
| 1866 | </property> | ||
| 1867 | </widget> | ||
| 1868 | </item> | ||
| 1869 | <item> | ||
| 1870 | <spacer name="horizontalSpacer_30"> | ||
| 1871 | <property name="orientation"> | ||
| 1872 | <enum>Qt::Horizontal</enum> | ||
| 1873 | </property> | ||
| 1874 | <property name="sizeHint" stdset="0"> | ||
| 1875 | <size> | ||
| 1876 | <width>0</width> | ||
| 1877 | <height>20</height> | ||
| 1878 | </size> | ||
| 1879 | </property> | ||
| 1880 | </spacer> | ||
| 1881 | </item> | ||
| 1882 | <item> | ||
| 1883 | <widget class="QWidget" name="button_A_shift" native="true"/> | ||
| 1884 | </item> | ||
| 1885 | <item> | ||
| 1886 | <spacer name="horizontalSpacer_31"> | ||
| 1887 | <property name="orientation"> | ||
| 1888 | <enum>Qt::Horizontal</enum> | ||
| 1889 | </property> | ||
| 1890 | <property name="sizeHint" stdset="0"> | ||
| 1891 | <size> | ||
| 1892 | <width>0</width> | ||
| 1893 | <height>20</height> | ||
| 1894 | </size> | ||
| 1895 | </property> | ||
| 1896 | </spacer> | ||
| 1897 | </item> | ||
| 1898 | <item> | ||
| 1899 | <widget class="QLabel" name="label_enter_shift"> | ||
| 1900 | <property name="font"> | ||
| 1901 | <font> | ||
| 1902 | <pointsize>18</pointsize> | ||
| 1903 | </font> | ||
| 1904 | </property> | ||
| 1905 | <property name="text"> | ||
| 1906 | <string notr="true">Enter</string> | ||
| 1907 | </property> | ||
| 1908 | </widget> | ||
| 1909 | </item> | ||
| 1910 | <item> | ||
| 1911 | <spacer name="horizontalSpacer_32"> | ||
| 1912 | <property name="orientation"> | ||
| 1913 | <enum>Qt::Horizontal</enum> | ||
| 1914 | </property> | ||
| 1915 | <property name="sizeHint" stdset="0"> | ||
| 1916 | <size> | ||
| 1917 | <width>0</width> | ||
| 1918 | <height>20</height> | ||
| 1919 | </size> | ||
| 1920 | </property> | ||
| 1921 | </spacer> | ||
| 1922 | </item> | ||
| 1923 | </layout> | ||
| 1924 | </widget> | ||
| 1925 | </item> | ||
| 1926 | <item row="1" column="11"> | ||
| 1927 | <widget class="QPushButton" name="button_underscore"> | ||
| 1928 | <property name="sizePolicy"> | ||
| 1929 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 1930 | <horstretch>1</horstretch> | ||
| 1931 | <verstretch>1</verstretch> | ||
| 1932 | </sizepolicy> | ||
| 1933 | </property> | ||
| 1934 | <property name="font"> | ||
| 1935 | <font> | ||
| 1936 | <pointsize>28</pointsize> | ||
| 1937 | </font> | ||
| 1938 | </property> | ||
| 1939 | <property name="text"> | ||
| 1940 | <string notr="true">_</string> | ||
| 1941 | </property> | ||
| 1942 | </widget> | ||
| 1943 | </item> | ||
| 1944 | <item row="3" column="11"> | ||
| 1945 | <widget class="QPushButton" name="button_quotation"> | ||
| 1946 | <property name="sizePolicy"> | ||
| 1947 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 1948 | <horstretch>1</horstretch> | ||
| 1949 | <verstretch>1</verstretch> | ||
| 1950 | </sizepolicy> | ||
| 1951 | </property> | ||
| 1952 | <property name="font"> | ||
| 1953 | <font> | ||
| 1954 | <pointsize>28</pointsize> | ||
| 1955 | </font> | ||
| 1956 | </property> | ||
| 1957 | <property name="text"> | ||
| 1958 | <string notr="true">"</string> | ||
| 1959 | </property> | ||
| 1960 | </widget> | ||
| 1961 | </item> | ||
| 1962 | <item row="2" column="11"> | ||
| 1963 | <widget class="QPushButton" name="button_at"> | ||
| 1964 | <property name="sizePolicy"> | ||
| 1965 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 1966 | <horstretch>1</horstretch> | ||
| 1967 | <verstretch>1</verstretch> | ||
| 1968 | </sizepolicy> | ||
| 1969 | </property> | ||
| 1970 | <property name="font"> | ||
| 1971 | <font> | ||
| 1972 | <pointsize>28</pointsize> | ||
| 1973 | </font> | ||
| 1974 | </property> | ||
| 1975 | <property name="text"> | ||
| 1976 | <string notr="true">@</string> | ||
| 1977 | </property> | ||
| 1978 | </widget> | ||
| 1979 | </item> | ||
| 1980 | <item row="4" column="11"> | ||
| 1981 | <widget class="QPushButton" name="button_equal"> | ||
| 1982 | <property name="sizePolicy"> | ||
| 1983 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 1984 | <horstretch>1</horstretch> | ||
| 1985 | <verstretch>1</verstretch> | ||
| 1986 | </sizepolicy> | ||
| 1987 | </property> | ||
| 1988 | <property name="font"> | ||
| 1989 | <font> | ||
| 1990 | <pointsize>28</pointsize> | ||
| 1991 | </font> | ||
| 1992 | </property> | ||
| 1993 | <property name="text"> | ||
| 1994 | <string notr="true">=</string> | ||
| 1995 | </property> | ||
| 1996 | </widget> | ||
| 1997 | </item> | ||
| 1998 | <item row="1" column="7"> | ||
| 1999 | <widget class="QPushButton" name="button_ampersand"> | ||
| 2000 | <property name="sizePolicy"> | ||
| 2001 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 2002 | <horstretch>1</horstretch> | ||
| 2003 | <verstretch>1</verstretch> | ||
| 2004 | </sizepolicy> | ||
| 2005 | </property> | ||
| 2006 | <property name="font"> | ||
| 2007 | <font> | ||
| 2008 | <pointsize>28</pointsize> | ||
| 2009 | </font> | ||
| 2010 | </property> | ||
| 2011 | <property name="text"> | ||
| 2012 | <string notr="true">&&</string> | ||
| 2013 | </property> | ||
| 2014 | </widget> | ||
| 2015 | </item> | ||
| 2016 | <item row="1" column="8"> | ||
| 2017 | <widget class="QPushButton" name="button_asterisk"> | ||
| 2018 | <property name="sizePolicy"> | ||
| 2019 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 2020 | <horstretch>1</horstretch> | ||
| 2021 | <verstretch>1</verstretch> | ||
| 2022 | </sizepolicy> | ||
| 2023 | </property> | ||
| 2024 | <property name="font"> | ||
| 2025 | <font> | ||
| 2026 | <pointsize>28</pointsize> | ||
| 2027 | </font> | ||
| 2028 | </property> | ||
| 2029 | <property name="text"> | ||
| 2030 | <string notr="true">*</string> | ||
| 2031 | </property> | ||
| 2032 | </widget> | ||
| 2033 | </item> | ||
| 2034 | <item row="1" column="10"> | ||
| 2035 | <widget class="QPushButton" name="button_right_parenthesis"> | ||
| 2036 | <property name="sizePolicy"> | ||
| 2037 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 2038 | <horstretch>1</horstretch> | ||
| 2039 | <verstretch>1</verstretch> | ||
| 2040 | </sizepolicy> | ||
| 2041 | </property> | ||
| 2042 | <property name="font"> | ||
| 2043 | <font> | ||
| 2044 | <pointsize>28</pointsize> | ||
| 2045 | </font> | ||
| 2046 | </property> | ||
| 2047 | <property name="text"> | ||
| 2048 | <string notr="true">)</string> | ||
| 2049 | </property> | ||
| 2050 | </widget> | ||
| 2051 | </item> | ||
| 2052 | <item row="1" column="9"> | ||
| 2053 | <widget class="QPushButton" name="button_left_parenthesis"> | ||
| 2054 | <property name="sizePolicy"> | ||
| 2055 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 2056 | <horstretch>1</horstretch> | ||
| 2057 | <verstretch>1</verstretch> | ||
| 2058 | </sizepolicy> | ||
| 2059 | </property> | ||
| 2060 | <property name="font"> | ||
| 2061 | <font> | ||
| 2062 | <pointsize>28</pointsize> | ||
| 2063 | </font> | ||
| 2064 | </property> | ||
| 2065 | <property name="text"> | ||
| 2066 | <string notr="true">(</string> | ||
| 2067 | </property> | ||
| 2068 | </widget> | ||
| 2069 | </item> | ||
| 2070 | <item row="2" column="2"> | ||
| 2071 | <widget class="QPushButton" name="button_w_shift"> | ||
| 2072 | <property name="sizePolicy"> | ||
| 2073 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 2074 | <horstretch>1</horstretch> | ||
| 2075 | <verstretch>1</verstretch> | ||
| 2076 | </sizepolicy> | ||
| 2077 | </property> | ||
| 2078 | <property name="font"> | ||
| 2079 | <font> | ||
| 2080 | <pointsize>28</pointsize> | ||
| 2081 | </font> | ||
| 2082 | </property> | ||
| 2083 | <property name="text"> | ||
| 2084 | <string notr="true">W</string> | ||
| 2085 | </property> | ||
| 2086 | </widget> | ||
| 2087 | </item> | ||
| 2088 | <item row="2" column="4"> | ||
| 2089 | <widget class="QPushButton" name="button_r_shift"> | ||
| 2090 | <property name="sizePolicy"> | ||
| 2091 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 2092 | <horstretch>1</horstretch> | ||
| 2093 | <verstretch>1</verstretch> | ||
| 2094 | </sizepolicy> | ||
| 2095 | </property> | ||
| 2096 | <property name="font"> | ||
| 2097 | <font> | ||
| 2098 | <pointsize>28</pointsize> | ||
| 2099 | </font> | ||
| 2100 | </property> | ||
| 2101 | <property name="text"> | ||
| 2102 | <string notr="true">R</string> | ||
| 2103 | </property> | ||
| 2104 | </widget> | ||
| 2105 | </item> | ||
| 2106 | <item row="2" column="3"> | ||
| 2107 | <widget class="QPushButton" name="button_e_shift"> | ||
| 2108 | <property name="sizePolicy"> | ||
| 2109 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 2110 | <horstretch>1</horstretch> | ||
| 2111 | <verstretch>1</verstretch> | ||
| 2112 | </sizepolicy> | ||
| 2113 | </property> | ||
| 2114 | <property name="font"> | ||
| 2115 | <font> | ||
| 2116 | <pointsize>28</pointsize> | ||
| 2117 | </font> | ||
| 2118 | </property> | ||
| 2119 | <property name="text"> | ||
| 2120 | <string notr="true">E</string> | ||
| 2121 | </property> | ||
| 2122 | </widget> | ||
| 2123 | </item> | ||
| 2124 | <item row="2" column="1"> | ||
| 2125 | <widget class="QPushButton" name="button_q_shift"> | ||
| 2126 | <property name="sizePolicy"> | ||
| 2127 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 2128 | <horstretch>1</horstretch> | ||
| 2129 | <verstretch>1</verstretch> | ||
| 2130 | </sizepolicy> | ||
| 2131 | </property> | ||
| 2132 | <property name="font"> | ||
| 2133 | <font> | ||
| 2134 | <pointsize>28</pointsize> | ||
| 2135 | </font> | ||
| 2136 | </property> | ||
| 2137 | <property name="text"> | ||
| 2138 | <string notr="true">Q</string> | ||
| 2139 | </property> | ||
| 2140 | </widget> | ||
| 2141 | </item> | ||
| 2142 | <item row="2" column="7"> | ||
| 2143 | <widget class="QPushButton" name="button_u_shift"> | ||
| 2144 | <property name="sizePolicy"> | ||
| 2145 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 2146 | <horstretch>1</horstretch> | ||
| 2147 | <verstretch>1</verstretch> | ||
| 2148 | </sizepolicy> | ||
| 2149 | </property> | ||
| 2150 | <property name="font"> | ||
| 2151 | <font> | ||
| 2152 | <pointsize>28</pointsize> | ||
| 2153 | </font> | ||
| 2154 | </property> | ||
| 2155 | <property name="text"> | ||
| 2156 | <string notr="true">U</string> | ||
| 2157 | </property> | ||
| 2158 | </widget> | ||
| 2159 | </item> | ||
| 2160 | <item row="2" column="6"> | ||
| 2161 | <widget class="QPushButton" name="button_y_shift"> | ||
| 2162 | <property name="sizePolicy"> | ||
| 2163 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 2164 | <horstretch>1</horstretch> | ||
| 2165 | <verstretch>1</verstretch> | ||
| 2166 | </sizepolicy> | ||
| 2167 | </property> | ||
| 2168 | <property name="font"> | ||
| 2169 | <font> | ||
| 2170 | <pointsize>28</pointsize> | ||
| 2171 | </font> | ||
| 2172 | </property> | ||
| 2173 | <property name="text"> | ||
| 2174 | <string notr="true">Y</string> | ||
| 2175 | </property> | ||
| 2176 | </widget> | ||
| 2177 | </item> | ||
| 2178 | <item row="2" column="5"> | ||
| 2179 | <widget class="QPushButton" name="button_t_shift"> | ||
| 2180 | <property name="sizePolicy"> | ||
| 2181 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 2182 | <horstretch>1</horstretch> | ||
| 2183 | <verstretch>1</verstretch> | ||
| 2184 | </sizepolicy> | ||
| 2185 | </property> | ||
| 2186 | <property name="font"> | ||
| 2187 | <font> | ||
| 2188 | <pointsize>28</pointsize> | ||
| 2189 | </font> | ||
| 2190 | </property> | ||
| 2191 | <property name="text"> | ||
| 2192 | <string notr="true">T</string> | ||
| 2193 | </property> | ||
| 2194 | </widget> | ||
| 2195 | </item> | ||
| 2196 | <item row="2" column="9"> | ||
| 2197 | <widget class="QPushButton" name="button_o_shift"> | ||
| 2198 | <property name="sizePolicy"> | ||
| 2199 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 2200 | <horstretch>1</horstretch> | ||
| 2201 | <verstretch>1</verstretch> | ||
| 2202 | </sizepolicy> | ||
| 2203 | </property> | ||
| 2204 | <property name="font"> | ||
| 2205 | <font> | ||
| 2206 | <pointsize>28</pointsize> | ||
| 2207 | </font> | ||
| 2208 | </property> | ||
| 2209 | <property name="text"> | ||
| 2210 | <string notr="true">O</string> | ||
| 2211 | </property> | ||
| 2212 | </widget> | ||
| 2213 | </item> | ||
| 2214 | <item row="2" column="10"> | ||
| 2215 | <widget class="QPushButton" name="button_p_shift"> | ||
| 2216 | <property name="sizePolicy"> | ||
| 2217 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 2218 | <horstretch>1</horstretch> | ||
| 2219 | <verstretch>1</verstretch> | ||
| 2220 | </sizepolicy> | ||
| 2221 | </property> | ||
| 2222 | <property name="font"> | ||
| 2223 | <font> | ||
| 2224 | <pointsize>28</pointsize> | ||
| 2225 | </font> | ||
| 2226 | </property> | ||
| 2227 | <property name="text"> | ||
| 2228 | <string notr="true">P</string> | ||
| 2229 | </property> | ||
| 2230 | </widget> | ||
| 2231 | </item> | ||
| 2232 | <item row="2" column="8"> | ||
| 2233 | <widget class="QPushButton" name="button_i_shift"> | ||
| 2234 | <property name="sizePolicy"> | ||
| 2235 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 2236 | <horstretch>1</horstretch> | ||
| 2237 | <verstretch>1</verstretch> | ||
| 2238 | </sizepolicy> | ||
| 2239 | </property> | ||
| 2240 | <property name="font"> | ||
| 2241 | <font> | ||
| 2242 | <pointsize>28</pointsize> | ||
| 2243 | </font> | ||
| 2244 | </property> | ||
| 2245 | <property name="text"> | ||
| 2246 | <string notr="true">I</string> | ||
| 2247 | </property> | ||
| 2248 | </widget> | ||
| 2249 | </item> | ||
| 2250 | <item row="3" column="1"> | ||
| 2251 | <widget class="QPushButton" name="button_a_shift"> | ||
| 2252 | <property name="sizePolicy"> | ||
| 2253 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 2254 | <horstretch>1</horstretch> | ||
| 2255 | <verstretch>1</verstretch> | ||
| 2256 | </sizepolicy> | ||
| 2257 | </property> | ||
| 2258 | <property name="font"> | ||
| 2259 | <font> | ||
| 2260 | <pointsize>28</pointsize> | ||
| 2261 | </font> | ||
| 2262 | </property> | ||
| 2263 | <property name="text"> | ||
| 2264 | <string notr="true">A</string> | ||
| 2265 | </property> | ||
| 2266 | </widget> | ||
| 2267 | </item> | ||
| 2268 | <item row="3" column="2"> | ||
| 2269 | <widget class="QPushButton" name="button_s_shift"> | ||
| 2270 | <property name="sizePolicy"> | ||
| 2271 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 2272 | <horstretch>1</horstretch> | ||
| 2273 | <verstretch>1</verstretch> | ||
| 2274 | </sizepolicy> | ||
| 2275 | </property> | ||
| 2276 | <property name="font"> | ||
| 2277 | <font> | ||
| 2278 | <pointsize>28</pointsize> | ||
| 2279 | </font> | ||
| 2280 | </property> | ||
| 2281 | <property name="text"> | ||
| 2282 | <string notr="true">S</string> | ||
| 2283 | </property> | ||
| 2284 | </widget> | ||
| 2285 | </item> | ||
| 2286 | <item row="3" column="3"> | ||
| 2287 | <widget class="QPushButton" name="button_d_shift"> | ||
| 2288 | <property name="sizePolicy"> | ||
| 2289 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 2290 | <horstretch>1</horstretch> | ||
| 2291 | <verstretch>1</verstretch> | ||
| 2292 | </sizepolicy> | ||
| 2293 | </property> | ||
| 2294 | <property name="font"> | ||
| 2295 | <font> | ||
| 2296 | <pointsize>28</pointsize> | ||
| 2297 | </font> | ||
| 2298 | </property> | ||
| 2299 | <property name="text"> | ||
| 2300 | <string notr="true">D</string> | ||
| 2301 | </property> | ||
| 2302 | </widget> | ||
| 2303 | </item> | ||
| 2304 | <item row="3" column="4"> | ||
| 2305 | <widget class="QPushButton" name="button_f_shift"> | ||
| 2306 | <property name="sizePolicy"> | ||
| 2307 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 2308 | <horstretch>1</horstretch> | ||
| 2309 | <verstretch>1</verstretch> | ||
| 2310 | </sizepolicy> | ||
| 2311 | </property> | ||
| 2312 | <property name="font"> | ||
| 2313 | <font> | ||
| 2314 | <pointsize>28</pointsize> | ||
| 2315 | </font> | ||
| 2316 | </property> | ||
| 2317 | <property name="text"> | ||
| 2318 | <string notr="true">F</string> | ||
| 2319 | </property> | ||
| 2320 | </widget> | ||
| 2321 | </item> | ||
| 2322 | <item row="3" column="6"> | ||
| 2323 | <widget class="QPushButton" name="button_h_shift"> | ||
| 2324 | <property name="sizePolicy"> | ||
| 2325 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 2326 | <horstretch>1</horstretch> | ||
| 2327 | <verstretch>1</verstretch> | ||
| 2328 | </sizepolicy> | ||
| 2329 | </property> | ||
| 2330 | <property name="font"> | ||
| 2331 | <font> | ||
| 2332 | <pointsize>28</pointsize> | ||
| 2333 | </font> | ||
| 2334 | </property> | ||
| 2335 | <property name="text"> | ||
| 2336 | <string notr="true">H</string> | ||
| 2337 | </property> | ||
| 2338 | </widget> | ||
| 2339 | </item> | ||
| 2340 | <item row="3" column="7"> | ||
| 2341 | <widget class="QPushButton" name="button_j_shift"> | ||
| 2342 | <property name="sizePolicy"> | ||
| 2343 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 2344 | <horstretch>1</horstretch> | ||
| 2345 | <verstretch>1</verstretch> | ||
| 2346 | </sizepolicy> | ||
| 2347 | </property> | ||
| 2348 | <property name="font"> | ||
| 2349 | <font> | ||
| 2350 | <pointsize>28</pointsize> | ||
| 2351 | </font> | ||
| 2352 | </property> | ||
| 2353 | <property name="text"> | ||
| 2354 | <string notr="true">J</string> | ||
| 2355 | </property> | ||
| 2356 | </widget> | ||
| 2357 | </item> | ||
| 2358 | <item row="3" column="5"> | ||
| 2359 | <widget class="QPushButton" name="button_g_shift"> | ||
| 2360 | <property name="sizePolicy"> | ||
| 2361 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 2362 | <horstretch>1</horstretch> | ||
| 2363 | <verstretch>1</verstretch> | ||
| 2364 | </sizepolicy> | ||
| 2365 | </property> | ||
| 2366 | <property name="font"> | ||
| 2367 | <font> | ||
| 2368 | <pointsize>28</pointsize> | ||
| 2369 | </font> | ||
| 2370 | </property> | ||
| 2371 | <property name="text"> | ||
| 2372 | <string notr="true">G</string> | ||
| 2373 | </property> | ||
| 2374 | </widget> | ||
| 2375 | </item> | ||
| 2376 | <item row="3" column="8"> | ||
| 2377 | <widget class="QPushButton" name="button_k_shift"> | ||
| 2378 | <property name="sizePolicy"> | ||
| 2379 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 2380 | <horstretch>1</horstretch> | ||
| 2381 | <verstretch>1</verstretch> | ||
| 2382 | </sizepolicy> | ||
| 2383 | </property> | ||
| 2384 | <property name="font"> | ||
| 2385 | <font> | ||
| 2386 | <pointsize>28</pointsize> | ||
| 2387 | </font> | ||
| 2388 | </property> | ||
| 2389 | <property name="text"> | ||
| 2390 | <string notr="true">K</string> | ||
| 2391 | </property> | ||
| 2392 | </widget> | ||
| 2393 | </item> | ||
| 2394 | <item row="3" column="9"> | ||
| 2395 | <widget class="QPushButton" name="button_l_shift"> | ||
| 2396 | <property name="sizePolicy"> | ||
| 2397 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 2398 | <horstretch>1</horstretch> | ||
| 2399 | <verstretch>1</verstretch> | ||
| 2400 | </sizepolicy> | ||
| 2401 | </property> | ||
| 2402 | <property name="font"> | ||
| 2403 | <font> | ||
| 2404 | <pointsize>28</pointsize> | ||
| 2405 | </font> | ||
| 2406 | </property> | ||
| 2407 | <property name="text"> | ||
| 2408 | <string notr="true">L</string> | ||
| 2409 | </property> | ||
| 2410 | </widget> | ||
| 2411 | </item> | ||
| 2412 | <item row="3" column="10"> | ||
| 2413 | <widget class="QPushButton" name="button_semicolon"> | ||
| 2414 | <property name="sizePolicy"> | ||
| 2415 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 2416 | <horstretch>1</horstretch> | ||
| 2417 | <verstretch>1</verstretch> | ||
| 2418 | </sizepolicy> | ||
| 2419 | </property> | ||
| 2420 | <property name="font"> | ||
| 2421 | <font> | ||
| 2422 | <pointsize>28</pointsize> | ||
| 2423 | </font> | ||
| 2424 | </property> | ||
| 2425 | <property name="text"> | ||
| 2426 | <string notr="true">;</string> | ||
| 2427 | </property> | ||
| 2428 | </widget> | ||
| 2429 | </item> | ||
| 2430 | <item row="2" column="12" rowspan="2"> | ||
| 2431 | <widget class="QPushButton" name="button_return_shift"> | ||
| 2432 | <property name="sizePolicy"> | ||
| 2433 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 2434 | <horstretch>1</horstretch> | ||
| 2435 | <verstretch>1</verstretch> | ||
| 2436 | </sizepolicy> | ||
| 2437 | </property> | ||
| 2438 | <property name="font"> | ||
| 2439 | <font> | ||
| 2440 | <pointsize>18</pointsize> | ||
| 2441 | </font> | ||
| 2442 | </property> | ||
| 2443 | <property name="text"> | ||
| 2444 | <string notr="true">Return</string> | ||
| 2445 | </property> | ||
| 2446 | </widget> | ||
| 2447 | </item> | ||
| 2448 | <item row="4" column="12" rowspan="2"> | ||
| 2449 | <widget class="QPushButton" name="button_ok_shift"> | ||
| 2450 | <property name="sizePolicy"> | ||
| 2451 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 2452 | <horstretch>1</horstretch> | ||
| 2453 | <verstretch>1</verstretch> | ||
| 2454 | </sizepolicy> | ||
| 2455 | </property> | ||
| 2456 | <property name="font"> | ||
| 2457 | <font> | ||
| 2458 | <pointsize>18</pointsize> | ||
| 2459 | </font> | ||
| 2460 | </property> | ||
| 2461 | <property name="text"> | ||
| 2462 | <string notr="true">OK</string> | ||
| 2463 | </property> | ||
| 2464 | </widget> | ||
| 2465 | </item> | ||
| 2466 | <item row="4" column="1"> | ||
| 2467 | <widget class="QPushButton" name="button_z_shift"> | ||
| 2468 | <property name="sizePolicy"> | ||
| 2469 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 2470 | <horstretch>1</horstretch> | ||
| 2471 | <verstretch>1</verstretch> | ||
| 2472 | </sizepolicy> | ||
| 2473 | </property> | ||
| 2474 | <property name="font"> | ||
| 2475 | <font> | ||
| 2476 | <pointsize>28</pointsize> | ||
| 2477 | </font> | ||
| 2478 | </property> | ||
| 2479 | <property name="text"> | ||
| 2480 | <string notr="true">Z</string> | ||
| 2481 | </property> | ||
| 2482 | </widget> | ||
| 2483 | </item> | ||
| 2484 | <item row="4" column="3"> | ||
| 2485 | <widget class="QPushButton" name="button_c_shift"> | ||
| 2486 | <property name="sizePolicy"> | ||
| 2487 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 2488 | <horstretch>1</horstretch> | ||
| 2489 | <verstretch>1</verstretch> | ||
| 2490 | </sizepolicy> | ||
| 2491 | </property> | ||
| 2492 | <property name="font"> | ||
| 2493 | <font> | ||
| 2494 | <pointsize>28</pointsize> | ||
| 2495 | </font> | ||
| 2496 | </property> | ||
| 2497 | <property name="text"> | ||
| 2498 | <string notr="true">C</string> | ||
| 2499 | </property> | ||
| 2500 | </widget> | ||
| 2501 | </item> | ||
| 2502 | <item row="4" column="2"> | ||
| 2503 | <widget class="QPushButton" name="button_x_shift"> | ||
| 2504 | <property name="sizePolicy"> | ||
| 2505 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 2506 | <horstretch>1</horstretch> | ||
| 2507 | <verstretch>1</verstretch> | ||
| 2508 | </sizepolicy> | ||
| 2509 | </property> | ||
| 2510 | <property name="font"> | ||
| 2511 | <font> | ||
| 2512 | <pointsize>28</pointsize> | ||
| 2513 | </font> | ||
| 2514 | </property> | ||
| 2515 | <property name="text"> | ||
| 2516 | <string notr="true">X</string> | ||
| 2517 | </property> | ||
| 2518 | </widget> | ||
| 2519 | </item> | ||
| 2520 | <item row="4" column="4"> | ||
| 2521 | <widget class="QPushButton" name="button_v_shift"> | ||
| 2522 | <property name="sizePolicy"> | ||
| 2523 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 2524 | <horstretch>1</horstretch> | ||
| 2525 | <verstretch>1</verstretch> | ||
| 2526 | </sizepolicy> | ||
| 2527 | </property> | ||
| 2528 | <property name="font"> | ||
| 2529 | <font> | ||
| 2530 | <pointsize>28</pointsize> | ||
| 2531 | </font> | ||
| 2532 | </property> | ||
| 2533 | <property name="text"> | ||
| 2534 | <string notr="true">V</string> | ||
| 2535 | </property> | ||
| 2536 | </widget> | ||
| 2537 | </item> | ||
| 2538 | <item row="4" column="7"> | ||
| 2539 | <widget class="QPushButton" name="button_m_shift"> | ||
| 2540 | <property name="sizePolicy"> | ||
| 2541 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 2542 | <horstretch>1</horstretch> | ||
| 2543 | <verstretch>1</verstretch> | ||
| 2544 | </sizepolicy> | ||
| 2545 | </property> | ||
| 2546 | <property name="font"> | ||
| 2547 | <font> | ||
| 2548 | <pointsize>28</pointsize> | ||
| 2549 | </font> | ||
| 2550 | </property> | ||
| 2551 | <property name="text"> | ||
| 2552 | <string notr="true">M</string> | ||
| 2553 | </property> | ||
| 2554 | </widget> | ||
| 2555 | </item> | ||
| 2556 | <item row="4" column="8"> | ||
| 2557 | <widget class="QPushButton" name="button_less_than"> | ||
| 2558 | <property name="sizePolicy"> | ||
| 2559 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 2560 | <horstretch>1</horstretch> | ||
| 2561 | <verstretch>1</verstretch> | ||
| 2562 | </sizepolicy> | ||
| 2563 | </property> | ||
| 2564 | <property name="font"> | ||
| 2565 | <font> | ||
| 2566 | <pointsize>28</pointsize> | ||
| 2567 | </font> | ||
| 2568 | </property> | ||
| 2569 | <property name="text"> | ||
| 2570 | <string notr="true"><</string> | ||
| 2571 | </property> | ||
| 2572 | </widget> | ||
| 2573 | </item> | ||
| 2574 | <item row="4" column="6"> | ||
| 2575 | <widget class="QPushButton" name="button_n_shift"> | ||
| 2576 | <property name="sizePolicy"> | ||
| 2577 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 2578 | <horstretch>1</horstretch> | ||
| 2579 | <verstretch>1</verstretch> | ||
| 2580 | </sizepolicy> | ||
| 2581 | </property> | ||
| 2582 | <property name="font"> | ||
| 2583 | <font> | ||
| 2584 | <pointsize>28</pointsize> | ||
| 2585 | </font> | ||
| 2586 | </property> | ||
| 2587 | <property name="text"> | ||
| 2588 | <string notr="true">N</string> | ||
| 2589 | </property> | ||
| 2590 | </widget> | ||
| 2591 | </item> | ||
| 2592 | <item row="4" column="5"> | ||
| 2593 | <widget class="QPushButton" name="button_b_shift"> | ||
| 2594 | <property name="sizePolicy"> | ||
| 2595 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 2596 | <horstretch>1</horstretch> | ||
| 2597 | <verstretch>1</verstretch> | ||
| 2598 | </sizepolicy> | ||
| 2599 | </property> | ||
| 2600 | <property name="font"> | ||
| 2601 | <font> | ||
| 2602 | <pointsize>28</pointsize> | ||
| 2603 | </font> | ||
| 2604 | </property> | ||
| 2605 | <property name="text"> | ||
| 2606 | <string notr="true">B</string> | ||
| 2607 | </property> | ||
| 2608 | </widget> | ||
| 2609 | </item> | ||
| 2610 | <item row="5" column="1" colspan="2"> | ||
| 2611 | <widget class="QPushButton" name="button_shift_shift"> | ||
| 2612 | <property name="sizePolicy"> | ||
| 2613 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 2614 | <horstretch>1</horstretch> | ||
| 2615 | <verstretch>1</verstretch> | ||
| 2616 | </sizepolicy> | ||
| 2617 | </property> | ||
| 2618 | <property name="font"> | ||
| 2619 | <font> | ||
| 2620 | <pointsize>18</pointsize> | ||
| 2621 | </font> | ||
| 2622 | </property> | ||
| 2623 | <property name="text"> | ||
| 2624 | <string notr="true"/> | ||
| 2625 | </property> | ||
| 2626 | <property name="checkable"> | ||
| 2627 | <bool>true</bool> | ||
| 2628 | </property> | ||
| 2629 | <property name="checked"> | ||
| 2630 | <bool>false</bool> | ||
| 2631 | </property> | ||
| 2632 | </widget> | ||
| 2633 | </item> | ||
| 2634 | <item row="4" column="10"> | ||
| 2635 | <widget class="QPushButton" name="button_plus"> | ||
| 2636 | <property name="sizePolicy"> | ||
| 2637 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 2638 | <horstretch>1</horstretch> | ||
| 2639 | <verstretch>1</verstretch> | ||
| 2640 | </sizepolicy> | ||
| 2641 | </property> | ||
| 2642 | <property name="font"> | ||
| 2643 | <font> | ||
| 2644 | <pointsize>28</pointsize> | ||
| 2645 | </font> | ||
| 2646 | </property> | ||
| 2647 | <property name="text"> | ||
| 2648 | <string notr="true">+</string> | ||
| 2649 | </property> | ||
| 2650 | </widget> | ||
| 2651 | </item> | ||
| 2652 | <item row="4" column="9"> | ||
| 2653 | <widget class="QPushButton" name="button_greater_than"> | ||
| 2654 | <property name="sizePolicy"> | ||
| 2655 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 2656 | <horstretch>1</horstretch> | ||
| 2657 | <verstretch>1</verstretch> | ||
| 2658 | </sizepolicy> | ||
| 2659 | </property> | ||
| 2660 | <property name="font"> | ||
| 2661 | <font> | ||
| 2662 | <pointsize>28</pointsize> | ||
| 2663 | </font> | ||
| 2664 | </property> | ||
| 2665 | <property name="text"> | ||
| 2666 | <string notr="true">></string> | ||
| 2667 | </property> | ||
| 2668 | </widget> | ||
| 2669 | </item> | ||
| 2670 | <item row="1" column="1"> | ||
| 2671 | <widget class="QPushButton" name="button_hash"> | ||
| 2672 | <property name="sizePolicy"> | ||
| 2673 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 2674 | <horstretch>1</horstretch> | ||
| 2675 | <verstretch>1</verstretch> | ||
| 2676 | </sizepolicy> | ||
| 2677 | </property> | ||
| 2678 | <property name="font"> | ||
| 2679 | <font> | ||
| 2680 | <pointsize>28</pointsize> | ||
| 2681 | </font> | ||
| 2682 | </property> | ||
| 2683 | <property name="text"> | ||
| 2684 | <string notr="true">#</string> | ||
| 2685 | </property> | ||
| 2686 | </widget> | ||
| 2687 | </item> | ||
| 2688 | <item row="1" column="3"> | ||
| 2689 | <widget class="QPushButton" name="button_right_bracket"> | ||
| 2690 | <property name="sizePolicy"> | ||
| 2691 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 2692 | <horstretch>1</horstretch> | ||
| 2693 | <verstretch>1</verstretch> | ||
| 2694 | </sizepolicy> | ||
| 2695 | </property> | ||
| 2696 | <property name="font"> | ||
| 2697 | <font> | ||
| 2698 | <pointsize>28</pointsize> | ||
| 2699 | </font> | ||
| 2700 | </property> | ||
| 2701 | <property name="text"> | ||
| 2702 | <string notr="true">]</string> | ||
| 2703 | </property> | ||
| 2704 | </widget> | ||
| 2705 | </item> | ||
| 2706 | <item row="1" column="4"> | ||
| 2707 | <widget class="QPushButton" name="button_dollar"> | ||
| 2708 | <property name="sizePolicy"> | ||
| 2709 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 2710 | <horstretch>1</horstretch> | ||
| 2711 | <verstretch>1</verstretch> | ||
| 2712 | </sizepolicy> | ||
| 2713 | </property> | ||
| 2714 | <property name="font"> | ||
| 2715 | <font> | ||
| 2716 | <pointsize>28</pointsize> | ||
| 2717 | </font> | ||
| 2718 | </property> | ||
| 2719 | <property name="text"> | ||
| 2720 | <string notr="true">$</string> | ||
| 2721 | </property> | ||
| 2722 | </widget> | ||
| 2723 | </item> | ||
| 2724 | <item row="1" column="2"> | ||
| 2725 | <widget class="QPushButton" name="button_left_bracket"> | ||
| 2726 | <property name="sizePolicy"> | ||
| 2727 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 2728 | <horstretch>1</horstretch> | ||
| 2729 | <verstretch>1</verstretch> | ||
| 2730 | </sizepolicy> | ||
| 2731 | </property> | ||
| 2732 | <property name="font"> | ||
| 2733 | <font> | ||
| 2734 | <pointsize>28</pointsize> | ||
| 2735 | </font> | ||
| 2736 | </property> | ||
| 2737 | <property name="text"> | ||
| 2738 | <string notr="true">[</string> | ||
| 2739 | </property> | ||
| 2740 | </widget> | ||
| 2741 | </item> | ||
| 2742 | <item row="1" column="6"> | ||
| 2743 | <widget class="QPushButton" name="button_circumflex"> | ||
| 2744 | <property name="sizePolicy"> | ||
| 2745 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 2746 | <horstretch>1</horstretch> | ||
| 2747 | <verstretch>1</verstretch> | ||
| 2748 | </sizepolicy> | ||
| 2749 | </property> | ||
| 2750 | <property name="font"> | ||
| 2751 | <font> | ||
| 2752 | <pointsize>28</pointsize> | ||
| 2753 | </font> | ||
| 2754 | </property> | ||
| 2755 | <property name="text"> | ||
| 2756 | <string notr="true">^</string> | ||
| 2757 | </property> | ||
| 2758 | </widget> | ||
| 2759 | </item> | ||
| 2760 | <item row="1" column="5"> | ||
| 2761 | <widget class="QPushButton" name="button_percent"> | ||
| 2762 | <property name="sizePolicy"> | ||
| 2763 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 2764 | <horstretch>1</horstretch> | ||
| 2765 | <verstretch>1</verstretch> | ||
| 2766 | </sizepolicy> | ||
| 2767 | </property> | ||
| 2768 | <property name="font"> | ||
| 2769 | <font> | ||
| 2770 | <pointsize>28</pointsize> | ||
| 2771 | </font> | ||
| 2772 | </property> | ||
| 2773 | <property name="text"> | ||
| 2774 | <string notr="true">%</string> | ||
| 2775 | </property> | ||
| 2776 | </widget> | ||
| 2777 | </item> | ||
| 2778 | <item row="5" column="3" colspan="9"> | ||
| 2779 | <widget class="QPushButton" name="button_space_shift"> | ||
| 2780 | <property name="sizePolicy"> | ||
| 2781 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 2782 | <horstretch>1</horstretch> | ||
| 2783 | <verstretch>1</verstretch> | ||
| 2784 | </sizepolicy> | ||
| 2785 | </property> | ||
| 2786 | <property name="font"> | ||
| 2787 | <font> | ||
| 2788 | <pointsize>18</pointsize> | ||
| 2789 | </font> | ||
| 2790 | </property> | ||
| 2791 | <property name="text"> | ||
| 2792 | <string notr="true">Space</string> | ||
| 2793 | </property> | ||
| 2794 | </widget> | ||
| 2795 | </item> | ||
| 2796 | <item row="1" column="12"> | ||
| 2797 | <widget class="QPushButton" name="button_backspace_shift"> | ||
| 2798 | <property name="sizePolicy"> | ||
| 2799 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 2800 | <horstretch>1</horstretch> | ||
| 2801 | <verstretch>1</verstretch> | ||
| 2802 | </sizepolicy> | ||
| 2803 | </property> | ||
| 2804 | <property name="font"> | ||
| 2805 | <font> | ||
| 2806 | <pointsize>18</pointsize> | ||
| 2807 | </font> | ||
| 2808 | </property> | ||
| 2809 | <property name="text"> | ||
| 2810 | <string notr="true"/> | ||
| 2811 | </property> | ||
| 2812 | </widget> | ||
| 2813 | </item> | ||
| 2814 | <item row="1" column="0"> | ||
| 2815 | <spacer name="horizontalSpacer_33"> | ||
| 2816 | <property name="orientation"> | ||
| 2817 | <enum>Qt::Horizontal</enum> | ||
| 2818 | </property> | ||
| 2819 | <property name="sizeHint" stdset="0"> | ||
| 2820 | <size> | ||
| 2821 | <width>40</width> | ||
| 2822 | <height>20</height> | ||
| 2823 | </size> | ||
| 2824 | </property> | ||
| 2825 | </spacer> | ||
| 2826 | </item> | ||
| 2827 | <item row="0" column="1"> | ||
| 2828 | <spacer name="verticalSpacer_6"> | ||
| 2829 | <property name="orientation"> | ||
| 2830 | <enum>Qt::Vertical</enum> | ||
| 2831 | </property> | ||
| 2832 | <property name="sizeHint" stdset="0"> | ||
| 2833 | <size> | ||
| 2834 | <width>20</width> | ||
| 2835 | <height>0</height> | ||
| 2836 | </size> | ||
| 2837 | </property> | ||
| 2838 | </spacer> | ||
| 2839 | </item> | ||
| 2840 | <item row="1" column="13"> | ||
| 2841 | <spacer name="horizontalSpacer_34"> | ||
| 2842 | <property name="orientation"> | ||
| 2843 | <enum>Qt::Horizontal</enum> | ||
| 2844 | </property> | ||
| 2845 | <property name="sizeHint" stdset="0"> | ||
| 2846 | <size> | ||
| 2847 | <width>40</width> | ||
| 2848 | <height>20</height> | ||
| 2849 | </size> | ||
| 2850 | </property> | ||
| 2851 | </spacer> | ||
| 2852 | </item> | ||
| 2853 | </layout> | ||
| 2854 | </item> | ||
| 2855 | </layout> | ||
| 2856 | </widget> | ||
| 2857 | <widget class="QWidget" name="numOSK"> | ||
| 2858 | <layout class="QVBoxLayout" name="graphicsTabVerticalLayout"> | ||
| 2859 | <property name="leftMargin"> | ||
| 2860 | <number>0</number> | ||
| 2861 | </property> | ||
| 2862 | <property name="topMargin"> | ||
| 2863 | <number>0</number> | ||
| 2864 | </property> | ||
| 2865 | <property name="rightMargin"> | ||
| 2866 | <number>0</number> | ||
| 2867 | </property> | ||
| 2868 | <property name="bottomMargin"> | ||
| 2869 | <number>0</number> | ||
| 2870 | </property> | ||
| 2871 | <item> | ||
| 2872 | <layout class="QGridLayout" name="kbOSKnum" rowstretch="18,63,63,63,63,10,70" columnstretch="54,307,186,186,186,120,187,54"> | ||
| 2873 | <property name="leftMargin"> | ||
| 2874 | <number>0</number> | ||
| 2875 | </property> | ||
| 2876 | <property name="rightMargin"> | ||
| 2877 | <number>0</number> | ||
| 2878 | </property> | ||
| 2879 | <property name="spacing"> | ||
| 2880 | <number>0</number> | ||
| 2881 | </property> | ||
| 2882 | <item row="1" column="5"> | ||
| 2883 | <widget class="QPushButton" name="button_backspace_num"> | ||
| 2884 | <property name="sizePolicy"> | ||
| 2885 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 2886 | <horstretch>1</horstretch> | ||
| 2887 | <verstretch>1</verstretch> | ||
| 2888 | </sizepolicy> | ||
| 2889 | </property> | ||
| 2890 | <property name="font"> | ||
| 2891 | <font> | ||
| 2892 | <pointsize>18</pointsize> | ||
| 2893 | </font> | ||
| 2894 | </property> | ||
| 2895 | <property name="text"> | ||
| 2896 | <string notr="true"/> | ||
| 2897 | </property> | ||
| 2898 | </widget> | ||
| 2899 | </item> | ||
| 2900 | <item row="1" column="6"> | ||
| 2901 | <spacer name="horizontalSpacer_35"> | ||
| 2902 | <property name="orientation"> | ||
| 2903 | <enum>Qt::Horizontal</enum> | ||
| 2904 | </property> | ||
| 2905 | <property name="sizeHint" stdset="0"> | ||
| 2906 | <size> | ||
| 2907 | <width>40</width> | ||
| 2908 | <height>20</height> | ||
| 2909 | </size> | ||
| 2910 | </property> | ||
| 2911 | </spacer> | ||
| 2912 | </item> | ||
| 2913 | <item row="1" column="1"> | ||
| 2914 | <spacer name="horizontalSpacer_36"> | ||
| 2915 | <property name="orientation"> | ||
| 2916 | <enum>Qt::Horizontal</enum> | ||
| 2917 | </property> | ||
| 2918 | <property name="sizeHint" stdset="0"> | ||
| 2919 | <size> | ||
| 2920 | <width>40</width> | ||
| 2921 | <height>20</height> | ||
| 2922 | </size> | ||
| 2923 | </property> | ||
| 2924 | </spacer> | ||
| 2925 | </item> | ||
| 2926 | <item row="0" column="2"> | ||
| 2927 | <spacer name="verticalSpacer_7"> | ||
| 2928 | <property name="orientation"> | ||
| 2929 | <enum>Qt::Vertical</enum> | ||
| 2930 | </property> | ||
| 2931 | <property name="sizeHint" stdset="0"> | ||
| 2932 | <size> | ||
| 2933 | <width>20</width> | ||
| 2934 | <height>0</height> | ||
| 2935 | </size> | ||
| 2936 | </property> | ||
| 2937 | </spacer> | ||
| 2938 | </item> | ||
| 2939 | <item row="6" column="1" colspan="6"> | ||
| 2940 | <widget class="QWidget" name="legendOSKnum" native="true"> | ||
| 2941 | <layout class="QHBoxLayout" name="horizontalLayout_6" stretch="25,70,601,25,12,22,41,25,12,22,41,29,12,69,37,29,12,56,30"> | ||
| 2942 | <property name="spacing"> | ||
| 2943 | <number>0</number> | ||
| 2944 | </property> | ||
| 2945 | <property name="leftMargin"> | ||
| 2946 | <number>0</number> | ||
| 2947 | </property> | ||
| 2948 | <property name="topMargin"> | ||
| 2949 | <number>0</number> | ||
| 2950 | </property> | ||
| 2951 | <property name="rightMargin"> | ||
| 2952 | <number>0</number> | ||
| 2953 | </property> | ||
| 2954 | <property name="bottomMargin"> | ||
| 2955 | <number>0</number> | ||
| 2956 | </property> | ||
| 2957 | <item> | ||
| 2958 | <spacer name="horizontalSpacer_48"> | ||
| 2959 | <property name="orientation"> | ||
| 2960 | <enum>Qt::Horizontal</enum> | ||
| 2961 | </property> | ||
| 2962 | <property name="sizeHint" stdset="0"> | ||
| 2963 | <size> | ||
| 2964 | <width>40</width> | ||
| 2965 | <height>20</height> | ||
| 2966 | </size> | ||
| 2967 | </property> | ||
| 2968 | </spacer> | ||
| 2969 | </item> | ||
| 2970 | <item> | ||
| 2971 | <widget class="QWidget" name="icon_controller_num" native="true"> | ||
| 2972 | <property name="styleSheet"> | ||
| 2973 | <string notr="true"/> | ||
| 2974 | </property> | ||
| 2975 | </widget> | ||
| 2976 | </item> | ||
| 2977 | <item> | ||
| 2978 | <spacer name="horizontalSpacer_38"> | ||
| 2979 | <property name="orientation"> | ||
| 2980 | <enum>Qt::Horizontal</enum> | ||
| 2981 | </property> | ||
| 2982 | <property name="sizeHint" stdset="0"> | ||
| 2983 | <size> | ||
| 2984 | <width>0</width> | ||
| 2985 | <height>20</height> | ||
| 2986 | </size> | ||
| 2987 | </property> | ||
| 2988 | </spacer> | ||
| 2989 | </item> | ||
| 2990 | <item> | ||
| 2991 | <widget class="QWidget" name="button_L_num" native="true"/> | ||
| 2992 | </item> | ||
| 2993 | <item> | ||
| 2994 | <spacer name="horizontalSpacer_39"> | ||
| 2995 | <property name="orientation"> | ||
| 2996 | <enum>Qt::Horizontal</enum> | ||
| 2997 | </property> | ||
| 2998 | <property name="sizeHint" stdset="0"> | ||
| 2999 | <size> | ||
| 3000 | <width>0</width> | ||
| 3001 | <height>20</height> | ||
| 3002 | </size> | ||
| 3003 | </property> | ||
| 3004 | </spacer> | ||
| 3005 | </item> | ||
| 3006 | <item> | ||
| 3007 | <widget class="QWidget" name="arrow_left_num" native="true"/> | ||
| 3008 | </item> | ||
| 3009 | <item> | ||
| 3010 | <spacer name="horizontalSpacer_40"> | ||
| 3011 | <property name="orientation"> | ||
| 3012 | <enum>Qt::Horizontal</enum> | ||
| 3013 | </property> | ||
| 3014 | <property name="sizeHint" stdset="0"> | ||
| 3015 | <size> | ||
| 3016 | <width>0</width> | ||
| 3017 | <height>20</height> | ||
| 3018 | </size> | ||
| 3019 | </property> | ||
| 3020 | </spacer> | ||
| 3021 | </item> | ||
| 3022 | <item> | ||
| 3023 | <widget class="QWidget" name="button_R_num" native="true"/> | ||
| 3024 | </item> | ||
| 3025 | <item> | ||
| 3026 | <spacer name="horizontalSpacer_41"> | ||
| 3027 | <property name="orientation"> | ||
| 3028 | <enum>Qt::Horizontal</enum> | ||
| 3029 | </property> | ||
| 3030 | <property name="sizeHint" stdset="0"> | ||
| 3031 | <size> | ||
| 3032 | <width>0</width> | ||
| 3033 | <height>20</height> | ||
| 3034 | </size> | ||
| 3035 | </property> | ||
| 3036 | </spacer> | ||
| 3037 | </item> | ||
| 3038 | <item> | ||
| 3039 | <widget class="QWidget" name="arrow_right_num" native="true"/> | ||
| 3040 | </item> | ||
| 3041 | <item> | ||
| 3042 | <spacer name="horizontalSpacer_42"> | ||
| 3043 | <property name="orientation"> | ||
| 3044 | <enum>Qt::Horizontal</enum> | ||
| 3045 | </property> | ||
| 3046 | <property name="sizeHint" stdset="0"> | ||
| 3047 | <size> | ||
| 3048 | <width>0</width> | ||
| 3049 | <height>20</height> | ||
| 3050 | </size> | ||
| 3051 | </property> | ||
| 3052 | </spacer> | ||
| 3053 | </item> | ||
| 3054 | <item> | ||
| 3055 | <widget class="QWidget" name="button_X_num" native="true"/> | ||
| 3056 | </item> | ||
| 3057 | <item> | ||
| 3058 | <spacer name="horizontalSpacer_43"> | ||
| 3059 | <property name="orientation"> | ||
| 3060 | <enum>Qt::Horizontal</enum> | ||
| 3061 | </property> | ||
| 3062 | <property name="sizeHint" stdset="0"> | ||
| 3063 | <size> | ||
| 3064 | <width>0</width> | ||
| 3065 | <height>20</height> | ||
| 3066 | </size> | ||
| 3067 | </property> | ||
| 3068 | </spacer> | ||
| 3069 | </item> | ||
| 3070 | <item> | ||
| 3071 | <widget class="QLabel" name="label_cancel_num"> | ||
| 3072 | <property name="font"> | ||
| 3073 | <font> | ||
| 3074 | <pointsize>18</pointsize> | ||
| 3075 | </font> | ||
| 3076 | </property> | ||
| 3077 | <property name="text"> | ||
| 3078 | <string notr="true">Cancel</string> | ||
| 3079 | </property> | ||
| 3080 | </widget> | ||
| 3081 | </item> | ||
| 3082 | <item> | ||
| 3083 | <spacer name="horizontalSpacer_44"> | ||
| 3084 | <property name="orientation"> | ||
| 3085 | <enum>Qt::Horizontal</enum> | ||
| 3086 | </property> | ||
| 3087 | <property name="sizeHint" stdset="0"> | ||
| 3088 | <size> | ||
| 3089 | <width>0</width> | ||
| 3090 | <height>20</height> | ||
| 3091 | </size> | ||
| 3092 | </property> | ||
| 3093 | </spacer> | ||
| 3094 | </item> | ||
| 3095 | <item> | ||
| 3096 | <widget class="QWidget" name="button_A_num" native="true"/> | ||
| 3097 | </item> | ||
| 3098 | <item> | ||
| 3099 | <spacer name="horizontalSpacer_45"> | ||
| 3100 | <property name="orientation"> | ||
| 3101 | <enum>Qt::Horizontal</enum> | ||
| 3102 | </property> | ||
| 3103 | <property name="sizeHint" stdset="0"> | ||
| 3104 | <size> | ||
| 3105 | <width>0</width> | ||
| 3106 | <height>20</height> | ||
| 3107 | </size> | ||
| 3108 | </property> | ||
| 3109 | </spacer> | ||
| 3110 | </item> | ||
| 3111 | <item> | ||
| 3112 | <widget class="QLabel" name="label_enter_num"> | ||
| 3113 | <property name="font"> | ||
| 3114 | <font> | ||
| 3115 | <pointsize>18</pointsize> | ||
| 3116 | </font> | ||
| 3117 | </property> | ||
| 3118 | <property name="text"> | ||
| 3119 | <string notr="true">Enter</string> | ||
| 3120 | </property> | ||
| 3121 | </widget> | ||
| 3122 | </item> | ||
| 3123 | <item> | ||
| 3124 | <spacer name="horizontalSpacer_46"> | ||
| 3125 | <property name="orientation"> | ||
| 3126 | <enum>Qt::Horizontal</enum> | ||
| 3127 | </property> | ||
| 3128 | <property name="sizeHint" stdset="0"> | ||
| 3129 | <size> | ||
| 3130 | <width>0</width> | ||
| 3131 | <height>20</height> | ||
| 3132 | </size> | ||
| 3133 | </property> | ||
| 3134 | </spacer> | ||
| 3135 | </item> | ||
| 3136 | </layout> | ||
| 3137 | </widget> | ||
| 3138 | </item> | ||
| 3139 | <item row="2" column="4"> | ||
| 3140 | <widget class="QPushButton" name="button_6_num"> | ||
| 3141 | <property name="sizePolicy"> | ||
| 3142 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 3143 | <horstretch>1</horstretch> | ||
| 3144 | <verstretch>1</verstretch> | ||
| 3145 | </sizepolicy> | ||
| 3146 | </property> | ||
| 3147 | <property name="font"> | ||
| 3148 | <font> | ||
| 3149 | <pointsize>28</pointsize> | ||
| 3150 | </font> | ||
| 3151 | </property> | ||
| 3152 | <property name="text"> | ||
| 3153 | <string notr="true">6</string> | ||
| 3154 | </property> | ||
| 3155 | </widget> | ||
| 3156 | </item> | ||
| 3157 | <item row="2" column="2"> | ||
| 3158 | <widget class="QPushButton" name="button_4_num"> | ||
| 3159 | <property name="sizePolicy"> | ||
| 3160 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 3161 | <horstretch>1</horstretch> | ||
| 3162 | <verstretch>1</verstretch> | ||
| 3163 | </sizepolicy> | ||
| 3164 | </property> | ||
| 3165 | <property name="font"> | ||
| 3166 | <font> | ||
| 3167 | <pointsize>28</pointsize> | ||
| 3168 | </font> | ||
| 3169 | </property> | ||
| 3170 | <property name="text"> | ||
| 3171 | <string notr="true">4</string> | ||
| 3172 | </property> | ||
| 3173 | </widget> | ||
| 3174 | </item> | ||
| 3175 | <item row="3" column="4"> | ||
| 3176 | <widget class="QPushButton" name="button_9_num"> | ||
| 3177 | <property name="sizePolicy"> | ||
| 3178 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 3179 | <horstretch>1</horstretch> | ||
| 3180 | <verstretch>1</verstretch> | ||
| 3181 | </sizepolicy> | ||
| 3182 | </property> | ||
| 3183 | <property name="font"> | ||
| 3184 | <font> | ||
| 3185 | <pointsize>28</pointsize> | ||
| 3186 | </font> | ||
| 3187 | </property> | ||
| 3188 | <property name="text"> | ||
| 3189 | <string notr="true">9</string> | ||
| 3190 | </property> | ||
| 3191 | </widget> | ||
| 3192 | </item> | ||
| 3193 | <item row="2" column="3"> | ||
| 3194 | <widget class="QPushButton" name="button_5_num"> | ||
| 3195 | <property name="sizePolicy"> | ||
| 3196 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 3197 | <horstretch>1</horstretch> | ||
| 3198 | <verstretch>1</verstretch> | ||
| 3199 | </sizepolicy> | ||
| 3200 | </property> | ||
| 3201 | <property name="font"> | ||
| 3202 | <font> | ||
| 3203 | <pointsize>28</pointsize> | ||
| 3204 | </font> | ||
| 3205 | </property> | ||
| 3206 | <property name="text"> | ||
| 3207 | <string notr="true">5</string> | ||
| 3208 | </property> | ||
| 3209 | </widget> | ||
| 3210 | </item> | ||
| 3211 | <item row="2" column="5" rowspan="3"> | ||
| 3212 | <widget class="QPushButton" name="button_ok_num"> | ||
| 3213 | <property name="sizePolicy"> | ||
| 3214 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 3215 | <horstretch>1</horstretch> | ||
| 3216 | <verstretch>1</verstretch> | ||
| 3217 | </sizepolicy> | ||
| 3218 | </property> | ||
| 3219 | <property name="font"> | ||
| 3220 | <font> | ||
| 3221 | <pointsize>18</pointsize> | ||
| 3222 | </font> | ||
| 3223 | </property> | ||
| 3224 | <property name="text"> | ||
| 3225 | <string notr="true">OK</string> | ||
| 3226 | </property> | ||
| 3227 | </widget> | ||
| 3228 | </item> | ||
| 3229 | <item row="3" column="2"> | ||
| 3230 | <widget class="QPushButton" name="button_7_num"> | ||
| 3231 | <property name="sizePolicy"> | ||
| 3232 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 3233 | <horstretch>1</horstretch> | ||
| 3234 | <verstretch>1</verstretch> | ||
| 3235 | </sizepolicy> | ||
| 3236 | </property> | ||
| 3237 | <property name="font"> | ||
| 3238 | <font> | ||
| 3239 | <pointsize>28</pointsize> | ||
| 3240 | </font> | ||
| 3241 | </property> | ||
| 3242 | <property name="text"> | ||
| 3243 | <string notr="true">7</string> | ||
| 3244 | </property> | ||
| 3245 | </widget> | ||
| 3246 | </item> | ||
| 3247 | <item row="3" column="3"> | ||
| 3248 | <widget class="QPushButton" name="button_8_num"> | ||
| 3249 | <property name="sizePolicy"> | ||
| 3250 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 3251 | <horstretch>1</horstretch> | ||
| 3252 | <verstretch>1</verstretch> | ||
| 3253 | </sizepolicy> | ||
| 3254 | </property> | ||
| 3255 | <property name="font"> | ||
| 3256 | <font> | ||
| 3257 | <pointsize>28</pointsize> | ||
| 3258 | </font> | ||
| 3259 | </property> | ||
| 3260 | <property name="text"> | ||
| 3261 | <string notr="true">8</string> | ||
| 3262 | </property> | ||
| 3263 | </widget> | ||
| 3264 | </item> | ||
| 3265 | <item row="1" column="3"> | ||
| 3266 | <widget class="QPushButton" name="button_2_num"> | ||
| 3267 | <property name="sizePolicy"> | ||
| 3268 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 3269 | <horstretch>1</horstretch> | ||
| 3270 | <verstretch>1</verstretch> | ||
| 3271 | </sizepolicy> | ||
| 3272 | </property> | ||
| 3273 | <property name="font"> | ||
| 3274 | <font> | ||
| 3275 | <pointsize>28</pointsize> | ||
| 3276 | </font> | ||
| 3277 | </property> | ||
| 3278 | <property name="text"> | ||
| 3279 | <string notr="true">2</string> | ||
| 3280 | </property> | ||
| 3281 | </widget> | ||
| 3282 | </item> | ||
| 3283 | <item row="1" column="2"> | ||
| 3284 | <widget class="QPushButton" name="button_1_num"> | ||
| 3285 | <property name="sizePolicy"> | ||
| 3286 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 3287 | <horstretch>1</horstretch> | ||
| 3288 | <verstretch>1</verstretch> | ||
| 3289 | </sizepolicy> | ||
| 3290 | </property> | ||
| 3291 | <property name="font"> | ||
| 3292 | <font> | ||
| 3293 | <pointsize>28</pointsize> | ||
| 3294 | </font> | ||
| 3295 | </property> | ||
| 3296 | <property name="text"> | ||
| 3297 | <string notr="true">1</string> | ||
| 3298 | </property> | ||
| 3299 | </widget> | ||
| 3300 | </item> | ||
| 3301 | <item row="4" column="3"> | ||
| 3302 | <widget class="QPushButton" name="button_0_num"> | ||
| 3303 | <property name="sizePolicy"> | ||
| 3304 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 3305 | <horstretch>1</horstretch> | ||
| 3306 | <verstretch>1</verstretch> | ||
| 3307 | </sizepolicy> | ||
| 3308 | </property> | ||
| 3309 | <property name="font"> | ||
| 3310 | <font> | ||
| 3311 | <pointsize>28</pointsize> | ||
| 3312 | </font> | ||
| 3313 | </property> | ||
| 3314 | <property name="text"> | ||
| 3315 | <string notr="true">0</string> | ||
| 3316 | </property> | ||
| 3317 | </widget> | ||
| 3318 | </item> | ||
| 3319 | <item row="1" column="4"> | ||
| 3320 | <widget class="QPushButton" name="button_3_num"> | ||
| 3321 | <property name="sizePolicy"> | ||
| 3322 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 3323 | <horstretch>1</horstretch> | ||
| 3324 | <verstretch>1</verstretch> | ||
| 3325 | </sizepolicy> | ||
| 3326 | </property> | ||
| 3327 | <property name="font"> | ||
| 3328 | <font> | ||
| 3329 | <pointsize>28</pointsize> | ||
| 3330 | </font> | ||
| 3331 | </property> | ||
| 3332 | <property name="text"> | ||
| 3333 | <string notr="true">3</string> | ||
| 3334 | </property> | ||
| 3335 | </widget> | ||
| 3336 | </item> | ||
| 3337 | <item row="1" column="0"> | ||
| 3338 | <spacer name="horizontalSpacer_37"> | ||
| 3339 | <property name="orientation"> | ||
| 3340 | <enum>Qt::Horizontal</enum> | ||
| 3341 | </property> | ||
| 3342 | <property name="sizeHint" stdset="0"> | ||
| 3343 | <size> | ||
| 3344 | <width>40</width> | ||
| 3345 | <height>20</height> | ||
| 3346 | </size> | ||
| 3347 | </property> | ||
| 3348 | </spacer> | ||
| 3349 | </item> | ||
| 3350 | <item row="1" column="7"> | ||
| 3351 | <spacer name="horizontalSpacer_47"> | ||
| 3352 | <property name="orientation"> | ||
| 3353 | <enum>Qt::Horizontal</enum> | ||
| 3354 | </property> | ||
| 3355 | <property name="sizeHint" stdset="0"> | ||
| 3356 | <size> | ||
| 3357 | <width>40</width> | ||
| 3358 | <height>20</height> | ||
| 3359 | </size> | ||
| 3360 | </property> | ||
| 3361 | </spacer> | ||
| 3362 | </item> | ||
| 3363 | <item row="5" column="3"> | ||
| 3364 | <spacer name="verticalSpacer_8"> | ||
| 3365 | <property name="orientation"> | ||
| 3366 | <enum>Qt::Vertical</enum> | ||
| 3367 | </property> | ||
| 3368 | <property name="sizeHint" stdset="0"> | ||
| 3369 | <size> | ||
| 3370 | <width>20</width> | ||
| 3371 | <height>0</height> | ||
| 3372 | </size> | ||
| 3373 | </property> | ||
| 3374 | </spacer> | ||
| 3375 | </item> | ||
| 3376 | </layout> | ||
| 3377 | </item> | ||
| 3378 | </layout> | ||
| 3379 | </widget> | ||
| 3380 | </widget> | ||
| 3381 | </item> | ||
| 3382 | </layout> | ||
| 3383 | </widget> | ||
| 3384 | </item> | ||
| 3385 | </layout> | ||
| 3386 | </widget> | ||
| 3387 | <tabstops> | ||
| 3388 | <tabstop>button_1</tabstop> | ||
| 3389 | <tabstop>button_2</tabstop> | ||
| 3390 | <tabstop>button_3</tabstop> | ||
| 3391 | <tabstop>button_4</tabstop> | ||
| 3392 | <tabstop>button_5</tabstop> | ||
| 3393 | <tabstop>button_6</tabstop> | ||
| 3394 | <tabstop>button_7</tabstop> | ||
| 3395 | <tabstop>button_8</tabstop> | ||
| 3396 | <tabstop>button_9</tabstop> | ||
| 3397 | <tabstop>button_0</tabstop> | ||
| 3398 | <tabstop>button_minus</tabstop> | ||
| 3399 | <tabstop>button_backspace</tabstop> | ||
| 3400 | <tabstop>button_q</tabstop> | ||
| 3401 | <tabstop>button_w</tabstop> | ||
| 3402 | <tabstop>button_e</tabstop> | ||
| 3403 | <tabstop>button_r</tabstop> | ||
| 3404 | <tabstop>button_t</tabstop> | ||
| 3405 | <tabstop>button_y</tabstop> | ||
| 3406 | <tabstop>button_u</tabstop> | ||
| 3407 | <tabstop>button_i</tabstop> | ||
| 3408 | <tabstop>button_o</tabstop> | ||
| 3409 | <tabstop>button_p</tabstop> | ||
| 3410 | <tabstop>button_slash</tabstop> | ||
| 3411 | <tabstop>button_return</tabstop> | ||
| 3412 | <tabstop>button_a</tabstop> | ||
| 3413 | <tabstop>button_s</tabstop> | ||
| 3414 | <tabstop>button_d</tabstop> | ||
| 3415 | <tabstop>button_f</tabstop> | ||
| 3416 | <tabstop>button_g</tabstop> | ||
| 3417 | <tabstop>button_h</tabstop> | ||
| 3418 | <tabstop>button_j</tabstop> | ||
| 3419 | <tabstop>button_k</tabstop> | ||
| 3420 | <tabstop>button_l</tabstop> | ||
| 3421 | <tabstop>button_colon</tabstop> | ||
| 3422 | <tabstop>button_apostrophe</tabstop> | ||
| 3423 | <tabstop>button_z</tabstop> | ||
| 3424 | <tabstop>button_x</tabstop> | ||
| 3425 | <tabstop>button_c</tabstop> | ||
| 3426 | <tabstop>button_v</tabstop> | ||
| 3427 | <tabstop>button_b</tabstop> | ||
| 3428 | <tabstop>button_n</tabstop> | ||
| 3429 | <tabstop>button_m</tabstop> | ||
| 3430 | <tabstop>button_comma</tabstop> | ||
| 3431 | <tabstop>button_dot</tabstop> | ||
| 3432 | <tabstop>button_question</tabstop> | ||
| 3433 | <tabstop>button_exclamation</tabstop> | ||
| 3434 | <tabstop>button_ok</tabstop> | ||
| 3435 | <tabstop>button_shift</tabstop> | ||
| 3436 | <tabstop>button_space</tabstop> | ||
| 3437 | <tabstop>button_hash</tabstop> | ||
| 3438 | <tabstop>button_left_bracket</tabstop> | ||
| 3439 | <tabstop>button_right_bracket</tabstop> | ||
| 3440 | <tabstop>button_dollar</tabstop> | ||
| 3441 | <tabstop>button_percent</tabstop> | ||
| 3442 | <tabstop>button_circumflex</tabstop> | ||
| 3443 | <tabstop>button_ampersand</tabstop> | ||
| 3444 | <tabstop>button_asterisk</tabstop> | ||
| 3445 | <tabstop>button_left_parenthesis</tabstop> | ||
| 3446 | <tabstop>button_right_parenthesis</tabstop> | ||
| 3447 | <tabstop>button_underscore</tabstop> | ||
| 3448 | <tabstop>button_backspace_shift</tabstop> | ||
| 3449 | <tabstop>button_q_shift</tabstop> | ||
| 3450 | <tabstop>button_w_shift</tabstop> | ||
| 3451 | <tabstop>button_e_shift</tabstop> | ||
| 3452 | <tabstop>button_r_shift</tabstop> | ||
| 3453 | <tabstop>button_t_shift</tabstop> | ||
| 3454 | <tabstop>button_y_shift</tabstop> | ||
| 3455 | <tabstop>button_u_shift</tabstop> | ||
| 3456 | <tabstop>button_i_shift</tabstop> | ||
| 3457 | <tabstop>button_o_shift</tabstop> | ||
| 3458 | <tabstop>button_p_shift</tabstop> | ||
| 3459 | <tabstop>button_at</tabstop> | ||
| 3460 | <tabstop>button_return_shift</tabstop> | ||
| 3461 | <tabstop>button_a_shift</tabstop> | ||
| 3462 | <tabstop>button_s_shift</tabstop> | ||
| 3463 | <tabstop>button_d_shift</tabstop> | ||
| 3464 | <tabstop>button_f_shift</tabstop> | ||
| 3465 | <tabstop>button_g_shift</tabstop> | ||
| 3466 | <tabstop>button_h_shift</tabstop> | ||
| 3467 | <tabstop>button_j_shift</tabstop> | ||
| 3468 | <tabstop>button_k_shift</tabstop> | ||
| 3469 | <tabstop>button_l_shift</tabstop> | ||
| 3470 | <tabstop>button_semicolon</tabstop> | ||
| 3471 | <tabstop>button_quotation</tabstop> | ||
| 3472 | <tabstop>button_z_shift</tabstop> | ||
| 3473 | <tabstop>button_x_shift</tabstop> | ||
| 3474 | <tabstop>button_c_shift</tabstop> | ||
| 3475 | <tabstop>button_v_shift</tabstop> | ||
| 3476 | <tabstop>button_b_shift</tabstop> | ||
| 3477 | <tabstop>button_n_shift</tabstop> | ||
| 3478 | <tabstop>button_m_shift</tabstop> | ||
| 3479 | <tabstop>button_less_than</tabstop> | ||
| 3480 | <tabstop>button_greater_than</tabstop> | ||
| 3481 | <tabstop>button_plus</tabstop> | ||
| 3482 | <tabstop>button_equal</tabstop> | ||
| 3483 | <tabstop>button_ok_shift</tabstop> | ||
| 3484 | <tabstop>button_shift_shift</tabstop> | ||
| 3485 | <tabstop>button_space_shift</tabstop> | ||
| 3486 | <tabstop>button_1_num</tabstop> | ||
| 3487 | <tabstop>button_2_num</tabstop> | ||
| 3488 | <tabstop>button_3_num</tabstop> | ||
| 3489 | <tabstop>button_backspace_num</tabstop> | ||
| 3490 | <tabstop>button_4_num</tabstop> | ||
| 3491 | <tabstop>button_5_num</tabstop> | ||
| 3492 | <tabstop>button_6_num</tabstop> | ||
| 3493 | <tabstop>button_ok_num</tabstop> | ||
| 3494 | <tabstop>button_7_num</tabstop> | ||
| 3495 | <tabstop>button_8_num</tabstop> | ||
| 3496 | <tabstop>button_9_num</tabstop> | ||
| 3497 | <tabstop>button_0_num</tabstop> | ||
| 3498 | </tabstops> | ||
| 3499 | <resources> | ||
| 3500 | <include location="../../../dist/icons/overlay/overlay.qrc"/> | ||
| 3501 | </resources> | ||
| 3502 | <connections/> | ||
| 3503 | </ui> | ||
diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp index 15c09e0ad..9c7daeac7 100644 --- a/src/yuzu/bootmanager.cpp +++ b/src/yuzu/bootmanager.cpp | |||
| @@ -29,10 +29,10 @@ | |||
| 29 | #include "common/microprofile.h" | 29 | #include "common/microprofile.h" |
| 30 | #include "common/scm_rev.h" | 30 | #include "common/scm_rev.h" |
| 31 | #include "common/scope_exit.h" | 31 | #include "common/scope_exit.h" |
| 32 | #include "common/settings.h" | ||
| 32 | #include "core/core.h" | 33 | #include "core/core.h" |
| 33 | #include "core/frontend/framebuffer_layout.h" | 34 | #include "core/frontend/framebuffer_layout.h" |
| 34 | #include "core/hle/kernel/process.h" | 35 | #include "core/hle/kernel/process.h" |
| 35 | #include "core/settings.h" | ||
| 36 | #include "input_common/keyboard.h" | 36 | #include "input_common/keyboard.h" |
| 37 | #include "input_common/main.h" | 37 | #include "input_common/main.h" |
| 38 | #include "input_common/mouse/mouse_input.h" | 38 | #include "input_common/mouse/mouse_input.h" |
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index 1bac57bb2..851246233 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp | |||
| @@ -641,6 +641,9 @@ void Config::ReadDebuggingValues() { | |||
| 641 | ReadSetting(QStringLiteral("disable_macro_jit"), false).toBool(); | 641 | ReadSetting(QStringLiteral("disable_macro_jit"), false).toBool(); |
| 642 | Settings::values.extended_logging = | 642 | Settings::values.extended_logging = |
| 643 | ReadSetting(QStringLiteral("extended_logging"), false).toBool(); | 643 | ReadSetting(QStringLiteral("extended_logging"), false).toBool(); |
| 644 | Settings::values.use_debug_asserts = | ||
| 645 | ReadSetting(QStringLiteral("use_debug_asserts"), false).toBool(); | ||
| 646 | Settings::values.use_auto_stub = ReadSetting(QStringLiteral("use_auto_stub"), false).toBool(); | ||
| 644 | 647 | ||
| 645 | qt_config->endGroup(); | 648 | qt_config->endGroup(); |
| 646 | } | 649 | } |
| @@ -770,6 +773,13 @@ void Config::ReadRendererValues() { | |||
| 770 | ReadSettingGlobal(Settings::values.renderer_backend, QStringLiteral("backend"), 0); | 773 | ReadSettingGlobal(Settings::values.renderer_backend, QStringLiteral("backend"), 0); |
| 771 | ReadSettingGlobal(Settings::values.renderer_debug, QStringLiteral("debug"), false); | 774 | ReadSettingGlobal(Settings::values.renderer_debug, QStringLiteral("debug"), false); |
| 772 | ReadSettingGlobal(Settings::values.vulkan_device, QStringLiteral("vulkan_device"), 0); | 775 | ReadSettingGlobal(Settings::values.vulkan_device, QStringLiteral("vulkan_device"), 0); |
| 776 | #ifdef _WIN32 | ||
| 777 | ReadSettingGlobal(Settings::values.fullscreen_mode, QStringLiteral("fullscreen_mode"), 0); | ||
| 778 | #else | ||
| 779 | // *nix platforms may have issues with the borderless windowed fullscreen mode. | ||
| 780 | // Default to exclusive fullscreen on these platforms for now. | ||
| 781 | ReadSettingGlobal(Settings::values.fullscreen_mode, QStringLiteral("fullscreen_mode"), 1); | ||
| 782 | #endif | ||
| 773 | ReadSettingGlobal(Settings::values.aspect_ratio, QStringLiteral("aspect_ratio"), 0); | 783 | ReadSettingGlobal(Settings::values.aspect_ratio, QStringLiteral("aspect_ratio"), 0); |
| 774 | ReadSettingGlobal(Settings::values.max_anisotropy, QStringLiteral("max_anisotropy"), 0); | 784 | ReadSettingGlobal(Settings::values.max_anisotropy, QStringLiteral("max_anisotropy"), 0); |
| 775 | ReadSettingGlobal(Settings::values.use_frame_limit, QStringLiteral("use_frame_limit"), true); | 785 | ReadSettingGlobal(Settings::values.use_frame_limit, QStringLiteral("use_frame_limit"), true); |
| @@ -1230,6 +1240,7 @@ void Config::SaveDebuggingValues() { | |||
| 1230 | WriteSetting(QStringLiteral("dump_exefs"), Settings::values.dump_exefs, false); | 1240 | WriteSetting(QStringLiteral("dump_exefs"), Settings::values.dump_exefs, false); |
| 1231 | WriteSetting(QStringLiteral("dump_nso"), Settings::values.dump_nso, false); | 1241 | WriteSetting(QStringLiteral("dump_nso"), Settings::values.dump_nso, false); |
| 1232 | WriteSetting(QStringLiteral("quest_flag"), Settings::values.quest_flag, false); | 1242 | WriteSetting(QStringLiteral("quest_flag"), Settings::values.quest_flag, false); |
| 1243 | WriteSetting(QStringLiteral("use_debug_asserts"), Settings::values.use_debug_asserts, false); | ||
| 1233 | WriteSetting(QStringLiteral("disable_macro_jit"), Settings::values.disable_macro_jit, false); | 1244 | WriteSetting(QStringLiteral("disable_macro_jit"), Settings::values.disable_macro_jit, false); |
| 1234 | 1245 | ||
| 1235 | qt_config->endGroup(); | 1246 | qt_config->endGroup(); |
| @@ -1333,6 +1344,13 @@ void Config::SaveRendererValues() { | |||
| 1333 | Settings::values.renderer_backend.UsingGlobal(), 0); | 1344 | Settings::values.renderer_backend.UsingGlobal(), 0); |
| 1334 | WriteSetting(QStringLiteral("debug"), Settings::values.renderer_debug, false); | 1345 | WriteSetting(QStringLiteral("debug"), Settings::values.renderer_debug, false); |
| 1335 | WriteSettingGlobal(QStringLiteral("vulkan_device"), Settings::values.vulkan_device, 0); | 1346 | WriteSettingGlobal(QStringLiteral("vulkan_device"), Settings::values.vulkan_device, 0); |
| 1347 | #ifdef _WIN32 | ||
| 1348 | WriteSettingGlobal(QStringLiteral("fullscreen_mode"), Settings::values.fullscreen_mode, 0); | ||
| 1349 | #else | ||
| 1350 | // *nix platforms may have issues with the borderless windowed fullscreen mode. | ||
| 1351 | // Default to exclusive fullscreen on these platforms for now. | ||
| 1352 | WriteSettingGlobal(QStringLiteral("fullscreen_mode"), Settings::values.fullscreen_mode, 1); | ||
| 1353 | #endif | ||
| 1336 | WriteSettingGlobal(QStringLiteral("aspect_ratio"), Settings::values.aspect_ratio, 0); | 1354 | WriteSettingGlobal(QStringLiteral("aspect_ratio"), Settings::values.aspect_ratio, 0); |
| 1337 | WriteSettingGlobal(QStringLiteral("max_anisotropy"), Settings::values.max_anisotropy, 0); | 1355 | WriteSettingGlobal(QStringLiteral("max_anisotropy"), Settings::values.max_anisotropy, 0); |
| 1338 | WriteSettingGlobal(QStringLiteral("use_frame_limit"), Settings::values.use_frame_limit, true); | 1356 | WriteSettingGlobal(QStringLiteral("use_frame_limit"), Settings::values.use_frame_limit, true); |
| @@ -1584,7 +1602,7 @@ void Config::Reload() { | |||
| 1584 | ReadValues(); | 1602 | ReadValues(); |
| 1585 | // To apply default value changes | 1603 | // To apply default value changes |
| 1586 | SaveValues(); | 1604 | SaveValues(); |
| 1587 | Settings::Apply(Core::System::GetInstance()); | 1605 | Core::System::GetInstance().ApplySettings(); |
| 1588 | } | 1606 | } |
| 1589 | 1607 | ||
| 1590 | void Config::Save() { | 1608 | void Config::Save() { |
diff --git a/src/yuzu/configuration/config.h b/src/yuzu/configuration/config.h index 949c4eb13..5a2c026b3 100644 --- a/src/yuzu/configuration/config.h +++ b/src/yuzu/configuration/config.h | |||
| @@ -9,7 +9,7 @@ | |||
| 9 | #include <string> | 9 | #include <string> |
| 10 | #include <QMetaType> | 10 | #include <QMetaType> |
| 11 | #include <QVariant> | 11 | #include <QVariant> |
| 12 | #include "core/settings.h" | 12 | #include "common/settings.h" |
| 13 | #include "yuzu/uisettings.h" | 13 | #include "yuzu/uisettings.h" |
| 14 | 14 | ||
| 15 | class QSettings; | 15 | class QSettings; |
| @@ -131,6 +131,6 @@ private: | |||
| 131 | bool global; | 131 | bool global; |
| 132 | }; | 132 | }; |
| 133 | 133 | ||
| 134 | // These metatype declarations cannot be in core/settings.h because core is devoid of QT | 134 | // These metatype declarations cannot be in common/settings.h because core is devoid of QT |
| 135 | Q_DECLARE_METATYPE(Settings::RendererBackend); | 135 | Q_DECLARE_METATYPE(Settings::RendererBackend); |
| 136 | Q_DECLARE_METATYPE(Settings::GPUAccuracy); | 136 | Q_DECLARE_METATYPE(Settings::GPUAccuracy); |
diff --git a/src/yuzu/configuration/configuration_shared.cpp b/src/yuzu/configuration/configuration_shared.cpp index 18482795c..89be4a62d 100644 --- a/src/yuzu/configuration/configuration_shared.cpp +++ b/src/yuzu/configuration/configuration_shared.cpp | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | #include <QComboBox> | 6 | #include <QComboBox> |
| 7 | #include <QObject> | 7 | #include <QObject> |
| 8 | #include <QString> | 8 | #include <QString> |
| 9 | #include "core/settings.h" | 9 | #include "common/settings.h" |
| 10 | #include "yuzu/configuration/configuration_shared.h" | 10 | #include "yuzu/configuration/configuration_shared.h" |
| 11 | #include "yuzu/configuration/configure_per_game.h" | 11 | #include "yuzu/configuration/configure_per_game.h" |
| 12 | 12 | ||
diff --git a/src/yuzu/configuration/configuration_shared.h b/src/yuzu/configuration/configuration_shared.h index 312b9e549..5b344cdbd 100644 --- a/src/yuzu/configuration/configuration_shared.h +++ b/src/yuzu/configuration/configuration_shared.h | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | #include <QCheckBox> | 7 | #include <QCheckBox> |
| 8 | #include <QComboBox> | 8 | #include <QComboBox> |
| 9 | #include <QString> | 9 | #include <QString> |
| 10 | #include "core/settings.h" | 10 | #include "common/settings.h" |
| 11 | 11 | ||
| 12 | namespace ConfigurationShared { | 12 | namespace ConfigurationShared { |
| 13 | 13 | ||
diff --git a/src/yuzu/configuration/configure_audio.cpp b/src/yuzu/configuration/configure_audio.cpp index db9518798..f9507e228 100644 --- a/src/yuzu/configuration/configure_audio.cpp +++ b/src/yuzu/configuration/configure_audio.cpp | |||
| @@ -8,8 +8,8 @@ | |||
| 8 | 8 | ||
| 9 | #include "audio_core/sink.h" | 9 | #include "audio_core/sink.h" |
| 10 | #include "audio_core/sink_details.h" | 10 | #include "audio_core/sink_details.h" |
| 11 | #include "common/settings.h" | ||
| 11 | #include "core/core.h" | 12 | #include "core/core.h" |
| 12 | #include "core/settings.h" | ||
| 13 | #include "ui_configure_audio.h" | 13 | #include "ui_configure_audio.h" |
| 14 | #include "yuzu/configuration/configuration_shared.h" | 14 | #include "yuzu/configuration/configuration_shared.h" |
| 15 | #include "yuzu/configuration/configure_audio.h" | 15 | #include "yuzu/configuration/configure_audio.h" |
diff --git a/src/yuzu/configuration/configure_cpu.cpp b/src/yuzu/configuration/configure_cpu.cpp index d055cbd60..4f99bc80f 100644 --- a/src/yuzu/configuration/configure_cpu.cpp +++ b/src/yuzu/configuration/configure_cpu.cpp | |||
| @@ -7,8 +7,8 @@ | |||
| 7 | 7 | ||
| 8 | #include "common/common_types.h" | 8 | #include "common/common_types.h" |
| 9 | #include "common/logging/log.h" | 9 | #include "common/logging/log.h" |
| 10 | #include "common/settings.h" | ||
| 10 | #include "core/core.h" | 11 | #include "core/core.h" |
| 11 | #include "core/settings.h" | ||
| 12 | #include "ui_configure_cpu.h" | 12 | #include "ui_configure_cpu.h" |
| 13 | #include "yuzu/configuration/configure_cpu.h" | 13 | #include "yuzu/configuration/configure_cpu.h" |
| 14 | 14 | ||
diff --git a/src/yuzu/configuration/configure_cpu.h b/src/yuzu/configuration/configure_cpu.h index 3c5683d81..ef77b2e7e 100644 --- a/src/yuzu/configuration/configure_cpu.h +++ b/src/yuzu/configuration/configure_cpu.h | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | 6 | ||
| 7 | #include <memory> | 7 | #include <memory> |
| 8 | #include <QWidget> | 8 | #include <QWidget> |
| 9 | #include "core/settings.h" | 9 | #include "common/settings.h" |
| 10 | 10 | ||
| 11 | namespace Ui { | 11 | namespace Ui { |
| 12 | class ConfigureCpu; | 12 | class ConfigureCpu; |
diff --git a/src/yuzu/configuration/configure_cpu_debug.cpp b/src/yuzu/configuration/configure_cpu_debug.cpp index 3385b2cf6..c925c023c 100644 --- a/src/yuzu/configuration/configure_cpu_debug.cpp +++ b/src/yuzu/configuration/configure_cpu_debug.cpp | |||
| @@ -6,8 +6,8 @@ | |||
| 6 | 6 | ||
| 7 | #include "common/common_types.h" | 7 | #include "common/common_types.h" |
| 8 | #include "common/logging/log.h" | 8 | #include "common/logging/log.h" |
| 9 | #include "common/settings.h" | ||
| 9 | #include "core/core.h" | 10 | #include "core/core.h" |
| 10 | #include "core/settings.h" | ||
| 11 | #include "ui_configure_cpu_debug.h" | 11 | #include "ui_configure_cpu_debug.h" |
| 12 | #include "yuzu/configuration/configure_cpu_debug.h" | 12 | #include "yuzu/configuration/configure_cpu_debug.h" |
| 13 | 13 | ||
diff --git a/src/yuzu/configuration/configure_cpu_debug.h b/src/yuzu/configuration/configure_cpu_debug.h index c9941ef3b..10de55099 100644 --- a/src/yuzu/configuration/configure_cpu_debug.h +++ b/src/yuzu/configuration/configure_cpu_debug.h | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | 6 | ||
| 7 | #include <memory> | 7 | #include <memory> |
| 8 | #include <QWidget> | 8 | #include <QWidget> |
| 9 | #include "core/settings.h" | 9 | #include "common/settings.h" |
| 10 | 10 | ||
| 11 | namespace Ui { | 11 | namespace Ui { |
| 12 | class ConfigureCpuDebug; | 12 | class ConfigureCpuDebug; |
diff --git a/src/yuzu/configuration/configure_debug.cpp b/src/yuzu/configuration/configure_debug.cpp index 121873f95..6730eb356 100644 --- a/src/yuzu/configuration/configure_debug.cpp +++ b/src/yuzu/configuration/configure_debug.cpp | |||
| @@ -7,8 +7,8 @@ | |||
| 7 | #include "common/file_util.h" | 7 | #include "common/file_util.h" |
| 8 | #include "common/logging/backend.h" | 8 | #include "common/logging/backend.h" |
| 9 | #include "common/logging/filter.h" | 9 | #include "common/logging/filter.h" |
| 10 | #include "common/settings.h" | ||
| 10 | #include "core/core.h" | 11 | #include "core/core.h" |
| 11 | #include "core/settings.h" | ||
| 12 | #include "ui_configure_debug.h" | 12 | #include "ui_configure_debug.h" |
| 13 | #include "yuzu/configuration/configure_debug.h" | 13 | #include "yuzu/configuration/configure_debug.h" |
| 14 | #include "yuzu/debugger/console.h" | 14 | #include "yuzu/debugger/console.h" |
| @@ -34,6 +34,8 @@ void ConfigureDebug::SetConfiguration() { | |||
| 34 | ui->homebrew_args_edit->setText(QString::fromStdString(Settings::values.program_args)); | 34 | ui->homebrew_args_edit->setText(QString::fromStdString(Settings::values.program_args)); |
| 35 | ui->reporting_services->setChecked(Settings::values.reporting_services); | 35 | ui->reporting_services->setChecked(Settings::values.reporting_services); |
| 36 | ui->quest_flag->setChecked(Settings::values.quest_flag); | 36 | ui->quest_flag->setChecked(Settings::values.quest_flag); |
| 37 | ui->use_debug_asserts->setChecked(Settings::values.use_debug_asserts); | ||
| 38 | ui->use_auto_stub->setChecked(Settings::values.use_auto_stub); | ||
| 37 | ui->enable_graphics_debugging->setEnabled(!Core::System::GetInstance().IsPoweredOn()); | 39 | ui->enable_graphics_debugging->setEnabled(!Core::System::GetInstance().IsPoweredOn()); |
| 38 | ui->enable_graphics_debugging->setChecked(Settings::values.renderer_debug); | 40 | ui->enable_graphics_debugging->setChecked(Settings::values.renderer_debug); |
| 39 | ui->disable_macro_jit->setEnabled(!Core::System::GetInstance().IsPoweredOn()); | 41 | ui->disable_macro_jit->setEnabled(!Core::System::GetInstance().IsPoweredOn()); |
| @@ -47,13 +49,15 @@ void ConfigureDebug::ApplyConfiguration() { | |||
| 47 | Settings::values.program_args = ui->homebrew_args_edit->text().toStdString(); | 49 | Settings::values.program_args = ui->homebrew_args_edit->text().toStdString(); |
| 48 | Settings::values.reporting_services = ui->reporting_services->isChecked(); | 50 | Settings::values.reporting_services = ui->reporting_services->isChecked(); |
| 49 | Settings::values.quest_flag = ui->quest_flag->isChecked(); | 51 | Settings::values.quest_flag = ui->quest_flag->isChecked(); |
| 52 | Settings::values.use_debug_asserts = ui->use_debug_asserts->isChecked(); | ||
| 53 | Settings::values.use_auto_stub = ui->use_auto_stub->isChecked(); | ||
| 50 | Settings::values.renderer_debug = ui->enable_graphics_debugging->isChecked(); | 54 | Settings::values.renderer_debug = ui->enable_graphics_debugging->isChecked(); |
| 51 | Settings::values.disable_macro_jit = ui->disable_macro_jit->isChecked(); | 55 | Settings::values.disable_macro_jit = ui->disable_macro_jit->isChecked(); |
| 52 | Settings::values.extended_logging = ui->extended_logging->isChecked(); | 56 | Settings::values.extended_logging = ui->extended_logging->isChecked(); |
| 53 | Debugger::ToggleConsole(); | 57 | Debugger::ToggleConsole(); |
| 54 | Log::Filter filter; | 58 | Common::Log::Filter filter; |
| 55 | filter.ParseFilterString(Settings::values.log_filter); | 59 | filter.ParseFilterString(Settings::values.log_filter); |
| 56 | Log::SetGlobalFilter(filter); | 60 | Common::Log::SetGlobalFilter(filter); |
| 57 | } | 61 | } |
| 58 | 62 | ||
| 59 | void ConfigureDebug::changeEvent(QEvent* event) { | 63 | void ConfigureDebug::changeEvent(QEvent* event) { |
diff --git a/src/yuzu/configuration/configure_debug.ui b/src/yuzu/configuration/configure_debug.ui index 9186aa732..d812858b6 100644 --- a/src/yuzu/configuration/configure_debug.ui +++ b/src/yuzu/configuration/configure_debug.ui | |||
| @@ -185,6 +185,35 @@ | |||
| 185 | </property> | 185 | </property> |
| 186 | </widget> | 186 | </widget> |
| 187 | </item> | 187 | </item> |
| 188 | <item> | ||
| 189 | <widget class="QCheckBox" name="use_debug_asserts"> | ||
| 190 | <property name="text"> | ||
| 191 | <string>Enable Debug Asserts</string> | ||
| 192 | </property> | ||
| 193 | </widget> | ||
| 194 | </item> | ||
| 195 | <item> | ||
| 196 | <widget class="QCheckBox" name="use_auto_stub"> | ||
| 197 | <property name="text"> | ||
| 198 | <string>Enable Auto-Stub</string> | ||
| 199 | </property> | ||
| 200 | </widget> | ||
| 201 | </item> | ||
| 202 | <item> | ||
| 203 | <widget class="QLabel" name="label_3"> | ||
| 204 | <property name="font"> | ||
| 205 | <font> | ||
| 206 | <italic>true</italic> | ||
| 207 | </font> | ||
| 208 | </property> | ||
| 209 | <property name="text"> | ||
| 210 | <string>This will be reset automatically when yuzu closes.</string> | ||
| 211 | </property> | ||
| 212 | <property name="indent"> | ||
| 213 | <number>20</number> | ||
| 214 | </property> | ||
| 215 | </widget> | ||
| 216 | </item> | ||
| 188 | </layout> | 217 | </layout> |
| 189 | </widget> | 218 | </widget> |
| 190 | </item> | 219 | </item> |
diff --git a/src/yuzu/configuration/configure_dialog.cpp b/src/yuzu/configuration/configure_dialog.cpp index d6b17a28d..3ad40d2b3 100644 --- a/src/yuzu/configuration/configure_dialog.cpp +++ b/src/yuzu/configuration/configure_dialog.cpp | |||
| @@ -5,8 +5,8 @@ | |||
| 5 | #include <QHash> | 5 | #include <QHash> |
| 6 | #include <QListWidgetItem> | 6 | #include <QListWidgetItem> |
| 7 | #include <QSignalBlocker> | 7 | #include <QSignalBlocker> |
| 8 | #include "common/settings.h" | ||
| 8 | #include "core/core.h" | 9 | #include "core/core.h" |
| 9 | #include "core/settings.h" | ||
| 10 | #include "ui_configure.h" | 10 | #include "ui_configure.h" |
| 11 | #include "yuzu/configuration/config.h" | 11 | #include "yuzu/configuration/config.h" |
| 12 | #include "yuzu/configuration/configure_dialog.h" | 12 | #include "yuzu/configuration/configure_dialog.h" |
| @@ -55,7 +55,7 @@ void ConfigureDialog::ApplyConfiguration() { | |||
| 55 | ui->debugTab->ApplyConfiguration(); | 55 | ui->debugTab->ApplyConfiguration(); |
| 56 | ui->webTab->ApplyConfiguration(); | 56 | ui->webTab->ApplyConfiguration(); |
| 57 | ui->serviceTab->ApplyConfiguration(); | 57 | ui->serviceTab->ApplyConfiguration(); |
| 58 | Settings::Apply(Core::System::GetInstance()); | 58 | Core::System::GetInstance().ApplySettings(); |
| 59 | Settings::LogSettings(); | 59 | Settings::LogSettings(); |
| 60 | } | 60 | } |
| 61 | 61 | ||
diff --git a/src/yuzu/configuration/configure_filesystem.cpp b/src/yuzu/configuration/configure_filesystem.cpp index 58f644af4..006eda4b0 100644 --- a/src/yuzu/configuration/configure_filesystem.cpp +++ b/src/yuzu/configuration/configure_filesystem.cpp | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | #include <QMessageBox> | 6 | #include <QMessageBox> |
| 7 | #include "common/common_paths.h" | 7 | #include "common/common_paths.h" |
| 8 | #include "common/file_util.h" | 8 | #include "common/file_util.h" |
| 9 | #include "core/settings.h" | 9 | #include "common/settings.h" |
| 10 | #include "ui_configure_filesystem.h" | 10 | #include "ui_configure_filesystem.h" |
| 11 | #include "yuzu/configuration/configure_filesystem.h" | 11 | #include "yuzu/configuration/configure_filesystem.h" |
| 12 | #include "yuzu/uisettings.h" | 12 | #include "yuzu/uisettings.h" |
diff --git a/src/yuzu/configuration/configure_general.cpp b/src/yuzu/configuration/configure_general.cpp index d4d29d422..2fa88dcec 100644 --- a/src/yuzu/configuration/configure_general.cpp +++ b/src/yuzu/configuration/configure_general.cpp | |||
| @@ -4,8 +4,8 @@ | |||
| 4 | 4 | ||
| 5 | #include <QCheckBox> | 5 | #include <QCheckBox> |
| 6 | #include <QSpinBox> | 6 | #include <QSpinBox> |
| 7 | #include "common/settings.h" | ||
| 7 | #include "core/core.h" | 8 | #include "core/core.h" |
| 8 | #include "core/settings.h" | ||
| 9 | #include "ui_configure_general.h" | 9 | #include "ui_configure_general.h" |
| 10 | #include "yuzu/configuration/configuration_shared.h" | 10 | #include "yuzu/configuration/configuration_shared.h" |
| 11 | #include "yuzu/configuration/configure_general.h" | 11 | #include "yuzu/configuration/configure_general.h" |
diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp index 9ff32aec4..0a7536617 100644 --- a/src/yuzu/configuration/configure_graphics.cpp +++ b/src/yuzu/configuration/configure_graphics.cpp | |||
| @@ -11,8 +11,8 @@ | |||
| 11 | 11 | ||
| 12 | #include "common/common_types.h" | 12 | #include "common/common_types.h" |
| 13 | #include "common/logging/log.h" | 13 | #include "common/logging/log.h" |
| 14 | #include "common/settings.h" | ||
| 14 | #include "core/core.h" | 15 | #include "core/core.h" |
| 15 | #include "core/settings.h" | ||
| 16 | #include "ui_configure_graphics.h" | 16 | #include "ui_configure_graphics.h" |
| 17 | #include "video_core/vulkan_common/vulkan_instance.h" | 17 | #include "video_core/vulkan_common/vulkan_instance.h" |
| 18 | #include "video_core/vulkan_common/vulkan_library.h" | 18 | #include "video_core/vulkan_common/vulkan_library.h" |
| @@ -77,18 +77,25 @@ void ConfigureGraphics::SetConfiguration() { | |||
| 77 | 77 | ||
| 78 | if (Settings::IsConfiguringGlobal()) { | 78 | if (Settings::IsConfiguringGlobal()) { |
| 79 | ui->api->setCurrentIndex(static_cast<int>(Settings::values.renderer_backend.GetValue())); | 79 | ui->api->setCurrentIndex(static_cast<int>(Settings::values.renderer_backend.GetValue())); |
| 80 | ui->fullscreen_mode_combobox->setCurrentIndex(Settings::values.fullscreen_mode.GetValue()); | ||
| 80 | ui->aspect_ratio_combobox->setCurrentIndex(Settings::values.aspect_ratio.GetValue()); | 81 | ui->aspect_ratio_combobox->setCurrentIndex(Settings::values.aspect_ratio.GetValue()); |
| 81 | } else { | 82 | } else { |
| 82 | ConfigurationShared::SetPerGameSetting(ui->api, &Settings::values.renderer_backend); | 83 | ConfigurationShared::SetPerGameSetting(ui->api, &Settings::values.renderer_backend); |
| 83 | ConfigurationShared::SetHighlight(ui->api_layout, | 84 | ConfigurationShared::SetHighlight(ui->api_layout, |
| 84 | !Settings::values.renderer_backend.UsingGlobal()); | 85 | !Settings::values.renderer_backend.UsingGlobal()); |
| 86 | |||
| 87 | ConfigurationShared::SetPerGameSetting(ui->fullscreen_mode_combobox, | ||
| 88 | &Settings::values.fullscreen_mode); | ||
| 89 | ConfigurationShared::SetHighlight(ui->fullscreen_mode_label, | ||
| 90 | !Settings::values.fullscreen_mode.UsingGlobal()); | ||
| 91 | |||
| 85 | ConfigurationShared::SetPerGameSetting(ui->aspect_ratio_combobox, | 92 | ConfigurationShared::SetPerGameSetting(ui->aspect_ratio_combobox, |
| 86 | &Settings::values.aspect_ratio); | 93 | &Settings::values.aspect_ratio); |
| 94 | ConfigurationShared::SetHighlight(ui->ar_label, | ||
| 95 | !Settings::values.aspect_ratio.UsingGlobal()); | ||
| 87 | 96 | ||
| 88 | ui->bg_combobox->setCurrentIndex(Settings::values.bg_red.UsingGlobal() ? 0 : 1); | 97 | ui->bg_combobox->setCurrentIndex(Settings::values.bg_red.UsingGlobal() ? 0 : 1); |
| 89 | ui->bg_button->setEnabled(!Settings::values.bg_red.UsingGlobal()); | 98 | ui->bg_button->setEnabled(!Settings::values.bg_red.UsingGlobal()); |
| 90 | ConfigurationShared::SetHighlight(ui->ar_label, | ||
| 91 | !Settings::values.aspect_ratio.UsingGlobal()); | ||
| 92 | ConfigurationShared::SetHighlight(ui->bg_layout, !Settings::values.bg_red.UsingGlobal()); | 99 | ConfigurationShared::SetHighlight(ui->bg_layout, !Settings::values.bg_red.UsingGlobal()); |
| 93 | } | 100 | } |
| 94 | 101 | ||
| @@ -107,6 +114,9 @@ void ConfigureGraphics::ApplyConfiguration() { | |||
| 107 | if (Settings::values.vulkan_device.UsingGlobal()) { | 114 | if (Settings::values.vulkan_device.UsingGlobal()) { |
| 108 | Settings::values.vulkan_device.SetValue(vulkan_device); | 115 | Settings::values.vulkan_device.SetValue(vulkan_device); |
| 109 | } | 116 | } |
| 117 | if (Settings::values.fullscreen_mode.UsingGlobal()) { | ||
| 118 | Settings::values.fullscreen_mode.SetValue(ui->fullscreen_mode_combobox->currentIndex()); | ||
| 119 | } | ||
| 110 | if (Settings::values.aspect_ratio.UsingGlobal()) { | 120 | if (Settings::values.aspect_ratio.UsingGlobal()) { |
| 111 | Settings::values.aspect_ratio.SetValue(ui->aspect_ratio_combobox->currentIndex()); | 121 | Settings::values.aspect_ratio.SetValue(ui->aspect_ratio_combobox->currentIndex()); |
| 112 | } | 122 | } |
| @@ -140,6 +150,8 @@ void ConfigureGraphics::ApplyConfiguration() { | |||
| 140 | } | 150 | } |
| 141 | } | 151 | } |
| 142 | 152 | ||
| 153 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.fullscreen_mode, | ||
| 154 | ui->fullscreen_mode_combobox); | ||
| 143 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.aspect_ratio, | 155 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.aspect_ratio, |
| 144 | ui->aspect_ratio_combobox); | 156 | ui->aspect_ratio_combobox); |
| 145 | 157 | ||
| @@ -227,7 +239,7 @@ void ConfigureGraphics::RetrieveVulkanDevices() try { | |||
| 227 | vulkan_devices.clear(); | 239 | vulkan_devices.clear(); |
| 228 | vulkan_devices.reserve(physical_devices.size()); | 240 | vulkan_devices.reserve(physical_devices.size()); |
| 229 | for (const VkPhysicalDevice device : physical_devices) { | 241 | for (const VkPhysicalDevice device : physical_devices) { |
| 230 | const char* const name = vk::PhysicalDevice(device, dld).GetProperties().deviceName; | 242 | const std::string name = vk::PhysicalDevice(device, dld).GetProperties().deviceName; |
| 231 | vulkan_devices.push_back(QString::fromStdString(name)); | 243 | vulkan_devices.push_back(QString::fromStdString(name)); |
| 232 | } | 244 | } |
| 233 | 245 | ||
| @@ -253,6 +265,7 @@ void ConfigureGraphics::SetupPerGameUI() { | |||
| 253 | if (Settings::IsConfiguringGlobal()) { | 265 | if (Settings::IsConfiguringGlobal()) { |
| 254 | ui->api->setEnabled(Settings::values.renderer_backend.UsingGlobal()); | 266 | ui->api->setEnabled(Settings::values.renderer_backend.UsingGlobal()); |
| 255 | ui->device->setEnabled(Settings::values.renderer_backend.UsingGlobal()); | 267 | ui->device->setEnabled(Settings::values.renderer_backend.UsingGlobal()); |
| 268 | ui->fullscreen_mode_combobox->setEnabled(Settings::values.fullscreen_mode.UsingGlobal()); | ||
| 256 | ui->aspect_ratio_combobox->setEnabled(Settings::values.aspect_ratio.UsingGlobal()); | 269 | ui->aspect_ratio_combobox->setEnabled(Settings::values.aspect_ratio.UsingGlobal()); |
| 257 | ui->use_asynchronous_gpu_emulation->setEnabled( | 270 | ui->use_asynchronous_gpu_emulation->setEnabled( |
| 258 | Settings::values.use_asynchronous_gpu_emulation.UsingGlobal()); | 271 | Settings::values.use_asynchronous_gpu_emulation.UsingGlobal()); |
| @@ -278,6 +291,8 @@ void ConfigureGraphics::SetupPerGameUI() { | |||
| 278 | 291 | ||
| 279 | ConfigurationShared::SetColoredComboBox(ui->aspect_ratio_combobox, ui->ar_label, | 292 | ConfigurationShared::SetColoredComboBox(ui->aspect_ratio_combobox, ui->ar_label, |
| 280 | Settings::values.aspect_ratio.GetValue(true)); | 293 | Settings::values.aspect_ratio.GetValue(true)); |
| 294 | ConfigurationShared::SetColoredComboBox(ui->fullscreen_mode_combobox, ui->fullscreen_mode_label, | ||
| 295 | Settings::values.fullscreen_mode.GetValue(true)); | ||
| 281 | ConfigurationShared::InsertGlobalItem( | 296 | ConfigurationShared::InsertGlobalItem( |
| 282 | ui->api, static_cast<int>(Settings::values.renderer_backend.GetValue(true))); | 297 | ui->api, static_cast<int>(Settings::values.renderer_backend.GetValue(true))); |
| 283 | } | 298 | } |
diff --git a/src/yuzu/configuration/configure_graphics.h b/src/yuzu/configuration/configure_graphics.h index 1fefc88eb..c162048a2 100644 --- a/src/yuzu/configuration/configure_graphics.h +++ b/src/yuzu/configuration/configure_graphics.h | |||
| @@ -8,7 +8,7 @@ | |||
| 8 | #include <vector> | 8 | #include <vector> |
| 9 | #include <QString> | 9 | #include <QString> |
| 10 | #include <QWidget> | 10 | #include <QWidget> |
| 11 | #include "core/settings.h" | 11 | #include "common/settings.h" |
| 12 | 12 | ||
| 13 | namespace ConfigurationShared { | 13 | namespace ConfigurationShared { |
| 14 | enum class CheckState; | 14 | enum class CheckState; |
diff --git a/src/yuzu/configuration/configure_graphics.ui b/src/yuzu/configuration/configure_graphics.ui index 58486eb1e..ab0bd4d77 100644 --- a/src/yuzu/configuration/configure_graphics.ui +++ b/src/yuzu/configuration/configure_graphics.ui | |||
| @@ -105,8 +105,47 @@ | |||
| 105 | </widget> | 105 | </widget> |
| 106 | </item> | 106 | </item> |
| 107 | <item> | 107 | <item> |
| 108 | <widget class="QWidget" name="fullscreen_mode_layout" native="true"> | ||
| 109 | <layout class="QHBoxLayout" name="horizontalLayout_1"> | ||
| 110 | <property name="leftMargin"> | ||
| 111 | <number>0</number> | ||
| 112 | </property> | ||
| 113 | <property name="topMargin"> | ||
| 114 | <number>0</number> | ||
| 115 | </property> | ||
| 116 | <property name="rightMargin"> | ||
| 117 | <number>0</number> | ||
| 118 | </property> | ||
| 119 | <property name="bottomMargin"> | ||
| 120 | <number>0</number> | ||
| 121 | </property> | ||
| 122 | <item> | ||
| 123 | <widget class="QLabel" name="fullscreen_mode_label"> | ||
| 124 | <property name="text"> | ||
| 125 | <string>Fullscreen Mode:</string> | ||
| 126 | </property> | ||
| 127 | </widget> | ||
| 128 | </item> | ||
| 129 | <item> | ||
| 130 | <widget class="QComboBox" name="fullscreen_mode_combobox"> | ||
| 131 | <item> | ||
| 132 | <property name="text"> | ||
| 133 | <string>Borderless Windowed</string> | ||
| 134 | </property> | ||
| 135 | </item> | ||
| 136 | <item> | ||
| 137 | <property name="text"> | ||
| 138 | <string>Exclusive Fullscreen</string> | ||
| 139 | </property> | ||
| 140 | </item> | ||
| 141 | </widget> | ||
| 142 | </item> | ||
| 143 | </layout> | ||
| 144 | </widget> | ||
| 145 | </item> | ||
| 146 | <item> | ||
| 108 | <widget class="QWidget" name="aspect_ratio_layout" native="true"> | 147 | <widget class="QWidget" name="aspect_ratio_layout" native="true"> |
| 109 | <layout class="QHBoxLayout" name="horizontalLayout_6"> | 148 | <layout class="QHBoxLayout" name="horizontalLayout_2"> |
| 110 | <property name="leftMargin"> | 149 | <property name="leftMargin"> |
| 111 | <number>0</number> | 150 | <number>0</number> |
| 112 | </property> | 151 | </property> |
diff --git a/src/yuzu/configuration/configure_graphics_advanced.cpp b/src/yuzu/configuration/configure_graphics_advanced.cpp index 383c7bac8..c67609b0e 100644 --- a/src/yuzu/configuration/configure_graphics_advanced.cpp +++ b/src/yuzu/configuration/configure_graphics_advanced.cpp | |||
| @@ -2,8 +2,8 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include "common/settings.h" | ||
| 5 | #include "core/core.h" | 6 | #include "core/core.h" |
| 6 | #include "core/settings.h" | ||
| 7 | #include "ui_configure_graphics_advanced.h" | 7 | #include "ui_configure_graphics_advanced.h" |
| 8 | #include "yuzu/configuration/configuration_shared.h" | 8 | #include "yuzu/configuration/configuration_shared.h" |
| 9 | #include "yuzu/configuration/configure_graphics_advanced.h" | 9 | #include "yuzu/configuration/configure_graphics_advanced.h" |
diff --git a/src/yuzu/configuration/configure_hotkeys.cpp b/src/yuzu/configuration/configure_hotkeys.cpp index cbee51a5e..ed76fe18e 100644 --- a/src/yuzu/configuration/configure_hotkeys.cpp +++ b/src/yuzu/configuration/configure_hotkeys.cpp | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | #include <QMenu> | 5 | #include <QMenu> |
| 6 | #include <QMessageBox> | 6 | #include <QMessageBox> |
| 7 | #include <QStandardItemModel> | 7 | #include <QStandardItemModel> |
| 8 | #include "core/settings.h" | 8 | #include "common/settings.h" |
| 9 | #include "ui_configure_hotkeys.h" | 9 | #include "ui_configure_hotkeys.h" |
| 10 | #include "yuzu/configuration/config.h" | 10 | #include "yuzu/configuration/config.h" |
| 11 | #include "yuzu/configuration/configure_hotkeys.h" | 11 | #include "yuzu/configuration/configure_hotkeys.h" |
diff --git a/src/yuzu/configuration/configure_input_advanced.cpp b/src/yuzu/configuration/configure_input_advanced.cpp index a1a0eb676..d8d3b83dc 100644 --- a/src/yuzu/configuration/configure_input_advanced.cpp +++ b/src/yuzu/configuration/configure_input_advanced.cpp | |||
| @@ -3,8 +3,8 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <QColorDialog> | 5 | #include <QColorDialog> |
| 6 | #include "common/settings.h" | ||
| 6 | #include "core/core.h" | 7 | #include "core/core.h" |
| 7 | #include "core/settings.h" | ||
| 8 | #include "ui_configure_input_advanced.h" | 8 | #include "ui_configure_input_advanced.h" |
| 9 | #include "yuzu/configuration/configure_input_advanced.h" | 9 | #include "yuzu/configuration/configure_input_advanced.h" |
| 10 | 10 | ||
diff --git a/src/yuzu/configuration/configure_input_player.h b/src/yuzu/configuration/configure_input_player.h index efe953fbc..c7d101682 100644 --- a/src/yuzu/configuration/configure_input_player.h +++ b/src/yuzu/configuration/configure_input_player.h | |||
| @@ -14,7 +14,7 @@ | |||
| 14 | #include <QWidget> | 14 | #include <QWidget> |
| 15 | 15 | ||
| 16 | #include "common/param_package.h" | 16 | #include "common/param_package.h" |
| 17 | #include "core/settings.h" | 17 | #include "common/settings.h" |
| 18 | #include "ui_configure_input.h" | 18 | #include "ui_configure_input.h" |
| 19 | 19 | ||
| 20 | class QCheckBox; | 20 | class QCheckBox; |
diff --git a/src/yuzu/configuration/configure_input_player_widget.h b/src/yuzu/configuration/configure_input_player_widget.h index 91c3343f1..51bb84eb6 100644 --- a/src/yuzu/configuration/configure_input_player_widget.h +++ b/src/yuzu/configuration/configure_input_player_widget.h | |||
| @@ -7,8 +7,8 @@ | |||
| 7 | #include <array> | 7 | #include <array> |
| 8 | #include <QFrame> | 8 | #include <QFrame> |
| 9 | #include <QPointer> | 9 | #include <QPointer> |
| 10 | #include "common/settings.h" | ||
| 10 | #include "core/frontend/input.h" | 11 | #include "core/frontend/input.h" |
| 11 | #include "core/settings.h" | ||
| 12 | 12 | ||
| 13 | class QLabel; | 13 | class QLabel; |
| 14 | 14 | ||
diff --git a/src/yuzu/configuration/configure_motion_touch.cpp b/src/yuzu/configuration/configure_motion_touch.cpp index 52fdf7265..6a5d625df 100644 --- a/src/yuzu/configuration/configure_motion_touch.cpp +++ b/src/yuzu/configuration/configure_motion_touch.cpp | |||
| @@ -14,7 +14,7 @@ | |||
| 14 | #include <QVBoxLayout> | 14 | #include <QVBoxLayout> |
| 15 | 15 | ||
| 16 | #include "common/logging/log.h" | 16 | #include "common/logging/log.h" |
| 17 | #include "core/settings.h" | 17 | #include "common/settings.h" |
| 18 | #include "input_common/main.h" | 18 | #include "input_common/main.h" |
| 19 | #include "input_common/udp/client.h" | 19 | #include "input_common/udp/client.h" |
| 20 | #include "input_common/udp/udp.h" | 20 | #include "input_common/udp/udp.h" |
| @@ -23,8 +23,7 @@ | |||
| 23 | #include "yuzu/configuration/configure_touch_from_button.h" | 23 | #include "yuzu/configuration/configure_touch_from_button.h" |
| 24 | 24 | ||
| 25 | CalibrationConfigurationDialog::CalibrationConfigurationDialog(QWidget* parent, | 25 | CalibrationConfigurationDialog::CalibrationConfigurationDialog(QWidget* parent, |
| 26 | const std::string& host, u16 port, | 26 | const std::string& host, u16 port) |
| 27 | u8 pad_index) | ||
| 28 | : QDialog(parent) { | 27 | : QDialog(parent) { |
| 29 | layout = new QVBoxLayout; | 28 | layout = new QVBoxLayout; |
| 30 | status_label = new QLabel(tr("Communicating with the server...")); | 29 | status_label = new QLabel(tr("Communicating with the server...")); |
| @@ -41,7 +40,7 @@ CalibrationConfigurationDialog::CalibrationConfigurationDialog(QWidget* parent, | |||
| 41 | 40 | ||
| 42 | using namespace InputCommon::CemuhookUDP; | 41 | using namespace InputCommon::CemuhookUDP; |
| 43 | job = std::make_unique<CalibrationConfigurationJob>( | 42 | job = std::make_unique<CalibrationConfigurationJob>( |
| 44 | host, port, pad_index, | 43 | host, port, |
| 45 | [this](CalibrationConfigurationJob::Status status) { | 44 | [this](CalibrationConfigurationJob::Status status) { |
| 46 | QString text; | 45 | QString text; |
| 47 | switch (status) { | 46 | switch (status) { |
| @@ -217,7 +216,7 @@ void ConfigureMotionTouch::OnCemuhookUDPTest() { | |||
| 217 | ui->udp_test->setText(tr("Testing")); | 216 | ui->udp_test->setText(tr("Testing")); |
| 218 | udp_test_in_progress = true; | 217 | udp_test_in_progress = true; |
| 219 | InputCommon::CemuhookUDP::TestCommunication( | 218 | InputCommon::CemuhookUDP::TestCommunication( |
| 220 | ui->udp_server->text().toStdString(), static_cast<u16>(ui->udp_port->text().toInt()), 0, | 219 | ui->udp_server->text().toStdString(), static_cast<u16>(ui->udp_port->text().toInt()), |
| 221 | [this] { | 220 | [this] { |
| 222 | LOG_INFO(Frontend, "UDP input test success"); | 221 | LOG_INFO(Frontend, "UDP input test success"); |
| 223 | QMetaObject::invokeMethod(this, "ShowUDPTestResult", Q_ARG(bool, true)); | 222 | QMetaObject::invokeMethod(this, "ShowUDPTestResult", Q_ARG(bool, true)); |
| @@ -232,7 +231,7 @@ void ConfigureMotionTouch::OnConfigureTouchCalibration() { | |||
| 232 | ui->touch_calibration_config->setEnabled(false); | 231 | ui->touch_calibration_config->setEnabled(false); |
| 233 | ui->touch_calibration_config->setText(tr("Configuring")); | 232 | ui->touch_calibration_config->setText(tr("Configuring")); |
| 234 | CalibrationConfigurationDialog dialog(this, ui->udp_server->text().toStdString(), | 233 | CalibrationConfigurationDialog dialog(this, ui->udp_server->text().toStdString(), |
| 235 | static_cast<u16>(ui->udp_port->text().toUInt()), 0); | 234 | static_cast<u16>(ui->udp_port->text().toUInt())); |
| 236 | dialog.exec(); | 235 | dialog.exec(); |
| 237 | if (dialog.completed) { | 236 | if (dialog.completed) { |
| 238 | min_x = dialog.min_x; | 237 | min_x = dialog.min_x; |
diff --git a/src/yuzu/configuration/configure_motion_touch.h b/src/yuzu/configuration/configure_motion_touch.h index d76bc8154..8b707d2ff 100644 --- a/src/yuzu/configuration/configure_motion_touch.h +++ b/src/yuzu/configuration/configure_motion_touch.h | |||
| @@ -29,8 +29,7 @@ class ConfigureMotionTouch; | |||
| 29 | class CalibrationConfigurationDialog : public QDialog { | 29 | class CalibrationConfigurationDialog : public QDialog { |
| 30 | Q_OBJECT | 30 | Q_OBJECT |
| 31 | public: | 31 | public: |
| 32 | explicit CalibrationConfigurationDialog(QWidget* parent, const std::string& host, u16 port, | 32 | explicit CalibrationConfigurationDialog(QWidget* parent, const std::string& host, u16 port); |
| 33 | u8 pad_index); | ||
| 34 | ~CalibrationConfigurationDialog() override; | 33 | ~CalibrationConfigurationDialog() override; |
| 35 | 34 | ||
| 36 | private: | 35 | private: |
diff --git a/src/yuzu/configuration/configure_per_game.cpp b/src/yuzu/configuration/configure_per_game.cpp index f598513df..bd91ebc42 100644 --- a/src/yuzu/configuration/configure_per_game.cpp +++ b/src/yuzu/configuration/configure_per_game.cpp | |||
| @@ -57,7 +57,7 @@ void ConfigurePerGame::ApplyConfiguration() { | |||
| 57 | ui->graphicsAdvancedTab->ApplyConfiguration(); | 57 | ui->graphicsAdvancedTab->ApplyConfiguration(); |
| 58 | ui->audioTab->ApplyConfiguration(); | 58 | ui->audioTab->ApplyConfiguration(); |
| 59 | 59 | ||
| 60 | Settings::Apply(Core::System::GetInstance()); | 60 | Core::System::GetInstance().ApplySettings(); |
| 61 | Settings::LogSettings(); | 61 | Settings::LogSettings(); |
| 62 | 62 | ||
| 63 | game_config->Save(); | 63 | game_config->Save(); |
diff --git a/src/yuzu/configuration/configure_profile_manager.cpp b/src/yuzu/configuration/configure_profile_manager.cpp index 51647a028..d61b5e29b 100644 --- a/src/yuzu/configuration/configure_profile_manager.cpp +++ b/src/yuzu/configuration/configure_profile_manager.cpp | |||
| @@ -13,10 +13,10 @@ | |||
| 13 | #include <QVBoxLayout> | 13 | #include <QVBoxLayout> |
| 14 | #include "common/assert.h" | 14 | #include "common/assert.h" |
| 15 | #include "common/file_util.h" | 15 | #include "common/file_util.h" |
| 16 | #include "common/settings.h" | ||
| 16 | #include "common/string_util.h" | 17 | #include "common/string_util.h" |
| 17 | #include "core/core.h" | 18 | #include "core/core.h" |
| 18 | #include "core/hle/service/acc/profile_manager.h" | 19 | #include "core/hle/service/acc/profile_manager.h" |
| 19 | #include "core/settings.h" | ||
| 20 | #include "ui_configure_profile_manager.h" | 20 | #include "ui_configure_profile_manager.h" |
| 21 | #include "yuzu/configuration/configure_profile_manager.h" | 21 | #include "yuzu/configuration/configure_profile_manager.h" |
| 22 | #include "yuzu/util/limitable_input_dialog.h" | 22 | #include "yuzu/util/limitable_input_dialog.h" |
| @@ -180,7 +180,7 @@ void ConfigureProfileManager::ApplyConfiguration() { | |||
| 180 | return; | 180 | return; |
| 181 | } | 181 | } |
| 182 | 182 | ||
| 183 | Settings::Apply(Core::System::GetInstance()); | 183 | Core::System::GetInstance().ApplySettings(); |
| 184 | } | 184 | } |
| 185 | 185 | ||
| 186 | void ConfigureProfileManager::SelectUser(const QModelIndex& index) { | 186 | void ConfigureProfileManager::SelectUser(const QModelIndex& index) { |
diff --git a/src/yuzu/configuration/configure_service.cpp b/src/yuzu/configuration/configure_service.cpp index b580cfff2..6d954a67f 100644 --- a/src/yuzu/configuration/configure_service.cpp +++ b/src/yuzu/configuration/configure_service.cpp | |||
| @@ -4,8 +4,8 @@ | |||
| 4 | 4 | ||
| 5 | #include <QGraphicsItem> | 5 | #include <QGraphicsItem> |
| 6 | #include <QtConcurrent/QtConcurrent> | 6 | #include <QtConcurrent/QtConcurrent> |
| 7 | #include "common/settings.h" | ||
| 7 | #include "core/hle/service/bcat/backend/boxcat.h" | 8 | #include "core/hle/service/bcat/backend/boxcat.h" |
| 8 | #include "core/settings.h" | ||
| 9 | #include "ui_configure_service.h" | 9 | #include "ui_configure_service.h" |
| 10 | #include "yuzu/configuration/configure_service.h" | 10 | #include "yuzu/configuration/configure_service.h" |
| 11 | 11 | ||
diff --git a/src/yuzu/configuration/configure_system.cpp b/src/yuzu/configuration/configure_system.cpp index 6cf2032da..268ed44c3 100644 --- a/src/yuzu/configuration/configure_system.cpp +++ b/src/yuzu/configuration/configure_system.cpp | |||
| @@ -11,9 +11,9 @@ | |||
| 11 | #include <QMessageBox> | 11 | #include <QMessageBox> |
| 12 | #include "common/assert.h" | 12 | #include "common/assert.h" |
| 13 | #include "common/file_util.h" | 13 | #include "common/file_util.h" |
| 14 | #include "common/settings.h" | ||
| 14 | #include "core/core.h" | 15 | #include "core/core.h" |
| 15 | #include "core/hle/service/time/time.h" | 16 | #include "core/hle/service/time/time.h" |
| 16 | #include "core/settings.h" | ||
| 17 | #include "ui_configure_system.h" | 17 | #include "ui_configure_system.h" |
| 18 | #include "yuzu/configuration/configuration_shared.h" | 18 | #include "yuzu/configuration/configuration_shared.h" |
| 19 | #include "yuzu/configuration/configure_system.h" | 19 | #include "yuzu/configuration/configure_system.h" |
| @@ -199,7 +199,7 @@ void ConfigureSystem::ApplyConfiguration() { | |||
| 199 | } | 199 | } |
| 200 | } | 200 | } |
| 201 | 201 | ||
| 202 | Settings::Apply(system); | 202 | system.ApplySettings(); |
| 203 | } | 203 | } |
| 204 | 204 | ||
| 205 | void ConfigureSystem::RefreshConsoleID() { | 205 | void ConfigureSystem::RefreshConsoleID() { |
diff --git a/src/yuzu/configuration/configure_touch_from_button.cpp b/src/yuzu/configuration/configure_touch_from_button.cpp index 15557e4b8..40129f228 100644 --- a/src/yuzu/configuration/configure_touch_from_button.cpp +++ b/src/yuzu/configuration/configure_touch_from_button.cpp | |||
| @@ -10,8 +10,8 @@ | |||
| 10 | #include <QStandardItemModel> | 10 | #include <QStandardItemModel> |
| 11 | #include <QTimer> | 11 | #include <QTimer> |
| 12 | #include "common/param_package.h" | 12 | #include "common/param_package.h" |
| 13 | #include "common/settings.h" | ||
| 13 | #include "core/frontend/framebuffer_layout.h" | 14 | #include "core/frontend/framebuffer_layout.h" |
| 14 | #include "core/settings.h" | ||
| 15 | #include "input_common/main.h" | 15 | #include "input_common/main.h" |
| 16 | #include "ui_configure_touch_from_button.h" | 16 | #include "ui_configure_touch_from_button.h" |
| 17 | #include "yuzu/configuration/configure_touch_from_button.h" | 17 | #include "yuzu/configuration/configure_touch_from_button.h" |
diff --git a/src/yuzu/configuration/configure_ui.cpp b/src/yuzu/configuration/configure_ui.cpp index aed876008..f35c89e04 100644 --- a/src/yuzu/configuration/configure_ui.cpp +++ b/src/yuzu/configuration/configure_ui.cpp | |||
| @@ -9,8 +9,8 @@ | |||
| 9 | #include <QDirIterator> | 9 | #include <QDirIterator> |
| 10 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 11 | #include "common/file_util.h" | 11 | #include "common/file_util.h" |
| 12 | #include "common/settings.h" | ||
| 12 | #include "core/core.h" | 13 | #include "core/core.h" |
| 13 | #include "core/settings.h" | ||
| 14 | #include "ui_configure_ui.h" | 14 | #include "ui_configure_ui.h" |
| 15 | #include "yuzu/configuration/configure_ui.h" | 15 | #include "yuzu/configuration/configure_ui.h" |
| 16 | #include "yuzu/uisettings.h" | 16 | #include "yuzu/uisettings.h" |
| @@ -85,7 +85,7 @@ void ConfigureUi::ApplyConfiguration() { | |||
| 85 | UISettings::values.enable_screenshot_save_as = ui->enable_screenshot_save_as->isChecked(); | 85 | UISettings::values.enable_screenshot_save_as = ui->enable_screenshot_save_as->isChecked(); |
| 86 | Common::FS::GetUserPath(Common::FS::UserPath::ScreenshotsDir, | 86 | Common::FS::GetUserPath(Common::FS::UserPath::ScreenshotsDir, |
| 87 | ui->screenshot_path_edit->text().toStdString()); | 87 | ui->screenshot_path_edit->text().toStdString()); |
| 88 | Settings::Apply(Core::System::GetInstance()); | 88 | Core::System::GetInstance().ApplySettings(); |
| 89 | } | 89 | } |
| 90 | 90 | ||
| 91 | void ConfigureUi::RequestGameListUpdate() { | 91 | void ConfigureUi::RequestGameListUpdate() { |
diff --git a/src/yuzu/configuration/configure_vibration.cpp b/src/yuzu/configuration/configure_vibration.cpp index 7dcb2c5b9..9d92c4949 100644 --- a/src/yuzu/configuration/configure_vibration.cpp +++ b/src/yuzu/configuration/configure_vibration.cpp | |||
| @@ -8,7 +8,7 @@ | |||
| 8 | #include <fmt/format.h> | 8 | #include <fmt/format.h> |
| 9 | 9 | ||
| 10 | #include "common/param_package.h" | 10 | #include "common/param_package.h" |
| 11 | #include "core/settings.h" | 11 | #include "common/settings.h" |
| 12 | #include "ui_configure_vibration.h" | 12 | #include "ui_configure_vibration.h" |
| 13 | #include "yuzu/configuration/configure_vibration.h" | 13 | #include "yuzu/configuration/configure_vibration.h" |
| 14 | 14 | ||
diff --git a/src/yuzu/configuration/configure_web.cpp b/src/yuzu/configuration/configure_web.cpp index 8637f5b3c..f3f3b54d6 100644 --- a/src/yuzu/configuration/configure_web.cpp +++ b/src/yuzu/configuration/configure_web.cpp | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | #include <QIcon> | 5 | #include <QIcon> |
| 6 | #include <QMessageBox> | 6 | #include <QMessageBox> |
| 7 | #include <QtConcurrent/QtConcurrentRun> | 7 | #include <QtConcurrent/QtConcurrentRun> |
| 8 | #include "core/settings.h" | 8 | #include "common/settings.h" |
| 9 | #include "core/telemetry_session.h" | 9 | #include "core/telemetry_session.h" |
| 10 | #include "ui_configure_web.h" | 10 | #include "ui_configure_web.h" |
| 11 | #include "yuzu/configuration/configure_web.h" | 11 | #include "yuzu/configuration/configure_web.h" |
diff --git a/src/yuzu/debugger/console.cpp b/src/yuzu/debugger/console.cpp index 207ff4d58..c11a326ac 100644 --- a/src/yuzu/debugger/console.cpp +++ b/src/yuzu/debugger/console.cpp | |||
| @@ -29,13 +29,13 @@ void ToggleConsole() { | |||
| 29 | freopen_s(&temp, "CONIN$", "r", stdin); | 29 | freopen_s(&temp, "CONIN$", "r", stdin); |
| 30 | freopen_s(&temp, "CONOUT$", "w", stdout); | 30 | freopen_s(&temp, "CONOUT$", "w", stdout); |
| 31 | freopen_s(&temp, "CONOUT$", "w", stderr); | 31 | freopen_s(&temp, "CONOUT$", "w", stderr); |
| 32 | Log::AddBackend(std::make_unique<Log::ColorConsoleBackend>()); | 32 | Common::Log::AddBackend(std::make_unique<Common::Log::ColorConsoleBackend>()); |
| 33 | } | 33 | } |
| 34 | } else { | 34 | } else { |
| 35 | if (FreeConsole()) { | 35 | if (FreeConsole()) { |
| 36 | // In order to close the console, we have to also detach the streams on it. | 36 | // In order to close the console, we have to also detach the streams on it. |
| 37 | // Just redirect them to NUL if there is no console window | 37 | // Just redirect them to NUL if there is no console window |
| 38 | Log::RemoveBackend(Log::ColorConsoleBackend::Name()); | 38 | Common::Log::RemoveBackend(Common::Log::ColorConsoleBackend::Name()); |
| 39 | freopen_s(&temp, "NUL", "r", stdin); | 39 | freopen_s(&temp, "NUL", "r", stdin); |
| 40 | freopen_s(&temp, "NUL", "w", stdout); | 40 | freopen_s(&temp, "NUL", "w", stdout); |
| 41 | freopen_s(&temp, "NUL", "w", stderr); | 41 | freopen_s(&temp, "NUL", "w", stderr); |
| @@ -43,9 +43,9 @@ void ToggleConsole() { | |||
| 43 | } | 43 | } |
| 44 | #else | 44 | #else |
| 45 | if (UISettings::values.show_console) { | 45 | if (UISettings::values.show_console) { |
| 46 | Log::AddBackend(std::make_unique<Log::ColorConsoleBackend>()); | 46 | Common::Log::AddBackend(std::make_unique<Common::Log::ColorConsoleBackend>()); |
| 47 | } else { | 47 | } else { |
| 48 | Log::RemoveBackend(Log::ColorConsoleBackend::Name()); | 48 | Common::Log::RemoveBackend(Common::Log::ColorConsoleBackend::Name()); |
| 49 | } | 49 | } |
| 50 | #endif | 50 | #endif |
| 51 | } | 51 | } |
diff --git a/src/yuzu/debugger/controller.cpp b/src/yuzu/debugger/controller.cpp index 2731d948d..7186eac76 100644 --- a/src/yuzu/debugger/controller.cpp +++ b/src/yuzu/debugger/controller.cpp | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | #include <QAction> | 5 | #include <QAction> |
| 6 | #include <QLayout> | 6 | #include <QLayout> |
| 7 | #include <QString> | 7 | #include <QString> |
| 8 | #include "core/settings.h" | 8 | #include "common/settings.h" |
| 9 | #include "yuzu/configuration/configure_input_player_widget.h" | 9 | #include "yuzu/configuration/configure_input_player_widget.h" |
| 10 | #include "yuzu/debugger/controller.h" | 10 | #include "yuzu/debugger/controller.h" |
| 11 | 11 | ||
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 24bfa4d34..5f6cdc0c6 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp | |||
| @@ -79,6 +79,7 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual | |||
| 79 | #ifdef ARCHITECTURE_x86_64 | 79 | #ifdef ARCHITECTURE_x86_64 |
| 80 | #include "common/x64/cpu_detect.h" | 80 | #include "common/x64/cpu_detect.h" |
| 81 | #endif | 81 | #endif |
| 82 | #include "common/settings.h" | ||
| 82 | #include "common/telemetry.h" | 83 | #include "common/telemetry.h" |
| 83 | #include "core/core.h" | 84 | #include "core/core.h" |
| 84 | #include "core/crypto/key_manager.h" | 85 | #include "core/crypto/key_manager.h" |
| @@ -98,9 +99,9 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual | |||
| 98 | #include "core/hle/service/sm/sm.h" | 99 | #include "core/hle/service/sm/sm.h" |
| 99 | #include "core/loader/loader.h" | 100 | #include "core/loader/loader.h" |
| 100 | #include "core/perf_stats.h" | 101 | #include "core/perf_stats.h" |
| 101 | #include "core/settings.h" | ||
| 102 | #include "core/telemetry_session.h" | 102 | #include "core/telemetry_session.h" |
| 103 | #include "input_common/main.h" | 103 | #include "input_common/main.h" |
| 104 | #include "util/overlay_dialog.h" | ||
| 104 | #include "video_core/gpu.h" | 105 | #include "video_core/gpu.h" |
| 105 | #include "video_core/shader_notify.h" | 106 | #include "video_core/shader_notify.h" |
| 106 | #include "yuzu/about_dialog.h" | 107 | #include "yuzu/about_dialog.h" |
| @@ -164,19 +165,21 @@ void GMainWindow::ShowTelemetryCallout() { | |||
| 164 | "<br/><br/>Would you like to share your usage data with us?"); | 165 | "<br/><br/>Would you like to share your usage data with us?"); |
| 165 | if (QMessageBox::question(this, tr("Telemetry"), telemetry_message) != QMessageBox::Yes) { | 166 | if (QMessageBox::question(this, tr("Telemetry"), telemetry_message) != QMessageBox::Yes) { |
| 166 | Settings::values.enable_telemetry = false; | 167 | Settings::values.enable_telemetry = false; |
| 167 | Settings::Apply(Core::System::GetInstance()); | 168 | Core::System::GetInstance().ApplySettings(); |
| 168 | } | 169 | } |
| 169 | } | 170 | } |
| 170 | 171 | ||
| 171 | const int GMainWindow::max_recent_files_item; | 172 | const int GMainWindow::max_recent_files_item; |
| 172 | 173 | ||
| 173 | static void InitializeLogging() { | 174 | static void InitializeLogging() { |
| 175 | using namespace Common; | ||
| 176 | |||
| 174 | Log::Filter log_filter; | 177 | Log::Filter log_filter; |
| 175 | log_filter.ParseFilterString(Settings::values.log_filter); | 178 | log_filter.ParseFilterString(Settings::values.log_filter); |
| 176 | Log::SetGlobalFilter(log_filter); | 179 | Log::SetGlobalFilter(log_filter); |
| 177 | 180 | ||
| 178 | const std::string& log_dir = Common::FS::GetUserPath(Common::FS::UserPath::LogDir); | 181 | const std::string& log_dir = FS::GetUserPath(FS::UserPath::LogDir); |
| 179 | Common::FS::CreateFullPath(log_dir); | 182 | FS::CreateFullPath(log_dir); |
| 180 | Log::AddBackend(std::make_unique<Log::FileBackend>(log_dir + LOG_FILE)); | 183 | Log::AddBackend(std::make_unique<Log::FileBackend>(log_dir + LOG_FILE)); |
| 181 | #ifdef _WIN32 | 184 | #ifdef _WIN32 |
| 182 | Log::AddBackend(std::make_unique<Log::DebuggerBackend>()); | 185 | Log::AddBackend(std::make_unique<Log::DebuggerBackend>()); |
| @@ -225,6 +228,8 @@ GMainWindow::GMainWindow() | |||
| 225 | SetDiscordEnabled(UISettings::values.enable_discord_presence); | 228 | SetDiscordEnabled(UISettings::values.enable_discord_presence); |
| 226 | discord_rpc->Update(); | 229 | discord_rpc->Update(); |
| 227 | 230 | ||
| 231 | RegisterMetaTypes(); | ||
| 232 | |||
| 228 | InitializeWidgets(); | 233 | InitializeWidgets(); |
| 229 | InitializeDebugWidgets(); | 234 | InitializeDebugWidgets(); |
| 230 | InitializeRecentFileMenuActions(); | 235 | InitializeRecentFileMenuActions(); |
| @@ -320,6 +325,34 @@ GMainWindow::GMainWindow() | |||
| 320 | continue; | 325 | continue; |
| 321 | } | 326 | } |
| 322 | 327 | ||
| 328 | // Launch game with a specific user | ||
| 329 | if (args[i] == QStringLiteral("-u")) { | ||
| 330 | if (i >= args.size() - 1) { | ||
| 331 | continue; | ||
| 332 | } | ||
| 333 | |||
| 334 | if (args[i + 1].startsWith(QChar::fromLatin1('-'))) { | ||
| 335 | continue; | ||
| 336 | } | ||
| 337 | |||
| 338 | bool argument_ok; | ||
| 339 | const std::size_t selected_user = args[++i].toUInt(&argument_ok); | ||
| 340 | |||
| 341 | if (!argument_ok) { | ||
| 342 | LOG_ERROR(Frontend, "Invalid user argument"); | ||
| 343 | continue; | ||
| 344 | } | ||
| 345 | |||
| 346 | const Service::Account::ProfileManager manager; | ||
| 347 | if (!manager.UserExistsIndex(selected_user)) { | ||
| 348 | LOG_ERROR(Frontend, "Selected user doesn't exist"); | ||
| 349 | continue; | ||
| 350 | } | ||
| 351 | |||
| 352 | Settings::values.current_user = selected_user; | ||
| 353 | continue; | ||
| 354 | } | ||
| 355 | |||
| 323 | // Launch game at path | 356 | // Launch game at path |
| 324 | if (args[i] == QStringLiteral("-g")) { | 357 | if (args[i] == QStringLiteral("-g")) { |
| 325 | if (i >= args.size() - 1) { | 358 | if (i >= args.size() - 1) { |
| @@ -345,6 +378,55 @@ GMainWindow::~GMainWindow() { | |||
| 345 | delete render_window; | 378 | delete render_window; |
| 346 | } | 379 | } |
| 347 | 380 | ||
| 381 | void GMainWindow::RegisterMetaTypes() { | ||
| 382 | // Register integral and floating point types | ||
| 383 | qRegisterMetaType<u8>("u8"); | ||
| 384 | qRegisterMetaType<u16>("u16"); | ||
| 385 | qRegisterMetaType<u32>("u32"); | ||
| 386 | qRegisterMetaType<u64>("u64"); | ||
| 387 | qRegisterMetaType<u128>("u128"); | ||
| 388 | qRegisterMetaType<s8>("s8"); | ||
| 389 | qRegisterMetaType<s16>("s16"); | ||
| 390 | qRegisterMetaType<s32>("s32"); | ||
| 391 | qRegisterMetaType<s64>("s64"); | ||
| 392 | qRegisterMetaType<f32>("f32"); | ||
| 393 | qRegisterMetaType<f64>("f64"); | ||
| 394 | |||
| 395 | // Register string types | ||
| 396 | qRegisterMetaType<std::string>("std::string"); | ||
| 397 | qRegisterMetaType<std::wstring>("std::wstring"); | ||
| 398 | qRegisterMetaType<std::u8string>("std::u8string"); | ||
| 399 | qRegisterMetaType<std::u16string>("std::u16string"); | ||
| 400 | qRegisterMetaType<std::u32string>("std::u32string"); | ||
| 401 | qRegisterMetaType<std::string_view>("std::string_view"); | ||
| 402 | qRegisterMetaType<std::wstring_view>("std::wstring_view"); | ||
| 403 | qRegisterMetaType<std::u8string_view>("std::u8string_view"); | ||
| 404 | qRegisterMetaType<std::u16string_view>("std::u16string_view"); | ||
| 405 | qRegisterMetaType<std::u32string_view>("std::u32string_view"); | ||
| 406 | |||
| 407 | // Register applet types | ||
| 408 | |||
| 409 | // Controller Applet | ||
| 410 | qRegisterMetaType<Core::Frontend::ControllerParameters>("Core::Frontend::ControllerParameters"); | ||
| 411 | |||
| 412 | // Software Keyboard Applet | ||
| 413 | qRegisterMetaType<Core::Frontend::KeyboardInitializeParameters>( | ||
| 414 | "Core::Frontend::KeyboardInitializeParameters"); | ||
| 415 | qRegisterMetaType<Core::Frontend::InlineAppearParameters>( | ||
| 416 | "Core::Frontend::InlineAppearParameters"); | ||
| 417 | qRegisterMetaType<Core::Frontend::InlineTextParameters>("Core::Frontend::InlineTextParameters"); | ||
| 418 | qRegisterMetaType<Service::AM::Applets::SwkbdResult>("Service::AM::Applets::SwkbdResult"); | ||
| 419 | qRegisterMetaType<Service::AM::Applets::SwkbdTextCheckResult>( | ||
| 420 | "Service::AM::Applets::SwkbdTextCheckResult"); | ||
| 421 | qRegisterMetaType<Service::AM::Applets::SwkbdReplyType>("Service::AM::Applets::SwkbdReplyType"); | ||
| 422 | |||
| 423 | // Web Browser Applet | ||
| 424 | qRegisterMetaType<Service::AM::Applets::WebExitReason>("Service::AM::Applets::WebExitReason"); | ||
| 425 | |||
| 426 | // Register loader types | ||
| 427 | qRegisterMetaType<Core::System::ResultStatus>("Core::System::ResultStatus"); | ||
| 428 | } | ||
| 429 | |||
| 348 | void GMainWindow::ControllerSelectorReconfigureControllers( | 430 | void GMainWindow::ControllerSelectorReconfigureControllers( |
| 349 | const Core::Frontend::ControllerParameters& parameters) { | 431 | const Core::Frontend::ControllerParameters& parameters) { |
| 350 | QtControllerSelectorDialog dialog(this, parameters, input_subsystem.get()); | 432 | QtControllerSelectorDialog dialog(this, parameters, input_subsystem.get()); |
| @@ -357,7 +439,7 @@ void GMainWindow::ControllerSelectorReconfigureControllers( | |||
| 357 | emit ControllerSelectorReconfigureFinished(); | 439 | emit ControllerSelectorReconfigureFinished(); |
| 358 | 440 | ||
| 359 | // Don't forget to apply settings. | 441 | // Don't forget to apply settings. |
| 360 | Settings::Apply(Core::System::GetInstance()); | 442 | Core::System::GetInstance().ApplySettings(); |
| 361 | config->Save(); | 443 | config->Save(); |
| 362 | 444 | ||
| 363 | UpdateStatusButtons(); | 445 | UpdateStatusButtons(); |
| @@ -384,25 +466,112 @@ void GMainWindow::ProfileSelectorSelectProfile() { | |||
| 384 | emit ProfileSelectorFinishedSelection(uuid); | 466 | emit ProfileSelectorFinishedSelection(uuid); |
| 385 | } | 467 | } |
| 386 | 468 | ||
| 387 | void GMainWindow::SoftwareKeyboardGetText( | 469 | void GMainWindow::SoftwareKeyboardInitialize( |
| 388 | const Core::Frontend::SoftwareKeyboardParameters& parameters) { | 470 | bool is_inline, Core::Frontend::KeyboardInitializeParameters initialize_parameters) { |
| 389 | QtSoftwareKeyboardDialog dialog(this, parameters); | 471 | if (software_keyboard) { |
| 390 | dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint | | 472 | LOG_ERROR(Frontend, "The software keyboard is already initialized!"); |
| 391 | Qt::WindowTitleHint | Qt::WindowSystemMenuHint | | 473 | return; |
| 392 | Qt::WindowCloseButtonHint); | 474 | } |
| 393 | dialog.setWindowModality(Qt::WindowModal); | ||
| 394 | 475 | ||
| 395 | if (dialog.exec() == QDialog::Rejected) { | 476 | software_keyboard = new QtSoftwareKeyboardDialog(render_window, Core::System::GetInstance(), |
| 396 | emit SoftwareKeyboardFinishedText(std::nullopt); | 477 | is_inline, std::move(initialize_parameters)); |
| 478 | |||
| 479 | if (is_inline) { | ||
| 480 | connect( | ||
| 481 | software_keyboard, &QtSoftwareKeyboardDialog::SubmitInlineText, this, | ||
| 482 | [this](Service::AM::Applets::SwkbdReplyType reply_type, std::u16string submitted_text, | ||
| 483 | s32 cursor_position) { | ||
| 484 | emit SoftwareKeyboardSubmitInlineText(reply_type, submitted_text, cursor_position); | ||
| 485 | }, | ||
| 486 | Qt::QueuedConnection); | ||
| 487 | } else { | ||
| 488 | connect( | ||
| 489 | software_keyboard, &QtSoftwareKeyboardDialog::SubmitNormalText, this, | ||
| 490 | [this](Service::AM::Applets::SwkbdResult result, std::u16string submitted_text) { | ||
| 491 | emit SoftwareKeyboardSubmitNormalText(result, submitted_text); | ||
| 492 | }, | ||
| 493 | Qt::QueuedConnection); | ||
| 494 | } | ||
| 495 | } | ||
| 496 | |||
| 497 | void GMainWindow::SoftwareKeyboardShowNormal() { | ||
| 498 | if (!software_keyboard) { | ||
| 499 | LOG_ERROR(Frontend, "The software keyboard is not initialized!"); | ||
| 500 | return; | ||
| 501 | } | ||
| 502 | |||
| 503 | const auto& layout = render_window->GetFramebufferLayout(); | ||
| 504 | |||
| 505 | const auto x = layout.screen.left; | ||
| 506 | const auto y = layout.screen.top; | ||
| 507 | const auto w = layout.screen.GetWidth(); | ||
| 508 | const auto h = layout.screen.GetHeight(); | ||
| 509 | |||
| 510 | software_keyboard->ShowNormalKeyboard(render_window->mapToGlobal(QPoint(x, y)), QSize(w, h)); | ||
| 511 | } | ||
| 512 | |||
| 513 | void GMainWindow::SoftwareKeyboardShowTextCheck( | ||
| 514 | Service::AM::Applets::SwkbdTextCheckResult text_check_result, | ||
| 515 | std::u16string text_check_message) { | ||
| 516 | if (!software_keyboard) { | ||
| 517 | LOG_ERROR(Frontend, "The software keyboard is not initialized!"); | ||
| 397 | return; | 518 | return; |
| 398 | } | 519 | } |
| 399 | 520 | ||
| 400 | emit SoftwareKeyboardFinishedText(dialog.GetText()); | 521 | software_keyboard->ShowTextCheckDialog(text_check_result, text_check_message); |
| 401 | } | 522 | } |
| 402 | 523 | ||
| 403 | void GMainWindow::SoftwareKeyboardInvokeCheckDialog(std::u16string error_message) { | 524 | void GMainWindow::SoftwareKeyboardShowInline( |
| 404 | QMessageBox::warning(this, tr("Text Check Failed"), QString::fromStdU16String(error_message)); | 525 | Core::Frontend::InlineAppearParameters appear_parameters) { |
| 405 | emit SoftwareKeyboardFinishedCheckDialog(); | 526 | if (!software_keyboard) { |
| 527 | LOG_ERROR(Frontend, "The software keyboard is not initialized!"); | ||
| 528 | return; | ||
| 529 | } | ||
| 530 | |||
| 531 | const auto& layout = render_window->GetFramebufferLayout(); | ||
| 532 | |||
| 533 | const auto x = | ||
| 534 | static_cast<int>(layout.screen.left + (0.5f * layout.screen.GetWidth() * | ||
| 535 | ((2.0f * appear_parameters.key_top_translate_x) + | ||
| 536 | (1.0f - appear_parameters.key_top_scale_x)))); | ||
| 537 | const auto y = | ||
| 538 | static_cast<int>(layout.screen.top + (layout.screen.GetHeight() * | ||
| 539 | ((2.0f * appear_parameters.key_top_translate_y) + | ||
| 540 | (1.0f - appear_parameters.key_top_scale_y)))); | ||
| 541 | const auto w = static_cast<int>(layout.screen.GetWidth() * appear_parameters.key_top_scale_x); | ||
| 542 | const auto h = static_cast<int>(layout.screen.GetHeight() * appear_parameters.key_top_scale_y); | ||
| 543 | |||
| 544 | software_keyboard->ShowInlineKeyboard(std::move(appear_parameters), | ||
| 545 | render_window->mapToGlobal(QPoint(x, y)), QSize(w, h)); | ||
| 546 | } | ||
| 547 | |||
| 548 | void GMainWindow::SoftwareKeyboardHideInline() { | ||
| 549 | if (!software_keyboard) { | ||
| 550 | LOG_ERROR(Frontend, "The software keyboard is not initialized!"); | ||
| 551 | return; | ||
| 552 | } | ||
| 553 | |||
| 554 | software_keyboard->HideInlineKeyboard(); | ||
| 555 | } | ||
| 556 | |||
| 557 | void GMainWindow::SoftwareKeyboardInlineTextChanged( | ||
| 558 | Core::Frontend::InlineTextParameters text_parameters) { | ||
| 559 | if (!software_keyboard) { | ||
| 560 | LOG_ERROR(Frontend, "The software keyboard is not initialized!"); | ||
| 561 | return; | ||
| 562 | } | ||
| 563 | |||
| 564 | software_keyboard->InlineTextChanged(std::move(text_parameters)); | ||
| 565 | } | ||
| 566 | |||
| 567 | void GMainWindow::SoftwareKeyboardExit() { | ||
| 568 | if (!software_keyboard) { | ||
| 569 | return; | ||
| 570 | } | ||
| 571 | |||
| 572 | software_keyboard->ExitKeyboard(); | ||
| 573 | |||
| 574 | software_keyboard = nullptr; | ||
| 406 | } | 575 | } |
| 407 | 576 | ||
| 408 | void GMainWindow::WebBrowserOpenWebPage(std::string_view main_url, std::string_view additional_args, | 577 | void GMainWindow::WebBrowserOpenWebPage(std::string_view main_url, std::string_view additional_args, |
| @@ -622,7 +791,7 @@ void GMainWindow::InitializeWidgets() { | |||
| 622 | Settings::values.use_asynchronous_gpu_emulation.SetValue( | 791 | Settings::values.use_asynchronous_gpu_emulation.SetValue( |
| 623 | !Settings::values.use_asynchronous_gpu_emulation.GetValue()); | 792 | !Settings::values.use_asynchronous_gpu_emulation.GetValue()); |
| 624 | async_status_button->setChecked(Settings::values.use_asynchronous_gpu_emulation.GetValue()); | 793 | async_status_button->setChecked(Settings::values.use_asynchronous_gpu_emulation.GetValue()); |
| 625 | Settings::Apply(Core::System::GetInstance()); | 794 | Core::System::GetInstance().ApplySettings(); |
| 626 | }); | 795 | }); |
| 627 | async_status_button->setText(tr("ASYNC")); | 796 | async_status_button->setText(tr("ASYNC")); |
| 628 | async_status_button->setCheckable(true); | 797 | async_status_button->setCheckable(true); |
| @@ -638,7 +807,7 @@ void GMainWindow::InitializeWidgets() { | |||
| 638 | } | 807 | } |
| 639 | Settings::values.use_multi_core.SetValue(!Settings::values.use_multi_core.GetValue()); | 808 | Settings::values.use_multi_core.SetValue(!Settings::values.use_multi_core.GetValue()); |
| 640 | multicore_status_button->setChecked(Settings::values.use_multi_core.GetValue()); | 809 | multicore_status_button->setChecked(Settings::values.use_multi_core.GetValue()); |
| 641 | Settings::Apply(Core::System::GetInstance()); | 810 | Core::System::GetInstance().ApplySettings(); |
| 642 | }); | 811 | }); |
| 643 | multicore_status_button->setText(tr("MULTICORE")); | 812 | multicore_status_button->setText(tr("MULTICORE")); |
| 644 | multicore_status_button->setCheckable(true); | 813 | multicore_status_button->setCheckable(true); |
| @@ -669,7 +838,7 @@ void GMainWindow::InitializeWidgets() { | |||
| 669 | Settings::values.renderer_backend.SetValue(Settings::RendererBackend::OpenGL); | 838 | Settings::values.renderer_backend.SetValue(Settings::RendererBackend::OpenGL); |
| 670 | } | 839 | } |
| 671 | 840 | ||
| 672 | Settings::Apply(Core::System::GetInstance()); | 841 | Core::System::GetInstance().ApplySettings(); |
| 673 | }); | 842 | }); |
| 674 | statusBar()->insertPermanentWidget(0, renderer_status_button); | 843 | statusBar()->insertPermanentWidget(0, renderer_status_button); |
| 675 | 844 | ||
| @@ -948,6 +1117,10 @@ void GMainWindow::ConnectWidgetEvents() { | |||
| 948 | connect(this, &GMainWindow::EmulationStopping, render_window, | 1117 | connect(this, &GMainWindow::EmulationStopping, render_window, |
| 949 | &GRenderWindow::OnEmulationStopping); | 1118 | &GRenderWindow::OnEmulationStopping); |
| 950 | 1119 | ||
| 1120 | // Software Keyboard Applet | ||
| 1121 | connect(this, &GMainWindow::EmulationStarting, this, &GMainWindow::SoftwareKeyboardExit); | ||
| 1122 | connect(this, &GMainWindow::EmulationStopping, this, &GMainWindow::SoftwareKeyboardExit); | ||
| 1123 | |||
| 951 | connect(&status_bar_update_timer, &QTimer::timeout, this, &GMainWindow::UpdateStatusBar); | 1124 | connect(&status_bar_update_timer, &QTimer::timeout, this, &GMainWindow::UpdateStatusBar); |
| 952 | } | 1125 | } |
| 953 | 1126 | ||
| @@ -2157,15 +2330,6 @@ void GMainWindow::OnStartGame() { | |||
| 2157 | 2330 | ||
| 2158 | emu_thread->SetRunning(true); | 2331 | emu_thread->SetRunning(true); |
| 2159 | 2332 | ||
| 2160 | qRegisterMetaType<Core::Frontend::ControllerParameters>("Core::Frontend::ControllerParameters"); | ||
| 2161 | qRegisterMetaType<Core::Frontend::SoftwareKeyboardParameters>( | ||
| 2162 | "Core::Frontend::SoftwareKeyboardParameters"); | ||
| 2163 | qRegisterMetaType<Core::System::ResultStatus>("Core::System::ResultStatus"); | ||
| 2164 | qRegisterMetaType<std::string>("std::string"); | ||
| 2165 | qRegisterMetaType<std::optional<std::u16string>>("std::optional<std::u16string>"); | ||
| 2166 | qRegisterMetaType<std::string_view>("std::string_view"); | ||
| 2167 | qRegisterMetaType<Service::AM::Applets::WebExitReason>("Service::AM::Applets::WebExitReason"); | ||
| 2168 | |||
| 2169 | connect(emu_thread.get(), &EmuThread::ErrorThrown, this, &GMainWindow::OnCoreError); | 2333 | connect(emu_thread.get(), &EmuThread::ErrorThrown, this, &GMainWindow::OnCoreError); |
| 2170 | 2334 | ||
| 2171 | ui.action_Start->setEnabled(false); | 2335 | ui.action_Start->setEnabled(false); |
| @@ -2214,8 +2378,11 @@ void GMainWindow::OnExecuteProgram(std::size_t program_index) { | |||
| 2214 | BootGame(last_filename_booted, program_index); | 2378 | BootGame(last_filename_booted, program_index); |
| 2215 | } | 2379 | } |
| 2216 | 2380 | ||
| 2217 | void GMainWindow::ErrorDisplayDisplayError(QString body) { | 2381 | void GMainWindow::ErrorDisplayDisplayError(QString error_code, QString error_text) { |
| 2218 | QMessageBox::critical(this, tr("Error Display"), body); | 2382 | OverlayDialog dialog(render_window, Core::System::GetInstance(), error_code, error_text, |
| 2383 | QString{}, tr("OK"), Qt::AlignLeft | Qt::AlignVCenter); | ||
| 2384 | dialog.exec(); | ||
| 2385 | |||
| 2219 | emit ErrorDisplayFinished(); | 2386 | emit ErrorDisplayFinished(); |
| 2220 | } | 2387 | } |
| 2221 | 2388 | ||
| @@ -2267,24 +2434,66 @@ void GMainWindow::ToggleFullscreen() { | |||
| 2267 | void GMainWindow::ShowFullscreen() { | 2434 | void GMainWindow::ShowFullscreen() { |
| 2268 | if (ui.action_Single_Window_Mode->isChecked()) { | 2435 | if (ui.action_Single_Window_Mode->isChecked()) { |
| 2269 | UISettings::values.geometry = saveGeometry(); | 2436 | UISettings::values.geometry = saveGeometry(); |
| 2437 | |||
| 2270 | ui.menubar->hide(); | 2438 | ui.menubar->hide(); |
| 2271 | statusBar()->hide(); | 2439 | statusBar()->hide(); |
| 2272 | showFullScreen(); | 2440 | |
| 2441 | if (Settings::values.fullscreen_mode.GetValue() == 1) { | ||
| 2442 | showFullScreen(); | ||
| 2443 | return; | ||
| 2444 | } | ||
| 2445 | |||
| 2446 | hide(); | ||
| 2447 | setWindowFlags(windowFlags() | Qt::FramelessWindowHint); | ||
| 2448 | const auto screen_geometry = QApplication::desktop()->screenGeometry(this); | ||
| 2449 | setGeometry(screen_geometry.x(), screen_geometry.y(), screen_geometry.width(), | ||
| 2450 | screen_geometry.height() + 1); | ||
| 2451 | raise(); | ||
| 2452 | showNormal(); | ||
| 2273 | } else { | 2453 | } else { |
| 2274 | UISettings::values.renderwindow_geometry = render_window->saveGeometry(); | 2454 | UISettings::values.renderwindow_geometry = render_window->saveGeometry(); |
| 2275 | render_window->showFullScreen(); | 2455 | |
| 2456 | if (Settings::values.fullscreen_mode.GetValue() == 1) { | ||
| 2457 | render_window->showFullScreen(); | ||
| 2458 | return; | ||
| 2459 | } | ||
| 2460 | |||
| 2461 | render_window->hide(); | ||
| 2462 | render_window->setWindowFlags(windowFlags() | Qt::FramelessWindowHint); | ||
| 2463 | const auto screen_geometry = QApplication::desktop()->screenGeometry(this); | ||
| 2464 | render_window->setGeometry(screen_geometry.x(), screen_geometry.y(), | ||
| 2465 | screen_geometry.width(), screen_geometry.height() + 1); | ||
| 2466 | render_window->raise(); | ||
| 2467 | render_window->showNormal(); | ||
| 2276 | } | 2468 | } |
| 2277 | } | 2469 | } |
| 2278 | 2470 | ||
| 2279 | void GMainWindow::HideFullscreen() { | 2471 | void GMainWindow::HideFullscreen() { |
| 2280 | if (ui.action_Single_Window_Mode->isChecked()) { | 2472 | if (ui.action_Single_Window_Mode->isChecked()) { |
| 2473 | if (Settings::values.fullscreen_mode.GetValue() == 1) { | ||
| 2474 | showNormal(); | ||
| 2475 | restoreGeometry(UISettings::values.geometry); | ||
| 2476 | } else { | ||
| 2477 | hide(); | ||
| 2478 | setWindowFlags(windowFlags() & ~Qt::FramelessWindowHint); | ||
| 2479 | restoreGeometry(UISettings::values.geometry); | ||
| 2480 | raise(); | ||
| 2481 | show(); | ||
| 2482 | } | ||
| 2483 | |||
| 2281 | statusBar()->setVisible(ui.action_Show_Status_Bar->isChecked()); | 2484 | statusBar()->setVisible(ui.action_Show_Status_Bar->isChecked()); |
| 2282 | ui.menubar->show(); | 2485 | ui.menubar->show(); |
| 2283 | showNormal(); | ||
| 2284 | restoreGeometry(UISettings::values.geometry); | ||
| 2285 | } else { | 2486 | } else { |
| 2286 | render_window->showNormal(); | 2487 | if (Settings::values.fullscreen_mode.GetValue() == 1) { |
| 2287 | render_window->restoreGeometry(UISettings::values.renderwindow_geometry); | 2488 | render_window->showNormal(); |
| 2489 | render_window->restoreGeometry(UISettings::values.renderwindow_geometry); | ||
| 2490 | } else { | ||
| 2491 | render_window->hide(); | ||
| 2492 | render_window->setWindowFlags(windowFlags() & ~Qt::FramelessWindowHint); | ||
| 2493 | render_window->restoreGeometry(UISettings::values.renderwindow_geometry); | ||
| 2494 | render_window->raise(); | ||
| 2495 | render_window->show(); | ||
| 2496 | } | ||
| 2288 | } | 2497 | } |
| 2289 | } | 2498 | } |
| 2290 | 2499 | ||
diff --git a/src/yuzu/main.h b/src/yuzu/main.h index 04d37d4ae..7f1e50a5b 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h | |||
| @@ -37,9 +37,13 @@ enum class GameListRemoveTarget; | |||
| 37 | enum class InstalledEntryType; | 37 | enum class InstalledEntryType; |
| 38 | class GameListPlaceholder; | 38 | class GameListPlaceholder; |
| 39 | 39 | ||
| 40 | class QtSoftwareKeyboardDialog; | ||
| 41 | |||
| 40 | namespace Core::Frontend { | 42 | namespace Core::Frontend { |
| 41 | struct ControllerParameters; | 43 | struct ControllerParameters; |
| 42 | struct SoftwareKeyboardParameters; | 44 | struct InlineAppearParameters; |
| 45 | struct InlineTextParameters; | ||
| 46 | struct KeyboardInitializeParameters; | ||
| 43 | } // namespace Core::Frontend | 47 | } // namespace Core::Frontend |
| 44 | 48 | ||
| 45 | namespace DiscordRPC { | 49 | namespace DiscordRPC { |
| @@ -57,8 +61,11 @@ class InputSubsystem; | |||
| 57 | } | 61 | } |
| 58 | 62 | ||
| 59 | namespace Service::AM::Applets { | 63 | namespace Service::AM::Applets { |
| 64 | enum class SwkbdResult : u32; | ||
| 65 | enum class SwkbdTextCheckResult : u32; | ||
| 66 | enum class SwkbdReplyType : u32; | ||
| 60 | enum class WebExitReason : u32; | 67 | enum class WebExitReason : u32; |
| 61 | } | 68 | } // namespace Service::AM::Applets |
| 62 | 69 | ||
| 63 | enum class EmulatedDirectoryTarget { | 70 | enum class EmulatedDirectoryTarget { |
| 64 | NAND, | 71 | NAND, |
| @@ -128,8 +135,10 @@ signals: | |||
| 128 | 135 | ||
| 129 | void ProfileSelectorFinishedSelection(std::optional<Common::UUID> uuid); | 136 | void ProfileSelectorFinishedSelection(std::optional<Common::UUID> uuid); |
| 130 | 137 | ||
| 131 | void SoftwareKeyboardFinishedText(std::optional<std::u16string> text); | 138 | void SoftwareKeyboardSubmitNormalText(Service::AM::Applets::SwkbdResult result, |
| 132 | void SoftwareKeyboardFinishedCheckDialog(); | 139 | std::u16string submitted_text); |
| 140 | void SoftwareKeyboardSubmitInlineText(Service::AM::Applets::SwkbdReplyType reply_type, | ||
| 141 | std::u16string submitted_text, s32 cursor_position); | ||
| 133 | 142 | ||
| 134 | void WebBrowserExtractOfflineRomFS(); | 143 | void WebBrowserExtractOfflineRomFS(); |
| 135 | void WebBrowserClosed(Service::AM::Applets::WebExitReason exit_reason, std::string last_url); | 144 | void WebBrowserClosed(Service::AM::Applets::WebExitReason exit_reason, std::string last_url); |
| @@ -139,15 +148,24 @@ public slots: | |||
| 139 | void OnExecuteProgram(std::size_t program_index); | 148 | void OnExecuteProgram(std::size_t program_index); |
| 140 | void ControllerSelectorReconfigureControllers( | 149 | void ControllerSelectorReconfigureControllers( |
| 141 | const Core::Frontend::ControllerParameters& parameters); | 150 | const Core::Frontend::ControllerParameters& parameters); |
| 142 | void ErrorDisplayDisplayError(QString body); | 151 | void SoftwareKeyboardInitialize( |
| 152 | bool is_inline, Core::Frontend::KeyboardInitializeParameters initialize_parameters); | ||
| 153 | void SoftwareKeyboardShowNormal(); | ||
| 154 | void SoftwareKeyboardShowTextCheck(Service::AM::Applets::SwkbdTextCheckResult text_check_result, | ||
| 155 | std::u16string text_check_message); | ||
| 156 | void SoftwareKeyboardShowInline(Core::Frontend::InlineAppearParameters appear_parameters); | ||
| 157 | void SoftwareKeyboardHideInline(); | ||
| 158 | void SoftwareKeyboardInlineTextChanged(Core::Frontend::InlineTextParameters text_parameters); | ||
| 159 | void SoftwareKeyboardExit(); | ||
| 160 | void ErrorDisplayDisplayError(QString error_code, QString error_text); | ||
| 143 | void ProfileSelectorSelectProfile(); | 161 | void ProfileSelectorSelectProfile(); |
| 144 | void SoftwareKeyboardGetText(const Core::Frontend::SoftwareKeyboardParameters& parameters); | ||
| 145 | void SoftwareKeyboardInvokeCheckDialog(std::u16string error_message); | ||
| 146 | void WebBrowserOpenWebPage(std::string_view main_url, std::string_view additional_args, | 162 | void WebBrowserOpenWebPage(std::string_view main_url, std::string_view additional_args, |
| 147 | bool is_local); | 163 | bool is_local); |
| 148 | void OnAppFocusStateChanged(Qt::ApplicationState state); | 164 | void OnAppFocusStateChanged(Qt::ApplicationState state); |
| 149 | 165 | ||
| 150 | private: | 166 | private: |
| 167 | void RegisterMetaTypes(); | ||
| 168 | |||
| 151 | void InitializeWidgets(); | 169 | void InitializeWidgets(); |
| 152 | void InitializeDebugWidgets(); | 170 | void InitializeDebugWidgets(); |
| 153 | void InitializeRecentFileMenuActions(); | 171 | void InitializeRecentFileMenuActions(); |
| @@ -334,6 +352,9 @@ private: | |||
| 334 | // Disables the web applet for the rest of the emulated session | 352 | // Disables the web applet for the rest of the emulated session |
| 335 | bool disable_web_applet{}; | 353 | bool disable_web_applet{}; |
| 336 | 354 | ||
| 355 | // Applets | ||
| 356 | QtSoftwareKeyboardDialog* software_keyboard = nullptr; | ||
| 357 | |||
| 337 | protected: | 358 | protected: |
| 338 | void dropEvent(QDropEvent* event) override; | 359 | void dropEvent(QDropEvent* event) override; |
| 339 | void dragEnterEvent(QDragEnterEvent* event) override; | 360 | void dragEnterEvent(QDragEnterEvent* event) override; |
diff --git a/src/yuzu/util/overlay_dialog.cpp b/src/yuzu/util/overlay_dialog.cpp new file mode 100644 index 000000000..95b148545 --- /dev/null +++ b/src/yuzu/util/overlay_dialog.cpp | |||
| @@ -0,0 +1,249 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <QKeyEvent> | ||
| 6 | #include <QScreen> | ||
| 7 | |||
| 8 | #include "core/core.h" | ||
| 9 | #include "core/frontend/input_interpreter.h" | ||
| 10 | #include "ui_overlay_dialog.h" | ||
| 11 | #include "yuzu/util/overlay_dialog.h" | ||
| 12 | |||
| 13 | namespace { | ||
| 14 | |||
| 15 | constexpr float BASE_TITLE_FONT_SIZE = 14.0f; | ||
| 16 | constexpr float BASE_FONT_SIZE = 18.0f; | ||
| 17 | constexpr float BASE_WIDTH = 1280.0f; | ||
| 18 | constexpr float BASE_HEIGHT = 720.0f; | ||
| 19 | |||
| 20 | } // Anonymous namespace | ||
| 21 | |||
| 22 | OverlayDialog::OverlayDialog(QWidget* parent, Core::System& system, const QString& title_text, | ||
| 23 | const QString& body_text, const QString& left_button_text, | ||
| 24 | const QString& right_button_text, Qt::Alignment alignment, | ||
| 25 | bool use_rich_text_) | ||
| 26 | : QDialog(parent), ui{std::make_unique<Ui::OverlayDialog>()}, use_rich_text{use_rich_text_} { | ||
| 27 | ui->setupUi(this); | ||
| 28 | |||
| 29 | setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint | Qt::WindowTitleHint | | ||
| 30 | Qt::WindowSystemMenuHint | Qt::CustomizeWindowHint); | ||
| 31 | setWindowModality(Qt::WindowModal); | ||
| 32 | setAttribute(Qt::WA_TranslucentBackground); | ||
| 33 | |||
| 34 | if (use_rich_text) { | ||
| 35 | InitializeRichTextDialog(title_text, body_text, left_button_text, right_button_text, | ||
| 36 | alignment); | ||
| 37 | } else { | ||
| 38 | InitializeRegularTextDialog(title_text, body_text, left_button_text, right_button_text, | ||
| 39 | alignment); | ||
| 40 | } | ||
| 41 | |||
| 42 | MoveAndResizeWindow(); | ||
| 43 | |||
| 44 | // TODO (Morph): Remove this when InputInterpreter no longer relies on the HID backend | ||
| 45 | if (system.IsPoweredOn()) { | ||
| 46 | input_interpreter = std::make_unique<InputInterpreter>(system); | ||
| 47 | |||
| 48 | StartInputThread(); | ||
| 49 | } | ||
| 50 | } | ||
| 51 | |||
| 52 | OverlayDialog::~OverlayDialog() { | ||
| 53 | StopInputThread(); | ||
| 54 | } | ||
| 55 | |||
| 56 | void OverlayDialog::InitializeRegularTextDialog(const QString& title_text, const QString& body_text, | ||
| 57 | const QString& left_button_text, | ||
| 58 | const QString& right_button_text, | ||
| 59 | Qt::Alignment alignment) { | ||
| 60 | ui->stackedDialog->setCurrentIndex(0); | ||
| 61 | |||
| 62 | ui->label_title->setText(title_text); | ||
| 63 | ui->label_dialog->setText(body_text); | ||
| 64 | ui->button_cancel->setText(left_button_text); | ||
| 65 | ui->button_ok_label->setText(right_button_text); | ||
| 66 | |||
| 67 | ui->label_dialog->setAlignment(alignment); | ||
| 68 | |||
| 69 | if (title_text.isEmpty()) { | ||
| 70 | ui->label_title->hide(); | ||
| 71 | ui->verticalLayout_2->setStretch(0, 0); | ||
| 72 | ui->verticalLayout_2->setStretch(1, 219); | ||
| 73 | ui->verticalLayout_2->setStretch(2, 82); | ||
| 74 | } | ||
| 75 | |||
| 76 | if (left_button_text.isEmpty()) { | ||
| 77 | ui->button_cancel->hide(); | ||
| 78 | ui->button_cancel->setEnabled(false); | ||
| 79 | } | ||
| 80 | |||
| 81 | if (right_button_text.isEmpty()) { | ||
| 82 | ui->button_ok_label->hide(); | ||
| 83 | ui->button_ok_label->setEnabled(false); | ||
| 84 | } | ||
| 85 | |||
| 86 | connect( | ||
| 87 | ui->button_cancel, &QPushButton::clicked, this, | ||
| 88 | [this](bool) { | ||
| 89 | StopInputThread(); | ||
| 90 | QDialog::reject(); | ||
| 91 | }, | ||
| 92 | Qt::QueuedConnection); | ||
| 93 | connect( | ||
| 94 | ui->button_ok_label, &QPushButton::clicked, this, | ||
| 95 | [this](bool) { | ||
| 96 | StopInputThread(); | ||
| 97 | QDialog::accept(); | ||
| 98 | }, | ||
| 99 | Qt::QueuedConnection); | ||
| 100 | } | ||
| 101 | |||
| 102 | void OverlayDialog::InitializeRichTextDialog(const QString& title_text, const QString& body_text, | ||
| 103 | const QString& left_button_text, | ||
| 104 | const QString& right_button_text, | ||
| 105 | Qt::Alignment alignment) { | ||
| 106 | ui->stackedDialog->setCurrentIndex(1); | ||
| 107 | |||
| 108 | ui->label_title_rich->setText(title_text); | ||
| 109 | ui->text_browser_dialog->setText(body_text); | ||
| 110 | ui->button_cancel_rich->setText(left_button_text); | ||
| 111 | ui->button_ok_rich->setText(right_button_text); | ||
| 112 | |||
| 113 | // TODO (Morph/Rei): Replace this with something that works better | ||
| 114 | ui->text_browser_dialog->setAlignment(alignment); | ||
| 115 | |||
| 116 | if (title_text.isEmpty()) { | ||
| 117 | ui->label_title_rich->hide(); | ||
| 118 | ui->verticalLayout_3->setStretch(0, 0); | ||
| 119 | ui->verticalLayout_3->setStretch(1, 438); | ||
| 120 | ui->verticalLayout_3->setStretch(2, 82); | ||
| 121 | } | ||
| 122 | |||
| 123 | if (left_button_text.isEmpty()) { | ||
| 124 | ui->button_cancel_rich->hide(); | ||
| 125 | ui->button_cancel_rich->setEnabled(false); | ||
| 126 | } | ||
| 127 | |||
| 128 | if (right_button_text.isEmpty()) { | ||
| 129 | ui->button_ok_rich->hide(); | ||
| 130 | ui->button_ok_rich->setEnabled(false); | ||
| 131 | } | ||
| 132 | |||
| 133 | connect( | ||
| 134 | ui->button_cancel_rich, &QPushButton::clicked, this, | ||
| 135 | [this](bool) { | ||
| 136 | StopInputThread(); | ||
| 137 | QDialog::reject(); | ||
| 138 | }, | ||
| 139 | Qt::QueuedConnection); | ||
| 140 | connect( | ||
| 141 | ui->button_ok_rich, &QPushButton::clicked, this, | ||
| 142 | [this](bool) { | ||
| 143 | StopInputThread(); | ||
| 144 | QDialog::accept(); | ||
| 145 | }, | ||
| 146 | Qt::QueuedConnection); | ||
| 147 | } | ||
| 148 | |||
| 149 | void OverlayDialog::MoveAndResizeWindow() { | ||
| 150 | const auto pos = parentWidget()->mapToGlobal(parentWidget()->rect().topLeft()); | ||
| 151 | const auto width = static_cast<float>(parentWidget()->width()); | ||
| 152 | const auto height = static_cast<float>(parentWidget()->height()); | ||
| 153 | |||
| 154 | // High DPI | ||
| 155 | const float dpi_scale = qApp->screenAt(pos)->logicalDotsPerInch() / 96.0f; | ||
| 156 | |||
| 157 | const auto title_text_font_size = BASE_TITLE_FONT_SIZE * (height / BASE_HEIGHT) / dpi_scale; | ||
| 158 | const auto body_text_font_size = | ||
| 159 | BASE_FONT_SIZE * (((width / BASE_WIDTH) + (height / BASE_HEIGHT)) / 2.0f) / dpi_scale; | ||
| 160 | const auto button_text_font_size = BASE_FONT_SIZE * (height / BASE_HEIGHT) / dpi_scale; | ||
| 161 | |||
| 162 | QFont title_text_font(QStringLiteral("MS Shell Dlg 2"), title_text_font_size, QFont::Normal); | ||
| 163 | QFont body_text_font(QStringLiteral("MS Shell Dlg 2"), body_text_font_size, QFont::Normal); | ||
| 164 | QFont button_text_font(QStringLiteral("MS Shell Dlg 2"), button_text_font_size, QFont::Normal); | ||
| 165 | |||
| 166 | if (use_rich_text) { | ||
| 167 | ui->label_title_rich->setFont(title_text_font); | ||
| 168 | ui->text_browser_dialog->setFont(body_text_font); | ||
| 169 | ui->button_cancel_rich->setFont(button_text_font); | ||
| 170 | ui->button_ok_rich->setFont(button_text_font); | ||
| 171 | } else { | ||
| 172 | ui->label_title->setFont(title_text_font); | ||
| 173 | ui->label_dialog->setFont(body_text_font); | ||
| 174 | ui->button_cancel->setFont(button_text_font); | ||
| 175 | ui->button_ok_label->setFont(button_text_font); | ||
| 176 | } | ||
| 177 | |||
| 178 | QDialog::move(pos); | ||
| 179 | QDialog::resize(width, height); | ||
| 180 | } | ||
| 181 | |||
| 182 | template <HIDButton... T> | ||
| 183 | void OverlayDialog::HandleButtonPressedOnce() { | ||
| 184 | const auto f = [this](HIDButton button) { | ||
| 185 | if (input_interpreter->IsButtonPressedOnce(button)) { | ||
| 186 | TranslateButtonPress(button); | ||
| 187 | } | ||
| 188 | }; | ||
| 189 | |||
| 190 | (f(T), ...); | ||
| 191 | } | ||
| 192 | |||
| 193 | void OverlayDialog::TranslateButtonPress(HIDButton button) { | ||
| 194 | QPushButton* left_button = use_rich_text ? ui->button_cancel_rich : ui->button_cancel; | ||
| 195 | QPushButton* right_button = use_rich_text ? ui->button_ok_rich : ui->button_ok_label; | ||
| 196 | |||
| 197 | // TODO (Morph): Handle QTextBrowser text scrolling | ||
| 198 | // TODO (Morph): focusPrevious/NextChild() doesn't work well with the rich text dialog, fix it | ||
| 199 | |||
| 200 | switch (button) { | ||
| 201 | case HIDButton::A: | ||
| 202 | case HIDButton::B: | ||
| 203 | if (left_button->hasFocus()) { | ||
| 204 | left_button->click(); | ||
| 205 | } else if (right_button->hasFocus()) { | ||
| 206 | right_button->click(); | ||
| 207 | } | ||
| 208 | break; | ||
| 209 | case HIDButton::DLeft: | ||
| 210 | case HIDButton::LStickLeft: | ||
| 211 | focusPreviousChild(); | ||
| 212 | break; | ||
| 213 | case HIDButton::DRight: | ||
| 214 | case HIDButton::LStickRight: | ||
| 215 | focusNextChild(); | ||
| 216 | break; | ||
| 217 | default: | ||
| 218 | break; | ||
| 219 | } | ||
| 220 | } | ||
| 221 | |||
| 222 | void OverlayDialog::StartInputThread() { | ||
| 223 | if (input_thread_running) { | ||
| 224 | return; | ||
| 225 | } | ||
| 226 | |||
| 227 | input_thread_running = true; | ||
| 228 | |||
| 229 | input_thread = std::thread(&OverlayDialog::InputThread, this); | ||
| 230 | } | ||
| 231 | |||
| 232 | void OverlayDialog::StopInputThread() { | ||
| 233 | input_thread_running = false; | ||
| 234 | |||
| 235 | if (input_thread.joinable()) { | ||
| 236 | input_thread.join(); | ||
| 237 | } | ||
| 238 | } | ||
| 239 | |||
| 240 | void OverlayDialog::InputThread() { | ||
| 241 | while (input_thread_running) { | ||
| 242 | input_interpreter->PollInput(); | ||
| 243 | |||
| 244 | HandleButtonPressedOnce<HIDButton::A, HIDButton::B, HIDButton::DLeft, HIDButton::DRight, | ||
| 245 | HIDButton::LStickLeft, HIDButton::LStickRight>(); | ||
| 246 | |||
| 247 | std::this_thread::sleep_for(std::chrono::milliseconds(50)); | ||
| 248 | } | ||
| 249 | } | ||
diff --git a/src/yuzu/util/overlay_dialog.h b/src/yuzu/util/overlay_dialog.h new file mode 100644 index 000000000..e8c388bd0 --- /dev/null +++ b/src/yuzu/util/overlay_dialog.h | |||
| @@ -0,0 +1,107 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <array> | ||
| 8 | #include <atomic> | ||
| 9 | #include <memory> | ||
| 10 | #include <thread> | ||
| 11 | |||
| 12 | #include <QDialog> | ||
| 13 | |||
| 14 | #include "common/common_types.h" | ||
| 15 | |||
| 16 | enum class HIDButton : u8; | ||
| 17 | |||
| 18 | class InputInterpreter; | ||
| 19 | |||
| 20 | namespace Core { | ||
| 21 | class System; | ||
| 22 | } | ||
| 23 | |||
| 24 | namespace Ui { | ||
| 25 | class OverlayDialog; | ||
| 26 | } | ||
| 27 | |||
| 28 | /** | ||
| 29 | * An OverlayDialog is an interactive dialog that accepts controller input (while a game is running) | ||
| 30 | * This dialog attempts to replicate the look and feel of the Nintendo Switch's overlay dialogs and | ||
| 31 | * provide some extra features such as embedding HTML/Rich Text content in a QTextBrowser. | ||
| 32 | * The OverlayDialog provides 2 modes: one to embed regular text into a QLabel and another to embed | ||
| 33 | * HTML/Rich Text content into a QTextBrowser. | ||
| 34 | */ | ||
| 35 | class OverlayDialog final : public QDialog { | ||
| 36 | Q_OBJECT | ||
| 37 | |||
| 38 | public: | ||
| 39 | explicit OverlayDialog(QWidget* parent, Core::System& system, const QString& title_text, | ||
| 40 | const QString& body_text, const QString& left_button_text, | ||
| 41 | const QString& right_button_text, | ||
| 42 | Qt::Alignment alignment = Qt::AlignCenter, bool use_rich_text_ = false); | ||
| 43 | ~OverlayDialog() override; | ||
| 44 | |||
| 45 | private: | ||
| 46 | /** | ||
| 47 | * Initializes a text dialog with a QLabel storing text. | ||
| 48 | * Only use this for short text as the dialog buttons would be squashed with longer text. | ||
| 49 | * | ||
| 50 | * @param title_text Title text to be displayed | ||
| 51 | * @param body_text Main text to be displayed | ||
| 52 | * @param left_button_text Left button text. If empty, the button is hidden and disabled | ||
| 53 | * @param right_button_text Right button text. If empty, the button is hidden and disabled | ||
| 54 | * @param alignment Main text alignment | ||
| 55 | */ | ||
| 56 | void InitializeRegularTextDialog(const QString& title_text, const QString& body_text, | ||
| 57 | const QString& left_button_text, | ||
| 58 | const QString& right_button_text, Qt::Alignment alignment); | ||
| 59 | |||
| 60 | /** | ||
| 61 | * Initializes a text dialog with a QTextBrowser storing text. | ||
| 62 | * This is ideal for longer text or rich text content. A scrollbar is shown for longer text. | ||
| 63 | * | ||
| 64 | * @param title_text Title text to be displayed | ||
| 65 | * @param body_text Main text to be displayed | ||
| 66 | * @param left_button_text Left button text. If empty, the button is hidden and disabled | ||
| 67 | * @param right_button_text Right button text. If empty, the button is hidden and disabled | ||
| 68 | * @param alignment Main text alignment | ||
| 69 | */ | ||
| 70 | void InitializeRichTextDialog(const QString& title_text, const QString& body_text, | ||
| 71 | const QString& left_button_text, const QString& right_button_text, | ||
| 72 | Qt::Alignment alignment); | ||
| 73 | |||
| 74 | /// Moves and resizes the dialog to be fully overlayed on top of the parent window. | ||
| 75 | void MoveAndResizeWindow(); | ||
| 76 | |||
| 77 | /** | ||
| 78 | * Handles button presses and converts them into keyboard input. | ||
| 79 | * | ||
| 80 | * @tparam HIDButton The list of buttons that can be converted into keyboard input. | ||
| 81 | */ | ||
| 82 | template <HIDButton... T> | ||
| 83 | void HandleButtonPressedOnce(); | ||
| 84 | |||
| 85 | /** | ||
| 86 | * Translates a button press to focus or click either the left or right buttons. | ||
| 87 | * | ||
| 88 | * @param button The button press to process. | ||
| 89 | */ | ||
| 90 | void TranslateButtonPress(HIDButton button); | ||
| 91 | |||
| 92 | void StartInputThread(); | ||
| 93 | void StopInputThread(); | ||
| 94 | |||
| 95 | /// The thread where input is being polled and processed. | ||
| 96 | void InputThread(); | ||
| 97 | |||
| 98 | std::unique_ptr<Ui::OverlayDialog> ui; | ||
| 99 | |||
| 100 | bool use_rich_text; | ||
| 101 | |||
| 102 | std::unique_ptr<InputInterpreter> input_interpreter; | ||
| 103 | |||
| 104 | std::thread input_thread; | ||
| 105 | |||
| 106 | std::atomic<bool> input_thread_running{}; | ||
| 107 | }; | ||
diff --git a/src/yuzu/util/overlay_dialog.ui b/src/yuzu/util/overlay_dialog.ui new file mode 100644 index 000000000..278e2f219 --- /dev/null +++ b/src/yuzu/util/overlay_dialog.ui | |||
| @@ -0,0 +1,404 @@ | |||
| 1 | <?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | <ui version="4.0"> | ||
| 3 | <class>OverlayDialog</class> | ||
| 4 | <widget class="QDialog" name="OverlayDialog"> | ||
| 5 | <property name="geometry"> | ||
| 6 | <rect> | ||
| 7 | <x>0</x> | ||
| 8 | <y>0</y> | ||
| 9 | <width>1280</width> | ||
| 10 | <height>720</height> | ||
| 11 | </rect> | ||
| 12 | </property> | ||
| 13 | <property name="windowTitle"> | ||
| 14 | <string>Dialog</string> | ||
| 15 | </property> | ||
| 16 | <property name="styleSheet"> | ||
| 17 | <string notr="true"/> | ||
| 18 | </property> | ||
| 19 | <layout class="QVBoxLayout" name="verticalLayout"> | ||
| 20 | <property name="spacing"> | ||
| 21 | <number>0</number> | ||
| 22 | </property> | ||
| 23 | <property name="leftMargin"> | ||
| 24 | <number>0</number> | ||
| 25 | </property> | ||
| 26 | <property name="topMargin"> | ||
| 27 | <number>0</number> | ||
| 28 | </property> | ||
| 29 | <property name="rightMargin"> | ||
| 30 | <number>0</number> | ||
| 31 | </property> | ||
| 32 | <property name="bottomMargin"> | ||
| 33 | <number>0</number> | ||
| 34 | </property> | ||
| 35 | <item> | ||
| 36 | <widget class="QStackedWidget" name="stackedDialog"> | ||
| 37 | <property name="currentIndex"> | ||
| 38 | <number>0</number> | ||
| 39 | </property> | ||
| 40 | <widget class="QWidget" name="lineDialog"> | ||
| 41 | <layout class="QGridLayout" name="lineDialogGridLayout" rowstretch="210,300,210" columnstretch="250,780,250"> | ||
| 42 | <property name="leftMargin"> | ||
| 43 | <number>0</number> | ||
| 44 | </property> | ||
| 45 | <property name="topMargin"> | ||
| 46 | <number>0</number> | ||
| 47 | </property> | ||
| 48 | <property name="rightMargin"> | ||
| 49 | <number>0</number> | ||
| 50 | </property> | ||
| 51 | <property name="bottomMargin"> | ||
| 52 | <number>0</number> | ||
| 53 | </property> | ||
| 54 | <property name="spacing"> | ||
| 55 | <number>0</number> | ||
| 56 | </property> | ||
| 57 | <item row="1" column="1"> | ||
| 58 | <widget class="QWidget" name="contentDialog" native="true"> | ||
| 59 | <layout class="QVBoxLayout" name="verticalLayout_2" stretch="70,149,82"> | ||
| 60 | <property name="spacing"> | ||
| 61 | <number>0</number> | ||
| 62 | </property> | ||
| 63 | <property name="leftMargin"> | ||
| 64 | <number>0</number> | ||
| 65 | </property> | ||
| 66 | <property name="topMargin"> | ||
| 67 | <number>0</number> | ||
| 68 | </property> | ||
| 69 | <property name="rightMargin"> | ||
| 70 | <number>0</number> | ||
| 71 | </property> | ||
| 72 | <property name="bottomMargin"> | ||
| 73 | <number>0</number> | ||
| 74 | </property> | ||
| 75 | <item> | ||
| 76 | <widget class="QLabel" name="label_title"> | ||
| 77 | <property name="font"> | ||
| 78 | <font> | ||
| 79 | <pointsize>14</pointsize> | ||
| 80 | </font> | ||
| 81 | </property> | ||
| 82 | <property name="alignment"> | ||
| 83 | <set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set> | ||
| 84 | </property> | ||
| 85 | </widget> | ||
| 86 | </item> | ||
| 87 | <item> | ||
| 88 | <widget class="QLabel" name="label_dialog"> | ||
| 89 | <property name="font"> | ||
| 90 | <font> | ||
| 91 | <pointsize>18</pointsize> | ||
| 92 | </font> | ||
| 93 | </property> | ||
| 94 | <property name="alignment"> | ||
| 95 | <set>Qt::AlignCenter</set> | ||
| 96 | </property> | ||
| 97 | <property name="wordWrap"> | ||
| 98 | <bool>true</bool> | ||
| 99 | </property> | ||
| 100 | </widget> | ||
| 101 | </item> | ||
| 102 | <item> | ||
| 103 | <widget class="QWidget" name="buttonsDialog" native="true"> | ||
| 104 | <layout class="QHBoxLayout" name="horizontalLayout"> | ||
| 105 | <property name="spacing"> | ||
| 106 | <number>0</number> | ||
| 107 | </property> | ||
| 108 | <property name="leftMargin"> | ||
| 109 | <number>0</number> | ||
| 110 | </property> | ||
| 111 | <property name="topMargin"> | ||
| 112 | <number>0</number> | ||
| 113 | </property> | ||
| 114 | <property name="rightMargin"> | ||
| 115 | <number>0</number> | ||
| 116 | </property> | ||
| 117 | <property name="bottomMargin"> | ||
| 118 | <number>0</number> | ||
| 119 | </property> | ||
| 120 | <item> | ||
| 121 | <widget class="QPushButton" name="button_cancel"> | ||
| 122 | <property name="sizePolicy"> | ||
| 123 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 124 | <horstretch>0</horstretch> | ||
| 125 | <verstretch>0</verstretch> | ||
| 126 | </sizepolicy> | ||
| 127 | </property> | ||
| 128 | <property name="font"> | ||
| 129 | <font> | ||
| 130 | <pointsize>18</pointsize> | ||
| 131 | </font> | ||
| 132 | </property> | ||
| 133 | <property name="text"> | ||
| 134 | <string>Cancel</string> | ||
| 135 | </property> | ||
| 136 | </widget> | ||
| 137 | </item> | ||
| 138 | <item> | ||
| 139 | <widget class="QPushButton" name="button_ok_label"> | ||
| 140 | <property name="sizePolicy"> | ||
| 141 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 142 | <horstretch>0</horstretch> | ||
| 143 | <verstretch>0</verstretch> | ||
| 144 | </sizepolicy> | ||
| 145 | </property> | ||
| 146 | <property name="font"> | ||
| 147 | <font> | ||
| 148 | <pointsize>18</pointsize> | ||
| 149 | </font> | ||
| 150 | </property> | ||
| 151 | <property name="text"> | ||
| 152 | <string>OK</string> | ||
| 153 | </property> | ||
| 154 | </widget> | ||
| 155 | </item> | ||
| 156 | </layout> | ||
| 157 | </widget> | ||
| 158 | </item> | ||
| 159 | </layout> | ||
| 160 | </widget> | ||
| 161 | </item> | ||
| 162 | <item row="0" column="1"> | ||
| 163 | <spacer name="verticalSpacer"> | ||
| 164 | <property name="orientation"> | ||
| 165 | <enum>Qt::Vertical</enum> | ||
| 166 | </property> | ||
| 167 | <property name="sizeHint" stdset="0"> | ||
| 168 | <size> | ||
| 169 | <width>20</width> | ||
| 170 | <height>40</height> | ||
| 171 | </size> | ||
| 172 | </property> | ||
| 173 | </spacer> | ||
| 174 | </item> | ||
| 175 | <item row="1" column="0"> | ||
| 176 | <spacer name="horizontalSpacer"> | ||
| 177 | <property name="orientation"> | ||
| 178 | <enum>Qt::Horizontal</enum> | ||
| 179 | </property> | ||
| 180 | <property name="sizeHint" stdset="0"> | ||
| 181 | <size> | ||
| 182 | <width>40</width> | ||
| 183 | <height>20</height> | ||
| 184 | </size> | ||
| 185 | </property> | ||
| 186 | </spacer> | ||
| 187 | </item> | ||
| 188 | <item row="2" column="1"> | ||
| 189 | <spacer name="verticalSpacer_2"> | ||
| 190 | <property name="orientation"> | ||
| 191 | <enum>Qt::Vertical</enum> | ||
| 192 | </property> | ||
| 193 | <property name="sizeHint" stdset="0"> | ||
| 194 | <size> | ||
| 195 | <width>20</width> | ||
| 196 | <height>40</height> | ||
| 197 | </size> | ||
| 198 | </property> | ||
| 199 | </spacer> | ||
| 200 | </item> | ||
| 201 | <item row="1" column="2"> | ||
| 202 | <spacer name="horizontalSpacer_2"> | ||
| 203 | <property name="orientation"> | ||
| 204 | <enum>Qt::Horizontal</enum> | ||
| 205 | </property> | ||
| 206 | <property name="sizeHint" stdset="0"> | ||
| 207 | <size> | ||
| 208 | <width>40</width> | ||
| 209 | <height>20</height> | ||
| 210 | </size> | ||
| 211 | </property> | ||
| 212 | </spacer> | ||
| 213 | </item> | ||
| 214 | </layout> | ||
| 215 | </widget> | ||
| 216 | <widget class="QWidget" name="richDialog"> | ||
| 217 | <layout class="QGridLayout" name="richDialogGridLayout" rowstretch="100,520,100" columnstretch="165,950,165"> | ||
| 218 | <property name="leftMargin"> | ||
| 219 | <number>0</number> | ||
| 220 | </property> | ||
| 221 | <property name="topMargin"> | ||
| 222 | <number>0</number> | ||
| 223 | </property> | ||
| 224 | <property name="rightMargin"> | ||
| 225 | <number>0</number> | ||
| 226 | </property> | ||
| 227 | <property name="bottomMargin"> | ||
| 228 | <number>0</number> | ||
| 229 | </property> | ||
| 230 | <property name="spacing"> | ||
| 231 | <number>0</number> | ||
| 232 | </property> | ||
| 233 | <item row="1" column="0"> | ||
| 234 | <spacer name="horizontalSpacer_3"> | ||
| 235 | <property name="orientation"> | ||
| 236 | <enum>Qt::Horizontal</enum> | ||
| 237 | </property> | ||
| 238 | <property name="sizeHint" stdset="0"> | ||
| 239 | <size> | ||
| 240 | <width>40</width> | ||
| 241 | <height>20</height> | ||
| 242 | </size> | ||
| 243 | </property> | ||
| 244 | </spacer> | ||
| 245 | </item> | ||
| 246 | <item row="2" column="1"> | ||
| 247 | <spacer name="verticalSpacer_4"> | ||
| 248 | <property name="orientation"> | ||
| 249 | <enum>Qt::Vertical</enum> | ||
| 250 | </property> | ||
| 251 | <property name="sizeHint" stdset="0"> | ||
| 252 | <size> | ||
| 253 | <width>20</width> | ||
| 254 | <height>40</height> | ||
| 255 | </size> | ||
| 256 | </property> | ||
| 257 | </spacer> | ||
| 258 | </item> | ||
| 259 | <item row="0" column="1"> | ||
| 260 | <spacer name="verticalSpacer_3"> | ||
| 261 | <property name="orientation"> | ||
| 262 | <enum>Qt::Vertical</enum> | ||
| 263 | </property> | ||
| 264 | <property name="sizeHint" stdset="0"> | ||
| 265 | <size> | ||
| 266 | <width>20</width> | ||
| 267 | <height>40</height> | ||
| 268 | </size> | ||
| 269 | </property> | ||
| 270 | </spacer> | ||
| 271 | </item> | ||
| 272 | <item row="1" column="1"> | ||
| 273 | <widget class="QWidget" name="contentRichDialog" native="true"> | ||
| 274 | <layout class="QVBoxLayout" name="verticalLayout_3" stretch="70,368,82"> | ||
| 275 | <property name="spacing"> | ||
| 276 | <number>0</number> | ||
| 277 | </property> | ||
| 278 | <property name="leftMargin"> | ||
| 279 | <number>0</number> | ||
| 280 | </property> | ||
| 281 | <property name="topMargin"> | ||
| 282 | <number>0</number> | ||
| 283 | </property> | ||
| 284 | <property name="rightMargin"> | ||
| 285 | <number>0</number> | ||
| 286 | </property> | ||
| 287 | <property name="bottomMargin"> | ||
| 288 | <number>0</number> | ||
| 289 | </property> | ||
| 290 | <item> | ||
| 291 | <widget class="QLabel" name="label_title_rich"> | ||
| 292 | <property name="font"> | ||
| 293 | <font> | ||
| 294 | <pointsize>14</pointsize> | ||
| 295 | </font> | ||
| 296 | </property> | ||
| 297 | <property name="text"> | ||
| 298 | <string/> | ||
| 299 | </property> | ||
| 300 | <property name="alignment"> | ||
| 301 | <set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set> | ||
| 302 | </property> | ||
| 303 | </widget> | ||
| 304 | </item> | ||
| 305 | <item> | ||
| 306 | <widget class="QTextBrowser" name="text_browser_dialog"> | ||
| 307 | <property name="font"> | ||
| 308 | <font> | ||
| 309 | <pointsize>18</pointsize> | ||
| 310 | </font> | ||
| 311 | </property> | ||
| 312 | <property name="html"> | ||
| 313 | <string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> | ||
| 314 | <html><head><meta name="qrichtext" content="1" /><style type="text/css"> | ||
| 315 | p, li { white-space: pre-wrap; } | ||
| 316 | </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:400; font-style:normal;"> | ||
| 317 | <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html></string> | ||
| 318 | </property> | ||
| 319 | </widget> | ||
| 320 | </item> | ||
| 321 | <item> | ||
| 322 | <widget class="QWidget" name="buttonsRichDialog" native="true"> | ||
| 323 | <layout class="QHBoxLayout" name="horizontalLayout_2"> | ||
| 324 | <property name="spacing"> | ||
| 325 | <number>0</number> | ||
| 326 | </property> | ||
| 327 | <property name="leftMargin"> | ||
| 328 | <number>0</number> | ||
| 329 | </property> | ||
| 330 | <property name="topMargin"> | ||
| 331 | <number>0</number> | ||
| 332 | </property> | ||
| 333 | <property name="rightMargin"> | ||
| 334 | <number>0</number> | ||
| 335 | </property> | ||
| 336 | <property name="bottomMargin"> | ||
| 337 | <number>0</number> | ||
| 338 | </property> | ||
| 339 | <item> | ||
| 340 | <widget class="QPushButton" name="button_cancel_rich"> | ||
| 341 | <property name="sizePolicy"> | ||
| 342 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 343 | <horstretch>0</horstretch> | ||
| 344 | <verstretch>0</verstretch> | ||
| 345 | </sizepolicy> | ||
| 346 | </property> | ||
| 347 | <property name="font"> | ||
| 348 | <font> | ||
| 349 | <pointsize>18</pointsize> | ||
| 350 | </font> | ||
| 351 | </property> | ||
| 352 | <property name="text"> | ||
| 353 | <string>Cancel</string> | ||
| 354 | </property> | ||
| 355 | </widget> | ||
| 356 | </item> | ||
| 357 | <item> | ||
| 358 | <widget class="QPushButton" name="button_ok_rich"> | ||
| 359 | <property name="sizePolicy"> | ||
| 360 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 361 | <horstretch>0</horstretch> | ||
| 362 | <verstretch>0</verstretch> | ||
| 363 | </sizepolicy> | ||
| 364 | </property> | ||
| 365 | <property name="font"> | ||
| 366 | <font> | ||
| 367 | <pointsize>18</pointsize> | ||
| 368 | </font> | ||
| 369 | </property> | ||
| 370 | <property name="text"> | ||
| 371 | <string>OK</string> | ||
| 372 | </property> | ||
| 373 | </widget> | ||
| 374 | </item> | ||
| 375 | </layout> | ||
| 376 | </widget> | ||
| 377 | </item> | ||
| 378 | </layout> | ||
| 379 | </widget> | ||
| 380 | </item> | ||
| 381 | <item row="1" column="2"> | ||
| 382 | <spacer name="horizontalSpacer_4"> | ||
| 383 | <property name="orientation"> | ||
| 384 | <enum>Qt::Horizontal</enum> | ||
| 385 | </property> | ||
| 386 | <property name="sizeHint" stdset="0"> | ||
| 387 | <size> | ||
| 388 | <width>40</width> | ||
| 389 | <height>20</height> | ||
| 390 | </size> | ||
| 391 | </property> | ||
| 392 | </spacer> | ||
| 393 | </item> | ||
| 394 | </layout> | ||
| 395 | </widget> | ||
| 396 | </widget> | ||
| 397 | </item> | ||
| 398 | </layout> | ||
| 399 | </widget> | ||
| 400 | <resources> | ||
| 401 | <include location="../../../dist/icons/overlay/overlay.qrc"/> | ||
| 402 | </resources> | ||
| 403 | <connections/> | ||
| 404 | </ui> | ||
diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp index 43877fc98..2f984d1b8 100644 --- a/src/yuzu_cmd/config.cpp +++ b/src/yuzu_cmd/config.cpp | |||
| @@ -9,8 +9,8 @@ | |||
| 9 | #include "common/file_util.h" | 9 | #include "common/file_util.h" |
| 10 | #include "common/logging/log.h" | 10 | #include "common/logging/log.h" |
| 11 | #include "common/param_package.h" | 11 | #include "common/param_package.h" |
| 12 | #include "common/settings.h" | ||
| 12 | #include "core/hle/service/acc/profile_manager.h" | 13 | #include "core/hle/service/acc/profile_manager.h" |
| 13 | #include "core/settings.h" | ||
| 14 | #include "input_common/main.h" | 14 | #include "input_common/main.h" |
| 15 | #include "input_common/udp/client.h" | 15 | #include "input_common/udp/client.h" |
| 16 | #include "yuzu_cmd/config.h" | 16 | #include "yuzu_cmd/config.h" |
| @@ -428,6 +428,10 @@ void Config::ReadValues() { | |||
| 428 | Settings::values.reporting_services = | 428 | Settings::values.reporting_services = |
| 429 | sdl2_config->GetBoolean("Debugging", "reporting_services", false); | 429 | sdl2_config->GetBoolean("Debugging", "reporting_services", false); |
| 430 | Settings::values.quest_flag = sdl2_config->GetBoolean("Debugging", "quest_flag", false); | 430 | Settings::values.quest_flag = sdl2_config->GetBoolean("Debugging", "quest_flag", false); |
| 431 | Settings::values.use_debug_asserts = | ||
| 432 | sdl2_config->GetBoolean("Debugging", "use_debug_asserts", false); | ||
| 433 | Settings::values.use_auto_stub = sdl2_config->GetBoolean("Debugging", "use_auto_stub", false); | ||
| 434 | |||
| 431 | Settings::values.disable_macro_jit = | 435 | Settings::values.disable_macro_jit = |
| 432 | sdl2_config->GetBoolean("Debugging", "disable_macro_jit", false); | 436 | sdl2_config->GetBoolean("Debugging", "disable_macro_jit", false); |
| 433 | 437 | ||
diff --git a/src/yuzu_cmd/default_ini.h b/src/yuzu_cmd/default_ini.h index 3ee0e037d..4ce8e08e4 100644 --- a/src/yuzu_cmd/default_ini.h +++ b/src/yuzu_cmd/default_ini.h | |||
| @@ -325,6 +325,12 @@ dump_nso=false | |||
| 325 | # Determines whether or not yuzu will report to the game that the emulated console is in Kiosk Mode | 325 | # Determines whether or not yuzu will report to the game that the emulated console is in Kiosk Mode |
| 326 | # false: Retail/Normal Mode (default), true: Kiosk Mode | 326 | # false: Retail/Normal Mode (default), true: Kiosk Mode |
| 327 | quest_flag = | 327 | quest_flag = |
| 328 | # Determines whether debug asserts should be enabled, which will throw an exception on asserts. | ||
| 329 | # false: Disabled (default), true: Enabled | ||
| 330 | use_debug_asserts = | ||
| 331 | # Determines whether unimplemented HLE service calls should be automatically stubbed. | ||
| 332 | # false: Disabled (default), true: Enabled | ||
| 333 | use_auto_stub = | ||
| 328 | # Enables/Disables the macro JIT compiler | 334 | # Enables/Disables the macro JIT compiler |
| 329 | disable_macro_jit=false | 335 | disable_macro_jit=false |
| 330 | 336 | ||
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp index a02485c14..a765fa7b3 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp | |||
| @@ -12,9 +12,9 @@ | |||
| 12 | #include "common/assert.h" | 12 | #include "common/assert.h" |
| 13 | #include "common/logging/log.h" | 13 | #include "common/logging/log.h" |
| 14 | #include "common/scm_rev.h" | 14 | #include "common/scm_rev.h" |
| 15 | #include "common/settings.h" | ||
| 15 | #include "common/string_util.h" | 16 | #include "common/string_util.h" |
| 16 | #include "core/core.h" | 17 | #include "core/core.h" |
| 17 | #include "core/settings.h" | ||
| 18 | #include "input_common/keyboard.h" | 18 | #include "input_common/keyboard.h" |
| 19 | #include "input_common/main.h" | 19 | #include "input_common/main.h" |
| 20 | #include "video_core/renderer_base.h" | 20 | #include "video_core/renderer_base.h" |
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp index 6f9b00461..dfd53e285 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp | |||
| @@ -11,7 +11,7 @@ | |||
| 11 | #include "common/assert.h" | 11 | #include "common/assert.h" |
| 12 | #include "common/logging/log.h" | 12 | #include "common/logging/log.h" |
| 13 | #include "common/scm_rev.h" | 13 | #include "common/scm_rev.h" |
| 14 | #include "core/settings.h" | 14 | #include "common/settings.h" |
| 15 | #include "video_core/renderer_vulkan/renderer_vulkan.h" | 15 | #include "video_core/renderer_vulkan/renderer_vulkan.h" |
| 16 | #include "yuzu_cmd/emu_window/emu_window_sdl2_vk.h" | 16 | #include "yuzu_cmd/emu_window/emu_window_sdl2_vk.h" |
| 17 | 17 | ||
diff --git a/src/yuzu_cmd/yuzu.cpp b/src/yuzu_cmd/yuzu.cpp index 982c41785..4871ac3bb 100644 --- a/src/yuzu_cmd/yuzu.cpp +++ b/src/yuzu_cmd/yuzu.cpp | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | #include "common/nvidia_flags.h" | 20 | #include "common/nvidia_flags.h" |
| 21 | #include "common/scm_rev.h" | 21 | #include "common/scm_rev.h" |
| 22 | #include "common/scope_exit.h" | 22 | #include "common/scope_exit.h" |
| 23 | #include "common/settings.h" | ||
| 23 | #include "common/string_util.h" | 24 | #include "common/string_util.h" |
| 24 | #include "common/telemetry.h" | 25 | #include "common/telemetry.h" |
| 25 | #include "core/core.h" | 26 | #include "core/core.h" |
| @@ -29,7 +30,6 @@ | |||
| 29 | #include "core/hle/kernel/process.h" | 30 | #include "core/hle/kernel/process.h" |
| 30 | #include "core/hle/service/filesystem/filesystem.h" | 31 | #include "core/hle/service/filesystem/filesystem.h" |
| 31 | #include "core/loader/loader.h" | 32 | #include "core/loader/loader.h" |
| 32 | #include "core/settings.h" | ||
| 33 | #include "core/telemetry_session.h" | 33 | #include "core/telemetry_session.h" |
| 34 | #include "input_common/main.h" | 34 | #include "input_common/main.h" |
| 35 | #include "video_core/renderer_base.h" | 35 | #include "video_core/renderer_base.h" |
| @@ -74,14 +74,16 @@ static void PrintVersion() { | |||
| 74 | } | 74 | } |
| 75 | 75 | ||
| 76 | static void InitializeLogging() { | 76 | static void InitializeLogging() { |
| 77 | using namespace Common; | ||
| 78 | |||
| 77 | Log::Filter log_filter(Log::Level::Debug); | 79 | Log::Filter log_filter(Log::Level::Debug); |
| 78 | log_filter.ParseFilterString(Settings::values.log_filter); | 80 | log_filter.ParseFilterString(Settings::values.log_filter); |
| 79 | Log::SetGlobalFilter(log_filter); | 81 | Log::SetGlobalFilter(log_filter); |
| 80 | 82 | ||
| 81 | Log::AddBackend(std::make_unique<Log::ColorConsoleBackend>()); | 83 | Log::AddBackend(std::make_unique<Log::ColorConsoleBackend>()); |
| 82 | 84 | ||
| 83 | const std::string& log_dir = Common::FS::GetUserPath(Common::FS::UserPath::LogDir); | 85 | const std::string& log_dir = FS::GetUserPath(FS::UserPath::LogDir); |
| 84 | Common::FS::CreateFullPath(log_dir); | 86 | FS::CreateFullPath(log_dir); |
| 85 | Log::AddBackend(std::make_unique<Log::FileBackend>(log_dir + LOG_FILE)); | 87 | Log::AddBackend(std::make_unique<Log::FileBackend>(log_dir + LOG_FILE)); |
| 86 | #ifdef _WIN32 | 88 | #ifdef _WIN32 |
| 87 | Log::AddBackend(std::make_unique<Log::DebuggerBackend>()); | 89 | Log::AddBackend(std::make_unique<Log::DebuggerBackend>()); |
| @@ -164,7 +166,7 @@ int main(int argc, char** argv) { | |||
| 164 | InputCommon::InputSubsystem input_subsystem; | 166 | InputCommon::InputSubsystem input_subsystem; |
| 165 | 167 | ||
| 166 | // Apply the command line arguments | 168 | // Apply the command line arguments |
| 167 | Settings::Apply(system); | 169 | system.ApplySettings(); |
| 168 | 170 | ||
| 169 | std::unique_ptr<EmuWindow_SDL2> emu_window; | 171 | std::unique_ptr<EmuWindow_SDL2> emu_window; |
| 170 | switch (Settings::values.renderer_backend.GetValue()) { | 172 | switch (Settings::values.renderer_backend.GetValue()) { |