diff options
Diffstat (limited to 'src')
57 files changed, 1118 insertions, 433 deletions
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index eafb96b0b..7a4d9e354 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt | |||
| @@ -154,6 +154,7 @@ add_library(common STATIC | |||
| 154 | param_package.cpp | 154 | param_package.cpp |
| 155 | param_package.h | 155 | param_package.h |
| 156 | parent_of_member.h | 156 | parent_of_member.h |
| 157 | point.h | ||
| 157 | quaternion.h | 158 | quaternion.h |
| 158 | ring_buffer.h | 159 | ring_buffer.h |
| 159 | scm_rev.cpp | 160 | scm_rev.cpp |
diff --git a/src/common/fs/file.h b/src/common/fs/file.h index 209f9664b..50e270c5b 100644 --- a/src/common/fs/file.h +++ b/src/common/fs/file.h | |||
| @@ -117,7 +117,7 @@ template <typename Path> | |||
| 117 | } | 117 | } |
| 118 | #endif | 118 | #endif |
| 119 | 119 | ||
| 120 | class IOFile final : NonCopyable { | 120 | class IOFile final { |
| 121 | public: | 121 | public: |
| 122 | IOFile(); | 122 | IOFile(); |
| 123 | 123 | ||
| @@ -142,7 +142,10 @@ public: | |||
| 142 | FileType type = FileType::BinaryFile, | 142 | FileType type = FileType::BinaryFile, |
| 143 | FileShareFlag flag = FileShareFlag::ShareReadOnly); | 143 | FileShareFlag flag = FileShareFlag::ShareReadOnly); |
| 144 | 144 | ||
| 145 | virtual ~IOFile(); | 145 | ~IOFile(); |
| 146 | |||
| 147 | IOFile(const IOFile&) = delete; | ||
| 148 | IOFile& operator=(const IOFile&) = delete; | ||
| 146 | 149 | ||
| 147 | IOFile(IOFile&& other) noexcept; | 150 | IOFile(IOFile&& other) noexcept; |
| 148 | IOFile& operator=(IOFile&& other) noexcept; | 151 | IOFile& operator=(IOFile&& other) noexcept; |
| @@ -441,8 +444,8 @@ public: | |||
| 441 | 444 | ||
| 442 | private: | 445 | private: |
| 443 | std::filesystem::path file_path; | 446 | std::filesystem::path file_path; |
| 444 | FileAccessMode file_access_mode; | 447 | FileAccessMode file_access_mode{}; |
| 445 | FileType file_type; | 448 | FileType file_type{}; |
| 446 | 449 | ||
| 447 | std::FILE* file = nullptr; | 450 | std::FILE* file = nullptr; |
| 448 | }; | 451 | }; |
diff --git a/src/common/page_table.cpp b/src/common/page_table.cpp index 8fd8620fd..9fffd816f 100644 --- a/src/common/page_table.cpp +++ b/src/common/page_table.cpp | |||
| @@ -14,6 +14,7 @@ void PageTable::Resize(size_t address_space_width_in_bits, size_t page_size_in_b | |||
| 14 | const size_t num_page_table_entries{1ULL << (address_space_width_in_bits - page_size_in_bits)}; | 14 | const size_t num_page_table_entries{1ULL << (address_space_width_in_bits - page_size_in_bits)}; |
| 15 | pointers.resize(num_page_table_entries); | 15 | pointers.resize(num_page_table_entries); |
| 16 | backing_addr.resize(num_page_table_entries); | 16 | backing_addr.resize(num_page_table_entries); |
| 17 | current_address_space_width_in_bits = address_space_width_in_bits; | ||
| 17 | } | 18 | } |
| 18 | 19 | ||
| 19 | } // namespace Common | 20 | } // namespace Common |
diff --git a/src/common/page_table.h b/src/common/page_table.h index 61c5552e0..e92b66b2b 100644 --- a/src/common/page_table.h +++ b/src/common/page_table.h | |||
| @@ -98,6 +98,10 @@ struct PageTable { | |||
| 98 | */ | 98 | */ |
| 99 | void Resize(size_t address_space_width_in_bits, size_t page_size_in_bits); | 99 | void Resize(size_t address_space_width_in_bits, size_t page_size_in_bits); |
| 100 | 100 | ||
| 101 | size_t GetAddressSpaceBits() const { | ||
| 102 | return current_address_space_width_in_bits; | ||
| 103 | } | ||
| 104 | |||
| 101 | /** | 105 | /** |
| 102 | * Vector of memory pointers backing each page. An entry can only be non-null if the | 106 | * Vector of memory pointers backing each page. An entry can only be non-null if the |
| 103 | * corresponding attribute element is of type `Memory`. | 107 | * corresponding attribute element is of type `Memory`. |
| @@ -105,6 +109,8 @@ struct PageTable { | |||
| 105 | VirtualBuffer<PageInfo> pointers; | 109 | VirtualBuffer<PageInfo> pointers; |
| 106 | 110 | ||
| 107 | VirtualBuffer<u64> backing_addr; | 111 | VirtualBuffer<u64> backing_addr; |
| 112 | |||
| 113 | size_t current_address_space_width_in_bits; | ||
| 108 | }; | 114 | }; |
| 109 | 115 | ||
| 110 | } // namespace Common | 116 | } // namespace Common |
diff --git a/src/common/point.h b/src/common/point.h new file mode 100644 index 000000000..c0a52ad8d --- /dev/null +++ b/src/common/point.h | |||
| @@ -0,0 +1,57 @@ | |||
| 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 <type_traits> | ||
| 8 | |||
| 9 | namespace Common { | ||
| 10 | |||
| 11 | // Represents a point within a 2D space. | ||
| 12 | template <typename T> | ||
| 13 | struct Point { | ||
| 14 | static_assert(std::is_arithmetic_v<T>, "T must be an arithmetic type!"); | ||
| 15 | |||
| 16 | T x{}; | ||
| 17 | T y{}; | ||
| 18 | |||
| 19 | #define ARITHMETIC_OP(op, compound_op) \ | ||
| 20 | friend constexpr Point operator op(const Point& lhs, const Point& rhs) noexcept { \ | ||
| 21 | return { \ | ||
| 22 | .x = static_cast<T>(lhs.x op rhs.x), \ | ||
| 23 | .y = static_cast<T>(lhs.y op rhs.y), \ | ||
| 24 | }; \ | ||
| 25 | } \ | ||
| 26 | friend constexpr Point operator op(const Point& lhs, T value) noexcept { \ | ||
| 27 | return { \ | ||
| 28 | .x = static_cast<T>(lhs.x op value), \ | ||
| 29 | .y = static_cast<T>(lhs.y op value), \ | ||
| 30 | }; \ | ||
| 31 | } \ | ||
| 32 | friend constexpr Point operator op(T value, const Point& rhs) noexcept { \ | ||
| 33 | return { \ | ||
| 34 | .x = static_cast<T>(value op rhs.x), \ | ||
| 35 | .y = static_cast<T>(value op rhs.y), \ | ||
| 36 | }; \ | ||
| 37 | } \ | ||
| 38 | friend constexpr Point& operator compound_op(Point& lhs, const Point& rhs) noexcept { \ | ||
| 39 | lhs.x = static_cast<T>(lhs.x op rhs.x); \ | ||
| 40 | lhs.y = static_cast<T>(lhs.y op rhs.y); \ | ||
| 41 | return lhs; \ | ||
| 42 | } \ | ||
| 43 | friend constexpr Point& operator compound_op(Point& lhs, T value) noexcept { \ | ||
| 44 | lhs.x = static_cast<T>(lhs.x op value); \ | ||
| 45 | lhs.y = static_cast<T>(lhs.y op value); \ | ||
| 46 | return lhs; \ | ||
| 47 | } | ||
| 48 | ARITHMETIC_OP(+, +=) | ||
| 49 | ARITHMETIC_OP(-, -=) | ||
| 50 | ARITHMETIC_OP(*, *=) | ||
| 51 | ARITHMETIC_OP(/, /=) | ||
| 52 | #undef ARITHMETIC_OP | ||
| 53 | |||
| 54 | friend constexpr bool operator==(const Point&, const Point&) = default; | ||
| 55 | }; | ||
| 56 | |||
| 57 | } // namespace Common | ||
diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h index 9a0151736..689e3ceb5 100644 --- a/src/core/arm/arm_interface.h +++ b/src/core/arm/arm_interface.h | |||
| @@ -65,9 +65,6 @@ public: | |||
| 65 | /// Step CPU by one instruction | 65 | /// Step CPU by one instruction |
| 66 | virtual void Step() = 0; | 66 | virtual void Step() = 0; |
| 67 | 67 | ||
| 68 | /// Exits execution from a callback, the callback must rewind the stack | ||
| 69 | virtual void ExceptionalExit() = 0; | ||
| 70 | |||
| 71 | /// Clear all instruction cache | 68 | /// Clear all instruction cache |
| 72 | virtual void ClearInstructionCache() = 0; | 69 | virtual void ClearInstructionCache() = 0; |
| 73 | 70 | ||
| @@ -159,8 +156,6 @@ public: | |||
| 159 | */ | 156 | */ |
| 160 | virtual void SetTPIDR_EL0(u64 value) = 0; | 157 | virtual void SetTPIDR_EL0(u64 value) = 0; |
| 161 | 158 | ||
| 162 | virtual void ChangeProcessorID(std::size_t new_core_id) = 0; | ||
| 163 | |||
| 164 | virtual void SaveContext(ThreadContext32& ctx) = 0; | 159 | virtual void SaveContext(ThreadContext32& ctx) = 0; |
| 165 | virtual void SaveContext(ThreadContext64& ctx) = 0; | 160 | virtual void SaveContext(ThreadContext64& ctx) = 0; |
| 166 | virtual void LoadContext(const ThreadContext32& ctx) = 0; | 161 | virtual void LoadContext(const ThreadContext32& ctx) = 0; |
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp index 93d43e22e..cea7f0fb1 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp | |||
| @@ -4,9 +4,9 @@ | |||
| 4 | 4 | ||
| 5 | #include <cinttypes> | 5 | #include <cinttypes> |
| 6 | #include <memory> | 6 | #include <memory> |
| 7 | #include <dynarmic/A32/a32.h> | 7 | #include <dynarmic/interface/A32/a32.h> |
| 8 | #include <dynarmic/A32/config.h> | 8 | #include <dynarmic/interface/A32/config.h> |
| 9 | #include <dynarmic/A32/context.h> | 9 | #include <dynarmic/interface/A32/context.h> |
| 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" |
| @@ -24,45 +24,46 @@ namespace Core { | |||
| 24 | 24 | ||
| 25 | class DynarmicCallbacks32 : public Dynarmic::A32::UserCallbacks { | 25 | class DynarmicCallbacks32 : public Dynarmic::A32::UserCallbacks { |
| 26 | public: | 26 | public: |
| 27 | explicit DynarmicCallbacks32(ARM_Dynarmic_32& parent_) : parent{parent_} {} | 27 | explicit DynarmicCallbacks32(ARM_Dynarmic_32& parent_) |
| 28 | : parent{parent_}, memory(parent.system.Memory()) {} | ||
| 28 | 29 | ||
| 29 | u8 MemoryRead8(u32 vaddr) override { | 30 | u8 MemoryRead8(u32 vaddr) override { |
| 30 | return parent.system.Memory().Read8(vaddr); | 31 | return memory.Read8(vaddr); |
| 31 | } | 32 | } |
| 32 | u16 MemoryRead16(u32 vaddr) override { | 33 | u16 MemoryRead16(u32 vaddr) override { |
| 33 | return parent.system.Memory().Read16(vaddr); | 34 | return memory.Read16(vaddr); |
| 34 | } | 35 | } |
| 35 | u32 MemoryRead32(u32 vaddr) override { | 36 | u32 MemoryRead32(u32 vaddr) override { |
| 36 | return parent.system.Memory().Read32(vaddr); | 37 | return memory.Read32(vaddr); |
| 37 | } | 38 | } |
| 38 | u64 MemoryRead64(u32 vaddr) override { | 39 | u64 MemoryRead64(u32 vaddr) override { |
| 39 | return parent.system.Memory().Read64(vaddr); | 40 | return memory.Read64(vaddr); |
| 40 | } | 41 | } |
| 41 | 42 | ||
| 42 | void MemoryWrite8(u32 vaddr, u8 value) override { | 43 | void MemoryWrite8(u32 vaddr, u8 value) override { |
| 43 | parent.system.Memory().Write8(vaddr, value); | 44 | memory.Write8(vaddr, value); |
| 44 | } | 45 | } |
| 45 | void MemoryWrite16(u32 vaddr, u16 value) override { | 46 | void MemoryWrite16(u32 vaddr, u16 value) override { |
| 46 | parent.system.Memory().Write16(vaddr, value); | 47 | memory.Write16(vaddr, value); |
| 47 | } | 48 | } |
| 48 | void MemoryWrite32(u32 vaddr, u32 value) override { | 49 | void MemoryWrite32(u32 vaddr, u32 value) override { |
| 49 | parent.system.Memory().Write32(vaddr, value); | 50 | memory.Write32(vaddr, value); |
| 50 | } | 51 | } |
| 51 | void MemoryWrite64(u32 vaddr, u64 value) override { | 52 | void MemoryWrite64(u32 vaddr, u64 value) override { |
| 52 | parent.system.Memory().Write64(vaddr, value); | 53 | memory.Write64(vaddr, value); |
| 53 | } | 54 | } |
| 54 | 55 | ||
| 55 | bool MemoryWriteExclusive8(u32 vaddr, u8 value, u8 expected) override { | 56 | bool MemoryWriteExclusive8(u32 vaddr, u8 value, u8 expected) override { |
| 56 | return parent.system.Memory().WriteExclusive8(vaddr, value, expected); | 57 | return memory.WriteExclusive8(vaddr, value, expected); |
| 57 | } | 58 | } |
| 58 | bool MemoryWriteExclusive16(u32 vaddr, u16 value, u16 expected) override { | 59 | bool MemoryWriteExclusive16(u32 vaddr, u16 value, u16 expected) override { |
| 59 | return parent.system.Memory().WriteExclusive16(vaddr, value, expected); | 60 | return memory.WriteExclusive16(vaddr, value, expected); |
| 60 | } | 61 | } |
| 61 | bool MemoryWriteExclusive32(u32 vaddr, u32 value, u32 expected) override { | 62 | bool MemoryWriteExclusive32(u32 vaddr, u32 value, u32 expected) override { |
| 62 | return parent.system.Memory().WriteExclusive32(vaddr, value, expected); | 63 | return memory.WriteExclusive32(vaddr, value, expected); |
| 63 | } | 64 | } |
| 64 | bool MemoryWriteExclusive64(u32 vaddr, u64 value, u64 expected) override { | 65 | bool MemoryWriteExclusive64(u32 vaddr, u64 value, u64 expected) override { |
| 65 | return parent.system.Memory().WriteExclusive64(vaddr, value, expected); | 66 | return memory.WriteExclusive64(vaddr, value, expected); |
| 66 | } | 67 | } |
| 67 | 68 | ||
| 68 | void InterpreterFallback(u32 pc, std::size_t num_instructions) override { | 69 | void InterpreterFallback(u32 pc, std::size_t num_instructions) override { |
| @@ -78,7 +79,9 @@ public: | |||
| 78 | } | 79 | } |
| 79 | 80 | ||
| 80 | void CallSVC(u32 swi) override { | 81 | void CallSVC(u32 swi) override { |
| 81 | Kernel::Svc::Call(parent.system, swi); | 82 | parent.svc_called = true; |
| 83 | parent.svc_swi = swi; | ||
| 84 | parent.jit->HaltExecution(); | ||
| 82 | } | 85 | } |
| 83 | 86 | ||
| 84 | void AddTicks(u64 ticks) override { | 87 | void AddTicks(u64 ticks) override { |
| @@ -110,6 +113,7 @@ public: | |||
| 110 | } | 113 | } |
| 111 | 114 | ||
| 112 | ARM_Dynarmic_32& parent; | 115 | ARM_Dynarmic_32& parent; |
| 116 | Core::Memory::Memory& memory; | ||
| 113 | std::size_t num_interpreted_instructions{}; | 117 | std::size_t num_interpreted_instructions{}; |
| 114 | static constexpr u64 minimum_run_cycles = 1000U; | 118 | static constexpr u64 minimum_run_cycles = 1000U; |
| 115 | }; | 119 | }; |
| @@ -187,11 +191,17 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable* | |||
| 187 | } | 191 | } |
| 188 | 192 | ||
| 189 | void ARM_Dynarmic_32::Run() { | 193 | void ARM_Dynarmic_32::Run() { |
| 190 | jit->Run(); | 194 | while (true) { |
| 191 | } | 195 | jit->Run(); |
| 192 | 196 | if (!svc_called) { | |
| 193 | void ARM_Dynarmic_32::ExceptionalExit() { | 197 | break; |
| 194 | jit->ExceptionalExit(); | 198 | } |
| 199 | svc_called = false; | ||
| 200 | Kernel::Svc::Call(system, svc_swi); | ||
| 201 | if (shutdown) { | ||
| 202 | break; | ||
| 203 | } | ||
| 204 | } | ||
| 195 | } | 205 | } |
| 196 | 206 | ||
| 197 | void ARM_Dynarmic_32::Step() { | 207 | void ARM_Dynarmic_32::Step() { |
| @@ -255,10 +265,6 @@ void ARM_Dynarmic_32::SetTPIDR_EL0(u64 value) { | |||
| 255 | cp15->uprw = static_cast<u32>(value); | 265 | cp15->uprw = static_cast<u32>(value); |
| 256 | } | 266 | } |
| 257 | 267 | ||
| 258 | void ARM_Dynarmic_32::ChangeProcessorID(std::size_t new_core_id) { | ||
| 259 | jit->ChangeProcessorID(new_core_id); | ||
| 260 | } | ||
| 261 | |||
| 262 | void ARM_Dynarmic_32::SaveContext(ThreadContext32& ctx) { | 268 | void ARM_Dynarmic_32::SaveContext(ThreadContext32& ctx) { |
| 263 | Dynarmic::A32::Context context; | 269 | Dynarmic::A32::Context context; |
| 264 | jit->SaveContext(context); | 270 | jit->SaveContext(context); |
| @@ -279,6 +285,7 @@ void ARM_Dynarmic_32::LoadContext(const ThreadContext32& ctx) { | |||
| 279 | 285 | ||
| 280 | void ARM_Dynarmic_32::PrepareReschedule() { | 286 | void ARM_Dynarmic_32::PrepareReschedule() { |
| 281 | jit->HaltExecution(); | 287 | jit->HaltExecution(); |
| 288 | shutdown = true; | ||
| 282 | } | 289 | } |
| 283 | 290 | ||
| 284 | void ARM_Dynarmic_32::ClearInstructionCache() { | 291 | void ARM_Dynarmic_32::ClearInstructionCache() { |
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.h b/src/core/arm/dynarmic/arm_dynarmic_32.h index 42778c02c..063605b46 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.h +++ b/src/core/arm/dynarmic/arm_dynarmic_32.h | |||
| @@ -7,9 +7,9 @@ | |||
| 7 | #include <memory> | 7 | #include <memory> |
| 8 | #include <unordered_map> | 8 | #include <unordered_map> |
| 9 | 9 | ||
| 10 | #include <dynarmic/A32/a32.h> | 10 | #include <dynarmic/interface/A32/a32.h> |
| 11 | #include <dynarmic/A64/a64.h> | 11 | #include <dynarmic/interface/A64/a64.h> |
| 12 | #include <dynarmic/exclusive_monitor.h> | 12 | #include <dynarmic/interface/exclusive_monitor.h> |
| 13 | #include "common/common_types.h" | 13 | #include "common/common_types.h" |
| 14 | #include "common/hash.h" | 14 | #include "common/hash.h" |
| 15 | #include "core/arm/arm_interface.h" | 15 | #include "core/arm/arm_interface.h" |
| @@ -42,13 +42,11 @@ public: | |||
| 42 | u32 GetPSTATE() const override; | 42 | u32 GetPSTATE() const override; |
| 43 | void SetPSTATE(u32 pstate) override; | 43 | void SetPSTATE(u32 pstate) override; |
| 44 | void Run() override; | 44 | void Run() override; |
| 45 | void ExceptionalExit() override; | ||
| 46 | void Step() override; | 45 | void Step() override; |
| 47 | VAddr GetTlsAddress() const override; | 46 | VAddr GetTlsAddress() const override; |
| 48 | void SetTlsAddress(VAddr address) override; | 47 | void SetTlsAddress(VAddr address) override; |
| 49 | void SetTPIDR_EL0(u64 value) override; | 48 | void SetTPIDR_EL0(u64 value) override; |
| 50 | u64 GetTPIDR_EL0() const override; | 49 | u64 GetTPIDR_EL0() const override; |
| 51 | void ChangeProcessorID(std::size_t new_core_id) override; | ||
| 52 | 50 | ||
| 53 | bool IsInThumbMode() const { | 51 | bool IsInThumbMode() const { |
| 54 | return (GetPSTATE() & 0x20) != 0; | 52 | return (GetPSTATE() & 0x20) != 0; |
| @@ -83,6 +81,12 @@ private: | |||
| 83 | std::size_t core_index; | 81 | std::size_t core_index; |
| 84 | DynarmicExclusiveMonitor& exclusive_monitor; | 82 | DynarmicExclusiveMonitor& exclusive_monitor; |
| 85 | std::shared_ptr<Dynarmic::A32::Jit> jit; | 83 | std::shared_ptr<Dynarmic::A32::Jit> jit; |
| 84 | |||
| 85 | // SVC callback | ||
| 86 | u32 svc_swi{}; | ||
| 87 | bool svc_called{}; | ||
| 88 | |||
| 89 | bool shutdown{}; | ||
| 86 | }; | 90 | }; |
| 87 | 91 | ||
| 88 | } // namespace Core | 92 | } // namespace Core |
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp index 08fa85904..63193dcb1 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp | |||
| @@ -4,8 +4,8 @@ | |||
| 4 | 4 | ||
| 5 | #include <cinttypes> | 5 | #include <cinttypes> |
| 6 | #include <memory> | 6 | #include <memory> |
| 7 | #include <dynarmic/A64/a64.h> | 7 | #include <dynarmic/interface/A64/a64.h> |
| 8 | #include <dynarmic/A64/config.h> | 8 | #include <dynarmic/interface/A64/config.h> |
| 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" |
| @@ -27,57 +27,56 @@ using Vector = Dynarmic::A64::Vector; | |||
| 27 | 27 | ||
| 28 | class DynarmicCallbacks64 : public Dynarmic::A64::UserCallbacks { | 28 | class DynarmicCallbacks64 : public Dynarmic::A64::UserCallbacks { |
| 29 | public: | 29 | public: |
| 30 | explicit DynarmicCallbacks64(ARM_Dynarmic_64& parent_) : parent{parent_} {} | 30 | explicit DynarmicCallbacks64(ARM_Dynarmic_64& parent_) |
| 31 | : parent{parent_}, memory(parent.system.Memory()) {} | ||
| 31 | 32 | ||
| 32 | u8 MemoryRead8(u64 vaddr) override { | 33 | u8 MemoryRead8(u64 vaddr) override { |
| 33 | return parent.system.Memory().Read8(vaddr); | 34 | return memory.Read8(vaddr); |
| 34 | } | 35 | } |
| 35 | u16 MemoryRead16(u64 vaddr) override { | 36 | u16 MemoryRead16(u64 vaddr) override { |
| 36 | return parent.system.Memory().Read16(vaddr); | 37 | return memory.Read16(vaddr); |
| 37 | } | 38 | } |
| 38 | u32 MemoryRead32(u64 vaddr) override { | 39 | u32 MemoryRead32(u64 vaddr) override { |
| 39 | return parent.system.Memory().Read32(vaddr); | 40 | return memory.Read32(vaddr); |
| 40 | } | 41 | } |
| 41 | u64 MemoryRead64(u64 vaddr) override { | 42 | u64 MemoryRead64(u64 vaddr) override { |
| 42 | return parent.system.Memory().Read64(vaddr); | 43 | return memory.Read64(vaddr); |
| 43 | } | 44 | } |
| 44 | Vector MemoryRead128(u64 vaddr) override { | 45 | Vector MemoryRead128(u64 vaddr) override { |
| 45 | auto& memory = parent.system.Memory(); | ||
| 46 | return {memory.Read64(vaddr), memory.Read64(vaddr + 8)}; | 46 | return {memory.Read64(vaddr), memory.Read64(vaddr + 8)}; |
| 47 | } | 47 | } |
| 48 | 48 | ||
| 49 | void MemoryWrite8(u64 vaddr, u8 value) override { | 49 | void MemoryWrite8(u64 vaddr, u8 value) override { |
| 50 | parent.system.Memory().Write8(vaddr, value); | 50 | memory.Write8(vaddr, value); |
| 51 | } | 51 | } |
| 52 | void MemoryWrite16(u64 vaddr, u16 value) override { | 52 | void MemoryWrite16(u64 vaddr, u16 value) override { |
| 53 | parent.system.Memory().Write16(vaddr, value); | 53 | memory.Write16(vaddr, value); |
| 54 | } | 54 | } |
| 55 | void MemoryWrite32(u64 vaddr, u32 value) override { | 55 | void MemoryWrite32(u64 vaddr, u32 value) override { |
| 56 | parent.system.Memory().Write32(vaddr, value); | 56 | memory.Write32(vaddr, value); |
| 57 | } | 57 | } |
| 58 | void MemoryWrite64(u64 vaddr, u64 value) override { | 58 | void MemoryWrite64(u64 vaddr, u64 value) override { |
| 59 | parent.system.Memory().Write64(vaddr, value); | 59 | memory.Write64(vaddr, value); |
| 60 | } | 60 | } |
| 61 | void MemoryWrite128(u64 vaddr, Vector value) override { | 61 | void MemoryWrite128(u64 vaddr, Vector value) override { |
| 62 | auto& memory = parent.system.Memory(); | ||
| 63 | memory.Write64(vaddr, value[0]); | 62 | memory.Write64(vaddr, value[0]); |
| 64 | memory.Write64(vaddr + 8, value[1]); | 63 | memory.Write64(vaddr + 8, value[1]); |
| 65 | } | 64 | } |
| 66 | 65 | ||
| 67 | bool MemoryWriteExclusive8(u64 vaddr, std::uint8_t value, std::uint8_t expected) override { | 66 | bool MemoryWriteExclusive8(u64 vaddr, std::uint8_t value, std::uint8_t expected) override { |
| 68 | return parent.system.Memory().WriteExclusive8(vaddr, value, expected); | 67 | return memory.WriteExclusive8(vaddr, value, expected); |
| 69 | } | 68 | } |
| 70 | bool MemoryWriteExclusive16(u64 vaddr, std::uint16_t value, std::uint16_t expected) override { | 69 | bool MemoryWriteExclusive16(u64 vaddr, std::uint16_t value, std::uint16_t expected) override { |
| 71 | return parent.system.Memory().WriteExclusive16(vaddr, value, expected); | 70 | return memory.WriteExclusive16(vaddr, value, expected); |
| 72 | } | 71 | } |
| 73 | bool MemoryWriteExclusive32(u64 vaddr, std::uint32_t value, std::uint32_t expected) override { | 72 | bool MemoryWriteExclusive32(u64 vaddr, std::uint32_t value, std::uint32_t expected) override { |
| 74 | return parent.system.Memory().WriteExclusive32(vaddr, value, expected); | 73 | return memory.WriteExclusive32(vaddr, value, expected); |
| 75 | } | 74 | } |
| 76 | bool MemoryWriteExclusive64(u64 vaddr, std::uint64_t value, std::uint64_t expected) override { | 75 | bool MemoryWriteExclusive64(u64 vaddr, std::uint64_t value, std::uint64_t expected) override { |
| 77 | return parent.system.Memory().WriteExclusive64(vaddr, value, expected); | 76 | return memory.WriteExclusive64(vaddr, value, expected); |
| 78 | } | 77 | } |
| 79 | bool MemoryWriteExclusive128(u64 vaddr, Vector value, Vector expected) override { | 78 | bool MemoryWriteExclusive128(u64 vaddr, Vector value, Vector expected) override { |
| 80 | return parent.system.Memory().WriteExclusive128(vaddr, value, expected); | 79 | return memory.WriteExclusive128(vaddr, value, expected); |
| 81 | } | 80 | } |
| 82 | 81 | ||
| 83 | void InterpreterFallback(u64 pc, std::size_t num_instructions) override { | 82 | void InterpreterFallback(u64 pc, std::size_t num_instructions) override { |
| @@ -102,7 +101,9 @@ public: | |||
| 102 | } | 101 | } |
| 103 | 102 | ||
| 104 | void CallSVC(u32 swi) override { | 103 | void CallSVC(u32 swi) override { |
| 105 | Kernel::Svc::Call(parent.system, swi); | 104 | parent.svc_called = true; |
| 105 | parent.svc_swi = swi; | ||
| 106 | parent.jit->HaltExecution(); | ||
| 106 | } | 107 | } |
| 107 | 108 | ||
| 108 | void AddTicks(u64 ticks) override { | 109 | void AddTicks(u64 ticks) override { |
| @@ -137,6 +138,7 @@ public: | |||
| 137 | } | 138 | } |
| 138 | 139 | ||
| 139 | ARM_Dynarmic_64& parent; | 140 | ARM_Dynarmic_64& parent; |
| 141 | Core::Memory::Memory& memory; | ||
| 140 | u64 tpidrro_el0 = 0; | 142 | u64 tpidrro_el0 = 0; |
| 141 | u64 tpidr_el0 = 0; | 143 | u64 tpidr_el0 = 0; |
| 142 | static constexpr u64 minimum_run_cycles = 1000U; | 144 | static constexpr u64 minimum_run_cycles = 1000U; |
| @@ -227,11 +229,17 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable* | |||
| 227 | } | 229 | } |
| 228 | 230 | ||
| 229 | void ARM_Dynarmic_64::Run() { | 231 | void ARM_Dynarmic_64::Run() { |
| 230 | jit->Run(); | 232 | while (true) { |
| 231 | } | 233 | jit->Run(); |
| 232 | 234 | if (!svc_called) { | |
| 233 | void ARM_Dynarmic_64::ExceptionalExit() { | 235 | break; |
| 234 | jit->ExceptionalExit(); | 236 | } |
| 237 | svc_called = false; | ||
| 238 | Kernel::Svc::Call(system, svc_swi); | ||
| 239 | if (shutdown) { | ||
| 240 | break; | ||
| 241 | } | ||
| 242 | } | ||
| 235 | } | 243 | } |
| 236 | 244 | ||
| 237 | void ARM_Dynarmic_64::Step() { | 245 | void ARM_Dynarmic_64::Step() { |
| @@ -296,10 +304,6 @@ void ARM_Dynarmic_64::SetTPIDR_EL0(u64 value) { | |||
| 296 | cb->tpidr_el0 = value; | 304 | cb->tpidr_el0 = value; |
| 297 | } | 305 | } |
| 298 | 306 | ||
| 299 | void ARM_Dynarmic_64::ChangeProcessorID(std::size_t new_core_id) { | ||
| 300 | jit->ChangeProcessorID(new_core_id); | ||
| 301 | } | ||
| 302 | |||
| 303 | void ARM_Dynarmic_64::SaveContext(ThreadContext64& ctx) { | 307 | void ARM_Dynarmic_64::SaveContext(ThreadContext64& ctx) { |
| 304 | ctx.cpu_registers = jit->GetRegisters(); | 308 | ctx.cpu_registers = jit->GetRegisters(); |
| 305 | ctx.sp = jit->GetSP(); | 309 | ctx.sp = jit->GetSP(); |
| @@ -324,6 +328,7 @@ void ARM_Dynarmic_64::LoadContext(const ThreadContext64& ctx) { | |||
| 324 | 328 | ||
| 325 | void ARM_Dynarmic_64::PrepareReschedule() { | 329 | void ARM_Dynarmic_64::PrepareReschedule() { |
| 326 | jit->HaltExecution(); | 330 | jit->HaltExecution(); |
| 331 | shutdown = true; | ||
| 327 | } | 332 | } |
| 328 | 333 | ||
| 329 | void ARM_Dynarmic_64::ClearInstructionCache() { | 334 | void ARM_Dynarmic_64::ClearInstructionCache() { |
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.h b/src/core/arm/dynarmic/arm_dynarmic_64.h index b81fbcc66..0c4e46c64 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.h +++ b/src/core/arm/dynarmic/arm_dynarmic_64.h | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | #include <memory> | 7 | #include <memory> |
| 8 | #include <unordered_map> | 8 | #include <unordered_map> |
| 9 | 9 | ||
| 10 | #include <dynarmic/A64/a64.h> | 10 | #include <dynarmic/interface/A64/a64.h> |
| 11 | #include "common/common_types.h" | 11 | #include "common/common_types.h" |
| 12 | #include "common/hash.h" | 12 | #include "common/hash.h" |
| 13 | #include "core/arm/arm_interface.h" | 13 | #include "core/arm/arm_interface.h" |
| @@ -40,12 +40,10 @@ public: | |||
| 40 | void SetPSTATE(u32 pstate) override; | 40 | void SetPSTATE(u32 pstate) override; |
| 41 | void Run() override; | 41 | void Run() override; |
| 42 | void Step() override; | 42 | void Step() override; |
| 43 | void ExceptionalExit() override; | ||
| 44 | VAddr GetTlsAddress() const override; | 43 | VAddr GetTlsAddress() const override; |
| 45 | void SetTlsAddress(VAddr address) override; | 44 | void SetTlsAddress(VAddr address) override; |
| 46 | void SetTPIDR_EL0(u64 value) override; | 45 | void SetTPIDR_EL0(u64 value) override; |
| 47 | u64 GetTPIDR_EL0() const override; | 46 | u64 GetTPIDR_EL0() const override; |
| 48 | void ChangeProcessorID(std::size_t new_core_id) override; | ||
| 49 | 47 | ||
| 50 | void SaveContext(ThreadContext32& ctx) override {} | 48 | void SaveContext(ThreadContext32& ctx) override {} |
| 51 | void SaveContext(ThreadContext64& ctx) override; | 49 | void SaveContext(ThreadContext64& ctx) override; |
| @@ -76,6 +74,12 @@ private: | |||
| 76 | DynarmicExclusiveMonitor& exclusive_monitor; | 74 | DynarmicExclusiveMonitor& exclusive_monitor; |
| 77 | 75 | ||
| 78 | std::shared_ptr<Dynarmic::A64::Jit> jit; | 76 | std::shared_ptr<Dynarmic::A64::Jit> jit; |
| 77 | |||
| 78 | // SVC callback | ||
| 79 | u32 svc_swi{}; | ||
| 80 | bool svc_called{}; | ||
| 81 | |||
| 82 | bool shutdown{}; | ||
| 79 | }; | 83 | }; |
| 80 | 84 | ||
| 81 | } // namespace Core | 85 | } // namespace Core |
diff --git a/src/core/arm/dynarmic/arm_dynarmic_cp15.h b/src/core/arm/dynarmic/arm_dynarmic_cp15.h index 8597beddf..7c7ede79e 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_cp15.h +++ b/src/core/arm/dynarmic/arm_dynarmic_cp15.h | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | #include <memory> | 7 | #include <memory> |
| 8 | #include <optional> | 8 | #include <optional> |
| 9 | 9 | ||
| 10 | #include <dynarmic/A32/coprocessor.h> | 10 | #include <dynarmic/interface/A32/coprocessor.h> |
| 11 | #include "common/common_types.h" | 11 | #include "common/common_types.h" |
| 12 | 12 | ||
| 13 | namespace Core { | 13 | namespace Core { |
diff --git a/src/core/arm/dynarmic/arm_exclusive_monitor.h b/src/core/arm/dynarmic/arm_exclusive_monitor.h index f9f056a59..73d41f223 100644 --- a/src/core/arm/dynarmic/arm_exclusive_monitor.h +++ b/src/core/arm/dynarmic/arm_exclusive_monitor.h | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | #include <memory> | 7 | #include <memory> |
| 8 | #include <unordered_map> | 8 | #include <unordered_map> |
| 9 | 9 | ||
| 10 | #include <dynarmic/exclusive_monitor.h> | 10 | #include <dynarmic/interface/exclusive_monitor.h> |
| 11 | 11 | ||
| 12 | #include "common/common_types.h" | 12 | #include "common/common_types.h" |
| 13 | #include "core/arm/dynarmic/arm_dynarmic_32.h" | 13 | #include "core/arm/dynarmic/arm_dynarmic_32.h" |
diff --git a/src/core/hle/kernel/k_class_token.cpp b/src/core/hle/kernel/k_class_token.cpp index beb8a2a05..0be0027be 100644 --- a/src/core/hle/kernel/k_class_token.cpp +++ b/src/core/hle/kernel/k_class_token.cpp | |||
| @@ -84,50 +84,43 @@ static_assert(ClassToken<KTransferMemory> == ((0b10010001 << 8) | ClassToken<KAu | |||
| 84 | // Ensure that the token hierarchy reflects the class hierarchy. | 84 | // Ensure that the token hierarchy reflects the class hierarchy. |
| 85 | 85 | ||
| 86 | // Base classes. | 86 | // Base classes. |
| 87 | static_assert(!std::is_final<KSynchronizationObject>::value && | 87 | static_assert(!std::is_final_v<KSynchronizationObject> && |
| 88 | std::is_base_of<KAutoObject, KSynchronizationObject>::value); | 88 | std::is_base_of_v<KAutoObject, KSynchronizationObject>); |
| 89 | static_assert(!std::is_final<KReadableEvent>::value && | 89 | static_assert(!std::is_final_v<KReadableEvent> && |
| 90 | std::is_base_of<KSynchronizationObject, KReadableEvent>::value); | 90 | std::is_base_of_v<KSynchronizationObject, KReadableEvent>); |
| 91 | 91 | ||
| 92 | // Final classes | 92 | // Final classes |
| 93 | // static_assert(std::is_final<KInterruptEvent>::value && | 93 | // static_assert(std::is_final_v<KInterruptEvent> && |
| 94 | // std::is_base_of<KReadableEvent, KInterruptEvent>::value); | 94 | // std::is_base_of_v<KReadableEvent, KInterruptEvent>); |
| 95 | // static_assert(std::is_final<KDebug>::value && | 95 | // static_assert(std::is_final_v<KDebug> && |
| 96 | // std::is_base_of<KSynchronizationObject, KDebug>::value); | 96 | // std::is_base_of_v<KSynchronizationObject, KDebug>); |
| 97 | static_assert(std::is_final<KThread>::value && | 97 | static_assert(std::is_final_v<KThread> && std::is_base_of_v<KSynchronizationObject, KThread>); |
| 98 | std::is_base_of<KSynchronizationObject, KThread>::value); | 98 | static_assert(std::is_final_v<KServerPort> && |
| 99 | static_assert(std::is_final<KServerPort>::value && | 99 | std::is_base_of_v<KSynchronizationObject, KServerPort>); |
| 100 | std::is_base_of<KSynchronizationObject, KServerPort>::value); | 100 | static_assert(std::is_final_v<KServerSession> && |
| 101 | static_assert(std::is_final<KServerSession>::value && | 101 | std::is_base_of_v<KSynchronizationObject, KServerSession>); |
| 102 | std::is_base_of<KSynchronizationObject, KServerSession>::value); | 102 | static_assert(std::is_final_v<KClientPort> && |
| 103 | static_assert(std::is_final<KClientPort>::value && | 103 | std::is_base_of_v<KSynchronizationObject, KClientPort>); |
| 104 | std::is_base_of<KSynchronizationObject, KClientPort>::value); | 104 | static_assert(std::is_final_v<KClientSession> && std::is_base_of_v<KAutoObject, KClientSession>); |
| 105 | static_assert(std::is_final<KClientSession>::value && | 105 | static_assert(std::is_final_v<KProcess> && std::is_base_of_v<KSynchronizationObject, KProcess>); |
| 106 | std::is_base_of<KAutoObject, KClientSession>::value); | 106 | static_assert(std::is_final_v<KResourceLimit> && std::is_base_of_v<KAutoObject, KResourceLimit>); |
| 107 | static_assert(std::is_final<KProcess>::value && | 107 | // static_assert(std::is_final_v<KLightSession> && |
| 108 | std::is_base_of<KSynchronizationObject, KProcess>::value); | 108 | // std::is_base_of_v<KAutoObject, KLightSession>); |
| 109 | static_assert(std::is_final<KResourceLimit>::value && | 109 | static_assert(std::is_final_v<KPort> && std::is_base_of_v<KAutoObject, KPort>); |
| 110 | std::is_base_of<KAutoObject, KResourceLimit>::value); | 110 | static_assert(std::is_final_v<KSession> && std::is_base_of_v<KAutoObject, KSession>); |
| 111 | // static_assert(std::is_final<KLightSession>::value && | 111 | static_assert(std::is_final_v<KSharedMemory> && std::is_base_of_v<KAutoObject, KSharedMemory>); |
| 112 | // std::is_base_of<KAutoObject, KLightSession>::value); | 112 | static_assert(std::is_final_v<KEvent> && std::is_base_of_v<KAutoObject, KEvent>); |
| 113 | static_assert(std::is_final<KPort>::value && std::is_base_of<KAutoObject, KPort>::value); | 113 | static_assert(std::is_final_v<KWritableEvent> && std::is_base_of_v<KAutoObject, KWritableEvent>); |
| 114 | static_assert(std::is_final<KSession>::value && std::is_base_of<KAutoObject, KSession>::value); | 114 | // static_assert(std::is_final_v<KLightClientSession> && |
| 115 | static_assert(std::is_final<KSharedMemory>::value && | 115 | // std::is_base_of_v<KAutoObject, KLightClientSession>); |
| 116 | std::is_base_of<KAutoObject, KSharedMemory>::value); | 116 | // static_assert(std::is_final_v<KLightServerSession> && |
| 117 | static_assert(std::is_final<KEvent>::value && std::is_base_of<KAutoObject, KEvent>::value); | 117 | // std::is_base_of_v<KAutoObject, KLightServerSession>); |
| 118 | static_assert(std::is_final<KWritableEvent>::value && | 118 | static_assert(std::is_final_v<KTransferMemory> && std::is_base_of_v<KAutoObject, KTransferMemory>); |
| 119 | std::is_base_of<KAutoObject, KWritableEvent>::value); | 119 | // static_assert(std::is_final_v<KDeviceAddressSpace> && |
| 120 | // static_assert(std::is_final<KLightClientSession>::value && | 120 | // std::is_base_of_v<KAutoObject, KDeviceAddressSpace>); |
| 121 | // std::is_base_of<KAutoObject, KLightClientSession>::value); | 121 | // static_assert(std::is_final_v<KSessionRequest> && |
| 122 | // static_assert(std::is_final<KLightServerSession>::value && | 122 | // std::is_base_of_v<KAutoObject, KSessionRequest>); |
| 123 | // std::is_base_of<KAutoObject, KLightServerSession>::value); | 123 | // static_assert(std::is_final_v<KCodeMemory> && |
| 124 | static_assert(std::is_final<KTransferMemory>::value && | 124 | // std::is_base_of_v<KAutoObject, KCodeMemory>); |
| 125 | std::is_base_of<KAutoObject, KTransferMemory>::value); | ||
| 126 | // static_assert(std::is_final<KDeviceAddressSpace>::value && | ||
| 127 | // std::is_base_of<KAutoObject, KDeviceAddressSpace>::value); | ||
| 128 | // static_assert(std::is_final<KSessionRequest>::value && | ||
| 129 | // std::is_base_of<KAutoObject, KSessionRequest>::value); | ||
| 130 | // static_assert(std::is_final<KCodeMemory>::value && | ||
| 131 | // std::is_base_of<KAutoObject, KCodeMemory>::value); | ||
| 132 | 125 | ||
| 133 | } // namespace Kernel | 126 | } // namespace Kernel |
diff --git a/src/core/hle/kernel/k_client_port.h b/src/core/hle/kernel/k_client_port.h index 8501156e8..f2fff3b01 100644 --- a/src/core/hle/kernel/k_client_port.h +++ b/src/core/hle/kernel/k_client_port.h | |||
| @@ -22,7 +22,7 @@ class KClientPort final : public KSynchronizationObject { | |||
| 22 | 22 | ||
| 23 | public: | 23 | public: |
| 24 | explicit KClientPort(KernelCore& kernel_); | 24 | explicit KClientPort(KernelCore& kernel_); |
| 25 | virtual ~KClientPort() override; | 25 | ~KClientPort() override; |
| 26 | 26 | ||
| 27 | void Initialize(KPort* parent_, s32 max_sessions_, std::string&& name_); | 27 | void Initialize(KPort* parent_, s32 max_sessions_, std::string&& name_); |
| 28 | void OnSessionFinalized(); | 28 | void OnSessionFinalized(); |
| @@ -49,8 +49,8 @@ public: | |||
| 49 | bool IsServerClosed() const; | 49 | bool IsServerClosed() const; |
| 50 | 50 | ||
| 51 | // Overridden virtual functions. | 51 | // Overridden virtual functions. |
| 52 | virtual void Destroy() override; | 52 | void Destroy() override; |
| 53 | virtual bool IsSignaled() const override; | 53 | bool IsSignaled() const override; |
| 54 | 54 | ||
| 55 | ResultCode CreateSession(KClientSession** out); | 55 | ResultCode CreateSession(KClientSession** out); |
| 56 | 56 | ||
diff --git a/src/core/hle/kernel/k_client_session.h b/src/core/hle/kernel/k_client_session.h index 720a8c243..b11d5b4e3 100644 --- a/src/core/hle/kernel/k_client_session.h +++ b/src/core/hle/kernel/k_client_session.h | |||
| @@ -34,7 +34,7 @@ class KClientSession final | |||
| 34 | 34 | ||
| 35 | public: | 35 | public: |
| 36 | explicit KClientSession(KernelCore& kernel_); | 36 | explicit KClientSession(KernelCore& kernel_); |
| 37 | virtual ~KClientSession(); | 37 | ~KClientSession() override; |
| 38 | 38 | ||
| 39 | void Initialize(KSession* parent_, std::string&& name_) { | 39 | void Initialize(KSession* parent_, std::string&& name_) { |
| 40 | // Set member variables. | 40 | // Set member variables. |
| @@ -42,7 +42,7 @@ public: | |||
| 42 | name = std::move(name_); | 42 | name = std::move(name_); |
| 43 | } | 43 | } |
| 44 | 44 | ||
| 45 | virtual void Destroy() override; | 45 | void Destroy() override; |
| 46 | static void PostDestroy([[maybe_unused]] uintptr_t arg) {} | 46 | static void PostDestroy([[maybe_unused]] uintptr_t arg) {} |
| 47 | 47 | ||
| 48 | KSession* GetParent() const { | 48 | KSession* GetParent() const { |
diff --git a/src/core/hle/kernel/k_event.h b/src/core/hle/kernel/k_event.h index 9a59ffb70..3d3ec99e2 100644 --- a/src/core/hle/kernel/k_event.h +++ b/src/core/hle/kernel/k_event.h | |||
| @@ -20,23 +20,21 @@ class KEvent final : public KAutoObjectWithSlabHeapAndContainer<KEvent, KAutoObj | |||
| 20 | 20 | ||
| 21 | public: | 21 | public: |
| 22 | explicit KEvent(KernelCore& kernel_); | 22 | explicit KEvent(KernelCore& kernel_); |
| 23 | virtual ~KEvent(); | 23 | ~KEvent() override; |
| 24 | 24 | ||
| 25 | void Initialize(std::string&& name); | 25 | void Initialize(std::string&& name); |
| 26 | 26 | ||
| 27 | virtual void Finalize() override; | 27 | void Finalize() override; |
| 28 | 28 | ||
| 29 | virtual bool IsInitialized() const override { | 29 | bool IsInitialized() const override { |
| 30 | return initialized; | 30 | return initialized; |
| 31 | } | 31 | } |
| 32 | 32 | ||
| 33 | virtual uintptr_t GetPostDestroyArgument() const override { | 33 | uintptr_t GetPostDestroyArgument() const override { |
| 34 | return reinterpret_cast<uintptr_t>(owner); | 34 | return reinterpret_cast<uintptr_t>(owner); |
| 35 | } | 35 | } |
| 36 | 36 | ||
| 37 | static void PostDestroy(uintptr_t arg); | 37 | KProcess* GetOwner() const override { |
| 38 | |||
| 39 | virtual KProcess* GetOwner() const override { | ||
| 40 | return owner; | 38 | return owner; |
| 41 | } | 39 | } |
| 42 | 40 | ||
| @@ -48,6 +46,8 @@ public: | |||
| 48 | return writable_event; | 46 | return writable_event; |
| 49 | } | 47 | } |
| 50 | 48 | ||
| 49 | static void PostDestroy(uintptr_t arg); | ||
| 50 | |||
| 51 | private: | 51 | private: |
| 52 | KReadableEvent readable_event; | 52 | KReadableEvent readable_event; |
| 53 | KWritableEvent writable_event; | 53 | KWritableEvent writable_event; |
diff --git a/src/core/hle/kernel/k_port.h b/src/core/hle/kernel/k_port.h index 960f1f3a3..4018ea2df 100644 --- a/src/core/hle/kernel/k_port.h +++ b/src/core/hle/kernel/k_port.h | |||
| @@ -22,7 +22,7 @@ class KPort final : public KAutoObjectWithSlabHeapAndContainer<KPort, KAutoObjec | |||
| 22 | 22 | ||
| 23 | public: | 23 | public: |
| 24 | explicit KPort(KernelCore& kernel_); | 24 | explicit KPort(KernelCore& kernel_); |
| 25 | virtual ~KPort(); | 25 | ~KPort() override; |
| 26 | 26 | ||
| 27 | static void PostDestroy([[maybe_unused]] uintptr_t arg) {} | 27 | static void PostDestroy([[maybe_unused]] uintptr_t arg) {} |
| 28 | 28 | ||
| @@ -59,7 +59,6 @@ private: | |||
| 59 | ServerClosed = 3, | 59 | ServerClosed = 3, |
| 60 | }; | 60 | }; |
| 61 | 61 | ||
| 62 | private: | ||
| 63 | KServerPort server; | 62 | KServerPort server; |
| 64 | KClientPort client; | 63 | KClientPort client; |
| 65 | State state{State::Invalid}; | 64 | State state{State::Invalid}; |
diff --git a/src/core/hle/kernel/k_process.h b/src/core/hle/kernel/k_process.h index 123d71cd3..c0656b9af 100644 --- a/src/core/hle/kernel/k_process.h +++ b/src/core/hle/kernel/k_process.h | |||
| @@ -331,19 +331,19 @@ public: | |||
| 331 | 331 | ||
| 332 | void LoadModule(CodeSet code_set, VAddr base_addr); | 332 | void LoadModule(CodeSet code_set, VAddr base_addr); |
| 333 | 333 | ||
| 334 | virtual bool IsInitialized() const override { | 334 | bool IsInitialized() const override { |
| 335 | return is_initialized; | 335 | return is_initialized; |
| 336 | } | 336 | } |
| 337 | 337 | ||
| 338 | static void PostDestroy([[maybe_unused]] uintptr_t arg) {} | 338 | static void PostDestroy([[maybe_unused]] uintptr_t arg) {} |
| 339 | 339 | ||
| 340 | virtual void Finalize(); | 340 | void Finalize() override; |
| 341 | 341 | ||
| 342 | virtual u64 GetId() const override final { | 342 | u64 GetId() const override { |
| 343 | return GetProcessID(); | 343 | return GetProcessID(); |
| 344 | } | 344 | } |
| 345 | 345 | ||
| 346 | virtual bool IsSignaled() const override; | 346 | bool IsSignaled() const override; |
| 347 | 347 | ||
| 348 | void PinCurrentThread(); | 348 | void PinCurrentThread(); |
| 349 | void UnpinCurrentThread(); | 349 | void UnpinCurrentThread(); |
diff --git a/src/core/hle/kernel/k_readable_event.h b/src/core/hle/kernel/k_readable_event.h index 33cd1dd3e..b2850ac7b 100644 --- a/src/core/hle/kernel/k_readable_event.h +++ b/src/core/hle/kernel/k_readable_event.h | |||
| @@ -31,8 +31,8 @@ public: | |||
| 31 | return parent; | 31 | return parent; |
| 32 | } | 32 | } |
| 33 | 33 | ||
| 34 | virtual bool IsSignaled() const override; | 34 | bool IsSignaled() const override; |
| 35 | virtual void Destroy() override; | 35 | void Destroy() override; |
| 36 | 36 | ||
| 37 | ResultCode Signal(); | 37 | ResultCode Signal(); |
| 38 | ResultCode Clear(); | 38 | ResultCode Clear(); |
diff --git a/src/core/hle/kernel/k_resource_limit.h b/src/core/hle/kernel/k_resource_limit.h index 0debbbb51..fab6005ff 100644 --- a/src/core/hle/kernel/k_resource_limit.h +++ b/src/core/hle/kernel/k_resource_limit.h | |||
| @@ -37,10 +37,10 @@ class KResourceLimit final | |||
| 37 | 37 | ||
| 38 | public: | 38 | public: |
| 39 | explicit KResourceLimit(KernelCore& kernel_); | 39 | explicit KResourceLimit(KernelCore& kernel_); |
| 40 | virtual ~KResourceLimit(); | 40 | ~KResourceLimit() override; |
| 41 | 41 | ||
| 42 | void Initialize(const Core::Timing::CoreTiming* core_timing_); | 42 | void Initialize(const Core::Timing::CoreTiming* core_timing_); |
| 43 | virtual void Finalize() override; | 43 | void Finalize() override; |
| 44 | 44 | ||
| 45 | s64 GetLimitValue(LimitableResource which) const; | 45 | s64 GetLimitValue(LimitableResource which) const; |
| 46 | s64 GetCurrentValue(LimitableResource which) const; | 46 | s64 GetCurrentValue(LimitableResource which) const; |
diff --git a/src/core/hle/kernel/k_scheduler.cpp b/src/core/hle/kernel/k_scheduler.cpp index 2f82fbcd6..6a7d80d03 100644 --- a/src/core/hle/kernel/k_scheduler.cpp +++ b/src/core/hle/kernel/k_scheduler.cpp | |||
| @@ -659,7 +659,6 @@ void KScheduler::Unload(KThread* thread) { | |||
| 659 | 659 | ||
| 660 | if (thread) { | 660 | if (thread) { |
| 661 | if (thread->IsCallingSvc()) { | 661 | if (thread->IsCallingSvc()) { |
| 662 | system.ArmInterface(core_id).ExceptionalExit(); | ||
| 663 | thread->ClearIsCallingSvc(); | 662 | thread->ClearIsCallingSvc(); |
| 664 | } | 663 | } |
| 665 | if (!thread->IsTerminationRequested()) { | 664 | if (!thread->IsTerminationRequested()) { |
diff --git a/src/core/hle/kernel/k_server_port.h b/src/core/hle/kernel/k_server_port.h index d1a757ec3..55481d63f 100644 --- a/src/core/hle/kernel/k_server_port.h +++ b/src/core/hle/kernel/k_server_port.h | |||
| @@ -25,12 +25,9 @@ class SessionRequestHandler; | |||
| 25 | class KServerPort final : public KSynchronizationObject { | 25 | class KServerPort final : public KSynchronizationObject { |
| 26 | KERNEL_AUTOOBJECT_TRAITS(KServerPort, KSynchronizationObject); | 26 | KERNEL_AUTOOBJECT_TRAITS(KServerPort, KSynchronizationObject); |
| 27 | 27 | ||
| 28 | private: | ||
| 29 | using SessionList = boost::intrusive::list<KServerSession>; | ||
| 30 | |||
| 31 | public: | 28 | public: |
| 32 | explicit KServerPort(KernelCore& kernel_); | 29 | explicit KServerPort(KernelCore& kernel_); |
| 33 | virtual ~KServerPort() override; | 30 | ~KServerPort() override; |
| 34 | 31 | ||
| 35 | void Initialize(KPort* parent_, std::string&& name_); | 32 | void Initialize(KPort* parent_, std::string&& name_); |
| 36 | 33 | ||
| @@ -63,13 +60,14 @@ public: | |||
| 63 | bool IsLight() const; | 60 | bool IsLight() const; |
| 64 | 61 | ||
| 65 | // Overridden virtual functions. | 62 | // Overridden virtual functions. |
| 66 | virtual void Destroy() override; | 63 | void Destroy() override; |
| 67 | virtual bool IsSignaled() const override; | 64 | bool IsSignaled() const override; |
| 68 | 65 | ||
| 69 | private: | 66 | private: |
| 67 | using SessionList = boost::intrusive::list<KServerSession>; | ||
| 68 | |||
| 70 | void CleanupSessions(); | 69 | void CleanupSessions(); |
| 71 | 70 | ||
| 72 | private: | ||
| 73 | SessionList session_list; | 71 | SessionList session_list; |
| 74 | SessionRequestHandlerPtr session_handler; | 72 | SessionRequestHandlerPtr session_handler; |
| 75 | KPort* parent{}; | 73 | KPort* parent{}; |
diff --git a/src/core/hle/kernel/k_server_session.h b/src/core/hle/kernel/k_server_session.h index dd4de2904..27b757ad2 100644 --- a/src/core/hle/kernel/k_server_session.h +++ b/src/core/hle/kernel/k_server_session.h | |||
| @@ -42,9 +42,9 @@ class KServerSession final : public KSynchronizationObject, | |||
| 42 | 42 | ||
| 43 | public: | 43 | public: |
| 44 | explicit KServerSession(KernelCore& kernel_); | 44 | explicit KServerSession(KernelCore& kernel_); |
| 45 | virtual ~KServerSession() override; | 45 | ~KServerSession() override; |
| 46 | 46 | ||
| 47 | virtual void Destroy() override; | 47 | void Destroy() override; |
| 48 | 48 | ||
| 49 | void Initialize(KSession* parent_, std::string&& name_); | 49 | void Initialize(KSession* parent_, std::string&& name_); |
| 50 | 50 | ||
| @@ -56,7 +56,7 @@ public: | |||
| 56 | return parent; | 56 | return parent; |
| 57 | } | 57 | } |
| 58 | 58 | ||
| 59 | virtual bool IsSignaled() const override; | 59 | bool IsSignaled() const override; |
| 60 | 60 | ||
| 61 | void OnClientClosed(); | 61 | void OnClientClosed(); |
| 62 | 62 | ||
diff --git a/src/core/hle/kernel/k_session.h b/src/core/hle/kernel/k_session.h index a981fd1f6..4ddd080d2 100644 --- a/src/core/hle/kernel/k_session.h +++ b/src/core/hle/kernel/k_session.h | |||
| @@ -18,17 +18,17 @@ class KSession final : public KAutoObjectWithSlabHeapAndContainer<KSession, KAut | |||
| 18 | 18 | ||
| 19 | public: | 19 | public: |
| 20 | explicit KSession(KernelCore& kernel_); | 20 | explicit KSession(KernelCore& kernel_); |
| 21 | virtual ~KSession() override; | 21 | ~KSession() override; |
| 22 | 22 | ||
| 23 | void Initialize(KClientPort* port_, const std::string& name_); | 23 | void Initialize(KClientPort* port_, const std::string& name_); |
| 24 | 24 | ||
| 25 | virtual void Finalize() override; | 25 | void Finalize() override; |
| 26 | 26 | ||
| 27 | virtual bool IsInitialized() const override { | 27 | bool IsInitialized() const override { |
| 28 | return initialized; | 28 | return initialized; |
| 29 | } | 29 | } |
| 30 | 30 | ||
| 31 | virtual uintptr_t GetPostDestroyArgument() const override { | 31 | uintptr_t GetPostDestroyArgument() const override { |
| 32 | return reinterpret_cast<uintptr_t>(process); | 32 | return reinterpret_cast<uintptr_t>(process); |
| 33 | } | 33 | } |
| 34 | 34 | ||
| @@ -78,7 +78,6 @@ private: | |||
| 78 | ServerClosed = 3, | 78 | ServerClosed = 3, |
| 79 | }; | 79 | }; |
| 80 | 80 | ||
| 81 | private: | ||
| 82 | void SetState(State state) { | 81 | void SetState(State state) { |
| 83 | atomic_state = static_cast<u8>(state); | 82 | atomic_state = static_cast<u8>(state); |
| 84 | } | 83 | } |
| @@ -87,7 +86,6 @@ private: | |||
| 87 | return static_cast<State>(atomic_state.load(std::memory_order_relaxed)); | 86 | return static_cast<State>(atomic_state.load(std::memory_order_relaxed)); |
| 88 | } | 87 | } |
| 89 | 88 | ||
| 90 | private: | ||
| 91 | KServerSession server; | 89 | KServerSession server; |
| 92 | KClientSession client; | 90 | KClientSession client; |
| 93 | std::atomic<std::underlying_type_t<State>> atomic_state{ | 91 | std::atomic<std::underlying_type_t<State>> atomic_state{ |
diff --git a/src/core/hle/kernel/k_shared_memory.h b/src/core/hle/kernel/k_shared_memory.h index 553a56327..e9815f90b 100644 --- a/src/core/hle/kernel/k_shared_memory.h +++ b/src/core/hle/kernel/k_shared_memory.h | |||
| @@ -68,9 +68,9 @@ public: | |||
| 68 | return device_memory->GetPointer(physical_address + offset); | 68 | return device_memory->GetPointer(physical_address + offset); |
| 69 | } | 69 | } |
| 70 | 70 | ||
| 71 | virtual void Finalize() override; | 71 | void Finalize() override; |
| 72 | 72 | ||
| 73 | virtual bool IsInitialized() const override { | 73 | bool IsInitialized() const override { |
| 74 | return is_initialized; | 74 | return is_initialized; |
| 75 | } | 75 | } |
| 76 | static void PostDestroy([[maybe_unused]] uintptr_t arg) {} | 76 | static void PostDestroy([[maybe_unused]] uintptr_t arg) {} |
diff --git a/src/core/hle/kernel/k_slab_heap.h b/src/core/hle/kernel/k_slab_heap.h index 81d472a3e..0ad74b0a0 100644 --- a/src/core/hle/kernel/k_slab_heap.h +++ b/src/core/hle/kernel/k_slab_heap.h | |||
| @@ -4,34 +4,213 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <atomic> | ||
| 8 | |||
| 9 | #include "common/assert.h" | ||
| 10 | #include "common/common_types.h" | ||
| 11 | |||
| 7 | namespace Kernel { | 12 | namespace Kernel { |
| 8 | 13 | ||
| 9 | class KernelCore; | 14 | class KernelCore; |
| 10 | 15 | ||
| 11 | /// This is a placeholder class to manage slab heaps for kernel objects. For now, we just allocate | 16 | namespace impl { |
| 12 | /// these with new/delete, but this can be re-implemented later to allocate these in emulated | 17 | |
| 13 | /// memory. | 18 | class KSlabHeapImpl final : NonCopyable { |
| 19 | public: | ||
| 20 | struct Node { | ||
| 21 | Node* next{}; | ||
| 22 | }; | ||
| 23 | |||
| 24 | constexpr KSlabHeapImpl() = default; | ||
| 25 | |||
| 26 | void Initialize(std::size_t size) { | ||
| 27 | ASSERT(head == nullptr); | ||
| 28 | obj_size = size; | ||
| 29 | } | ||
| 30 | |||
| 31 | constexpr std::size_t GetObjectSize() const { | ||
| 32 | return obj_size; | ||
| 33 | } | ||
| 34 | |||
| 35 | Node* GetHead() const { | ||
| 36 | return head; | ||
| 37 | } | ||
| 38 | |||
| 39 | void* Allocate() { | ||
| 40 | Node* ret = head.load(); | ||
| 41 | |||
| 42 | do { | ||
| 43 | if (ret == nullptr) { | ||
| 44 | break; | ||
| 45 | } | ||
| 46 | } while (!head.compare_exchange_weak(ret, ret->next)); | ||
| 47 | |||
| 48 | return ret; | ||
| 49 | } | ||
| 50 | |||
| 51 | void Free(void* obj) { | ||
| 52 | Node* node = static_cast<Node*>(obj); | ||
| 53 | |||
| 54 | Node* cur_head = head.load(); | ||
| 55 | do { | ||
| 56 | node->next = cur_head; | ||
| 57 | } while (!head.compare_exchange_weak(cur_head, node)); | ||
| 58 | } | ||
| 59 | |||
| 60 | private: | ||
| 61 | std::atomic<Node*> head{}; | ||
| 62 | std::size_t obj_size{}; | ||
| 63 | }; | ||
| 64 | |||
| 65 | } // namespace impl | ||
| 66 | |||
| 67 | class KSlabHeapBase : NonCopyable { | ||
| 68 | public: | ||
| 69 | constexpr KSlabHeapBase() = default; | ||
| 70 | |||
| 71 | constexpr bool Contains(uintptr_t addr) const { | ||
| 72 | return start <= addr && addr < end; | ||
| 73 | } | ||
| 74 | |||
| 75 | constexpr std::size_t GetSlabHeapSize() const { | ||
| 76 | return (end - start) / GetObjectSize(); | ||
| 77 | } | ||
| 78 | |||
| 79 | constexpr std::size_t GetObjectSize() const { | ||
| 80 | return impl.GetObjectSize(); | ||
| 81 | } | ||
| 82 | |||
| 83 | constexpr uintptr_t GetSlabHeapAddress() const { | ||
| 84 | return start; | ||
| 85 | } | ||
| 86 | |||
| 87 | std::size_t GetObjectIndexImpl(const void* obj) const { | ||
| 88 | return (reinterpret_cast<uintptr_t>(obj) - start) / GetObjectSize(); | ||
| 89 | } | ||
| 90 | |||
| 91 | std::size_t GetPeakIndex() const { | ||
| 92 | return GetObjectIndexImpl(reinterpret_cast<const void*>(peak)); | ||
| 93 | } | ||
| 94 | |||
| 95 | void* AllocateImpl() { | ||
| 96 | return impl.Allocate(); | ||
| 97 | } | ||
| 98 | |||
| 99 | void FreeImpl(void* obj) { | ||
| 100 | // Don't allow freeing an object that wasn't allocated from this heap | ||
| 101 | ASSERT(Contains(reinterpret_cast<uintptr_t>(obj))); | ||
| 102 | |||
| 103 | impl.Free(obj); | ||
| 104 | } | ||
| 105 | |||
| 106 | void InitializeImpl(std::size_t obj_size, void* memory, std::size_t memory_size) { | ||
| 107 | // Ensure we don't initialize a slab using null memory | ||
| 108 | ASSERT(memory != nullptr); | ||
| 109 | |||
| 110 | // Initialize the base allocator | ||
| 111 | impl.Initialize(obj_size); | ||
| 112 | |||
| 113 | // Set our tracking variables | ||
| 114 | const std::size_t num_obj = (memory_size / obj_size); | ||
| 115 | start = reinterpret_cast<uintptr_t>(memory); | ||
| 116 | end = start + num_obj * obj_size; | ||
| 117 | peak = start; | ||
| 118 | |||
| 119 | // Free the objects | ||
| 120 | u8* cur = reinterpret_cast<u8*>(end); | ||
| 121 | |||
| 122 | for (std::size_t i{}; i < num_obj; i++) { | ||
| 123 | cur -= obj_size; | ||
| 124 | impl.Free(cur); | ||
| 125 | } | ||
| 126 | } | ||
| 127 | |||
| 128 | private: | ||
| 129 | using Impl = impl::KSlabHeapImpl; | ||
| 130 | |||
| 131 | Impl impl; | ||
| 132 | uintptr_t peak{}; | ||
| 133 | uintptr_t start{}; | ||
| 134 | uintptr_t end{}; | ||
| 135 | }; | ||
| 14 | 136 | ||
| 15 | template <typename T> | 137 | template <typename T> |
| 16 | class KSlabHeap final : NonCopyable { | 138 | class KSlabHeap final : public KSlabHeapBase { |
| 17 | public: | 139 | public: |
| 18 | KSlabHeap() = default; | 140 | enum class AllocationType { |
| 141 | Host, | ||
| 142 | Guest, | ||
| 143 | }; | ||
| 19 | 144 | ||
| 20 | void Initialize([[maybe_unused]] void* memory, [[maybe_unused]] std::size_t memory_size) { | 145 | explicit constexpr KSlabHeap(AllocationType allocation_type_ = AllocationType::Host) |
| 21 | // Placeholder that should initialize the backing slab heap implementation. | 146 | : KSlabHeapBase(), allocation_type{allocation_type_} {} |
| 147 | |||
| 148 | void Initialize(void* memory, std::size_t memory_size) { | ||
| 149 | if (allocation_type == AllocationType::Guest) { | ||
| 150 | InitializeImpl(sizeof(T), memory, memory_size); | ||
| 151 | } | ||
| 22 | } | 152 | } |
| 23 | 153 | ||
| 24 | T* Allocate() { | 154 | T* Allocate() { |
| 25 | return new T(); | 155 | switch (allocation_type) { |
| 156 | case AllocationType::Host: | ||
| 157 | // Fallback for cases where we do not yet support allocating guest memory from the slab | ||
| 158 | // heap, such as for kernel memory regions. | ||
| 159 | return new T; | ||
| 160 | |||
| 161 | case AllocationType::Guest: | ||
| 162 | T* obj = static_cast<T*>(AllocateImpl()); | ||
| 163 | if (obj != nullptr) { | ||
| 164 | new (obj) T(); | ||
| 165 | } | ||
| 166 | return obj; | ||
| 167 | } | ||
| 168 | |||
| 169 | UNREACHABLE_MSG("Invalid AllocationType {}", allocation_type); | ||
| 170 | return nullptr; | ||
| 26 | } | 171 | } |
| 27 | 172 | ||
| 28 | T* AllocateWithKernel(KernelCore& kernel) { | 173 | T* AllocateWithKernel(KernelCore& kernel) { |
| 29 | return new T(kernel); | 174 | switch (allocation_type) { |
| 175 | case AllocationType::Host: | ||
| 176 | // Fallback for cases where we do not yet support allocating guest memory from the slab | ||
| 177 | // heap, such as for kernel memory regions. | ||
| 178 | return new T(kernel); | ||
| 179 | |||
| 180 | case AllocationType::Guest: | ||
| 181 | T* obj = static_cast<T*>(AllocateImpl()); | ||
| 182 | if (obj != nullptr) { | ||
| 183 | new (obj) T(kernel); | ||
| 184 | } | ||
| 185 | return obj; | ||
| 186 | } | ||
| 187 | |||
| 188 | UNREACHABLE_MSG("Invalid AllocationType {}", allocation_type); | ||
| 189 | return nullptr; | ||
| 30 | } | 190 | } |
| 31 | 191 | ||
| 32 | void Free(T* obj) { | 192 | void Free(T* obj) { |
| 33 | delete obj; | 193 | switch (allocation_type) { |
| 194 | case AllocationType::Host: | ||
| 195 | // Fallback for cases where we do not yet support allocating guest memory from the slab | ||
| 196 | // heap, such as for kernel memory regions. | ||
| 197 | delete obj; | ||
| 198 | return; | ||
| 199 | |||
| 200 | case AllocationType::Guest: | ||
| 201 | FreeImpl(obj); | ||
| 202 | return; | ||
| 203 | } | ||
| 204 | |||
| 205 | UNREACHABLE_MSG("Invalid AllocationType {}", allocation_type); | ||
| 34 | } | 206 | } |
| 207 | |||
| 208 | constexpr std::size_t GetObjectIndex(const T* obj) const { | ||
| 209 | return GetObjectIndexImpl(obj); | ||
| 210 | } | ||
| 211 | |||
| 212 | private: | ||
| 213 | const AllocationType allocation_type; | ||
| 35 | }; | 214 | }; |
| 36 | 215 | ||
| 37 | } // namespace Kernel | 216 | } // namespace Kernel |
diff --git a/src/core/hle/kernel/k_synchronization_object.h b/src/core/hle/kernel/k_synchronization_object.h index a41dd1220..3d4ce1fbc 100644 --- a/src/core/hle/kernel/k_synchronization_object.h +++ b/src/core/hle/kernel/k_synchronization_object.h | |||
| @@ -29,7 +29,7 @@ public: | |||
| 29 | KSynchronizationObject** objects, const s32 num_objects, | 29 | KSynchronizationObject** objects, const s32 num_objects, |
| 30 | s64 timeout); | 30 | s64 timeout); |
| 31 | 31 | ||
| 32 | virtual void Finalize() override; | 32 | void Finalize() override; |
| 33 | 33 | ||
| 34 | [[nodiscard]] virtual bool IsSignaled() const = 0; | 34 | [[nodiscard]] virtual bool IsSignaled() const = 0; |
| 35 | 35 | ||
| @@ -37,7 +37,7 @@ public: | |||
| 37 | 37 | ||
| 38 | protected: | 38 | protected: |
| 39 | explicit KSynchronizationObject(KernelCore& kernel); | 39 | explicit KSynchronizationObject(KernelCore& kernel); |
| 40 | virtual ~KSynchronizationObject(); | 40 | ~KSynchronizationObject() override; |
| 41 | 41 | ||
| 42 | virtual void OnFinalizeSynchronizationObject() {} | 42 | virtual void OnFinalizeSynchronizationObject() {} |
| 43 | 43 | ||
diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp index e3f08f256..3cf43d290 100644 --- a/src/core/hle/kernel/k_thread.cpp +++ b/src/core/hle/kernel/k_thread.cpp | |||
| @@ -168,13 +168,13 @@ ResultCode KThread::Initialize(KThreadFunction func, uintptr_t arg, VAddr user_s | |||
| 168 | std::memset(static_cast<void*>(std::addressof(GetStackParameters())), 0, | 168 | std::memset(static_cast<void*>(std::addressof(GetStackParameters())), 0, |
| 169 | sizeof(StackParameters)); | 169 | sizeof(StackParameters)); |
| 170 | 170 | ||
| 171 | // Setup the TLS, if needed. | ||
| 172 | if (type == ThreadType::User) { | ||
| 173 | tls_address = owner->CreateTLSRegion(); | ||
| 174 | } | ||
| 175 | |||
| 176 | // Set parent, if relevant. | 171 | // Set parent, if relevant. |
| 177 | if (owner != nullptr) { | 172 | if (owner != nullptr) { |
| 173 | // Setup the TLS, if needed. | ||
| 174 | if (type == ThreadType::User) { | ||
| 175 | tls_address = owner->CreateTLSRegion(); | ||
| 176 | } | ||
| 177 | |||
| 178 | parent = owner; | 178 | parent = owner; |
| 179 | parent->Open(); | 179 | parent->Open(); |
| 180 | parent->IncrementThreadCount(); | 180 | parent->IncrementThreadCount(); |
diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h index 4abfc2b49..01eebb165 100644 --- a/src/core/hle/kernel/k_thread.h +++ b/src/core/hle/kernel/k_thread.h | |||
| @@ -358,21 +358,21 @@ public: | |||
| 358 | return termination_requested || GetRawState() == ThreadState::Terminated; | 358 | return termination_requested || GetRawState() == ThreadState::Terminated; |
| 359 | } | 359 | } |
| 360 | 360 | ||
| 361 | [[nodiscard]] virtual u64 GetId() const override final { | 361 | [[nodiscard]] u64 GetId() const override { |
| 362 | return this->GetThreadID(); | 362 | return this->GetThreadID(); |
| 363 | } | 363 | } |
| 364 | 364 | ||
| 365 | [[nodiscard]] virtual bool IsInitialized() const override { | 365 | [[nodiscard]] bool IsInitialized() const override { |
| 366 | return initialized; | 366 | return initialized; |
| 367 | } | 367 | } |
| 368 | 368 | ||
| 369 | [[nodiscard]] virtual uintptr_t GetPostDestroyArgument() const override { | 369 | [[nodiscard]] uintptr_t GetPostDestroyArgument() const override { |
| 370 | return reinterpret_cast<uintptr_t>(parent) | (resource_limit_release_hint ? 1 : 0); | 370 | return reinterpret_cast<uintptr_t>(parent) | (resource_limit_release_hint ? 1 : 0); |
| 371 | } | 371 | } |
| 372 | 372 | ||
| 373 | virtual void Finalize() override; | 373 | void Finalize() override; |
| 374 | 374 | ||
| 375 | [[nodiscard]] virtual bool IsSignaled() const override; | 375 | [[nodiscard]] bool IsSignaled() const override; |
| 376 | 376 | ||
| 377 | static void PostDestroy(uintptr_t arg); | 377 | static void PostDestroy(uintptr_t arg); |
| 378 | 378 | ||
diff --git a/src/core/hle/kernel/k_transfer_memory.h b/src/core/hle/kernel/k_transfer_memory.h index c2d0f1eaf..31029a5c2 100644 --- a/src/core/hle/kernel/k_transfer_memory.h +++ b/src/core/hle/kernel/k_transfer_memory.h | |||
| @@ -27,23 +27,23 @@ class KTransferMemory final | |||
| 27 | 27 | ||
| 28 | public: | 28 | public: |
| 29 | explicit KTransferMemory(KernelCore& kernel_); | 29 | explicit KTransferMemory(KernelCore& kernel_); |
| 30 | virtual ~KTransferMemory() override; | 30 | ~KTransferMemory() override; |
| 31 | 31 | ||
| 32 | ResultCode Initialize(VAddr address_, std::size_t size_, Svc::MemoryPermission owner_perm_); | 32 | ResultCode Initialize(VAddr address_, std::size_t size_, Svc::MemoryPermission owner_perm_); |
| 33 | 33 | ||
| 34 | virtual void Finalize() override; | 34 | void Finalize() override; |
| 35 | 35 | ||
| 36 | virtual bool IsInitialized() const override { | 36 | bool IsInitialized() const override { |
| 37 | return is_initialized; | 37 | return is_initialized; |
| 38 | } | 38 | } |
| 39 | 39 | ||
| 40 | virtual uintptr_t GetPostDestroyArgument() const override { | 40 | uintptr_t GetPostDestroyArgument() const override { |
| 41 | return reinterpret_cast<uintptr_t>(owner); | 41 | return reinterpret_cast<uintptr_t>(owner); |
| 42 | } | 42 | } |
| 43 | 43 | ||
| 44 | static void PostDestroy(uintptr_t arg); | 44 | static void PostDestroy(uintptr_t arg); |
| 45 | 45 | ||
| 46 | KProcess* GetOwner() const { | 46 | KProcess* GetOwner() const override { |
| 47 | return owner; | 47 | return owner; |
| 48 | } | 48 | } |
| 49 | 49 | ||
diff --git a/src/core/hle/kernel/k_writable_event.h b/src/core/hle/kernel/k_writable_event.h index 607b0eadb..858d982c4 100644 --- a/src/core/hle/kernel/k_writable_event.h +++ b/src/core/hle/kernel/k_writable_event.h | |||
| @@ -21,7 +21,7 @@ public: | |||
| 21 | explicit KWritableEvent(KernelCore& kernel_); | 21 | explicit KWritableEvent(KernelCore& kernel_); |
| 22 | ~KWritableEvent() override; | 22 | ~KWritableEvent() override; |
| 23 | 23 | ||
| 24 | virtual void Destroy() override; | 24 | void Destroy() override; |
| 25 | 25 | ||
| 26 | static void PostDestroy([[maybe_unused]] uintptr_t arg) {} | 26 | static void PostDestroy([[maybe_unused]] uintptr_t arg) {} |
| 27 | 27 | ||
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 8b55df82e..0ffb78d51 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp | |||
| @@ -258,7 +258,7 @@ struct KernelCore::Impl { | |||
| 258 | KAutoObject::Create(thread.get()); | 258 | KAutoObject::Create(thread.get()); |
| 259 | ASSERT(KThread::InitializeDummyThread(thread.get()).IsSuccess()); | 259 | ASSERT(KThread::InitializeDummyThread(thread.get()).IsSuccess()); |
| 260 | thread->SetName(fmt::format("DummyThread:{}", GetHostThreadId())); | 260 | thread->SetName(fmt::format("DummyThread:{}", GetHostThreadId())); |
| 261 | return std::move(thread); | 261 | return thread; |
| 262 | }; | 262 | }; |
| 263 | 263 | ||
| 264 | thread_local auto thread = make_thread(); | 264 | thread_local auto thread = make_thread(); |
| @@ -620,7 +620,8 @@ struct KernelCore::Impl { | |||
| 620 | 620 | ||
| 621 | void InitializePageSlab() { | 621 | void InitializePageSlab() { |
| 622 | // Allocate slab heaps | 622 | // Allocate slab heaps |
| 623 | user_slab_heap_pages = std::make_unique<KSlabHeap<Page>>(); | 623 | user_slab_heap_pages = |
| 624 | std::make_unique<KSlabHeap<Page>>(KSlabHeap<Page>::AllocationType::Guest); | ||
| 624 | 625 | ||
| 625 | // TODO(ameerj): This should be derived, not hardcoded within the kernel | 626 | // TODO(ameerj): This should be derived, not hardcoded within the kernel |
| 626 | constexpr u64 user_slab_heap_size{0x3de000}; | 627 | constexpr u64 user_slab_heap_size{0x3de000}; |
diff --git a/src/core/hle/service/am/applets/software_keyboard.cpp b/src/core/hle/service/am/applets/software_keyboard.cpp index b05a5da04..b1a81810b 100644 --- a/src/core/hle/service/am/applets/software_keyboard.cpp +++ b/src/core/hle/service/am/applets/software_keyboard.cpp | |||
| @@ -273,8 +273,13 @@ void SoftwareKeyboard::ProcessTextCheck() { | |||
| 273 | 273 | ||
| 274 | std::memcpy(&swkbd_text_check, text_check_data.data(), sizeof(SwkbdTextCheck)); | 274 | std::memcpy(&swkbd_text_check, text_check_data.data(), sizeof(SwkbdTextCheck)); |
| 275 | 275 | ||
| 276 | std::u16string text_check_message = Common::UTF16StringFromFixedZeroTerminatedBuffer( | 276 | std::u16string text_check_message = |
| 277 | swkbd_text_check.text_check_message.data(), swkbd_text_check.text_check_message.size()); | 277 | swkbd_text_check.text_check_result == SwkbdTextCheckResult::Failure || |
| 278 | swkbd_text_check.text_check_result == SwkbdTextCheckResult::Confirm | ||
| 279 | ? Common::UTF16StringFromFixedZeroTerminatedBuffer( | ||
| 280 | swkbd_text_check.text_check_message.data(), | ||
| 281 | swkbd_text_check.text_check_message.size()) | ||
| 282 | : u""; | ||
| 278 | 283 | ||
| 279 | LOG_INFO(Service_AM, "\nTextCheckResult: {}\nTextCheckMessage: {}", | 284 | LOG_INFO(Service_AM, "\nTextCheckResult: {}\nTextCheckMessage: {}", |
| 280 | GetTextCheckResultName(swkbd_text_check.text_check_result), | 285 | GetTextCheckResultName(swkbd_text_check.text_check_result), |
| @@ -285,10 +290,10 @@ void SoftwareKeyboard::ProcessTextCheck() { | |||
| 285 | SubmitNormalOutputAndExit(SwkbdResult::Ok, current_text); | 290 | SubmitNormalOutputAndExit(SwkbdResult::Ok, current_text); |
| 286 | break; | 291 | break; |
| 287 | case SwkbdTextCheckResult::Failure: | 292 | case SwkbdTextCheckResult::Failure: |
| 288 | ShowTextCheckDialog(SwkbdTextCheckResult::Failure, text_check_message); | 293 | ShowTextCheckDialog(SwkbdTextCheckResult::Failure, std::move(text_check_message)); |
| 289 | break; | 294 | break; |
| 290 | case SwkbdTextCheckResult::Confirm: | 295 | case SwkbdTextCheckResult::Confirm: |
| 291 | ShowTextCheckDialog(SwkbdTextCheckResult::Confirm, text_check_message); | 296 | ShowTextCheckDialog(SwkbdTextCheckResult::Confirm, std::move(text_check_message)); |
| 292 | break; | 297 | break; |
| 293 | case SwkbdTextCheckResult::Silent: | 298 | case SwkbdTextCheckResult::Silent: |
| 294 | default: | 299 | default: |
| @@ -482,7 +487,7 @@ void SoftwareKeyboard::InitializeFrontendKeyboard() { | |||
| 482 | max_text_length <= 32 ? SwkbdTextDrawType::Line : SwkbdTextDrawType::Box; | 487 | max_text_length <= 32 ? SwkbdTextDrawType::Line : SwkbdTextDrawType::Box; |
| 483 | 488 | ||
| 484 | Core::Frontend::KeyboardInitializeParameters initialize_parameters{ | 489 | Core::Frontend::KeyboardInitializeParameters initialize_parameters{ |
| 485 | .ok_text{ok_text}, | 490 | .ok_text{std::move(ok_text)}, |
| 486 | .header_text{}, | 491 | .header_text{}, |
| 487 | .sub_text{}, | 492 | .sub_text{}, |
| 488 | .guide_text{}, | 493 | .guide_text{}, |
| @@ -558,10 +563,10 @@ void SoftwareKeyboard::InitializeFrontendKeyboard() { | |||
| 558 | : false; | 563 | : false; |
| 559 | 564 | ||
| 560 | Core::Frontend::KeyboardInitializeParameters initialize_parameters{ | 565 | Core::Frontend::KeyboardInitializeParameters initialize_parameters{ |
| 561 | .ok_text{ok_text}, | 566 | .ok_text{std::move(ok_text)}, |
| 562 | .header_text{header_text}, | 567 | .header_text{std::move(header_text)}, |
| 563 | .sub_text{sub_text}, | 568 | .sub_text{std::move(sub_text)}, |
| 564 | .guide_text{guide_text}, | 569 | .guide_text{std::move(guide_text)}, |
| 565 | .initial_text{initial_text}, | 570 | .initial_text{initial_text}, |
| 566 | .max_text_length{max_text_length}, | 571 | .max_text_length{max_text_length}, |
| 567 | .min_text_length{min_text_length}, | 572 | .min_text_length{min_text_length}, |
| @@ -590,7 +595,7 @@ void SoftwareKeyboard::ShowNormalKeyboard() { | |||
| 590 | 595 | ||
| 591 | void SoftwareKeyboard::ShowTextCheckDialog(SwkbdTextCheckResult text_check_result, | 596 | void SoftwareKeyboard::ShowTextCheckDialog(SwkbdTextCheckResult text_check_result, |
| 592 | std::u16string text_check_message) { | 597 | std::u16string text_check_message) { |
| 593 | frontend.ShowTextCheckDialog(text_check_result, text_check_message); | 598 | frontend.ShowTextCheckDialog(text_check_result, std::move(text_check_message)); |
| 594 | } | 599 | } |
| 595 | 600 | ||
| 596 | void SoftwareKeyboard::ShowInlineKeyboard() { | 601 | void SoftwareKeyboard::ShowInlineKeyboard() { |
diff --git a/src/core/hle/service/hid/controllers/gesture.cpp b/src/core/hle/service/hid/controllers/gesture.cpp index d311f754b..764abb5b6 100644 --- a/src/core/hle/service/hid/controllers/gesture.cpp +++ b/src/core/hle/service/hid/controllers/gesture.cpp | |||
| @@ -91,8 +91,7 @@ bool Controller_Gesture::ShouldUpdateGesture(const GestureProperties& gesture, | |||
| 91 | 91 | ||
| 92 | // Update if coordinates change | 92 | // Update if coordinates change |
| 93 | for (size_t id = 0; id < MAX_POINTS; id++) { | 93 | for (size_t id = 0; id < MAX_POINTS; id++) { |
| 94 | if (gesture.points[id].x != last_gesture.points[id].x || | 94 | if (gesture.points[id] != last_gesture.points[id]) { |
| 95 | gesture.points[id].y != last_gesture.points[id].y) { | ||
| 96 | return true; | 95 | return true; |
| 97 | } | 96 | } |
| 98 | } | 97 | } |
| @@ -124,8 +123,7 @@ void Controller_Gesture::UpdateGestureSharedMemory(u8* data, std::size_t size, | |||
| 124 | cur_entry.sampling_number2 = cur_entry.sampling_number; | 123 | cur_entry.sampling_number2 = cur_entry.sampling_number; |
| 125 | 124 | ||
| 126 | // Reset values to default | 125 | // Reset values to default |
| 127 | cur_entry.delta_x = 0; | 126 | cur_entry.delta = {}; |
| 128 | cur_entry.delta_y = 0; | ||
| 129 | cur_entry.vel_x = 0; | 127 | cur_entry.vel_x = 0; |
| 130 | cur_entry.vel_y = 0; | 128 | cur_entry.vel_y = 0; |
| 131 | cur_entry.direction = Direction::None; | 129 | cur_entry.direction = Direction::None; |
| @@ -146,13 +144,9 @@ void Controller_Gesture::UpdateGestureSharedMemory(u8* data, std::size_t size, | |||
| 146 | cur_entry.detection_count = gesture.detection_count; | 144 | cur_entry.detection_count = gesture.detection_count; |
| 147 | cur_entry.type = type; | 145 | cur_entry.type = type; |
| 148 | cur_entry.attributes = attributes; | 146 | cur_entry.attributes = attributes; |
| 149 | cur_entry.x = gesture.mid_point.x; | 147 | cur_entry.pos = gesture.mid_point; |
| 150 | cur_entry.y = gesture.mid_point.y; | ||
| 151 | cur_entry.point_count = static_cast<s32>(gesture.active_points); | 148 | cur_entry.point_count = static_cast<s32>(gesture.active_points); |
| 152 | for (size_t id = 0; id < MAX_POINTS; id++) { | 149 | cur_entry.points = gesture.points; |
| 153 | cur_entry.points[id].x = gesture.points[id].x; | ||
| 154 | cur_entry.points[id].y = gesture.points[id].y; | ||
| 155 | } | ||
| 156 | last_gesture = gesture; | 150 | last_gesture = gesture; |
| 157 | 151 | ||
| 158 | std::memcpy(data + SHARED_MEMORY_OFFSET, &shared_memory, sizeof(SharedMemory)); | 152 | std::memcpy(data + SHARED_MEMORY_OFFSET, &shared_memory, sizeof(SharedMemory)); |
| @@ -160,8 +154,8 @@ void Controller_Gesture::UpdateGestureSharedMemory(u8* data, std::size_t size, | |||
| 160 | 154 | ||
| 161 | void Controller_Gesture::NewGesture(GestureProperties& gesture, TouchType& type, | 155 | void Controller_Gesture::NewGesture(GestureProperties& gesture, TouchType& type, |
| 162 | Attribute& attributes) { | 156 | Attribute& attributes) { |
| 163 | const auto& last_entry = | 157 | const auto& last_entry = GetLastGestureEntry(); |
| 164 | shared_memory.gesture_states[(shared_memory.header.last_entry_index + 16) % 17]; | 158 | |
| 165 | gesture.detection_count++; | 159 | gesture.detection_count++; |
| 166 | type = TouchType::Touch; | 160 | type = TouchType::Touch; |
| 167 | 161 | ||
| @@ -174,13 +168,11 @@ void Controller_Gesture::NewGesture(GestureProperties& gesture, TouchType& type, | |||
| 174 | 168 | ||
| 175 | void Controller_Gesture::UpdateExistingGesture(GestureProperties& gesture, TouchType& type, | 169 | void Controller_Gesture::UpdateExistingGesture(GestureProperties& gesture, TouchType& type, |
| 176 | f32 time_difference) { | 170 | f32 time_difference) { |
| 177 | const auto& last_entry = | 171 | const auto& last_entry = GetLastGestureEntry(); |
| 178 | shared_memory.gesture_states[(shared_memory.header.last_entry_index + 16) % 17]; | ||
| 179 | 172 | ||
| 180 | // Promote to pan type if touch moved | 173 | // Promote to pan type if touch moved |
| 181 | for (size_t id = 0; id < MAX_POINTS; id++) { | 174 | for (size_t id = 0; id < MAX_POINTS; id++) { |
| 182 | if (gesture.points[id].x != last_gesture.points[id].x || | 175 | if (gesture.points[id] != last_gesture.points[id]) { |
| 183 | gesture.points[id].y != last_gesture.points[id].y) { | ||
| 184 | type = TouchType::Pan; | 176 | type = TouchType::Pan; |
| 185 | break; | 177 | break; |
| 186 | } | 178 | } |
| @@ -192,10 +184,7 @@ void Controller_Gesture::UpdateExistingGesture(GestureProperties& gesture, Touch | |||
| 192 | enable_press_and_tap = false; | 184 | enable_press_and_tap = false; |
| 193 | gesture.active_points = 0; | 185 | gesture.active_points = 0; |
| 194 | gesture.mid_point = {}; | 186 | gesture.mid_point = {}; |
| 195 | for (size_t id = 0; id < MAX_POINTS; id++) { | 187 | gesture.points.fill({}); |
| 196 | gesture.points[id].x = 0; | ||
| 197 | gesture.points[id].y = 0; | ||
| 198 | } | ||
| 199 | return; | 188 | return; |
| 200 | } | 189 | } |
| 201 | 190 | ||
| @@ -214,8 +203,8 @@ void Controller_Gesture::UpdateExistingGesture(GestureProperties& gesture, Touch | |||
| 214 | void Controller_Gesture::EndGesture(GestureProperties& gesture, | 203 | void Controller_Gesture::EndGesture(GestureProperties& gesture, |
| 215 | GestureProperties& last_gesture_props, TouchType& type, | 204 | GestureProperties& last_gesture_props, TouchType& type, |
| 216 | Attribute& attributes, f32 time_difference) { | 205 | Attribute& attributes, f32 time_difference) { |
| 217 | const auto& last_entry = | 206 | const auto& last_entry = GetLastGestureEntry(); |
| 218 | shared_memory.gesture_states[(shared_memory.header.last_entry_index + 16) % 17]; | 207 | |
| 219 | if (last_gesture_props.active_points != 0) { | 208 | if (last_gesture_props.active_points != 0) { |
| 220 | switch (last_entry.type) { | 209 | switch (last_entry.type) { |
| 221 | case TouchType::Touch: | 210 | case TouchType::Touch: |
| @@ -265,13 +254,11 @@ void Controller_Gesture::UpdatePanEvent(GestureProperties& gesture, | |||
| 265 | GestureProperties& last_gesture_props, TouchType& type, | 254 | GestureProperties& last_gesture_props, TouchType& type, |
| 266 | f32 time_difference) { | 255 | f32 time_difference) { |
| 267 | auto& cur_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index]; | 256 | auto& cur_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index]; |
| 268 | const auto& last_entry = | 257 | const auto& last_entry = GetLastGestureEntry(); |
| 269 | shared_memory.gesture_states[(shared_memory.header.last_entry_index + 16) % 17]; | ||
| 270 | cur_entry.delta_x = gesture.mid_point.x - last_entry.x; | ||
| 271 | cur_entry.delta_y = gesture.mid_point.y - last_entry.y; | ||
| 272 | 258 | ||
| 273 | cur_entry.vel_x = static_cast<f32>(cur_entry.delta_x) / time_difference; | 259 | cur_entry.delta = gesture.mid_point - last_entry.pos; |
| 274 | cur_entry.vel_y = static_cast<f32>(cur_entry.delta_y) / time_difference; | 260 | cur_entry.vel_x = static_cast<f32>(cur_entry.delta.x) / time_difference; |
| 261 | cur_entry.vel_y = static_cast<f32>(cur_entry.delta.y) / time_difference; | ||
| 275 | last_pan_time_difference = time_difference; | 262 | last_pan_time_difference = time_difference; |
| 276 | 263 | ||
| 277 | // Promote to pinch type | 264 | // Promote to pinch type |
| @@ -295,12 +282,11 @@ void Controller_Gesture::EndPanEvent(GestureProperties& gesture, | |||
| 295 | GestureProperties& last_gesture_props, TouchType& type, | 282 | GestureProperties& last_gesture_props, TouchType& type, |
| 296 | f32 time_difference) { | 283 | f32 time_difference) { |
| 297 | auto& cur_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index]; | 284 | auto& cur_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index]; |
| 298 | const auto& last_entry = | 285 | const auto& last_entry = GetLastGestureEntry(); |
| 299 | shared_memory.gesture_states[(shared_memory.header.last_entry_index + 16) % 17]; | ||
| 300 | cur_entry.vel_x = | 286 | cur_entry.vel_x = |
| 301 | static_cast<f32>(last_entry.delta_x) / (last_pan_time_difference + time_difference); | 287 | static_cast<f32>(last_entry.delta.x) / (last_pan_time_difference + time_difference); |
| 302 | cur_entry.vel_y = | 288 | cur_entry.vel_y = |
| 303 | static_cast<f32>(last_entry.delta_y) / (last_pan_time_difference + time_difference); | 289 | static_cast<f32>(last_entry.delta.y) / (last_pan_time_difference + time_difference); |
| 304 | const f32 curr_vel = | 290 | const f32 curr_vel = |
| 305 | std::sqrt((cur_entry.vel_x * cur_entry.vel_x) + (cur_entry.vel_y * cur_entry.vel_y)); | 291 | std::sqrt((cur_entry.vel_x * cur_entry.vel_x) + (cur_entry.vel_y * cur_entry.vel_y)); |
| 306 | 292 | ||
| @@ -320,22 +306,22 @@ void Controller_Gesture::EndPanEvent(GestureProperties& gesture, | |||
| 320 | void Controller_Gesture::SetSwipeEvent(GestureProperties& gesture, | 306 | void Controller_Gesture::SetSwipeEvent(GestureProperties& gesture, |
| 321 | GestureProperties& last_gesture_props, TouchType& type) { | 307 | GestureProperties& last_gesture_props, TouchType& type) { |
| 322 | auto& cur_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index]; | 308 | auto& cur_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index]; |
| 323 | const auto& last_entry = | 309 | const auto& last_entry = GetLastGestureEntry(); |
| 324 | shared_memory.gesture_states[(shared_memory.header.last_entry_index + 16) % 17]; | 310 | |
| 325 | type = TouchType::Swipe; | 311 | type = TouchType::Swipe; |
| 326 | gesture = last_gesture_props; | 312 | gesture = last_gesture_props; |
| 327 | force_update = true; | 313 | force_update = true; |
| 328 | cur_entry.delta_x = last_entry.delta_x; | 314 | cur_entry.delta = last_entry.delta; |
| 329 | cur_entry.delta_y = last_entry.delta_y; | 315 | |
| 330 | if (std::abs(cur_entry.delta_x) > std::abs(cur_entry.delta_y)) { | 316 | if (std::abs(cur_entry.delta.x) > std::abs(cur_entry.delta.y)) { |
| 331 | if (cur_entry.delta_x > 0) { | 317 | if (cur_entry.delta.x > 0) { |
| 332 | cur_entry.direction = Direction::Right; | 318 | cur_entry.direction = Direction::Right; |
| 333 | return; | 319 | return; |
| 334 | } | 320 | } |
| 335 | cur_entry.direction = Direction::Left; | 321 | cur_entry.direction = Direction::Left; |
| 336 | return; | 322 | return; |
| 337 | } | 323 | } |
| 338 | if (cur_entry.delta_y > 0) { | 324 | if (cur_entry.delta.y > 0) { |
| 339 | cur_entry.direction = Direction::Down; | 325 | cur_entry.direction = Direction::Down; |
| 340 | return; | 326 | return; |
| 341 | } | 327 | } |
| @@ -364,6 +350,14 @@ std::optional<std::size_t> Controller_Gesture::GetUnusedFingerID() const { | |||
| 364 | return std::nullopt; | 350 | return std::nullopt; |
| 365 | } | 351 | } |
| 366 | 352 | ||
| 353 | Controller_Gesture::GestureState& Controller_Gesture::GetLastGestureEntry() { | ||
| 354 | return shared_memory.gesture_states[(shared_memory.header.last_entry_index + 16) % 17]; | ||
| 355 | } | ||
| 356 | |||
| 357 | const Controller_Gesture::GestureState& Controller_Gesture::GetLastGestureEntry() const { | ||
| 358 | return shared_memory.gesture_states[(shared_memory.header.last_entry_index + 16) % 17]; | ||
| 359 | } | ||
| 360 | |||
| 367 | std::size_t Controller_Gesture::UpdateTouchInputEvent( | 361 | std::size_t Controller_Gesture::UpdateTouchInputEvent( |
| 368 | const std::tuple<float, float, bool>& touch_input, std::size_t finger_id) { | 362 | const std::tuple<float, float, bool>& touch_input, std::size_t finger_id) { |
| 369 | const auto& [x, y, pressed] = touch_input; | 363 | const auto& [x, y, pressed] = touch_input; |
| @@ -381,8 +375,7 @@ std::size_t Controller_Gesture::UpdateTouchInputEvent( | |||
| 381 | finger_id = first_free_id.value(); | 375 | finger_id = first_free_id.value(); |
| 382 | fingers[finger_id].pressed = true; | 376 | fingers[finger_id].pressed = true; |
| 383 | } | 377 | } |
| 384 | fingers[finger_id].x = x; | 378 | fingers[finger_id].pos = {x, y}; |
| 385 | fingers[finger_id].y = y; | ||
| 386 | return finger_id; | 379 | return finger_id; |
| 387 | } | 380 | } |
| 388 | 381 | ||
| @@ -402,17 +395,18 @@ Controller_Gesture::GestureProperties Controller_Gesture::GetGestureProperties() | |||
| 402 | static_cast<std::size_t>(std::distance(active_fingers.begin(), end_iter)); | 395 | static_cast<std::size_t>(std::distance(active_fingers.begin(), end_iter)); |
| 403 | 396 | ||
| 404 | for (size_t id = 0; id < gesture.active_points; ++id) { | 397 | for (size_t id = 0; id < gesture.active_points; ++id) { |
| 405 | gesture.points[id].x = | 398 | const auto& [active_x, active_y] = active_fingers[id].pos; |
| 406 | static_cast<s32>(active_fingers[id].x * Layout::ScreenUndocked::Width); | 399 | gesture.points[id] = { |
| 407 | gesture.points[id].y = | 400 | .x = static_cast<s32>(active_x * Layout::ScreenUndocked::Width), |
| 408 | static_cast<s32>(active_fingers[id].y * Layout::ScreenUndocked::Height); | 401 | .y = static_cast<s32>(active_y * Layout::ScreenUndocked::Height), |
| 402 | }; | ||
| 409 | 403 | ||
| 410 | // Hack: There is no touch in docked but games still allow it | 404 | // Hack: There is no touch in docked but games still allow it |
| 411 | if (Settings::values.use_docked_mode.GetValue()) { | 405 | if (Settings::values.use_docked_mode.GetValue()) { |
| 412 | gesture.points[id].x = | 406 | gesture.points[id] = { |
| 413 | static_cast<s32>(active_fingers[id].x * Layout::ScreenDocked::Width); | 407 | .x = static_cast<s32>(active_x * Layout::ScreenDocked::Width), |
| 414 | gesture.points[id].y = | 408 | .y = static_cast<s32>(active_y * Layout::ScreenDocked::Height), |
| 415 | static_cast<s32>(active_fingers[id].y * Layout::ScreenDocked::Height); | 409 | }; |
| 416 | } | 410 | } |
| 417 | 411 | ||
| 418 | gesture.mid_point.x += static_cast<s32>(gesture.points[id].x / gesture.active_points); | 412 | gesture.mid_point.x += static_cast<s32>(gesture.points[id].x / gesture.active_points); |
diff --git a/src/core/hle/service/hid/controllers/gesture.h b/src/core/hle/service/hid/controllers/gesture.h index f46e29411..7e7ae6625 100644 --- a/src/core/hle/service/hid/controllers/gesture.h +++ b/src/core/hle/service/hid/controllers/gesture.h | |||
| @@ -7,6 +7,7 @@ | |||
| 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/point.h" | ||
| 10 | #include "core/frontend/input.h" | 11 | #include "core/frontend/input.h" |
| 11 | #include "core/hle/service/hid/controllers/controller_base.h" | 12 | #include "core/hle/service/hid/controllers/controller_base.h" |
| 12 | 13 | ||
| @@ -63,29 +64,21 @@ private: | |||
| 63 | }; | 64 | }; |
| 64 | static_assert(sizeof(Attribute) == 4, "Attribute is an invalid size"); | 65 | static_assert(sizeof(Attribute) == 4, "Attribute is an invalid size"); |
| 65 | 66 | ||
| 66 | struct Points { | ||
| 67 | s32_le x; | ||
| 68 | s32_le y; | ||
| 69 | }; | ||
| 70 | static_assert(sizeof(Points) == 8, "Points is an invalid size"); | ||
| 71 | |||
| 72 | struct GestureState { | 67 | struct GestureState { |
| 73 | s64_le sampling_number; | 68 | s64_le sampling_number; |
| 74 | s64_le sampling_number2; | 69 | s64_le sampling_number2; |
| 75 | s64_le detection_count; | 70 | s64_le detection_count; |
| 76 | TouchType type; | 71 | TouchType type; |
| 77 | Direction direction; | 72 | Direction direction; |
| 78 | s32_le x; | 73 | Common::Point<s32_le> pos; |
| 79 | s32_le y; | 74 | Common::Point<s32_le> delta; |
| 80 | s32_le delta_x; | ||
| 81 | s32_le delta_y; | ||
| 82 | f32 vel_x; | 75 | f32 vel_x; |
| 83 | f32 vel_y; | 76 | f32 vel_y; |
| 84 | Attribute attributes; | 77 | Attribute attributes; |
| 85 | f32 scale; | 78 | f32 scale; |
| 86 | f32 rotation_angle; | 79 | f32 rotation_angle; |
| 87 | s32_le point_count; | 80 | s32_le point_count; |
| 88 | std::array<Points, 4> points; | 81 | std::array<Common::Point<s32_le>, 4> points; |
| 89 | }; | 82 | }; |
| 90 | static_assert(sizeof(GestureState) == 0x68, "GestureState is an invalid size"); | 83 | static_assert(sizeof(GestureState) == 0x68, "GestureState is an invalid size"); |
| 91 | 84 | ||
| @@ -96,15 +89,14 @@ private: | |||
| 96 | static_assert(sizeof(SharedMemory) == 0x708, "SharedMemory is an invalid size"); | 89 | static_assert(sizeof(SharedMemory) == 0x708, "SharedMemory is an invalid size"); |
| 97 | 90 | ||
| 98 | struct Finger { | 91 | struct Finger { |
| 99 | f32 x{}; | 92 | Common::Point<f32> pos{}; |
| 100 | f32 y{}; | ||
| 101 | bool pressed{}; | 93 | bool pressed{}; |
| 102 | }; | 94 | }; |
| 103 | 95 | ||
| 104 | struct GestureProperties { | 96 | struct GestureProperties { |
| 105 | std::array<Points, MAX_POINTS> points{}; | 97 | std::array<Common::Point<s32_le>, MAX_POINTS> points{}; |
| 106 | std::size_t active_points{}; | 98 | std::size_t active_points{}; |
| 107 | Points mid_point{}; | 99 | Common::Point<s32_le> mid_point{}; |
| 108 | s64_le detection_count{}; | 100 | s64_le detection_count{}; |
| 109 | u64_le delta_time{}; | 101 | u64_le delta_time{}; |
| 110 | f32 average_distance{}; | 102 | f32 average_distance{}; |
| @@ -148,7 +140,11 @@ private: | |||
| 148 | TouchType& type); | 140 | TouchType& type); |
| 149 | 141 | ||
| 150 | // Returns an unused finger id, if there is no fingers available std::nullopt is returned. | 142 | // Returns an unused finger id, if there is no fingers available std::nullopt is returned. |
| 151 | std::optional<size_t> GetUnusedFingerID() const; | 143 | [[nodiscard]] std::optional<size_t> GetUnusedFingerID() const; |
| 144 | |||
| 145 | // Retrieves the last gesture entry, as indicated by shared memory indices. | ||
| 146 | [[nodiscard]] GestureState& GetLastGestureEntry(); | ||
| 147 | [[nodiscard]] const GestureState& GetLastGestureEntry() const; | ||
| 152 | 148 | ||
| 153 | /** | 149 | /** |
| 154 | * If the touch is new it tries to assign a new finger id, if there is no fingers available no | 150 | * If the touch is new it tries to assign a new finger id, if there is no fingers available no |
| @@ -166,10 +162,10 @@ private: | |||
| 166 | std::unique_ptr<Input::TouchDevice> touch_mouse_device; | 162 | std::unique_ptr<Input::TouchDevice> touch_mouse_device; |
| 167 | std::unique_ptr<Input::TouchDevice> touch_udp_device; | 163 | std::unique_ptr<Input::TouchDevice> touch_udp_device; |
| 168 | std::unique_ptr<Input::TouchDevice> touch_btn_device; | 164 | std::unique_ptr<Input::TouchDevice> touch_btn_device; |
| 169 | std::array<size_t, MAX_FINGERS> mouse_finger_id; | 165 | std::array<size_t, MAX_FINGERS> mouse_finger_id{}; |
| 170 | std::array<size_t, MAX_FINGERS> keyboard_finger_id; | 166 | std::array<size_t, MAX_FINGERS> keyboard_finger_id{}; |
| 171 | std::array<size_t, MAX_FINGERS> udp_finger_id; | 167 | std::array<size_t, MAX_FINGERS> udp_finger_id{}; |
| 172 | std::array<Finger, MAX_POINTS> fingers; | 168 | std::array<Finger, MAX_POINTS> fingers{}; |
| 173 | GestureProperties last_gesture{}; | 169 | GestureProperties last_gesture{}; |
| 174 | s64_le last_update_timestamp{}; | 170 | s64_le last_update_timestamp{}; |
| 175 | s64_le last_tap_timestamp{}; | 171 | s64_le last_tap_timestamp{}; |
diff --git a/src/core/hle/service/hid/controllers/touchscreen.cpp b/src/core/hle/service/hid/controllers/touchscreen.cpp index ac9112c40..6ef17acc5 100644 --- a/src/core/hle/service/hid/controllers/touchscreen.cpp +++ b/src/core/hle/service/hid/controllers/touchscreen.cpp | |||
| @@ -74,8 +74,11 @@ void Controller_Touchscreen::OnUpdate(const Core::Timing::CoreTiming& core_timin | |||
| 74 | for (std::size_t id = 0; id < MAX_FINGERS; ++id) { | 74 | for (std::size_t id = 0; id < MAX_FINGERS; ++id) { |
| 75 | auto& touch_entry = cur_entry.states[id]; | 75 | auto& touch_entry = cur_entry.states[id]; |
| 76 | if (id < active_fingers_count) { | 76 | if (id < active_fingers_count) { |
| 77 | touch_entry.x = static_cast<u16>(active_fingers[id].x * Layout::ScreenUndocked::Width); | 77 | const auto& [active_x, active_y] = active_fingers[id].position; |
| 78 | touch_entry.y = static_cast<u16>(active_fingers[id].y * Layout::ScreenUndocked::Height); | 78 | touch_entry.position = { |
| 79 | .x = static_cast<u16>(active_x * Layout::ScreenUndocked::Width), | ||
| 80 | .y = static_cast<u16>(active_y * Layout::ScreenUndocked::Height), | ||
| 81 | }; | ||
| 79 | touch_entry.diameter_x = Settings::values.touchscreen.diameter_x; | 82 | touch_entry.diameter_x = Settings::values.touchscreen.diameter_x; |
| 80 | touch_entry.diameter_y = Settings::values.touchscreen.diameter_y; | 83 | touch_entry.diameter_y = Settings::values.touchscreen.diameter_y; |
| 81 | touch_entry.rotation_angle = Settings::values.touchscreen.rotation_angle; | 84 | touch_entry.rotation_angle = Settings::values.touchscreen.rotation_angle; |
| @@ -86,8 +89,7 @@ void Controller_Touchscreen::OnUpdate(const Core::Timing::CoreTiming& core_timin | |||
| 86 | } else { | 89 | } else { |
| 87 | // Clear touch entry | 90 | // Clear touch entry |
| 88 | touch_entry.attribute.raw = 0; | 91 | touch_entry.attribute.raw = 0; |
| 89 | touch_entry.x = 0; | 92 | touch_entry.position = {}; |
| 90 | touch_entry.y = 0; | ||
| 91 | touch_entry.diameter_x = 0; | 93 | touch_entry.diameter_x = 0; |
| 92 | touch_entry.diameter_y = 0; | 94 | touch_entry.diameter_y = 0; |
| 93 | touch_entry.rotation_angle = 0; | 95 | touch_entry.rotation_angle = 0; |
| @@ -140,8 +142,7 @@ std::size_t Controller_Touchscreen::UpdateTouchInputEvent( | |||
| 140 | fingers[finger_id].id = static_cast<u32_le>(finger_id); | 142 | fingers[finger_id].id = static_cast<u32_le>(finger_id); |
| 141 | attribute.start_touch.Assign(1); | 143 | attribute.start_touch.Assign(1); |
| 142 | } | 144 | } |
| 143 | fingers[finger_id].x = x; | 145 | fingers[finger_id].position = {x, y}; |
| 144 | fingers[finger_id].y = y; | ||
| 145 | fingers[finger_id].attribute = attribute; | 146 | fingers[finger_id].attribute = attribute; |
| 146 | return finger_id; | 147 | return finger_id; |
| 147 | } | 148 | } |
diff --git a/src/core/hle/service/hid/controllers/touchscreen.h b/src/core/hle/service/hid/controllers/touchscreen.h index 2869d0cfd..ef2becefd 100644 --- a/src/core/hle/service/hid/controllers/touchscreen.h +++ b/src/core/hle/service/hid/controllers/touchscreen.h | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include "common/bit_field.h" | 7 | #include "common/bit_field.h" |
| 8 | #include "common/common_funcs.h" | 8 | #include "common/common_funcs.h" |
| 9 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| 10 | #include "common/point.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" |
| @@ -55,8 +56,7 @@ private: | |||
| 55 | u64_le delta_time; | 56 | u64_le delta_time; |
| 56 | Attributes attribute; | 57 | Attributes attribute; |
| 57 | u32_le finger; | 58 | u32_le finger; |
| 58 | u32_le x; | 59 | Common::Point<u32_le> position; |
| 59 | u32_le y; | ||
| 60 | u32_le diameter_x; | 60 | u32_le diameter_x; |
| 61 | u32_le diameter_y; | 61 | u32_le diameter_y; |
| 62 | u32_le rotation_angle; | 62 | u32_le rotation_angle; |
| @@ -81,8 +81,7 @@ private: | |||
| 81 | 81 | ||
| 82 | struct Finger { | 82 | struct Finger { |
| 83 | u64_le last_touch{}; | 83 | u64_le last_touch{}; |
| 84 | float x{}; | 84 | Common::Point<float> position; |
| 85 | float y{}; | ||
| 86 | u32_le id{}; | 85 | u32_le id{}; |
| 87 | bool pressed{}; | 86 | bool pressed{}; |
| 88 | Attributes attribute; | 87 | Attributes attribute; |
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 49c17fd14..df0fe1c8e 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp | |||
| @@ -1770,7 +1770,7 @@ public: | |||
| 1770 | {232, nullptr, "GetIrSensorState"}, | 1770 | {232, nullptr, "GetIrSensorState"}, |
| 1771 | {233, nullptr, "GetXcdHandleForNpadWithIrSensor"}, | 1771 | {233, nullptr, "GetXcdHandleForNpadWithIrSensor"}, |
| 1772 | {301, nullptr, "ActivateNpadSystem"}, | 1772 | {301, nullptr, "ActivateNpadSystem"}, |
| 1773 | {303, nullptr, "ApplyNpadSystemCommonPolicy"}, | 1773 | {303, &HidSys::ApplyNpadSystemCommonPolicy, "ApplyNpadSystemCommonPolicy"}, |
| 1774 | {304, nullptr, "EnableAssigningSingleOnSlSrPress"}, | 1774 | {304, nullptr, "EnableAssigningSingleOnSlSrPress"}, |
| 1775 | {305, nullptr, "DisableAssigningSingleOnSlSrPress"}, | 1775 | {305, nullptr, "DisableAssigningSingleOnSlSrPress"}, |
| 1776 | {306, nullptr, "GetLastActiveNpad"}, | 1776 | {306, nullptr, "GetLastActiveNpad"}, |
| @@ -1949,6 +1949,15 @@ public: | |||
| 1949 | 1949 | ||
| 1950 | RegisterHandlers(functions); | 1950 | RegisterHandlers(functions); |
| 1951 | } | 1951 | } |
| 1952 | |||
| 1953 | private: | ||
| 1954 | void ApplyNpadSystemCommonPolicy(Kernel::HLERequestContext& ctx) { | ||
| 1955 | // We already do this for homebrew so we can just stub it out | ||
| 1956 | LOG_WARNING(Service_HID, "called"); | ||
| 1957 | |||
| 1958 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1959 | rb.Push(RESULT_SUCCESS); | ||
| 1960 | } | ||
| 1952 | }; | 1961 | }; |
| 1953 | 1962 | ||
| 1954 | class HidTmp final : public ServiceFramework<HidTmp> { | 1963 | class HidTmp final : public ServiceFramework<HidTmp> { |
diff --git a/src/core/hle/service/ldn/ldn.cpp b/src/core/hle/service/ldn/ldn.cpp index d160ffe87..c709a8028 100644 --- a/src/core/hle/service/ldn/ldn.cpp +++ b/src/core/hle/service/ldn/ldn.cpp | |||
| @@ -215,10 +215,151 @@ public: | |||
| 215 | } | 215 | } |
| 216 | }; | 216 | }; |
| 217 | 217 | ||
| 218 | class INetworkService final : public ServiceFramework<INetworkService> { | ||
| 219 | public: | ||
| 220 | explicit INetworkService(Core::System& system_) : ServiceFramework{system_, "INetworkService"} { | ||
| 221 | // clang-format off | ||
| 222 | static const FunctionInfo functions[] = { | ||
| 223 | {0, nullptr, "Initialize"}, | ||
| 224 | {256, nullptr, "AttachNetworkInterfaceStateChangeEvent"}, | ||
| 225 | {264, nullptr, "GetNetworkInterfaceLastError"}, | ||
| 226 | {272, nullptr, "GetRole"}, | ||
| 227 | {280, nullptr, "GetAdvertiseData"}, | ||
| 228 | {288, nullptr, "GetGroupInfo"}, | ||
| 229 | {296, nullptr, "GetGroupInfo2"}, | ||
| 230 | {304, nullptr, "GetGroupOwner"}, | ||
| 231 | {312, nullptr, "GetIpConfig"}, | ||
| 232 | {320, nullptr, "GetLinkLevel"}, | ||
| 233 | {512, nullptr, "Scan"}, | ||
| 234 | {768, nullptr, "CreateGroup"}, | ||
| 235 | {776, nullptr, "DestroyGroup"}, | ||
| 236 | {784, nullptr, "SetAdvertiseData"}, | ||
| 237 | {1536, nullptr, "SendToOtherGroup"}, | ||
| 238 | {1544, nullptr, "RecvFromOtherGroup"}, | ||
| 239 | {1552, nullptr, "AddAcceptableGroupId"}, | ||
| 240 | {1560, nullptr, "ClearAcceptableGroupId"}, | ||
| 241 | }; | ||
| 242 | // clang-format on | ||
| 243 | |||
| 244 | RegisterHandlers(functions); | ||
| 245 | } | ||
| 246 | }; | ||
| 247 | |||
| 248 | class INetworkServiceMonitor final : public ServiceFramework<INetworkServiceMonitor> { | ||
| 249 | public: | ||
| 250 | explicit INetworkServiceMonitor(Core::System& system_) | ||
| 251 | : ServiceFramework{system_, "INetworkServiceMonitor"} { | ||
| 252 | // clang-format off | ||
| 253 | static const FunctionInfo functions[] = { | ||
| 254 | {0, &INetworkServiceMonitor::Initialize, "Initialize"}, | ||
| 255 | {256, nullptr, "AttachNetworkInterfaceStateChangeEvent"}, | ||
| 256 | {264, nullptr, "GetNetworkInterfaceLastError"}, | ||
| 257 | {272, nullptr, "GetRole"}, | ||
| 258 | {280, nullptr, "GetAdvertiseData"}, | ||
| 259 | {281, nullptr, "GetAdvertiseData2"}, | ||
| 260 | {288, nullptr, "GetGroupInfo"}, | ||
| 261 | {296, nullptr, "GetGroupInfo2"}, | ||
| 262 | {304, nullptr, "GetGroupOwner"}, | ||
| 263 | {312, nullptr, "GetIpConfig"}, | ||
| 264 | {320, nullptr, "GetLinkLevel"}, | ||
| 265 | {328, nullptr, "AttachJoinEvent"}, | ||
| 266 | {336, nullptr, "GetMembers"}, | ||
| 267 | }; | ||
| 268 | // clang-format on | ||
| 269 | |||
| 270 | RegisterHandlers(functions); | ||
| 271 | } | ||
| 272 | |||
| 273 | void Initialize(Kernel::HLERequestContext& ctx) { | ||
| 274 | LOG_WARNING(Service_LDN, "(STUBBED) called"); | ||
| 275 | |||
| 276 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 277 | rb.Push(ERROR_DISABLED); | ||
| 278 | } | ||
| 279 | }; | ||
| 280 | |||
| 281 | class LP2PAPP final : public ServiceFramework<LP2PAPP> { | ||
| 282 | public: | ||
| 283 | explicit LP2PAPP(Core::System& system_) : ServiceFramework{system_, "lp2p:app"} { | ||
| 284 | // clang-format off | ||
| 285 | static const FunctionInfo functions[] = { | ||
| 286 | {0, &LP2PAPP::CreateMonitorService, "CreateNetworkService"}, | ||
| 287 | {8, &LP2PAPP::CreateMonitorService, "CreateNetworkServiceMonitor"}, | ||
| 288 | }; | ||
| 289 | // clang-format on | ||
| 290 | |||
| 291 | RegisterHandlers(functions); | ||
| 292 | } | ||
| 293 | |||
| 294 | void CreateNetworkervice(Kernel::HLERequestContext& ctx) { | ||
| 295 | IPC::RequestParser rp{ctx}; | ||
| 296 | const u64 reserved_input = rp.Pop<u64>(); | ||
| 297 | const u32 input = rp.Pop<u32>(); | ||
| 298 | |||
| 299 | LOG_WARNING(Service_LDN, "(STUBBED) called reserved_input={} input={}", reserved_input, | ||
| 300 | input); | ||
| 301 | |||
| 302 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 303 | rb.Push(RESULT_SUCCESS); | ||
| 304 | rb.PushIpcInterface<INetworkService>(system); | ||
| 305 | } | ||
| 306 | |||
| 307 | void CreateMonitorService(Kernel::HLERequestContext& ctx) { | ||
| 308 | IPC::RequestParser rp{ctx}; | ||
| 309 | const u64 reserved_input = rp.Pop<u64>(); | ||
| 310 | |||
| 311 | LOG_WARNING(Service_LDN, "(STUBBED) called reserved_input={}", reserved_input); | ||
| 312 | |||
| 313 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 314 | rb.Push(RESULT_SUCCESS); | ||
| 315 | rb.PushIpcInterface<INetworkServiceMonitor>(system); | ||
| 316 | } | ||
| 317 | }; | ||
| 318 | |||
| 319 | class LP2PSYS final : public ServiceFramework<LP2PSYS> { | ||
| 320 | public: | ||
| 321 | explicit LP2PSYS(Core::System& system_) : ServiceFramework{system_, "lp2p:sys"} { | ||
| 322 | // clang-format off | ||
| 323 | static const FunctionInfo functions[] = { | ||
| 324 | {0, &LP2PSYS::CreateMonitorService, "CreateNetworkService"}, | ||
| 325 | {8, &LP2PSYS::CreateMonitorService, "CreateNetworkServiceMonitor"}, | ||
| 326 | }; | ||
| 327 | // clang-format on | ||
| 328 | |||
| 329 | RegisterHandlers(functions); | ||
| 330 | } | ||
| 331 | |||
| 332 | void CreateNetworkervice(Kernel::HLERequestContext& ctx) { | ||
| 333 | IPC::RequestParser rp{ctx}; | ||
| 334 | const u64 reserved_input = rp.Pop<u64>(); | ||
| 335 | const u32 input = rp.Pop<u32>(); | ||
| 336 | |||
| 337 | LOG_WARNING(Service_LDN, "(STUBBED) called reserved_input={} input={}", reserved_input, | ||
| 338 | input); | ||
| 339 | |||
| 340 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 341 | rb.Push(RESULT_SUCCESS); | ||
| 342 | rb.PushIpcInterface<INetworkService>(system); | ||
| 343 | } | ||
| 344 | |||
| 345 | void CreateMonitorService(Kernel::HLERequestContext& ctx) { | ||
| 346 | IPC::RequestParser rp{ctx}; | ||
| 347 | const u64 reserved_input = rp.Pop<u64>(); | ||
| 348 | |||
| 349 | LOG_WARNING(Service_LDN, "(STUBBED) called reserved_input={}", reserved_input); | ||
| 350 | |||
| 351 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 352 | rb.Push(RESULT_SUCCESS); | ||
| 353 | rb.PushIpcInterface<INetworkServiceMonitor>(system); | ||
| 354 | } | ||
| 355 | }; | ||
| 356 | |||
| 218 | void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) { | 357 | void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) { |
| 219 | std::make_shared<LDNM>(system)->InstallAsService(sm); | 358 | std::make_shared<LDNM>(system)->InstallAsService(sm); |
| 220 | std::make_shared<LDNS>(system)->InstallAsService(sm); | 359 | std::make_shared<LDNS>(system)->InstallAsService(sm); |
| 221 | std::make_shared<LDNU>(system)->InstallAsService(sm); | 360 | std::make_shared<LDNU>(system)->InstallAsService(sm); |
| 361 | std::make_shared<LP2PAPP>(system)->InstallAsService(sm); | ||
| 362 | std::make_shared<LP2PSYS>(system)->InstallAsService(sm); | ||
| 222 | } | 363 | } |
| 223 | 364 | ||
| 224 | } // namespace Service::LDN | 365 | } // namespace Service::LDN |
diff --git a/src/core/memory.cpp b/src/core/memory.cpp index bf2ef7816..9857278f6 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp | |||
| @@ -591,7 +591,15 @@ struct Memory::Impl { | |||
| 591 | * @returns The instance of T read from the specified virtual address. | 591 | * @returns The instance of T read from the specified virtual address. |
| 592 | */ | 592 | */ |
| 593 | template <typename T> | 593 | template <typename T> |
| 594 | T Read(const VAddr vaddr) { | 594 | T Read(VAddr vaddr) { |
| 595 | // AARCH64 masks the upper 16 bit of all memory accesses | ||
| 596 | vaddr &= 0xffffffffffffLL; | ||
| 597 | |||
| 598 | if (vaddr >= 1uLL << current_page_table->GetAddressSpaceBits()) { | ||
| 599 | LOG_ERROR(HW_Memory, "Unmapped Read{} @ 0x{:08X}", sizeof(T) * 8, vaddr); | ||
| 600 | return 0; | ||
| 601 | } | ||
| 602 | |||
| 595 | // Avoid adding any extra logic to this fast-path block | 603 | // Avoid adding any extra logic to this fast-path block |
| 596 | const uintptr_t raw_pointer = current_page_table->pointers[vaddr >> PAGE_BITS].Raw(); | 604 | const uintptr_t raw_pointer = current_page_table->pointers[vaddr >> PAGE_BITS].Raw(); |
| 597 | if (const u8* const pointer = Common::PageTable::PageInfo::ExtractPointer(raw_pointer)) { | 605 | if (const u8* const pointer = Common::PageTable::PageInfo::ExtractPointer(raw_pointer)) { |
| @@ -629,7 +637,16 @@ struct Memory::Impl { | |||
| 629 | * is undefined. | 637 | * is undefined. |
| 630 | */ | 638 | */ |
| 631 | template <typename T> | 639 | template <typename T> |
| 632 | void Write(const VAddr vaddr, const T data) { | 640 | void Write(VAddr vaddr, const T data) { |
| 641 | // AARCH64 masks the upper 16 bit of all memory accesses | ||
| 642 | vaddr &= 0xffffffffffffLL; | ||
| 643 | |||
| 644 | if (vaddr >= 1uLL << current_page_table->GetAddressSpaceBits()) { | ||
| 645 | LOG_ERROR(HW_Memory, "Unmapped Write{} 0x{:08X} @ 0x{:016X}", sizeof(data) * 8, | ||
| 646 | static_cast<u32>(data), vaddr); | ||
| 647 | return; | ||
| 648 | } | ||
| 649 | |||
| 633 | // Avoid adding any extra logic to this fast-path block | 650 | // Avoid adding any extra logic to this fast-path block |
| 634 | const uintptr_t raw_pointer = current_page_table->pointers[vaddr >> PAGE_BITS].Raw(); | 651 | const uintptr_t raw_pointer = current_page_table->pointers[vaddr >> PAGE_BITS].Raw(); |
| 635 | if (u8* const pointer = Common::PageTable::PageInfo::ExtractPointer(raw_pointer)) { | 652 | if (u8* const pointer = Common::PageTable::PageInfo::ExtractPointer(raw_pointer)) { |
| @@ -656,7 +673,16 @@ struct Memory::Impl { | |||
| 656 | } | 673 | } |
| 657 | 674 | ||
| 658 | template <typename T> | 675 | template <typename T> |
| 659 | bool WriteExclusive(const VAddr vaddr, const T data, const T expected) { | 676 | bool WriteExclusive(VAddr vaddr, const T data, const T expected) { |
| 677 | // AARCH64 masks the upper 16 bit of all memory accesses | ||
| 678 | vaddr &= 0xffffffffffffLL; | ||
| 679 | |||
| 680 | if (vaddr >= 1uLL << current_page_table->GetAddressSpaceBits()) { | ||
| 681 | LOG_ERROR(HW_Memory, "Unmapped Write{} 0x{:08X} @ 0x{:016X}", sizeof(data) * 8, | ||
| 682 | static_cast<u32>(data), vaddr); | ||
| 683 | return true; | ||
| 684 | } | ||
| 685 | |||
| 660 | const uintptr_t raw_pointer = current_page_table->pointers[vaddr >> PAGE_BITS].Raw(); | 686 | const uintptr_t raw_pointer = current_page_table->pointers[vaddr >> PAGE_BITS].Raw(); |
| 661 | if (u8* const pointer = Common::PageTable::PageInfo::ExtractPointer(raw_pointer)) { | 687 | if (u8* const pointer = Common::PageTable::PageInfo::ExtractPointer(raw_pointer)) { |
| 662 | // NOTE: Avoid adding any extra logic to this fast-path block | 688 | // NOTE: Avoid adding any extra logic to this fast-path block |
| @@ -683,7 +709,16 @@ struct Memory::Impl { | |||
| 683 | return true; | 709 | return true; |
| 684 | } | 710 | } |
| 685 | 711 | ||
| 686 | bool WriteExclusive128(const VAddr vaddr, const u128 data, const u128 expected) { | 712 | bool WriteExclusive128(VAddr vaddr, const u128 data, const u128 expected) { |
| 713 | // AARCH64 masks the upper 16 bit of all memory accesses | ||
| 714 | vaddr &= 0xffffffffffffLL; | ||
| 715 | |||
| 716 | if (vaddr >= 1uLL << current_page_table->GetAddressSpaceBits()) { | ||
| 717 | LOG_ERROR(HW_Memory, "Unmapped Write{} 0x{:08X} @ 0x{:016X}", sizeof(data) * 8, | ||
| 718 | static_cast<u32>(data[0]), vaddr); | ||
| 719 | return true; | ||
| 720 | } | ||
| 721 | |||
| 687 | const uintptr_t raw_pointer = current_page_table->pointers[vaddr >> PAGE_BITS].Raw(); | 722 | const uintptr_t raw_pointer = current_page_table->pointers[vaddr >> PAGE_BITS].Raw(); |
| 688 | if (u8* const pointer = Common::PageTable::PageInfo::ExtractPointer(raw_pointer)) { | 723 | if (u8* const pointer = Common::PageTable::PageInfo::ExtractPointer(raw_pointer)) { |
| 689 | // NOTE: Avoid adding any extra logic to this fast-path block | 724 | // NOTE: Avoid adding any extra logic to this fast-path block |
diff --git a/src/input_common/sdl/sdl_impl.cpp b/src/input_common/sdl/sdl_impl.cpp index b9b584b2a..68672a92b 100644 --- a/src/input_common/sdl/sdl_impl.cpp +++ b/src/input_common/sdl/sdl_impl.cpp | |||
| @@ -18,16 +18,6 @@ | |||
| 18 | #include <utility> | 18 | #include <utility> |
| 19 | #include <vector> | 19 | #include <vector> |
| 20 | 20 | ||
| 21 | // Ignore -Wimplicit-fallthrough due to https://github.com/libsdl-org/SDL/issues/4307 | ||
| 22 | #ifdef __clang__ | ||
| 23 | #pragma clang diagnostic push | ||
| 24 | #pragma clang diagnostic ignored "-Wimplicit-fallthrough" | ||
| 25 | #endif | ||
| 26 | #include <SDL.h> | ||
| 27 | #ifdef __clang__ | ||
| 28 | #pragma clang diagnostic pop | ||
| 29 | #endif | ||
| 30 | |||
| 31 | #include "common/logging/log.h" | 21 | #include "common/logging/log.h" |
| 32 | #include "common/math_util.h" | 22 | #include "common/math_util.h" |
| 33 | #include "common/param_package.h" | 23 | #include "common/param_package.h" |
| @@ -214,6 +204,40 @@ public: | |||
| 214 | sdl_controller.reset(controller); | 204 | sdl_controller.reset(controller); |
| 215 | } | 205 | } |
| 216 | 206 | ||
| 207 | bool IsJoyconLeft() const { | ||
| 208 | return std::strstr(GetControllerName().c_str(), "Joy-Con Left") != nullptr; | ||
| 209 | } | ||
| 210 | |||
| 211 | bool IsJoyconRight() const { | ||
| 212 | return std::strstr(GetControllerName().c_str(), "Joy-Con Right") != nullptr; | ||
| 213 | } | ||
| 214 | |||
| 215 | std::string GetControllerName() const { | ||
| 216 | if (sdl_controller) { | ||
| 217 | switch (SDL_GameControllerGetType(sdl_controller.get())) { | ||
| 218 | case SDL_CONTROLLER_TYPE_XBOX360: | ||
| 219 | return "XBox 360 Controller"; | ||
| 220 | case SDL_CONTROLLER_TYPE_XBOXONE: | ||
| 221 | return "XBox One Controller"; | ||
| 222 | default: | ||
| 223 | break; | ||
| 224 | } | ||
| 225 | const auto name = SDL_GameControllerName(sdl_controller.get()); | ||
| 226 | if (name) { | ||
| 227 | return name; | ||
| 228 | } | ||
| 229 | } | ||
| 230 | |||
| 231 | if (sdl_joystick) { | ||
| 232 | const auto name = SDL_JoystickName(sdl_joystick.get()); | ||
| 233 | if (name) { | ||
| 234 | return name; | ||
| 235 | } | ||
| 236 | } | ||
| 237 | |||
| 238 | return "Unknown"; | ||
| 239 | } | ||
| 240 | |||
| 217 | private: | 241 | private: |
| 218 | struct State { | 242 | struct State { |
| 219 | std::unordered_map<int, bool> buttons; | 243 | std::unordered_map<int, bool> buttons; |
| @@ -858,23 +882,42 @@ SDLState::~SDLState() { | |||
| 858 | std::vector<Common::ParamPackage> SDLState::GetInputDevices() { | 882 | std::vector<Common::ParamPackage> SDLState::GetInputDevices() { |
| 859 | std::scoped_lock lock(joystick_map_mutex); | 883 | std::scoped_lock lock(joystick_map_mutex); |
| 860 | std::vector<Common::ParamPackage> devices; | 884 | std::vector<Common::ParamPackage> devices; |
| 885 | std::unordered_map<int, std::shared_ptr<SDLJoystick>> joycon_pairs; | ||
| 886 | for (const auto& [key, value] : joystick_map) { | ||
| 887 | for (const auto& joystick : value) { | ||
| 888 | if (!joystick->GetSDLJoystick()) { | ||
| 889 | continue; | ||
| 890 | } | ||
| 891 | std::string name = | ||
| 892 | fmt::format("{} {}", joystick->GetControllerName(), joystick->GetPort()); | ||
| 893 | devices.emplace_back(Common::ParamPackage{ | ||
| 894 | {"class", "sdl"}, | ||
| 895 | {"display", std::move(name)}, | ||
| 896 | {"guid", joystick->GetGUID()}, | ||
| 897 | {"port", std::to_string(joystick->GetPort())}, | ||
| 898 | }); | ||
| 899 | if (joystick->IsJoyconLeft()) { | ||
| 900 | joycon_pairs.insert_or_assign(joystick->GetPort(), joystick); | ||
| 901 | } | ||
| 902 | } | ||
| 903 | } | ||
| 904 | |||
| 905 | // Add dual controllers | ||
| 861 | for (const auto& [key, value] : joystick_map) { | 906 | for (const auto& [key, value] : joystick_map) { |
| 862 | for (const auto& joystick : value) { | 907 | for (const auto& joystick : value) { |
| 863 | if (auto* const controller = joystick->GetSDLGameController()) { | 908 | if (joystick->IsJoyconRight()) { |
| 909 | if (!joycon_pairs.contains(joystick->GetPort())) { | ||
| 910 | continue; | ||
| 911 | } | ||
| 912 | const auto joystick2 = joycon_pairs.at(joystick->GetPort()); | ||
| 913 | |||
| 864 | std::string name = | 914 | std::string name = |
| 865 | fmt::format("{} {}", GetControllerName(controller), joystick->GetPort()); | 915 | fmt::format("{} {}", "Nintendo Dual Joy-Con", joystick->GetPort()); |
| 866 | devices.emplace_back(Common::ParamPackage{ | ||
| 867 | {"class", "sdl"}, | ||
| 868 | {"display", std::move(name)}, | ||
| 869 | {"guid", joystick->GetGUID()}, | ||
| 870 | {"port", std::to_string(joystick->GetPort())}, | ||
| 871 | }); | ||
| 872 | } else if (auto* const joy = joystick->GetSDLJoystick()) { | ||
| 873 | std::string name = fmt::format("{} {}", SDL_JoystickName(joy), joystick->GetPort()); | ||
| 874 | devices.emplace_back(Common::ParamPackage{ | 916 | devices.emplace_back(Common::ParamPackage{ |
| 875 | {"class", "sdl"}, | 917 | {"class", "sdl"}, |
| 876 | {"display", std::move(name)}, | 918 | {"display", std::move(name)}, |
| 877 | {"guid", joystick->GetGUID()}, | 919 | {"guid", joystick->GetGUID()}, |
| 920 | {"guid2", joystick2->GetGUID()}, | ||
| 878 | {"port", std::to_string(joystick->GetPort())}, | 921 | {"port", std::to_string(joystick->GetPort())}, |
| 879 | }); | 922 | }); |
| 880 | } | 923 | } |
| @@ -883,17 +926,6 @@ std::vector<Common::ParamPackage> SDLState::GetInputDevices() { | |||
| 883 | return devices; | 926 | return devices; |
| 884 | } | 927 | } |
| 885 | 928 | ||
| 886 | std::string SDLState::GetControllerName(SDL_GameController* controller) const { | ||
| 887 | switch (SDL_GameControllerGetType(controller)) { | ||
| 888 | case SDL_CONTROLLER_TYPE_XBOX360: | ||
| 889 | return "XBox 360 Controller"; | ||
| 890 | case SDL_CONTROLLER_TYPE_XBOXONE: | ||
| 891 | return "XBox One Controller"; | ||
| 892 | default: | ||
| 893 | return SDL_GameControllerName(controller); | ||
| 894 | } | ||
| 895 | } | ||
| 896 | |||
| 897 | namespace { | 929 | namespace { |
| 898 | Common::ParamPackage BuildAnalogParamPackageForButton(int port, std::string guid, s32 axis, | 930 | Common::ParamPackage BuildAnalogParamPackageForButton(int port, std::string guid, s32 axis, |
| 899 | float value = 0.1f) { | 931 | float value = 0.1f) { |
| @@ -1073,24 +1105,48 @@ ButtonMapping SDLState::GetButtonMappingForDevice(const Common::ParamPackage& pa | |||
| 1073 | return {}; | 1105 | return {}; |
| 1074 | } | 1106 | } |
| 1075 | const auto joystick = GetSDLJoystickByGUID(params.Get("guid", ""), params.Get("port", 0)); | 1107 | const auto joystick = GetSDLJoystickByGUID(params.Get("guid", ""), params.Get("port", 0)); |
| 1108 | |||
| 1076 | auto* controller = joystick->GetSDLGameController(); | 1109 | auto* controller = joystick->GetSDLGameController(); |
| 1077 | if (controller == nullptr) { | 1110 | if (controller == nullptr) { |
| 1078 | return {}; | 1111 | return {}; |
| 1079 | } | 1112 | } |
| 1080 | 1113 | ||
| 1081 | const bool invert = | ||
| 1082 | SDL_GameControllerGetType(controller) != SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO; | ||
| 1083 | |||
| 1084 | // This list is missing ZL/ZR since those are not considered buttons in SDL GameController. | 1114 | // This list is missing ZL/ZR since those are not considered buttons in SDL GameController. |
| 1085 | // We will add those afterwards | 1115 | // We will add those afterwards |
| 1086 | // This list also excludes Screenshot since theres not really a mapping for that | 1116 | // This list also excludes Screenshot since theres not really a mapping for that |
| 1087 | using ButtonBindings = | 1117 | ButtonBindings switch_to_sdl_button; |
| 1088 | std::array<std::pair<Settings::NativeButton::Values, SDL_GameControllerButton>, 17>; | 1118 | |
| 1089 | const ButtonBindings switch_to_sdl_button{{ | 1119 | if (SDL_GameControllerGetType(controller) == SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO) { |
| 1090 | {Settings::NativeButton::A, invert ? SDL_CONTROLLER_BUTTON_B : SDL_CONTROLLER_BUTTON_A}, | 1120 | switch_to_sdl_button = GetNintendoButtonBinding(joystick); |
| 1091 | {Settings::NativeButton::B, invert ? SDL_CONTROLLER_BUTTON_A : SDL_CONTROLLER_BUTTON_B}, | 1121 | } else { |
| 1092 | {Settings::NativeButton::X, invert ? SDL_CONTROLLER_BUTTON_Y : SDL_CONTROLLER_BUTTON_X}, | 1122 | switch_to_sdl_button = GetDefaultButtonBinding(); |
| 1093 | {Settings::NativeButton::Y, invert ? SDL_CONTROLLER_BUTTON_X : SDL_CONTROLLER_BUTTON_Y}, | 1123 | } |
| 1124 | |||
| 1125 | // Add the missing bindings for ZL/ZR | ||
| 1126 | static constexpr ZButtonBindings switch_to_sdl_axis{{ | ||
| 1127 | {Settings::NativeButton::ZL, SDL_CONTROLLER_AXIS_TRIGGERLEFT}, | ||
| 1128 | {Settings::NativeButton::ZR, SDL_CONTROLLER_AXIS_TRIGGERRIGHT}, | ||
| 1129 | }}; | ||
| 1130 | |||
| 1131 | // Parameters contain two joysticks return dual | ||
| 1132 | if (params.Has("guid2")) { | ||
| 1133 | const auto joystick2 = GetSDLJoystickByGUID(params.Get("guid2", ""), params.Get("port", 0)); | ||
| 1134 | |||
| 1135 | if (joystick2->GetSDLGameController() != nullptr) { | ||
| 1136 | return GetDualControllerMapping(joystick, joystick2, switch_to_sdl_button, | ||
| 1137 | switch_to_sdl_axis); | ||
| 1138 | } | ||
| 1139 | } | ||
| 1140 | |||
| 1141 | return GetSingleControllerMapping(joystick, switch_to_sdl_button, switch_to_sdl_axis); | ||
| 1142 | } | ||
| 1143 | |||
| 1144 | ButtonBindings SDLState::GetDefaultButtonBinding() const { | ||
| 1145 | return { | ||
| 1146 | std::pair{Settings::NativeButton::A, SDL_CONTROLLER_BUTTON_B}, | ||
| 1147 | {Settings::NativeButton::B, SDL_CONTROLLER_BUTTON_A}, | ||
| 1148 | {Settings::NativeButton::X, SDL_CONTROLLER_BUTTON_Y}, | ||
| 1149 | {Settings::NativeButton::Y, SDL_CONTROLLER_BUTTON_X}, | ||
| 1094 | {Settings::NativeButton::LStick, SDL_CONTROLLER_BUTTON_LEFTSTICK}, | 1150 | {Settings::NativeButton::LStick, SDL_CONTROLLER_BUTTON_LEFTSTICK}, |
| 1095 | {Settings::NativeButton::RStick, SDL_CONTROLLER_BUTTON_RIGHTSTICK}, | 1151 | {Settings::NativeButton::RStick, SDL_CONTROLLER_BUTTON_RIGHTSTICK}, |
| 1096 | {Settings::NativeButton::L, SDL_CONTROLLER_BUTTON_LEFTSHOULDER}, | 1152 | {Settings::NativeButton::L, SDL_CONTROLLER_BUTTON_LEFTSHOULDER}, |
| @@ -1104,18 +1160,51 @@ ButtonMapping SDLState::GetButtonMappingForDevice(const Common::ParamPackage& pa | |||
| 1104 | {Settings::NativeButton::SL, SDL_CONTROLLER_BUTTON_LEFTSHOULDER}, | 1160 | {Settings::NativeButton::SL, SDL_CONTROLLER_BUTTON_LEFTSHOULDER}, |
| 1105 | {Settings::NativeButton::SR, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER}, | 1161 | {Settings::NativeButton::SR, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER}, |
| 1106 | {Settings::NativeButton::Home, SDL_CONTROLLER_BUTTON_GUIDE}, | 1162 | {Settings::NativeButton::Home, SDL_CONTROLLER_BUTTON_GUIDE}, |
| 1107 | }}; | 1163 | }; |
| 1164 | } | ||
| 1108 | 1165 | ||
| 1109 | // Add the missing bindings for ZL/ZR | 1166 | ButtonBindings SDLState::GetNintendoButtonBinding( |
| 1110 | using ZBindings = | 1167 | const std::shared_ptr<SDLJoystick>& joystick) const { |
| 1111 | std::array<std::pair<Settings::NativeButton::Values, SDL_GameControllerAxis>, 2>; | 1168 | // Default SL/SR mapping for pro controllers |
| 1112 | static constexpr ZBindings switch_to_sdl_axis{{ | 1169 | auto sl_button = SDL_CONTROLLER_BUTTON_LEFTSHOULDER; |
| 1113 | {Settings::NativeButton::ZL, SDL_CONTROLLER_AXIS_TRIGGERLEFT}, | 1170 | auto sr_button = SDL_CONTROLLER_BUTTON_RIGHTSHOULDER; |
| 1114 | {Settings::NativeButton::ZR, SDL_CONTROLLER_AXIS_TRIGGERRIGHT}, | 1171 | |
| 1115 | }}; | 1172 | if (joystick->IsJoyconLeft()) { |
| 1173 | sl_button = SDL_CONTROLLER_BUTTON_PADDLE2; | ||
| 1174 | sr_button = SDL_CONTROLLER_BUTTON_PADDLE4; | ||
| 1175 | } | ||
| 1176 | if (joystick->IsJoyconRight()) { | ||
| 1177 | sl_button = SDL_CONTROLLER_BUTTON_PADDLE3; | ||
| 1178 | sr_button = SDL_CONTROLLER_BUTTON_PADDLE1; | ||
| 1179 | } | ||
| 1116 | 1180 | ||
| 1181 | return { | ||
| 1182 | std::pair{Settings::NativeButton::A, SDL_CONTROLLER_BUTTON_A}, | ||
| 1183 | {Settings::NativeButton::B, SDL_CONTROLLER_BUTTON_B}, | ||
| 1184 | {Settings::NativeButton::X, SDL_CONTROLLER_BUTTON_X}, | ||
| 1185 | {Settings::NativeButton::Y, SDL_CONTROLLER_BUTTON_Y}, | ||
| 1186 | {Settings::NativeButton::LStick, SDL_CONTROLLER_BUTTON_LEFTSTICK}, | ||
| 1187 | {Settings::NativeButton::RStick, SDL_CONTROLLER_BUTTON_RIGHTSTICK}, | ||
| 1188 | {Settings::NativeButton::L, SDL_CONTROLLER_BUTTON_LEFTSHOULDER}, | ||
| 1189 | {Settings::NativeButton::R, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER}, | ||
| 1190 | {Settings::NativeButton::Plus, SDL_CONTROLLER_BUTTON_START}, | ||
| 1191 | {Settings::NativeButton::Minus, SDL_CONTROLLER_BUTTON_BACK}, | ||
| 1192 | {Settings::NativeButton::DLeft, SDL_CONTROLLER_BUTTON_DPAD_LEFT}, | ||
| 1193 | {Settings::NativeButton::DUp, SDL_CONTROLLER_BUTTON_DPAD_UP}, | ||
| 1194 | {Settings::NativeButton::DRight, SDL_CONTROLLER_BUTTON_DPAD_RIGHT}, | ||
| 1195 | {Settings::NativeButton::DDown, SDL_CONTROLLER_BUTTON_DPAD_DOWN}, | ||
| 1196 | {Settings::NativeButton::SL, sl_button}, | ||
| 1197 | {Settings::NativeButton::SR, sr_button}, | ||
| 1198 | {Settings::NativeButton::Home, SDL_CONTROLLER_BUTTON_GUIDE}, | ||
| 1199 | }; | ||
| 1200 | } | ||
| 1201 | |||
| 1202 | ButtonMapping SDLState::GetSingleControllerMapping( | ||
| 1203 | const std::shared_ptr<SDLJoystick>& joystick, const ButtonBindings& switch_to_sdl_button, | ||
| 1204 | const ZButtonBindings& switch_to_sdl_axis) const { | ||
| 1117 | ButtonMapping mapping; | 1205 | ButtonMapping mapping; |
| 1118 | mapping.reserve(switch_to_sdl_button.size() + switch_to_sdl_axis.size()); | 1206 | mapping.reserve(switch_to_sdl_button.size() + switch_to_sdl_axis.size()); |
| 1207 | auto* controller = joystick->GetSDLGameController(); | ||
| 1119 | 1208 | ||
| 1120 | for (const auto& [switch_button, sdl_button] : switch_to_sdl_button) { | 1209 | for (const auto& [switch_button, sdl_button] : switch_to_sdl_button) { |
| 1121 | const auto& binding = SDL_GameControllerGetBindForButton(controller, sdl_button); | 1210 | const auto& binding = SDL_GameControllerGetBindForButton(controller, sdl_button); |
| @@ -1133,11 +1222,68 @@ ButtonMapping SDLState::GetButtonMappingForDevice(const Common::ParamPackage& pa | |||
| 1133 | return mapping; | 1222 | return mapping; |
| 1134 | } | 1223 | } |
| 1135 | 1224 | ||
| 1225 | ButtonMapping SDLState::GetDualControllerMapping(const std::shared_ptr<SDLJoystick>& joystick, | ||
| 1226 | const std::shared_ptr<SDLJoystick>& joystick2, | ||
| 1227 | const ButtonBindings& switch_to_sdl_button, | ||
| 1228 | const ZButtonBindings& switch_to_sdl_axis) const { | ||
| 1229 | ButtonMapping mapping; | ||
| 1230 | mapping.reserve(switch_to_sdl_button.size() + switch_to_sdl_axis.size()); | ||
| 1231 | auto* controller = joystick->GetSDLGameController(); | ||
| 1232 | auto* controller2 = joystick2->GetSDLGameController(); | ||
| 1233 | |||
| 1234 | for (const auto& [switch_button, sdl_button] : switch_to_sdl_button) { | ||
| 1235 | if (IsButtonOnLeftSide(switch_button)) { | ||
| 1236 | const auto& binding = SDL_GameControllerGetBindForButton(controller2, sdl_button); | ||
| 1237 | mapping.insert_or_assign( | ||
| 1238 | switch_button, | ||
| 1239 | BuildParamPackageForBinding(joystick2->GetPort(), joystick2->GetGUID(), binding)); | ||
| 1240 | continue; | ||
| 1241 | } | ||
| 1242 | const auto& binding = SDL_GameControllerGetBindForButton(controller, sdl_button); | ||
| 1243 | mapping.insert_or_assign( | ||
| 1244 | switch_button, | ||
| 1245 | BuildParamPackageForBinding(joystick->GetPort(), joystick->GetGUID(), binding)); | ||
| 1246 | } | ||
| 1247 | for (const auto& [switch_button, sdl_axis] : switch_to_sdl_axis) { | ||
| 1248 | if (IsButtonOnLeftSide(switch_button)) { | ||
| 1249 | const auto& binding = SDL_GameControllerGetBindForAxis(controller2, sdl_axis); | ||
| 1250 | mapping.insert_or_assign( | ||
| 1251 | switch_button, | ||
| 1252 | BuildParamPackageForBinding(joystick2->GetPort(), joystick2->GetGUID(), binding)); | ||
| 1253 | continue; | ||
| 1254 | } | ||
| 1255 | const auto& binding = SDL_GameControllerGetBindForAxis(controller, sdl_axis); | ||
| 1256 | mapping.insert_or_assign( | ||
| 1257 | switch_button, | ||
| 1258 | BuildParamPackageForBinding(joystick->GetPort(), joystick->GetGUID(), binding)); | ||
| 1259 | } | ||
| 1260 | |||
| 1261 | return mapping; | ||
| 1262 | } | ||
| 1263 | |||
| 1264 | bool SDLState::IsButtonOnLeftSide(Settings::NativeButton::Values button) const { | ||
| 1265 | switch (button) { | ||
| 1266 | case Settings::NativeButton::DDown: | ||
| 1267 | case Settings::NativeButton::DLeft: | ||
| 1268 | case Settings::NativeButton::DRight: | ||
| 1269 | case Settings::NativeButton::DUp: | ||
| 1270 | case Settings::NativeButton::L: | ||
| 1271 | case Settings::NativeButton::LStick: | ||
| 1272 | case Settings::NativeButton::Minus: | ||
| 1273 | case Settings::NativeButton::Screenshot: | ||
| 1274 | case Settings::NativeButton::ZL: | ||
| 1275 | return true; | ||
| 1276 | default: | ||
| 1277 | return false; | ||
| 1278 | } | ||
| 1279 | } | ||
| 1280 | |||
| 1136 | AnalogMapping SDLState::GetAnalogMappingForDevice(const Common::ParamPackage& params) { | 1281 | AnalogMapping SDLState::GetAnalogMappingForDevice(const Common::ParamPackage& params) { |
| 1137 | if (!params.Has("guid") || !params.Has("port")) { | 1282 | if (!params.Has("guid") || !params.Has("port")) { |
| 1138 | return {}; | 1283 | return {}; |
| 1139 | } | 1284 | } |
| 1140 | const auto joystick = GetSDLJoystickByGUID(params.Get("guid", ""), params.Get("port", 0)); | 1285 | const auto joystick = GetSDLJoystickByGUID(params.Get("guid", ""), params.Get("port", 0)); |
| 1286 | const auto joystick2 = GetSDLJoystickByGUID(params.Get("guid2", ""), params.Get("port", 0)); | ||
| 1141 | auto* controller = joystick->GetSDLGameController(); | 1287 | auto* controller = joystick->GetSDLGameController(); |
| 1142 | if (controller == nullptr) { | 1288 | if (controller == nullptr) { |
| 1143 | return {}; | 1289 | return {}; |
| @@ -1148,10 +1294,17 @@ AnalogMapping SDLState::GetAnalogMappingForDevice(const Common::ParamPackage& pa | |||
| 1148 | SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_LEFTX); | 1294 | SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_LEFTX); |
| 1149 | const auto& binding_left_y = | 1295 | const auto& binding_left_y = |
| 1150 | SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_LEFTY); | 1296 | SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_LEFTY); |
| 1151 | mapping.insert_or_assign(Settings::NativeAnalog::LStick, | 1297 | if (params.Has("guid2")) { |
| 1152 | BuildParamPackageForAnalog(joystick->GetPort(), joystick->GetGUID(), | 1298 | mapping.insert_or_assign( |
| 1153 | binding_left_x.value.axis, | 1299 | Settings::NativeAnalog::LStick, |
| 1154 | binding_left_y.value.axis)); | 1300 | BuildParamPackageForAnalog(joystick2->GetPort(), joystick2->GetGUID(), |
| 1301 | binding_left_x.value.axis, binding_left_y.value.axis)); | ||
| 1302 | } else { | ||
| 1303 | mapping.insert_or_assign( | ||
| 1304 | Settings::NativeAnalog::LStick, | ||
| 1305 | BuildParamPackageForAnalog(joystick->GetPort(), joystick->GetGUID(), | ||
| 1306 | binding_left_x.value.axis, binding_left_y.value.axis)); | ||
| 1307 | } | ||
| 1155 | const auto& binding_right_x = | 1308 | const auto& binding_right_x = |
| 1156 | SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_RIGHTX); | 1309 | SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_RIGHTX); |
| 1157 | const auto& binding_right_y = | 1310 | const auto& binding_right_y = |
| @@ -1168,20 +1321,32 @@ MotionMapping SDLState::GetMotionMappingForDevice(const Common::ParamPackage& pa | |||
| 1168 | return {}; | 1321 | return {}; |
| 1169 | } | 1322 | } |
| 1170 | const auto joystick = GetSDLJoystickByGUID(params.Get("guid", ""), params.Get("port", 0)); | 1323 | const auto joystick = GetSDLJoystickByGUID(params.Get("guid", ""), params.Get("port", 0)); |
| 1324 | const auto joystick2 = GetSDLJoystickByGUID(params.Get("guid2", ""), params.Get("port", 0)); | ||
| 1171 | auto* controller = joystick->GetSDLGameController(); | 1325 | auto* controller = joystick->GetSDLGameController(); |
| 1172 | if (controller == nullptr) { | 1326 | if (controller == nullptr) { |
| 1173 | return {}; | 1327 | return {}; |
| 1174 | } | 1328 | } |
| 1175 | 1329 | ||
| 1330 | MotionMapping mapping = {}; | ||
| 1176 | joystick->EnableMotion(); | 1331 | joystick->EnableMotion(); |
| 1177 | 1332 | ||
| 1178 | if (!joystick->HasGyro() && !joystick->HasAccel()) { | 1333 | if (joystick->HasGyro() || joystick->HasAccel()) { |
| 1179 | return {}; | 1334 | mapping.insert_or_assign(Settings::NativeMotion::MotionRight, |
| 1335 | BuildMotionParam(joystick->GetPort(), joystick->GetGUID())); | ||
| 1336 | } | ||
| 1337 | if (params.Has("guid2")) { | ||
| 1338 | joystick2->EnableMotion(); | ||
| 1339 | if (joystick2->HasGyro() || joystick2->HasAccel()) { | ||
| 1340 | mapping.insert_or_assign(Settings::NativeMotion::MotionLeft, | ||
| 1341 | BuildMotionParam(joystick2->GetPort(), joystick2->GetGUID())); | ||
| 1342 | } | ||
| 1343 | } else { | ||
| 1344 | if (joystick->HasGyro() || joystick->HasAccel()) { | ||
| 1345 | mapping.insert_or_assign(Settings::NativeMotion::MotionLeft, | ||
| 1346 | BuildMotionParam(joystick->GetPort(), joystick->GetGUID())); | ||
| 1347 | } | ||
| 1180 | } | 1348 | } |
| 1181 | 1349 | ||
| 1182 | MotionMapping mapping = {}; | ||
| 1183 | mapping.insert_or_assign(Settings::NativeMotion::MotionLeft, | ||
| 1184 | BuildMotionParam(joystick->GetPort(), joystick->GetGUID())); | ||
| 1185 | return mapping; | 1350 | return mapping; |
| 1186 | } | 1351 | } |
| 1187 | namespace Polling { | 1352 | namespace Polling { |
diff --git a/src/input_common/sdl/sdl_impl.h b/src/input_common/sdl/sdl_impl.h index 121e01913..b77afcbd8 100644 --- a/src/input_common/sdl/sdl_impl.h +++ b/src/input_common/sdl/sdl_impl.h | |||
| @@ -9,6 +9,17 @@ | |||
| 9 | #include <mutex> | 9 | #include <mutex> |
| 10 | #include <thread> | 10 | #include <thread> |
| 11 | #include <unordered_map> | 11 | #include <unordered_map> |
| 12 | |||
| 13 | // Ignore -Wimplicit-fallthrough due to https://github.com/libsdl-org/SDL/issues/4307 | ||
| 14 | #ifdef __GNUC__ | ||
| 15 | #pragma GCC diagnostic push | ||
| 16 | #pragma GCC diagnostic ignored "-Wimplicit-fallthrough" | ||
| 17 | #endif | ||
| 18 | #include <SDL.h> | ||
| 19 | #ifdef __GNUC__ | ||
| 20 | #pragma GCC diagnostic pop | ||
| 21 | #endif | ||
| 22 | |||
| 12 | #include "common/common_types.h" | 23 | #include "common/common_types.h" |
| 13 | #include "common/threadsafe_queue.h" | 24 | #include "common/threadsafe_queue.h" |
| 14 | #include "input_common/sdl/sdl.h" | 25 | #include "input_common/sdl/sdl.h" |
| @@ -18,6 +29,11 @@ using SDL_GameController = struct _SDL_GameController; | |||
| 18 | using SDL_Joystick = struct _SDL_Joystick; | 29 | using SDL_Joystick = struct _SDL_Joystick; |
| 19 | using SDL_JoystickID = s32; | 30 | using SDL_JoystickID = s32; |
| 20 | 31 | ||
| 32 | using ButtonBindings = | ||
| 33 | std::array<std::pair<Settings::NativeButton::Values, SDL_GameControllerButton>, 17>; | ||
| 34 | using ZButtonBindings = | ||
| 35 | std::array<std::pair<Settings::NativeButton::Values, SDL_GameControllerAxis>, 2>; | ||
| 36 | |||
| 21 | namespace InputCommon::SDL { | 37 | namespace InputCommon::SDL { |
| 22 | 38 | ||
| 23 | class SDLAnalogFactory; | 39 | class SDLAnalogFactory; |
| @@ -66,8 +82,25 @@ private: | |||
| 66 | /// Needs to be called before SDL_QuitSubSystem. | 82 | /// Needs to be called before SDL_QuitSubSystem. |
| 67 | void CloseJoysticks(); | 83 | void CloseJoysticks(); |
| 68 | 84 | ||
| 69 | /// Returns a custom name for specific controllers because the default name is not correct | 85 | /// Returns the default button bindings list for generic controllers |
| 70 | std::string GetControllerName(SDL_GameController* controller) const; | 86 | ButtonBindings GetDefaultButtonBinding() const; |
| 87 | |||
| 88 | /// Returns the default button bindings list for nintendo controllers | ||
| 89 | ButtonBindings GetNintendoButtonBinding(const std::shared_ptr<SDLJoystick>& joystick) const; | ||
| 90 | |||
| 91 | /// Returns the button mappings from a single controller | ||
| 92 | ButtonMapping GetSingleControllerMapping(const std::shared_ptr<SDLJoystick>& joystick, | ||
| 93 | const ButtonBindings& switch_to_sdl_button, | ||
| 94 | const ZButtonBindings& switch_to_sdl_axis) const; | ||
| 95 | |||
| 96 | /// Returns the button mappings from two different controllers | ||
| 97 | ButtonMapping GetDualControllerMapping(const std::shared_ptr<SDLJoystick>& joystick, | ||
| 98 | const std::shared_ptr<SDLJoystick>& joystick2, | ||
| 99 | const ButtonBindings& switch_to_sdl_button, | ||
| 100 | const ZButtonBindings& switch_to_sdl_axis) const; | ||
| 101 | |||
| 102 | /// Returns true if the button is on the left joycon | ||
| 103 | bool IsButtonOnLeftSide(Settings::NativeButton::Values button) const; | ||
| 71 | 104 | ||
| 72 | // Set to true if SDL supports game controller subsystem | 105 | // Set to true if SDL supports game controller subsystem |
| 73 | bool has_gamecontroller = false; | 106 | bool has_gamecontroller = false; |
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index de971041f..9e6b87960 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h | |||
| @@ -596,7 +596,7 @@ void BufferCache<P>::PopAsyncFlushes() { | |||
| 596 | runtime.CopyBuffer(download_staging.buffer, slot_buffers[buffer_id], copies); | 596 | runtime.CopyBuffer(download_staging.buffer, slot_buffers[buffer_id], copies); |
| 597 | } | 597 | } |
| 598 | runtime.Finish(); | 598 | runtime.Finish(); |
| 599 | for (const auto [copy, buffer_id] : downloads) { | 599 | for (const auto& [copy, buffer_id] : downloads) { |
| 600 | const Buffer& buffer = slot_buffers[buffer_id]; | 600 | const Buffer& buffer = slot_buffers[buffer_id]; |
| 601 | const VAddr cpu_addr = buffer.CpuAddr() + copy.src_offset; | 601 | const VAddr cpu_addr = buffer.CpuAddr() + copy.src_offset; |
| 602 | // Undo the modified offset | 602 | // Undo the modified offset |
| @@ -606,7 +606,7 @@ void BufferCache<P>::PopAsyncFlushes() { | |||
| 606 | } | 606 | } |
| 607 | } else { | 607 | } else { |
| 608 | const std::span<u8> immediate_buffer = ImmediateBuffer(largest_copy); | 608 | const std::span<u8> immediate_buffer = ImmediateBuffer(largest_copy); |
| 609 | for (const auto [copy, buffer_id] : downloads) { | 609 | for (const auto& [copy, buffer_id] : downloads) { |
| 610 | Buffer& buffer = slot_buffers[buffer_id]; | 610 | Buffer& buffer = slot_buffers[buffer_id]; |
| 611 | buffer.ImmediateDownload(copy.src_offset, immediate_buffer.subspan(0, copy.size)); | 611 | buffer.ImmediateDownload(copy.src_offset, immediate_buffer.subspan(0, copy.size)); |
| 612 | const VAddr cpu_addr = buffer.CpuAddr() + copy.src_offset; | 612 | const VAddr cpu_addr = buffer.CpuAddr() + copy.src_offset; |
diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp index 37f7b24e1..35cc561be 100644 --- a/src/video_core/gpu.cpp +++ b/src/video_core/gpu.cpp | |||
| @@ -104,7 +104,13 @@ void GPU::WaitFence(u32 syncpoint_id, u32 value) { | |||
| 104 | } | 104 | } |
| 105 | MICROPROFILE_SCOPE(GPU_wait); | 105 | MICROPROFILE_SCOPE(GPU_wait); |
| 106 | std::unique_lock lock{sync_mutex}; | 106 | std::unique_lock lock{sync_mutex}; |
| 107 | sync_cv.wait(lock, [=, this] { return syncpoints.at(syncpoint_id).load() >= value; }); | 107 | sync_cv.wait(lock, [=, this] { |
| 108 | if (shutting_down.load(std::memory_order_relaxed)) { | ||
| 109 | // We're shutting down, ensure no threads continue to wait for the next syncpoint | ||
| 110 | return true; | ||
| 111 | } | ||
| 112 | return syncpoints.at(syncpoint_id).load() >= value; | ||
| 113 | }); | ||
| 108 | } | 114 | } |
| 109 | 115 | ||
| 110 | void GPU::IncrementSyncPoint(const u32 syncpoint_id) { | 116 | void GPU::IncrementSyncPoint(const u32 syncpoint_id) { |
| @@ -523,6 +529,10 @@ void GPU::TriggerCpuInterrupt(const u32 syncpoint_id, const u32 value) const { | |||
| 523 | } | 529 | } |
| 524 | 530 | ||
| 525 | void GPU::ShutDown() { | 531 | void GPU::ShutDown() { |
| 532 | // Signal that threads should no longer block on syncpoint fences | ||
| 533 | shutting_down.store(true, std::memory_order_relaxed); | ||
| 534 | sync_cv.notify_all(); | ||
| 535 | |||
| 526 | gpu_thread.ShutDown(); | 536 | gpu_thread.ShutDown(); |
| 527 | } | 537 | } |
| 528 | 538 | ||
diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h index 29a867863..a8e98e51b 100644 --- a/src/video_core/gpu.h +++ b/src/video_core/gpu.h | |||
| @@ -389,6 +389,8 @@ private: | |||
| 389 | std::unique_ptr<Engines::KeplerMemory> kepler_memory; | 389 | std::unique_ptr<Engines::KeplerMemory> kepler_memory; |
| 390 | /// Shader build notifier | 390 | /// Shader build notifier |
| 391 | std::unique_ptr<VideoCore::ShaderNotify> shader_notify; | 391 | std::unique_ptr<VideoCore::ShaderNotify> shader_notify; |
| 392 | /// When true, we are about to shut down emulation session, so terminate outstanding tasks | ||
| 393 | std::atomic_bool shutting_down{}; | ||
| 392 | 394 | ||
| 393 | std::array<std::atomic<u32>, Service::Nvidia::MaxSyncPoints> syncpoints{}; | 395 | std::array<std::atomic<u32>, Service::Nvidia::MaxSyncPoints> syncpoints{}; |
| 394 | 396 | ||
diff --git a/src/video_core/rasterizer_accelerated.cpp b/src/video_core/rasterizer_accelerated.cpp index 62d84c0f8..6decd2546 100644 --- a/src/video_core/rasterizer_accelerated.cpp +++ b/src/video_core/rasterizer_accelerated.cpp | |||
| @@ -18,10 +18,10 @@ RasterizerAccelerated::~RasterizerAccelerated() = default; | |||
| 18 | void RasterizerAccelerated::UpdatePagesCachedCount(VAddr addr, u64 size, int delta) { | 18 | void RasterizerAccelerated::UpdatePagesCachedCount(VAddr addr, u64 size, int delta) { |
| 19 | const auto page_end = Common::DivCeil(addr + size, Core::Memory::PAGE_SIZE); | 19 | const auto page_end = Common::DivCeil(addr + size, Core::Memory::PAGE_SIZE); |
| 20 | for (auto page = addr >> Core::Memory::PAGE_BITS; page != page_end; ++page) { | 20 | for (auto page = addr >> Core::Memory::PAGE_BITS; page != page_end; ++page) { |
| 21 | auto& count = cached_pages.at(page >> 3).Count(page); | 21 | auto& count = cached_pages.at(page >> 2).Count(page); |
| 22 | 22 | ||
| 23 | if (delta > 0) { | 23 | if (delta > 0) { |
| 24 | ASSERT_MSG(count < UINT8_MAX, "Count may overflow!"); | 24 | ASSERT_MSG(count < UINT16_MAX, "Count may overflow!"); |
| 25 | } else if (delta < 0) { | 25 | } else if (delta < 0) { |
| 26 | ASSERT_MSG(count > 0, "Count may underflow!"); | 26 | ASSERT_MSG(count > 0, "Count may underflow!"); |
| 27 | } else { | 27 | } else { |
| @@ -29,7 +29,7 @@ void RasterizerAccelerated::UpdatePagesCachedCount(VAddr addr, u64 size, int del | |||
| 29 | } | 29 | } |
| 30 | 30 | ||
| 31 | // Adds or subtracts 1, as count is a unsigned 8-bit value | 31 | // Adds or subtracts 1, as count is a unsigned 8-bit value |
| 32 | count += static_cast<u8>(delta); | 32 | count += static_cast<u16>(delta); |
| 33 | 33 | ||
| 34 | // Assume delta is either -1 or 1 | 34 | // Assume delta is either -1 or 1 |
| 35 | if (count == 0) { | 35 | if (count == 0) { |
diff --git a/src/video_core/rasterizer_accelerated.h b/src/video_core/rasterizer_accelerated.h index 9227a4adc..ea879bfdd 100644 --- a/src/video_core/rasterizer_accelerated.h +++ b/src/video_core/rasterizer_accelerated.h | |||
| @@ -29,20 +29,20 @@ private: | |||
| 29 | public: | 29 | public: |
| 30 | CacheEntry() = default; | 30 | CacheEntry() = default; |
| 31 | 31 | ||
| 32 | std::atomic_uint8_t& Count(std::size_t page) { | 32 | std::atomic_uint16_t& Count(std::size_t page) { |
| 33 | return values[page & 7]; | 33 | return values[page & 3]; |
| 34 | } | 34 | } |
| 35 | 35 | ||
| 36 | const std::atomic_uint8_t& Count(std::size_t page) const { | 36 | const std::atomic_uint16_t& Count(std::size_t page) const { |
| 37 | return values[page & 7]; | 37 | return values[page & 3]; |
| 38 | } | 38 | } |
| 39 | 39 | ||
| 40 | private: | 40 | private: |
| 41 | std::array<std::atomic_uint8_t, 8> values{}; | 41 | std::array<std::atomic_uint16_t, 4> values{}; |
| 42 | }; | 42 | }; |
| 43 | static_assert(sizeof(CacheEntry) == 8, "CacheEntry should be 8 bytes!"); | 43 | static_assert(sizeof(CacheEntry) == 8, "CacheEntry should be 8 bytes!"); |
| 44 | 44 | ||
| 45 | std::array<CacheEntry, 0x800000> cached_pages; | 45 | std::array<CacheEntry, 0x1000000> cached_pages; |
| 46 | Core::Memory::Memory& cpu_memory; | 46 | Core::Memory::Memory& cpu_memory; |
| 47 | }; | 47 | }; |
| 48 | 48 | ||
diff --git a/src/video_core/vulkan_common/vulkan_memory_allocator.cpp b/src/video_core/vulkan_common/vulkan_memory_allocator.cpp index fa37aa79a..5edd06ebc 100644 --- a/src/video_core/vulkan_common/vulkan_memory_allocator.cpp +++ b/src/video_core/vulkan_common/vulkan_memory_allocator.cpp | |||
| @@ -53,6 +53,18 @@ struct Range { | |||
| 53 | UNREACHABLE_MSG("Invalid memory usage={}", usage); | 53 | UNREACHABLE_MSG("Invalid memory usage={}", usage); |
| 54 | return VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; | 54 | return VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; |
| 55 | } | 55 | } |
| 56 | |||
| 57 | constexpr VkExportMemoryAllocateInfo EXPORT_ALLOCATE_INFO{ | ||
| 58 | .sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO, | ||
| 59 | .pNext = nullptr, | ||
| 60 | #ifdef _WIN32 | ||
| 61 | .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT, | ||
| 62 | #elif __unix__ | ||
| 63 | .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT, | ||
| 64 | #else | ||
| 65 | .handleTypes = 0, | ||
| 66 | #endif | ||
| 67 | }; | ||
| 56 | } // Anonymous namespace | 68 | } // Anonymous namespace |
| 57 | 69 | ||
| 58 | class MemoryAllocation { | 70 | class MemoryAllocation { |
| @@ -131,7 +143,7 @@ public: | |||
| 131 | 143 | ||
| 132 | /// Returns whether this allocation is compatible with the arguments. | 144 | /// Returns whether this allocation is compatible with the arguments. |
| 133 | [[nodiscard]] bool IsCompatible(VkMemoryPropertyFlags flags, u32 type_mask) const { | 145 | [[nodiscard]] bool IsCompatible(VkMemoryPropertyFlags flags, u32 type_mask) const { |
| 134 | return (flags & property_flags) && (type_mask & shifted_memory_type) != 0; | 146 | return (flags & property_flags) == property_flags && (type_mask & shifted_memory_type) != 0; |
| 135 | } | 147 | } |
| 136 | 148 | ||
| 137 | private: | 149 | private: |
| @@ -217,14 +229,18 @@ MemoryAllocator::~MemoryAllocator() = default; | |||
| 217 | 229 | ||
| 218 | MemoryCommit MemoryAllocator::Commit(const VkMemoryRequirements& requirements, MemoryUsage usage) { | 230 | MemoryCommit MemoryAllocator::Commit(const VkMemoryRequirements& requirements, MemoryUsage usage) { |
| 219 | // Find the fastest memory flags we can afford with the current requirements | 231 | // Find the fastest memory flags we can afford with the current requirements |
| 220 | const VkMemoryPropertyFlags flags = MemoryPropertyFlags(requirements.memoryTypeBits, usage); | 232 | const u32 type_mask = requirements.memoryTypeBits; |
| 233 | const VkMemoryPropertyFlags usage_flags = MemoryUsagePropertyFlags(usage); | ||
| 234 | const VkMemoryPropertyFlags flags = MemoryPropertyFlags(type_mask, usage_flags); | ||
| 221 | if (std::optional<MemoryCommit> commit = TryCommit(requirements, flags)) { | 235 | if (std::optional<MemoryCommit> commit = TryCommit(requirements, flags)) { |
| 222 | return std::move(*commit); | 236 | return std::move(*commit); |
| 223 | } | 237 | } |
| 224 | // Commit has failed, allocate more memory. | 238 | // Commit has failed, allocate more memory. |
| 225 | // TODO(Rodrigo): Handle out of memory situations in some way like flushing to guest memory. | 239 | const u64 chunk_size = AllocationChunkSize(requirements.size); |
| 226 | AllocMemory(flags, requirements.memoryTypeBits, AllocationChunkSize(requirements.size)); | 240 | if (!TryAllocMemory(flags, type_mask, chunk_size)) { |
| 227 | 241 | // TODO(Rodrigo): Handle out of memory situations in some way like flushing to guest memory. | |
| 242 | throw vk::Exception(VK_ERROR_OUT_OF_DEVICE_MEMORY); | ||
| 243 | } | ||
| 228 | // Commit again, this time it won't fail since there's a fresh allocation above. | 244 | // Commit again, this time it won't fail since there's a fresh allocation above. |
| 229 | // If it does, there's a bug. | 245 | // If it does, there's a bug. |
| 230 | return TryCommit(requirements, flags).value(); | 246 | return TryCommit(requirements, flags).value(); |
| @@ -242,26 +258,25 @@ MemoryCommit MemoryAllocator::Commit(const vk::Image& image, MemoryUsage usage) | |||
| 242 | return commit; | 258 | return commit; |
| 243 | } | 259 | } |
| 244 | 260 | ||
| 245 | void MemoryAllocator::AllocMemory(VkMemoryPropertyFlags flags, u32 type_mask, u64 size) { | 261 | bool MemoryAllocator::TryAllocMemory(VkMemoryPropertyFlags flags, u32 type_mask, u64 size) { |
| 246 | const u32 type = FindType(flags, type_mask).value(); | 262 | const u32 type = FindType(flags, type_mask).value(); |
| 247 | const VkExportMemoryAllocateInfo export_allocate_info{ | 263 | vk::DeviceMemory memory = device.GetLogical().TryAllocateMemory({ |
| 248 | .sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO, | ||
| 249 | .pNext = nullptr, | ||
| 250 | #ifdef _WIN32 | ||
| 251 | .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT, | ||
| 252 | #elif __unix__ | ||
| 253 | .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT, | ||
| 254 | #else | ||
| 255 | .handleTypes = 0, | ||
| 256 | #endif | ||
| 257 | }; | ||
| 258 | vk::DeviceMemory memory = device.GetLogical().AllocateMemory({ | ||
| 259 | .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, | 264 | .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, |
| 260 | .pNext = export_allocations ? &export_allocate_info : nullptr, | 265 | .pNext = export_allocations ? &EXPORT_ALLOCATE_INFO : nullptr, |
| 261 | .allocationSize = size, | 266 | .allocationSize = size, |
| 262 | .memoryTypeIndex = type, | 267 | .memoryTypeIndex = type, |
| 263 | }); | 268 | }); |
| 269 | if (!memory) { | ||
| 270 | if ((flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) != 0) { | ||
| 271 | // Try to allocate non device local memory | ||
| 272 | return TryAllocMemory(flags & ~VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, type_mask, size); | ||
| 273 | } else { | ||
| 274 | // RIP | ||
| 275 | return false; | ||
| 276 | } | ||
| 277 | } | ||
| 264 | allocations.push_back(std::make_unique<MemoryAllocation>(std::move(memory), flags, size, type)); | 278 | allocations.push_back(std::make_unique<MemoryAllocation>(std::move(memory), flags, size, type)); |
| 279 | return true; | ||
| 265 | } | 280 | } |
| 266 | 281 | ||
| 267 | std::optional<MemoryCommit> MemoryAllocator::TryCommit(const VkMemoryRequirements& requirements, | 282 | std::optional<MemoryCommit> MemoryAllocator::TryCommit(const VkMemoryRequirements& requirements, |
| @@ -274,24 +289,24 @@ std::optional<MemoryCommit> MemoryAllocator::TryCommit(const VkMemoryRequirement | |||
| 274 | return commit; | 289 | return commit; |
| 275 | } | 290 | } |
| 276 | } | 291 | } |
| 292 | if ((flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) != 0) { | ||
| 293 | // Look for non device local commits on failure | ||
| 294 | return TryCommit(requirements, flags & ~VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); | ||
| 295 | } | ||
| 277 | return std::nullopt; | 296 | return std::nullopt; |
| 278 | } | 297 | } |
| 279 | 298 | ||
| 280 | VkMemoryPropertyFlags MemoryAllocator::MemoryPropertyFlags(u32 type_mask, MemoryUsage usage) const { | ||
| 281 | return MemoryPropertyFlags(type_mask, MemoryUsagePropertyFlags(usage)); | ||
| 282 | } | ||
| 283 | |||
| 284 | VkMemoryPropertyFlags MemoryAllocator::MemoryPropertyFlags(u32 type_mask, | 299 | VkMemoryPropertyFlags MemoryAllocator::MemoryPropertyFlags(u32 type_mask, |
| 285 | VkMemoryPropertyFlags flags) const { | 300 | VkMemoryPropertyFlags flags) const { |
| 286 | if (FindType(flags, type_mask)) { | 301 | if (FindType(flags, type_mask)) { |
| 287 | // Found a memory type with those requirements | 302 | // Found a memory type with those requirements |
| 288 | return flags; | 303 | return flags; |
| 289 | } | 304 | } |
| 290 | if (flags & VK_MEMORY_PROPERTY_HOST_CACHED_BIT) { | 305 | if ((flags & VK_MEMORY_PROPERTY_HOST_CACHED_BIT) != 0) { |
| 291 | // Remove host cached bit in case it's not supported | 306 | // Remove host cached bit in case it's not supported |
| 292 | return MemoryPropertyFlags(type_mask, flags & ~VK_MEMORY_PROPERTY_HOST_CACHED_BIT); | 307 | return MemoryPropertyFlags(type_mask, flags & ~VK_MEMORY_PROPERTY_HOST_CACHED_BIT); |
| 293 | } | 308 | } |
| 294 | if (flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) { | 309 | if ((flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) != 0) { |
| 295 | // Remove device local, if it's not supported by the requested resource | 310 | // Remove device local, if it's not supported by the requested resource |
| 296 | return MemoryPropertyFlags(type_mask, flags & ~VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); | 311 | return MemoryPropertyFlags(type_mask, flags & ~VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); |
| 297 | } | 312 | } |
| @@ -302,7 +317,7 @@ VkMemoryPropertyFlags MemoryAllocator::MemoryPropertyFlags(u32 type_mask, | |||
| 302 | std::optional<u32> MemoryAllocator::FindType(VkMemoryPropertyFlags flags, u32 type_mask) const { | 317 | std::optional<u32> MemoryAllocator::FindType(VkMemoryPropertyFlags flags, u32 type_mask) const { |
| 303 | for (u32 type_index = 0; type_index < properties.memoryTypeCount; ++type_index) { | 318 | for (u32 type_index = 0; type_index < properties.memoryTypeCount; ++type_index) { |
| 304 | const VkMemoryPropertyFlags type_flags = properties.memoryTypes[type_index].propertyFlags; | 319 | const VkMemoryPropertyFlags type_flags = properties.memoryTypes[type_index].propertyFlags; |
| 305 | if ((type_mask & (1U << type_index)) && (type_flags & flags)) { | 320 | if ((type_mask & (1U << type_index)) != 0 && (type_flags & flags) == flags) { |
| 306 | // The type matches in type and in the wanted properties. | 321 | // The type matches in type and in the wanted properties. |
| 307 | return type_index; | 322 | return type_index; |
| 308 | } | 323 | } |
diff --git a/src/video_core/vulkan_common/vulkan_memory_allocator.h b/src/video_core/vulkan_common/vulkan_memory_allocator.h index d1ce29450..db12d02f4 100644 --- a/src/video_core/vulkan_common/vulkan_memory_allocator.h +++ b/src/video_core/vulkan_common/vulkan_memory_allocator.h | |||
| @@ -101,16 +101,13 @@ public: | |||
| 101 | MemoryCommit Commit(const vk::Image& image, MemoryUsage usage); | 101 | MemoryCommit Commit(const vk::Image& image, MemoryUsage usage); |
| 102 | 102 | ||
| 103 | private: | 103 | private: |
| 104 | /// Allocates a chunk of memory. | 104 | /// Tries to allocate a chunk of memory. |
| 105 | void AllocMemory(VkMemoryPropertyFlags flags, u32 type_mask, u64 size); | 105 | bool TryAllocMemory(VkMemoryPropertyFlags flags, u32 type_mask, u64 size); |
| 106 | 106 | ||
| 107 | /// Tries to allocate a memory commit. | 107 | /// Tries to allocate a memory commit. |
| 108 | std::optional<MemoryCommit> TryCommit(const VkMemoryRequirements& requirements, | 108 | std::optional<MemoryCommit> TryCommit(const VkMemoryRequirements& requirements, |
| 109 | VkMemoryPropertyFlags flags); | 109 | VkMemoryPropertyFlags flags); |
| 110 | 110 | ||
| 111 | /// Returns the fastest compatible memory property flags from a wanted usage. | ||
| 112 | VkMemoryPropertyFlags MemoryPropertyFlags(u32 type_mask, MemoryUsage usage) const; | ||
| 113 | |||
| 114 | /// Returns the fastest compatible memory property flags from the wanted flags. | 111 | /// Returns the fastest compatible memory property flags from the wanted flags. |
| 115 | VkMemoryPropertyFlags MemoryPropertyFlags(u32 type_mask, VkMemoryPropertyFlags flags) const; | 112 | VkMemoryPropertyFlags MemoryPropertyFlags(u32 type_mask, VkMemoryPropertyFlags flags) const; |
| 116 | 113 | ||
diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index cc0790e07..634fe66a5 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt | |||
| @@ -4,6 +4,12 @@ set(CMAKE_AUTOUIC ON) | |||
| 4 | set(CMAKE_INCLUDE_CURRENT_DIR ON) | 4 | set(CMAKE_INCLUDE_CURRENT_DIR ON) |
| 5 | set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/CMakeModules) | 5 | set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/CMakeModules) |
| 6 | 6 | ||
| 7 | # Set the RPATH for Qt Libraries | ||
| 8 | # This must be done before the `yuzu` target is created | ||
| 9 | if (YUZU_USE_BUNDLED_QT AND (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")) | ||
| 10 | set(CMAKE_BUILD_RPATH "${CMAKE_BINARY_DIR}/bin/lib/") | ||
| 11 | endif() | ||
| 12 | |||
| 7 | add_executable(yuzu | 13 | add_executable(yuzu |
| 8 | Info.plist | 14 | Info.plist |
| 9 | about_dialog.cpp | 15 | about_dialog.cpp |
| @@ -278,11 +284,14 @@ if(UNIX AND NOT APPLE) | |||
| 278 | install(TARGETS yuzu RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}/bin") | 284 | install(TARGETS yuzu RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}/bin") |
| 279 | endif() | 285 | endif() |
| 280 | 286 | ||
| 281 | if (MSVC) | 287 | if (YUZU_USE_BUNDLED_QT) |
| 282 | include(CopyYuzuQt5Deps) | 288 | include(CopyYuzuQt5Deps) |
| 289 | copy_yuzu_Qt5_deps(yuzu) | ||
| 290 | endif() | ||
| 291 | |||
| 292 | if (MSVC) | ||
| 283 | include(CopyYuzuSDLDeps) | 293 | include(CopyYuzuSDLDeps) |
| 284 | include(CopyYuzuFFmpegDeps) | 294 | include(CopyYuzuFFmpegDeps) |
| 285 | copy_yuzu_Qt5_deps(yuzu) | ||
| 286 | copy_yuzu_SDL_deps(yuzu) | 295 | copy_yuzu_SDL_deps(yuzu) |
| 287 | copy_yuzu_FFmpeg_deps(yuzu) | 296 | copy_yuzu_FFmpeg_deps(yuzu) |
| 288 | endif() | 297 | endif() |
diff --git a/src/yuzu/applets/software_keyboard.cpp b/src/yuzu/applets/software_keyboard.cpp index b0f764994..aa453a79f 100644 --- a/src/yuzu/applets/software_keyboard.cpp +++ b/src/yuzu/applets/software_keyboard.cpp | |||
| @@ -720,21 +720,9 @@ void QtSoftwareKeyboardDialog::SetTextDrawType() { | |||
| 720 | ui->line_edit_osk->setFocus(); | 720 | ui->line_edit_osk->setFocus(); |
| 721 | }); | 721 | }); |
| 722 | 722 | ||
| 723 | connect(ui->line_edit_osk, &QLineEdit::returnPressed, [this] { | 723 | connect( |
| 724 | switch (bottom_osk_index) { | 724 | ui->line_edit_osk, &QLineEdit::returnPressed, this, |
| 725 | case BottomOSKIndex::LowerCase: | 725 | [this] { TranslateButtonPress(HIDButton::Plus); }, Qt::QueuedConnection); |
| 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 | 726 | ||
| 739 | ui->line_edit_osk->setPlaceholderText( | 727 | ui->line_edit_osk->setPlaceholderText( |
| 740 | QString::fromStdU16String(initialize_parameters.guide_text)); | 728 | QString::fromStdU16String(initialize_parameters.guide_text)); |
| @@ -1113,12 +1101,11 @@ void QtSoftwareKeyboardDialog::NormalKeyboardButtonClicked(QPushButton* button) | |||
| 1113 | } | 1101 | } |
| 1114 | 1102 | ||
| 1115 | if (button == ui->button_ok || button == ui->button_ok_shift || button == ui->button_ok_num) { | 1103 | if (button == ui->button_ok || button == ui->button_ok_shift || button == ui->button_ok_num) { |
| 1116 | if (ui->topOSK->currentIndex() == 1) { | 1104 | auto text = ui->topOSK->currentIndex() == 1 |
| 1117 | emit SubmitNormalText(SwkbdResult::Ok, | 1105 | ? ui->text_edit_osk->toPlainText().toStdU16String() |
| 1118 | ui->text_edit_osk->toPlainText().toStdU16String()); | 1106 | : ui->line_edit_osk->text().toStdU16String(); |
| 1119 | } else { | 1107 | |
| 1120 | emit SubmitNormalText(SwkbdResult::Ok, ui->line_edit_osk->text().toStdU16String()); | 1108 | emit SubmitNormalText(SwkbdResult::Ok, std::move(text)); |
| 1121 | } | ||
| 1122 | return; | 1109 | return; |
| 1123 | } | 1110 | } |
| 1124 | 1111 | ||
| @@ -1277,13 +1264,11 @@ void QtSoftwareKeyboardDialog::TranslateButtonPress(HIDButton button) { | |||
| 1277 | if (is_inline) { | 1264 | if (is_inline) { |
| 1278 | emit SubmitInlineText(SwkbdReplyType::DecidedCancel, current_text, cursor_position); | 1265 | emit SubmitInlineText(SwkbdReplyType::DecidedCancel, current_text, cursor_position); |
| 1279 | } else { | 1266 | } else { |
| 1280 | if (ui->topOSK->currentIndex() == 1) { | 1267 | auto text = ui->topOSK->currentIndex() == 1 |
| 1281 | emit SubmitNormalText(SwkbdResult::Cancel, | 1268 | ? ui->text_edit_osk->toPlainText().toStdU16String() |
| 1282 | ui->text_edit_osk->toPlainText().toStdU16String()); | 1269 | : ui->line_edit_osk->text().toStdU16String(); |
| 1283 | } else { | 1270 | |
| 1284 | emit SubmitNormalText(SwkbdResult::Cancel, | 1271 | emit SubmitNormalText(SwkbdResult::Cancel, std::move(text)); |
| 1285 | ui->line_edit_osk->text().toStdU16String()); | ||
| 1286 | } | ||
| 1287 | } | 1272 | } |
| 1288 | break; | 1273 | break; |
| 1289 | case HIDButton::Y: | 1274 | case HIDButton::Y: |
| @@ -1575,7 +1560,7 @@ void QtSoftwareKeyboard::ShowNormalKeyboard() const { | |||
| 1575 | void QtSoftwareKeyboard::ShowTextCheckDialog( | 1560 | void QtSoftwareKeyboard::ShowTextCheckDialog( |
| 1576 | Service::AM::Applets::SwkbdTextCheckResult text_check_result, | 1561 | Service::AM::Applets::SwkbdTextCheckResult text_check_result, |
| 1577 | std::u16string text_check_message) const { | 1562 | std::u16string text_check_message) const { |
| 1578 | emit MainWindowShowTextCheckDialog(text_check_result, text_check_message); | 1563 | emit MainWindowShowTextCheckDialog(text_check_result, std::move(text_check_message)); |
| 1579 | } | 1564 | } |
| 1580 | 1565 | ||
| 1581 | void QtSoftwareKeyboard::ShowInlineKeyboard( | 1566 | void QtSoftwareKeyboard::ShowInlineKeyboard( |
diff --git a/src/yuzu/configuration/configure_dialog.cpp b/src/yuzu/configuration/configure_dialog.cpp index 3ad40d2b3..6028135c5 100644 --- a/src/yuzu/configuration/configure_dialog.cpp +++ b/src/yuzu/configuration/configure_dialog.cpp | |||
| @@ -2,8 +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 | #include <QAbstractButton> | ||
| 6 | #include <QDialogButtonBox> | ||
| 5 | #include <QHash> | 7 | #include <QHash> |
| 6 | #include <QListWidgetItem> | 8 | #include <QListWidgetItem> |
| 9 | #include <QPushButton> | ||
| 7 | #include <QSignalBlocker> | 10 | #include <QSignalBlocker> |
| 8 | #include "common/settings.h" | 11 | #include "common/settings.h" |
| 9 | #include "core/core.h" | 12 | #include "core/core.h" |
| @@ -31,6 +34,12 @@ ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry, | |||
| 31 | connect(ui->selectorList, &QListWidget::itemSelectionChanged, this, | 34 | connect(ui->selectorList, &QListWidget::itemSelectionChanged, this, |
| 32 | &ConfigureDialog::UpdateVisibleTabs); | 35 | &ConfigureDialog::UpdateVisibleTabs); |
| 33 | 36 | ||
| 37 | if (Core::System::GetInstance().IsPoweredOn()) { | ||
| 38 | QPushButton* apply_button = ui->buttonBox->addButton(QDialogButtonBox::Apply); | ||
| 39 | connect(apply_button, &QAbstractButton::clicked, this, | ||
| 40 | &ConfigureDialog::HandleApplyButtonClicked); | ||
| 41 | } | ||
| 42 | |||
| 34 | adjustSize(); | 43 | adjustSize(); |
| 35 | ui->selectorList->setCurrentRow(0); | 44 | ui->selectorList->setCurrentRow(0); |
| 36 | } | 45 | } |
| @@ -80,6 +89,11 @@ void ConfigureDialog::RetranslateUI() { | |||
| 80 | ui->tabWidget->setCurrentIndex(old_index); | 89 | ui->tabWidget->setCurrentIndex(old_index); |
| 81 | } | 90 | } |
| 82 | 91 | ||
| 92 | void ConfigureDialog::HandleApplyButtonClicked() { | ||
| 93 | UISettings::values.configuration_applied = true; | ||
| 94 | ApplyConfiguration(); | ||
| 95 | } | ||
| 96 | |||
| 83 | Q_DECLARE_METATYPE(QList<QWidget*>); | 97 | Q_DECLARE_METATYPE(QList<QWidget*>); |
| 84 | 98 | ||
| 85 | void ConfigureDialog::PopulateSelectionList() { | 99 | void ConfigureDialog::PopulateSelectionList() { |
diff --git a/src/yuzu/configuration/configure_dialog.h b/src/yuzu/configuration/configure_dialog.h index 570c3b941..abe019635 100644 --- a/src/yuzu/configuration/configure_dialog.h +++ b/src/yuzu/configuration/configure_dialog.h | |||
| @@ -35,9 +35,10 @@ signals: | |||
| 35 | 35 | ||
| 36 | private: | 36 | private: |
| 37 | void changeEvent(QEvent* event) override; | 37 | void changeEvent(QEvent* event) override; |
| 38 | |||
| 39 | void RetranslateUI(); | 38 | void RetranslateUI(); |
| 40 | 39 | ||
| 40 | void HandleApplyButtonClicked(); | ||
| 41 | |||
| 41 | void SetConfiguration(); | 42 | void SetConfiguration(); |
| 42 | void UpdateVisibleTabs(); | 43 | void UpdateVisibleTabs(); |
| 43 | void PopulateSelectionList(); | 44 | void PopulateSelectionList(); |
diff --git a/src/yuzu/configuration/configure_per_game.cpp b/src/yuzu/configuration/configure_per_game.cpp index 007d93c77..7dfcf150c 100644 --- a/src/yuzu/configuration/configure_per_game.cpp +++ b/src/yuzu/configuration/configure_per_game.cpp | |||
| @@ -7,9 +7,12 @@ | |||
| 7 | #include <string> | 7 | #include <string> |
| 8 | #include <utility> | 8 | #include <utility> |
| 9 | 9 | ||
| 10 | #include <QAbstractButton> | ||
| 10 | #include <QCheckBox> | 11 | #include <QCheckBox> |
| 12 | #include <QDialogButtonBox> | ||
| 11 | #include <QHeaderView> | 13 | #include <QHeaderView> |
| 12 | #include <QMenu> | 14 | #include <QMenu> |
| 15 | #include <QPushButton> | ||
| 13 | #include <QStandardItemModel> | 16 | #include <QStandardItemModel> |
| 14 | #include <QString> | 17 | #include <QString> |
| 15 | #include <QTimer> | 18 | #include <QTimer> |
| @@ -45,6 +48,12 @@ ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id, std::string_vi | |||
| 45 | scene = new QGraphicsScene; | 48 | scene = new QGraphicsScene; |
| 46 | ui->icon_view->setScene(scene); | 49 | ui->icon_view->setScene(scene); |
| 47 | 50 | ||
| 51 | if (Core::System::GetInstance().IsPoweredOn()) { | ||
| 52 | QPushButton* apply_button = ui->buttonBox->addButton(QDialogButtonBox::Apply); | ||
| 53 | connect(apply_button, &QAbstractButton::clicked, this, | ||
| 54 | &ConfigurePerGame::HandleApplyButtonClicked); | ||
| 55 | } | ||
| 56 | |||
| 48 | LoadConfiguration(); | 57 | LoadConfiguration(); |
| 49 | } | 58 | } |
| 50 | 59 | ||
| @@ -77,6 +86,11 @@ void ConfigurePerGame::RetranslateUI() { | |||
| 77 | ui->retranslateUi(this); | 86 | ui->retranslateUi(this); |
| 78 | } | 87 | } |
| 79 | 88 | ||
| 89 | void ConfigurePerGame::HandleApplyButtonClicked() { | ||
| 90 | UISettings::values.configuration_applied = true; | ||
| 91 | ApplyConfiguration(); | ||
| 92 | } | ||
| 93 | |||
| 80 | void ConfigurePerGame::LoadFromFile(FileSys::VirtualFile file) { | 94 | void ConfigurePerGame::LoadFromFile(FileSys::VirtualFile file) { |
| 81 | this->file = std::move(file); | 95 | this->file = std::move(file); |
| 82 | LoadConfiguration(); | 96 | LoadConfiguration(); |
diff --git a/src/yuzu/configuration/configure_per_game.h b/src/yuzu/configuration/configure_per_game.h index d86749a0e..dc6b68763 100644 --- a/src/yuzu/configuration/configure_per_game.h +++ b/src/yuzu/configuration/configure_per_game.h | |||
| @@ -40,6 +40,8 @@ private: | |||
| 40 | void changeEvent(QEvent* event) override; | 40 | void changeEvent(QEvent* event) override; |
| 41 | void RetranslateUI(); | 41 | void RetranslateUI(); |
| 42 | 42 | ||
| 43 | void HandleApplyButtonClicked(); | ||
| 44 | |||
| 43 | void LoadConfiguration(); | 45 | void LoadConfiguration(); |
| 44 | 46 | ||
| 45 | std::unique_ptr<Ui::ConfigurePerGame> ui; | 47 | std::unique_ptr<Ui::ConfigurePerGame> ui; |
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 1d63ababb..dd8dd3233 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp | |||
| @@ -2594,12 +2594,12 @@ void GMainWindow::OnConfigure() { | |||
| 2594 | &GMainWindow::OnLanguageChanged); | 2594 | &GMainWindow::OnLanguageChanged); |
| 2595 | 2595 | ||
| 2596 | const auto result = configure_dialog.exec(); | 2596 | const auto result = configure_dialog.exec(); |
| 2597 | if (result != QDialog::Accepted) { | 2597 | if (result != QDialog::Accepted && !UISettings::values.configuration_applied) { |
| 2598 | return; | 2598 | return; |
| 2599 | } else if (result == QDialog::Accepted) { | ||
| 2600 | configure_dialog.ApplyConfiguration(); | ||
| 2601 | controller_dialog->refreshConfiguration(); | ||
| 2599 | } | 2602 | } |
| 2600 | |||
| 2601 | configure_dialog.ApplyConfiguration(); | ||
| 2602 | controller_dialog->refreshConfiguration(); | ||
| 2603 | InitializeHotkeys(); | 2603 | InitializeHotkeys(); |
| 2604 | if (UISettings::values.theme != old_theme) { | 2604 | if (UISettings::values.theme != old_theme) { |
| 2605 | UpdateUITheme(); | 2605 | UpdateUITheme(); |
| @@ -2614,6 +2614,8 @@ void GMainWindow::OnConfigure() { | |||
| 2614 | game_list->PopulateAsync(UISettings::values.game_dirs); | 2614 | game_list->PopulateAsync(UISettings::values.game_dirs); |
| 2615 | } | 2615 | } |
| 2616 | 2616 | ||
| 2617 | UISettings::values.configuration_applied = false; | ||
| 2618 | |||
| 2617 | config->Save(); | 2619 | config->Save(); |
| 2618 | 2620 | ||
| 2619 | if ((UISettings::values.hide_mouse || Settings::values.mouse_panning) && emulation_running) { | 2621 | if ((UISettings::values.hide_mouse || Settings::values.mouse_panning) && emulation_running) { |
| @@ -2643,23 +2645,27 @@ void GMainWindow::OpenPerGameConfiguration(u64 title_id, const std::string& file | |||
| 2643 | ConfigurePerGame dialog(this, title_id, file_name); | 2645 | ConfigurePerGame dialog(this, title_id, file_name); |
| 2644 | dialog.LoadFromFile(v_file); | 2646 | dialog.LoadFromFile(v_file); |
| 2645 | const auto result = dialog.exec(); | 2647 | const auto result = dialog.exec(); |
| 2646 | if (result == QDialog::Accepted) { | 2648 | |
| 2649 | if (result != QDialog::Accepted && !UISettings::values.configuration_applied) { | ||
| 2650 | Settings::RestoreGlobalState(system.IsPoweredOn()); | ||
| 2651 | return; | ||
| 2652 | } else if (result == QDialog::Accepted) { | ||
| 2647 | dialog.ApplyConfiguration(); | 2653 | dialog.ApplyConfiguration(); |
| 2654 | } | ||
| 2648 | 2655 | ||
| 2649 | const auto reload = UISettings::values.is_game_list_reload_pending.exchange(false); | 2656 | const auto reload = UISettings::values.is_game_list_reload_pending.exchange(false); |
| 2650 | if (reload) { | 2657 | if (reload) { |
| 2651 | game_list->PopulateAsync(UISettings::values.game_dirs); | 2658 | game_list->PopulateAsync(UISettings::values.game_dirs); |
| 2652 | } | 2659 | } |
| 2653 | 2660 | ||
| 2654 | // Do not cause the global config to write local settings into the config file | 2661 | // Do not cause the global config to write local settings into the config file |
| 2655 | const bool is_powered_on = system.IsPoweredOn(); | 2662 | const bool is_powered_on = system.IsPoweredOn(); |
| 2656 | Settings::RestoreGlobalState(is_powered_on); | 2663 | Settings::RestoreGlobalState(is_powered_on); |
| 2657 | 2664 | ||
| 2658 | if (!is_powered_on) { | 2665 | UISettings::values.configuration_applied = false; |
| 2659 | config->Save(); | 2666 | |
| 2660 | } | 2667 | if (!is_powered_on) { |
| 2661 | } else { | 2668 | config->Save(); |
| 2662 | Settings::RestoreGlobalState(system.IsPoweredOn()); | ||
| 2663 | } | 2669 | } |
| 2664 | } | 2670 | } |
| 2665 | 2671 | ||
diff --git a/src/yuzu/uisettings.h b/src/yuzu/uisettings.h index 5ba00b8c8..49122ec32 100644 --- a/src/yuzu/uisettings.h +++ b/src/yuzu/uisettings.h | |||
| @@ -95,6 +95,8 @@ struct Values { | |||
| 95 | uint8_t row_2_text_id; | 95 | uint8_t row_2_text_id; |
| 96 | std::atomic_bool is_game_list_reload_pending{false}; | 96 | std::atomic_bool is_game_list_reload_pending{false}; |
| 97 | bool cache_game_list; | 97 | bool cache_game_list; |
| 98 | |||
| 99 | bool configuration_applied; | ||
| 98 | }; | 100 | }; |
| 99 | 101 | ||
| 100 | extern Values values; | 102 | extern Values values; |